mirror of
https://github.com/weiju/amiga-stuff
synced 2025-11-20 08:48:41 +00:00
started disassembler
This commit is contained in:
109
hunktools/disassemble.py
Normal file
109
hunktools/disassemble.py
Normal file
@ -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': '#<data>',
|
||||
'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>':
|
||||
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))
|
||||
@ -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__':
|
||||
|
||||
Reference in New Issue
Block a user