|
| 1 | +import esp32_ulp.opcodes as opcodes |
| 2 | +import ubinascii |
| 3 | +import sys |
| 4 | + |
| 5 | + |
| 6 | +def decode_instruction(i): |
| 7 | + ins = opcodes._end |
| 8 | + ins.all = i # abuse a struct to get opcode and sub_opcode |
| 9 | + |
| 10 | + print(ubinascii.hexlify(i.to_bytes(4, 'little'))) |
| 11 | + |
| 12 | + if ins.opcode == opcodes.OPCODE_ADC: |
| 13 | + print('OPCODE_ADC') |
| 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 |
| 80 | + |
| 81 | + possible_fields = ( |
| 82 | + 'addr', 'cmp', 'cycle_sel', 'cycles', 'data', 'delay', 'dreg', |
| 83 | + 'high', 'i2c_sel', 'imm', 'low', 'mux', 'offset', 'opcode', |
| 84 | + 'periph_sel', 'reg', 'rw', 'sar_sel', 'sel', 'sign', 'sreg', |
| 85 | + 'sub_addr', 'sub_opcode', 'treg', 'type', 'unused', 'unused1', |
| 86 | + 'unused2', 'wakeup' |
| 87 | + ) |
| 88 | + for field in possible_fields: |
| 89 | + try: |
| 90 | + # eval is ugly but constrained to possible_fields and variable ins |
| 91 | + val = eval('i.%s' % field, {}, {'i': ins}) |
| 92 | + except KeyError: |
| 93 | + continue |
| 94 | + extra = '' |
| 95 | + if field == 'sel': |
| 96 | + if ins.sub_opcode == opcodes.SUB_OPCODE_ALU_CNT: |
| 97 | + alu_ops = ('INC', 'DEC', 'RST') |
| 98 | + else: |
| 99 | + alu_ops = ('ADD', 'SUB', 'AND', 'OR', 'MOV', 'LSH', 'RSH') |
| 100 | + extra = ' (%s)' % alu_ops[val] |
| 101 | + elif field == 'cmp': |
| 102 | + cmp_ops = ('LT', 'GE', 'LE', 'EQ', 'GT') |
| 103 | + extra = ' (%s)' % cmp_ops[val] |
| 104 | + print(" {:10} = {:3}{}".format(field, val, extra)) |
| 105 | + |
| 106 | + |
| 107 | +def disassemble_manually(byte_sequence_string): |
| 108 | + sequence = byte_sequence_string.strip().replace(' ','') |
| 109 | + chars_per_instruction = 8 |
| 110 | + list = [ |
| 111 | + sequence[i:i+chars_per_instruction] |
| 112 | + for i in range(0, len(sequence), chars_per_instruction) |
| 113 | + ] |
| 114 | + |
| 115 | + for instruction in list: |
| 116 | + byte_sequence = ubinascii.unhexlify(instruction.replace(' ','')) |
| 117 | + i = int.from_bytes(byte_sequence, 'little') |
| 118 | + decode_instruction(i) |
| 119 | + |
| 120 | + |
| 121 | +def handle_cmdline(params): |
| 122 | + byte_sequence = "".join(params) |
| 123 | + disassemble_manually(byte_sequence) |
| 124 | + |
| 125 | + |
| 126 | +if sys.argv: # if run from cmdline |
| 127 | + handle_cmdline(sys.argv[1:]) |
0 commit comments