mirror of
https://github.com/weiju/amiga-stuff
synced 2025-12-08 14:58:33 +00:00
added more instructions to disassembler
This commit is contained in:
+108
-27
@@ -13,19 +13,43 @@ ADDR_MODES_EXT = {
|
||||
|
||||
OPCODE_CATEGORIES = {
|
||||
'0000': 'bitops_movep_imm', '0001': 'move.b', '0010': 'move.l', '0011': 'move.w',
|
||||
'0100': 'misc', '1101': 'add_addx'
|
||||
'0100': 'misc', '1001': 'sub_subx',
|
||||
'0110': 'bcc_bsr_bra', '0111': 'moveq',
|
||||
'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')
|
||||
ADD_SUB_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')
|
||||
}
|
||||
|
||||
SIZES = ['b', 'w', 'l']
|
||||
|
||||
CONDITION_CODES = [
|
||||
't', 'f', 'hi', 'ls',
|
||||
'cc', 'cs', 'ne', 'eq',
|
||||
'vc', 'vs', 'pl', 'mi',
|
||||
'ge', 'lt', 'gt', 'le'
|
||||
]
|
||||
|
||||
|
||||
def is_move(category):
|
||||
return category in {'move.b', 'move.w', 'move.l'}
|
||||
|
||||
|
||||
def next_word(size, data, data_offset):
|
||||
if size == 'L':
|
||||
value = struct.unpack('>i', data[data_offset:data_offset+4])[0]
|
||||
added = 4
|
||||
elif size == 'W':
|
||||
data[data_offset:data_offset+2]
|
||||
value = struct.unpack('>h', data[data_offset:data_offset+2])[0]
|
||||
added = 2
|
||||
else:
|
||||
raise Exception('unsupported size: ', size)
|
||||
return (value, added)
|
||||
|
||||
|
||||
def operand(size, mode_bits, reg_bits, data, offset):
|
||||
result = ""
|
||||
added = 0
|
||||
@@ -36,17 +60,20 @@ def operand(size, mode_bits, reg_bits, data, offset):
|
||||
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)
|
||||
imm_value, added = next_word(size, data, offset + 2)
|
||||
result = "#%d" % imm_value
|
||||
elif mode in {'(xxx).L', '(xxx).W'}: # absolute
|
||||
addr, added = next_word(mode[-1], data, offset + 2)
|
||||
result = "%d.%s" % (addr, mode[-1])
|
||||
elif mode == '(d16,PC)':
|
||||
disp16, added = next_word('W', data, offset + 2)
|
||||
result = "%d(PC)" % disp16
|
||||
else:
|
||||
raise Exception("unsupported ext mode: '%s'" % mode)
|
||||
elif mode == '(d16,An)':
|
||||
regnum = int(reg_bits, 2)
|
||||
disp16, added = next_word('W', data, offset + 2)
|
||||
result = "%d(A%d)" % (disp16, regnum)
|
||||
else:
|
||||
regnum = int(reg_bits, 2)
|
||||
result = mode.replace('n', str(regnum))
|
||||
@@ -67,43 +94,97 @@ def disassemble_move(bits, data, offset):
|
||||
return ((category, src_op, dst_op), total_added)
|
||||
|
||||
|
||||
def disassemble_add(bits, data, offset):
|
||||
def disassemble_add_sub(name, bits, data, offset):
|
||||
total_added = 0
|
||||
reg = "D%d" % int(bits[4:7], 2)
|
||||
size, operation = ADD_OPMODES[bits[7:10]]
|
||||
size, operation = ADD_SUB_OPMODES[bits[7:10]]
|
||||
ea, added = operand(size, bits[10:13], bits[13:16], data, offset)
|
||||
total_added += added
|
||||
|
||||
if operation == 'ea+dn->dn':
|
||||
if operation == 'ea,dn->dn':
|
||||
src = ea
|
||||
dst = reg
|
||||
elif operation == 'dn+ea->ea':
|
||||
elif operation == 'dn,ea->ea':
|
||||
src = reg
|
||||
dst = ea
|
||||
else:
|
||||
raise Exception('Unknown operation for add')
|
||||
raise Exception('Unknown operation for %s' % name)
|
||||
|
||||
return (('add.%s' % size, src, dst), total_added)
|
||||
return (('%s.%s' % (name, size), src, dst), total_added)
|
||||
|
||||
|
||||
def disassemble_misc(bits, data, offset):
|
||||
if bits == '0100111001110101': # rts
|
||||
return (('rts', ), 0)
|
||||
elif bits[7:10] == '111': # lea
|
||||
regnum = int(bits[4:7], 2)
|
||||
ea, added = operand('l', bits[10:13], bits[13:16], data, offset)
|
||||
return (('lea', ea, 'A%d' % regnum), added)
|
||||
elif bits.startswith('0100111010'): # jsr
|
||||
ea, added = operand('l', bits[10:13], bits[13:16], data, offset)
|
||||
return (('jsr', ea), added)
|
||||
elif bits.startswith('0100111011'): # jmp
|
||||
ea, added = operand('l', bits[10:13], bits[13:16], data, offset)
|
||||
return (('jmp', ea), added)
|
||||
elif bits.startswith('01001010'): # tst.x
|
||||
size = SIZES[int(bits[8:10], 2)]
|
||||
ea, added = operand('l', bits[10:13], bits[13:16], data, offset)
|
||||
return (('test.%s' % size, ea), added)
|
||||
else:
|
||||
print("unrecognized misc: %s" % bits)
|
||||
raise Exception('TODO Misc')
|
||||
|
||||
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]
|
||||
added = 0
|
||||
|
||||
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')
|
||||
elif category in {'add_addx', 'sub_subx'}:
|
||||
if bits[7] == 1 and bits[10:12] == '11': # extended
|
||||
raise Exception('addx/subx not supported yet')
|
||||
else:
|
||||
op, added = disassemble_add(bits, data, offset)
|
||||
op, added = disassemble_add_sub(category[0:3], bits, data, offset)
|
||||
elif category == 'misc':
|
||||
op, added = disassemble_misc(bits, data, offset)
|
||||
elif category == 'moveq':
|
||||
regnum = int(bits[4:7], 2)
|
||||
value = int(bits[8:16], 2)
|
||||
op = ('moveq', value, 'D%d' % regnum)
|
||||
elif category == 'bcc_bsr_bra':
|
||||
if bits[0:16] == '01100000': # bra
|
||||
raise Exception('BRA TODO')
|
||||
elif bits[0:16] == '01100001': # bsr
|
||||
raise Exception('BSR TODO')
|
||||
else:
|
||||
cond = CONDITION_CODES[int(bits[4:8], 2)]
|
||||
disp8 = int(bits[8:16], 2)
|
||||
if disp8 == 0:
|
||||
# 16 bit displacement TODO
|
||||
raise Exception('16 bit branch displacement TODO')
|
||||
elif disp8 == 255:
|
||||
# 16 bit displacement TODO
|
||||
raise Exception('16 bit branch displacement TODO')
|
||||
if disp8 >= 128:
|
||||
raise Exception('wrong value for signed displacement: %d', disp8)
|
||||
return (('b%s' % cond, disp8), 2)
|
||||
else:
|
||||
print("category: ", category)
|
||||
print("\nUnknown instruction\nCategory: ", category, " Bits: ", bits)
|
||||
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))
|
||||
if len(op) == 3:
|
||||
opcode, src, dst = op
|
||||
print("$%08x:\t%8s %s,%s" % (address, opcode, src, dst))
|
||||
elif len(op) == 2:
|
||||
opcode, ea = op
|
||||
print("$%08x:\t%8s %s" % (address, opcode, ea))
|
||||
elif len(op) == 1:
|
||||
print("$%08x:\t%8s" % (address, op[0]))
|
||||
else:
|
||||
raise Exception("can't print instruction with %d components" % len(op))
|
||||
|
||||
+3
-1
@@ -159,13 +159,15 @@ def parse_hunkfile(hunkfile):
|
||||
elif block[0] == 'BSS':
|
||||
print("Block %d: '%s' -> %d" % (i, block[0], block[1]))
|
||||
elif block[0] == 'CODE':
|
||||
print("%d: '%s'" % (i, block[0]))
|
||||
print("%d: '%s', size = %d" % (i, block[0], len(block[1])))
|
||||
print("----------------------------\n")
|
||||
code = block[1]
|
||||
offset = 0
|
||||
while offset < len(code):
|
||||
op, size = disassemble(code, offset)
|
||||
print_instruction(offset, op)
|
||||
offset += size
|
||||
print("\n---------------------------\n")
|
||||
else:
|
||||
print("Block %d: '%s'" % (i, block[0]))
|
||||
|
||||
|
||||
Reference in New Issue
Block a user