Massive code modernization spree.

Full PEP8 compliance. Also, booleans have been inserted where
they make sense (introduced in 2.3!) and I haven't knowingly
added anything that will break 2.3 compatibility.

At this point the code really doesn't look like it was written
ten years ago. Hooray!
This commit is contained in:
Michael C. Martin 2012-06-01 10:25:48 -07:00
parent f83379287f
commit 14a37ca879
38 changed files with 1459 additions and 925 deletions

2
README
View File

@ -28,4 +28,4 @@ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE. THE SOFTWARE.

View File

@ -9,4 +9,4 @@ _next: .word 0 ; End of program
.advance 2064 .advance 2064
.require "kernal.oph" .require "kernal.oph"

View File

@ -37,4 +37,4 @@ _next: .word 0 ; End of program
_main: _main:
; Program follows... ; Program follows...
.scend .scend

View File

@ -249,7 +249,7 @@
.checkpc $100 .checkpc $100
</programlisting> </programlisting>
</section> </section>
</section> </section>
<section> <section>
<title>Macros</title> <title>Macros</title>
<para> <para>
@ -400,7 +400,7 @@
code in and of itself, nor does it overwrite anything that code in and of itself, nor does it overwrite anything that
previously existed.</emphasis> If you wish to jump ahead in memory, previously existed.</emphasis> If you wish to jump ahead in memory,
use <literal>.advance</literal>.</para></listitem> use <literal>.advance</literal>.</para></listitem>
<listitem><para><literal>.require</literal> <emphasis>filename</emphasis>: Includes the entirety <listitem><para><literal>.require</literal> <emphasis>filename</emphasis>: Includes the entirety
of the file specified at that point in the program. Unlike <literal>.include</literal>, of the file specified at that point in the program. Unlike <literal>.include</literal>,
however, code included with <literal>.require</literal> will only be inserted once. however, code included with <literal>.require</literal> will only be inserted once.
The <literal>.require</literal> directive is useful for ensuring that certain code libraries The <literal>.require</literal> directive is useful for ensuring that certain code libraries
@ -447,5 +447,5 @@
macro definition intends to read. A shorthand for <literal>.invoke</literal> macro definition intends to read. A shorthand for <literal>.invoke</literal>
is the name of the macro to invoke, backquoted.</para></listitem> is the name of the macro to invoke, backquoted.</para></listitem>
</itemizedlist> </itemizedlist>
</section> </section>
</appendix> </appendix>

View File

@ -333,7 +333,7 @@ delay: tax
iny iny
bne - bne -
dex dex
bne - bne -
rts rts
</programlisting> </programlisting>
</section> </section>

View File

@ -153,19 +153,19 @@ next: .word 0 ; End of program
Labels are defined by putting their name, then a colon, as Labels are defined by putting their name, then a colon, as
seen in the definition of <literal>next</literal>. seen in the definition of <literal>next</literal>.
</para></listitem> </para></listitem>
<listitem><para> <listitem><para>
Instead of putting in the hex codes for the string part of Instead of putting in the hex codes for the string part of
the BASIC code, we included the string directly. Each the BASIC code, we included the string directly. Each
character in the string becomes one byte. character in the string becomes one byte.
</para></listitem> </para></listitem>
<listitem><para> <listitem><para>
Instead of adding the buffer ourselves, we Instead of adding the buffer ourselves, we
used <literal>.advance</literal>, which outputs zeros until used <literal>.advance</literal>, which outputs zeros until
the specified address is reached. Attempting the specified address is reached. Attempting
to <literal>.advance</literal> backwards produces an to <literal>.advance</literal> backwards produces an
assemble-time error. assemble-time error.
</para></listitem> </para></listitem>
<listitem><para> <listitem><para>
It has comments that explain what the data are for. The It has comments that explain what the data are for. The
semicolon is the comment marker; everything from a semicolon semicolon is the comment marker; everything from a semicolon
to the end of the line is ignored. to the end of the line is ignored.
@ -263,9 +263,9 @@ hello: .byte "HELLO, WORLD!", 0
<row> <row>
<entry align="center">Option</entry> <entry align="center">Option</entry>
<entry align="center">Effect</entry> <entry align="center">Effect</entry>
</row> </row>
</thead> </thead>
<tbody> <tbody>
<row><entry><option>-6510</option></entry><entry>Allows the 6510 undocumented opcodes as listed in the VICE documentation.</entry></row> <row><entry><option>-6510</option></entry><entry>Allows the 6510 undocumented opcodes as listed in the VICE documentation.</entry></row>
<row><entry><option>-65c02</option></entry><entry>Allows opcodes and addressing modes added by the 65C02.</entry></row> <row><entry><option>-65c02</option></entry><entry>Allows opcodes and addressing modes added by the 65C02.</entry></row>
<row><entry><option>-v 0</option></entry><entry>Quiet operation. Only reports errors.</entry></row> <row><entry><option>-v 0</option></entry><entry>Quiet operation. Only reports errors.</entry></row>

View File

@ -64,4 +64,4 @@
; ...and character set ; ...and character set
.alias upper'case 142 .alias upper'case 142
.alias lower'case 14 .alias lower'case 14

View File

@ -15,4 +15,4 @@ loop: lda hello, x
bne loop bne loop
done: rts done: rts
hello: .byte "HELLO, WORLD!", 0 hello: .byte "HELLO, WORLD!", 0

View File

@ -19,4 +19,4 @@ _next: .word 0 ; End of program
bne - bne -
* rts * rts
hello: .byte "HELLO, WORLD!", 0 hello: .byte "HELLO, WORLD!", 0

View File

@ -42,4 +42,4 @@ target6: .byte "NATION", 0
target7: .byte "WORLD", 0 target7: .byte "WORLD", 0
target8: .byte "SOLAR SYSTEM", 0 target8: .byte "SOLAR SYSTEM", 0
target9: .byte "GALAXY", 0 target9: .byte "GALAXY", 0
target10: .byte "UNIVERSE", 0 target10: .byte "UNIVERSE", 0

View File

@ -63,7 +63,7 @@ delay: tax
bne - bne -
dex dex
bne - bne -
rts rts

View File

@ -65,7 +65,7 @@ delay: tax
bne - bne -
dex dex
bne - bne -
rts rts

View File

@ -68,6 +68,6 @@ delay: tax
bne - bne -
dex dex
bne - bne -
rts rts

View File

@ -72,4 +72,4 @@ delay: sta _tmp ; save argument (rdtim destroys it)
.checkpc $A000 .checkpc $A000
.data .data
.checkpc $D000 .checkpc $D000

View File

@ -99,4 +99,4 @@ _done: rts
.checkpc $A000 .checkpc $A000
.data .data
.checkpc $D000 .checkpc $D000

View File

@ -93,4 +93,4 @@ _done: rts
.checkpc $D000 .checkpc $D000
.data zp .data zp
.checkpc $80 .checkpc $80

View File

@ -6,44 +6,59 @@ import optparse
# You may use, modify, and distribute this file under the MIT # You may use, modify, and distribute this file under the MIT
# license: See README for details. # license: See README for details.
enable_collapse = True enable_collapse = True
enable_branch_extend = True enable_branch_extend = True
enable_undoc_ops = False enable_undoc_ops = False
enable_65c02_exts = False enable_65c02_exts = False
warn_on_branch_extend = True warn_on_branch_extend = True
print_summary = True print_summary = True
print_loaded_files = False print_loaded_files = False
print_pass = False print_pass = False
print_ir = False print_ir = False
print_labels = False print_labels = False
infile = None
outfile = None
infile = None
outfile = None
def parse_args(raw_args): def parse_args(raw_args):
"Populate the module's globals based on the command-line options given." "Populate the module's globals based on the command-line options given."
global enable_collapse, enable_branch_extend, enable_undoc_ops, enable_65c02_exts global enable_collapse, enable_branch_extend
global enable_undoc_ops, enable_65c02_exts
global warn_on_branch_extend global warn_on_branch_extend
global print_summary, print_loaded_files, print_pass, print_ir, print_labels global print_summary, print_loaded_files
global print_pass, print_ir, print_labels
global infile, outfile global infile, outfile
parser = optparse.OptionParser(usage= "Usage: %prog [options] srcfile outfile", version="Ophis 6502 cross-assembler, version 2.0") parser = optparse.OptionParser(
usage="Usage: %prog [options] srcfile outfile",
version="Ophis 6502 cross-assembler, version 2.0")
ingrp = optparse.OptionGroup(parser, "Input options") ingrp = optparse.OptionGroup(parser, "Input options")
ingrp.add_option("-u", "--undoc", action="store_true", default=False, help="Enable 6502 undocumented opcodes") ingrp.add_option("-u", "--undoc", action="store_true", default=False,
ingrp.add_option("-c", "--65c02", action="store_true", default=False, dest="c02", help="Enable 65c02 extended instruction set") help="Enable 6502 undocumented opcodes")
ingrp.add_option("-c", "--65c02", action="store_true", default=False,
dest="c02", help="Enable 65c02 extended instruction set")
outgrp = optparse.OptionGroup(parser, "Console output options") outgrp = optparse.OptionGroup(parser, "Console output options")
outgrp.add_option("-v", "--verbose", action="store_const", const=2, help="Verbose mode", default=1) outgrp.add_option("-v", "--verbose", action="store_const", const=2,
outgrp.add_option("-q", "--quiet", action="store_const", help="Quiet mode", dest="verbose", const=0) help="Verbose mode", default=1)
outgrp.add_option("-d", "--debug", action="count", dest="verbose", help=optparse.SUPPRESS_HELP) outgrp.add_option("-q", "--quiet", action="store_const", help="Quiet mode",
outgrp.add_option("--no-warn", action="store_false", dest="warn", default=True, help="Do not print warnings") dest="verbose", const=0)
outgrp.add_option("-d", "--debug", action="count", dest="verbose",
help=optparse.SUPPRESS_HELP)
outgrp.add_option("--no-warn", action="store_false", dest="warn",
default=True, help="Do not print warnings")
bingrp = optparse.OptionGroup(parser, "Binary output options") bingrp = optparse.OptionGroup(parser, "Compilation options")
bingrp.add_option("--no-collapse", action="store_false", dest="enable_collapse", default="True", help="Disable zero-page collapse pass") bingrp.add_option("--no-collapse", action="store_false",
bingrp.add_option("--no-branch-extend", action="store_false", dest="enable_branch_extend", default="True", help="Disable branch-extension pass") dest="enable_collapse", default="True",
help="Disable zero-page collapse pass")
bingrp.add_option("--no-branch-extend", action="store_false",
dest="enable_branch_extend", default="True",
help="Disable branch-extension pass")
parser.add_option_group(ingrp) parser.add_option_group(ingrp)
parser.add_option_group(outgrp) parser.add_option_group(outgrp)
@ -60,15 +75,15 @@ def parse_args(raw_args):
if options.c02 and options.undoc: if options.c02 and options.undoc:
parser.error("--undoc and --65c02 are mutually exclusive") parser.error("--undoc and --65c02 are mutually exclusive")
infile = args[0] infile = args[0]
outfile = args[1] outfile = args[1]
enable_collapse = options.enable_collapse enable_collapse = options.enable_collapse
enable_branch_extend = options.enable_branch_extend enable_branch_extend = options.enable_branch_extend
enable_undoc_ops = options.undoc enable_undoc_ops = options.undoc
enable_65c02_exts = options.c02 enable_65c02_exts = options.c02
warn_on_branch_extend = options.warn warn_on_branch_extend = options.warn
print_summary = options.verbose > 0 # no options set print_summary = options.verbose > 0 # no options set
print_loaded_files = options.verbose > 1 # v print_loaded_files = options.verbose > 1 # v
print_pass = options.verbose > 2 # dd print_pass = options.verbose > 2 # dd
print_ir = options.verbose > 3 # ddd print_ir = options.verbose > 3 # ddd
print_labels = options.verbose > 4 # dddd print_labels = options.verbose > 4 # dddd

View File

@ -10,46 +10,52 @@ import Ophis.IR as IR
import Ophis.Frontend as FE import Ophis.Frontend as FE
import Ophis.Errors as Err import Ophis.Errors as Err
loadedfiles={} loadedfiles = {}
basecharmap = "".join([chr(x) for x in range(256)]) basecharmap = "".join([chr(x) for x in range(256)])
currentcharmap = basecharmap currentcharmap = basecharmap
def reset(): def reset():
global loadedfiles, currentcharmap, basecharmap global loadedfiles, currentcharmap, basecharmap
loadedfiles={} loadedfiles = {}
currentcharmap = basecharmap currentcharmap = basecharmap
def pragmaInclude(ppt, line, result): def pragmaInclude(ppt, line, result):
"Includes a source file" "Includes a source file"
filename = line.expect("STRING").value filename = line.expect("STRING").value
line.expect("EOL") line.expect("EOL")
if type(filename)==str: result.append(FE.parse_file(ppt, filename)) if type(filename) == str:
result.append(FE.parse_file(ppt, filename))
def pragmaRequire(ppt, line, result): def pragmaRequire(ppt, line, result):
"Includes a source file at most one time" "Includes a source file at most one time"
filename = line.expect("STRING").value filename = line.expect("STRING").value
line.expect("EOL") line.expect("EOL")
if type(filename)==str: if type(filename) == str:
global loadedfiles global loadedfiles
if filename not in loadedfiles: if filename not in loadedfiles:
loadedfiles[filename]=1 loadedfiles[filename] = True
result.append(FE.parse_file(ppt, filename)) result.append(FE.parse_file(ppt, filename))
def pragmaIncbin(ppt, line, result): def pragmaIncbin(ppt, line, result):
"Includes a binary file" "Includes a binary file"
filename = line.expect("STRING").value filename = line.expect("STRING").value
line.expect("EOL") line.expect("EOL")
if type(filename)==str: if type(filename) == str:
try: try:
f = file(filename, "rb") f = file(filename, "rb")
bytes = f.read() bytes = f.read()
f.close() f.close()
except IOError: except IOError:
Err.log ("Could not read "+filename) Err.log("Could not read " + filename)
return return
bytes = [IR.ConstantExpr(ord(x)) for x in bytes] bytes = [IR.ConstantExpr(ord(x)) for x in bytes]
result.append(IR.Node(ppt, "Byte", *bytes)) result.append(IR.Node(ppt, "Byte", *bytes))
def pragmaCharmap(ppt, line, result): def pragmaCharmap(ppt, line, result):
"Modify the character map." "Modify the character map."
global currentcharmap, basecharmap global currentcharmap, basecharmap
@ -60,30 +66,33 @@ def pragmaCharmap(ppt, line, result):
try: try:
base = bytes[0].data base = bytes[0].data
newsubstr = "".join([chr(x.data) for x in bytes[1:]]) newsubstr = "".join([chr(x.data) for x in bytes[1:]])
currentcharmap = currentcharmap[:base] + newsubstr + currentcharmap[base+len(newsubstr):] currentcharmap = currentcharmap[:base] + newsubstr + \
currentcharmap[base + len(newsubstr):]
if len(currentcharmap) != 256 or base < 0 or base > 255: if len(currentcharmap) != 256 or base < 0 or base > 255:
Err.log("Charmap replacement out of range") Err.log("Charmap replacement out of range")
currentcharmap = currentcharmap[:256] currentcharmap = currentcharmap[:256]
except ValueError: except ValueError:
Err.log("Illegal character in .charmap directive") Err.log("Illegal character in .charmap directive")
def pragmaCharmapbin(ppt, line, result): def pragmaCharmapbin(ppt, line, result):
"Load a new character map from a file" "Load a new character map from a file"
global currentcharmap global currentcharmap
filename = line.expect("STRING").value filename = line.expect("STRING").value
line.expect("EOL") line.expect("EOL")
if type(filename)==str: if type(filename) == str:
try: try:
f = file(filename, "rb") f = file(filename, "rb")
bytes = f.read() bytes = f.read()
f.close() f.close()
except IOError: except IOError:
Err.log ("Could not read "+filename) Err.log("Could not read " + filename)
return return
if len(bytes)==256: if len(bytes) == 256:
currentcharmap = bytes currentcharmap = bytes
else: else:
Err.log("Character map "+filename+" not 256 bytes long") Err.log("Character map " + filename + " not 256 bytes long")
def pragmaOrg(ppt, line, result): def pragmaOrg(ppt, line, result):
"Relocates the PC with no output" "Relocates the PC with no output"
@ -91,6 +100,7 @@ def pragmaOrg(ppt, line, result):
line.expect("EOL") line.expect("EOL")
result.append(IR.Node(ppt, "SetPC", newPC)) result.append(IR.Node(ppt, "SetPC", newPC))
def pragmaAdvance(ppt, line, result): def pragmaAdvance(ppt, line, result):
"Outputs filler until reaching the target PC" "Outputs filler until reaching the target PC"
newPC = FE.parse_expr(line) newPC = FE.parse_expr(line)
@ -102,25 +112,31 @@ def pragmaAdvance(ppt, line, result):
line.expect("EOL") line.expect("EOL")
result.append(IR.Node(ppt, "Advance", newPC, fillexpr)) result.append(IR.Node(ppt, "Advance", newPC, fillexpr))
def pragmaCheckpc(ppt, line, result): def pragmaCheckpc(ppt, line, result):
"Enforces that the PC has not exceeded a certain point" "Enforces that the PC has not exceeded a certain point"
target = FE.parse_expr(line) target = FE.parse_expr(line)
line.expect("EOL") line.expect("EOL")
result.append(IR.Node(ppt, "CheckPC", target)) result.append(IR.Node(ppt, "CheckPC", target))
def pragmaAlias(ppt, line, result): def pragmaAlias(ppt, line, result):
"Assigns an arbitrary label" "Assigns an arbitrary label"
lbl = line.expect("LABEL").value lbl = line.expect("LABEL").value
target = FE.parse_expr(line) target = FE.parse_expr(line)
result.append(IR.Node(ppt, "Label", lbl, target)) result.append(IR.Node(ppt, "Label", lbl, target))
def pragmaSpace(ppt, line, result): def pragmaSpace(ppt, line, result):
"Reserves space in a data segment for a variable" "Reserves space in a data segment for a variable"
lbl = line.expect("LABEL").value lbl = line.expect("LABEL").value
size = line.expect("NUM").value size = line.expect("NUM").value
line.expect("EOL") line.expect("EOL")
result.append(IR.Node(ppt, "Label", lbl, IR.PCExpr())) result.append(IR.Node(ppt, "Label", lbl, IR.PCExpr()))
result.append(IR.Node(ppt, "SetPC", IR.SequenceExpr([IR.PCExpr(), "+", IR.ConstantExpr(size)]))) result.append(IR.Node(ppt, "SetPC",
IR.SequenceExpr([IR.PCExpr(), "+",
IR.ConstantExpr(size)])))
def pragmaText(ppt, line, result): def pragmaText(ppt, line, result):
"Switches to a text segment" "Switches to a text segment"
@ -132,6 +148,7 @@ def pragmaText(ppt, line, result):
segment = "*text-default*" segment = "*text-default*"
result.append(IR.Node(ppt, "TextSegment", segment)) result.append(IR.Node(ppt, "TextSegment", segment))
def pragmaData(ppt, line, result): def pragmaData(ppt, line, result):
"Switches to a data segment (no output allowed)" "Switches to a data segment (no output allowed)"
next = line.expect("LABEL", "EOL") next = line.expect("LABEL", "EOL")
@ -142,67 +159,80 @@ def pragmaData(ppt, line, result):
segment = "*data-default*" segment = "*data-default*"
result.append(IR.Node(ppt, "DataSegment", segment)) result.append(IR.Node(ppt, "DataSegment", segment))
def readData(line): def readData(line):
"Read raw data from a comma-separated list" "Read raw data from a comma-separated list"
if line.lookahead(0).type == "STRING": if line.lookahead(0).type == "STRING":
data = [IR.ConstantExpr(ord(x)) for x in line.expect("STRING").value.translate(currentcharmap)] data = [IR.ConstantExpr(ord(x))
for x in line.expect("STRING").value.translate(currentcharmap)]
else: else:
data = [FE.parse_expr(line)] data = [FE.parse_expr(line)]
next = line.expect(',', 'EOL').type next = line.expect(',', 'EOL').type
while next == ',': while next == ',':
if line.lookahead(0).type == "STRING": if line.lookahead(0).type == "STRING":
data.extend([IR.ConstantExpr(ord(x)) for x in line.expect("STRING").value]) data.extend([IR.ConstantExpr(ord(x))
for x in line.expect("STRING").value])
else: else:
data.append(FE.parse_expr(line)) data.append(FE.parse_expr(line))
next = line.expect(',', 'EOL').type next = line.expect(',', 'EOL').type
return data return data
def pragmaByte(ppt, line, result): def pragmaByte(ppt, line, result):
"Raw data, a byte at a time" "Raw data, a byte at a time"
bytes = readData(line) bytes = readData(line)
result.append(IR.Node(ppt, "Byte", *bytes)) result.append(IR.Node(ppt, "Byte", *bytes))
def pragmaWord(ppt, line, result): def pragmaWord(ppt, line, result):
"Raw data, a word at a time, little-endian" "Raw data, a word at a time, little-endian"
words = readData(line) words = readData(line)
result.append(IR.Node(ppt, "Word", *words)) result.append(IR.Node(ppt, "Word", *words))
def pragmaDword(ppt, line, result): def pragmaDword(ppt, line, result):
"Raw data, a double-word at a time, little-endian" "Raw data, a double-word at a time, little-endian"
dwords = readData(line) dwords = readData(line)
result.append(IR.Node(ppt, "Dword", *dwords)) result.append(IR.Node(ppt, "Dword", *dwords))
def pragmaWordbe(ppt, line, result): def pragmaWordbe(ppt, line, result):
"Raw data, a word at a time, big-endian" "Raw data, a word at a time, big-endian"
words = readData(line) words = readData(line)
result.append(IR.Node(ppt, "WordBE", *words)) result.append(IR.Node(ppt, "WordBE", *words))
def pragmaDwordbe(ppt, line, result): def pragmaDwordbe(ppt, line, result):
"Raw data, a dword at a time, big-endian" "Raw data, a dword at a time, big-endian"
dwords = readData(line) dwords = readData(line)
result.append(IR.Node(ppt, "DwordBE", *dwords)) result.append(IR.Node(ppt, "DwordBE", *dwords))
def pragmaScope(ppt, line, result): def pragmaScope(ppt, line, result):
"Create a new lexical scoping block" "Create a new lexical scoping block"
line.expect("EOL") line.expect("EOL")
result.append(IR.Node(ppt, "ScopeBegin")) result.append(IR.Node(ppt, "ScopeBegin"))
def pragmaScend(ppt, line, result): def pragmaScend(ppt, line, result):
"End the innermost lexical scoping block" "End the innermost lexical scoping block"
line.expect("EOL") line.expect("EOL")
result.append(IR.Node(ppt, "ScopeEnd")) result.append(IR.Node(ppt, "ScopeEnd"))
def pragmaMacro(ppt, line, result): def pragmaMacro(ppt, line, result):
"Begin a macro definition" "Begin a macro definition"
lbl = line.expect("LABEL").value lbl = line.expect("LABEL").value
line.expect("EOL") line.expect("EOL")
result.append(IR.Node(ppt, "MacroBegin", lbl)) result.append(IR.Node(ppt, "MacroBegin", lbl))
def pragmaMacend(ppt, line, result): def pragmaMacend(ppt, line, result):
"End a macro definition" "End a macro definition"
line.expect("EOL") line.expect("EOL")
result.append(IR.Node(ppt, "MacroEnd")) result.append(IR.Node(ppt, "MacroEnd"))
def pragmaInvoke(ppt, line, result): def pragmaInvoke(ppt, line, result):
macro = line.expect("LABEL").value macro = line.expect("LABEL").value
if line.lookahead(0).type == "EOL": if line.lookahead(0).type == "EOL":

View File

@ -9,6 +9,7 @@
import Ophis.Errors as Err import Ophis.Errors as Err
class Environment(object): class Environment(object):
"""Environment class. """Environment class.
Controls the various scopes and global abstract execution variables.""" Controls the various scopes and global abstract execution variables."""
@ -19,39 +20,52 @@ class Environment(object):
self.segmentdict = {} self.segmentdict = {}
self.segment = "*text-default*" self.segment = "*text-default*"
self.scopecount = 0 self.scopecount = 0
def __contains__(self, item): def __contains__(self, item):
if item[0] == '_': if item[0] == '_':
for dict in [self.dicts[i] for i in self.stack]: for dict in [self.dicts[i] for i in self.stack]:
if item in dict: return 1 if item in dict:
return 0 return True
return False
return item in self.dicts[0] return item in self.dicts[0]
def __getitem__(self, item): def __getitem__(self, item):
if item[0] == '_': if item[0] == '_':
for dict in [self.dicts[i] for i in self.stack]: for dict in [self.dicts[i] for i in self.stack]:
if item in dict: return dict[item] if item in dict:
return dict[item]
else: else:
if item in self.dicts[0]: return self.dicts[0][item] if item in self.dicts[0]:
return self.dicts[0][item]
Err.log("Unknown label '%s'" % item) Err.log("Unknown label '%s'" % item)
return 0 return 0
def __setitem__(self, item, value): def __setitem__(self, item, value):
if item[0] == '_': if item[0] == '_':
self.dicts[self.stack[0]][item] = value self.dicts[self.stack[0]][item] = value
else: else:
self.dicts[0][item] = value self.dicts[0][item] = value
def __str__(self): def __str__(self):
return str(self.dicts) return str(self.dicts)
def getPC(self): def getPC(self):
return self.pc return self.pc
def setPC(self, value): def setPC(self, value):
self.pc = value self.pc = value
def incPC(self, amount): def incPC(self, amount):
self.pc += amount self.pc += amount
def getsegment(self): def getsegment(self):
return self.segment return self.segment
def setsegment(self, segment): def setsegment(self, segment):
self.segmentdict[self.segment] = self.pc self.segmentdict[self.segment] = self.pc
self.segment = segment self.segment = segment
self.pc = self.segmentdict.get(segment, 0) self.pc = self.segmentdict.get(segment, 0)
def reset(self): def reset(self):
"Clears out program counter, segment, and scoping information" "Clears out program counter, segment, and scoping information"
self.pc = 0 self.pc = 0
@ -61,14 +75,16 @@ class Environment(object):
if len(self.stack) > 1: if len(self.stack) > 1:
Err.log("Unmatched .scope") Err.log("Unmatched .scope")
self.stack = [0] self.stack = [0]
def newscope(self): def newscope(self):
"Enters a new scope for temporary labels." "Enters a new scope for temporary labels."
self.scopecount += 1 self.scopecount += 1
self.stack.insert(0, self.scopecount) self.stack.insert(0, self.scopecount)
if len(self.dicts) <= self.scopecount: self.dicts.append({}) if len(self.dicts) <= self.scopecount:
self.dicts.append({})
def endscope(self): def endscope(self):
"Leaves a scope." "Leaves a scope."
if len(self.stack) == 1: if len(self.stack) == 1:
Err.log("Unmatched .scend") Err.log("Unmatched .scend")
self.stack.pop(0) self.stack.pop(0)

View File

@ -12,15 +12,20 @@ import sys
count = 0 count = 0
currentpoint = "<Top Level>" currentpoint = "<Top Level>"
def log(err): def log(err):
"""Reports an error at the current program point, and increases """Reports an error at the current program point, and increases
the global error count.""" the global error count."""
global count global count
count = count+1 count = count + 1
print>>sys.stderr, currentpoint+": "+err print>>sys.stderr, currentpoint + ": " + err
def report(): def report():
"Print out the number of errors." "Print out the number of errors."
if count == 0: print>>sys.stderr, "No errors" if count == 0:
elif count == 1: print>>sys.stderr, "1 error" print>>sys.stderr, "No errors"
else: print>>sys.stderr, str(count)+" errors" elif count == 1:
print>>sys.stderr, "1 error"
else:
print>>sys.stderr, str(count) + " errors"

View File

@ -13,35 +13,44 @@ import os
# You may use, modify, and distribute this file under the MIT # You may use, modify, and distribute this file under the MIT
# license: See README for details. # license: See README for details.
class Lexeme(object): class Lexeme(object):
"Class for lexer tokens. Used by lexer and parser." "Class for lexer tokens. Used by lexer and parser."
def __init__(self, type="UNKNOWN", value=None): def __init__(self, type="UNKNOWN", value=None):
self.type = type.upper() self.type = type.upper()
self.value = value self.value = value
def __str__(self): def __str__(self):
if self.value == None: if self.value is None:
return self.type return self.type
else: else:
return self.type+":"+str(self.value) return self.type + ":" + str(self.value)
def __repr__(self): def __repr__(self):
return "Lexeme("+`self.type`+", "+`self.value`+")" return "Lexeme(" + repr(self.type) + ", " + repr(self.value) + ")"
def matches(self, other): def matches(self, other):
"1 if Lexemes a and b have the same type." "1 if Lexemes a and b have the same type."
return self.type == other.type return self.type == other.type
bases = {"$":("hexadecimal", 16),
"%":("binary", 2), bases = {"$": ("hexadecimal", 16),
"0":("octal", 8)} "%": ("binary", 2),
"0": ("octal", 8)}
punctuation = "#,`<>():.+-*/&|^[]" punctuation = "#,`<>():.+-*/&|^[]"
def lex(point, line): def lex(point, line):
"""Turns a line of source into a sequence of lexemes.""" """Turns a line of source into a sequence of lexemes."""
Err.currentpoint = point Err.currentpoint = point
result = [] result = []
def is_opcode(op): def is_opcode(op):
"Tests whether a string is an opcode or an identifier" "Tests whether a string is an opcode or an identifier"
return op in Ops.opcodes return op in Ops.opcodes
def add_token(token): def add_token(token):
"Converts a substring into a single lexeme" "Converts a substring into a single lexeme"
if token == "": if token == "":
@ -59,7 +68,8 @@ def lex(point, line):
result.append(Lexeme("NUM", long(rest, bases[firstchar][1]))) result.append(Lexeme("NUM", long(rest, bases[firstchar][1])))
return return
except ValueError: except ValueError:
Err.log('Invalid '+bases[firstchar][0]+' constant: '+rest) Err.log('Invalid ' + bases[firstchar][0] + ' constant: ' +
rest)
result.append(Lexeme("NUM", 0)) result.append(Lexeme("NUM", 0))
return return
elif firstchar.isdigit(): elif firstchar.isdigit():
@ -73,12 +83,12 @@ def lex(point, line):
if len(rest) == 1: if len(rest) == 1:
result.append(Lexeme("NUM", ord(rest))) result.append(Lexeme("NUM", ord(rest)))
else: else:
Err.log("Invalid character constant '"+rest+"'") Err.log("Invalid character constant '" + rest + "'")
result.append(Lexeme("NUM", 0)) result.append(Lexeme("NUM", 0))
return return
elif firstchar in punctuation: elif firstchar in punctuation:
if rest != "": if rest != "":
Err.log("Internal lexer error! '"+token+"' can't happen!") Err.log("Internal lexer error! '" + token + "' can't happen!")
result.append(Lexeme(firstchar)) result.append(Lexeme(firstchar))
return return
else: # Label, opcode, or index register else: # Label, opcode, or index register
@ -94,22 +104,24 @@ def lex(point, line):
return return
# should never reach here # should never reach here
Err.log("Internal lexer error: add_token fall-through") Err.log("Internal lexer error: add_token fall-through")
def add_EOL(): def add_EOL():
"Adds an end-of-line lexeme" "Adds an end-of-line lexeme"
result.append(Lexeme("EOL")) result.append(Lexeme("EOL"))
# Actual routine begins here # Actual routine begins here
value = "" value = ""
quotemode = 0 quotemode = False
backslashmode = 0 backslashmode = False
for c in line.strip(): for c in line.strip():
if backslashmode: if backslashmode:
backslashmode = 0 backslashmode = False
value = value + c value = value + c
elif c == "\\": elif c == "\\":
backslashmode = 1 backslashmode = True
elif quotemode: elif quotemode:
if c == '"': if c == '"':
quotemode = 0 quotemode = False
else: else:
value = value + c value = value + c
elif c == ';': elif c == ';':
@ -126,7 +138,7 @@ def lex(point, line):
elif c == '"': elif c == '"':
add_token(value) add_token(value)
value = '"' value = '"'
quotemode = 1 quotemode = True
else: else:
value = value + c value = value + c
if backslashmode: if backslashmode:
@ -137,35 +149,45 @@ def lex(point, line):
add_EOL() add_EOL()
return result return result
class ParseLine(object): class ParseLine(object):
"Maintains the parse state of a line of code. Enables arbitrary lookahead." "Maintains the parse state of a line of code. Enables arbitrary lookahead."
def __init__(self, lexemes): def __init__(self, lexemes):
self.lexemes = lexemes self.lexemes = lexemes
self.location = 0 self.location = 0
def lookahead(self, i): def lookahead(self, i):
"""Returns the token i units ahead in the parse. """Returns the token i units ahead in the parse.
lookahead(0) returns the next token; trying to read off the end of lookahead(0) returns the next token; trying to read off the end of
the sequence returns the last token in the sequence (usually EOL).""" the sequence returns the last token in the sequence (usually EOL)."""
target = self.location+i target = self.location + i
if target >= len(self.lexemes): target = -1 if target >= len(self.lexemes):
target = -1
return self.lexemes[target] return self.lexemes[target]
def pop(self): def pop(self):
"Returns and removes the next element in the line." "Returns and removes the next element in the line."
old = self.location old = self.location
if self.location < len(self.lexemes)-1: self.location += 1 if self.location < len(self.lexemes) - 1:
self.location += 1
return self.lexemes[old] return self.lexemes[old]
def expect(self, *tokens): def expect(self, *tokens):
"""Reads a token from the ParseLine line and returns it if it's of a type """Reads a token from the ParseLine line and returns it if it's of a
in the sequence tokens. Otherwise, it logs an error.""" type in the sequence tokens. Otherwise, it logs an error."""
token = self.pop() token = self.pop()
if token.type not in tokens: if token.type not in tokens:
Err.log('Expected: "'+'", "'.join(tokens)+'"') Err.log('Expected: "' + '", "'.join(tokens) + '"')
return token return token
pragma_modules = [] pragma_modules = []
def parse_expr(line): def parse_expr(line):
"Parses an Ophis arithmetic expression." "Parses an Ophis arithmetic expression."
def atom(): def atom():
"Parses lowest-priority expression components." "Parses lowest-priority expression components."
next = line.lookahead(0).type next = line.lookahead(0).type
@ -187,14 +209,14 @@ def parse_expr(line):
offset += 1 offset += 1
line.expect("+") line.expect("+")
next = line.lookahead(0).type next = line.lookahead(0).type
return IR.LabelExpr("*"+str(templabelcount+offset)) return IR.LabelExpr("*" + str(templabelcount + offset))
elif next == "-": elif next == "-":
offset = 1 offset = 1
while next == "-": while next == "-":
offset -= 1 offset -= 1
line.expect("-") line.expect("-")
next = line.lookahead(0).type next = line.lookahead(0).type
return IR.LabelExpr("*"+str(templabelcount+offset)) return IR.LabelExpr("*" + str(templabelcount + offset))
elif next == ">": elif next == ">":
line.expect(">") line.expect(">")
return IR.HighByteExpr(atom()) return IR.HighByteExpr(atom())
@ -203,6 +225,7 @@ def parse_expr(line):
return IR.LowByteExpr(atom()) return IR.LowByteExpr(atom())
else: else:
Err.log('Expected: expression') Err.log('Expected: expression')
def precedence_read(constructor, reader, separators): def precedence_read(constructor, reader, separators):
"""Handles precedence. The reader argument is a function that returns """Handles precedence. The reader argument is a function that returns
expressions that bind more tightly than these; separators is a list expressions that bind more tightly than these; separators is a list
@ -218,51 +241,60 @@ def parse_expr(line):
result.append(nextop) result.append(nextop)
result.append(reader()) result.append(reader())
nextop = line.lookahead(0).type nextop = line.lookahead(0).type
if len(result) == 1: return result[0] if len(result) == 1:
return result[0]
return constructor(result) return constructor(result)
def term(): def term():
"Parses * and /" "Parses * and /"
return precedence_read(IR.SequenceExpr, atom, ["*", "/"]) return precedence_read(IR.SequenceExpr, atom, ["*", "/"])
def arith(): def arith():
"Parses + and -" "Parses + and -"
return precedence_read(IR.SequenceExpr, term, ["+", "-"]) return precedence_read(IR.SequenceExpr, term, ["+", "-"])
def bits(): def bits():
"Parses &, |, and ^" "Parses &, |, and ^"
return precedence_read(IR.SequenceExpr, arith, ["&", "|", "^"]) return precedence_read(IR.SequenceExpr, arith, ["&", "|", "^"])
return bits() return bits()
def parse_line(ppt, lexemelist): def parse_line(ppt, lexemelist):
"Turn a line of source into an IR Node." "Turn a line of source into an IR Node."
Err.currentpoint = ppt Err.currentpoint = ppt
result = [] result = []
line = ParseLine(lexemelist) line = ParseLine(lexemelist)
def aux(): def aux():
"Accumulates all IR nodes defined by this line." "Accumulates all IR nodes defined by this line."
if line.lookahead(0).type == "EOL": if line.lookahead(0).type == "EOL":
pass pass
elif line.lookahead(1).type == ":": elif line.lookahead(1).type == ":":
newlabel=line.expect("LABEL").value newlabel = line.expect("LABEL").value
line.expect(":") line.expect(":")
result.append(IR.Node(ppt, "Label", newlabel, IR.PCExpr())) result.append(IR.Node(ppt, "Label", newlabel, IR.PCExpr()))
aux() aux()
elif line.lookahead(0).type == "*": elif line.lookahead(0).type == "*":
global templabelcount global templabelcount
templabelcount = templabelcount + 1 templabelcount = templabelcount + 1
result.append(IR.Node(ppt, "Label", "*"+str(templabelcount), IR.PCExpr())) result.append(IR.Node(ppt, "Label", "*" + str(templabelcount),
IR.PCExpr()))
line.expect("*") line.expect("*")
aux() aux()
elif line.lookahead(0).type == "." or line.lookahead(0).type == "`": elif line.lookahead(0).type == "." or line.lookahead(0).type == "`":
which = line.expect(".", "`").type which = line.expect(".", "`").type
if (which == "."): pragma = line.expect("LABEL").value if (which == "."):
else: pragma = "invoke" pragma = line.expect("LABEL").value
pragmaFunction = "pragma"+pragma.title() else:
pragma = "invoke"
pragmaFunction = "pragma" + pragma.title()
for mod in pragma_modules: for mod in pragma_modules:
if hasattr(mod, pragmaFunction): if hasattr(mod, pragmaFunction):
getattr(mod, pragmaFunction)(ppt, line, result) getattr(mod, pragmaFunction)(ppt, line, result)
break break
else: else:
Err.log("Unknown pragma "+pragma) Err.log("Unknown pragma " + pragma)
else: # Instruction else: # Instruction
opcode = line.expect("OPCODE").value opcode = line.expect("OPCODE").value
if line.lookahead(0).type == "#": if line.lookahead(0).type == "#":
@ -296,23 +328,30 @@ def parse_line(ppt, lexemelist):
tok = line.expect("EOL", ",").type tok = line.expect("EOL", ",").type
if tok == ",": if tok == ",":
tok = line.expect("X", "Y").type tok = line.expect("X", "Y").type
if tok == "X": mode = "MemoryX" if tok == "X":
else: mode = "MemoryY" mode = "MemoryX"
else:
mode = "MemoryY"
line.expect("EOL") line.expect("EOL")
else: mode = "Memory" else:
mode = "Memory"
result.append(IR.Node(ppt, mode, opcode, arg)) result.append(IR.Node(ppt, mode, opcode, arg))
aux() aux()
result = [node for node in result if node is not IR.NullNode] result = [node for node in result if node is not IR.NullNode]
if len(result) == 0: return IR.NullNode if len(result) == 0:
if len(result) == 1: return result[0] return IR.NullNode
if len(result) == 1:
return result[0]
return IR.SequenceNode(ppt, result) return IR.SequenceNode(ppt, result)
def parse_file(ppt, filename): def parse_file(ppt, filename):
"Loads an Ophis source file, and returns an IR list." "Loads an Ophis source file, and returns an IR list."
Err.currentpoint = ppt Err.currentpoint = ppt
if Cmd.print_loaded_files: if Cmd.print_loaded_files:
if filename != '-': if filename != '-':
print>>sys.stderr, "Loading "+filename print>>sys.stderr, "Loading " + filename
else: else:
print>>sys.stderr, "Loading from standard input" print>>sys.stderr, "Loading from standard input"
try: try:
@ -322,18 +361,19 @@ def parse_file(ppt, filename):
f.close() f.close()
else: else:
linelist = sys.stdin.readlines() linelist = sys.stdin.readlines()
pptlist = ["%s:%d" % (filename, i+1) for i in range(len(linelist))] pptlist = ["%s:%d" % (filename, i + 1) for i in range(len(linelist))]
lexlist = map(lex, pptlist, linelist) lexlist = map(lex, pptlist, linelist)
IRlist = map(parse_line, pptlist, lexlist) IRlist = map(parse_line, pptlist, lexlist)
IRlist = [node for node in IRlist if node is not IR.NullNode] IRlist = [node for node in IRlist if node is not IR.NullNode]
return IR.SequenceNode(ppt, IRlist) return IR.SequenceNode(ppt, IRlist)
except IOError: except IOError:
Err.log ("Could not read "+filename) Err.log("Could not read " + filename)
return IR.NullNode return IR.NullNode
def parse(filename): def parse(filename):
"Top level parsing routine, taking a source file name and returning an IR list." """Top level parsing routine, taking a source file name
and returning an IR list."""
global templabelcount global templabelcount
templabelcount = 0 templabelcount = 0
return parse_file("<Top Level>", filename) return parse_file("<Top Level>", filename)

View File

@ -9,6 +9,7 @@
import Ophis.Errors as Err import Ophis.Errors as Err
class Node(object): class Node(object):
"""The default IR Node """The default IR Node
Instances of Node always have the three fields ppt(Program Point), Instances of Node always have the three fields ppt(Program Point),
@ -17,27 +18,35 @@ class Node(object):
self.ppt = ppt self.ppt = ppt
self.nodetype = nodetype self.nodetype = nodetype
self.data = list(data) self.data = list(data)
def accept(self, asmpass, env=None): def accept(self, asmpass, env=None):
"""Implements the Visitor pattern for an assembler pass. """Implements the Visitor pattern for an assembler pass.
Calls the routine 'asmpass.visitTYPE(self, env)' where Calls the routine 'asmpass.visitTYPE(self, env)' where
TYPE is the value of self.nodetype.""" TYPE is the value of self.nodetype."""
Err.currentpoint = self.ppt Err.currentpoint = self.ppt
routine = getattr(asmpass, "visit"+self.nodetype, asmpass.visitUnknown) routine = getattr(asmpass, "visit" + self.nodetype,
asmpass.visitUnknown)
routine(self, env) routine(self, env)
def __str__(self): def __str__(self):
if self.nodetype != "SEQUENCE": if self.nodetype != "SEQUENCE":
return str(self.ppt)+": "+self.nodetype+" - "+" ".join(map(str, self.data)) return str(self.ppt) + ": " + self.nodetype + " - " + \
" ".join(map(str, self.data))
else: else:
return "\n".join(map(str, self.data)) return "\n".join(map(str, self.data))
def __repr__(self): def __repr__(self):
args = [self.ppt, self.nodetype] + self.data args = [self.ppt, self.nodetype] + self.data
return "Node(" + ", ".join(map(repr, args)) + ")" return "Node(" + ", ".join(map(repr, args)) + ")"
NullNode = Node("<none>", "None") NullNode = Node("<none>", "None")
def SequenceNode(ppt, nodelist): def SequenceNode(ppt, nodelist):
return Node(ppt, "SEQUENCE", *nodelist) return Node(ppt, "SEQUENCE", *nodelist)
class Expr(object): class Expr(object):
"""Base class for Ophis expressions """Base class for Ophis expressions
All expressions have a field called "data" and a boolean field All expressions have a field called "data" and a boolean field
@ -45,78 +54,102 @@ class Expr(object):
symbolic values in it.""" symbolic values in it."""
def __init__(self, data): def __init__(self, data):
self.data = data self.data = data
self.hardcoded = 0 self.hardcoded = False
def __str__(self): def __str__(self):
return "<UNKNOWN: "+`self.data`+">" return "<UNKNOWN: " + repr(self.data) + ">"
def valid(self, env=None, PCvalid=0):
def valid(self, env=None, PCvalid=False):
"""Returns true if the the expression can be successfully """Returns true if the the expression can be successfully
evaluated in the specified environment.""" evaluated in the specified environment."""
return 0 return False
def value(self, env=None): def value(self, env=None):
"Evaluates this expression in the given environment." "Evaluates this expression in the given environment."
return None return None
class ConstantExpr(Expr): class ConstantExpr(Expr):
"Represents a numeric constant" "Represents a numeric constant"
def __init__(self, data): def __init__(self, data):
self.data = data self.data = data
self.hardcoded = 1 self.hardcoded = True
def __str__(self): def __str__(self):
return str(self.data) return str(self.data)
def valid(self, env=None, PCvalid=0):
return 1 def valid(self, env=None, PCvalid=False):
return True
def value(self, env=None): def value(self, env=None):
return self.data return self.data
class LabelExpr(Expr): class LabelExpr(Expr):
"Represents a symbolic constant" "Represents a symbolic constant"
def __init__(self, data): def __init__(self, data):
self.data = data self.data = data
self.hardcoded = 0 self.hardcoded = False
def __str__(self): def __str__(self):
return self.data return self.data
def valid(self, env=None, PCvalid=0):
def valid(self, env=None, PCvalid=False):
return (env is not None) and self.data in env return (env is not None) and self.data in env
def value(self, env=None): def value(self, env=None):
return env[self.data] return env[self.data]
class PCExpr(Expr): class PCExpr(Expr):
"Represents the current program counter: ^" "Represents the current program counter: ^"
def __init__(self): def __init__(self):
self.hardcoded = 0 self.hardcoded = False
def __str__(self): def __str__(self):
return "^" return "^"
def valid(self, env=None, PCvalid=0):
def valid(self, env=None, PCvalid=False):
return env is not None and PCvalid return env is not None and PCvalid
def value(self, env=None): def value(self, env=None):
return env.getPC() return env.getPC()
class HighByteExpr(Expr): class HighByteExpr(Expr):
"Represents the expression >{data}" "Represents the expression >{data}"
def __init__(self, data): def __init__(self, data):
self.data = data self.data = data
self.hardcoded = data.hardcoded self.hardcoded = data.hardcoded
def __str__(self): def __str__(self):
return ">"+str(self.data) return ">" + str(self.data)
def valid(self, env=None, PCvalid=0):
def valid(self, env=None, PCvalid=False):
return self.data.valid(env, PCvalid) return self.data.valid(env, PCvalid)
def value(self, env=None): def value(self, env=None):
val = self.data.value(env) val = self.data.value(env)
return (val >> 8) & 0xff return (val >> 8) & 0xff
class LowByteExpr(Expr): class LowByteExpr(Expr):
"Represents the expression <{data}" "Represents the expression <{data}"
def __init__(self, data): def __init__(self, data):
self.data = data self.data = data
self.hardcoded = data.hardcoded self.hardcoded = data.hardcoded
def __str__(self): def __str__(self):
return "<"+str(self.data) return "<" + str(self.data)
def valid(self, env=None, PCvalid=0):
def valid(self, env=None, PCvalid=False):
return self.data.valid(env, PCvalid) return self.data.valid(env, PCvalid)
def value(self, env=None): def value(self, env=None):
val = self.data.value(env) val = self.data.value(env)
return val & 0xff return val & 0xff
class SequenceExpr(Expr): class SequenceExpr(Expr):
"""Represents an interleaving of operands (of type Expr) and """Represents an interleaving of operands (of type Expr) and
operators (of type String). Subclasses must provide a routine operators (of type String). Subclasses must provide a routine
@ -128,20 +161,23 @@ class SequenceExpr(Expr):
[Expr, str, Expr, str, Expr, str, ... Expr, str, Expr].""" [Expr, str, Expr, str, Expr, str, ... Expr, str, Expr]."""
self.data = data self.data = data
self.operands = [x for x in data if isinstance(x, Expr)] self.operands = [x for x in data if isinstance(x, Expr)]
self.operators = [x for x in data if type(x)==str] self.operators = [x for x in data if type(x) == str]
for i in self.operands: for i in self.operands:
if not i.hardcoded: if not i.hardcoded:
self.hardcoded = 0 self.hardcoded = False
break break
else: else:
self.hardcoded = 1 self.hardcoded = True
def __str__(self): def __str__(self):
return "["+" ".join(map(str, self.data))+"]" return "[" + " ".join(map(str, self.data)) + "]"
def valid(self, env=None, PCvalid=0):
def valid(self, env=None, PCvalid=False):
for i in self.operands: for i in self.operands:
if not i.valid(env, PCvalid): if not i.valid(env, PCvalid):
return 0 return False
return 1 return True
def value(self, env=None): def value(self, env=None):
subs = map((lambda x: x.value(env)), self.operands) subs = map((lambda x: x.value(env)), self.operands)
result = subs[0] result = subs[0]
@ -150,11 +186,19 @@ class SequenceExpr(Expr):
result = self.operate(result, op, subs[index]) result = self.operate(result, op, subs[index])
index += 1 index += 1
return result return result
def operate(self, start, op, other): def operate(self, start, op, other):
if op=="*": return start * other if op == "*":
if op=="/": return start // other return start * other
if op=="+": return start + other if op == "/":
if op=="-": return start - other return start // other
if op=="&": return start & other if op == "+":
if op=="|": return start | other return start + other
if op=="^": return start ^ other if op == "-":
return start - other
if op == "&":
return start & other
if op == "|":
return start | other
if op == "^":
return start ^ other

View File

@ -18,6 +18,7 @@ macros = {}
currentname = None currentname = None
currentbody = None currentbody = None
def newMacro(name): def newMacro(name):
"Start creating a new macro with the specified name." "Start creating a new macro with the specified name."
global currentname global currentname
@ -31,10 +32,12 @@ def newMacro(name):
currentname = name currentname = name
currentbody = [] currentbody = []
def registerNode(node): def registerNode(node):
global currentbody global currentbody
currentbody.append(IR.Node(node.ppt, node.nodetype, *node.data)) currentbody.append(IR.Node(node.ppt, node.nodetype, *node.data))
def endMacro(): def endMacro():
global currentname global currentname
global currentbody global currentbody
@ -46,21 +49,29 @@ def endMacro():
currentname = None currentname = None
currentbody = None currentbody = None
def expandMacro(ppt, name, arglist): def expandMacro(ppt, name, arglist):
global macros global macros
if name not in macros: if name not in macros:
Err.log("Undefined macro '%s'" % name) Err.log("Undefined macro '%s'" % name)
return IR.NullNode return IR.NullNode
argexprs = [IR.Node(ppt, "Label", "_*%d" % i, arg) for (i, arg) in zip(xrange(1, sys.maxint), arglist)] argexprs = [IR.Node(ppt, "Label", "_*%d" % i, arg)
bindexprs = [IR.Node(ppt, "Label", "_%d" % i, IR.LabelExpr("_*%d" % i)) for i in range(1, len(arglist)+1)] for (i, arg) in zip(xrange(1, sys.maxint), arglist)]
body = [IR.Node("%s->%s" % (ppt, node.ppt), node.nodetype, *node.data) for node in macros[name]] bindexprs = [IR.Node(ppt, "Label", "_%d" % i, IR.LabelExpr("_*%d" % i))
invocation = [IR.Node(ppt, "ScopeBegin")] + argexprs + [IR.Node(ppt, "ScopeBegin")] + bindexprs + body + [IR.Node(ppt, "ScopeEnd"), IR.Node(ppt, "ScopeEnd")] for i in range(1, len(arglist) + 1)]
body = [IR.Node("%s->%s" % (ppt, node.ppt), node.nodetype, *node.data)
for node in macros[name]]
invocation = [IR.Node(ppt, "ScopeBegin")] + argexprs + \
[IR.Node(ppt, "ScopeBegin")] + bindexprs + body + \
[IR.Node(ppt, "ScopeEnd"), IR.Node(ppt, "ScopeEnd")]
return IR.SequenceNode(ppt, invocation) return IR.SequenceNode(ppt, invocation)
def dump(): def dump():
global macros global macros
for mac in macros: for mac in macros:
body = macros[mac] body = macros[mac]
print>>sys.stderr, "Macro: "+mac print>>sys.stderr, "Macro: " + mac
for node in body: print>>sys.stderr, node for node in body:
print>>sys.stderr, node
print>>sys.stderr, "" print>>sys.stderr, ""

View File

@ -17,6 +17,7 @@ import Ophis.Environment
import Ophis.CmdLine import Ophis.CmdLine
import Ophis.Opcodes import Ophis.Opcodes
def run_all(infile, outfile): def run_all(infile, outfile):
"Transforms the source infile to a binary outfile." "Transforms the source infile to a binary outfile."
Err.count = 0 Err.count = 0
@ -26,21 +27,31 @@ def run_all(infile, outfile):
m = Ophis.Passes.ExpandMacros() m = Ophis.Passes.ExpandMacros()
i = Ophis.Passes.InitLabels() i = Ophis.Passes.InitLabels()
l_basic = Ophis.Passes.UpdateLabels() l_basic = Ophis.Passes.UpdateLabels()
l = Ophis.Passes.FixPoint("label update", [l_basic], lambda: l_basic.changed == 0) l = Ophis.Passes.FixPoint("label update", [l_basic],
lambda: not l_basic.changed)
c_basic = Ophis.Passes.Collapse() c_basic = Ophis.Passes.Collapse()
c = Ophis.Passes.FixPoint("instruction selection 1", [l, c_basic], lambda: c_basic.collapsed == 0) c = Ophis.Passes.FixPoint("instruction selection 1", [l, c_basic],
lambda: not c_basic.changed)
b = Ophis.Passes.ExtendBranches() b = Ophis.Passes.ExtendBranches()
a = Ophis.Passes.Assembler() a = Ophis.Passes.Assembler()
passes = [] passes = []
passes.append(Ophis.Passes.DefineMacros()) passes.append(Ophis.Passes.DefineMacros())
passes.append(Ophis.Passes.FixPoint("macro expansion", [m], lambda: m.changed == 0)) passes.append(Ophis.Passes.FixPoint("macro expansion", [m],
passes.append(Ophis.Passes.FixPoint("label initialization", [i], lambda: i.changed == 0)) lambda: not m.changed))
passes.extend([Ophis.Passes.CircularityCheck(), Ophis.Passes.CheckExprs(), Ophis.Passes.EasyModes()]) passes.append(Ophis.Passes.FixPoint("label initialization", [i],
passes.append(Ophis.Passes.FixPoint("instruction selection 2", [c, b], lambda: b.expanded == 0)) lambda: not i.changed))
passes.extend([Ophis.Passes.NormalizeModes(), Ophis.Passes.UpdateLabels(), a]) passes.extend([Ophis.Passes.CircularityCheck(),
Ophis.Passes.CheckExprs(),
Ophis.Passes.EasyModes()])
passes.append(Ophis.Passes.FixPoint("instruction selection 2", [c, b],
lambda: not b.changed))
passes.extend([Ophis.Passes.NormalizeModes(),
Ophis.Passes.UpdateLabels(),
a])
for p in passes: p.go(z, env) for p in passes:
p.go(z, env)
if Err.count == 0: if Err.count == 0:
try: try:
@ -53,10 +64,11 @@ def run_all(infile, outfile):
if outfile != '-': if outfile != '-':
output.close() output.close()
except IOError: except IOError:
print>>sys.stderr, "Could not write to "+outfile print>>sys.stderr, "Could not write to " + outfile
else: else:
Err.report() Err.report()
def run_ophis(args): def run_ophis(args):
Ophis.CmdLine.parse_args(args) Ophis.CmdLine.parse_args(args)
Ophis.Frontend.pragma_modules.append(Ophis.CorePragmas) Ophis.Frontend.pragma_modules.append(Ophis.CorePragmas)
@ -69,5 +81,6 @@ def run_ophis(args):
Ophis.CorePragmas.reset() Ophis.CorePragmas.reset()
run_all(Ophis.CmdLine.infile, Ophis.CmdLine.outfile) run_all(Ophis.CmdLine.infile, Ophis.CmdLine.outfile)
if __name__ == '__main__': if __name__ == '__main__':
run_ophis(sys.argv[1:]) run_ophis(sys.argv[1:])

View File

@ -12,162 +12,291 @@
# the tables in tools/opcodes. Edit those tables, not these. # the tables in tools/opcodes. Edit those tables, not these.
# Names of addressing modes # Names of addressing modes
modes = ["Implied", # 0 modes = ["Implied", # 0
"Immediate", # 1 "Immediate", # 1
"Zero Page", # 2 "Zero Page", # 2
"Zero Page, X", # 3 "Zero Page, X", # 3
"Zero Page, Y", # 4 "Zero Page, Y", # 4
"Absolute", # 5 "Absolute", # 5
"Absolute, X", # 6 "Absolute, X", # 6
"Absolute, Y", # 7 "Absolute, Y", # 7
"(Absolute)", # 8 "(Absolute)", # 8
"(Absolute, X)", # 9 "(Absolute, X)", # 9
"(Absolute), Y", # 10 "(Absolute), Y", # 10
"(Zero Page)", # 11 "(Zero Page)", # 11
"(Zero Page, X)", # 12 "(Zero Page, X)", # 12
"(Zero Page), Y", # 13 "(Zero Page), Y", # 13
"Relative"] # 14 "Relative"] # 14
# Lengths of the argument # Lengths of the argument
lengths = [0, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1] lengths = [0, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1]
opcodes = { opcodes = {
'adc': [None, 0x69, 0x65, 0x75, None, 0x6D, 0x7D, 0x79, None, None, None, None, 0x61, 0x71, None], 'adc': [None, 0x69, 0x65, 0x75, None, 0x6D, 0x7D, 0x79,
'and': [None, 0x29, 0x25, 0x35, None, 0x2D, 0x3D, 0x39, None, None, None, None, 0x21, 0x31, None], None, None, None, None, 0x61, 0x71, None],
'asl': [0x0A, None, 0x06, 0x16, None, 0x0E, 0x1E, None, None, None, None, None, None, None, None], 'and': [None, 0x29, 0x25, 0x35, None, 0x2D, 0x3D, 0x39,
'bcc': [None, None, None, None, None, None, None, None, None, None, None, None, None, None, 0x90], None, None, None, None, 0x21, 0x31, None],
'bcs': [None, None, None, None, None, None, None, None, None, None, None, None, None, None, 0xB0], 'asl': [0x0A, None, 0x06, 0x16, None, 0x0E, 0x1E, None,
'beq': [None, None, None, None, None, None, None, None, None, None, None, None, None, None, 0xF0], None, None, None, None, None, None, None],
'bit': [None, None, 0x24, None, None, 0x2C, None, None, None, None, None, None, None, None, None], 'bcc': [None, None, None, None, None, None, None, None,
'bmi': [None, None, None, None, None, None, None, None, None, None, None, None, None, None, 0x30], None, None, None, None, None, None, 0x90],
'bne': [None, None, None, None, None, None, None, None, None, None, None, None, None, None, 0xD0], 'bcs': [None, None, None, None, None, None, None, None,
'bpl': [None, None, None, None, None, None, None, None, None, None, None, None, None, None, 0x10], None, None, None, None, None, None, 0xB0],
'brk': [0x00, None, None, None, None, None, None, None, None, None, None, None, None, None, None], 'beq': [None, None, None, None, None, None, None, None,
'bvc': [None, None, None, None, None, None, None, None, None, None, None, None, None, None, 0x50], None, None, None, None, None, None, 0xF0],
'bvs': [None, None, None, None, None, None, None, None, None, None, None, None, None, None, 0x70], 'bit': [None, None, 0x24, None, None, 0x2C, None, None,
'clc': [0x18, None, None, None, None, None, None, None, None, None, None, None, None, None, None], None, None, None, None, None, None, None],
'cld': [0xD8, None, None, None, None, None, None, None, None, None, None, None, None, None, None], 'bmi': [None, None, None, None, None, None, None, None,
'cli': [0x58, None, None, None, None, None, None, None, None, None, None, None, None, None, None], None, None, None, None, None, None, 0x30],
'clv': [0xB8, None, None, None, None, None, None, None, None, None, None, None, None, None, None], 'bne': [None, None, None, None, None, None, None, None,
'cmp': [None, 0xC9, 0xC5, 0xD5, None, 0xCD, 0xDD, 0xD9, None, None, None, None, 0xC1, 0xD1, None], None, None, None, None, None, None, 0xD0],
'cpx': [None, 0xE0, 0xE4, None, None, 0xEC, None, None, None, None, None, None, None, None, None], 'bpl': [None, None, None, None, None, None, None, None,
'cpy': [None, 0xC0, 0xC4, None, None, 0xCC, None, None, None, None, None, None, None, None, None], None, None, None, None, None, None, 0x10],
'dec': [None, None, 0xC6, 0xD6, None, 0xCE, 0xDE, None, None, None, None, None, None, None, None], 'brk': [0x00, None, None, None, None, None, None, None,
'dex': [0xCA, None, None, None, None, None, None, None, None, None, None, None, None, None, None], None, None, None, None, None, None, None],
'dey': [0x88, None, None, None, None, None, None, None, None, None, None, None, None, None, None], 'bvc': [None, None, None, None, None, None, None, None,
'eor': [None, 0x49, 0x45, 0x55, None, 0x4D, 0x5D, 0x59, None, None, None, None, 0x41, 0x51, None], None, None, None, None, None, None, 0x50],
'inc': [None, None, 0xE6, 0xF6, None, 0xEE, 0xFE, None, None, None, None, None, None, None, None], 'bvs': [None, None, None, None, None, None, None, None,
'inx': [0xE8, None, None, None, None, None, None, None, None, None, None, None, None, None, None], None, None, None, None, None, None, 0x70],
'iny': [0xC8, None, None, None, None, None, None, None, None, None, None, None, None, None, None], 'clc': [0x18, None, None, None, None, None, None, None,
'jmp': [None, None, None, None, None, 0x4C, None, None, 0x6C, None, None, None, None, None, None], None, None, None, None, None, None, None],
'jsr': [None, None, None, None, None, 0x20, None, None, None, None, None, None, None, None, None], 'cld': [0xD8, None, None, None, None, None, None, None,
'lda': [None, 0xA9, 0xA5, 0xB5, None, 0xAD, 0xBD, 0xB9, None, None, None, None, 0xA1, 0xB1, None], None, None, None, None, None, None, None],
'ldx': [None, 0xA2, 0xA6, None, 0xB6, 0xAE, None, 0xBE, None, None, None, None, None, None, None], 'cli': [0x58, None, None, None, None, None, None, None,
'ldy': [None, 0xA0, 0xA4, 0xB4, None, 0xAC, 0xBC, None, None, None, None, None, None, None, None], None, None, None, None, None, None, None],
'lsr': [0x4A, None, 0x46, 0x56, None, 0x4E, 0x5E, None, None, None, None, None, None, None, None], 'clv': [0xB8, None, None, None, None, None, None, None,
'nop': [0xEA, None, None, None, None, None, None, None, None, None, None, None, None, None, None], None, None, None, None, None, None, None],
'ora': [None, 0x09, 0x05, 0x15, None, 0x0D, 0x1D, 0x19, None, None, None, None, 0x01, 0x11, None], 'cmp': [None, 0xC9, 0xC5, 0xD5, None, 0xCD, 0xDD, 0xD9,
'pha': [0x48, None, None, None, None, None, None, None, None, None, None, None, None, None, None], None, None, None, None, 0xC1, 0xD1, None],
'php': [0x08, None, None, None, None, None, None, None, None, None, None, None, None, None, None], 'cpx': [None, 0xE0, 0xE4, None, None, 0xEC, None, None,
'pla': [0x68, None, None, None, None, None, None, None, None, None, None, None, None, None, None], None, None, None, None, None, None, None],
'plp': [0x28, None, None, None, None, None, None, None, None, None, None, None, None, None, None], 'cpy': [None, 0xC0, 0xC4, None, None, 0xCC, None, None,
'rol': [0x2A, None, 0x26, 0x36, None, 0x2E, 0x3E, None, None, None, None, None, None, None, None], None, None, None, None, None, None, None],
'ror': [0x6A, None, 0x66, 0x76, None, 0x6E, 0x7E, None, None, None, None, None, None, None, None], 'dec': [None, None, 0xC6, 0xD6, None, 0xCE, 0xDE, None,
'rti': [0x40, None, None, None, None, None, None, None, None, None, None, None, None, None, None], None, None, None, None, None, None, None],
'rts': [0x60, None, None, None, None, None, None, None, None, None, None, None, None, None, None], 'dex': [0xCA, None, None, None, None, None, None, None,
'sbc': [None, 0xE9, 0xE5, 0xF5, None, 0xED, 0xFD, 0xF9, None, None, None, None, 0xE1, 0xF1, None], None, None, None, None, None, None, None],
'sec': [0x38, None, None, None, None, None, None, None, None, None, None, None, None, None, None], 'dey': [0x88, None, None, None, None, None, None, None,
'sed': [0xF8, None, None, None, None, None, None, None, None, None, None, None, None, None, None], None, None, None, None, None, None, None],
'sei': [0x78, None, None, None, None, None, None, None, None, None, None, None, None, None, None], 'eor': [None, 0x49, 0x45, 0x55, None, 0x4D, 0x5D, 0x59,
'sta': [None, None, 0x85, 0x95, None, 0x8D, 0x9D, 0x99, None, None, None, None, 0x81, 0x91, None], None, None, None, None, 0x41, 0x51, None],
'stx': [None, None, 0x86, None, 0x96, 0x8E, None, None, None, None, None, None, None, None, None], 'inc': [None, None, 0xE6, 0xF6, None, 0xEE, 0xFE, None,
'sty': [None, None, 0x84, 0x94, None, 0x8C, None, None, None, None, None, None, None, None, None], None, None, None, None, None, None, None],
'tax': [0xAA, None, None, None, None, None, None, None, None, None, None, None, None, None, None], 'inx': [0xE8, None, None, None, None, None, None, None,
'tay': [0xA8, None, None, None, None, None, None, None, None, None, None, None, None, None, None], None, None, None, None, None, None, None],
'tsx': [0xBA, None, None, None, None, None, None, None, None, None, None, None, None, None, None], 'iny': [0xC8, None, None, None, None, None, None, None,
'txa': [0x8A, None, None, None, None, None, None, None, None, None, None, None, None, None, None], None, None, None, None, None, None, None],
'txs': [0x9A, None, None, None, None, None, None, None, None, None, None, None, None, None, None], 'jmp': [None, None, None, None, None, 0x4C, None, None,
'tya': [0x98, None, None, None, None, None, None, None, None, None, None, None, None, None, None], 0x6C, None, None, None, None, None, None],
'jsr': [None, None, None, None, None, 0x20, None, None,
None, None, None, None, None, None, None],
'lda': [None, 0xA9, 0xA5, 0xB5, None, 0xAD, 0xBD, 0xB9,
None, None, None, None, 0xA1, 0xB1, None],
'ldx': [None, 0xA2, 0xA6, None, 0xB6, 0xAE, None, 0xBE,
None, None, None, None, None, None, None],
'ldy': [None, 0xA0, 0xA4, 0xB4, None, 0xAC, 0xBC, None,
None, None, None, None, None, None, None],
'lsr': [0x4A, None, 0x46, 0x56, None, 0x4E, 0x5E, None,
None, None, None, None, None, None, None],
'nop': [0xEA, None, None, None, None, None, None, None,
None, None, None, None, None, None, None],
'ora': [None, 0x09, 0x05, 0x15, None, 0x0D, 0x1D, 0x19,
None, None, None, None, 0x01, 0x11, None],
'pha': [0x48, None, None, None, None, None, None, None,
None, None, None, None, None, None, None],
'php': [0x08, None, None, None, None, None, None, None,
None, None, None, None, None, None, None],
'pla': [0x68, None, None, None, None, None, None, None,
None, None, None, None, None, None, None],
'plp': [0x28, None, None, None, None, None, None, None,
None, None, None, None, None, None, None],
'rol': [0x2A, None, 0x26, 0x36, None, 0x2E, 0x3E, None,
None, None, None, None, None, None, None],
'ror': [0x6A, None, 0x66, 0x76, None, 0x6E, 0x7E, None,
None, None, None, None, None, None, None],
'rti': [0x40, None, None, None, None, None, None, None,
None, None, None, None, None, None, None],
'rts': [0x60, None, None, None, None, None, None, None,
None, None, None, None, None, None, None],
'sbc': [None, 0xE9, 0xE5, 0xF5, None, 0xED, 0xFD, 0xF9,
None, None, None, None, 0xE1, 0xF1, None],
'sec': [0x38, None, None, None, None, None, None, None,
None, None, None, None, None, None, None],
'sed': [0xF8, None, None, None, None, None, None, None,
None, None, None, None, None, None, None],
'sei': [0x78, None, None, None, None, None, None, None,
None, None, None, None, None, None, None],
'sta': [None, None, 0x85, 0x95, None, 0x8D, 0x9D, 0x99,
None, None, None, None, 0x81, 0x91, None],
'stx': [None, None, 0x86, None, 0x96, 0x8E, None, None,
None, None, None, None, None, None, None],
'sty': [None, None, 0x84, 0x94, None, 0x8C, None, None,
None, None, None, None, None, None, None],
'tax': [0xAA, None, None, None, None, None, None, None,
None, None, None, None, None, None, None],
'tay': [0xA8, None, None, None, None, None, None, None,
None, None, None, None, None, None, None],
'tsx': [0xBA, None, None, None, None, None, None, None,
None, None, None, None, None, None, None],
'txa': [0x8A, None, None, None, None, None, None, None,
None, None, None, None, None, None, None],
'txs': [0x9A, None, None, None, None, None, None, None,
None, None, None, None, None, None, None],
'tya': [0x98, None, None, None, None, None, None, None,
None, None, None, None, None, None, None],
} }
undocops = { undocops = {
'anc': [None, 0x0B, None, None, None, None, None, None, None, None, None, None, None, None, None], 'anc': [None, 0x0B, None, None, None, None, None, None,
'ane': [None, 0x8B, None, None, None, None, None, None, None, None, None, None, None, None, None], None, None, None, None, None, None, None],
'arr': [None, 0x6B, None, None, None, None, None, None, None, None, None, None, None, None, None], 'ane': [None, 0x8B, None, None, None, None, None, None,
'asr': [None, 0x4B, None, None, None, None, None, None, None, None, None, None, None, None, None], None, None, None, None, None, None, None],
'dcp': [None, None, 0xC7, 0xD7, None, 0xCF, 0xDF, 0xDB, None, None, None, None, 0xC3, 0xD3, None], 'arr': [None, 0x6B, None, None, None, None, None, None,
'isb': [None, None, 0xE7, 0xF7, None, 0xEF, 0xFF, 0xFB, None, None, None, None, 0xE3, 0xF3, None], None, None, None, None, None, None, None],
'las': [None, None, None, None, None, None, None, 0xBB, None, None, None, None, None, None, None], 'asr': [None, 0x4B, None, None, None, None, None, None,
'lax': [None, None, 0xA7, None, 0xB7, 0xAF, None, 0xBF, None, None, None, None, 0xA3, 0xB3, None], None, None, None, None, None, None, None],
'lxa': [None, 0xAB, None, None, None, None, None, None, None, None, None, None, None, None, None], 'dcp': [None, None, 0xC7, 0xD7, None, 0xCF, 0xDF, 0xDB,
'nop': [0xEA, None, 0x04, None, None, None, None, None, None, None, None, None, None, None, None], None, None, None, None, 0xC3, 0xD3, None],
'rla': [None, None, 0x27, 0x37, None, 0x2F, 0x3F, 0x3B, None, None, None, None, 0x23, 0x33, None], 'isb': [None, None, 0xE7, 0xF7, None, 0xEF, 0xFF, 0xFB,
'rra': [None, None, 0x67, 0x77, None, 0x6F, 0x7F, 0x7B, None, None, None, None, 0x63, 0x73, None], None, None, None, None, 0xE3, 0xF3, None],
'sax': [None, None, 0x87, None, 0x97, 0x8F, None, None, None, None, None, None, 0x83, None, None], 'las': [None, None, None, None, None, None, None, 0xBB,
'sbx': [None, 0xCB, None, None, None, None, None, None, None, None, None, None, None, None, None], None, None, None, None, None, None, None],
'sha': [None, None, None, None, None, None, None, 0x9F, None, None, None, None, None, 0x93, None], 'lax': [None, None, 0xA7, None, 0xB7, 0xAF, None, 0xBF,
'shs': [None, None, None, None, None, None, None, 0x9B, None, None, None, None, None, None, None], None, None, None, None, 0xA3, 0xB3, None],
'shx': [None, None, None, None, None, None, None, 0x9E, None, None, None, None, None, None, None], 'lxa': [None, 0xAB, None, None, None, None, None, None,
'slo': [None, None, 0x07, 0x17, None, 0x0F, 0x1F, 0x1B, None, None, None, None, 0x03, 0x13, None], None, None, None, None, None, None, None],
'sre': [None, None, 0x47, 0x57, None, 0x4F, 0x5F, 0x5B, None, None, None, None, 0x43, 0x53, None], 'nop': [0xEA, None, 0x04, None, None, None, None, None,
None, None, None, None, None, None, None],
'rla': [None, None, 0x27, 0x37, None, 0x2F, 0x3F, 0x3B,
None, None, None, None, 0x23, 0x33, None],
'rra': [None, None, 0x67, 0x77, None, 0x6F, 0x7F, 0x7B,
None, None, None, None, 0x63, 0x73, None],
'sax': [None, None, 0x87, None, 0x97, 0x8F, None, None,
None, None, None, None, 0x83, None, None],
'sbx': [None, 0xCB, None, None, None, None, None, None,
None, None, None, None, None, None, None],
'sha': [None, None, None, None, None, None, None, 0x9F,
None, None, None, None, None, 0x93, None],
'shs': [None, None, None, None, None, None, None, 0x9B,
None, None, None, None, None, None, None],
'shx': [None, None, None, None, None, None, None, 0x9E,
None, None, None, None, None, None, None],
'slo': [None, None, 0x07, 0x17, None, 0x0F, 0x1F, 0x1B,
None, None, None, None, 0x03, 0x13, None],
'sre': [None, None, 0x47, 0x57, None, 0x4F, 0x5F, 0x5B,
None, None, None, None, 0x43, 0x53, None],
} }
c02extensions = { c02extensions = {
'adc': [None, 0x69, 0x65, 0x75, None, 0x6D, 0x7D, 0x79, None, None, None, 0x72, 0x61, 0x71, None], 'adc': [None, 0x69, 0x65, 0x75, None, 0x6D, 0x7D, 0x79,
'and': [None, 0x29, 0x25, 0x35, None, 0x2D, 0x3D, 0x39, None, None, None, 0x32, 0x21, 0x31, None], None, None, None, 0x72, 0x61, 0x71, None],
'bbr0': [None, None, None, None, None, None, None, None, None, None, None, None, None, None, 0x0F], 'and': [None, 0x29, 0x25, 0x35, None, 0x2D, 0x3D, 0x39,
'bbr1': [None, None, None, None, None, None, None, None, None, None, None, None, None, None, 0x1F], None, None, None, 0x32, 0x21, 0x31, None],
'bbr2': [None, None, None, None, None, None, None, None, None, None, None, None, None, None, 0x2F], 'bbr0': [None, None, None, None, None, None, None, None,
'bbr3': [None, None, None, None, None, None, None, None, None, None, None, None, None, None, 0x3F], None, None, None, None, None, None, 0x0F],
'bbr4': [None, None, None, None, None, None, None, None, None, None, None, None, None, None, 0x4F], 'bbr1': [None, None, None, None, None, None, None, None,
'bbr5': [None, None, None, None, None, None, None, None, None, None, None, None, None, None, 0x5F], None, None, None, None, None, None, 0x1F],
'bbr6': [None, None, None, None, None, None, None, None, None, None, None, None, None, None, 0x6F], 'bbr2': [None, None, None, None, None, None, None, None,
'bbr7': [None, None, None, None, None, None, None, None, None, None, None, None, None, None, 0x7F], None, None, None, None, None, None, 0x2F],
'bbs0': [None, None, None, None, None, None, None, None, None, None, None, None, None, None, 0x8F], 'bbr3': [None, None, None, None, None, None, None, None,
'bbs1': [None, None, None, None, None, None, None, None, None, None, None, None, None, None, 0x9F], None, None, None, None, None, None, 0x3F],
'bbs2': [None, None, None, None, None, None, None, None, None, None, None, None, None, None, 0xAF], 'bbr4': [None, None, None, None, None, None, None, None,
'bbs3': [None, None, None, None, None, None, None, None, None, None, None, None, None, None, 0xBF], None, None, None, None, None, None, 0x4F],
'bbs4': [None, None, None, None, None, None, None, None, None, None, None, None, None, None, 0xCF], 'bbr5': [None, None, None, None, None, None, None, None,
'bbs5': [None, None, None, None, None, None, None, None, None, None, None, None, None, None, 0xDF], None, None, None, None, None, None, 0x5F],
'bbs6': [None, None, None, None, None, None, None, None, None, None, None, None, None, None, 0xEF], 'bbr6': [None, None, None, None, None, None, None, None,
'bbs7': [None, None, None, None, None, None, None, None, None, None, None, None, None, None, 0xFF], None, None, None, None, None, None, 0x6F],
'bit': [None, 0x89, 0x24, 0x34, None, 0x2C, 0x3C, None, None, None, None, None, None, None, None], 'bbr7': [None, None, None, None, None, None, None, None,
'bra': [None, None, None, None, None, None, None, None, None, None, None, None, None, None, 0x80], None, None, None, None, None, None, 0x7F],
'cmp': [None, 0xC9, 0xC5, 0xD5, None, 0xCD, 0xDD, 0xD9, None, None, None, 0xD2, 0xC1, 0xD1, None], 'bbs0': [None, None, None, None, None, None, None, None,
'dea': [0x3A, None, None, None, None, None, None, None, None, None, None, None, None, None, None], None, None, None, None, None, None, 0x8F],
'dec': [0x3A, None, 0xC6, 0xD6, None, 0xCE, 0xDE, None, None, None, None, None, None, None, None], 'bbs1': [None, None, None, None, None, None, None, None,
'eor': [None, 0x49, 0x45, 0x55, None, 0x4D, 0x5D, 0x59, None, None, None, 0x52, 0x41, 0x51, None], None, None, None, None, None, None, 0x9F],
'ina': [0x1A, None, None, None, None, None, None, None, None, None, None, None, None, None, None], 'bbs2': [None, None, None, None, None, None, None, None,
'inc': [0x1A, None, 0xE6, 0xF6, None, 0xEE, 0xFE, None, None, None, None, None, None, None, None], None, None, None, None, None, None, 0xAF],
'jmp': [None, None, None, None, None, 0x4C, None, None, 0x6C, 0x7C, None, None, None, None, None], 'bbs3': [None, None, None, None, None, None, None, None,
'lda': [None, 0xA9, 0xA5, 0xB5, None, 0xAD, 0xBD, 0xB9, None, None, None, 0xB2, 0xA1, 0xB1, None], None, None, None, None, None, None, 0xBF],
'ora': [None, 0x09, 0x05, 0x15, None, 0x0D, 0x1D, 0x19, None, None, None, 0x12, 0x01, 0x11, None], 'bbs4': [None, None, None, None, None, None, None, None,
'phx': [0xDA, None, None, None, None, None, None, None, None, None, None, None, None, None, None], None, None, None, None, None, None, 0xCF],
'phy': [0x5A, None, None, None, None, None, None, None, None, None, None, None, None, None, None], 'bbs5': [None, None, None, None, None, None, None, None,
'plx': [0xFA, None, None, None, None, None, None, None, None, None, None, None, None, None, None], None, None, None, None, None, None, 0xDF],
'ply': [0x7A, None, None, None, None, None, None, None, None, None, None, None, None, None, None], 'bbs6': [None, None, None, None, None, None, None, None,
'rmb0': [None, None, 0x07, None, None, None, None, None, None, None, None, None, None, None, None], None, None, None, None, None, None, 0xEF],
'rmb1': [None, None, 0x17, None, None, None, None, None, None, None, None, None, None, None, None], 'bbs7': [None, None, None, None, None, None, None, None,
'rmb2': [None, None, 0x27, None, None, None, None, None, None, None, None, None, None, None, None], None, None, None, None, None, None, 0xFF],
'rmb3': [None, None, 0x37, None, None, None, None, None, None, None, None, None, None, None, None], 'bit': [None, 0x89, 0x24, 0x34, None, 0x2C, 0x3C, None,
'rmb4': [None, None, 0x47, None, None, None, None, None, None, None, None, None, None, None, None], None, None, None, None, None, None, None],
'rmb5': [None, None, 0x57, None, None, None, None, None, None, None, None, None, None, None, None], 'bra': [None, None, None, None, None, None, None, None,
'rmb6': [None, None, 0x67, None, None, None, None, None, None, None, None, None, None, None, None], None, None, None, None, None, None, 0x80],
'rmb7': [None, None, 0x77, None, None, None, None, None, None, None, None, None, None, None, None], 'cmp': [None, 0xC9, 0xC5, 0xD5, None, 0xCD, 0xDD, 0xD9,
'sbc': [None, 0xE9, 0xE5, 0xF5, None, 0xED, 0xFD, 0xF9, None, None, None, 0xF2, 0xE1, 0xF1, None], None, None, None, 0xD2, 0xC1, 0xD1, None],
'smb0': [None, None, 0x87, None, None, None, None, None, None, None, None, None, None, None, None], 'dea': [0x3A, None, None, None, None, None, None, None,
'smb1': [None, None, 0x97, None, None, None, None, None, None, None, None, None, None, None, None], None, None, None, None, None, None, None],
'smb2': [None, None, 0xA7, None, None, None, None, None, None, None, None, None, None, None, None], 'dec': [0x3A, None, 0xC6, 0xD6, None, 0xCE, 0xDE, None,
'smb3': [None, None, 0xB7, None, None, None, None, None, None, None, None, None, None, None, None], None, None, None, None, None, None, None],
'smb4': [None, None, 0xC7, None, None, None, None, None, None, None, None, None, None, None, None], 'eor': [None, 0x49, 0x45, 0x55, None, 0x4D, 0x5D, 0x59,
'smb5': [None, None, 0xD7, None, None, None, None, None, None, None, None, None, None, None, None], None, None, None, 0x52, 0x41, 0x51, None],
'smb6': [None, None, 0xE7, None, None, None, None, None, None, None, None, None, None, None, None], 'ina': [0x1A, None, None, None, None, None, None, None,
'smb7': [None, None, 0xF7, None, None, None, None, None, None, None, None, None, None, None, None], None, None, None, None, None, None, None],
'sta': [None, None, 0x85, 0x95, None, 0x8D, 0x9D, 0x99, None, None, None, 0x92, 0x81, 0x91, None], 'inc': [0x1A, None, 0xE6, 0xF6, None, 0xEE, 0xFE, None,
'stp': [0xDB, None, None, None, None, None, None, None, None, None, None, None, None, None, None], None, None, None, None, None, None, None],
'stz': [None, None, 0x64, 0x74, None, 0x9C, 0x9E, None, None, None, None, None, None, None, None], 'jmp': [None, None, None, None, None, 0x4C, None, None,
'trb': [None, None, 0x14, None, None, 0x1C, None, None, None, None, None, None, None, None, None], 0x6C, 0x7C, None, None, None, None, None],
'tsb': [None, None, 0x04, None, None, 0x0C, None, None, None, None, None, None, None, None, None], 'lda': [None, 0xA9, 0xA5, 0xB5, None, 0xAD, 0xBD, 0xB9,
'wai': [0xCB, None, None, None, None, None, None, None, None, None, None, None, None, None, None], None, None, None, 0xB2, 0xA1, 0xB1, None],
'ora': [None, 0x09, 0x05, 0x15, None, 0x0D, 0x1D, 0x19,
None, None, None, 0x12, 0x01, 0x11, None],
'phx': [0xDA, None, None, None, None, None, None, None,
None, None, None, None, None, None, None],
'phy': [0x5A, None, None, None, None, None, None, None,
None, None, None, None, None, None, None],
'plx': [0xFA, None, None, None, None, None, None, None,
None, None, None, None, None, None, None],
'ply': [0x7A, None, None, None, None, None, None, None,
None, None, None, None, None, None, None],
'rmb0': [None, None, 0x07, None, None, None, None, None,
None, None, None, None, None, None, None],
'rmb1': [None, None, 0x17, None, None, None, None, None,
None, None, None, None, None, None, None],
'rmb2': [None, None, 0x27, None, None, None, None, None,
None, None, None, None, None, None, None],
'rmb3': [None, None, 0x37, None, None, None, None, None,
None, None, None, None, None, None, None],
'rmb4': [None, None, 0x47, None, None, None, None, None,
None, None, None, None, None, None, None],
'rmb5': [None, None, 0x57, None, None, None, None, None,
None, None, None, None, None, None, None],
'rmb6': [None, None, 0x67, None, None, None, None, None,
None, None, None, None, None, None, None],
'rmb7': [None, None, 0x77, None, None, None, None, None,
None, None, None, None, None, None, None],
'sbc': [None, 0xE9, 0xE5, 0xF5, None, 0xED, 0xFD, 0xF9,
None, None, None, 0xF2, 0xE1, 0xF1, None],
'smb0': [None, None, 0x87, None, None, None, None, None,
None, None, None, None, None, None, None],
'smb1': [None, None, 0x97, None, None, None, None, None,
None, None, None, None, None, None, None],
'smb2': [None, None, 0xA7, None, None, None, None, None,
None, None, None, None, None, None, None],
'smb3': [None, None, 0xB7, None, None, None, None, None,
None, None, None, None, None, None, None],
'smb4': [None, None, 0xC7, None, None, None, None, None,
None, None, None, None, None, None, None],
'smb5': [None, None, 0xD7, None, None, None, None, None,
None, None, None, None, None, None, None],
'smb6': [None, None, 0xE7, None, None, None, None, None,
None, None, None, None, None, None, None],
'smb7': [None, None, 0xF7, None, None, None, None, None,
None, None, None, None, None, None, None],
'sta': [None, None, 0x85, 0x95, None, 0x8D, 0x9D, 0x99,
None, None, None, 0x92, 0x81, 0x91, None],
'stp': [0xDB, None, None, None, None, None, None, None,
None, None, None, None, None, None, None],
'stz': [None, None, 0x64, 0x74, None, 0x9C, 0x9E, None,
None, None, None, None, None, None, None],
'trb': [None, None, 0x14, None, None, 0x1C, None, None,
None, None, None, None, None, None, None],
'tsb': [None, None, 0x04, None, None, 0x0C, None, None,
None, None, None, None, None, None, None],
'wai': [0xCB, None, None, None, None, None, None, None,
None, None, None, None, None, None, None],
} }

View File

@ -6,7 +6,7 @@
translation occurs. This structure also makes the assembler translation occurs. This structure also makes the assembler
very extensible; additional analyses or optimizations may be very extensible; additional analyses or optimizations may be
added as new subclasses of Pass.""" added as new subclasses of Pass."""
# Copyright 2002-2012 Michael C. Martin and additional contributors. # Copyright 2002-2012 Michael C. Martin and additional contributors.
# You may use, modify, and distribute this file under the MIT # You may use, modify, and distribute this file under the MIT
# license: See README for details. # license: See README for details.
@ -20,41 +20,55 @@ import Ophis.Macro as Macro
# The passes themselves # The passes themselves
class Pass(object): class Pass(object):
"""Superclass for all assembler passes. Automatically handles IR """Superclass for all assembler passes. Automatically handles IR
types that modify the environent's structure, and by default types that modify the environent's structure, and by default
raises an error on anything else. Override visitUnknown in your raises an error on anything else. Override visitUnknown in your
extension pass to produce a pass that accepts everything.""" extension pass to produce a pass that accepts everything."""
name = "Default Pass" name = "Default Pass"
def __init__(self): def __init__(self):
self.writeOK = 1 self.writeOK = True
def visitNone(self, node, env): def visitNone(self, node, env):
pass pass
def visitSEQUENCE(self, node, env): def visitSEQUENCE(self, node, env):
Err.currentpoint = node.ppt Err.currentpoint = node.ppt
for n in node.data: for n in node.data:
n.accept(self, env) n.accept(self, env)
def visitDataSegment(self, node, env): def visitDataSegment(self, node, env):
self.writeOK = 0 self.writeOK = False
env.setsegment(node.data[0]) env.setsegment(node.data[0])
def visitTextSegment(self, node, env): def visitTextSegment(self, node, env):
self.writeOK = 1 self.writeOK = True
env.setsegment(node.data[0]) env.setsegment(node.data[0])
def visitScopeBegin(self, node, env): def visitScopeBegin(self, node, env):
env.newscope() env.newscope()
def visitScopeEnd(self, node, env): def visitScopeEnd(self, node, env):
env.endscope() env.endscope()
def visitUnknown(self, node, env): def visitUnknown(self, node, env):
Err.log("Internal error! "+self.name+" cannot understand node type "+node.nodetype) Err.log("Internal error! " + self.name +
" cannot understand node type " + node.nodetype)
def prePass(self): def prePass(self):
pass pass
def postPass(self): def postPass(self):
pass pass
def go(self, node, env): def go(self, node, env):
"""Prepares the environment and runs this pass, possibly """Prepares the environment and runs this pass, possibly
printing debugging information.""" printing debugging information."""
if Err.count == 0: if Err.count == 0:
if Cmd.print_pass: print>>sys.stderr, "Running: "+self.name if Cmd.print_pass:
print>>sys.stderr, "Running: " + self.name
env.reset() env.reset()
self.prePass() self.prePass()
node.accept(self, env) node.accept(self, env)
@ -67,6 +81,7 @@ class Pass(object):
print>>sys.stderr, "Current IR:" print>>sys.stderr, "Current IR:"
print>>sys.stderr, node print>>sys.stderr, node
class FixPoint(object): class FixPoint(object):
"""A specialized class that is not a pass but can be run like one. """A specialized class that is not a pass but can be run like one.
This class takes a list of passes and a "fixpoint" function.""" This class takes a list of passes and a "fixpoint" function."""
@ -74,48 +89,60 @@ class FixPoint(object):
self.name = name self.name = name
self.passes = passes self.passes = passes
self.fixpoint = fixpoint self.fixpoint = fixpoint
def go(self, node, env): def go(self, node, env):
"""Runs this FixPoint's passes, in order, until the fixpoint """Runs this FixPoint's passes, in order, until the fixpoint
is true. Always runs the passes at least once.""" is true. Always runs the passes at least once."""
for i in xrange(100): for i in xrange(100):
if Err.count != 0: break if Err.count != 0:
break
for p in self.passes: for p in self.passes:
p.go(node, env) p.go(node, env)
if Err.count != 0: break if Err.count != 0:
if self.fixpoint(): break break
if Cmd.print_pass: print>>sys.stderr, "Fixpoint failed, looping back" if self.fixpoint():
break
if Cmd.print_pass:
print>>sys.stderr, "Fixpoint failed, looping back"
else: else:
Err.log("Can't make %s converge! Maybe there's a recursive dependency somewhere?" % self.name) Err.log("Can't make %s converge! Maybe there's a recursive "
"dependency somewhere?" % self.name)
class DefineMacros(Pass): class DefineMacros(Pass):
"Extract macro definitions and remove them from the IR" "Extract macro definitions and remove them from the IR"
name = "Macro definition pass" name = "Macro definition pass"
def prePass(self): def prePass(self):
self.inDef = 0 self.inDef = False
self.nestedError = 0 self.nestedError = False
def postPass(self): def postPass(self):
if self.inDef: if self.inDef:
Err.log("Unmatched .macro") Err.log("Unmatched .macro")
elif Cmd.print_ir: elif Cmd.print_ir:
print>>sys.stderr, "Macro definitions:" print>>sys.stderr, "Macro definitions:"
Macro.dump() Macro.dump()
def visitMacroBegin(self, node, env): def visitMacroBegin(self, node, env):
if self.inDef: if self.inDef:
Err.log("Nested macro definition") Err.log("Nested macro definition")
self.nestedError = 1 self.nestedError = True
else: else:
Macro.newMacro(node.data[0]) Macro.newMacro(node.data[0])
node.nodetype = "None" node.nodetype = "None"
node.data = [] node.data = []
self.inDef = 1 self.inDef = True
def visitMacroEnd(self, node, env): def visitMacroEnd(self, node, env):
if self.inDef: if self.inDef:
Macro.endMacro() Macro.endMacro()
node.nodetype = "None" node.nodetype = "None"
node.data = [] node.data = []
self.inDef = 0 self.inDef = False
elif not self.nestedError: elif not self.nestedError:
Err.log("Unmatched .macend") Err.log("Unmatched .macend")
def visitUnknown(self, node, env): def visitUnknown(self, node, env):
if self.inDef: if self.inDef:
Macro.registerNode(node) Macro.registerNode(node)
@ -126,305 +153,438 @@ class DefineMacros(Pass):
class ExpandMacros(Pass): class ExpandMacros(Pass):
"Replace macro invocations with the appropriate text" "Replace macro invocations with the appropriate text"
name = "Macro expansion pass" name = "Macro expansion pass"
def prePass(self): def prePass(self):
self.changed = 0 self.changed = False
def visitMacroInvoke(self, node, env): def visitMacroInvoke(self, node, env):
replacement = Macro.expandMacro(node.ppt, node.data[0], node.data[1:]) replacement = Macro.expandMacro(node.ppt, node.data[0], node.data[1:])
node.nodetype = replacement.nodetype node.nodetype = replacement.nodetype
node.data = replacement.data node.data = replacement.data
self.changed = 1 self.changed = True
def visitUnknown(self, node, env): def visitUnknown(self, node, env):
pass pass
class InitLabels(Pass): class InitLabels(Pass):
"Finds all reachable labels" "Finds all reachable labels"
name = "Label initialization pass" name = "Label initialization pass"
def __init__(self): def __init__(self):
Pass.__init__(self) Pass.__init__(self)
self.labelmap = {} self.labelmap = {}
def prePass(self): def prePass(self):
self.changed = 0 self.changed = False
self.PCvalid = 1 self.PCvalid = True
def visitAdvance(self, node, env): def visitAdvance(self, node, env):
self.PCvalid=node.data[0].valid(env, self.PCvalid) self.PCvalid = node.data[0].valid(env, self.PCvalid)
def visitSetPC(self, node, env): def visitSetPC(self, node, env):
self.PCvalid=node.data[0].valid(env, self.PCvalid) self.PCvalid = node.data[0].valid(env, self.PCvalid)
def visitLabel(self, node, env): def visitLabel(self, node, env):
(label, val) = node.data (label, val) = node.data
fulllabel = "%d:%s" % (env.stack[0], label) fulllabel = "%d:%s" % (env.stack[0], label)
if fulllabel in self.labelmap and self.labelmap[fulllabel] is not node: if fulllabel in self.labelmap and self.labelmap[fulllabel] is not node:
Err.log("Duplicate label definition '%s'" % label) Err.log("Duplicate label definition '%s'" % label)
if fulllabel not in self.labelmap: if fulllabel not in self.labelmap:
self.labelmap[fulllabel] = node self.labelmap[fulllabel] = node
if val.valid(env, self.PCvalid) and label not in env: if val.valid(env, self.PCvalid) and label not in env:
env[label]=0 env[label] = 0
self.changed=1 self.changed = True
def visitUnknown(self, node, env): def visitUnknown(self, node, env):
pass pass
class CircularityCheck(Pass): class CircularityCheck(Pass):
"Checks for circular label dependencies" "Checks for circular label dependencies"
name = "Circularity check pass" name = "Circularity check pass"
def prePass(self): def prePass(self):
self.changed=0 self.changed = False
self.PCvalid=1 self.PCvalid = True
def visitAdvance(self, node, env): def visitAdvance(self, node, env):
PCvalid = self.PCvalid PCvalid = self.PCvalid
self.PCvalid=node.data[0].valid(env, self.PCvalid) self.PCvalid = node.data[0].valid(env, self.PCvalid)
if not node.data[0].valid(env, PCvalid): if not node.data[0].valid(env, PCvalid):
Err.log("Undefined or circular reference on .advance") Err.log("Undefined or circular reference on .advance")
def visitSetPC(self, node, env): def visitSetPC(self, node, env):
PCvalid = self.PCvalid PCvalid = self.PCvalid
self.PCvalid=node.data[0].valid(env, self.PCvalid) self.PCvalid = node.data[0].valid(env, self.PCvalid)
if not node.data[0].valid(env, PCvalid): if not node.data[0].valid(env, PCvalid):
Err.log("Undefined or circular reference on program counter set") Err.log("Undefined or circular reference on program counter set")
def visitCheckPC(self, node, env): def visitCheckPC(self, node, env):
if not node.data[0].valid(env, self.PCvalid): if not node.data[0].valid(env, self.PCvalid):
Err.log("Undefined or circular reference on program counter check") Err.log("Undefined or circular reference on program counter check")
def visitLabel(self, node, env): def visitLabel(self, node, env):
(label, val) = node.data (label, val) = node.data
if not val.valid(env, self.PCvalid): if not val.valid(env, self.PCvalid):
Err.log("Undefined or circular dependency for label '%s'" % label) Err.log("Undefined or circular dependency for label '%s'" % label)
def visitUnknown(self, node, env): def visitUnknown(self, node, env):
pass pass
class CheckExprs(Pass): class CheckExprs(Pass):
"Ensures all expressions can resolve" "Ensures all expressions can resolve"
name = "Expression checking pass" name = "Expression checking pass"
def visitUnknown(self, node, env): def visitUnknown(self, node, env):
# Throw away result, just confirm validity of all expressions
for i in [x for x in node.data if isinstance(x, IR.Expr)]: for i in [x for x in node.data if isinstance(x, IR.Expr)]:
i.value(env) # Throw away result, just confirm validity of all expressions i.value(env)
class EasyModes(Pass): class EasyModes(Pass):
"Assigns address modes to hardcoded and branch instructions" "Assigns address modes to hardcoded and branch instructions"
name = "Easy addressing modes pass" name = "Easy addressing modes pass"
def visitMemory(self, node, env): def visitMemory(self, node, env):
if Ops.opcodes[node.data[0]][14] is not None: if Ops.opcodes[node.data[0]][14] is not None:
node.nodetype = "Relative" node.nodetype = "Relative"
return return
if node.data[1].hardcoded: if node.data[1].hardcoded:
if not collapse_no_index(node, env): if not collapse_no_index(node, env):
node.nodetype = "Absolute" node.nodetype = "Absolute"
def visitMemoryX(self, node, env):
if node.data[1].hardcoded: def visitMemoryX(self, node, env):
if node.data[1].hardcoded:
if not collapse_x(node, env): if not collapse_x(node, env):
node.nodetype = "AbsoluteX" node.nodetype = "AbsoluteX"
def visitMemoryY(self, node, env):
if node.data[1].hardcoded: def visitMemoryY(self, node, env):
if node.data[1].hardcoded:
if not collapse_y(node, env): if not collapse_y(node, env):
node.nodetype = "AbsoluteY" node.nodetype = "AbsoluteY"
def visitPointer(self, node, env): def visitPointer(self, node, env):
if node.data[1].hardcoded: if node.data[1].hardcoded:
if not collapse_no_index_ind(node, env): if not collapse_no_index_ind(node, env):
node.nodetype = "Indirect" node.nodetype = "Indirect"
def visitPointerX(self, node, env): def visitPointerX(self, node, env):
if node.data[1].hardcoded: if node.data[1].hardcoded:
if not collapse_x_ind(node, env): if not collapse_x_ind(node, env):
node.nodetype = "AbsIndX" node.nodetype = "AbsIndX"
def visitPointerY(self, node, env): def visitPointerY(self, node, env):
if node.data[1].hardcoded: if node.data[1].hardcoded:
if not collapse_y_ind(node, env): if not collapse_y_ind(node, env):
node.nodetype = "AbsIndY" node.nodetype = "AbsIndY"
def visitUnknown(self, node, env): def visitUnknown(self, node, env):
pass pass
class PCTracker(Pass): class PCTracker(Pass):
"Superclass for passes that need an accurate program counter." "Superclass for passes that need an accurate program counter."
name = "**BUG** PC Tracker Superpass used directly" name = "**BUG** PC Tracker Superpass used directly"
def visitSetPC(self, node, env): env.setPC(node.data[0].value(env))
def visitAdvance(self, node, env): env.setPC(node.data[0].value(env)) def visitSetPC(self, node, env):
def visitImplied(self, node, env): env.incPC(1) env.setPC(node.data[0].value(env))
def visitImmediate(self, node, env): env.incPC(2)
def visitIndirectX(self, node, env): env.incPC(2) def visitAdvance(self, node, env):
def visitIndirectY(self, node, env): env.incPC(2) env.setPC(node.data[0].value(env))
def visitZPIndirect(self, node, env): env.incPC(2)
def visitZeroPage(self, node, env): env.incPC(2) def visitImplied(self, node, env):
def visitZeroPageX(self, node, env): env.incPC(2) env.incPC(1)
def visitZeroPageY(self, node, env): env.incPC(2)
def visitRelative(self, node, env): env.incPC(2) def visitImmediate(self, node, env):
def visitIndirect(self, node, env): env.incPC(3) env.incPC(2)
def visitAbsolute(self, node, env): env.incPC(3)
def visitAbsoluteX(self, node, env): env.incPC(3) def visitIndirectX(self, node, env):
def visitAbsoluteY(self, node, env): env.incPC(3) env.incPC(2)
def visitAbsIndX(self, node, env): env.incPC(3)
def visitAbsIndY(self, node, env): env.incPC(3) def visitIndirectY(self, node, env):
def visitMemory(self, node, env): env.incPC(3) env.incPC(2)
def visitMemoryX(self, node, env): env.incPC(3)
def visitMemoryY(self, node, env): env.incPC(3) def visitZPIndirect(self, node, env):
def visitPointer(self, node, env): env.incPC(3) env.incPC(2)
def visitPointerX(self, node, env): env.incPC(3)
def visitPointerY(self, node, env): env.incPC(3) def visitZeroPage(self, node, env):
def visitCheckPC(self, node, env): pass env.incPC(2)
def visitLabel(self, node, env): pass
def visitByte(self, node, env): env.incPC(len(node.data)) def visitZeroPageX(self, node, env):
def visitWord(self, node, env): env.incPC(len(node.data)*2) env.incPC(2)
def visitDword(self, node, env): env.incPC(len(node.data)*4)
def visitWordBE(self, node, env): env.incPC(len(node.data)*2) def visitZeroPageY(self, node, env):
def visitDwordBE(self, node, env): env.incPC(len(node.data)*4) env.incPC(2)
def visitRelative(self, node, env):
env.incPC(2)
def visitIndirect(self, node, env):
env.incPC(3)
def visitAbsolute(self, node, env):
env.incPC(3)
def visitAbsoluteX(self, node, env):
env.incPC(3)
def visitAbsoluteY(self, node, env):
env.incPC(3)
def visitAbsIndX(self, node, env):
env.incPC(3)
def visitAbsIndY(self, node, env):
env.incPC(3)
def visitMemory(self, node, env):
env.incPC(3)
def visitMemoryX(self, node, env):
env.incPC(3)
def visitMemoryY(self, node, env):
env.incPC(3)
def visitPointer(self, node, env):
env.incPC(3)
def visitPointerX(self, node, env):
env.incPC(3)
def visitPointerY(self, node, env):
env.incPC(3)
def visitCheckPC(self, node, env):
pass
def visitLabel(self, node, env):
pass
def visitByte(self, node, env):
env.incPC(len(node.data))
def visitWord(self, node, env):
env.incPC(len(node.data) * 2)
def visitDword(self, node, env):
env.incPC(len(node.data) * 4)
def visitWordBE(self, node, env):
env.incPC(len(node.data) * 2)
def visitDwordBE(self, node, env):
env.incPC(len(node.data) * 4)
class UpdateLabels(PCTracker): class UpdateLabels(PCTracker):
"Computes the new values for all entries in the symbol table" "Computes the new values for all entries in the symbol table"
name = "Label Update Pass" name = "Label Update Pass"
def prePass(self): def prePass(self):
self.changed = 0 self.changed = False
def visitLabel(self, node, env): def visitLabel(self, node, env):
(label, val) = node.data (label, val) = node.data
old = env[label] old = env[label]
env[label] = val.value(env) env[label] = val.value(env)
if old != env[label]: if old != env[label]:
self.changed = 1 self.changed = True
class Collapse(Pass): class Collapse(Pass):
"""Selects as many zero-page instructions to convert as "Selects as many zero-page instructions to convert as possible."
possible, and tracks how many instructions have been
converted this pass."""
name = "Instruction Collapse Pass" name = "Instruction Collapse Pass"
def prePass(self): def prePass(self):
self.collapsed = 0 self.changed = False
def visitMemory(self, node, env): def visitMemory(self, node, env):
if collapse_no_index(node, env): self.collapsed += 1 self.changed |= collapse_no_index(node, env)
def visitMemoryX(self, node, env): def visitMemoryX(self, node, env):
if collapse_x(node, env): self.collapsed += 1 self.changed |= collapse_x(node, env)
def visitMemoryY(self, node, env): def visitMemoryY(self, node, env):
if collapse_y(node, env): self.collapsed += 1 self.changed |= collapse_y(node, env)
def visitPointer(self, node, env): def visitPointer(self, node, env):
if collapse_no_index_ind(node, env): self.collapsed += 1 self.changed |= collapse_no_index_ind(node, env)
def visitPointerX(self, node, env): def visitPointerX(self, node, env):
if collapse_x_ind(node, env): self.collapsed += 1 self.changed |= collapse_x_ind(node, env)
def visitPointerY(self, node, env): def visitPointerY(self, node, env):
if collapse_y_ind(node, env): self.collapsed += 1 self.changed |= collapse_y_ind(node, env)
def visitUnknown(self, node, env): def visitUnknown(self, node, env):
pass pass
def collapse_no_index(node, env): def collapse_no_index(node, env):
"""Transforms a Memory node into a ZeroPage one if possible. """Transforms a Memory node into a ZeroPage one if possible.
Returns 1 if it made the collapse, false otherwise.""" Returns boolean indicating whether or not it made the collapse."""
if node.data[1].value(env) < 0x100 and Ops.opcodes[node.data[0]][2] is not None: if node.data[1].value(env) < 0x100:
node.nodetype = "ZeroPage" if Ops.opcodes[node.data[0]][2] is not None:
return 1 node.nodetype = "ZeroPage"
else: return True
return 0 return False
def collapse_x(node, env): def collapse_x(node, env):
"""Transforms a MemoryX node into a ZeroPageX one if possible. """Transforms a MemoryX node into a ZeroPageX one if possible.
Returns 1 if it made the collapse, false otherwise.""" Returns boolean indicating whether or not it made the collapse."""
if node.data[1].value(env) < 0x100 and Ops.opcodes[node.data[0]][3] is not None: if node.data[1].value(env) < 0x100:
node.nodetype = "ZeroPageX" if Ops.opcodes[node.data[0]][3] is not None:
return 1 node.nodetype = "ZeroPageX"
else: return True
return 0 return False
def collapse_y(node, env): def collapse_y(node, env):
"""Transforms a MemoryY node into a ZeroPageY one if possible. """Transforms a MemoryY node into a ZeroPageY one if possible.
Returns 1 if it made the collapse, false otherwise.""" Returns boolean indicating whether or not it made the collapse."""
if node.data[1].value(env) < 0x100 and Ops.opcodes[node.data[0]][4] is not None: if node.data[1].value(env) < 0x100:
node.nodetype = "ZeroPageY" if Ops.opcodes[node.data[0]][4] is not None:
return 1 node.nodetype = "ZeroPageY"
else: return True
return 0 return False
def collapse_no_index_ind(node, env): def collapse_no_index_ind(node, env):
"""Transforms a Pointer node into a ZPIndirect one if possible. """Transforms a Pointer node into a ZPIndirect one if possible.
Returns 1 if it made the collapse, false otherwise.""" Returns boolean indicating whether or not it made the collapse."""
if node.data[1].value(env) < 0x100 and Ops.opcodes[node.data[0]][11] is not None: if node.data[1].value(env) < 0x100:
node.nodetype = "ZPIndirect" if Ops.opcodes[node.data[0]][11] is not None:
return 1 node.nodetype = "ZPIndirect"
else: return True
return 0 return False
def collapse_x_ind(node, env): def collapse_x_ind(node, env):
"""Transforms a PointerX node into an IndirectX one if possible. """Transforms a PointerX node into an IndirectX one if possible.
Returns 1 if it made the collapse, false otherwise.""" Returns boolean indicating whether or not it made the collapse."""
if node.data[1].value(env) < 0x100 and Ops.opcodes[node.data[0]][12] is not None: if node.data[1].value(env) < 0x100:
node.nodetype = "IndirectX" if Ops.opcodes[node.data[0]][12] is not None:
return 1 node.nodetype = "IndirectX"
else: return True
return 0 return False
def collapse_y_ind(node, env): def collapse_y_ind(node, env):
"""Transforms a PointerY node into an IndirectY one if possible. """Transforms a PointerY node into an IndirectY one if possible.
Returns 1 if it made the collapse, false otherwise.""" Returns boolean indicating whether or not it made the collapse."""
if node.data[1].value(env) < 0x100 and Ops.opcodes[node.data[0]][13] is not None: if node.data[1].value(env) < 0x100:
node.nodetype = "IndirectY" if Ops.opcodes[node.data[0]][13] is not None:
return 1 node.nodetype = "IndirectY"
else: return True
return 0 return False
class ExtendBranches(PCTracker): class ExtendBranches(PCTracker):
"""Eliminates any branch instructions that would end up going past """Eliminates any branch instructions that would end up going past
the 128-byte range, and replaces them with a branch-jump the 128-byte range, and replaces them with a branch-jump pair."""
pair. Also tracks how many elements where changed this pass."""
name = "Branch Expansion Pass" name = "Branch Expansion Pass"
reversed = { 'bcc': 'bcs', reversed = {'bcc': 'bcs',
'bcs': 'bcc', 'bcs': 'bcc',
'beq': 'bne', 'beq': 'bne',
'bmi': 'bpl', 'bmi': 'bpl',
'bne': 'beq', 'bne': 'beq',
'bpl': 'bmi', 'bpl': 'bmi',
'bvc': 'bvs', 'bvc': 'bvs',
'bvs': 'bvc', 'bvs': 'bvc',
# 65c02 ones. 'bra' is special, though, having no inverse # 65c02 ones. 'bra' is special, though, having no inverse
'bbr0': 'bbs0', 'bbr0': 'bbs0',
'bbs0': 'bbr0', 'bbs0': 'bbr0',
'bbr1': 'bbs1', 'bbr1': 'bbs1',
'bbs1': 'bbr1', 'bbs1': 'bbr1',
'bbr2': 'bbs2', 'bbr2': 'bbs2',
'bbs2': 'bbr2', 'bbs2': 'bbr2',
'bbr3': 'bbs3', 'bbr3': 'bbs3',
'bbs3': 'bbr3', 'bbs3': 'bbr3',
'bbr4': 'bbs4', 'bbr4': 'bbs4',
'bbs4': 'bbr4', 'bbs4': 'bbr4',
'bbr5': 'bbs5', 'bbr5': 'bbs5',
'bbs5': 'bbr5', 'bbs5': 'bbr5',
'bbr6': 'bbs6', 'bbr6': 'bbs6',
'bbs6': 'bbr6', 'bbs6': 'bbr6',
'bbr7': 'bbs7', 'bbr7': 'bbs7',
'bbs7': 'bbr7' 'bbs7': 'bbr7'
} }
def prePass(self): def prePass(self):
self.expanded = 0 self.changed = False
def visitRelative(self, node, env): def visitRelative(self, node, env):
(opcode, expr) = node.data (opcode, expr) = node.data
arg = expr.value(env) arg = expr.value(env)
arg = arg-(env.getPC()+2) arg = arg - (env.getPC() + 2)
if arg < -128 or arg > 127: if arg < -128 or arg > 127:
if opcode == 'bra': if opcode == 'bra':
# If BRA - BRanch Always - is out of range, it's a JMP. # If BRA - BRanch Always - is out of range, it's a JMP.
node.data = ('jmp', expr) node.data = ('jmp', expr)
node.nodetype = "Absolute" node.nodetype = "Absolute"
if Cmd.warn_on_branch_extend: if Cmd.warn_on_branch_extend:
print>>sys.stderr, str(node.ppt) + ": WARNING: bra out of range, replacing with jmp" print>>sys.stderr, str(node.ppt) + ": WARNING: " \
"bra out of range, replacing with jmp"
else: else:
# Otherwise, we replace it with a 'macro' of sorts by hand: # Otherwise, we replace it with a 'macro' of sorts by hand:
# $branch LOC -> $reversed_branch ^+5; JMP LOC # $branch LOC -> $reversed_branch ^+5; JMP LOC
# We don't use temp labels here because labels need to have been fixed # We don't use temp labels here because labels need to have
# in place by this point, and JMP is always 3 bytes long. # been fixed in place by this point, and JMP is always 3
expansion = [IR.Node(node.ppt, "Relative", ExtendBranches.reversed[opcode], IR.SequenceExpr([IR.PCExpr(), "+", IR.ConstantExpr(5)])), # bytes long.
expansion = [IR.Node(node.ppt, "Relative",
ExtendBranches.reversed[opcode],
IR.SequenceExpr([IR.PCExpr(), "+",
IR.ConstantExpr(5)])),
IR.Node(node.ppt, "Absolute", 'jmp', expr)] IR.Node(node.ppt, "Absolute", 'jmp', expr)]
node.nodetype='SEQUENCE' node.nodetype = 'SEQUENCE'
node.data = expansion node.data = expansion
if Cmd.warn_on_branch_extend: if Cmd.warn_on_branch_extend:
print>>sys.stderr, str(node.ppt) + ": WARNING: "+opcode+" out of range, replacing with "+ExtendBranches.reversed[opcode] +"/jmp combo" print>>sys.stderr, str(node.ppt) + ": WARNING: " + \
self.expanded += 1 opcode + " out of range, " \
"replacing with " + \
ExtendBranches.reversed[opcode] + \
"/jmp combo"
self.changed = True
node.accept(self, env) node.accept(self, env)
else: else:
env.incPC(2) env.incPC(2)
class NormalizeModes(Pass): class NormalizeModes(Pass):
"""Eliminates the intermediate "Memory" and "Pointer" nodes, """Eliminates the intermediate "Memory" and "Pointer" nodes,
converting them to "Absolute".""" converting them to "Absolute"."""
name = "Mode Normalization pass" name = "Mode Normalization pass"
def visitMemory(self, node, env): node.nodetype = "Absolute"
def visitMemoryX(self, node, env): node.nodetype = "AbsoluteX" def visitMemory(self, node, env):
def visitMemoryY(self, node, env): node.nodetype = "AbsoluteY" node.nodetype = "Absolute"
def visitPointer(self, node, env): node.nodetype = "Indirect"
def visitPointerX(self, node, env): node.nodetype = "AbsIndX" def visitMemoryX(self, node, env):
node.nodetype = "AbsoluteX"
def visitMemoryY(self, node, env):
node.nodetype = "AbsoluteY"
def visitPointer(self, node, env):
node.nodetype = "Indirect"
def visitPointerX(self, node, env):
node.nodetype = "AbsIndX"
# If we ever hit a PointerY by this point, we have a bug. # If we ever hit a PointerY by this point, we have a bug.
def visitPointerY(self, node, env): node.nodetype = "AbsIndY"
def visitUnknown(self, node, env): pass def visitPointerY(self, node, env):
node.nodetype = "AbsIndY"
def visitUnknown(self, node, env):
pass
class Assembler(Pass): class Assembler(Pass):
"""Converts the IR into a list of bytes, suitable for writing to """Converts the IR into a list of bytes, suitable for writing to
a file.""" a file."""
name = "Assembler" name = "Assembler"
@ -436,36 +596,40 @@ class Assembler(Pass):
def postPass(self): def postPass(self):
if Cmd.print_summary and Err.count == 0: if Cmd.print_summary and Err.count == 0:
print>>sys.stderr, "Assembly complete: %s bytes output (%s code, %s data, %s filler)" \ print>>sys.stderr, "Assembly complete: %s bytes output " \
% (len(self.output), self.code, self.data, self.filler) "(%s code, %s data, %s filler)" \
% (len(self.output),
self.code, self.data, self.filler)
def outputbyte(self, expr, env): def outputbyte(self, expr, env):
'Outputs a byte, with range checking' 'Outputs a byte, with range checking'
if self.writeOK: if self.writeOK:
val = expr.value(env) val = expr.value(env)
if val < 0x00 or val > 0xff: if val < 0x00 or val > 0xff:
Err.log("Byte constant "+str(expr)+" out of range") Err.log("Byte constant " + str(expr) + " out of range")
val = 0 val = 0
self.output.append(int(val)) self.output.append(int(val))
else: else:
Err.log("Attempt to write to data segment") Err.log("Attempt to write to data segment")
def outputword(self, expr, env): def outputword(self, expr, env):
'Outputs a little-endian word, with range checking' 'Outputs a little-endian word, with range checking'
if self.writeOK: if self.writeOK:
val = expr.value(env) val = expr.value(env)
if val < 0x0000 or val > 0xFFFF: if val < 0x0000 or val > 0xFFFF:
Err.log("Word constant "+str(expr)+" out of range") Err.log("Word constant " + str(expr) + " out of range")
val = 0 val = 0
self.output.append(int(val & 0xFF)) self.output.append(int(val & 0xFF))
self.output.append(int((val >> 8) & 0xFF)) self.output.append(int((val >> 8) & 0xFF))
else: else:
Err.log("Attempt to write to data segment") Err.log("Attempt to write to data segment")
def outputdword(self, expr, env): def outputdword(self, expr, env):
'Outputs a little-endian dword, with range checking' 'Outputs a little-endian dword, with range checking'
if self.writeOK: if self.writeOK:
val = expr.value(env) val = expr.value(env)
if val < 0x00000000 or val > 0xFFFFFFFFL: if val < 0x00000000 or val > 0xFFFFFFFFL:
Err.log("DWord constant "+str(expr)+" out of range") Err.log("DWord constant " + str(expr) + " out of range")
val = 0 val = 0
self.output.append(int(val & 0xFF)) self.output.append(int(val & 0xFF))
self.output.append(int((val >> 8) & 0xFF)) self.output.append(int((val >> 8) & 0xFF))
@ -479,18 +643,19 @@ class Assembler(Pass):
if self.writeOK: if self.writeOK:
val = expr.value(env) val = expr.value(env)
if val < 0x0000 or val > 0xFFFF: if val < 0x0000 or val > 0xFFFF:
Err.log("Word constant "+str(expr)+" out of range") Err.log("Word constant " + str(expr) + " out of range")
val = 0 val = 0
self.output.append(int((val >> 8) & 0xFF)) self.output.append(int((val >> 8) & 0xFF))
self.output.append(int(val & 0xFF)) self.output.append(int(val & 0xFF))
else: else:
Err.log("Attempt to write to data segment") Err.log("Attempt to write to data segment")
def outputdword_be(self, expr, env): def outputdword_be(self, expr, env):
'Outputs a big-endian dword, with range checking' 'Outputs a big-endian dword, with range checking'
if self.writeOK: if self.writeOK:
val = expr.value(env) val = expr.value(env)
if val < 0x00000000 or val > 0xFFFFFFFFL: if val < 0x00000000 or val > 0xFFFFFFFFL:
Err.log("DWord constant "+str(expr)+" out of range") Err.log("DWord constant " + str(expr) + " out of range")
val = 0 val = 0
self.output.append(int((val >> 24) & 0xFF)) self.output.append(int((val >> 24) & 0xFF))
self.output.append(int((val >> 16) & 0xFF)) self.output.append(int((val >> 16) & 0xFF))
@ -504,77 +669,122 @@ class Assembler(Pass):
(opcode, expr) = node.data (opcode, expr) = node.data
bin_op = Ops.opcodes[opcode][mode] bin_op = Ops.opcodes[opcode][mode]
if bin_op is None: if bin_op is None:
Err.log('%s does not have mode "%s"' % (opcode.upper(), Ops.modes[mode])) Err.log('%s does not have mode "%s"' % (opcode.upper(),
Ops.modes[mode]))
return return
self.outputbyte(IR.ConstantExpr(bin_op), env) self.outputbyte(IR.ConstantExpr(bin_op), env)
arglen = Ops.lengths[mode] arglen = Ops.lengths[mode]
if mode == 14: # Special handling for relative mode if mode == 14: # Special handling for relative mode
arg = expr.value(env) arg = expr.value(env)
arg = arg-(env.getPC()+2) arg = arg - (env.getPC() + 2)
if arg < -128 or arg > 127: if arg < -128 or arg > 127:
Err.log("Branch target out of bounds") Err.log("Branch target out of bounds")
arg = 0 arg = 0
if arg < 0: arg += 256 if arg < 0:
arg += 256
expr = IR.ConstantExpr(arg) expr = IR.ConstantExpr(arg)
if arglen == 1: self.outputbyte(expr, env) if arglen == 1:
if arglen == 2: self.outputword(expr, env) self.outputbyte(expr, env)
env.incPC(1+arglen) if arglen == 2:
self.code += 1+arglen self.outputword(expr, env)
env.incPC(1 + arglen)
self.code += 1 + arglen
def visitImplied(self, node, env):
self.assemble(node, 0, env)
def visitImmediate(self, node, env):
self.assemble(node, 1, env)
def visitZeroPage(self, node, env):
self.assemble(node, 2, env)
def visitZeroPageX(self, node, env):
self.assemble(node, 3, env)
def visitZeroPageY(self, node, env):
self.assemble(node, 4, env)
def visitAbsolute(self, node, env):
self.assemble(node, 5, env)
def visitAbsoluteX(self, node, env):
self.assemble(node, 6, env)
def visitAbsoluteY(self, node, env):
self.assemble(node, 7, env)
def visitIndirect(self, node, env):
self.assemble(node, 8, env)
def visitAbsIndX(self, node, env):
self.assemble(node, 9, env)
def visitAbsIndY(self, node, env):
self.assemble(node, 10, env)
def visitZPIndirect(self, node, env):
self.assemble(node, 11, env)
def visitIndirectX(self, node, env):
self.assemble(node, 12, env)
def visitIndirectY(self, node, env):
self.assemble(node, 13, env)
def visitRelative(self, node, env):
self.assemble(node, 14, env)
def visitLabel(self, node, env):
pass
def visitImplied(self, node, env): self.assemble(node, 0, env)
def visitImmediate(self, node, env): self.assemble(node, 1, env)
def visitZeroPage(self, node, env): self.assemble(node, 2, env)
def visitZeroPageX(self, node, env): self.assemble(node, 3, env)
def visitZeroPageY(self, node, env): self.assemble(node, 4, env)
def visitAbsolute(self, node, env): self.assemble(node, 5, env)
def visitAbsoluteX(self, node, env): self.assemble(node, 6, env)
def visitAbsoluteY(self, node, env): self.assemble(node, 7, env)
def visitIndirect(self, node, env): self.assemble(node, 8, env)
def visitAbsIndX(self, node, env): self.assemble(node, 9, env)
def visitAbsIndY(self, node, env): self.assemble(node, 10, env)
def visitZPIndirect(self, node, env): self.assemble(node, 11, env)
def visitIndirectX(self, node, env): self.assemble(node, 12, env)
def visitIndirectY(self, node, env): self.assemble(node, 13, env)
def visitRelative(self, node, env): self.assemble(node, 14, env)
def visitLabel(self, node, env): pass
def visitByte(self, node, env): def visitByte(self, node, env):
for expr in node.data: for expr in node.data:
self.outputbyte(expr, env) self.outputbyte(expr, env)
env.incPC(len(node.data)) env.incPC(len(node.data))
self.data += len(node.data) self.data += len(node.data)
def visitWord(self, node, env): def visitWord(self, node, env):
for expr in node.data: for expr in node.data:
self.outputword(expr, env) self.outputword(expr, env)
env.incPC(len(node.data)*2) env.incPC(len(node.data) * 2)
self.data += len(node.data)*2 self.data += len(node.data) * 2
def visitDword(self, node, env): def visitDword(self, node, env):
for expr in node.data: for expr in node.data:
self.outputdword(expr, env) self.outputdword(expr, env)
env.incPC(len(node.data)*4) env.incPC(len(node.data) * 4)
self.data += len(node.data)*4 self.data += len(node.data) * 4
def visitWordBE(self, node, env): def visitWordBE(self, node, env):
for expr in node.data: for expr in node.data:
self.outputword_be(expr, env) self.outputword_be(expr, env)
env.incPC(len(node.data)*2) env.incPC(len(node.data) * 2)
self.data += len(node.data)*2 self.data += len(node.data) * 2
def visitDwordBE(self, node, env): def visitDwordBE(self, node, env):
for expr in node.data: for expr in node.data:
self.outputdword_be(expr, env) self.outputdword_be(expr, env)
env.incPC(len(node.data)*4) env.incPC(len(node.data) * 4)
self.data += len(node.data)*4 self.data += len(node.data) * 4
def visitSetPC(self, node, env):
def visitSetPC(self, node, env):
env.setPC(node.data[0].value(env)) env.setPC(node.data[0].value(env))
def visitCheckPC(self, node, env): def visitCheckPC(self, node, env):
pc = env.getPC() pc = env.getPC()
target = node.data[0].value(env) target = node.data[0].value(env)
if (pc > target): if (pc > target):
Err.log(".checkpc assertion failed: $%x > $%x" % (pc, target)) Err.log(".checkpc assertion failed: $%x > $%x" % (pc, target))
def visitAdvance(self, node, env):
def visitAdvance(self, node, env):
pc = env.getPC() pc = env.getPC()
target = node.data[0].value(env) target = node.data[0].value(env)
if (pc > target): if (pc > target):
Err.log("Attempted to .advance backwards: $%x to $%x" % (pc, target)) Err.log("Attempted to .advance backwards: $%x to $%x" %
(pc, target))
else: else:
for i in xrange(target-pc): self.outputbyte(node.data[1], env) for i in xrange(target - pc):
self.filler += target-pc self.outputbyte(node.data[1], env)
self.filler += target - pc
env.setPC(target) env.setPC(target)

View File

@ -155,4 +155,4 @@ Section Uninstall
DeleteRegKey ${PRODUCT_UNINST_ROOT_KEY} "${PRODUCT_UNINST_KEY}" DeleteRegKey ${PRODUCT_UNINST_ROOT_KEY} "${PRODUCT_UNINST_KEY}"
DeleteRegKey HKLM "${PRODUCT_DIR_REGKEY}" DeleteRegKey HKLM "${PRODUCT_DIR_REGKEY}"
SetAutoClose true SetAutoClose true
SectionEnd SectionEnd

View File

@ -6,6 +6,11 @@ setup(name='Ophis',
author="Michael Martin", author="Michael Martin",
author_email="mcmartin@gmail.com", author_email="mcmartin@gmail.com",
license="MIT", license="MIT",
long_description="Ophis is a cross-assembler for the 65xx series of chips. It supports the stock 6502 opcodes, the 65c02 extensions, and syntax for the \"undocumented opcodes\" in the 6510 chip used on the Commodore 64. (Syntax for these opcodes matches those given in the VICE team's documentation.)", long_description="Ophis is a cross-assembler for the 65xx series of "
"chips. It supports the stock 6502 opcodes, the 65c02 "
"extensions, and syntax for the \"undocumented "
"opcodes\" in the 6510 chip used on the Commodore 64. "
"(Syntax for these opcodes matches those given in the "
"VICE team's documentation.)",
packages=['Ophis'], packages=['Ophis'],
scripts=['scripts/ophis']) scripts=['scripts/ophis'])

View File

@ -1,9 +1,10 @@
from distutils.core import setup from distutils.core import setup
import py2exe, sys import py2exe
import sys
sys.argv.append('py2exe') sys.argv.append('py2exe')
setup(options = {'py2exe': {'bundle_files': 1}}, setup(options={'py2exe': {'bundle_files': 1}},
packages = ['Ophis'], packages=['Ophis'],
zipfile = None, zipfile=None,
console = [{'script': "scripts/ophis"}]) console=[{'script': "scripts/ophis"}])

View File

@ -51,4 +51,4 @@ late:
jmp early jmp early
* bne + * bne +
jmp early jmp early
* *

View File

@ -76,4 +76,4 @@
ISB $F7, X ISB $F7, X
ISB $FBFB, Y ISB $FBFB, Y
ISB $FFFF, X ISB $FFFF, X

View File

@ -25,7 +25,7 @@
AND ($32) ; 32: AND - (Zero Page) AND ($32) ; 32: AND - (Zero Page)
BIT $34, X ; 34: BIT - Zero Page, X BIT $34, X ; 34: BIT - Zero Page, X
RMB3 $37 ; 37: RMB3 - Zero Page RMB3 $37 ; 37: RMB3 - Zero Page
DEA ; 3A: DEA - Implied DEA ; 3A: DEA - Implied
DEC ; 3A: DEC - Implied DEC ; 3A: DEC - Implied
BIT $3C3C,X ; 3C: BIT - Absolute, X BIT $3C3C,X ; 3C: BIT - Absolute, X
BBR3 ^+$41 ; 3F: BBR3 - Relative BBR3 ^+$41 ; 3F: BBR3 - Relative

View File

@ -1,157 +1,157 @@
; Test file for base 6502 opcode compliance ; Test file for base 6502 opcode compliance
; This odd little source file uses every addressing mode ; This odd little source file uses every addressing mode
; of every opcode, and uses the opcode itself as the argument ; of every opcode, and uses the opcode itself as the argument
; to each instruction that takes one. The resulting binary's ; to each instruction that takes one. The resulting binary's
; bytes are thus in strictly increasing numerical order. ; bytes are thus in strictly increasing numerical order.
BRK BRK
ORA ($01, X) ORA ($01, X)
ORA $05 ORA $05
ASL $06 ASL $06
PHP PHP
ORA #$09 ORA #$09
ASL ASL
ORA $0D0D ORA $0D0D
ASL $0E0E ASL $0E0E
BPL ^+$12 BPL ^+$12
ORA ($11), Y ORA ($11), Y
ORA $15, X ORA $15, X
ASL $16, X ASL $16, X
CLC CLC
ORA $1919, Y ORA $1919, Y
ORA $1D1D, X ORA $1D1D, X
ASL $1E1E, X ASL $1E1E, X
JSR $2020 JSR $2020
AND ($21, X) AND ($21, X)
BIT $24 BIT $24
AND $25 AND $25
ROL $26 ROL $26
PLP PLP
AND #$29 AND #$29
ROL ROL
BIT $2C2C BIT $2C2C
AND $2D2D AND $2D2D
ROL $2E2E ROL $2E2E
BMI ^+$32 BMI ^+$32
AND ($31), Y AND ($31), Y
AND $35, X AND $35, X
ROL $36, X ROL $36, X
SEC SEC
AND $3939, Y AND $3939, Y
AND $3D3D, X AND $3D3D, X
ROL $3E3E, X ROL $3E3E, X
RTI RTI
EOR ($41, X) EOR ($41, X)
EOR $45 EOR $45
LSR $46 LSR $46
PHA PHA
EOR #$49 EOR #$49
LSR LSR
JMP $4C4C JMP $4C4C
EOR $4D4D EOR $4D4D
LSR $4E4E LSR $4E4E
BVC ^+$52 BVC ^+$52
EOR ($51), Y EOR ($51), Y
EOR $55, X EOR $55, X
LSR $56, X LSR $56, X
CLI CLI
EOR $5959, Y EOR $5959, Y
EOR $5D5D, X EOR $5D5D, X
LSR $5E5E, X LSR $5E5E, X
RTS RTS
ADC ($61, X) ADC ($61, X)
ADC $65 ADC $65
ROR $66 ROR $66
PLA PLA
ADC #$69 ADC #$69
ROR ROR
JMP ($6C6C) JMP ($6C6C)
ADC $6D6D ADC $6D6D
ROR $6E6E ROR $6E6E
BVS ^+$72 BVS ^+$72
ADC ($71), Y ADC ($71), Y
ADC $75, X ADC $75, X
ROR $76, X ROR $76, X
SEI SEI
ADC $7979, Y ADC $7979, Y
ADC $7D7D, X ADC $7D7D, X
ROR $7E7E, X ROR $7E7E, X
STA ($81, X) STA ($81, X)
STY $84 STY $84
STA $85 STA $85
STX $86 STX $86
DEY DEY
TXA TXA
STY $8C8C STY $8C8C
STA $8D8D STA $8D8D
STX $8E8E STX $8E8E
BCC ^-$6E BCC ^-$6E
STA ($91), Y STA ($91), Y
STY $94, X STY $94, X
STA $95, X STA $95, X
STX $96, Y STX $96, Y
TYA TYA
STA $9999, Y STA $9999, Y
TXS TXS
STA $9D9D, X STA $9D9D, X
LDY #$A0 LDY #$A0
LDA ($A1, X) LDA ($A1, X)
LDX #$A2 LDX #$A2
LDY $A4 LDY $A4
LDA $A5 LDA $A5
LDX $A6 LDX $A6
TAY TAY
LDA #$A9 LDA #$A9
TAX TAX
LDY $ACAC LDY $ACAC
LDA $ADAD LDA $ADAD
LDX $AEAE LDX $AEAE
BCS ^-$4e BCS ^-$4e
LDA ($B1), Y LDA ($B1), Y
LDY $B4, X LDY $B4, X
LDA $B5, X LDA $B5, X
LDX $B6, Y LDX $B6, Y
CLV CLV
LDA $B9B9,Y LDA $B9B9,Y
TSX TSX
LDY $BCBC, X LDY $BCBC, X
LDA $BDBD, X LDA $BDBD, X
LDX $BEBE, Y LDX $BEBE, Y
CPY #$C0 CPY #$C0
CMP ($C1, X) CMP ($C1, X)
CPY $C4 CPY $C4
CMP $C5 CMP $C5
DEC $C6 DEC $C6
INY INY
CMP #$C9 CMP #$C9
DEX DEX
CPY $CCCC CPY $CCCC
CMP $CDCD CMP $CDCD
DEC $CECE DEC $CECE
BNE ^-$2E BNE ^-$2E
CMP ($D1), Y CMP ($D1), Y
CMP $D5, X CMP $D5, X
DEC $D6, X DEC $D6, X
CLD CLD
CMP $D9D9, Y CMP $D9D9, Y
CMP $DDDD, X CMP $DDDD, X
DEC $DEDE, X DEC $DEDE, X
CPX #$E0 CPX #$E0
SBC ($E1, X) SBC ($E1, X)
CPX $E4 CPX $E4
SBC $E5 SBC $E5
INC $E6 INC $E6
INX INX
SBC #$E9 SBC #$E9
NOP NOP
CPX $ECEC CPX $ECEC
SBC $EDED SBC $EDED
INC $EEEE INC $EEEE
BEQ ^-$0E BEQ ^-$0E
SBC ($F1), Y SBC ($F1), Y
SBC $F5, X SBC $F5, X
INC $F6, X INC $F6, X
SED SED
SBC $F9F9, Y SBC $F9F9, Y
SBC $FDFD, X SBC $FDFD, X
INC $FEFE, X INC $FEFE, X

View File

@ -10,11 +10,13 @@ normmap = ''.join([bits[x] for x in norm])
ivrsmap = ''.join([bits[x] for x in ivrs]) ivrsmap = ''.join([bits[x] for x in ivrs])
blnkmap = ''.join([bits[x] for x in blnk]) blnkmap = ''.join([bits[x] for x in blnk])
def dumpfile(n, m): def dumpfile(n, m):
f = file(n, 'wb') f = file(n, 'wb')
f.write(m) f.write(m)
f.close() f.close()
dumpfile('a2normal.map', normmap) dumpfile('a2normal.map', normmap)
dumpfile('a2inverse.map', ivrsmap) dumpfile('a2inverse.map', ivrsmap)
dumpfile('a2blink.map', blnkmap) dumpfile('a2blink.map', blnkmap)

View File

@ -3,7 +3,7 @@ import sys
verbose = 0 verbose = 0
prologue = '"""' +"""Opcodes file. prologue = '"""' + """Opcodes file.
Tables for the assembly of 6502-family instructions, mapping Tables for the assembly of 6502-family instructions, mapping
opcodes and addressing modes to binary instructions.""" + '"""' + """ opcodes and addressing modes to binary instructions.""" + '"""' + """
@ -17,37 +17,38 @@ prologue = '"""' +"""Opcodes file.
# the tables in tools/opcodes. Edit those tables, not these. # the tables in tools/opcodes. Edit those tables, not these.
# Names of addressing modes # Names of addressing modes
modes = ["Implied", # 0 modes = ["Implied", # 0
"Immediate", # 1 "Immediate", # 1
"Zero Page", # 2 "Zero Page", # 2
"Zero Page, X", # 3 "Zero Page, X", # 3
"Zero Page, Y", # 4 "Zero Page, Y", # 4
"Absolute", # 5 "Absolute", # 5
"Absolute, X", # 6 "Absolute, X", # 6
"Absolute, Y", # 7 "Absolute, Y", # 7
"(Absolute)", # 8 "(Absolute)", # 8
"(Absolute, X)", # 9 "(Absolute, X)", # 9
"(Absolute), Y", # 10 "(Absolute), Y", # 10
"(Zero Page)", # 11 "(Zero Page)", # 11
"(Zero Page, X)", # 12 "(Zero Page, X)", # 12
"(Zero Page), Y", # 13 "(Zero Page), Y", # 13
"Relative"] # 14 "Relative"] # 14
# Lengths of the argument # Lengths of the argument
lengths = [0, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1] lengths = [0, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1]
""" """
# These values should match the ones in the prologue string. # These values should match the ones in the prologue string.
modes = ["Implied", # 0 modes = ["Implied", # 0
"Immediate", # 1 "Immediate", # 1
"Zero Page", # 2 "Zero Page", # 2
"Zero Page, X", # 3 "Zero Page, X", # 3
"Zero Page, Y", # 4 "Zero Page, Y", # 4
"Absolute", # 5 "Absolute", # 5
"Absolute, X", # 6 "Absolute, X", # 6
"Absolute, Y", # 7 "Absolute, Y", # 7
"(Absolute)", # 8 "(Absolute)", # 8
"(Absolute, X)", # 9 "(Absolute, X)", # 9
"(Absolute), Y", # 10 "(Absolute), Y", # 10
"(Zero Page)", # 11 "(Zero Page)", # 11
"(Zero Page, X)", # 12 "(Zero Page, X)", # 12
@ -56,24 +57,28 @@ modes = ["Implied", # 0
flatmodes = [x.lower() for x in modes] flatmodes = [x.lower() for x in modes]
# WARNING: This decommenter assumes that # never appears anywhere else # WARNING: This decommenter assumes that # never appears anywhere else
# in a line. # in a line.
def decomment (l): def decomment(l):
if '#' in l: if '#' in l:
l = l[:l.index('#')] l = l[:l.index('#')]
return l.strip() return l.strip()
def decomment_readlines (fname):
result = [decomment(x) for x in file(fname).readlines()]
return [x for x in result if len(x) > 0]
def parse_chipset_file (fname): def decomment_readlines(fname):
result = [decomment(x) for x in file(fname).readlines()]
return [x for x in result if len(x) > 0]
def parse_chipset_file(fname):
result = [None] * 256 result = [None] * 256
ls = [[x.strip() for x in y] for y in [z.split(':', 1) for z in decomment_readlines (fname)]] ls = [[x.strip() for x in y]
for y in [z.split(':', 1) for z in decomment_readlines(fname)]]
for l in ls: for l in ls:
if len(l) == 2: if len(l) == 2:
try: try:
op = int (l[0], 16) op = int(l[0], 16)
syns = l[1].split(';') syns = l[1].split(';')
for s in syns: for s in syns:
s_p = s.split('-') s_p = s.split('-')
@ -81,19 +86,20 @@ def parse_chipset_file (fname):
mnem = s_p[0].lower().strip() mnem = s_p[0].lower().strip()
mode = s_p[1].lower().strip() mode = s_p[1].lower().strip()
if mode in flatmodes: if mode in flatmodes:
if result[op] == None: if result[op] is None:
result[op] = [] result[op] = []
result[op].append((mnem, flatmodes.index(mode))) result[op].append((mnem, flatmodes.index(mode)))
else: else:
print "Unknown mode '%s'" % s_p[1] print "Unknown mode '%s'" % s_p[1]
except ValueError: except ValueError:
print "Illegal opcode '%s'" % l[0] print "Illegal opcode '%s'" % l[0]
return result return result
def collate_chipset_map (cs_list, base):
def collate_chipset_map(cs_list, base):
result = {} result = {}
for (opcode, insts) in zip (range(256), cs_list): for (opcode, insts) in zip(range(256), cs_list):
if insts != None: if insts is not None:
for inst in insts: for inst in insts:
(mnem, mode) = inst (mnem, mode) = inst
if mnem not in result: if mnem not in result:
@ -115,19 +121,26 @@ def collate_chipset_map (cs_list, base):
del result[x] del result[x]
return result return result
def mapval(x): def mapval(x):
if x is None: if x is None:
return "None" return "None"
else: else:
return "0x%02X" % x return "0x%02X" % x
def dump_map (m, prologue = ''):
def dump_map(m, prologue=''):
mnems = m.keys() mnems = m.keys()
mnems.sort() mnems.sort()
for mnem in mnems: for mnem in mnems:
print "%s'%s': [%s]," % (prologue, mnem, ', '.join([mapval(x) for x in m[mnem]])) codes = [mapval(x) for x in m[mnem]]
print "%s'%s': [%s,\n%s %s]," % (prologue, mnem,
', '.join(codes[:8]),
prologue + " " * len(mnem),
', '.join(codes[8:]))
if __name__=='__main__':
if __name__ == '__main__':
if len(sys.argv) > 1: if len(sys.argv) > 1:
chipsets = argv[1:] chipsets = argv[1:]
else: else:
@ -135,7 +148,8 @@ if __name__=='__main__':
archs = [] archs = []
for x in chipsets: for x in chipsets:
try: try:
ls = [[x.strip() for x in y] for y in [z.split(':', 1) for z in decomment_readlines (x)]] ls = [[x.strip() for x in y]
for y in [z.split(':', 1) for z in decomment_readlines(x)]]
for l in ls: for l in ls:
if len(l) != 2: if len(l) != 2:
print "Could not parse the chipset line '%s'" % ":".join(l) print "Could not parse the chipset line '%s'" % ":".join(l)
@ -147,10 +161,9 @@ if __name__=='__main__':
baseset = None baseset = None
for (field, fname) in archs: for (field, fname) in archs:
chipset_list = parse_chipset_file(fname) chipset_list = parse_chipset_file(fname)
instruction_map = collate_chipset_map (chipset_list, baseset) instruction_map = collate_chipset_map(chipset_list, baseset)
if baseset == None: if baseset is None:
baseset = instruction_map baseset = instruction_map
print "%s = {" % field print "%s = {" % field
dump_map (instruction_map, ' ' * (len(field) + 4)) dump_map(instruction_map, ' ' * (len(field) + 4))
print "%s}" % (' ' * (len(field) + 3)) print "%s}" % (' ' * (len(field) + 3))
print ""

View File

@ -1,256 +1,256 @@
00: BRK - Implied 00: BRK - Implied
01: ORA - (Zero Page, X) 01: ORA - (Zero Page, X)
02: 02:
03: 03:
04: 04:
05: ORA - Zero Page 05: ORA - Zero Page
06: ASL - Zero Page 06: ASL - Zero Page
07: 07:
08: PHP - Implied 08: PHP - Implied
09: ORA - Immediate 09: ORA - Immediate
0A: ASL - Implied 0A: ASL - Implied
0B: 0B:
0C: 0C:
0D: ORA - Absolute 0D: ORA - Absolute
0E: ASL - Absolute 0E: ASL - Absolute
0F: 0F:
10: BPL - Relative 10: BPL - Relative
11: ORA - (Zero Page), Y 11: ORA - (Zero Page), Y
12: 12:
13: 13:
14: 14:
15: ORA - Zero Page, X 15: ORA - Zero Page, X
16: ASL - Zero Page, X 16: ASL - Zero Page, X
17: 17:
18: CLC - Implied 18: CLC - Implied
19: ORA - Absolute, Y 19: ORA - Absolute, Y
1A: 1A:
1B: 1B:
1C: 1C:
1D: ORA - Absolute, X 1D: ORA - Absolute, X
1E: ASL - Absolute, X 1E: ASL - Absolute, X
1F: 1F:
20: JSR - Absolute 20: JSR - Absolute
21: AND - (Zero Page, X) 21: AND - (Zero Page, X)
22: 22:
23: 23:
24: BIT - Zero Page 24: BIT - Zero Page
25: AND - Zero Page 25: AND - Zero Page
26: ROL - Zero Page 26: ROL - Zero Page
27: 27:
28: PLP - Implied 28: PLP - Implied
29: AND - Immediate 29: AND - Immediate
2A: ROL - Implied 2A: ROL - Implied
2B: 2B:
2C: BIT - Absolute 2C: BIT - Absolute
2D: AND - Absolute 2D: AND - Absolute
2E: ROL - Absolute 2E: ROL - Absolute
2F: 2F:
30: BMI - Relative 30: BMI - Relative
31: AND - (Zero Page), Y 31: AND - (Zero Page), Y
32: 32:
33: 33:
34: 34:
35: AND - Zero Page, X 35: AND - Zero Page, X
36: ROL - Zero Page, X 36: ROL - Zero Page, X
37: 37:
38: SEC - Implied 38: SEC - Implied
39: AND - Absolute, Y 39: AND - Absolute, Y
3A: 3A:
3B: 3B:
3C: 3C:
3D: AND - Absolute, X 3D: AND - Absolute, X
3E: ROL - Absolute, X 3E: ROL - Absolute, X
3F: 3F:
40: RTI - Implied 40: RTI - Implied
41: EOR - (Zero Page, X) 41: EOR - (Zero Page, X)
42: 42:
43: 43:
44: 44:
45: EOR - Zero Page 45: EOR - Zero Page
46: LSR - Zero Page 46: LSR - Zero Page
47: 47:
48: PHA - Implied 48: PHA - Implied
49: EOR - Immediate 49: EOR - Immediate
4A: LSR - Implied 4A: LSR - Implied
4B: 4B:
4C: JMP - Absolute 4C: JMP - Absolute
4D: EOR - Absolute 4D: EOR - Absolute
4E: LSR - Absolute 4E: LSR - Absolute
4F: 4F:
50: BVC - Relative 50: BVC - Relative
51: EOR - (Zero Page), Y 51: EOR - (Zero Page), Y
52: 52:
53: 53:
54: 54:
55: EOR - Zero Page, X 55: EOR - Zero Page, X
56: LSR - Zero Page, X 56: LSR - Zero Page, X
57: 57:
58: CLI - Implied 58: CLI - Implied
59: EOR - Absolute, Y 59: EOR - Absolute, Y
5A: 5A:
5B: 5B:
5C: 5C:
5D: EOR - Absolute, X 5D: EOR - Absolute, X
5E: LSR - Absolute, X 5E: LSR - Absolute, X
5F: 5F:
60: RTS - Implied 60: RTS - Implied
61: ADC - (Zero Page, X) 61: ADC - (Zero Page, X)
62: 62:
63: 63:
64: 64:
65: ADC - Zero Page 65: ADC - Zero Page
66: ROR - Zero Page 66: ROR - Zero Page
67: 67:
68: PLA - Implied 68: PLA - Implied
69: ADC - Immediate 69: ADC - Immediate
6A: ROR - Implied 6A: ROR - Implied
6B: 6B:
6C: JMP - (Absolute) 6C: JMP - (Absolute)
6D: ADC - Absolute 6D: ADC - Absolute
6E: ROR - Absolute 6E: ROR - Absolute
6F: 6F:
70: BVS - Relative 70: BVS - Relative
71: ADC - (Zero Page), Y 71: ADC - (Zero Page), Y
72: 72:
73: 73:
74: 74:
75: ADC - Zero Page, X 75: ADC - Zero Page, X
76: ROR - Zero Page, X 76: ROR - Zero Page, X
77: 77:
78: SEI - Implied 78: SEI - Implied
79: ADC - Absolute, Y 79: ADC - Absolute, Y
7A: 7A:
7B: 7B:
7C: 7C:
7D: ADC - Absolute, X 7D: ADC - Absolute, X
7E: ROR - Absolute, X 7E: ROR - Absolute, X
7F: 7F:
80: 80:
81: STA - (Zero Page, X) 81: STA - (Zero Page, X)
82: 82:
83: 83:
84: STY - Zero Page 84: STY - Zero Page
85: STA - Zero Page 85: STA - Zero Page
86: STX - Zero Page 86: STX - Zero Page
87: 87:
88: DEY - Implied 88: DEY - Implied
89: 89:
8A: TXA - Implied 8A: TXA - Implied
8B: 8B:
8C: STY - Absolute 8C: STY - Absolute
8D: STA - Absolute 8D: STA - Absolute
8E: STX - Absolute 8E: STX - Absolute
8F: 8F:
90: BCC - Relative 90: BCC - Relative
91: STA - (Zero Page), Y 91: STA - (Zero Page), Y
92: 92:
93: 93:
94: STY - Zero Page, X 94: STY - Zero Page, X
95: STA - Zero Page, X 95: STA - Zero Page, X
96: STX - Zero Page, Y 96: STX - Zero Page, Y
97: 97:
98: TYA - Implied 98: TYA - Implied
99: STA - Absolute, Y 99: STA - Absolute, Y
9A: TXS - Implied 9A: TXS - Implied
9B: 9B:
9C: 9C:
9D: STA - Absolute, X 9D: STA - Absolute, X
9E: 9E:
9F: 9F:
A0: LDY - Immediate A0: LDY - Immediate
A1: LDA - (Zero Page, X) A1: LDA - (Zero Page, X)
A2: LDX - Immediate A2: LDX - Immediate
A3: A3:
A4: LDY - Zero Page A4: LDY - Zero Page
A5: LDA - Zero Page A5: LDA - Zero Page
A6: LDX - Zero Page A6: LDX - Zero Page
A7: A7:
A8: TAY - Implied A8: TAY - Implied
A9: LDA - Immediate A9: LDA - Immediate
AA: TAX - Implied AA: TAX - Implied
AB: AB:
AC: LDY - Absolute AC: LDY - Absolute
AD: LDA - Absolute AD: LDA - Absolute
AE: LDX - Absolute AE: LDX - Absolute
AF: AF:
B0: BCS - Relative B0: BCS - Relative
B1: LDA - (Zero Page), Y B1: LDA - (Zero Page), Y
B2: B2:
B3: B3:
B4: LDY - Zero Page, X B4: LDY - Zero Page, X
B5: LDA - Zero Page, X B5: LDA - Zero Page, X
B6: LDX - Zero Page, Y B6: LDX - Zero Page, Y
B7: B7:
B8: CLV - Implied B8: CLV - Implied
B9: LDA - Absolute, Y B9: LDA - Absolute, Y
BA: TSX - Implied BA: TSX - Implied
BB: BB:
BC: LDY - Absolute, X BC: LDY - Absolute, X
BD: LDA - Absolute, X BD: LDA - Absolute, X
BE: LDX - Absolute, Y BE: LDX - Absolute, Y
BF: BF:
C0: CPY - Immediate C0: CPY - Immediate
C1: CMP - (Zero Page, X) C1: CMP - (Zero Page, X)
C2: C2:
C3: C3:
C4: CPY - Zero Page C4: CPY - Zero Page
C5: CMP - Zero Page C5: CMP - Zero Page
C6: DEC - Zero Page C6: DEC - Zero Page
C7: C7:
C8: INY - Implied C8: INY - Implied
C9: CMP - Immediate C9: CMP - Immediate
CA: DEX - Implied CA: DEX - Implied
CB: CB:
CC: CPY - Absolute CC: CPY - Absolute
CD: CMP - Absolute CD: CMP - Absolute
CE: DEC - Absolute CE: DEC - Absolute
CF: CF:
D0: BNE - Relative D0: BNE - Relative
D1: CMP - (Zero Page), Y D1: CMP - (Zero Page), Y
D2: D2:
D3: D3:
D4: D4:
D5: CMP - Zero Page, X D5: CMP - Zero Page, X
D6: DEC - Zero Page, X D6: DEC - Zero Page, X
D7: D7:
D8: CLD - Implied D8: CLD - Implied
D9: CMP - Absolute, Y D9: CMP - Absolute, Y
DA: DA:
DB: DB:
DC: DC:
DD: CMP - Absolute, X DD: CMP - Absolute, X
DE: DEC - Absolute, X DE: DEC - Absolute, X
DF: DF:
E0: CPX - Immediate E0: CPX - Immediate
E1: SBC - (Zero Page, X) E1: SBC - (Zero Page, X)
E2: E2:
E3: E3:
E4: CPX - Zero Page E4: CPX - Zero Page
E5: SBC - Zero Page E5: SBC - Zero Page
E6: INC - Zero Page E6: INC - Zero Page
E7: E7:
E8: INX - Implied E8: INX - Implied
E9: SBC - Immediate E9: SBC - Immediate
EA: NOP - Implied EA: NOP - Implied
EB: EB:
EC: CPX - Absolute EC: CPX - Absolute
ED: SBC - Absolute ED: SBC - Absolute
EE: INC - Absolute EE: INC - Absolute
EF: EF:
F0: BEQ - Relative F0: BEQ - Relative
F1: SBC - (Zero Page), Y F1: SBC - (Zero Page), Y
F2: F2:
F3: F3:
F4: F4:
F5: SBC - Zero Page, X F5: SBC - Zero Page, X
F6: INC - Zero Page, X F6: INC - Zero Page, X
F7: F7:
F8: SED - Implied F8: SED - Implied
F9: SBC - Absolute, Y F9: SBC - Absolute, Y
FA: FA:
FB: FB:
FC: FC:
FD: SBC - Absolute, X FD: SBC - Absolute, X
FE: INC - Absolute, X FE: INC - Absolute, X
FF: FF:

View File

@ -1,8 +1,8 @@
00: BRK - Implied 00: BRK - Implied
01: ORA - (Zero Page, X) 01: ORA - (Zero Page, X)
02: 02:
03: SLO - (Zero Page, X) 03: SLO - (Zero Page, X)
04: NOP - Zero Page 04: NOP - Zero Page
05: ORA - Zero Page 05: ORA - Zero Page
06: ASL - Zero Page 06: ASL - Zero Page
07: SLO - Zero Page 07: SLO - Zero Page
@ -10,29 +10,29 @@
09: ORA - Immediate 09: ORA - Immediate
0A: ASL - Implied 0A: ASL - Implied
0B: ANC - Immediate 0B: ANC - Immediate
0C: 0C:
0D: ORA - Absolute 0D: ORA - Absolute
0E: ASL - Absolute 0E: ASL - Absolute
0F: SLO - Absolute 0F: SLO - Absolute
10: BPL - Relative 10: BPL - Relative
11: ORA - (Zero Page), Y 11: ORA - (Zero Page), Y
12: 12:
13: SLO - (Zero Page), Y 13: SLO - (Zero Page), Y
14: 14:
15: ORA - Zero Page, X 15: ORA - Zero Page, X
16: ASL - Zero Page, X 16: ASL - Zero Page, X
17: SLO - Zero Page, X 17: SLO - Zero Page, X
18: CLC - Implied 18: CLC - Implied
19: ORA - Absolute, Y 19: ORA - Absolute, Y
1A: 1A:
1B: SLO - Absolute, Y 1B: SLO - Absolute, Y
1C: 1C:
1D: ORA - Absolute, X 1D: ORA - Absolute, X
1E: ASL - Absolute, X 1E: ASL - Absolute, X
1F: SLO - Absolute, X 1F: SLO - Absolute, X
20: JSR - Absolute 20: JSR - Absolute
21: AND - (Zero Page, X) 21: AND - (Zero Page, X)
22: 22:
23: RLA - (Zero Page, X) 23: RLA - (Zero Page, X)
24: BIT - Zero Page 24: BIT - Zero Page
25: AND - Zero Page 25: AND - Zero Page
@ -41,32 +41,32 @@
28: PLP - Implied 28: PLP - Implied
29: AND - Immediate 29: AND - Immediate
2A: ROL - Implied 2A: ROL - Implied
2B: 2B:
2C: BIT - Absolute 2C: BIT - Absolute
2D: AND - Absolute 2D: AND - Absolute
2E: ROL - Absolute 2E: ROL - Absolute
2F: RLA - Absolute 2F: RLA - Absolute
30: BMI - Relative 30: BMI - Relative
31: AND - (Zero Page), Y 31: AND - (Zero Page), Y
32: 32:
33: RLA - (Zero Page), Y 33: RLA - (Zero Page), Y
34: 34:
35: AND - Zero Page, X 35: AND - Zero Page, X
36: ROL - Zero Page, X 36: ROL - Zero Page, X
37: RLA - Zero Page, X 37: RLA - Zero Page, X
38: SEC - Implied 38: SEC - Implied
39: AND - Absolute, Y 39: AND - Absolute, Y
3A: 3A:
3B: RLA - Absolute, Y 3B: RLA - Absolute, Y
3C: 3C:
3D: AND - Absolute, X 3D: AND - Absolute, X
3E: ROL - Absolute, X 3E: ROL - Absolute, X
3F: RLA - Absolute, X 3F: RLA - Absolute, X
40: RTI - Implied 40: RTI - Implied
41: EOR - (Zero Page, X) 41: EOR - (Zero Page, X)
42: 42:
43: SRE - (Zero Page, X) 43: SRE - (Zero Page, X)
44: 44:
45: EOR - Zero Page 45: EOR - Zero Page
46: LSR - Zero Page 46: LSR - Zero Page
47: SRE - Zero Page 47: SRE - Zero Page
@ -80,25 +80,25 @@
4F: SRE - Absolute 4F: SRE - Absolute
50: BVC - Relative 50: BVC - Relative
51: EOR - (Zero Page), Y 51: EOR - (Zero Page), Y
52: 52:
53: SRE - (Zero Page), Y 53: SRE - (Zero Page), Y
54: 54:
55: EOR - Zero Page, X 55: EOR - Zero Page, X
56: LSR - Zero Page, X 56: LSR - Zero Page, X
57: SRE - Zero Page, X 57: SRE - Zero Page, X
58: CLI - Implied 58: CLI - Implied
59: EOR - Absolute, Y 59: EOR - Absolute, Y
5A: 5A:
5B: SRE - Absolute, Y 5B: SRE - Absolute, Y
5C: 5C:
5D: EOR - Absolute, X 5D: EOR - Absolute, X
5E: LSR - Absolute, X 5E: LSR - Absolute, X
5F: SRE - Absolute, X 5F: SRE - Absolute, X
60: RTS - Implied 60: RTS - Implied
61: ADC - (Zero Page, X) 61: ADC - (Zero Page, X)
62: 62:
63: RRA - (Zero Page, X) 63: RRA - (Zero Page, X)
64: 64:
65: ADC - Zero Page 65: ADC - Zero Page
66: ROR - Zero Page 66: ROR - Zero Page
67: RRA - Zero Page 67: RRA - Zero Page
@ -112,30 +112,30 @@
6F: RRA - Absolute 6F: RRA - Absolute
70: BVS - Relative 70: BVS - Relative
71: ADC - (Zero Page), Y 71: ADC - (Zero Page), Y
72: 72:
73: RRA - (Zero Page), Y 73: RRA - (Zero Page), Y
74: 74:
75: ADC - Zero Page, X 75: ADC - Zero Page, X
76: ROR - Zero Page, X 76: ROR - Zero Page, X
77: RRA - Zero Page, X 77: RRA - Zero Page, X
78: SEI - Implied 78: SEI - Implied
79: ADC - Absolute, Y 79: ADC - Absolute, Y
7A: 7A:
7B: RRA - Absolute, Y 7B: RRA - Absolute, Y
7C: 7C:
7D: ADC - Absolute, X 7D: ADC - Absolute, X
7E: ROR - Absolute, X 7E: ROR - Absolute, X
7F: RRA - Absolute, X 7F: RRA - Absolute, X
80: 80:
81: STA - (Zero Page, X) 81: STA - (Zero Page, X)
82: 82:
83: SAX - (Zero Page, X) 83: SAX - (Zero Page, X)
84: STY - Zero Page 84: STY - Zero Page
85: STA - Zero Page 85: STA - Zero Page
86: STX - Zero Page 86: STX - Zero Page
87: SAX - Zero Page 87: SAX - Zero Page
88: DEY - Implied 88: DEY - Implied
89: 89:
8A: TXA - Implied 8A: TXA - Implied
8B: ANE - Immediate 8B: ANE - Immediate
8C: STY - Absolute 8C: STY - Absolute
@ -144,7 +144,7 @@
8F: SAX - Absolute 8F: SAX - Absolute
90: BCC - Relative 90: BCC - Relative
91: STA - (Zero Page), Y 91: STA - (Zero Page), Y
92: 92:
93: SHA - (Zero Page), Y 93: SHA - (Zero Page), Y
94: STY - Zero Page, X 94: STY - Zero Page, X
95: STA - Zero Page, X 95: STA - Zero Page, X
@ -154,7 +154,7 @@
99: STA - Absolute, Y 99: STA - Absolute, Y
9A: TXS - Implied 9A: TXS - Implied
9B: SHS - Absolute, Y 9B: SHS - Absolute, Y
9C: 9C:
9D: STA - Absolute, X 9D: STA - Absolute, X
9E: SHX - Absolute, Y 9E: SHX - Absolute, Y
9F: SHA - Absolute, Y 9F: SHA - Absolute, Y
@ -176,7 +176,7 @@
AF: LAX - Absolute AF: LAX - Absolute
B0: BCS - Relative B0: BCS - Relative
B1: LDA - (Zero Page), Y B1: LDA - (Zero Page), Y
B2: B2:
B3: LAX - (Zero Page), Y B3: LAX - (Zero Page), Y
B4: LDY - Zero Page, X B4: LDY - Zero Page, X
B5: LDA - Zero Page, X B5: LDA - Zero Page, X
@ -192,7 +192,7 @@
BF: LAX - Absolute, Y BF: LAX - Absolute, Y
C0: CPY - Immediate C0: CPY - Immediate
C1: CMP - (Zero Page, X) C1: CMP - (Zero Page, X)
C2: C2:
C3: DCP - (Zero Page, X) C3: DCP - (Zero Page, X)
C4: CPY - Zero Page C4: CPY - Zero Page
C5: CMP - Zero Page C5: CMP - Zero Page
@ -208,23 +208,23 @@
CF: DCP - Absolute CF: DCP - Absolute
D0: BNE - Relative D0: BNE - Relative
D1: CMP - (Zero Page), Y D1: CMP - (Zero Page), Y
D2: D2:
D3: DCP - (Zero Page), Y D3: DCP - (Zero Page), Y
D4: D4:
D5: CMP - Zero Page, X D5: CMP - Zero Page, X
D6: DEC - Zero Page, X D6: DEC - Zero Page, X
D7: DCP - Zero Page, X D7: DCP - Zero Page, X
D8: CLD - Implied D8: CLD - Implied
D9: CMP - Absolute, Y D9: CMP - Absolute, Y
DA: DA:
DB: DCP - Absolute, Y DB: DCP - Absolute, Y
DC: DC:
DD: CMP - Absolute, X DD: CMP - Absolute, X
DE: DEC - Absolute, X DE: DEC - Absolute, X
DF: DCP - Absolute, X DF: DCP - Absolute, X
E0: CPX - Immediate E0: CPX - Immediate
E1: SBC - (Zero Page, X) E1: SBC - (Zero Page, X)
E2: E2:
E3: ISB - (Zero Page, X) E3: ISB - (Zero Page, X)
E4: CPX - Zero Page E4: CPX - Zero Page
E5: SBC - Zero Page E5: SBC - Zero Page
@ -233,24 +233,24 @@
E8: INX - Implied E8: INX - Implied
E9: SBC - Immediate E9: SBC - Immediate
EA: NOP - Implied EA: NOP - Implied
EB: EB:
EC: CPX - Absolute EC: CPX - Absolute
ED: SBC - Absolute ED: SBC - Absolute
EE: INC - Absolute EE: INC - Absolute
EF: ISB - Absolute EF: ISB - Absolute
F0: BEQ - Relative F0: BEQ - Relative
F1: SBC - (Zero Page), Y F1: SBC - (Zero Page), Y
F2: F2:
F3: ISB - (Zero Page), Y F3: ISB - (Zero Page), Y
F4: F4:
F5: SBC - Zero Page, X F5: SBC - Zero Page, X
F6: INC - Zero Page, X F6: INC - Zero Page, X
F7: ISB - Zero Page, X F7: ISB - Zero Page, X
F8: SED - Implied F8: SED - Implied
F9: SBC - Absolute, Y F9: SBC - Absolute, Y
FA: FA:
FB: ISB - Absolute, Y FB: ISB - Absolute, Y
FC: FC:
FD: SBC - Absolute, X FD: SBC - Absolute, X
FE: INC - Absolute, X FE: INC - Absolute, X
FF: ISB - Absolute, X FF: ISB - Absolute, X

View File

@ -1,7 +1,7 @@
00: BRK - Implied 00: BRK - Implied
01: ORA - (Zero Page, X) 01: ORA - (Zero Page, X)
02: 02:
03: 03:
04: TSB - Zero Page 04: TSB - Zero Page
05: ORA - Zero Page 05: ORA - Zero Page
06: ASL - Zero Page 06: ASL - Zero Page
@ -9,7 +9,7 @@
08: PHP - Implied 08: PHP - Implied
09: ORA - Immediate 09: ORA - Immediate
0A: ASL - Implied 0A: ASL - Implied
0B: 0B:
0C: TSB - Absolute 0C: TSB - Absolute
0D: ORA - Absolute 0D: ORA - Absolute
0E: ASL - Absolute 0E: ASL - Absolute
@ -17,7 +17,7 @@
10: BPL - Relative 10: BPL - Relative
11: ORA - (Zero Page), Y 11: ORA - (Zero Page), Y
12: ORA - (Zero Page) 12: ORA - (Zero Page)
13: 13:
14: TRB - Zero Page 14: TRB - Zero Page
15: ORA - Zero Page, X 15: ORA - Zero Page, X
16: ASL - Zero Page, X 16: ASL - Zero Page, X
@ -25,15 +25,15 @@
18: CLC - Implied 18: CLC - Implied
19: ORA - Absolute, Y 19: ORA - Absolute, Y
1A: INA - Implied; INC - Implied 1A: INA - Implied; INC - Implied
1B: 1B:
1C: TRB - Absolute 1C: TRB - Absolute
1D: ORA - Absolute, X 1D: ORA - Absolute, X
1E: ASL - Absolute, X 1E: ASL - Absolute, X
1F: BBR1 - Relative 1F: BBR1 - Relative
20: JSR - Absolute 20: JSR - Absolute
21: AND - (Zero Page, X) 21: AND - (Zero Page, X)
22: 22:
23: 23:
24: BIT - Zero Page 24: BIT - Zero Page
25: AND - Zero Page 25: AND - Zero Page
26: ROL - Zero Page 26: ROL - Zero Page
@ -41,7 +41,7 @@
28: PLP - Implied 28: PLP - Implied
29: AND - Immediate 29: AND - Immediate
2A: ROL - Implied 2A: ROL - Implied
2B: 2B:
2C: BIT - Absolute 2C: BIT - Absolute
2D: AND - Absolute 2D: AND - Absolute
2E: ROL - Absolute 2E: ROL - Absolute
@ -49,7 +49,7 @@
30: BMI - Relative 30: BMI - Relative
31: AND - (Zero Page), Y 31: AND - (Zero Page), Y
32: AND - (Zero Page) 32: AND - (Zero Page)
33: 33:
34: BIT - Zero Page, X 34: BIT - Zero Page, X
35: AND - Zero Page, X 35: AND - Zero Page, X
36: ROL - Zero Page, X 36: ROL - Zero Page, X
@ -57,23 +57,23 @@
38: SEC - Implied 38: SEC - Implied
39: AND - Absolute, Y 39: AND - Absolute, Y
3A: DEA - Implied; DEC - Implied 3A: DEA - Implied; DEC - Implied
3B: 3B:
3C: BIT - Absolute, X 3C: BIT - Absolute, X
3D: AND - Absolute, X 3D: AND - Absolute, X
3E: ROL - Absolute, X 3E: ROL - Absolute, X
3F: BBR3 - Relative 3F: BBR3 - Relative
40: RTI - Implied 40: RTI - Implied
41: EOR - (Zero Page, X) 41: EOR - (Zero Page, X)
42: 42:
43: 43:
44: 44:
45: EOR - Zero Page 45: EOR - Zero Page
46: LSR - Zero Page 46: LSR - Zero Page
47: RMB4 - Zero Page 47: RMB4 - Zero Page
48: PHA - Implied 48: PHA - Implied
49: EOR - Immediate 49: EOR - Immediate
4A: LSR - Implied 4A: LSR - Implied
4B: 4B:
4C: JMP - Absolute 4C: JMP - Absolute
4D: EOR - Absolute 4D: EOR - Absolute
4E: LSR - Absolute 4E: LSR - Absolute
@ -81,23 +81,23 @@
50: BVC - Relative 50: BVC - Relative
51: EOR - (Zero Page), Y 51: EOR - (Zero Page), Y
52: EOR - (Zero Page) 52: EOR - (Zero Page)
53: 53:
54: 54:
55: EOR - Zero Page, X 55: EOR - Zero Page, X
56: LSR - Zero Page, X 56: LSR - Zero Page, X
57: RMB5 - Zero Page 57: RMB5 - Zero Page
58: CLI - Implied 58: CLI - Implied
59: EOR - Absolute, Y 59: EOR - Absolute, Y
5A: PHY - Implied 5A: PHY - Implied
5B: 5B:
5C: 5C:
5D: EOR - Absolute, X 5D: EOR - Absolute, X
5E: LSR - Absolute, X 5E: LSR - Absolute, X
5F: BBR5 - Relative 5F: BBR5 - Relative
60: RTS - Implied 60: RTS - Implied
61: ADC - (Zero Page, X) 61: ADC - (Zero Page, X)
62: 62:
63: 63:
64: STZ - Zero Page 64: STZ - Zero Page
65: ADC - Zero Page 65: ADC - Zero Page
66: ROR - Zero Page 66: ROR - Zero Page
@ -105,7 +105,7 @@
68: PLA - Implied 68: PLA - Implied
69: ADC - Immediate 69: ADC - Immediate
6A: ROR - Implied 6A: ROR - Implied
6B: 6B:
6C: JMP - (Absolute) 6C: JMP - (Absolute)
6D: ADC - Absolute 6D: ADC - Absolute
6E: ROR - Absolute 6E: ROR - Absolute
@ -113,7 +113,7 @@
70: BVS - Relative 70: BVS - Relative
71: ADC - (Zero Page), Y 71: ADC - (Zero Page), Y
72: ADC - (Zero Page) 72: ADC - (Zero Page)
73: 73:
74: STZ - Zero Page, X 74: STZ - Zero Page, X
75: ADC - Zero Page, X 75: ADC - Zero Page, X
76: ROR - Zero Page, X 76: ROR - Zero Page, X
@ -121,15 +121,15 @@
78: SEI - Implied 78: SEI - Implied
79: ADC - Absolute, Y 79: ADC - Absolute, Y
7A: PLY - Implied 7A: PLY - Implied
7B: 7B:
7C: JMP - (Absolute, X) 7C: JMP - (Absolute, X)
7D: ADC - Absolute, X 7D: ADC - Absolute, X
7E: ROR - Absolute, X 7E: ROR - Absolute, X
7F: BBR7 - Relative 7F: BBR7 - Relative
80: BRA - Relative 80: BRA - Relative
81: STA - (Zero Page, X) 81: STA - (Zero Page, X)
82: 82:
83: 83:
84: STY - Zero Page 84: STY - Zero Page
85: STA - Zero Page 85: STA - Zero Page
86: STX - Zero Page 86: STX - Zero Page
@ -137,7 +137,7 @@
88: DEY - Implied 88: DEY - Implied
89: BIT - Immediate 89: BIT - Immediate
8A: TXA - Implied 8A: TXA - Implied
8B: 8B:
8C: STY - Absolute 8C: STY - Absolute
8D: STA - Absolute 8D: STA - Absolute
8E: STX - Absolute 8E: STX - Absolute
@ -145,7 +145,7 @@
90: BCC - Relative 90: BCC - Relative
91: STA - (Zero Page), Y 91: STA - (Zero Page), Y
92: STA - (Zero Page) 92: STA - (Zero Page)
93: 93:
94: STY - Zero Page, X 94: STY - Zero Page, X
95: STA - Zero Page, X 95: STA - Zero Page, X
96: STX - Zero Page, Y 96: STX - Zero Page, Y
@ -153,7 +153,7 @@
98: TYA - Implied 98: TYA - Implied
99: STA - Absolute, Y 99: STA - Absolute, Y
9A: TXS - Implied 9A: TXS - Implied
9B: 9B:
9C: STZ - Absolute 9C: STZ - Absolute
9D: STA - Absolute, X 9D: STA - Absolute, X
9E: STZ - Absolute, X 9E: STZ - Absolute, X
@ -161,7 +161,7 @@
A0: LDY - Immediate A0: LDY - Immediate
A1: LDA - (Zero Page, X) A1: LDA - (Zero Page, X)
A2: LDX - Immediate A2: LDX - Immediate
A3: A3:
A4: LDY - Zero Page A4: LDY - Zero Page
A5: LDA - Zero Page A5: LDA - Zero Page
A6: LDX - Zero Page A6: LDX - Zero Page
@ -169,7 +169,7 @@
A8: TAY - Implied A8: TAY - Implied
A9: LDA - Immediate A9: LDA - Immediate
AA: TAX - Implied AA: TAX - Implied
AB: AB:
AC: LDY - Absolute AC: LDY - Absolute
AD: LDA - Absolute AD: LDA - Absolute
AE: LDX - Absolute AE: LDX - Absolute
@ -177,7 +177,7 @@
B0: BCS - Relative B0: BCS - Relative
B1: LDA - (Zero Page), Y B1: LDA - (Zero Page), Y
B2: LDA - (Zero Page) B2: LDA - (Zero Page)
B3: B3:
B4: LDY - Zero Page, X B4: LDY - Zero Page, X
B5: LDA - Zero Page, X B5: LDA - Zero Page, X
B6: LDX - Zero Page, Y B6: LDX - Zero Page, Y
@ -185,15 +185,15 @@
B8: CLV - Implied B8: CLV - Implied
B9: LDA - Absolute, Y B9: LDA - Absolute, Y
BA: TSX - Implied BA: TSX - Implied
BB: BB:
BC: LDY - Absolute, X BC: LDY - Absolute, X
BD: LDA - Absolute, X BD: LDA - Absolute, X
BE: LDX - Absolute, Y BE: LDX - Absolute, Y
BF: BBS3 - Relative BF: BBS3 - Relative
C0: CPY - Immediate C0: CPY - Immediate
C1: CMP - (Zero Page, X) C1: CMP - (Zero Page, X)
C2: C2:
C3: C3:
C4: CPY - Zero Page C4: CPY - Zero Page
C5: CMP - Zero Page C5: CMP - Zero Page
C6: DEC - Zero Page C6: DEC - Zero Page
@ -209,8 +209,8 @@
D0: BNE - Relative D0: BNE - Relative
D1: CMP - (Zero Page), Y D1: CMP - (Zero Page), Y
D2: CMP - (Zero Page) D2: CMP - (Zero Page)
D3: D3:
D4: D4:
D5: CMP - Zero Page, X D5: CMP - Zero Page, X
D6: DEC - Zero Page, X D6: DEC - Zero Page, X
D7: SMB5 - Zero Page D7: SMB5 - Zero Page
@ -218,14 +218,14 @@
D9: CMP - Absolute, Y D9: CMP - Absolute, Y
DA: PHX - Implied DA: PHX - Implied
DB: STP - Implied DB: STP - Implied
DC: DC:
DD: CMP - Absolute, X DD: CMP - Absolute, X
DE: DEC - Absolute, X DE: DEC - Absolute, X
DF: BBS5 - Relative DF: BBS5 - Relative
E0: CPX - Immediate E0: CPX - Immediate
E1: SBC - (Zero Page, X) E1: SBC - (Zero Page, X)
E2: E2:
E3: E3:
E4: CPX - Zero Page E4: CPX - Zero Page
E5: SBC - Zero Page E5: SBC - Zero Page
E6: INC - Zero Page E6: INC - Zero Page
@ -233,7 +233,7 @@
E8: INX - Implied E8: INX - Implied
E9: SBC - Immediate E9: SBC - Immediate
EA: NOP - Implied EA: NOP - Implied
EB: EB:
EC: CPX - Absolute EC: CPX - Absolute
ED: SBC - Absolute ED: SBC - Absolute
EE: INC - Absolute EE: INC - Absolute
@ -241,16 +241,16 @@
F0: BEQ - Relative F0: BEQ - Relative
F1: SBC - (Zero Page), Y F1: SBC - (Zero Page), Y
F2: SBC - (Zero Page) F2: SBC - (Zero Page)
F3: F3:
F4: F4:
F5: SBC - Zero Page, X F5: SBC - Zero Page, X
F6: INC - Zero Page, X F6: INC - Zero Page, X
F7: SMB7 - Zero Page F7: SMB7 - Zero Page
F8: SED - Implied F8: SED - Implied
F9: SBC - Absolute, Y F9: SBC - Absolute, Y
FA: PLX - Implied FA: PLX - Implied
FB: FB:
FC: FC:
FD: SBC - Absolute, X FD: SBC - Absolute, X
FE: INC - Absolute, X FE: INC - Absolute, X
FF: BBS7 - Relative FF: BBS7 - Relative