8000 Replace crude disassembly with lookup table · Plaque-fcc/micropython-esp32-ulp@4c834e3 · GitHub
[go: up one dir, main page]

Skip to content

Commit 4c834e3

Browse files
committed
Replace crude disassembly with lookup table
In this approach, each opcode has its own decoding (using the correct struct for each opcode). Each opcode (or opcode+subopcode) also has its own rendering function. The lookup table is hierarchical so the same structure used for opcodes is also used within opcodes for looking up subopcodes.
1 parent ce82cbb commit 4c834e3

File tree

1 file changed

+111
-73
lines changed

1 file changed

+111
-73
lines changed

tools/disassemble.py

Lines changed: 111 additions & 73 deletions
Original file line numberDiff line numberDiff line change
@@ -1,82 +1,122 @@
1+
from esp32_ulp.opcodes import RD_REG_PERIPH_RTC_CNTL, RD_REG_PERIPH_RTC_IO, RD_REG_PERIPH_RTC_I2C, \
2+
RD_REG_PERIPH_SENS, DR_REG_MAX_DIRECT
13
import esp32_ulp.opcodes as opcodes
4+
import esp32_ulp.soc as soc
25
import ubinascii
36
import sys
47

58

9+
alu_cnt_ops = ('STAGE_INC', 'STAGE_DEC', 'STAGE_RST')
10+
alu_ops = ('ADD', 'SUB', 'AND', 'OR', 'MOVE', 'LSH', 'RSH')
11+
jump_types = ('--', 'EQ', 'OV')
12+
cmp_ops = ('LT', 'GE', 'LE', 'EQ', 'GT')
13+
14+
lookup = {
15+
opcodes.OPCODE_ADC: ('ADC', opcodes._adc, lambda op: 'ADC r%s, %s, %s' % (op.dreg, op.mux, op.sar_sel)),
16+
opcodes.OPCODE_ALU: ('ALU', opcodes._alu_imm, {
17+
opcodes.SUB_OPCODE_ALU_CNT: (
18+
'ALU_CNT',
19+
opcodes._alu_cnt,
20+
lambda op: '%s%s' % (alu_cnt_ops[op.sel], '' if op.sel == opcodes.ALU_SEL_RST else ' %s' % op.imm)
21+
),
22+
opcodes.SUB_OPCODE_ALU_IMM: (
23+
'ALU_IMM',
24+
opcodes._alu_imm,
25+
lambda op: '%s r%s, %s' % (alu_ops[op.sel], op.dreg, op.imm) if op.sel == opcodes.ALU_SEL_MOV
26+
else '%s r%s, r%s, %s' % (alu_ops[op.sel], op.dreg, op.sreg, op.imm)
27+
),
28+
opcodes.SUB_OPCODE_ALU_REG: (
29+
'ALU_REG',
30+
opcodes._alu_reg,
31+
lambda op: '%s r%s, r%s, r%s' % (alu_ops[op.sel], op.dreg, op.sreg, op.treg)
32+
),
33+
}),
34+
opcodes.OPCODE_BRANCH: ('BRANCH', opcodes._bx, {
35+
opcodes.SUB_OPCODE_BX: (
36+
'BX',
37+
opcodes._bx,
38+
lambda op: 'JUMP %s%s' % (op.addr if op.reg == 0 else 'r%s' % op.dreg, ', %s' % jump_types[op.type]
39+
if op.type != 0 else '')
40+
),
41+
opcodes.SUB_OPCODE_BR: (
42+
'BR',
43+
opcodes._br,
44+
lambda op: 'JUMPR %s, %s, %s' % ('%s%s' % ('-' if op.sign == 1 else '', op.offset), op.imm, cmp_ops[op.cmp])
45+
),
46+
opcodes.SUB_OPCODE_BS: (
47+
'BS',
48+
opcodes._bs,
49+
lambda op: 'JUMPS %s, %s, %s' % ('%s%s' % ('-' if op.sign == 1 else '', op.offset), op.imm, cmp_ops[op.cmp])
50+
),
51+
}),
52+
opcodes.OPCODE_DELAY: (
53+
'DELAY',
54+
opcodes._delay,
55+
lambda op: 'NOP' if op.cycles == 0 else 'WAIT %s' % op.cycles
56+
),
57+
opcodes.OPCODE_END: ('END', opcodes._end, {
58+
opcodes.SUB_OPCODE_END: (
59+
'WAKE',
60+
opcodes._end
61+
),
62+
opcodes.SUB_OPCODE_SLEEP: (
63+
'SLEEP',
64+
opcodes._sleep,
65+
lambda op: 'SLEEP %s' % op.cycle_sel
66+
),
67+
}),
68+
opcodes.OPCODE_HALT: ('HALT', opcodes._halt),
69+
opcodes.OPCODE_I2C: (
70+
'I2C',
71+
opcodes._i2c,
72+
lambda op: 'I2C_%s %s, %s, %s, %s' % ('RD' if op.rw == 0 else 'WR', op.sub_addr, op.high, op.low, op.i2c_sel)
73+
),
74+
opcodes.OPCODE_LD: ('LD', opcodes._ld, lambda op: 'LD r%s, r%s, %s' % (op.dreg, op.sreg, op.offset)),
75+
opcodes.OPCODE_ST: ('ST', opcodes._st, lambda op: 'ST r%s, r%s, %s' % (op.sreg, op.dreg, op.offset)),
76+
opcodes.OPCODE_RD_REG: (
77+
'RD_REG',
78+
opcodes._rd_reg,
79+
lambda op: 'REG_RD 0x%x, %s, %s' % (op.periph_sel << 8 | op.addr, op.high, op.low)
80+
),
81+
opcodes.OPCODE_WR_REG: (
82+
'WR_REG',
83+
opcodes._wr_reg,
84+
lambda op: 'REG_WR 0x%x, %s, %s, %s' % (op.periph_sel << 8 | op.addr, op.high, op.low, op.data)
85+
),
86+
opcodes.OPCODE_TSENS: ('TSENS', opcodes._tsens, lambda op: 'TSENS r%s, %s' % (op.dreg, op.delay)),
87+
}
88+
89+
690
def decode_instruction(i):
791
ins = opcodes._end
8-
ins.all = i # abuse a struct to get opcode and sub_opcode
92+
ins.all = i # abuse a struct to get opcode
993

1094
print(ubinascii.hexlify(i.to_bytes(4, 'little')))
1195

12-
if ins.opcode == opcodes.OPCODE_ADC:
13-
print('OPCODE_ADC' A3E2 )
14-
opcodes._adc.all = i
15-
ins = opcodes._adc
16-
elif ins.opcode == opcodes.OPCODE_ALU and ins.sub_opcode == opcodes.SUB_OPCODE_ALU_CNT:
17-
print('OPCODE_ALU / SUB_OPCODE_ALU_CNT')
18-
opcodes._alu_cnt.all = i
19-
ins = opcodes._alu_cnt
20-
elif ins.opcode == opcodes.OPCODE_ALU and ins.sub_opcode == opcodes.SUB_OPCODE_ALU_IMM:
21-
print('OPCODE_ALU / SUB_OPCODE_ALU_IMM')
22-
opcodes._alu_imm.all = i
23-
ins = opcodes._alu_imm
24-
elif ins.opcode == opcodes.OPCODE_ALU and ins.sub_opcode == opcodes.SUB_OPCODE_ALU_REG:
25-
print('OPCODE_ALU / SUB_OPCODE_ALU_REG')
26-
opcodes._alu_reg.all = i
27-
ins = opcodes._alu_reg
28-
elif ins.opcode == opcodes.OPCODE_BRANCH and ins.sub_opcode == opcodes.SUB_OPCODE_BX:
29-
print('JUMP')
30-
opcodes._bx.all = i
31-
ins = opcodes._bx
32-
elif ins.opcode == opcodes.OPCODE_BRANCH and ins.sub_opcode == opcodes.SUB_OPCODE_BR:
33-
print('JUMPR')
34-
opcodes._br.all = i
35-
ins = opcodes._br
36-
elif ins.opcode == opcodes.OPCODE_BRANCH and ins.sub_opcode == opcodes.SUB_OPCODE_BS:
37-
print('JUMPS')
38-
opcodes._bs.all = i
39-
ins = opcodes._bs
40-
elif ins.opcode == opcodes.OPCODE_DELAY:
41-
print('OPCODE_DELAY')
42-
opcodes._delay.all = i
43-
ins = opcodes._delay
44-
elif ins.opcode == opcodes.OPCODE_END and ins.sub_opcode == opcodes.SUB_OPCODE_END:
45-
print('OPCODE_END')
46-
opcodes._end.all = i
47-
ins = opcodes._end
48-
elif ins.opcode == opcodes.OPCODE_END and ins.sub_opcode == opcodes.SUB_OPCODE_SLEEP:
49-
print('OPCODE_SLEEP')
50-
opcodes._sleep.all = i
51-
ins = opcodes._sleep
52-
elif ins.opcode == opcodes.OPCODE_HALT:
53-
print('OPCODE_HALT')
54-
opcodes._halt.all = i
55-
ins = opcodes._halt
56-
elif ins.opcode == opcodes.OPCODE_I2C:
57-
print('OPCODE_I2C')
58-
opcodes._i2c.all = i
59-
ins = opcodes._i2c
60-
elif ins.opcode == opcodes.OPCODE_LD:
61-
print('OPCODE_LD')
62-
opcodes._ld.all = i
63-
ins = opcodes._ld
64-
elif ins.opcode == opcodes.OPCODE_RD_REG:
65-
print('OPCODE_RD_REG')
66-
opcodes._rd_reg.all = i
67-
ins = opcodes._rd_reg
68-
elif ins.opcode == opcodes.OPCODE_ST:
69-
print('OPCODE_ST')
70-
opcodes._st.all = i
71-
ins = opcodes._st
72-
elif ins.opcode == opcodes.OPCODE_TSENS:
73-
print('OPCODE_TSENS')
74-
opcodes._tsens.all = i
75-
ins = opcodes._tsens
76-
elif ins.opcode == opcodes.OPCODE_WR_REG:
77-
print('OPCODE_WR_REG')
78-
opcodes._wr_reg.all = i
79-
ins = opcodes._wr_reg
96+
params = lookup.get(ins.opcode, None)
97+
98+
if not params:
99+
print('Unknown instruction')
100+
return
101+
102+
if len(params) == 3:
103+
name, ins, third = params
104+
ins.all = i
105+
106+
if callable(third):
107+
params = (third(ins), ins)
108+
else:
109+
params = third.get(ins.sub_opcode, ())
110+
111+
if len(params) == 3:
112+
name, ins, pretty = params
113+
ins.all = i
114+
name = pretty(ins)
115+
else:
116+
name, ins = params
117+
ins.all = i
118+
119+
print(name)
80120

81121
possible_fields = (
82122
'addr', 'cmp', 'cycle_sel', 'cycles', 'data', 'delay', 'dreg',
@@ -94,12 +134,10 @@ def decode_instruction(i):
94134
extra = ''
95135
if field == 'sel':
96136
if ins.sub_opcode == opcodes.SUB_OPCODE_ALU_CNT:
97-
alu_ops = ('INC', 'DEC', 'RST')
137+
extra = ' (%s)' % alu_cnt_ops[val]
98138
else:
99-
alu_ops = ('ADD', 'SUB', 'AND', 'OR', 'MOV', 'LSH', 'RSH')
100-
extra = ' (%s)' % alu_ops[val]
139+
extra = ' (%s)' % alu_ops[val]
101140
elif field == 'cmp':
102-
cmp_ops = ('LT', 'GE', 'LE', 'EQ', 'GT')
103141
extra = ' (%s)' % cmp_ops[val]
104142
print(" {:10} = {:3}{}".format(field, val, extra))
105143

0 commit comments

Comments
 (0)
0