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>
This commit is contained in:
Alessandro Gatti
2024-08-25 16:28:35 +02:00
committed by Damien George
parent 3044233ea3
commit 268acb714d
47 changed files with 2649 additions and 45 deletions

View File

@@ -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))

View File

@@ -0,0 +1,5 @@
1
2
3
6
10

View File

@@ -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))

View File

@@ -0,0 +1,14 @@
0xfe
0x111
1
0
0
0
1
0
0
0
0
1
0
1

View File

@@ -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))

View File

@@ -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

View File

@@ -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()))

View File

@@ -0,0 +1,5 @@
0xfffffff
0x12345678
0x7ff
0xffffffff
0x1001

View File

@@ -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())

View File

@@ -0,0 +1,2 @@
4
5

View File

@@ -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)))

View File

@@ -0,0 +1,10 @@
0x12345678
0x20000000
0x40000000
0x80000000
0xfffffffe
0x12345678
0x20000000
0x40000000
0x80000000
0xfffffffe

View File

@@ -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))

View File

@@ -0,0 +1,18 @@
411
-411
-411
411
411
2
1
1
-1
1
-1
1
1
0
-2
0
-17
-1

View File

@@ -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())

View File

@@ -0,0 +1,6 @@
0
0
0
0
0
0

View File

@@ -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())

View File

@@ -0,0 +1,3 @@
0
1
2

View File

@@ -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)))

View File

@@ -0,0 +1,4 @@
1
False True
0 0x20000000 0x40000000 -0x80000000
0 0x20000000 0x40000000 0x80000000

View File

@@ -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")

View File

@@ -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

View File

@@ -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)))

View File

@@ -0,0 +1,15 @@
0x246
0x800000
0x91
0x1
0x91
-0x1
0x246
0x800000
0x91
0x1
0x91
-0x1
0x246
0x91
0x91

View File

@@ -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())

View File

@@ -0,0 +1,3 @@
1
1
2

View File

@@ -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)

View File

@@ -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

View File

@@ -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))

View File

@@ -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: