From dd08001c42b886fcd669cc32a26b98091d3677ab Mon Sep 17 00:00:00 2001 From: Wei-ju Wu Date: Fri, 7 Nov 2014 16:06:19 -0800 Subject: [PATCH] started disassembler --- hunktools/disassemble.py | 109 +++++++++++++++++++++++++++++++++++++++ hunktools/hunk.py | 16 ++++-- 2 files changed, 122 insertions(+), 3 deletions(-) create mode 100644 hunktools/disassemble.py diff --git a/hunktools/disassemble.py b/hunktools/disassemble.py new file mode 100644 index 0000000..74237e2 --- /dev/null +++ b/hunktools/disassemble.py @@ -0,0 +1,109 @@ +import struct + + +ADDR_MODES = { + '000': 'Dn', '001': 'An', '010': '(An)', '011': '(An)+', '100': '-(An)', + '101': '(d16,An)', '110': '(d8,An,Xn)', '111': 'EXT' # -> ADDR_MODES_EXT +} + +ADDR_MODES_EXT = { + '000': '(xxx).W', '001': '(xxx).L', '100': '#', + '010': '(d16,PC)', '011': '(d8,PC,Xn)' +} + +OPCODE_CATEGORIES = { + '0000': 'bitops_movep_imm', '0001': 'move.b', '0010': 'move.l', '0011': 'move.w', + '0100': 'misc', '1101': 'add_addx' +} + +ADD_OPMODES = { + '000': ('b', 'ea+dn->dn'), '001': ('w', 'ea+dn->dn'),'010': ('l', 'ea+dn->dn'), + '100': ('b', 'dn+ea->ea'), '101': ('w', 'dn+ea->ea'),'110': ('l', 'dn+ea->ea') +} + + +def is_move(category): + return category in {'move.b', 'move.w', 'move.l'} + + +def operand(size, mode_bits, reg_bits, data, offset): + result = "" + added = 0 + mode = ADDR_MODES[mode_bits] + size = size.upper() + + if mode == 'EXT': + mode = ADDR_MODES_EXT[reg_bits] + regnum = int(reg_bits, 2) + if mode == '#': + data_offset = offset + 2 + if size == 'L': + imm_value = struct.unpack('>i', data[data_offset:data_offset+4])[0] + added += 4 + elif size == 'W': + data[data_offset:data_offset+2] + imm_value = struct.unpack('>h', data[data_offset:data_offset+2])[0] + added += 2 + else: + raise Exception('unsupported size: ', size) + result = "#%d" % imm_value + else: + regnum = int(reg_bits, 2) + result = mode.replace('n', str(regnum)) + return result, added + + +def disassemble_move(bits, data, offset): + category = OPCODE_CATEGORIES[bits[0:4]] + total_added = 0 + # dst: reg|mode + dst_op, added = operand(category[-1], bits[7:10], bits[4:7], data, offset) + total_added += added + + # src: mode|reg + src_op,added = operand(category[-1], bits[10:13], bits[13:16], data, offset) + total_added += added + + return ((category, src_op, dst_op), total_added) + + +def disassemble_add(bits, data, offset): + total_added = 0 + reg = "D%d" % int(bits[4:7], 2) + size, operation = ADD_OPMODES[bits[7:10]] + ea, added = operand(size, bits[10:13], bits[13:16], data, offset) + total_added += added + + if operation == 'ea+dn->dn': + src = ea + dst = reg + elif operation == 'dn+ea->ea': + src = reg + dst = ea + else: + raise Exception('Unknown operation for add') + + return (('add.%s' % size, src, dst), total_added) + + +def disassemble(data, offset): + bits = "{0:016b}".format(struct.unpack(">H", data[offset:offset+2])[0]) + # first step categorize by looking at bits 15-12 + opcode = bits[0:4] + category = OPCODE_CATEGORIES[opcode] + if is_move(category): + op, added = disassemble_move(bits, data, offset) + elif category == 'add_addx': + if bits[7] == 1 and bits[10:12] == '11': # addx + raise Exception('addx not supported yet') + else: + op, added = disassemble_add(bits, data, offset) + else: + print("category: ", category) + raise Exception('TODO') + return (op, 2 + added) + + +def print_instruction(address, op): + opcode, src, dst = op + print("$%08x:\t%8s %8s, %8s" % (address, opcode, src, dst)) diff --git a/hunktools/hunk.py b/hunktools/hunk.py index ad73b5e..8e8036e 100755 --- a/hunktools/hunk.py +++ b/hunktools/hunk.py @@ -5,6 +5,8 @@ an Amiga Hunk file. import argparse import struct +from disassemble import disassemble, print_instruction + HUNK_BLOCK_UNIT = b'\x00\x00\x03\xe7' HUNK_BLOCK_NAME = b'\x00\x00\x03\xe8' HUNK_BLOCK_CODE = b'\x00\x00\x03\xe9' @@ -153,11 +155,19 @@ def parse_hunkfile(hunkfile): print("%d blocks read: " % len(blocks)) for i, block in enumerate(blocks): if block[0] == 'NAME': - print("%d: '%s' -> '%s'" % (i, block[0], block[1])) + print("Block %d: '%s' -> '%s'" % (i, block[0], block[1])) elif block[0] == 'BSS': - print("%d: '%s' -> %d" % (i, block[0], block[1])) - else: + print("Block %d: '%s' -> %d" % (i, block[0], block[1])) + elif block[0] == 'CODE': print("%d: '%s'" % (i, block[0])) + code = block[1] + offset = 0 + while offset < len(code): + op, size = disassemble(code, offset) + print_instruction(offset, op) + offset += size + else: + print("Block %d: '%s'" % (i, block[0])) if __name__ == '__main__':