mirror of
https://github.com/mnaberez/py65.git
synced 2024-12-28 15:29:40 +00:00
PEP8
This commit is contained in:
parent
e8565a6e81
commit
8f284a8e58
@ -6,6 +6,8 @@
|
||||
- Fixed assembling 65C02 opcodes whose mnemonics have a digit
|
||||
such as "RMB3".
|
||||
|
||||
- Reformatted source code to comply with PEP8.
|
||||
|
||||
0.13 (2012-11-15)
|
||||
|
||||
- Fixed a bug where negative numbers could be entered
|
||||
|
19
docs/conf.py
19
docs/conf.py
@ -3,15 +3,18 @@
|
||||
# test documentation build configuration file, created by
|
||||
# sphinx-quickstart on Sun Nov 30 14:39:06 2008.
|
||||
#
|
||||
# This file is execfile()d with the current directory set to its containing dir.
|
||||
# This file is execfile()d with the current dir set to its containing
|
||||
# directory.
|
||||
#
|
||||
# The contents of this file are pickled, so don't put values in the namespace
|
||||
# that aren't pickleable (module imports are okay, they're removed automatically).
|
||||
# that aren't pickleable (module imports are okay, they're removed
|
||||
# automatically).
|
||||
#
|
||||
# All configuration values have a default; values that are commented out
|
||||
# serve to show the default.
|
||||
|
||||
import sys, os
|
||||
import os
|
||||
import sys
|
||||
|
||||
# If your extensions are in another directory, add it here. If the directory
|
||||
# is relative to the documentation root, use os.path.abspath to make it
|
||||
@ -21,8 +24,8 @@ import sys, os
|
||||
# General configuration
|
||||
# ---------------------
|
||||
|
||||
# Add any Sphinx extension module names here, as strings. They can be extensions
|
||||
# coming with Sphinx (named 'sphinx.ext.*') or your custom ones.
|
||||
# Add any Sphinx extension module names here, as strings. They can be
|
||||
# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom ones.
|
||||
extensions = ['sphinx.ext.autodoc']
|
||||
|
||||
# Add any paths that contain templates here, relative to this directory.
|
||||
@ -67,7 +70,8 @@ release = '0.14-dev'
|
||||
# for source files.
|
||||
exclude_trees = []
|
||||
|
||||
# The reST default role (used for this markup: `text`) to use for all documents.
|
||||
# The reST default role (used for this markup: `text`) to use for all
|
||||
# documents.
|
||||
#default_role = None
|
||||
|
||||
# If true, '()' will be appended to :func: etc. cross-reference text.
|
||||
@ -163,7 +167,8 @@ htmlhelp_basename = 'testdoc'
|
||||
#latex_font_size = '10pt'
|
||||
|
||||
# Grouping the document tree into LaTeX files. List of tuples
|
||||
# (source start file, target name, title, author, document class [howto/manual]).
|
||||
# (source start file, target name, title, author, document class
|
||||
# [howto/manual]).
|
||||
latex_documents = [
|
||||
('index', 'test.tex', ur'test Documentation',
|
||||
ur'foo', 'manual'),
|
||||
|
@ -2,44 +2,76 @@ import re
|
||||
from py65.devices.mpu6502 import MPU
|
||||
from py65.utils.addressing import AddressParser
|
||||
|
||||
|
||||
class Assembler:
|
||||
Statement = re.compile(r'^([A-z]{3}[0-7]?\s+'
|
||||
r'\(?\s*)([^,\s\)]+)(\s*[,xXyY\s]*\)?'
|
||||
r'[,xXyY\s]*)$')
|
||||
|
||||
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"
|
||||
['zpg', re.compile(r'^\$00([0-9A-F]{2})$')], # "$0012"
|
||||
['inx', re.compile(r'^\(\$00([0-9A-F]{2}),X\)$')], # "($0012,X)"
|
||||
['iny', re.compile(r'^\(\$00([0-9A-F]{2})\),Y$')], # "($0012),Y"
|
||||
['ind', re.compile(r'^\(\$([0-9A-F]{2})([0-9A-F]{2})\)$')], # "($1234)"
|
||||
['abx', re.compile(r'^\$([0-9A-F]{2})([0-9A-F]{2}),X$')], # "$1234,X"
|
||||
['aby', re.compile(r'^\$([0-9A-F]{2})([0-9A-F]{2}),Y$')], # "$1234,Y"
|
||||
['abs', re.compile(r'^\$([0-9A-F]{2})([0-9A-F]{2})$')], # "$1234"
|
||||
['rel', re.compile(r'^\$([0-9A-F]{2})([0-9A-F]{2})$')], # "$1234"
|
||||
['imp', re.compile(r'^$')], # ""
|
||||
['acc', re.compile(r'^$')], # ""
|
||||
['acc', re.compile(r'^A$')], # "A"
|
||||
['imm', re.compile(r'^#\$([0-9A-F]{2})$')] # "#$12"
|
||||
['zpi', # "($0012)"
|
||||
re.compile(r'^\(\$00([0-9A-F]{2})\)$')],
|
||||
['zpx', # "$0012,X"
|
||||
re.compile(r'^\$00([0-9A-F]{2}),X$')],
|
||||
['zpy', # "$0012,Y"
|
||||
re.compile(r'^\$00([0-9A-F]{2}),Y$')],
|
||||
['zpg', # "$0012"
|
||||
re.compile(r'^\$00([0-9A-F]{2})$')],
|
||||
['inx', # "($0012,X)
|
||||
re.compile(r'^\(\$00([0-9A-F]{2}),X\)$')],
|
||||
['iny', # "($0012),Y"
|
||||
re.compile(r'^\(\$00([0-9A-F]{2})\),Y$')],
|
||||
['ind', # "($1234)"
|
||||
re.compile(r'^\(\$([0-9A-F]{2})([0-9A-F]{2})\)$')],
|
||||
['abx', # "$1234,X"
|
||||
re.compile(r'^\$([0-9A-F]{2})([0-9A-F]{2}),X$')],
|
||||
['aby', # "$1234,Y"
|
||||
re.compile(r'^\$([0-9A-F]{2})([0-9A-F]{2}),Y$')],
|
||||
['abs', # "$1234"
|
||||
re.compile(r'^\$([0-9A-F]{2})([0-9A-F]{2})$')],
|
||||
['rel', # "$1234"
|
||||
re.compile(r'^\$([0-9A-F]{2})([0-9A-F]{2})$')],
|
||||
['imp', # ""
|
||||
re.compile(r'^$')],
|
||||
['acc', # ""
|
||||
re.compile(r'^$')],
|
||||
['acc', # "A"
|
||||
re.compile(r'^A$')],
|
||||
['imm', # "#$12"
|
||||
re.compile(r'^#\$([0-9A-F]{2})$')]
|
||||
]
|
||||
|
||||
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"
|
||||
['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
|
||||
|
||||
|
@ -1,6 +1,7 @@
|
||||
from py65.utils.conversions import convert_to_bin, convert_to_bcd, itoa
|
||||
from py65.utils.devices import make_instruction_decorator
|
||||
|
||||
|
||||
class MPU:
|
||||
# vectors
|
||||
ResetTo = 0xfffc
|
||||
@ -11,7 +12,7 @@ class MPU:
|
||||
NEGATIVE = 128
|
||||
OVERFLOW = 64
|
||||
UNUSED = 32
|
||||
BREAK = 16 # there is no BREAK flag, but this position indicates BREAK
|
||||
BREAK = 16 # there is no actual BREAK flag but this indicates BREAK
|
||||
DECIMAL = 8
|
||||
INTERRUPT = 4
|
||||
ZERO = 2
|
||||
@ -44,16 +45,15 @@ class MPU:
|
||||
self.reset()
|
||||
|
||||
def reprformat(self):
|
||||
return ("%s PC AC XR YR SP NV-BDIZC\n" + \
|
||||
"%s: %04x %02x %02x %02x %02x %s"
|
||||
)
|
||||
return ("%s PC AC XR YR SP NV-BDIZC\n"
|
||||
"%s: %04x %02x %02x %02x %02x %s")
|
||||
|
||||
def __repr__(self):
|
||||
flags = itoa(self.p, 2).rjust(self.BYTE_WIDTH, '0')
|
||||
indent = ' ' * (len(self.name) + 2)
|
||||
|
||||
return self.reprformat() % (indent, self.name,
|
||||
self.pc, self.a, self.x, self.y, self.sp, flags)
|
||||
return self.reprformat() % (indent, self.name, self.pc, self.a,
|
||||
self.x, self.y, self.sp, flags)
|
||||
|
||||
def step(self):
|
||||
instructCode = self.memory[self.pc]
|
||||
@ -222,7 +222,7 @@ class MPU:
|
||||
|
||||
tbyte = tbyte >> 1
|
||||
if tbyte:
|
||||
pass # {}
|
||||
pass
|
||||
else:
|
||||
self.p |= self.ZERO
|
||||
|
||||
@ -352,7 +352,7 @@ class MPU:
|
||||
|
||||
if self.p & self.CARRY:
|
||||
if tbyte & 1:
|
||||
pass # {}
|
||||
pass
|
||||
else:
|
||||
self.p &= ~self.CARRY
|
||||
tbyte = (tbyte >> 1) | self.NEGATIVE
|
||||
@ -403,7 +403,9 @@ class MPU:
|
||||
adjust1 = 10 << 4
|
||||
|
||||
# the ALU outputs are not decimally adjusted
|
||||
aluresult = self.a + (~data & self.byteMask) + (self.p & self.CARRY)
|
||||
aluresult = self.a + (~data & self.byteMask) + \
|
||||
(self.p & self.CARRY)
|
||||
|
||||
if aluresult > self.byteMask:
|
||||
decimalcarry = 1
|
||||
aluresult &= self.byteMask
|
||||
@ -505,7 +507,8 @@ class MPU:
|
||||
|
||||
@instruction(name="BRK", mode="imp", cycles=7)
|
||||
def inst_0x00(self):
|
||||
pc = (self.pc + 1) & self.addrMask # The pc has already been increased one
|
||||
# pc has already been increased one
|
||||
pc = (self.pc + 1) & self.addrMask
|
||||
self.stPushWord(pc)
|
||||
|
||||
self.p |= self.BREAK
|
||||
|
@ -1,6 +1,7 @@
|
||||
from py65.devices import mpu6502
|
||||
from py65.utils.devices import make_instruction_decorator
|
||||
|
||||
|
||||
class MPU(mpu6502.MPU):
|
||||
def __init__(self, *args, **kwargs):
|
||||
mpu6502.MPU.__init__(self, *args, **kwargs)
|
||||
@ -267,4 +268,3 @@ class MPU(mpu6502.MPU):
|
||||
def inst_0xf2(self):
|
||||
self.opSBC(self.ZeroPageIndirectAddr)
|
||||
self.pc += 1
|
||||
|
||||
|
@ -1,6 +1,7 @@
|
||||
from py65.devices import mpu6502
|
||||
from py65.utils.devices import make_instruction_decorator
|
||||
|
||||
|
||||
class MPU(mpu6502.MPU):
|
||||
"""
|
||||
The 65Org16 is a derivative of the 6502 architecture
|
||||
@ -10,7 +11,8 @@ class MPU(mpu6502.MPU):
|
||||
- and otherwise all opcodes and addressing modes are like the NMOS 6502
|
||||
- sign bit is bit 15, overflow bit is bit 14
|
||||
|
||||
One implementation can be found here: https://github.com/BigEd/verilog-6502/wiki
|
||||
One implementation can be found here:
|
||||
https://github.com/BigEd/verilog-6502/wiki
|
||||
"""
|
||||
|
||||
BYTE_WIDTH = 16
|
||||
@ -42,6 +44,5 @@ class MPU(mpu6502.MPU):
|
||||
disassemble = mpu6502.MPU.disassemble[:]
|
||||
|
||||
def reprformat(self):
|
||||
return ("%s PC AC XR YR SP NV---------BDIZC\n" + \
|
||||
"%s: %08x %04x %04x %04x %04x %s"
|
||||
)
|
||||
return ("%s PC AC XR YR SP NV---------BDIZC\n" +
|
||||
"%s: %08x %04x %04x %04x %04x %s")
|
||||
|
@ -1,5 +1,6 @@
|
||||
from py65.utils.addressing import AddressParser
|
||||
|
||||
|
||||
class Disassembler:
|
||||
def __init__(self, mpu, address_parser=None):
|
||||
if address_parser is None:
|
||||
@ -29,22 +30,22 @@ class Disassembler:
|
||||
|
||||
elif addressing == 'abs':
|
||||
address = self._mpu.WordAt(pc + 1)
|
||||
address_or_label = self._address_parser.label_for(address,
|
||||
'$' + self.addrFmt % address)
|
||||
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)
|
||||
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)
|
||||
address_or_label = self._address_parser.label_for(
|
||||
address, '$' + self.addrFmt % address)
|
||||
disasm += ' %s,Y' % address_or_label
|
||||
length = 3
|
||||
|
||||
@ -58,22 +59,22 @@ class Disassembler:
|
||||
|
||||
elif addressing == 'ind':
|
||||
address = self._mpu.WordAt(pc + 1)
|
||||
address_or_label = self._address_parser.label_for(address,
|
||||
'$' + self.addrFmt % address)
|
||||
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)
|
||||
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)
|
||||
address_or_label = self._address_parser.label_for(
|
||||
zp_address, '$' + self.byteFmt % zp_address)
|
||||
disasm += ' (%s,X)' % address_or_label
|
||||
length = 2
|
||||
|
||||
@ -86,36 +87,36 @@ class Disassembler:
|
||||
targ += opv
|
||||
targ &= self.addrMask
|
||||
|
||||
address_or_label = self._address_parser.label_for(targ,
|
||||
'$' + self.addrFmt % targ)
|
||||
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 + ')' )
|
||||
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)
|
||||
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)
|
||||
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)
|
||||
address_or_label = self._address_parser.label_for(
|
||||
zp_address, '$' + self.byteFmt % zp_address)
|
||||
disasm += ' %s,Y' % address_or_label
|
||||
length = 2
|
||||
|
||||
|
@ -1,5 +1,6 @@
|
||||
from collections import defaultdict
|
||||
|
||||
|
||||
class ObservableMemory:
|
||||
def __init__(self, subject=None, addrWidth=16):
|
||||
self.physMask = 0xffff
|
||||
|
@ -30,11 +30,14 @@ from py65.utils import console
|
||||
from py65.utils.conversions import itoa
|
||||
from py65.memory import ObservableMemory
|
||||
|
||||
|
||||
class Monitor(cmd.Cmd):
|
||||
|
||||
Microprocessors = {'6502': NMOS6502, '65C02': CMOS65C02, '65Org16': V65Org16}
|
||||
Microprocessors = {'6502': NMOS6502, '65C02': CMOS65C02,
|
||||
'65Org16': V65Org16}
|
||||
|
||||
def __init__(self, mpu_type=NMOS6502, completekey='tab', stdin=None, stdout=None, argv=None):
|
||||
def __init__(self, mpu_type=NMOS6502, completekey='tab', stdin=None,
|
||||
stdout=None, argv=None):
|
||||
self.mpu_type = mpu_type
|
||||
if argv is None:
|
||||
argv = sys.argv
|
||||
@ -47,8 +50,9 @@ class Monitor(cmd.Cmd):
|
||||
|
||||
def _parse_args(self, argv):
|
||||
try:
|
||||
options, args = getopt.getopt(argv[1:], 'hm:l:r:g:',
|
||||
['help', 'mpu=', 'load=', 'rom=', 'goto='])
|
||||
shortopts = 'hm:l:r:g:'
|
||||
longopts = ['help', 'mpu=', 'load=', 'rom=', 'goto=']
|
||||
options, args = getopt.getopt(argv[1:], shortopts, longopts)
|
||||
except getopt.GetoptError, err:
|
||||
self._output(str(err))
|
||||
self._usage()
|
||||
@ -58,26 +62,32 @@ class Monitor(cmd.Cmd):
|
||||
if opt in ('-l', '--load'):
|
||||
cmd = "load %s" % value
|
||||
self.onecmd(cmd)
|
||||
|
||||
if opt in ('-r', '--rom'):
|
||||
# load a ROM and run from the reset vector
|
||||
cmd = "load %s %d" % (value, -1)
|
||||
self.onecmd(cmd)
|
||||
physMask = self._mpu.memory.physMask
|
||||
reset = self._mpu.ResetTo & physMask
|
||||
dest = self._mpu.memory[reset] + (self._mpu.memory[reset+1] << self.byteWidth)
|
||||
dest = self._mpu.memory[reset] + \
|
||||
(self._mpu.memory[reset + 1] << self.byteWidth)
|
||||
cmd = "goto %08x" % dest
|
||||
self.onecmd(cmd)
|
||||
|
||||
if opt in ('-g', '--goto'):
|
||||
cmd = "goto %s" % value
|
||||
self.onecmd(cmd)
|
||||
|
||||
if opt in ('-m', '--mpu'):
|
||||
if self._get_mpu(value) is None:
|
||||
mpus = self.Microprocessors.keys()
|
||||
mpus.sort()
|
||||
self._output("Fatal: no such MPU. Available MPUs: %s" % ', '.join(mpus))
|
||||
msg = "Fatal: no such MPU. Available MPUs: %s"
|
||||
self._output(msg % ', '.join(mpus))
|
||||
sys.exit(1)
|
||||
cmd = "mpu %s" % value
|
||||
self.onecmd(cmd)
|
||||
|
||||
elif opt in ("-h", "--help"):
|
||||
self._usage()
|
||||
self._exit(1)
|
||||
@ -279,7 +289,8 @@ class Monitor(cmd.Cmd):
|
||||
|
||||
end = start + len(bytes)
|
||||
self._mpu.memory[start:end] = bytes
|
||||
self.do_disassemble((self.addrFmt+":"+self.addrFmt) % (start, end))
|
||||
rangestr = (self.addrFmt + ":" + self.addrFmt) % (start, end)
|
||||
self.do_disassemble(rangestr)
|
||||
except KeyError:
|
||||
self._output("Bad label: %s" % args)
|
||||
except OverflowError:
|
||||
@ -304,7 +315,9 @@ class Monitor(cmd.Cmd):
|
||||
return
|
||||
|
||||
while True:
|
||||
prompt = "\r$" + ( self.addrFmt % start ) + " " + (" " * (1 + self.byteWidth/4) * 3)
|
||||
prompt = "\r$" + (self.addrFmt % start) + " " + \
|
||||
(" " * (1 + self.byteWidth / 4) * 3)
|
||||
|
||||
line = console.line_input(prompt,
|
||||
stdin=self.stdin, stdout=self.stdout)
|
||||
|
||||
@ -322,16 +335,20 @@ class Monitor(cmd.Cmd):
|
||||
# print disassembly
|
||||
bytes, disasm = self._disassembler.instruction_at(start)
|
||||
disassembly = self._format_disassembly(start, bytes, disasm)
|
||||
self.stdout.write("\r" + (' ' * (len(prompt+line) + 5) ) + "\r")
|
||||
indent = ' ' * (len(prompt + line) + 5)
|
||||
self.stdout.write("\r" + indent + "\r")
|
||||
self.stdout.write(disassembly + "\n")
|
||||
|
||||
start += bytes
|
||||
except KeyError:
|
||||
self.stdout.write("\r$" + (self.addrFmt % start) + " ?Label\n")
|
||||
addr = self.addrFmt % start
|
||||
self.stdout.write("\r$%s ?Label\n" % addr)
|
||||
except OverflowError:
|
||||
self.stdout.write("\r$" + (self.addrFmt % start) + " ?Overflow\n")
|
||||
addr = self.addrFmt % start
|
||||
self.stdout.write("\r$%s ?Overflow\n" % addr)
|
||||
except SyntaxError:
|
||||
self.stdout.write("\r$" + (self.addrFmt % start) + " ?Syntax\n")
|
||||
addr = self.addrFmt % start
|
||||
self.stdout.write("\r$%s ?Syntax\n" % addr)
|
||||
|
||||
def do_disassemble(self, args):
|
||||
split = shlex.split(args)
|
||||
@ -396,7 +413,7 @@ class Monitor(cmd.Cmd):
|
||||
|
||||
def help_radix(self):
|
||||
self._output("radix [H|D|O|B]")
|
||||
self._output("Set the default radix to hex, decimal, octal, or binary.")
|
||||
self._output("Set default radix to hex, decimal, octal, or binary.")
|
||||
self._output("With no argument, the current radix is printed.")
|
||||
|
||||
def help_cycles(self):
|
||||
@ -424,7 +441,7 @@ class Monitor(cmd.Cmd):
|
||||
|
||||
def help_tilde(self):
|
||||
self._output("~ <number>")
|
||||
self._output("Display the specified number in decimal, hex, octal, and binary.")
|
||||
self._output("Display a number in decimal, hex, octal, and binary.")
|
||||
|
||||
def do_tilde(self, args):
|
||||
try:
|
||||
@ -439,7 +456,7 @@ class Monitor(cmd.Cmd):
|
||||
self._output(itoa(num, 2).zfill(8))
|
||||
|
||||
def help_registers(self):
|
||||
self._output("registers[<reg_name> = <number> [, <reg_name> = <number>]*]")
|
||||
self._output("registers[<name>=<value> [, <name>=<value>]*]")
|
||||
self._output("Assign respective registers. With no parameters,")
|
||||
self._output("display register values.")
|
||||
|
||||
@ -487,7 +504,7 @@ class Monitor(cmd.Cmd):
|
||||
|
||||
def help_load(self):
|
||||
self._output("load \"filename\" <address>")
|
||||
self._output("Load the specified file into memory at the specified address.")
|
||||
self._output("Load a file into memory at the specified address.")
|
||||
self._output("Commodore-style load address bytes are ignored.")
|
||||
|
||||
def do_load(self, args):
|
||||
@ -528,8 +545,11 @@ class Monitor(cmd.Cmd):
|
||||
|
||||
if self.byteWidth == 8:
|
||||
bytes = map(ord, bytes)
|
||||
|
||||
elif self.byteWidth == 16:
|
||||
bytes=map(lambda msb,lsb: (ord(msb)<<8)+ord(lsb),bytes[0::2],bytes[1::2])
|
||||
def format(msb, lsb):
|
||||
return (ord(msb) << 8) + ord(lsb)
|
||||
bytes = map(format, bytes[0::2], bytes[1::2])
|
||||
|
||||
self._fill(start, start, bytes)
|
||||
|
||||
@ -560,14 +580,15 @@ class Monitor(cmd.Cmd):
|
||||
|
||||
def help_save(self):
|
||||
self._output("save \"filename\" <start> <end>")
|
||||
self._output("Save the specified memory range to disk as a binary file.")
|
||||
self._output("Save the specified memory range as a binary file.")
|
||||
self._output("Commodore-style load address bytes are not written.")
|
||||
|
||||
def help_fill(self):
|
||||
self._output("fill <address_range> <data_list>")
|
||||
self._output("Fill memory in the specified address range with the data in")
|
||||
self._output("<data_list>. If the size of the address range is greater")
|
||||
self._output("than the size of the data_list, the data_list is repeated.")
|
||||
self._output("Fill memory in the address range with the data in")
|
||||
self._output("<data_list>. If the size of the address range is")
|
||||
self._output("greater than the size of the data_list, the data_list ")
|
||||
self._output("is repeated.")
|
||||
|
||||
def do_fill(self, args):
|
||||
split = shlex.split(args)
|
||||
@ -681,6 +702,7 @@ class Monitor(cmd.Cmd):
|
||||
self._output("Set the width used by some commands to wrap output.")
|
||||
self._output("With no argument, the current width is printed.")
|
||||
|
||||
|
||||
def main(args=None):
|
||||
c = Monitor()
|
||||
|
||||
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -5,6 +5,7 @@ from py65.devices.mpu65c02 import MPU as MPU65C02
|
||||
from py65.assembler import Assembler
|
||||
from py65.utils.addressing import AddressParser
|
||||
|
||||
|
||||
class AssemblerTests(unittest.TestCase):
|
||||
def test_assemble_bad_syntax_raises_syntaxerror(self):
|
||||
self.assertRaises(SyntaxError,
|
||||
@ -955,6 +956,7 @@ class AssemblerTests(unittest.TestCase):
|
||||
assembler = Assembler(mpu, address_parser)
|
||||
return assembler.assemble(statement, pc)
|
||||
|
||||
|
||||
def test_suite():
|
||||
return unittest.findTestCases(sys.modules[__name__])
|
||||
|
||||
|
@ -5,6 +5,7 @@ from py65.devices.mpu65c02 import MPU as MPU65C02
|
||||
from py65.disassembler import Disassembler
|
||||
from py65.utils.addressing import AddressParser
|
||||
|
||||
|
||||
class DisassemblerTests(unittest.TestCase):
|
||||
def test_disassembles_00(self):
|
||||
length, disasm = self.disassemble([0x00])
|
||||
@ -1304,9 +1305,10 @@ class DisassemblerTests(unittest.TestCase):
|
||||
mpu = MPU()
|
||||
address_parser = AddressParser()
|
||||
disasm = Disassembler(mpu, address_parser)
|
||||
mpu.memory[pc:len(bytes)-1] = bytes
|
||||
mpu.memory[pc:len(bytes) - 81] = bytes
|
||||
return disasm.instruction_at(pc)
|
||||
|
||||
|
||||
def test_suite():
|
||||
return unittest.findTestCases(sys.modules[__name__])
|
||||
|
||||
|
@ -4,6 +4,7 @@ import re
|
||||
import os
|
||||
from py65.memory import ObservableMemory
|
||||
|
||||
|
||||
class ObservableMemoryTests(unittest.TestCase):
|
||||
|
||||
# __setitem__
|
||||
@ -68,6 +69,7 @@ class ObservableMemoryTests(unittest.TestCase):
|
||||
mem = ObservableMemory(subject=subject)
|
||||
|
||||
calls = []
|
||||
|
||||
def read_subscriber(address):
|
||||
calls.append('read_subscriber')
|
||||
|
||||
@ -107,6 +109,7 @@ class ObservableMemoryTests(unittest.TestCase):
|
||||
mem = ObservableMemory(subject=subject)
|
||||
|
||||
calls = []
|
||||
|
||||
def read_subscriber_1(address):
|
||||
calls.append('read_subscriber_1')
|
||||
return 0x01
|
||||
|
@ -6,6 +6,7 @@ import tempfile
|
||||
from py65.monitor import Monitor
|
||||
from StringIO import StringIO
|
||||
|
||||
|
||||
class MonitorTests(unittest.TestCase):
|
||||
|
||||
# line processing
|
||||
@ -249,7 +250,7 @@ class MonitorTests(unittest.TestCase):
|
||||
mon = Monitor(stdout=stdout)
|
||||
mon._address_parser.labels['foo'] = 0xc000
|
||||
mon.do_delete_label('foo')
|
||||
self.assertFalse(mon._address_parser.labels.has_key('foo'))
|
||||
self.assertFalse('foo' in mon._address_parser.labels)
|
||||
out = stdout.getvalue()
|
||||
self.assertEqual('', out)
|
||||
|
||||
@ -462,7 +463,8 @@ class MonitorTests(unittest.TestCase):
|
||||
mon.do_load("'%s' a600" % filename)
|
||||
self.assertEqual('Wrote +3 bytes from $a600 to $a602\n',
|
||||
stdout.getvalue())
|
||||
self.assertEqual([0xAA, 0xBB, 0xCC], mon._mpu.memory[0xA600:0xA603])
|
||||
self.assertEqual([0xAA, 0xBB, 0xCC],
|
||||
mon._mpu.memory[0xA600:0xA603])
|
||||
finally:
|
||||
os.unlink(filename)
|
||||
|
||||
@ -632,7 +634,6 @@ class MonitorTests(unittest.TestCase):
|
||||
out = stdout.getvalue()
|
||||
self.assertEqual("%s\n" % os.getcwd(), out)
|
||||
|
||||
|
||||
def test_help_pwd(self):
|
||||
stdout = StringIO()
|
||||
mon = Monitor(stdout=stdout)
|
||||
@ -714,7 +715,7 @@ class MonitorTests(unittest.TestCase):
|
||||
mon = Monitor(stdout=stdout)
|
||||
mon.help_registers()
|
||||
out = stdout.getvalue()
|
||||
self.assertTrue(out.startswith("registers[<reg_name>"))
|
||||
self.assertTrue(out.startswith("registers[<name>"))
|
||||
|
||||
# return
|
||||
|
||||
|
@ -2,6 +2,7 @@ import unittest
|
||||
import sys
|
||||
from py65.utils.addressing import AddressParser
|
||||
|
||||
|
||||
class AddressParserTests(unittest.TestCase):
|
||||
def test_maxwidth_can_be_set_in_constructor(self):
|
||||
parser = AddressParser(maxwidth=24)
|
||||
|
@ -2,6 +2,7 @@ import sys
|
||||
import unittest
|
||||
from py65.utils.console import getch
|
||||
|
||||
|
||||
class ConsoleTopLevelTests(unittest.TestCase):
|
||||
pass
|
||||
|
||||
|
@ -2,6 +2,7 @@ import sys
|
||||
import unittest
|
||||
from py65.utils.conversions import itoa
|
||||
|
||||
|
||||
class ConversionsTopLevelTests(unittest.TestCase):
|
||||
def test_itoa_decimal_output(self):
|
||||
self.assertEqual('10', itoa(10, base=10))
|
||||
|
@ -2,6 +2,7 @@ import unittest
|
||||
import sys
|
||||
from py65.utils.hexdump import load, Loader
|
||||
|
||||
|
||||
class TopLevelHexdumpTests(unittest.TestCase):
|
||||
def test_load(self):
|
||||
text = 'c000: aa bb'
|
||||
@ -9,6 +10,7 @@ class TopLevelHexdumpTests(unittest.TestCase):
|
||||
self.assertEqual(0xC000, start)
|
||||
self.assertEqual([0xAA, 0xBB], data)
|
||||
|
||||
|
||||
class HexdumpLoaderTests(unittest.TestCase):
|
||||
def test_empty_string_does_nothing(self):
|
||||
text = ''
|
||||
@ -126,7 +128,6 @@ class HexdumpLoaderTests(unittest.TestCase):
|
||||
self.assertEqual([0xAA, 0xBB], load.data)
|
||||
|
||||
|
||||
|
||||
def test_suite():
|
||||
return unittest.findTestCases(sys.modules[__name__])
|
||||
|
||||
|
@ -1,5 +1,6 @@
|
||||
import re
|
||||
|
||||
|
||||
class AddressParser(object):
|
||||
"""Parse user input into addresses or ranges of addresses.
|
||||
"""
|
||||
|
@ -86,7 +86,7 @@ def line_input(prompt='', stdin=sys.stdin, stdout=sys.stdout):
|
||||
elif code in (0x7f, 0x08): # backspace
|
||||
if len(line) > 0:
|
||||
line = line[:-1]
|
||||
stdout.write("\r%s\r%s%s" % \
|
||||
stdout.write("\r%s\r%s%s" %
|
||||
(' ' * (len(prompt + line) + 5), prompt, line))
|
||||
elif code == 0x1b: # escape
|
||||
pass
|
||||
|
@ -1,3 +1,5 @@
|
||||
|
||||
|
||||
def itoa(num, base=10):
|
||||
""" Convert a decimal number to its equivalent in another base.
|
||||
This is essentially the inverse of int(num, base).
|
||||
@ -14,31 +16,35 @@ def itoa(num, base=10):
|
||||
digits.reverse()
|
||||
return ''.join(digits)
|
||||
|
||||
|
||||
def convert_to_bin(bcd):
|
||||
return bcd2bin[bcd]
|
||||
|
||||
|
||||
def convert_to_bcd(bin):
|
||||
return bin2bcd[bin]
|
||||
|
||||
|
||||
bcd2bin = [
|
||||
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, # 0x00
|
||||
10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, # 0x10
|
||||
20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, # 0x20
|
||||
30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, # 0x30
|
||||
40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, # 0x40
|
||||
50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, # 0x50
|
||||
60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, # 0x60
|
||||
70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, # 0x70
|
||||
80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, # 0x80
|
||||
90, 91, 92, 93, 94, 95, 96, 97, 98, 99,100,101,102,103,104,105, # 0x90
|
||||
100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115, # 0xA0
|
||||
110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125, # 0xB0
|
||||
120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135, # 0xC0
|
||||
130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145, # 0xD0
|
||||
140,141,142,143,144,145,146,147,148,149,150,151,152,153,154,155, # 0xE0
|
||||
150,151,152,153,154,155,156,157,158,159,160,161,162,163,164,165 # 0xF0
|
||||
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 10, 11, 12, 13,
|
||||
14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 20, 21, 22, 23, 24, 25,
|
||||
26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 30, 31, 32, 33, 34, 35, 36, 37,
|
||||
38, 39, 40, 41, 42, 43, 44, 45, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49,
|
||||
50, 51, 52, 53, 54, 55, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61,
|
||||
62, 63, 64, 65, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73,
|
||||
74, 75, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85,
|
||||
80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 90, 91,
|
||||
92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 100, 101,
|
||||
102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115,
|
||||
110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123,
|
||||
124, 125, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131,
|
||||
132, 133, 134, 135, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139,
|
||||
140, 141, 142, 143, 144, 145, 140, 141, 142, 143, 144, 145, 146, 147,
|
||||
148, 149, 150, 151, 152, 153, 154, 155, 150, 151, 152, 153, 154, 155,
|
||||
156, 157, 158, 159, 160, 161, 162, 163, 164, 165
|
||||
]
|
||||
|
||||
|
||||
bin2bcd = [
|
||||
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09,
|
||||
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19,
|
||||
|
@ -1,4 +1,5 @@
|
||||
|
||||
|
||||
def make_instruction_decorator(instruct, disasm, allcycles, allextras):
|
||||
def instruction(name, mode, cycles, extracycles=0):
|
||||
def decorate(f):
|
||||
|
@ -1,9 +1,11 @@
|
||||
from binascii import a2b_hex
|
||||
|
||||
|
||||
def load(text):
|
||||
load = Loader(text)
|
||||
return (load.start_address, load.data)
|
||||
|
||||
|
||||
class Loader:
|
||||
def __init__(self, text):
|
||||
self.load(text)
|
||||
@ -45,12 +47,12 @@ class Loader:
|
||||
addr_bytes = [ord(c) for c in a2b_hex(piece)]
|
||||
except (TypeError, ValueError):
|
||||
msg = "Could not parse address: %s" % piece
|
||||
raise ValueError, msg
|
||||
raise ValueError(msg)
|
||||
|
||||
if len(addr_bytes) != 2:
|
||||
msg = "Expected address to be 2 bytes, got %d" % (
|
||||
len(addr_bytes))
|
||||
raise ValueError, msg
|
||||
raise ValueError(msg)
|
||||
|
||||
address = (addr_bytes[0] << 8) + addr_bytes[1]
|
||||
|
||||
@ -62,19 +64,19 @@ class Loader:
|
||||
msg = "Non-contigous block detected. Expected next address " \
|
||||
"to be $%04x, label was $%04x" % (self.current_address,
|
||||
address)
|
||||
raise ValueError, msg
|
||||
raise ValueError(msg)
|
||||
|
||||
def _parse_bytes(self, piece):
|
||||
if self.start_address is None:
|
||||
msg = "Start address was not found in data"
|
||||
raise ValueError, msg
|
||||
raise ValueError(msg)
|
||||
|
||||
else:
|
||||
try:
|
||||
bytes = [ord(c) for c in a2b_hex(piece)]
|
||||
except (TypeError, ValueError):
|
||||
msg = "Could not parse data: %s" % piece
|
||||
raise ValueError, msg
|
||||
raise ValueError(msg)
|
||||
|
||||
self.current_address += len(bytes)
|
||||
self.data.extend(bytes)
|
||||
|
Loading…
Reference in New Issue
Block a user