8000 Correct decoding of esp32s2 negative LD/ST offsets · wnienhaus/micropython-esp32-ulp@a157ebe · GitHub
[go: up one dir, main page]

Skip to content

Commit a157ebe

Browse files
committed
Correct decoding of esp32s2 negative LD/ST offsets
The ESP32-S2/S3 support a negative offset in ST/LD instructions. Those offsets are two's-complement encoded into a field that is 11-bits wide. This change corrects the decoding of negative offsets given the field width of just 11-bits, rather than relying on the 32 or 64 bits of a MicroPython `int`. Note 1: Negative offsets used in JUMP instructions are encoded differently (sign bit + positive value), and their decoding is already done correctly. Note 2: The LD/ST instructions in of the ESP32 do not support negative offsets (according to Espressif tests), so their decoding remains as is.
1 parent 9bc6fc3 commit a157ebe

File tree

4 files changed

+72
-11
lines changed

4 files changed

+72
-11
lines changed

tests/fixtures/all_opcodes-v.esp32s2.lst

Lines changed: 42 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
header
22
ULP magic : b'ulp\x00' (0x00706c75)
33
.text offset : 12 (0x0c)
4-
.text size : 244 (0xf4)
5-
.data offset : 256 (0x100)
4+
.text size : 260 (0x104)
5+
.data offset : 272 (0x110)
66
.data size : 8 (0x08)
77
.bss size : 0 (0x00)
88
----------------------------------------
@@ -527,7 +527,45 @@ ULP magic : b'ulp\x00' (0x00706c75)
527527
label = 0
528528
upper = 0
529529
wr_way = 0
530+
00f4 09e01fd0 LD r1, r2, -8
531+
dreg = 1
532+
offset = -8 (0x7f8)
533+
opcode = 13 (0x0d)
534+
sreg = 2
535+
unused1 = 0
536+
unused2 = 0
537+
rd_upper = 0
538+
00f8 09e01fd8 LDH r1, r2, -8
539+
dreg = 1
540+
offset = -8 (0x7f8)
541+
opcode = 13 (0x0d)
542+
sreg = 2
543+
unused1 = 0
544+
unused2 = 0
545+
rd_upper = 1
546+
00fc 89e11f68 ST r1, r2, -8
547+
dreg = 2
548+
offset = -8 (0x7f8)
549+
opcode = 6
550+
sreg = 1
551+
sub_opcode = 4
552+
unused1 = 0
553+
unused2 = 0
554+
label = 0
555+
upper = 0
556+
wr_way = 3
557+
0100 c9e11f68 STH r1, r2, -8
558+
dreg = 2
559+
offset = -8 (0x7f8)
560+
opcode = 6
561+
sreg = 1
562+
sub_opcode = 4
563+
unused1 = 0
564+
unused2 = 0
565+
label = 0
566+
upper = 1
567+
wr_way = 3
530568
----------------------------------------
531569
.data
532-
00f4 00000000 <empty>
533-
00f8 fecadec0 <non-empty>
570+
0104 00000000 <empty>
571+
0108 fecadec0 <non-empty>

tests/fixtures/all_opcodes.esp32s2.S

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,3 +89,9 @@ STI32 R1, R2, 0
8989
STI32 R1, R2, 1
9090

9191
STO 0x20
92+
93+
LDL R1, R2, -0x20
94+
LDH R1, R2, -0x20
95+
96+
STL R1, R2, -0x20
97+
STH R1, R2, -0x20

tests/fixtures/all_opcodes.esp32s2.lst

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,10 @@
6060
00e8 09000062 STI32 r1, r2, 0
6161
00ec 19000062 STI32 r1, r2, 1
6262
00f0 00200064 STO 8
63+
00f4 09e01fd0 LD r1, r2, -8
64+
00f8 09e01fd8 LDH r1, r2, -8
65+
00fc 89e11f68 ST r1, r2, -8
66+
0100 c9e11f68 STH r1, r2, -8
6367
.data
64-
00f4 00000000 <empty>
65-
00f8 fecadec0 <non-empty>
68+
0104 00000000 <empty>
69+
0108 fecadec0 <non-empty>

tools/decode_s2.py

Lines changed: 18 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,7 @@
6666
opcodes.OPCODE_LD: (
6767
'LD/LDH',
6868
opcodes._ld,
69-
lambda op: '%s r%s, r%s, %s' % ('LDH' if op.rd_upper else 'LD', op.dreg, op.sreg, op.offset)
69+
lambda op: '%s r%s, r%s, %s' % ('LDH' if op.rd_upper else 'LD', op.dreg, op.sreg, twos_comp(op.offset, 11))
7070
),
7171
opcodes.OPCODE_ST: ('ST', opcodes._st, {
7272
opcodes.SUB_OPCODE_ST_AUTO: (
@@ -79,14 +79,14 @@
7979
opcodes.SUB_OPCODE_ST_OFFSET: (
8080
'STO',
8181
opcodes._st,
82-
lambda op: 'STO %s' % op.offset
82+
lambda op: 'STO %s' % twos_comp(op.offset, 11)
8383
),
8484
opcodes.SUB_OPCODE_ST: (
8585
'ST/STH/ST32',
8686
opcodes._st,
87-
lambda op: '%s r%s, r%s, %s, %s' % ('STH' if op.upper else 'STL', op.sreg, op.dreg, op.offset, op.label) if op.wr_way and op.label
88-
else '%s r%s, r%s, %s' % ('STH' if op.upper else 'ST', op.sreg, op.dreg, op.offset) if op.wr_way
89-
else 'ST32 r%s, r%s, %s, %s' % (op.sreg, op.dreg, op.offset, op.label)
87+
lambda op: '%s r%s, r%s, %s, %s' % ('STH' if op.upper else 'STL', op.sreg, op.dreg, twos_comp(op.offset, 11), op.label) if op.wr_way and op.label
88+
else '%s r%s, r%s, %s' % ('STH' if op.upper else 'ST', op.sreg, op.dreg, twos_comp(op.offset, 11)) if op.wr_way
89+
else 'ST32 r%s, r%s, %s, %s' % (op.sreg, op.dreg, twos_comp(op.offset, 11), op.label)
9090
)
9191
}),
9292
opcodes.OPCODE_RD_REG: (
@@ -103,6 +103,16 @@
103103
}
104104

105105

106+
def twos_comp(val, bits):
107+
"""
108+
compute the correct value of a 2's complement
109+
based on the number of bits in the source
110+
"""
111+
if (val & (1 << (bits - 1))) != 0: # if sign bit is set e.g., 8bit: 128-255
112+
val = val - (1 << bits) # compute negative value
113+
return val
114+
115+
106116
def decode_instruction(i):
107117
if i == 0:
108118
raise Exception('<empty>')
@@ -167,6 +177,9 @@ def get_instruction_fields(ins):
167177
extra = ' (%s)' % bs_cmp_ops[val]
168178
else:
169179
extra = ' (%s)' % cmp_ops[val]
180+
elif field == 'offset':
181+
if ins.opcode in (opcodes.OPCODE_ST, opcodes.OPCODE_LD):
182+
val = twos_comp(val, 11)
170183

171184
field_details.append((field, val, extra))
172185

0 commit comments

Comments
 (0)
0