diff options
author | Alessandro Gatti <a.gatti@frob.it> | 2024-08-25 16:28:35 +0200 |
---|---|---|
committer | Damien George <damien@micropython.org> | 2025-01-02 11:49:10 +1100 |
commit | 268acb714dd79fa5eeeb82c1fca022bc4ea126b7 (patch) | |
tree | 428ed75070ee89847fd5087095e3d7331d5f9b26 /tests | |
parent | 3044233ea3726e9d8727d8f6a76f32c48e6fae5e (diff) | |
download | micropython-268acb714dd79fa5eeeb82c1fca022bc4ea126b7.tar.gz micropython-268acb714dd79fa5eeeb82c1fca022bc4ea126b7.zip |
py/emitinlinerv32: Add inline assembler support for RV32.
This commit adds support for writing inline assembler functions when
targeting a RV32IMC processor.
Given that this takes up a bit of rodata space due to its large
instruction decoding table and its extensive error messages, it is
enabled by default only on offline targets such as mpy-cross and the
qemu port.
Signed-off-by: Alessandro Gatti <a.gatti@frob.it>
Diffstat (limited to 'tests')
30 files changed, 1470 insertions, 2 deletions
diff --git a/tests/inlineasm/rv32/asmargs.py b/tests/inlineasm/rv32/asmargs.py new file mode 100644 index 0000000000..78afd51115 --- /dev/null +++ b/tests/inlineasm/rv32/asmargs.py @@ -0,0 +1,44 @@ +# test passing arguments + + +@micropython.asm_rv32 +def arg0(): + c_li(a0, 1) + + +print(arg0()) + + +@micropython.asm_rv32 +def arg1(a0): + addi(a0, a0, 1) + + +print(arg1(1)) + + +@micropython.asm_rv32 +def arg2(a0, a1): + add(a0, a0, a1) + + +print(arg2(1, 2)) + + +@micropython.asm_rv32 +def arg3(a0, a1, a2): + add(a0, a0, a1) + add(a0, a0, a2) + + +print(arg3(1, 2, 3)) + + +@micropython.asm_rv32 +def arg4(a0, a1, a2, a3): + add(a0, a0, a1) + add(a0, a0, a2) + add(a0, a0, a3) + + +print(arg4(1, 2, 3, 4)) diff --git a/tests/inlineasm/rv32/asmargs.py.exp b/tests/inlineasm/rv32/asmargs.py.exp new file mode 100644 index 0000000000..e33a6964f4 --- /dev/null +++ b/tests/inlineasm/rv32/asmargs.py.exp @@ -0,0 +1,5 @@ +1 +2 +3 +6 +10 diff --git a/tests/inlineasm/rv32/asmarith.py b/tests/inlineasm/rv32/asmarith.py new file mode 100644 index 0000000000..8b864c0b3b --- /dev/null +++ b/tests/inlineasm/rv32/asmarith.py @@ -0,0 +1,79 @@ +# test arithmetic opcodes + + +@micropython.asm_rv32 +def f1(): + li(a0, 0x100) + li(a1, 1) + add(a0, a0, a1) + addi(a0, a0, 1) + addi(a0, a0, -2) + sub(a0, a0, a1) + c_add(a0, a1) + c_addi(a0, -1) + c_sub(a0, a1) + + +print(hex(f1())) + + +@micropython.asm_rv32 +def f2(): + li(a0, 0x10FF) + li(a1, 1) + and_(a2, a0, a1) + andi(a3, a0, 0x10) + or_(a2, a2, a3) + ori(a2, a2, 8) + li(a1, 0x200) + c_or(a2, a1) + li(a1, 0xF0) + mv(a0, a2) + c_and(a0, a1) + li(a1, 0x101) + xor(a0, a0, a1) + xori(a0, a0, 0x101) + c_xor(a0, a1) + + +print(hex(f2())) + + +@micropython.asm_rv32 +def f3(a0, a1): + slt(a0, a0, a1) + + +print(f3(0xFFFFFFF0, 0xFFFFFFF1)) +print(f3(0x0, 0xFFFFFFF1)) +print(f3(0xFFFFFFF1, 0xFFFFFFF1)) +print(f3(0xFFFFFFF1, 0xFFFFFFF0)) + + +@micropython.asm_rv32 +def f4(a0, a1): + sltu(a0, a0, a1) + + +print(f3(0xFFFFFFF0, 0xFFFFFFF1)) +print(f3(0x0, 0xFFFFFFF1)) +print(f3(0xFFFFFFF1, 0xFFFFFFF1)) +print(f3(0xFFFFFFF1, 0xFFFFFFF0)) + + +@micropython.asm_rv32 +def f5(a0): + slti(a0, a0, -2) + + +print(f5(-1)) +print(f5(-3)) + + +@micropython.asm_rv32 +def f6(a0): + sltiu(a0, a0, -2) + + +print(f6(-1)) +print(f6(-3)) diff --git a/tests/inlineasm/rv32/asmarith.py.exp b/tests/inlineasm/rv32/asmarith.py.exp new file mode 100644 index 0000000000..7da4dd5c93 --- /dev/null +++ b/tests/inlineasm/rv32/asmarith.py.exp @@ -0,0 +1,14 @@ +0xfe +0x111 +1 +0 +0 +0 +1 +0 +0 +0 +0 +1 +0 +1 diff --git a/tests/inlineasm/rv32/asmbranch.py b/tests/inlineasm/rv32/asmbranch.py new file mode 100644 index 0000000000..d7d059d406 --- /dev/null +++ b/tests/inlineasm/rv32/asmbranch.py @@ -0,0 +1,161 @@ +# test branch instructions + + +@micropython.asm_rv32 +def tbeq(a0): + mv(a1, a0) + + li(a0, 10) + li(a2, 1) + beq(a1, a2, end) + + li(a0, 20) + li(a2, 2) + beq(a1, a2, end) + + li(a0, 30) + li(a2, 3) + beq(a1, a2, end) + + li(a0, 0) + + label(end) + + +print(tbeq(0)) +print(tbeq(1)) +print(tbeq(2)) +print(tbeq(3)) + + +@micropython.asm_rv32 +def tbne(a0): + mv(a1, a0) + + li(a0, 10) + li(a2, 1) + bne(a1, a2, end) + + li(a0, 20) + li(a2, 2) + bne(a1, a2, end) + + li(a0, 30) + li(a2, 3) + bne(a1, a2, end) + + li(a0, 0) + + label(end) + + +print(tbne(0)) +print(tbne(1)) +print(tbne(2)) +print(tbne(3)) + + +@micropython.asm_rv32 +def tbgeu(a0): + mv(a1, a0) + + li(a0, 1) + li(a2, 2) + bgeu(a1, a2, end) + li(a0, 0) + + label(end) + + +print(tbgeu(0)) +print(tbgeu(1)) +print(tbgeu(2)) +print(tbgeu(3)) + + +@micropython.asm_rv32 +def tbltu(a0): + mv(a1, a0) + + li(a0, 1) + li(a2, 2) + bltu(a1, a2, end) + li(a0, 0) + + label(end) + + +print(tbltu(0)) +print(tbltu(1)) +print(tbltu(2)) +print(tbltu(3)) + + +@micropython.asm_rv32 +def tbge(a0): + mv(a1, a0) + + li(a0, 1) + li(a2, -2) + bge(a1, a2, end) + li(a0, 0) + + label(end) + + +print(tbge(-3)) +print(tbge(-2)) +print(tbge(-1)) +print(tbge(0)) + + +@micropython.asm_rv32 +def tblt(a0): + mv(a1, a0) + + li(a0, 1) + li(a2, -2) + blt(a1, a2, end) + li(a0, 0) + + label(end) + + +print(tblt(-3)) +print(tblt(-2)) +print(tblt(-1)) +print(tblt(0)) + + +@micropython.asm_rv32 +def tcbeqz(a0): + mv(a1, a0) + + li(a0, 1) + c_beqz(a1, end) + li(a0, 0) + + label(end) + + +print(tcbeqz(0)) +print(tcbeqz(1)) +print(tcbeqz(2)) +print(tcbeqz(3)) + + +@micropython.asm_rv32 +def tcbnez(a0): + mv(a1, a0) + + li(a0, 1) + c_bnez(a1, end) + li(a0, 0) + + label(end) + + +print(tcbnez(0)) +print(tcbnez(1)) +print(tcbnez(2)) +print(tcbnez(3)) diff --git a/tests/inlineasm/rv32/asmbranch.py.exp b/tests/inlineasm/rv32/asmbranch.py.exp new file mode 100644 index 0000000000..baae691495 --- /dev/null +++ b/tests/inlineasm/rv32/asmbranch.py.exp @@ -0,0 +1,32 @@ +0 +10 +20 +30 +10 +20 +10 +10 +0 +0 +1 +1 +1 +1 +0 +0 +0 +1 +1 +1 +1 +0 +0 +0 +1 +0 +0 +0 +0 +1 +1 +1 diff --git a/tests/inlineasm/rv32/asmconst.py b/tests/inlineasm/rv32/asmconst.py new file mode 100644 index 0000000000..2b6363a43d --- /dev/null +++ b/tests/inlineasm/rv32/asmconst.py @@ -0,0 +1,49 @@ +# test constants in assembler + + +@micropython.asm_rv32 +def c1(): + li(a0, 0xFFFFFFFF) + li(a1, 0xF0000000) + sub(a0, a0, a1) + + +print(hex(c1())) + + +@micropython.asm_rv32 +def c2(): + lui(a0, 0x12345) + li(a1, 0x678) + add(a0, a0, a1) + + +print(hex(c2())) + + +@micropython.asm_rv32 +def c3() -> uint: + lui(a0, 0) + addi(a0, a0, 0x7FF) + + +print(hex(c3())) + + +@micropython.asm_rv32 +def c4() -> uint: + lui(a0, 0) + addi(a0, a0, -1) + + +print(hex(c4())) + + +@micropython.asm_rv32 +def c5(): + c_lui(a0, 1) + c_li(a1, 1) + c_add(a0, a1) + + +print(hex(c5())) diff --git a/tests/inlineasm/rv32/asmconst.py.exp b/tests/inlineasm/rv32/asmconst.py.exp new file mode 100644 index 0000000000..0c713a8414 --- /dev/null +++ b/tests/inlineasm/rv32/asmconst.py.exp @@ -0,0 +1,5 @@ +0xfffffff +0x12345678 +0x7ff +0xffffffff +0x1001 diff --git a/tests/inlineasm/rv32/asmcsr.py b/tests/inlineasm/rv32/asmcsr.py new file mode 100644 index 0000000000..f27e2aa5e3 --- /dev/null +++ b/tests/inlineasm/rv32/asmcsr.py @@ -0,0 +1,65 @@ +# test csr instructions + +# CSR 0x340 is `mscratch`. This test suite is only safe to run on a system +# where it is known that there is no other code that can read from or write +# to that register. The qemu port is one such system, as the CSR is only +# accessed when a machine exception occurs, and at that point it doesn't matter +# anymore whether these tests are running or not. + + +@micropython.asm_rv32 +def csr(): + li(a0, 0) + csrrw(zero, zero, 0x340) # All zeroes + csrrs(a1, zero, 0x340) # Read zeroes + c_bnez(a1, end) + addi(a0, a0, 1) + li(a1, 0xA5A5A5A5) + li(a2, 0x5A5A5A5A) + csrrs(a2, a1, 0x340) # Read zeroes, set 0xA5A5A5A5 + c_bnez(a2, end) + addi(a0, a0, 1) + csrrs(a3, zero, 0x340) # Read 0xA5A5A5A5 + bne(a3, a1, end) + addi(a0, a0, 1) + li(a2, 0xF0F0F0F0) + csrrc(zero, a2, 0x340) # Clear upper half + csrrs(a3, zero, 0x340) # Read 0x05050505 + xori(a2, a2, -1) + and_(a2, a1, a2) + bne(a2, a3, end) + addi(a0, a0, 1) + label(end) + + +print(csr()) + + +@micropython.asm_rv32 +def csri(): + li(a0, 0) + csrrwi(zero, 0x340, 15) # Write 0xF + csrrs(a1, zero, 0x340) # Read 0xF + csrrsi(a2, 0x340, 0) # Read + bne(a1, a2, end) + addi(a0, a0, 1) + csrrci(a2, 0x340, 0) # Read + bne(a1, a2, end) + addi(a0, a0, 1) + li(a2, 15) + bne(a1, a2, end) + addi(a0, a0, 1) + csrrci(zero, 0x340, 1) # Clear bit 1 + csrrs(a1, zero, 0x340) # Read 0xE + li(a2, 14) + bne(a1, a2, end) + addi(a0, a0, 1) + csrrsi(zero, 0x340, 1) # Set bit 1 + csrrs(a1, zero, 0x340) # Read 0xF + li(a2, 15) + bne(a1, a2, end) + addi(a0, a0, 1) + label(end) + + +print(csri()) diff --git a/tests/inlineasm/rv32/asmcsr.py.exp b/tests/inlineasm/rv32/asmcsr.py.exp new file mode 100644 index 0000000000..61c83cba41 --- /dev/null +++ b/tests/inlineasm/rv32/asmcsr.py.exp @@ -0,0 +1,2 @@ +4 +5 diff --git a/tests/inlineasm/rv32/asmdata.py b/tests/inlineasm/rv32/asmdata.py new file mode 100644 index 0000000000..5e555ef4bf --- /dev/null +++ b/tests/inlineasm/rv32/asmdata.py @@ -0,0 +1,33 @@ +# test the "data" directive + + +@micropython.asm_rv32 +def ret_num(a0) -> uint: + slli(a0, a0, 2) + addi(a0, a0, 16) + auipc(a1, 0) + add(a1, a1, a0) + lw(a0, 0(a1)) + jal(zero, HERE) + data(4, 0x12345678, 0x20000000, 0x40000000, 0x7FFFFFFF + 1, (1 << 32) - 2) + label(HERE) + + +for i in range(5): + print(hex(ret_num(i))) + + +@micropython.asm_rv32 +def ret_num_la(a0) -> uint: + slli(a0, a0, 2) + la(a1, DATA) + add(a1, a1, a0) + lw(a0, 0(a1)) + jal(zero, HERE) + label(DATA) + data(4, 0x12345678, 0x20000000, 0x40000000, 0x7FFFFFFF + 1, (1 << 32) - 2) + label(HERE) + + +for i in range(5): + print(hex(ret_num_la(i))) diff --git a/tests/inlineasm/rv32/asmdata.py.exp b/tests/inlineasm/rv32/asmdata.py.exp new file mode 100644 index 0000000000..79e92bdfa5 --- /dev/null +++ b/tests/inlineasm/rv32/asmdata.py.exp @@ -0,0 +1,10 @@ +0x12345678 +0x20000000 +0x40000000 +0x80000000 +0xfffffffe +0x12345678 +0x20000000 +0x40000000 +0x80000000 +0xfffffffe diff --git a/tests/inlineasm/rv32/asmdivmul.py b/tests/inlineasm/rv32/asmdivmul.py new file mode 100644 index 0000000000..e1120c6f63 --- /dev/null +++ b/tests/inlineasm/rv32/asmdivmul.py @@ -0,0 +1,63 @@ +@micropython.asm_rv32 +def sdiv(a0, a1): + div(a0, a0, a1) + + +@micropython.asm_rv32 +def udiv(a0, a1): + divu(a0, a0, a1) + + +@micropython.asm_rv32 +def srem(a0, a1): + rem(a0, a0, a1) + + +@micropython.asm_rv32 +def urem(a0, a1): + remu(a0, a0, a1) + + +print(sdiv(1234, 3)) +print(sdiv(-1234, 3)) +print(sdiv(1234, -3)) +print(sdiv(-1234, -3)) + +print(udiv(1234, 3)) +print(udiv(0xFFFFFFFF, 0x7FFFFFFF)) +print(udiv(0xFFFFFFFF, 0xFFFFFFFF)) + +print(srem(1234, 3)) +print(srem(-1234, 3)) +print(srem(1234, -3)) +print(srem(-1234, -3)) + +print(urem(1234, 3)) +print(urem(0xFFFFFFFF, 0x7FFFFFFF)) +print(urem(0xFFFFFFFF, 0xFFFFFFFF)) + + +@micropython.asm_rv32 +def m1(a0, a1): + mul(a0, a0, a1) + + +@micropython.asm_rv32 +def m2(a0, a1): + mulh(a0, a0, a1) + + +@micropython.asm_rv32 +def m3(a0, a1): + mulhu(a0, a0, a1) + + +@micropython.asm_rv32 +def m4(a0, a1): + mulhsu(a0, a0, a1) + + +print(m1(0xFFFFFFFF, 2)) +print(m2(0xFFFFFFFF, 0xFFFFFFF0)) +print(m3(0xFFFFFFFF, 0xFFFFFFF0)) +print(m4(0xFFFFFFFF, 0xFFFFFFF0)) diff --git a/tests/inlineasm/rv32/asmdivmul.py.exp b/tests/inlineasm/rv32/asmdivmul.py.exp new file mode 100644 index 0000000000..60d28635f7 --- /dev/null +++ b/tests/inlineasm/rv32/asmdivmul.py.exp @@ -0,0 +1,18 @@ +411 +-411 +-411 +411 +411 +2 +1 +1 +-1 +1 +-1 +1 +1 +0 +-2 +0 +-17 +-1 diff --git a/tests/inlineasm/rv32/asmjump.py b/tests/inlineasm/rv32/asmjump.py new file mode 100644 index 0000000000..fe87d3f968 --- /dev/null +++ b/tests/inlineasm/rv32/asmjump.py @@ -0,0 +1,115 @@ +@micropython.asm_rv32 +def f1(): + li(a0, 0) + la(a1, END) + c_jr(a1) + c_addi(a0, 1) + c_addi(a0, 1) + c_addi(a0, 1) + c_addi(a0, 1) + c_addi(a0, 1) + label(END) + + +print(f1()) + + +@micropython.asm_rv32 +def f2(): + addi(sp, sp, -4) + c_swsp(ra, 0) + li(ra, 0) + li(a0, 0) + c_jal(END) + c_addi(a0, 1) + c_addi(a0, 1) + c_addi(a0, 1) + c_addi(a0, 1) + c_addi(a0, 1) + label(END) + bne(ra, zero, SUCCESS) + c_addi(a0, 2) + label(SUCCESS) + c_lwsp(ra, 0) + addi(sp, sp, 4) + + +print(f2()) + + +@micropython.asm_rv32 +def f3(): + li(a0, 0) + c_j(END) + c_addi(a0, 1) + c_addi(a0, 1) + c_addi(a0, 1) + c_addi(a0, 1) + c_addi(a0, 1) + label(END) + + +print(f3()) + + +@micropython.asm_rv32 +def f4(): + addi(sp, sp, -4) + c_swsp(ra, 0) + li(ra, 0) + li(a0, 0) + la(a1, END) + c_jalr(a1) + c_addi(a0, 1) + c_addi(a0, 1) + c_addi(a0, 1) + c_addi(a0, 1) + c_addi(a0, 1) + label(END) + bne(ra, zero, SUCCESS) + c_addi(a0, 2) + label(SUCCESS) + c_lwsp(ra, 0) + addi(sp, sp, 4) + + +print(f4()) + + +@micropython.asm_rv32 +def f5(): + li(a0, 0) + li(a1, 0) + jal(a1, END) + c_addi(a0, 1) + c_addi(a0, 1) + c_addi(a0, 1) + c_addi(a0, 1) + c_addi(a0, 1) + label(END) + bne(a1, zero, SUCCESS) + c_addi(a0, 2) + label(SUCCESS) + + +print(f5()) + + +@micropython.asm_rv32 +def f6(): + li(a0, 0) + la(a1, JUMP) + li(a2, 0) + jalr(a2, a1, 10) + label(JUMP) + c_addi(a0, 1) + c_addi(a0, 1) + c_addi(a0, 1) + c_addi(a0, 1) + c_addi(a0, 1) + bne(a2, zero, SUCCESS) + c_addi(a0, 2) + label(SUCCESS) + + +print(f6()) diff --git a/tests/inlineasm/rv32/asmjump.py.exp b/tests/inlineasm/rv32/asmjump.py.exp new file mode 100644 index 0000000000..f7eb44d66e --- /dev/null +++ b/tests/inlineasm/rv32/asmjump.py.exp @@ -0,0 +1,6 @@ +0 +0 +0 +0 +0 +0 diff --git a/tests/inlineasm/rv32/asmloadstore.py b/tests/inlineasm/rv32/asmloadstore.py new file mode 100644 index 0000000000..2c49e07b41 --- /dev/null +++ b/tests/inlineasm/rv32/asmloadstore.py @@ -0,0 +1,86 @@ +# test load/store opcodes + + +@micropython.asm_rv32 +def l(): + li(a5, 4) + addi(sp, sp, -12) + li(a0, 0x123) + c_swsp(a0, 0) + addi(a1, a0, 0x111) + c_swsp(a1, 4) + addi(a2, a1, 0x111) + c_swsp(a2, 8) + mv(a4, sp) + c_lw(a3, 0(a4)) + bne(a3, a0, END) + addi(a5, a5, -1) + lw(a3, 4(a4)) + bne(a3, a1, END) + addi(a5, a5, -1) + lhu(a3, 8(a4)) + bne(a3, a2, END) + addi(a5, a5, -1) + lbu(a0, 8(a4)) + addi(a0, a0, 0x300) + bne(a0, a2, END) + addi(a5, a5, -1) + label(END) + addi(sp, sp, 12) + mv(a0, a5) + + +print(l()) + + +@micropython.asm_rv32 +def s(): + li(a5, 4) + addi(sp, sp, -12) + c_swsp(zero, 0) + c_swsp(zero, 4) + c_swsp(zero, 8) + li(a0, 0x12345) + mv(a4, sp) + c_sw(a0, 0(a4)) + sh(a0, 4(a4)) + sb(a0, 8(a4)) + li(a1, 0xFFFF) + and_(a1, a0, a1) + andi(a2, a0, 0xFF) + lw(a3, 0(sp)) + bne(a3, a0, END) + addi(a5, a5, -1) + lw(a3, 4(sp)) + bne(a3, a1, END) + addi(a5, a5, -1) + lw(a3, 8(sp)) + bne(a3, a2, END) + addi(a5, a5, -1) + label(END) + addi(sp, sp, 12) + mv(a0, a5) + + +print(s()) + + +@micropython.asm_rv32 +def lu(): + li(a5, 4) + addi(sp, sp, -8) + li(a0, 0xF1234567) + c_swsp(a0, 0) + c_swsp(a0, 4) + lh(a1, 0(sp)) + blt(a1, zero, END) + addi(a5, a5, -1) + lb(a2, 4(sp)) + blt(a2, zero, END) + addi(a5, a5, -1) + label(END) + addi(sp, sp, 8) + mv(a0, a5) + + +print(lu()) diff --git a/tests/inlineasm/rv32/asmloadstore.py.exp b/tests/inlineasm/rv32/asmloadstore.py.exp new file mode 100644 index 0000000000..4539bbf2d2 --- /dev/null +++ b/tests/inlineasm/rv32/asmloadstore.py.exp @@ -0,0 +1,3 @@ +0 +1 +2 diff --git a/tests/inlineasm/rv32/asmrettype.py b/tests/inlineasm/rv32/asmrettype.py new file mode 100644 index 0000000000..fc7ae61d15 --- /dev/null +++ b/tests/inlineasm/rv32/asmrettype.py @@ -0,0 +1,33 @@ +# test return type of inline asm + + +@micropython.asm_rv32 +def ret_obj(a0) -> object: + pass + + +ret_obj(print)(1) + + +@micropython.asm_rv32 +def ret_bool(a0) -> bool: + pass + + +print(ret_bool(0), ret_bool(1)) + + +@micropython.asm_rv32 +def ret_int(a0) -> int: + slli(a0, a0, 29) + + +print(ret_int(0), hex(ret_int(1)), hex(ret_int(2)), hex(ret_int(4))) + + +@micropython.asm_rv32 +def ret_uint(a0) -> uint: + slli(a0, a0, 29) + + +print(ret_uint(0), hex(ret_uint(1)), hex(ret_uint(2)), hex(ret_uint(4))) diff --git a/tests/inlineasm/rv32/asmrettype.py.exp b/tests/inlineasm/rv32/asmrettype.py.exp new file mode 100644 index 0000000000..cbb49d2472 --- /dev/null +++ b/tests/inlineasm/rv32/asmrettype.py.exp @@ -0,0 +1,4 @@ +1 +False True +0 0x20000000 0x40000000 -0x80000000 +0 0x20000000 0x40000000 0x80000000 diff --git a/tests/inlineasm/rv32/asmsanity.py b/tests/inlineasm/rv32/asmsanity.py new file mode 100644 index 0000000000..1a16d3504d --- /dev/null +++ b/tests/inlineasm/rv32/asmsanity.py @@ -0,0 +1,204 @@ +TEMPLATE3 = """ +@micropython.asm_rv32 +def f(): + {}({}, {}, {}) +""" + +TEMPLATE2 = """ +@micropython.asm_rv32 +def f(): + {}({}, {}) +""" + +TEMPLATE1 = """ +@micropython.asm_rv32 +def f(): + {}({}) +""" + + +REGISTERS = [ + "zero", + "s0", + "s1", + "s2", + "s3", + "s4", + "s5", + "s6", + "s7", + "s8", + "s9", + "s10", + "s11", + "a0", + "a1", + "a2", + "a3", + "a4", + "a5", + "a6", + "a7", + "tp", + "gp", + "sp", + "ra", + "t0", + "t1", + "t2", + "t3", + "t4", + "t5", + "t6", + "x0", + "x1", + "x2", + "x3", + "x4", + "x5", + "x6", + "x7", + "x8", + "x9", + "x10", + "x11", + "x12", + "x13", + "x14", + "x15", + "x16", + "x17", + "x18", + "x19", + "x20", + "x21", + "x22", + "x23", + "x24", + "x25", + "x26", + "x27", + "x28", + "x29", + "x30", + "x31", +] + + +def harness(opcode, fragment, tag): + try: + exec(fragment) + except SyntaxError: + print(tag, opcode) + + +for opcode in ("slli", "srli", "srai"): + harness(opcode, TEMPLATE3.format(opcode, "a0", "a0", -1), "-") + harness(opcode, TEMPLATE3.format(opcode, "a0", "a0", 33), "+") + +for opcode in ("c_slli", "c_srli", "c_srai"): + harness(opcode, TEMPLATE2.format(opcode, "a0", -1), "-") + harness(opcode, TEMPLATE2.format(opcode, "a0", 33), "+") + +harness("c_slli", TEMPLATE2.format("c_slli", "zero", 0), "0") +harness("c_slli", TEMPLATE2.format("c_slli", "x0", 0), "0") + +for opcode in ("c_srli", "c_srai"): + for register in REGISTERS: + harness(opcode, TEMPLATE2.format(opcode, register, 0), register) + +for opcode in ("c_mv", "c_add"): + harness(opcode, TEMPLATE2.format(opcode, "a0", "zero"), "0l") + harness(opcode, TEMPLATE2.format(opcode, "zero", "a0"), "0r") + harness(opcode, TEMPLATE2.format(opcode, "zero", "zero"), "0b") + +harness("c_jr", TEMPLATE1.format("c_jr", "zero"), "0") + +for opcode in ("addi", "andi", "ori", "slti", "sltiu", "xori"): + harness(opcode, TEMPLATE3.format(opcode, "a0", "a0", 0x7FF), ">=s") + harness(opcode, TEMPLATE3.format(opcode, "a0", "a0", 0x800), ">s") + harness(opcode, TEMPLATE3.format(opcode, "a0", "a0", -2048), "<=s") + harness(opcode, TEMPLATE3.format(opcode, "a0", "a0", -2049), "<s") + +for opcode in ("lb", "lbu", "lh", "lhu", "lw", "sb", "sh", "sw"): + TEMPLATE = """ +@micropython.asm_rv32 +def f(): + {}(a0, {}(a0)) +""" + harness(opcode, TEMPLATE.format(opcode, 0x7FF), ">=s") + harness(opcode, TEMPLATE.format(opcode, 0x800), ">s") + harness(opcode, TEMPLATE.format(opcode, -2048), "<=s") + harness(opcode, TEMPLATE.format(opcode, -2049), "<s") + +harness("c_addi", TEMPLATE2.format("c_andi", "zero", 0), "00") +harness("c_addi", TEMPLATE2.format("c_andi", "zero", 512), ">0") +harness("c_addi", TEMPLATE2.format("c_andi", "zero", -512), "<0") +harness("c_addi", TEMPLATE2.format("c_andi", "s0", 0), "s0") +harness("c_addi", TEMPLATE2.format("c_andi", "s0", -100), "<s") +harness("c_addi", TEMPLATE2.format("c_andi", "s0", 100), ">s") + +harness("c_andi", TEMPLATE2.format("c_andi", "zero", 0), "00") +harness("c_andi", TEMPLATE2.format("c_andi", "zero", 512), ">0") +harness("c_andi", TEMPLATE2.format("c_andi", "zero", -512), "<0") +harness("c_andi", TEMPLATE2.format("c_andi", "s0", 0), "s0") +harness("c_andi", TEMPLATE2.format("c_andi", "s0", -100), "<s") +harness("c_andi", TEMPLATE2.format("c_andi", "s0", 100), ">s") + +C_REGISTERS = ( + "a0", + "a1", + "a2", + "a3", + "a4", + "a5", + "s0", + "s1", + "x8", + "x9", + "x10", + "x11", + "x12", + "x13", + "x14", + "x15", +) + +for opcode in ("c_and", "c_or", "c_xor"): + for source in REGISTERS: + for destination in REGISTERS: + if source in C_REGISTERS and destination in C_REGISTERS: + try: + exec( + """ +@micropython.asm_rv32 +def f(): + {}({}, {}) +""".format(opcode, source, destination) + ) + except SyntaxError: + print(source, destination, opcode) + else: + try: + exec( + """ +@micropython.asm_rv32 +def f(): + {}({}, {}) +""".format(opcode, source, destination) + ) + print(source, destination, opcode) + except SyntaxError: + pass + print(opcode) + +for opcode in ("c_lw", "c_sw"): + TEMPLATE = """ +@micropython.asm_rv32 +def f(): + {}(a0, {}(a0)) +""" + harness(opcode, TEMPLATE.format(opcode, 60), ">=s") + harness(opcode, TEMPLATE.format(opcode, 61), ">s") + harness(opcode, TEMPLATE.format(opcode, -60), "<=s") + harness(opcode, TEMPLATE.format(opcode, -61), "<s") diff --git a/tests/inlineasm/rv32/asmsanity.py.exp b/tests/inlineasm/rv32/asmsanity.py.exp new file mode 100644 index 0000000000..c9d9b69d24 --- /dev/null +++ b/tests/inlineasm/rv32/asmsanity.py.exp @@ -0,0 +1,162 @@ +- slli ++ slli +- srli ++ srli +- srai ++ srai +- c_slli ++ c_slli +- c_srli ++ c_srli +- c_srai ++ c_srai +0 c_slli +0 c_slli +zero c_srli +s2 c_srli +s3 c_srli +s4 c_srli +s5 c_srli +s6 c_srli +s7 c_srli +s8 c_srli +s9 c_srli +s10 c_srli +s11 c_srli +a6 c_srli +a7 c_srli +tp c_srli +gp c_srli +sp c_srli +ra c_srli +t0 c_srli +t1 c_srli +t2 c_srli +t3 c_srli +t4 c_srli +t5 c_srli +t6 c_srli +x0 c_srli +x1 c_srli +x2 c_srli +x3 c_srli +x4 c_srli +x5 c_srli +x6 c_srli +x7 c_srli +x16 c_srli +x17 c_srli +x18 c_srli +x19 c_srli +x20 c_srli +x21 c_srli +x22 c_srli +x23 c_srli +x24 c_srli +x25 c_srli +x26 c_srli +x27 c_srli +x28 c_srli +x29 c_srli +x30 c_srli +x31 c_srli +zero c_srai +s2 c_srai +s3 c_srai +s4 c_srai +s5 c_srai +s6 c_srai +s7 c_srai +s8 c_srai +s9 c_srai +s10 c_srai +s11 c_srai +a6 c_srai +a7 c_srai +tp c_srai +gp c_srai +sp c_srai +ra c_srai +t0 c_srai +t1 c_srai +t2 c_srai +t3 c_srai +t4 c_srai +t5 c_srai +t6 c_srai +x0 c_srai +x1 c_srai +x2 c_srai +x3 c_srai +x4 c_srai +x5 c_srai +x6 c_srai +x7 c_srai +x16 c_srai +x17 c_srai +x18 c_srai +x19 c_srai +x20 c_srai +x21 c_srai +x22 c_srai +x23 c_srai +x24 c_srai +x25 c_srai +x26 c_srai +x27 c_srai +x28 c_srai +x29 c_srai +x30 c_srai +x31 c_srai +0l c_mv +0r c_mv +0b c_mv +0l c_add +0r c_add +0b c_add +0 c_jr +>s addi +<s addi +>s andi +<s andi +>s ori +<s ori +>s slti +<s slti +>s sltiu +<s sltiu +>s xori +<s xori +>s lb +<s lb +>s lbu +<s lbu +>s lh +<s lh +>s lhu +<s lhu +>s lw +<s lw +>s sb +<s sb +>s sh +<s sh +>s sw +<s sw +00 c_addi +>0 c_addi +<0 c_addi +<s c_addi +>s c_addi +00 c_andi +>0 c_andi +<0 c_andi +<s c_andi +>s c_andi +c_and +c_or +c_xor +>s c_lw +<s c_lw +>s c_sw +<s c_sw diff --git a/tests/inlineasm/rv32/asmshift.py b/tests/inlineasm/rv32/asmshift.py new file mode 100644 index 0000000000..89a231f4dc --- /dev/null +++ b/tests/inlineasm/rv32/asmshift.py @@ -0,0 +1,121 @@ +@micropython.asm_rv32 +def lsl1(a0): + slli(a0, a0, 1) + + +print(hex(lsl1(0x123))) + + +@micropython.asm_rv32 +def lsl23(a0): + slli(a0, a0, 23) + + +print(hex(lsl23(1))) + + +@micropython.asm_rv32 +def lsr1(a0): + srli(a0, a0, 1) + + +print(hex(lsr1(0x123))) + + +@micropython.asm_rv32 +def lsr31(a0): + srli(a0, a0, 31) + + +print(hex(lsr31(0x80000000))) + + +@micropython.asm_rv32 +def asr1(a0): + srai(a0, a0, 1) + + +print(hex(asr1(0x123))) + + +@micropython.asm_rv32 +def asr31(a0): + srai(a0, a0, 31) + + +print(hex(asr31(0x80000000))) + + +@micropython.asm_rv32 +def clsl1(a0): + c_slli(a0, 1) + + +print(hex(clsl1(0x123))) + + +@micropython.asm_rv32 +def clsl23(a0): + c_slli(a0, 23) + + +print(hex(clsl23(1))) + + +@micropython.asm_rv32 +def clsr1(a0): + c_srli(a0, 1) + + +print(hex(clsr1(0x123))) + + +@micropython.asm_rv32 +def clsr31(a0): + c_srli(a0, 31) + + +print(hex(clsr31(0x80000000))) + + +@micropython.asm_rv32 +def casr1(a0): + c_srai(a0, 1) + + +print(hex(casr1(0x123))) + + +@micropython.asm_rv32 +def casr31(a0): + c_srai(a0, 31) + + +print(hex(casr31(0x80000000))) + + +@micropython.asm_rv32 +def lsl1r(a0): + li(a1, 1) + sll(a0, a0, a1) + + +print(hex(lsl1r(0x123))) + + +@micropython.asm_rv32 +def lsr1r(a0): + li(a1, 1) + srl(a0, a0, a1) + + +print(hex(lsr1r(0x123))) + + +@micropython.asm_rv32 +def asr1r(a0): + li(a1, 1) + sra(a0, a0, a1) + + +print(hex(asr1r(0x123))) diff --git a/tests/inlineasm/rv32/asmshift.py.exp b/tests/inlineasm/rv32/asmshift.py.exp new file mode 100644 index 0000000000..feb4cc707a --- /dev/null +++ b/tests/inlineasm/rv32/asmshift.py.exp @@ -0,0 +1,15 @@ +0x246 +0x800000 +0x91 +0x1 +0x91 +-0x1 +0x246 +0x800000 +0x91 +0x1 +0x91 +-0x1 +0x246 +0x91 +0x91 diff --git a/tests/inlineasm/rv32/asmstack.py b/tests/inlineasm/rv32/asmstack.py new file mode 100644 index 0000000000..9035f87284 --- /dev/null +++ b/tests/inlineasm/rv32/asmstack.py @@ -0,0 +1,65 @@ +# test stack manipulation + + +@micropython.asm_rv32 +def l(): + li(a2, 3) + addi(sp, sp, -8) + li(a0, 0x123) + sw(a0, 0(sp)) + addi(a1, a0, 0x111) + sw(a1, 4(sp)) + c_lwsp(a3, 0) + bne(a3, a0, END) + addi(a2, a2, -1) + c_lwsp(a3, 4) + bne(a3, a1, END) + addi(a2, a2, -1) + label(END) + addi(sp, sp, 8) + mv(a0, a2) + + +print(l()) + + +@micropython.asm_rv32 +def s(): + li(a2, 3) + addi(sp, sp, -8) + li(a0, 0x123) + c_swsp(a0, 0) + addi(a1, a0, 0x111) + c_swsp(a1, 4) + lw(a3, 0(sp)) + bne(a3, a0, END) + addi(a2, a2, -1) + lw(a3, 4(sp)) + bne(a3, a1, END) + addi(a2, a2, -1) + label(END) + addi(sp, sp, 8) + mv(a0, a2) + + +print(s()) + + +@micropython.asm_rv32 +def a(): + li(a2, 3) + addi(sp, sp, -8) + li(a0, 0x123) + sw(a0, 0(sp)) + addi(a1, a0, 0x111) + sw(a1, 4(sp)) + c_addi4spn(a3, 4) + lw(a3, -4(a3)) + bne(a3, a0, END) + addi(a2, a2, -1) + label(END) + addi(sp, sp, 8) + mv(a0, a2) + + +print(a()) diff --git a/tests/inlineasm/rv32/asmstack.py.exp b/tests/inlineasm/rv32/asmstack.py.exp new file mode 100644 index 0000000000..33280629d4 --- /dev/null +++ b/tests/inlineasm/rv32/asmstack.py.exp @@ -0,0 +1,3 @@ +1 +1 +2 diff --git a/tests/inlineasm/rv32/asmsum.py b/tests/inlineasm/rv32/asmsum.py new file mode 100644 index 0000000000..5d805553b9 --- /dev/null +++ b/tests/inlineasm/rv32/asmsum.py @@ -0,0 +1,59 @@ +@micropython.asm_rv32 +def asm_sum_words(a0, a1): + # a0 = len + # a1 = ptr + # a2 = sum + # a3 = dummy + li(a2, 0) + + jal(zero, loop_entry) + + label(loop1) + lw(a3, 0(a1)) + add(a2, a2, a3) + + addi(a1, a1, 4) + addi(a0, a0, -1) + + label(loop_entry) + bne(a0, zero, loop1) + + mv(a0, a2) + + +@micropython.asm_rv32 +def asm_sum_bytes(a0, a1): + # a0 = len + # a1 = ptr + # a2 = sum + # a3 = dummy + li(a2, 0) + + jal(zero, loop_entry) + + label(loop1) + lbu(a3, 0(a1)) + add(a2, a2, a3) + + addi(a1, a1, 1) + addi(a0, a0, -1) + + label(loop_entry) + bne(a0, zero, loop1) + + mv(a0, a2) + + +import array + +b = array.array("l", (100, 200, 300, 400)) +n = asm_sum_words(len(b), b) +print(b, n) + +b = array.array("b", (10, 20, 30, 40, 50, 60, 70, 80)) +n = asm_sum_bytes(len(b), b) +print(b, n) + +b = b"\x01\x02\x03\x04" +n = asm_sum_bytes(len(b), b) +print(b, n) diff --git a/tests/inlineasm/rv32/asmsum.py.exp b/tests/inlineasm/rv32/asmsum.py.exp new file mode 100644 index 0000000000..3c83da367a --- /dev/null +++ b/tests/inlineasm/rv32/asmsum.py.exp @@ -0,0 +1,3 @@ +array('l', [100, 200, 300, 400]) 1000 +array('b', [10, 20, 30, 40, 50, 60, 70, 80]) 360 +b'\x01\x02\x03\x04' 10 diff --git a/tests/ports/qemu/asm_test.py b/tests/ports/qemu/asm_test.py index 57238c6294..ab5ce6905f 100644 --- a/tests/ports/qemu/asm_test.py +++ b/tests/ports/qemu/asm_test.py @@ -1,4 +1,10 @@ -import frozen_asm_thumb as frozen_asm +try: + import frozen_asm_thumb as frozen_asm +except ImportError: + try: + import frozen_asm_rv32 as frozen_asm + except ImportError: + raise ImportError print(frozen_asm.asm_add(1, 2)) print(frozen_asm.asm_add1(3)) diff --git a/tests/run-tests.py b/tests/run-tests.py index f00510f2da..db5ebe34cc 100755 --- a/tests/run-tests.py +++ b/tests/run-tests.py @@ -1245,9 +1245,12 @@ the last matching regex is used: elif args.platform == "qemu": test_dirs += ( "float", - "inlineasm/thumb", "ports/qemu", ) + if args.arch == "rv32imc": + test_dirs += ("inlineasm/rv32",) + else: + test_dirs += ("inlineasm/thumb",) elif args.platform == "webassembly": test_dirs += ("float", "ports/webassembly") else: |