py/emitinlinextensa: Add the rest of LX3 opcodes to the assembler.

This commit expands the Xtensa inline assembler to support most if not
all opcodes available on the ESP8266 and LX3 Xtensa cores.

This is meant as a stepping stone to add inline assembler support for
the ESP32 and its LX6 core, along to windowed-specific opcodes and
additional opcodes that are present only on the LX7 core (ESP32-S3 and
later).

New opcodes being added are covered by tests, and the provided tests
were expanded to also include opcodes available in the existing
implementation.  Given that the ESP8266 space requirements are tighter
than ESP32's, certain opcodes that won't be commonly used have been put
behind a define to save some space in the general use case.

Signed-off-by: Alessandro Gatti <a.gatti@frob.it>
This commit is contained in:
Alessandro Gatti
2025-01-25 09:33:41 +01:00
committed by Damien George
parent 555f1cf488
commit 1006ed69f0
18 changed files with 1145 additions and 14 deletions

View File

@@ -0,0 +1,44 @@
# test passing arguments
@micropython.asm_xtensa
def arg0():
movi(a2, 1)
print(arg0())
@micropython.asm_xtensa
def arg1(a2):
addi(a2, a2, 1)
print(arg1(1))
@micropython.asm_xtensa
def arg2(a2, a3):
add(a2, a2, a3)
print(arg2(1, 2))
@micropython.asm_xtensa
def arg3(a2, a3, a4):
add(a2, a2, a3)
add(a2, a2, a4)
print(arg3(1, 2, 3))
@micropython.asm_xtensa
def arg4(a2, a3, a4, a5):
add(a2, a2, a3)
add(a2, a2, a4)
add(a2, a2, a5)
print(arg4(1, 2, 3, 4))

View File

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

View File

@@ -0,0 +1,119 @@
@micropython.asm_xtensa
def f1(a2):
abs_(a2, a2)
for value in (10, -10, 0):
print(f1(value))
ADDMI_TEMPLATE = """
@micropython.asm_xtensa
def f1(a2) -> int:
addmi(a2, a2, {})
print(f1(0))
"""
for value in (-32768, -32767, 32512, 32513, 0):
try:
exec(ADDMI_TEMPLATE.format(value))
except SyntaxError as error:
print(error)
@micropython.asm_xtensa
def a2(a2, a3) -> int:
addx2(a2, a2, a3)
@micropython.asm_xtensa
def a4(a2, a3) -> int:
addx4(a2, a2, a3)
@micropython.asm_xtensa
def a8(a2, a3) -> int:
addx8(a2, a2, a3)
@micropython.asm_xtensa
def s2(a2, a3) -> int:
subx2(a2, a2, a3)
@micropython.asm_xtensa
def s4(a2, a3) -> int:
subx4(a2, a2, a3)
@micropython.asm_xtensa
def s8(a2, a3) -> int:
subx8(a2, a2, a3)
for first, second in ((100, 100), (-100, 100), (-100, -100), (100, -100)):
print("a2", a2(first, second))
print("a4", a4(first, second))
print("a8", a8(first, second))
print("s2", s2(first, second))
print("s4", s4(first, second))
print("s8", s8(first, second))
@micropython.asm_xtensa
def f5(a2) -> int:
neg(a2, a2)
for value in (0, -100, 100):
print(f5(value))
@micropython.asm_xtensa
def f6():
movi(a2, 0x100)
movi(a3, 1)
add(a2, a2, a3)
addi(a2, a2, 1)
addi(a2, a2, -2)
sub(a2, a2, a3)
print(hex(f6()))
@micropython.asm_xtensa
def f7():
movi(a2, 0x10FF)
movi(a3, 1)
and_(a4, a2, a3)
or_(a4, a4, a3)
movi(a3, 0x200)
xor(a2, a4, a3)
print(hex(f7()))
@micropython.asm_xtensa
def f8(a2, a3):
add_n(a2, a2, a3)
print(f8(100, 200))
@micropython.asm_xtensa
def f9(a2):
addi_n(a2, a2, 1)
print(f9(100))
@micropython.asm_xtensa
def f10(a2, a3) -> uint:
mull(a2, a2, a3)
print(hex(f10(0xC0000000, 2)))

View File

@@ -0,0 +1,40 @@
10
10
0
-32768
-32767 is not a multiple of 256
32512
'addmi' integer 32513 isn't within range -32768..32512
0
a2 300
a4 500
a8 900
s2 100
s4 300
s8 700
a2 -100
a4 -300
a8 -700
s2 -300
s4 -500
s8 -900
a2 -300
a4 -500
a8 -900
s2 -100
s4 -300
s8 -700
a2 100
a4 300
a8 700
s2 300
s4 500
s8 900
0
100
-100
0xff
0x201
300
101
0x80000000

View File

@@ -0,0 +1,299 @@
# test branch instructions
@micropython.asm_xtensa
def tball(a2, a3) -> int:
mov(a4, a2)
movi(a2, 0)
ball(a4, a3, end)
movi(a2, -1)
label(end)
print(tball(0xFFFFFFFF, 0xFFFFFFFF))
print(tball(0xFFFEFFFF, 0xFFFFFFFF))
print(tball(0x00000000, 0xFFFFFFFF))
print(tball(0xFFFFFFFF, 0x01010101))
@micropython.asm_xtensa
def tbany(a2, a3) -> int:
mov(a4, a2)
movi(a2, 0)
bany(a4, a3, end)
movi(a2, -1)
label(end)
print(tbany(0xFFFFFFFF, 0xFFFFFFFF))
print(tbany(0xFFFEFFFF, 0xFFFFFFFF))
print(tbany(0x00000000, 0xFFFFFFFF))
print(tbany(0xFFFFFFFF, 0x01010101))
@micropython.asm_xtensa
def tbbc(a2, a3) -> int:
mov(a4, a2)
movi(a2, 0)
bbc(a4, a3, end)
movi(a2, -1)
label(end)
print(tbbc(0xFFFFFFFF, 4))
print(tbbc(0xFFFEFFFF, 16))
print(tbbc(0x00000000, 1))
BBCI_TEMPLATE = """
@micropython.asm_xtensa
def tbbci(a2) -> int:
mov(a3, a2)
movi(a2, 0)
bbci(a3, {}, end)
movi(a2, -1)
label(end)
print(tbbci({}))
"""
for value, bit in ((0xFFFFFFFF, 4), (0xFFFEFFFF, 16), (0x00000000, 1)):
try:
exec(BBCI_TEMPLATE.format(bit, value))
except SyntaxError as error:
print(error)
@micropython.asm_xtensa
def tbbs(a2, a3) -> int:
mov(a4, a2)
movi(a2, 0)
bbs(a4, a3, end)
movi(a2, -1)
label(end)
print(tbbs(0x00000000, 4))
print(tbbs(0x00010000, 16))
print(tbbs(0xFFFFFFFF, 1))
BBSI_TEMPLATE = """
@micropython.asm_xtensa
def tbbsi(a2) -> int:
mov(a3, a2)
movi(a2, 0)
bbsi(a3, {}, end)
movi(a2, -1)
label(end)
print(tbbsi({}))
"""
for value, bit in ((0x00000000, 4), (0x00010000, 16), (0xFFFFFFFF, 1)):
try:
exec(BBSI_TEMPLATE.format(bit, value))
except SyntaxError as error:
print(error)
@micropython.asm_xtensa
def tbeq(a2, a3) -> int:
mov(a4, a2)
movi(a2, 0)
beq(a4, a3, end)
movi(a2, -1)
label(end)
print(tbeq(0x00000000, 0x00000000))
print(tbeq(0x00010000, 0x00000000))
print(tbeq(0xFFFFFFFF, 0xFFFFFFFF))
@micropython.asm_xtensa
def tbeqz(a2) -> int:
mov(a3, a2)
movi(a2, 0)
beqz(a3, end)
movi(a2, -1)
label(end)
print(tbeqz(0))
print(tbeqz(0x12345678))
print(tbeqz(-1))
@micropython.asm_xtensa
def tbge(a2, a3) -> int:
mov(a4, a2)
movi(a2, 0)
bge(a4, a3, end)
movi(a2, -1)
label(end)
print(tbge(0x00000000, 0x00000000))
print(tbge(0x00010000, 0x00000000))
print(tbge(0xF0000000, 0xFFFFFFFF))
@micropython.asm_xtensa
def tbgeu(a2, a3) -> int:
mov(a4, a2)
movi(a2, 0)
bgeu(a4, a3, end)
movi(a2, -1)
label(end)
print(tbgeu(0x00000000, 0x00000000))
print(tbgeu(0x00010000, 0x00000000))
print(tbgeu(0xF0000000, 0xFFFFFFFF))
print(tbgeu(0xFFFFFFFF, 0xF0000000))
@micropython.asm_xtensa
def tbgez(a2) -> int:
mov(a3, a2)
movi(a2, 0)
bgez(a3, end)
movi(a2, -1)
label(end)
print(tbgez(0))
print(tbgez(0x12345678))
print(tbgez(-1))
@micropython.asm_xtensa
def tblt(a2, a3) -> int:
mov(a4, a2)
movi(a2, 0)
blt(a4, a3, end)
movi(a2, -1)
label(end)
print(tblt(0x00000000, 0x00000000))
print(tblt(0x00010000, 0x00000000))
print(tblt(0xF0000000, 0xFFFFFFFF))
@micropython.asm_xtensa
def tbltu(a2, a3) -> int:
mov(a4, a2)
movi(a2, 0)
bltu(a4, a3, end)
movi(a2, -1)
label(end)
print(tbltu(0x00000000, 0x00000000))
print(tbltu(0x00010000, 0x00000000))
print(tbltu(0xF0000000, 0xFFFFFFFF))
print(tbltu(0xFFFFFFFF, 0xF0000000))
@micropython.asm_xtensa
def tbltz(a2) -> int:
mov(a3, a2)
movi(a2, 0)
bltz(a3, end)
movi(a2, -1)
label(end)
print(tbltz(0))
print(tbltz(0x12345678))
print(tbltz(-1))
@micropython.asm_xtensa
def tbnall(a2, a3) -> int:
mov(a4, a2)
movi(a2, 0)
bnall(a4, a3, end)
movi(a2, -1)
label(end)
print(tbnall(0xFFFFFFFF, 0xFFFFFFFF))
print(tbnall(0xFFFEFFFF, 0xFFFFFFFF))
print(tbnall(0x00000000, 0xFFFFFFFF))
print(tbnall(0xFFFFFFFF, 0x01010101))
@micropython.asm_xtensa
def tbne(a2, a3) -> int:
mov(a4, a2)
movi(a2, 0)
bne(a4, a3, end)
movi(a2, -1)
label(end)
print(tbne(0x00000000, 0x00000000))
print(tbne(0x00010000, 0x00000000))
print(tbne(0xFFFFFFFF, 0xFFFFFFFF))
@micropython.asm_xtensa
def tbnez(a2) -> int:
mov(a3, a2)
movi(a2, 0)
bnez(a3, end)
movi(a2, -1)
label(end)
print(tbnez(0))
print(tbnez(0x12345678))
print(tbnez(-1))
@micropython.asm_xtensa
def tbnone(a2, a3) -> int:
mov(a4, a2)
movi(a2, 0)
bnone(a4, a3, end)
movi(a2, -1)
label(end)
print(tbnone(0xFFFFFFFF, 0xFFFFFFFF))
print(tbnone(0xFFFEFFFF, 0xFFFFFFFF))
print(tbnone(0x00000000, 0xFFFFFFFF))
print(tbnone(0x10101010, 0x01010101))
@micropython.asm_xtensa
def tbeqz_n(a2) -> int:
mov(a3, a2)
movi(a2, 0)
beqz_n(a3, end)
movi(a2, -1)
label(end)
print(tbeqz_n(0))
print(tbeqz_n(0x12345678))
print(tbeqz_n(-1))
@micropython.asm_xtensa
def tbnez_n(a2) -> int:
mov(a3, a2)
movi(a2, 0)
bnez(a3, end)
movi(a2, -1)
label(end)
print(tbnez_n(0))
print(tbnez_n(0x12345678))
print(tbnez_n(-1))

View File

@@ -0,0 +1,66 @@
0
-1
-1
0
0
0
-1
0
-1
0
0
-1
0
0
-1
0
0
-1
0
0
0
-1
0
0
-1
-1
0
0
-1
0
0
-1
0
0
0
-1
-1
-1
0
-1
-1
0
-1
-1
-1
0
-1
0
0
-1
-1
0
-1
-1
0
0
-1
-1
0
0
0
-1
-1
-1
0
0

View File

@@ -0,0 +1,26 @@
@micropython.asm_xtensa
def jump() -> int:
movi(a2, 0)
j(NEXT)
addi(a2, a2, 1)
j(DONE)
label(NEXT)
addi(a2, a2, 2)
label(DONE)
print(jump())
@micropython.asm_xtensa
def jumpx() -> int:
call0(ENTRY)
label(ENTRY)
movi(a2, 0)
addi(a3, a0, 12)
jx(a3)
movi(a2, 1)
movi(a2, 2)
print(jumpx())

View File

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

View File

@@ -0,0 +1,98 @@
import array
# On the 8266 the generated code gets put into the IRAM segment, which is only
# word-addressable. Therefore, to test byte and halfword load/store opcodes
# some memory must be reserved in the DRAM segment.
BYTE_DATA = array.array("B", (0x11, 0x22, 0x33, 0x44))
WORD_DATA = array.array("h", (100, 200, -100, -200))
DWORD_DATA = array.array("i", (100_000, -200_000, 300_000, -400_000))
@micropython.asm_xtensa
def tl32r() -> int:
nop()
j(CODE)
align(4)
label(DATA)
data(1, 1, 2, 3, 4, 5, 6, 7)
align(4)
label(CODE)
nop_n()
nop_n()
l32r(a2, DATA)
print(hex(tl32r()))
@micropython.asm_xtensa
def tl32i() -> uint:
call0(ENTRY)
label(ENTRY)
l32i(a2, a0, 0)
print(hex(tl32i()))
@micropython.asm_xtensa
def tl8ui(a2) -> uint:
mov(a3, a2)
l8ui(a2, a3, 1)
print(hex(tl8ui(BYTE_DATA)))
@micropython.asm_xtensa
def tl16ui(a2) -> uint:
mov(a3, a2)
l16ui(a2, a3, 2)
print(tl16ui(WORD_DATA))
@micropython.asm_xtensa
def tl16si(a2) -> int:
mov(a3, a2)
l16si(a2, a3, 6)
print(tl16si(WORD_DATA))
@micropython.asm_xtensa
def ts8i(a2, a3):
s8i(a3, a2, 1)
ts8i(BYTE_DATA, 0xFF)
print(BYTE_DATA)
@micropython.asm_xtensa
def ts16i(a2, a3):
s16i(a3, a2, 2)
ts16i(WORD_DATA, -123)
print(WORD_DATA)
@micropython.asm_xtensa
def ts32i(a2, a3) -> uint:
s32i(a3, a2, 4)
ts32i(DWORD_DATA, -123456)
print(DWORD_DATA)
@micropython.asm_xtensa
def tl32i_n(a2) -> uint:
l32i_n(a2, a2, 8)
print(tl32i_n(DWORD_DATA))

View File

@@ -0,0 +1,9 @@
0x4030201
0xf8002022
0x22
200
-200
array('B', [17, 255, 51, 68])
array('h', [100, -123, -100, -200])
array('i', [100000, -123456, 300000, -400000])
300000

View File

@@ -0,0 +1,25 @@
@micropython.asm_xtensa
def tnop(a2, a3, a4, a5):
nop()
out2 = tnop(0x100, 0x200, 0x300, 0x400)
print(out2 == 0x100)
@micropython.asm_xtensa
def tnop_n(a2, a3, a4, a5):
nop_n()
out2 = tnop_n(0x100, 0x200, 0x300, 0x400)
print(out2 == 0x100)
@micropython.asm_xtensa
def tmov_n(a2, a3):
mov_n(a4, a3)
add(a2, a4, a3)
print(tmov_n(0, 1))

View File

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

View File

@@ -0,0 +1,137 @@
@micropython.asm_xtensa
def lsl1(a2):
slli(a2, a2, 1)
print(hex(lsl1(0x123)))
@micropython.asm_xtensa
def lsl23(a2):
slli(a2, a2, 23)
print(hex(lsl23(1)))
@micropython.asm_xtensa
def lsr1(a2):
srli(a2, a2, 1)
print(hex(lsr1(0x123)))
@micropython.asm_xtensa
def lsr15(a2):
srli(a2, a2, 15)
print(hex(lsr15(0x80000000)))
@micropython.asm_xtensa
def asr1(a2):
srai(a2, a2, 1)
print(hex(asr1(0x123)))
@micropython.asm_xtensa
def asr31(a2):
srai(a2, a2, 31)
print(hex(asr31(0x80000000)))
@micropython.asm_xtensa
def lsl1r(a2):
movi(a3, 1)
ssl(a3)
sll(a2, a2)
print(hex(lsl1r(0x123)))
@micropython.asm_xtensa
def lsr1r(a2):
movi(a3, 1)
ssr(a3)
srl(a2, a2)
print(hex(lsr1r(0x123)))
@micropython.asm_xtensa
def asr1r(a2):
movi(a3, 1)
ssr(a3)
sra(a2, a2)
print(hex(asr1r(0x123)))
@micropython.asm_xtensa
def sll9(a2):
ssai(9)
sll(a2, a2)
print(hex(sll9(1)))
@micropython.asm_xtensa
def srlr(a2, a3):
ssa8l(a3)
srl(a2, a2)
print(hex(srlr(0x12340000, 2)))
@micropython.asm_xtensa
def sllr(a2, a3):
ssa8b(a3)
sll(a2, a2)
print(hex(sllr(0x1234, 2)))
@micropython.asm_xtensa
def srcr(a2, a3, a4):
ssr(a4)
src(a2, a2, a3)
print(hex(srcr(0x00000001, 0x80000000, 2)))
@micropython.asm_xtensa
def srai24(a2):
srai(a2, a2, 24)
print(hex(srai24(0x12345678)))
@micropython.asm_xtensa
def nsar(a2, a3):
nsa(a2, a3)
print(nsar(0x12345678, 0))
print(nsar(0x12345678, -1))
@micropython.asm_xtensa
def nsaur(a2, a3):
nsau(a2, a3)
print(nsaur(0x12345678, 0))

View File

@@ -0,0 +1,17 @@
0x246
0x800000
0x91
0x10000
0x91
-0x1
0x246
0x91
0x91
0x800000
0x1234
0x12340000
0x60000000
0x12
31
31
32