mirror of https://github.com/mnaberez/py65.git
135 lines
4.6 KiB
Python
135 lines
4.6 KiB
Python
from py65.utils.addressing import AddressParser
|
|
|
|
|
|
class Disassembler:
|
|
def __init__(self, mpu, address_parser=None):
|
|
if address_parser is None:
|
|
address_parser = AddressParser()
|
|
|
|
self._mpu = mpu
|
|
self._address_parser = address_parser
|
|
|
|
self.addrWidth = mpu.ADDR_WIDTH
|
|
self.byteWidth = mpu.BYTE_WIDTH
|
|
self.addrFmt = mpu.ADDR_FORMAT
|
|
self.byteFmt = mpu.BYTE_FORMAT
|
|
self.addrMask = mpu.addrMask
|
|
self.byteMask = mpu.byteMask
|
|
|
|
def instruction_at(self, pc):
|
|
""" Disassemble the instruction at PC and return a tuple
|
|
containing (instruction byte count, human readable text)
|
|
"""
|
|
|
|
instruction = self._mpu.ByteAt(pc)
|
|
disasm, addressing = self._mpu.disassemble[instruction]
|
|
|
|
if addressing == 'acc':
|
|
disasm += ' A'
|
|
length = 1
|
|
|
|
elif addressing == 'abs':
|
|
address = self._mpu.WordAt(pc + 1)
|
|
address_or_label = self._address_parser.label_for(
|
|
address, '$' + self.addrFmt % address)
|
|
disasm += ' ' + address_or_label
|
|
length = 3
|
|
|
|
elif addressing == 'abx':
|
|
address = self._mpu.WordAt(pc + 1)
|
|
address_or_label = self._address_parser.label_for(
|
|
address, '$' + self.addrFmt % address)
|
|
disasm += ' %s,X' % address_or_label
|
|
length = 3
|
|
|
|
elif addressing == 'aby':
|
|
address = self._mpu.WordAt(pc + 1)
|
|
address_or_label = self._address_parser.label_for(
|
|
address, '$' + self.addrFmt % address)
|
|
disasm += ' %s,Y' % address_or_label
|
|
length = 3
|
|
|
|
elif addressing == 'imm':
|
|
byte = self._mpu.ByteAt(pc + 1)
|
|
disasm += ' #$' + self.byteFmt % byte
|
|
length = 2
|
|
|
|
elif addressing == 'imp':
|
|
length = 1
|
|
|
|
elif addressing == 'ind':
|
|
address = self._mpu.WordAt(pc + 1)
|
|
address_or_label = self._address_parser.label_for(
|
|
address, '$' + self.addrFmt % address)
|
|
disasm += ' (%s)' % address_or_label
|
|
length = 3
|
|
|
|
elif addressing == 'iny':
|
|
zp_address = self._mpu.ByteAt(pc + 1)
|
|
address_or_label = self._address_parser.label_for(
|
|
zp_address, '$' + self.byteFmt % zp_address)
|
|
disasm += ' (%s),Y' % address_or_label
|
|
length = 2
|
|
|
|
elif addressing == 'inx':
|
|
zp_address = self._mpu.ByteAt(pc + 1)
|
|
address_or_label = self._address_parser.label_for(
|
|
zp_address, '$' + self.byteFmt % zp_address)
|
|
disasm += ' (%s,X)' % address_or_label
|
|
length = 2
|
|
|
|
elif addressing == 'iax':
|
|
address = self._mpu.WordAt(pc + 1)
|
|
address_or_label = self._address_parser.label_for(
|
|
address, '$' + self.addrFmt % address)
|
|
disasm += ' (%s,X)' % address_or_label
|
|
length = 3
|
|
|
|
elif addressing == 'rel':
|
|
opv = self._mpu.ByteAt(pc + 1)
|
|
targ = pc + 2
|
|
if opv & (1 << (self.byteWidth - 1)):
|
|
targ -= (opv ^ self.byteMask) + 1
|
|
else:
|
|
targ += opv
|
|
targ &= self.addrMask
|
|
|
|
address_or_label = self._address_parser.label_for(
|
|
targ, '$' + self.addrFmt % targ)
|
|
disasm += ' ' + address_or_label
|
|
length = 2
|
|
|
|
elif addressing == 'zpi':
|
|
zp_address = self._mpu.ByteAt(pc + 1)
|
|
address_or_label = self._address_parser.label_for(
|
|
zp_address, '$' + self.byteFmt % zp_address)
|
|
disasm += ' (%s)' % address_or_label
|
|
length = 2
|
|
|
|
elif addressing == 'zpg':
|
|
zp_address = self._mpu.ByteAt(pc + 1)
|
|
address_or_label = self._address_parser.label_for(
|
|
zp_address, '$' + self.byteFmt % zp_address)
|
|
disasm += ' %s' % address_or_label
|
|
length = 2
|
|
|
|
elif addressing == 'zpx':
|
|
zp_address = self._mpu.ByteAt(pc + 1)
|
|
address_or_label = self._address_parser.label_for(
|
|
zp_address, '$' + self.byteFmt % zp_address)
|
|
disasm += ' %s,X' % address_or_label
|
|
length = 2
|
|
|
|
elif addressing == 'zpy':
|
|
zp_address = self._mpu.ByteAt(pc + 1)
|
|
address_or_label = self._address_parser.label_for(
|
|
zp_address, '$' + self.byteFmt % zp_address)
|
|
disasm += ' %s,Y' % address_or_label
|
|
length = 2
|
|
|
|
else:
|
|
msg = "Addressing mode: %r" % addressing
|
|
raise NotImplementedError(msg)
|
|
|
|
return (length, disasm)
|