From c264bd670702021c80f1b41684149323c63def19 Mon Sep 17 00:00:00 2001 From: BigEd Date: Sat, 20 Aug 2011 21:50:26 +0100 Subject: [PATCH] finish basic support for 65Org16, all tests passing --- src/py65/assembler.py | 44 ++++++++++++++++++++++++++----- src/py65/devices/mpu6502.py | 4 ++- src/py65/devices/mpu65Org16.py | 4 +-- src/py65/disassembler.py | 37 +++++++++++++++----------- src/py65/monitor.py | 47 ++++++++++++++++++++-------------- 5 files changed, 92 insertions(+), 44 deletions(-) diff --git a/src/py65/assembler.py b/src/py65/assembler.py index b7e2f53..351f10d 100644 --- a/src/py65/assembler.py +++ b/src/py65/assembler.py @@ -7,7 +7,7 @@ class Assembler: r'\(?\s*)([^,\s\)]+)(\s*[,xXyY\s]*\)?' r'[,xXyY\s]*)$') - Addressing = [ + Addressing8 = [ ['zpi', re.compile(r'^\(\$00([0-9A-F]{2})\)$')], # "($0012)" ['zpx', re.compile(r'^\$00([0-9A-F]{2}),X$')], # "$0012,X" ['zpy', re.compile(r'^\$00([0-9A-F]{2}),Y$')], # "$0012,Y" @@ -24,7 +24,25 @@ class Assembler: ['acc', re.compile(r'^A$')], # "A" ['imm', re.compile(r'^#\$([0-9A-F]{2})$')] # "#$12" ] - + Addressing16 = [ + ['zpi', re.compile(r'^\(\$0000([0-9A-F]{4})\)$')], # "($00001234)" + ['zpx', re.compile(r'^\$0000([0-9A-F]{4}),X$')], # "$00001234,X" + ['zpy', re.compile(r'^\$0000([0-9A-F]{4}),Y$')], # "$00001234,Y" + ['zpg', re.compile(r'^\$0000([0-9A-F]{4})$')], # "$00001234" + ['inx', re.compile(r'^\(\$0000([0-9A-F]{4}),X\)$')], # "($00001234,X)" + ['iny', re.compile(r'^\(\$0000([0-9A-F]{4})\),Y$')], # "($00001234),Y" + ['ind', re.compile(r'^\(\$([0-9A-F]{4})([0-9A-F]{4})\)$')], # "($12345678)" + ['abx', re.compile(r'^\$([0-9A-F]{4})([0-9A-F]{4}),X$')], # "$12345678,X" + ['aby', re.compile(r'^\$([0-9A-F]{4})([0-9A-F]{4}),Y$')], # "$12345678,Y" + ['abs', re.compile(r'^\$([0-9A-F]{4})([0-9A-F]{4})$')], # "$12345678" + ['rel', re.compile(r'^\$([0-9A-F]{4})([0-9A-F]{4})$')], # "$12345678" + ['imp', re.compile(r'^$')], # "" + ['acc', re.compile(r'^$')], # "" + ['acc', re.compile(r'^A$')], # "A" + ['imm', re.compile(r'^#\$([0-9A-F]{4})$')] # "#$1234" + ] + Addressing = Addressing8 + def __init__(self, mpu, address_parser=None): """ If a configured AddressParser is passed, symbolic addresses may be used in the assembly statements. @@ -35,6 +53,18 @@ class Assembler: self._mpu = mpu self._address_parser = address_parser + self.addrWidth = mpu.addrWidth + self.byteWidth = mpu.byteWidth + self.addrFmt = mpu.addrFmt + self.byteFmt = mpu.byteFmt + self.addrMask = mpu.addrMask + self.byteMask = mpu.byteMask + + if self.byteWidth == 8: + self.Addressing = self.Addressing8 + else: + self.Addressing = self.Addressing16 + def assemble(self, statement, pc=0000): """ Assemble the given assembly language statement. If the statement uses relative addressing, the program counter (pc) must also be given. @@ -58,8 +88,8 @@ class Assembler: absolute = int(''.join(operands), 16) relative = (absolute - pc) - 2 if (relative < 1): - relative = (relative ^ 0xFF) + 1 - operands = [ ('%02x' % relative) ] + relative = (relative ^ self.byteMask) + 1 + operands = [ (self.byteFmt % relative) ] elif len(operands) == 2: # swap bytes @@ -87,9 +117,9 @@ class Assembler: # target is an immediate number if target.startswith('#'): number = self._address_parser.number(target[1:]) - if (number < 0x00) or (number > 0xFF): + if (number < 0x00) or (number > self.byteMask): raise OverflowError - statement = '%s#$%02x' % (before, number) + statement = before + '#$' + self.byteFmt % number # target is the accumulator elif target in ('a', 'A'): @@ -98,7 +128,7 @@ class Assembler: # target is an address or label else: address = self._address_parser.number(target) - statement = '%s$%04x%s' % (before, address, after) + statement = before + '$' + self.addrFmt % address + after # strip unnecessary whitespace opcode = statement[:3].upper() diff --git a/src/py65/devices/mpu6502.py b/src/py65/devices/mpu6502.py index 7b91504..2de21d9 100644 --- a/src/py65/devices/mpu6502.py +++ b/src/py65/devices/mpu6502.py @@ -17,7 +17,7 @@ class MPU: ZERO = 2 CARRY = 1 - def __init__(self, memory=None, pc=0x0000, debug=False, byteWidth=8, addrWidth=16): + def __init__(self, memory=None, pc=0x0000, debug=False, byteWidth=8, addrWidth=16, addrFmt="%04x", byteFmt="%02x"): # config self.debug = debug self.name = '6502' @@ -26,6 +26,8 @@ class MPU: self.addrWidth = addrWidth self.addrMask = ((1< ") @@ -221,7 +227,7 @@ class Monitor(cmd.Cmd): assembling = True while assembling: - prompt = "\r$%04x " % (start) + prompt = "\r$" + ( self.addrFmt % start ) + " " + (" " * (1 + self.byteWidth/4) * 3) line = console.line_input(prompt, stdin=self.stdin, stdout=self.stdout) @@ -232,7 +238,7 @@ class Monitor(cmd.Cmd): # assemble into memory bytes = self._assembler.assemble(line) if bytes is None: - self.stdout.write("\r$%04x ???\n" % start) + self.stdout.write("\r$" + (self.addrFmt % start) + " ???\n") continue end = start + len(bytes) self._mpu.memory[start:end] = bytes @@ -259,9 +265,11 @@ class Monitor(cmd.Cmd): def _format_disassembly(self, address, bytes, disasm): mem = '' for byte in self._mpu.memory[address:address+bytes]: - mem += '%02x ' % byte + mem += self.byteFmt % byte + " " - return "$%04x %-10s%s" % (address, mem, disasm) + fieldwidth = 1 + (1 + self.byteWidth/4) * 3 + fieldfmt = "%%-%ds" % fieldwidth + return "$" + self.addrFmt % address + " " + fieldfmt % mem + disasm def help_disassemble(self): self._output("disassemble ") @@ -273,7 +281,7 @@ class Monitor(cmd.Cmd): def do_step(self, args): self._mpu.step() - self.do_disassemble('%04x' % self._mpu.pc) + self.do_disassemble(self.addrFmt % self._mpu.pc) def help_return(self): self._output("return") @@ -339,7 +347,7 @@ class Monitor(cmd.Cmd): return self._output("+%u" % num) - self._output("$%02x" % num) + self._output("$" + self.byteFmt % num) self._output("%04o" % num) self._output(itoa(num, 2).zfill(8)) @@ -361,9 +369,9 @@ class Monitor(cmd.Cmd): self._output("Invalid register: %s" % register) else: try: - intval = self._address_parser.number(value) & 0xFFFF + intval = self._address_parser.number(value) & self.addrMask if len(register) == 1: - intval &= 0xFF + intval &= self.byteMask setattr(self._mpu, register, intval) except KeyError, why: self._output(why[0]) @@ -466,19 +474,20 @@ class Monitor(cmd.Cmd): if start == end: end = start + length - 1 - if (end > 0xFFFF): - end = 0xFFFF + if (end > self.addrMask): + end = self.addrMask while address <= end: - address &= 0xFFFF - self._mpu.memory[address] = (filler[index] & 0xFF) + address &= self.addrMask + self._mpu.memory[address] = (filler[index] & self.byteMask) index += 1 if index == length: index = 0 address += 1 fmt = (end - start + 1, start, end) - self._output("Wrote +%d bytes from $%04x to $%04x" % fmt) + starttoend = "$" + self.addrFmt + " to $" + self.addrFmt + self._output(("Wrote +%d bytes from " + starttoend) % fmt) def help_mem(self): self._output("mem ") @@ -487,15 +496,15 @@ class Monitor(cmd.Cmd): def do_mem(self, args): start, end = self._address_parser.range(args) - line = "%04x:" % start + line = self.addrFmt % start + ":" for address in range(start, end+1): byte = self._mpu.memory[address] - more = " %02x" % byte + more = " " + self.byteFmt % byte exceeded = len(line) + len(more) > self._width if exceeded: self._output(line) - line = "%04x:" % address + line = self.addrFmt % address + ":" line += more self._output(line) @@ -525,7 +534,7 @@ class Monitor(cmd.Cmd): byaddress = zip(values, keys) byaddress.sort() for address, label in byaddress: - self._output("%04x: %s" % (address, label)) + self._output(self.addrFmt % address + ": " + label) def help_delete_label(self): self._output("delete_label