1
0
mirror of https://github.com/mnaberez/py65.git synced 2025-08-08 13:25:01 +00:00

Remove duplication from addressing mode patterns

This commit is contained in:
Mike Naberezny
2014-12-14 17:17:35 -08:00
parent a941071c92
commit 628593188e
2 changed files with 30 additions and 76 deletions

View File

@@ -7,96 +7,56 @@ class Assembler:
r'\(?\s*)([^,\s\)]+)(\s*[,xXyY\s]*\)?' r'\(?\s*)([^,\s\)]+)(\s*[,xXyY\s]*\)?'
r'[,xXyY\s]*)$') r'[,xXyY\s]*)$')
Addressing8 = [ Addressing = [
['zpi', # "($0012)" ['zpi', # "($0012)"
re.compile(r'^\(\$00([0-9A-F]{2})\)$')], r'^\(\$0{BYTE}([0-9A-F]{BYTE})\)$'],
['zpx', # "$0012,X" ['zpx', # "$0012,X"
re.compile(r'^\$00([0-9A-F]{2}),X$')], r'^\$0{BYTE}([0-9A-F]{BYTE}),X$'],
['zpy', # "$0012,Y" ['zpy', # "$0012,Y"
re.compile(r'^\$00([0-9A-F]{2}),Y$')], r'^\$0{BYTE}([0-9A-F]{BYTE}),Y$'],
['zpg', # "$0012" ['zpg', # "$0012"
re.compile(r'^\$00([0-9A-F]{2})$')], r'^\$0{BYTE}([0-9A-F]{BYTE})$'],
['inx', # "($0012,X) ['inx', # "($0012,X)
re.compile(r'^\(\$00([0-9A-F]{2}),X\)$')], r'^\(\$0{BYTE}([0-9A-F]{BYTE}),X\)$'],
['iax', # "($1234,X) ['iax', # "($1234,X)
re.compile(r'^\(\$([0-9A-F]{2})([0-9A-F]{2}),X\)$')], r'^\(\$([0-9A-F]{BYTE})([0-9A-F]{BYTE}),X\)$'],
['iny', # "($0012),Y" ['iny', # "($0012),Y"
re.compile(r'^\(\$00([0-9A-F]{2})\),Y$')], r'^\(\$0{BYTE}([0-9A-F]{BYTE})\),Y$'],
['ind', # "($1234)" ['ind', # "($1234)"
re.compile(r'^\(\$([0-9A-F]{2})([0-9A-F]{2})\)$')], r'^\(\$([0-9A-F]{BYTE})([0-9A-F]{BYTE})\)$'],
['abx', # "$1234,X" ['abx', # "$1234,X"
re.compile(r'^\$([0-9A-F]{2})([0-9A-F]{2}),X$')], r'^\$([0-9A-F]{BYTE})([0-9A-F]{BYTE}),X$'],
['aby', # "$1234,Y" ['aby', # "$1234,Y"
re.compile(r'^\$([0-9A-F]{2})([0-9A-F]{2}),Y$')], r'^\$([0-9A-F]{BYTE})([0-9A-F]{BYTE}),Y$'],
['abs', # "$1234" ['abs', # "$1234"
re.compile(r'^\$([0-9A-F]{2})([0-9A-F]{2})$')], r'^\$([0-9A-F]{BYTE})([0-9A-F]{BYTE})$'],
['rel', # "$1234" ['rel', # "$1234"
re.compile(r'^\$([0-9A-F]{2})([0-9A-F]{2})$')], r'^\$([0-9A-F]{BYTE})([0-9A-F]{BYTE})$'],
['imp', # "" ['imp', # ""
re.compile(r'^$')], r'^$'],
['acc', # "" ['acc', # ""
re.compile(r'^$')], r'^$'],
['acc', # "A" ['acc', # "A"
re.compile(r'^A$')], r'^A$'],
['imm', # "#$12" ['imm', # "#$12"
re.compile(r'^#\$([0-9A-F]{2})$')] r'^#\$([0-9A-F]{BYTE})$']
] ]
Addressing16 = [
['zpi', # "($00001234)"
re.compile(r'^\(\$0000([0-9A-F]{4})\)$')],
['zpx', # "$00001234,X"
re.compile(r'^\$0000([0-9A-F]{4}),X$')],
['zpy', # "$00001234,Y"
re.compile(r'^\$0000([0-9A-F]{4}),Y$')],
['zpg', # "$00001234"
re.compile(r'^\$0000([0-9A-F]{4})$')],
['inx', # "($00001234,X)"
re.compile(r'^\(\$0000([0-9A-F]{4}),X\)$')],
['iny', # "($00001234),Y"
re.compile(r'^\(\$0000([0-9A-F]{4})\),Y$')],
['ind', # "($12345678)"
re.compile(r'^\(\$([0-9A-F]{4})([0-9A-F]{4})\)$')],
['abx', # "$12345678,X"
re.compile(r'^\$([0-9A-F]{4})([0-9A-F]{4}),X$')],
['aby', # "$12345678,Y"
re.compile(r'^\$([0-9A-F]{4})([0-9A-F]{4}),Y$')],
['abs', # "$12345678"
re.compile(r'^\$([0-9A-F]{4})([0-9A-F]{4})$')],
['rel', # "$12345678"
re.compile(r'^\$([0-9A-F]{4})([0-9A-F]{4})$')],
['imp', # ""
re.compile(r'^$')],
['acc', # ""
re.compile(r'^$')],
['acc', # "A"
re.compile(r'^A$')],
['imm', # "#$1234"
re.compile(r'^#\$([0-9A-F]{4})$')]
]
Addressing = Addressing8
def __init__(self, mpu, address_parser=None): def __init__(self, mpu, address_parser=None):
""" If a configured AddressParser is passed, symbolic addresses """ If a configured AddressParser is passed, symbolic addresses
may be used in the assembly statements. may be used in the assembly statements.
""" """
self._mpu = mpu
if address_parser is None: if address_parser is None:
address_parser = AddressParser() address_parser = AddressParser()
self._mpu = mpu
self._address_parser = address_parser self._address_parser = address_parser
self.addrWidth = mpu.ADDR_WIDTH self._addressing = []
self.byteWidth = mpu.BYTE_WIDTH numchars = mpu.BYTE_WIDTH / 4 # 1 byte = 2 chars in hex
self.addrFmt = mpu.ADDR_FORMAT for mode, pattern in self.Addressing:
self.byteFmt = mpu.BYTE_FORMAT pattern = pattern.replace('BYTE', '%d' % numchars)
self.addrMask = mpu.addrMask self._addressing.append([mode, re.compile(pattern)])
self.byteMask = mpu.byteMask
if self.byteWidth == 8:
self.Addressing = self.Addressing8
else:
self.Addressing = self.Addressing16
def assemble(self, statement, pc=0000): def assemble(self, statement, pc=0000):
""" Assemble the given assembly language statement. If the statement """ Assemble the given assembly language statement. If the statement
@@ -105,7 +65,7 @@ class Assembler:
""" """
opcode, operand = self.normalize_and_split(statement) opcode, operand = self.normalize_and_split(statement)
for mode, pattern in self.Addressing: for mode, pattern in self._addressing:
match = pattern.match(operand) match = pattern.match(operand)
if match: if match:
@@ -120,8 +80,8 @@ class Assembler:
# relative branch # relative branch
absolute = int(''.join(operands), 16) absolute = int(''.join(operands), 16)
relative = (absolute - pc) - 2 relative = (absolute - pc) - 2
relative = relative & self.byteMask relative = relative & self._mpu.byteMask
operands = [(self.byteFmt % relative)] operands = [(self._mpu.BYTE_FORMAT % relative)]
elif len(operands) == 2: elif len(operands) == 2:
# swap bytes # swap bytes
@@ -155,9 +115,9 @@ class Assembler:
# target is an immediate number # target is an immediate number
if target.startswith('#'): if target.startswith('#'):
number = self._address_parser.number(target[1:]) number = self._address_parser.number(target[1:])
if (number < 0x00) or (number > self.byteMask): if (number < 0x00) or (number > self._mpu.byteMask):
raise OverflowError raise OverflowError
statement = before + '#$' + self.byteFmt % number statement = before + '#$' + self._mpu.BYTE_FORMAT % number
# target is the accumulator # target is the accumulator
elif target in ('a', 'A'): elif target in ('a', 'A'):
@@ -166,7 +126,7 @@ class Assembler:
# target is an address or label # target is an address or label
else: else:
address = self._address_parser.number(target) address = self._address_parser.number(target)
statement = before + '$' + self.addrFmt % address + after statement = before + '$' + self._mpu.ADDR_FORMAT % address + after
# separate opcode and operand # separate opcode and operand
splitted = statement.split(" ", 2) splitted = statement.split(" ", 2)

View File

@@ -20,12 +20,6 @@ class AssemblerTests(unittest.TestCase):
asm = Assembler(mpu) asm = Assembler(mpu)
self.assertFalse(asm._address_parser is None) self.assertFalse(asm._address_parser is None)
def test_ctor_uses_bus_width_from_mpu(self):
asm = Assembler(MPU())
self.assertEqual(16, asm.addrWidth)
asm = Assembler(MPU65Org16())
self.assertEqual(32, asm.addrWidth)
def test_assemble_bad_syntax_raises_syntaxerror(self): def test_assemble_bad_syntax_raises_syntaxerror(self):
self.assertRaises(SyntaxError, self.assertRaises(SyntaxError,
self.assemble, 'foo') self.assemble, 'foo')