summaryrefslogtreecommitdiffstatshomepage
path: root/tests
diff options
context:
space:
mode:
authorAlessandro Gatti <a.gatti@frob.it>2024-08-25 16:28:35 +0200
committerDamien George <damien@micropython.org>2025-01-02 11:49:10 +1100
commit268acb714dd79fa5eeeb82c1fca022bc4ea126b7 (patch)
tree428ed75070ee89847fd5087095e3d7331d5f9b26 /tests
parent3044233ea3726e9d8727d8f6a76f32c48e6fae5e (diff)
downloadmicropython-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')
-rw-r--r--tests/inlineasm/rv32/asmargs.py44
-rw-r--r--tests/inlineasm/rv32/asmargs.py.exp5
-rw-r--r--tests/inlineasm/rv32/asmarith.py79
-rw-r--r--tests/inlineasm/rv32/asmarith.py.exp14
-rw-r--r--tests/inlineasm/rv32/asmbranch.py161
-rw-r--r--tests/inlineasm/rv32/asmbranch.py.exp32
-rw-r--r--tests/inlineasm/rv32/asmconst.py49
-rw-r--r--tests/inlineasm/rv32/asmconst.py.exp5
-rw-r--r--tests/inlineasm/rv32/asmcsr.py65
-rw-r--r--tests/inlineasm/rv32/asmcsr.py.exp2
-rw-r--r--tests/inlineasm/rv32/asmdata.py33
-rw-r--r--tests/inlineasm/rv32/asmdata.py.exp10
-rw-r--r--tests/inlineasm/rv32/asmdivmul.py63
-rw-r--r--tests/inlineasm/rv32/asmdivmul.py.exp18
-rw-r--r--tests/inlineasm/rv32/asmjump.py115
-rw-r--r--tests/inlineasm/rv32/asmjump.py.exp6
-rw-r--r--tests/inlineasm/rv32/asmloadstore.py86
-rw-r--r--tests/inlineasm/rv32/asmloadstore.py.exp3
-rw-r--r--tests/inlineasm/rv32/asmrettype.py33
-rw-r--r--tests/inlineasm/rv32/asmrettype.py.exp4
-rw-r--r--tests/inlineasm/rv32/asmsanity.py204
-rw-r--r--tests/inlineasm/rv32/asmsanity.py.exp162
-rw-r--r--tests/inlineasm/rv32/asmshift.py121
-rw-r--r--tests/inlineasm/rv32/asmshift.py.exp15
-rw-r--r--tests/inlineasm/rv32/asmstack.py65
-rw-r--r--tests/inlineasm/rv32/asmstack.py.exp3
-rw-r--r--tests/inlineasm/rv32/asmsum.py59
-rw-r--r--tests/inlineasm/rv32/asmsum.py.exp3
-rw-r--r--tests/ports/qemu/asm_test.py8
-rwxr-xr-xtests/run-tests.py5
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: