mirror of
https://github.com/michaelcmartin/Ophis.git
synced 2025-04-06 19:37:08 +00:00
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:
parent
f83379287f
commit
14a37ca879
2
README
2
README
@ -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
|
||||
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
|
||||
THE SOFTWARE.
|
||||
THE SOFTWARE.
|
||||
|
@ -9,4 +9,4 @@ _next: .word 0 ; End of program
|
||||
|
||||
.advance 2064
|
||||
|
||||
.require "kernal.oph"
|
||||
.require "kernal.oph"
|
||||
|
@ -37,4 +37,4 @@ _next: .word 0 ; End of program
|
||||
|
||||
_main:
|
||||
; Program follows...
|
||||
.scend
|
||||
.scend
|
||||
|
@ -249,7 +249,7 @@
|
||||
.checkpc $100
|
||||
</programlisting>
|
||||
</section>
|
||||
</section>
|
||||
</section>
|
||||
<section>
|
||||
<title>Macros</title>
|
||||
<para>
|
||||
@ -400,7 +400,7 @@
|
||||
code in and of itself, nor does it overwrite anything that
|
||||
previously existed.</emphasis> If you wish to jump ahead in memory,
|
||||
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>,
|
||||
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
|
||||
@ -447,5 +447,5 @@
|
||||
macro definition intends to read. A shorthand for <literal>.invoke</literal>
|
||||
is the name of the macro to invoke, backquoted.</para></listitem>
|
||||
</itemizedlist>
|
||||
</section>
|
||||
</section>
|
||||
</appendix>
|
||||
|
@ -333,7 +333,7 @@ delay: tax
|
||||
iny
|
||||
bne -
|
||||
dex
|
||||
bne -
|
||||
bne -
|
||||
rts
|
||||
</programlisting>
|
||||
</section>
|
||||
|
@ -153,19 +153,19 @@ next: .word 0 ; End of program
|
||||
Labels are defined by putting their name, then a colon, as
|
||||
seen in the definition of <literal>next</literal>.
|
||||
</para></listitem>
|
||||
<listitem><para>
|
||||
<listitem><para>
|
||||
Instead of putting in the hex codes for the string part of
|
||||
the BASIC code, we included the string directly. Each
|
||||
character in the string becomes one byte.
|
||||
</para></listitem>
|
||||
<listitem><para>
|
||||
<listitem><para>
|
||||
Instead of adding the buffer ourselves, we
|
||||
used <literal>.advance</literal>, which outputs zeros until
|
||||
the specified address is reached. Attempting
|
||||
to <literal>.advance</literal> backwards produces an
|
||||
assemble-time error.
|
||||
</para></listitem>
|
||||
<listitem><para>
|
||||
<listitem><para>
|
||||
It has comments that explain what the data are for. The
|
||||
semicolon is the comment marker; everything from a semicolon
|
||||
to the end of the line is ignored.
|
||||
@ -263,9 +263,9 @@ hello: .byte "HELLO, WORLD!", 0
|
||||
<row>
|
||||
<entry align="center">Option</entry>
|
||||
<entry align="center">Effect</entry>
|
||||
</row>
|
||||
</row>
|
||||
</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>-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>
|
||||
|
@ -64,4 +64,4 @@
|
||||
|
||||
; ...and character set
|
||||
.alias upper'case 142
|
||||
.alias lower'case 14
|
||||
.alias lower'case 14
|
||||
|
@ -15,4 +15,4 @@ loop: lda hello, x
|
||||
bne loop
|
||||
done: rts
|
||||
|
||||
hello: .byte "HELLO, WORLD!", 0
|
||||
hello: .byte "HELLO, WORLD!", 0
|
||||
|
@ -19,4 +19,4 @@ _next: .word 0 ; End of program
|
||||
bne -
|
||||
* rts
|
||||
|
||||
hello: .byte "HELLO, WORLD!", 0
|
||||
hello: .byte "HELLO, WORLD!", 0
|
||||
|
@ -42,4 +42,4 @@ target6: .byte "NATION", 0
|
||||
target7: .byte "WORLD", 0
|
||||
target8: .byte "SOLAR SYSTEM", 0
|
||||
target9: .byte "GALAXY", 0
|
||||
target10: .byte "UNIVERSE", 0
|
||||
target10: .byte "UNIVERSE", 0
|
||||
|
@ -63,7 +63,7 @@ delay: tax
|
||||
bne -
|
||||
dex
|
||||
bne -
|
||||
|
||||
|
||||
|
||||
|
||||
rts
|
||||
|
||||
|
@ -65,7 +65,7 @@ delay: tax
|
||||
bne -
|
||||
dex
|
||||
bne -
|
||||
|
||||
|
||||
|
||||
|
||||
rts
|
||||
|
||||
|
@ -68,6 +68,6 @@ delay: tax
|
||||
bne -
|
||||
dex
|
||||
bne -
|
||||
|
||||
|
||||
rts
|
||||
|
||||
|
||||
rts
|
||||
|
@ -72,4 +72,4 @@ delay: sta _tmp ; save argument (rdtim destroys it)
|
||||
|
||||
.checkpc $A000
|
||||
.data
|
||||
.checkpc $D000
|
||||
.checkpc $D000
|
||||
|
@ -99,4 +99,4 @@ _done: rts
|
||||
|
||||
.checkpc $A000
|
||||
.data
|
||||
.checkpc $D000
|
||||
.checkpc $D000
|
||||
|
@ -93,4 +93,4 @@ _done: rts
|
||||
.checkpc $D000
|
||||
|
||||
.data zp
|
||||
.checkpc $80
|
||||
.checkpc $80
|
||||
|
@ -6,44 +6,59 @@ import optparse
|
||||
# You may use, modify, and distribute this file under the MIT
|
||||
# license: See README for details.
|
||||
|
||||
enable_collapse = True
|
||||
enable_branch_extend = True
|
||||
enable_undoc_ops = False
|
||||
enable_65c02_exts = False
|
||||
enable_collapse = True
|
||||
enable_branch_extend = True
|
||||
enable_undoc_ops = False
|
||||
enable_65c02_exts = False
|
||||
|
||||
warn_on_branch_extend = True
|
||||
|
||||
print_summary = True
|
||||
print_loaded_files = False
|
||||
print_pass = False
|
||||
print_ir = False
|
||||
print_labels = False
|
||||
print_summary = True
|
||||
print_loaded_files = False
|
||||
print_pass = False
|
||||
print_ir = False
|
||||
print_labels = False
|
||||
|
||||
infile = None
|
||||
outfile = None
|
||||
|
||||
infile = None
|
||||
outfile = None
|
||||
|
||||
def parse_args(raw_args):
|
||||
"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 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
|
||||
|
||||
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.add_option("-u", "--undoc", action="store_true", default=False, help="Enable 6502 undocumented opcodes")
|
||||
ingrp.add_option("-c", "--65c02", action="store_true", default=False, dest="c02", help="Enable 65c02 extended instruction set")
|
||||
ingrp.add_option("-u", "--undoc", action="store_true", default=False,
|
||||
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.add_option("-v", "--verbose", action="store_const", const=2, help="Verbose mode", default=1)
|
||||
outgrp.add_option("-q", "--quiet", action="store_const", help="Quiet mode", 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")
|
||||
outgrp.add_option("-v", "--verbose", action="store_const", const=2,
|
||||
help="Verbose mode", default=1)
|
||||
outgrp.add_option("-q", "--quiet", action="store_const", help="Quiet mode",
|
||||
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.add_option("--no-collapse", action="store_false", 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")
|
||||
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-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(outgrp)
|
||||
@ -60,15 +75,15 @@ def parse_args(raw_args):
|
||||
if options.c02 and options.undoc:
|
||||
parser.error("--undoc and --65c02 are mutually exclusive")
|
||||
|
||||
infile = args[0]
|
||||
outfile = args[1]
|
||||
enable_collapse = options.enable_collapse
|
||||
enable_branch_extend = options.enable_branch_extend
|
||||
enable_undoc_ops = options.undoc
|
||||
enable_65c02_exts = options.c02
|
||||
infile = args[0]
|
||||
outfile = args[1]
|
||||
enable_collapse = options.enable_collapse
|
||||
enable_branch_extend = options.enable_branch_extend
|
||||
enable_undoc_ops = options.undoc
|
||||
enable_65c02_exts = options.c02
|
||||
warn_on_branch_extend = options.warn
|
||||
print_summary = options.verbose > 0 # no options set
|
||||
print_loaded_files = options.verbose > 1 # v
|
||||
print_pass = options.verbose > 2 # dd
|
||||
print_ir = options.verbose > 3 # ddd
|
||||
print_labels = options.verbose > 4 # dddd
|
||||
print_summary = options.verbose > 0 # no options set
|
||||
print_loaded_files = options.verbose > 1 # v
|
||||
print_pass = options.verbose > 2 # dd
|
||||
print_ir = options.verbose > 3 # ddd
|
||||
print_labels = options.verbose > 4 # dddd
|
||||
|
@ -10,46 +10,52 @@ import Ophis.IR as IR
|
||||
import Ophis.Frontend as FE
|
||||
import Ophis.Errors as Err
|
||||
|
||||
loadedfiles={}
|
||||
loadedfiles = {}
|
||||
basecharmap = "".join([chr(x) for x in range(256)])
|
||||
currentcharmap = basecharmap
|
||||
|
||||
|
||||
def reset():
|
||||
global loadedfiles, currentcharmap, basecharmap
|
||||
loadedfiles={}
|
||||
loadedfiles = {}
|
||||
currentcharmap = basecharmap
|
||||
|
||||
|
||||
def pragmaInclude(ppt, line, result):
|
||||
"Includes a source file"
|
||||
filename = line.expect("STRING").value
|
||||
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):
|
||||
"Includes a source file at most one time"
|
||||
filename = line.expect("STRING").value
|
||||
line.expect("EOL")
|
||||
if type(filename)==str:
|
||||
if type(filename) == str:
|
||||
global loadedfiles
|
||||
if filename not in loadedfiles:
|
||||
loadedfiles[filename]=1
|
||||
loadedfiles[filename] = True
|
||||
result.append(FE.parse_file(ppt, filename))
|
||||
|
||||
|
||||
def pragmaIncbin(ppt, line, result):
|
||||
"Includes a binary file"
|
||||
filename = line.expect("STRING").value
|
||||
line.expect("EOL")
|
||||
if type(filename)==str:
|
||||
if type(filename) == str:
|
||||
try:
|
||||
f = file(filename, "rb")
|
||||
bytes = f.read()
|
||||
f.close()
|
||||
except IOError:
|
||||
Err.log ("Could not read "+filename)
|
||||
Err.log("Could not read " + filename)
|
||||
return
|
||||
bytes = [IR.ConstantExpr(ord(x)) for x in bytes]
|
||||
result.append(IR.Node(ppt, "Byte", *bytes))
|
||||
|
||||
|
||||
def pragmaCharmap(ppt, line, result):
|
||||
"Modify the character map."
|
||||
global currentcharmap, basecharmap
|
||||
@ -60,30 +66,33 @@ def pragmaCharmap(ppt, line, result):
|
||||
try:
|
||||
base = bytes[0].data
|
||||
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:
|
||||
Err.log("Charmap replacement out of range")
|
||||
currentcharmap = currentcharmap[:256]
|
||||
except ValueError:
|
||||
Err.log("Illegal character in .charmap directive")
|
||||
|
||||
|
||||
def pragmaCharmapbin(ppt, line, result):
|
||||
"Load a new character map from a file"
|
||||
global currentcharmap
|
||||
filename = line.expect("STRING").value
|
||||
line.expect("EOL")
|
||||
if type(filename)==str:
|
||||
if type(filename) == str:
|
||||
try:
|
||||
f = file(filename, "rb")
|
||||
bytes = f.read()
|
||||
f.close()
|
||||
except IOError:
|
||||
Err.log ("Could not read "+filename)
|
||||
Err.log("Could not read " + filename)
|
||||
return
|
||||
if len(bytes)==256:
|
||||
if len(bytes) == 256:
|
||||
currentcharmap = bytes
|
||||
else:
|
||||
Err.log("Character map "+filename+" not 256 bytes long")
|
||||
Err.log("Character map " + filename + " not 256 bytes long")
|
||||
|
||||
|
||||
def pragmaOrg(ppt, line, result):
|
||||
"Relocates the PC with no output"
|
||||
@ -91,6 +100,7 @@ def pragmaOrg(ppt, line, result):
|
||||
line.expect("EOL")
|
||||
result.append(IR.Node(ppt, "SetPC", newPC))
|
||||
|
||||
|
||||
def pragmaAdvance(ppt, line, result):
|
||||
"Outputs filler until reaching the target PC"
|
||||
newPC = FE.parse_expr(line)
|
||||
@ -102,25 +112,31 @@ def pragmaAdvance(ppt, line, result):
|
||||
line.expect("EOL")
|
||||
result.append(IR.Node(ppt, "Advance", newPC, fillexpr))
|
||||
|
||||
|
||||
def pragmaCheckpc(ppt, line, result):
|
||||
"Enforces that the PC has not exceeded a certain point"
|
||||
target = FE.parse_expr(line)
|
||||
line.expect("EOL")
|
||||
result.append(IR.Node(ppt, "CheckPC", target))
|
||||
|
||||
|
||||
def pragmaAlias(ppt, line, result):
|
||||
"Assigns an arbitrary label"
|
||||
lbl = line.expect("LABEL").value
|
||||
target = FE.parse_expr(line)
|
||||
result.append(IR.Node(ppt, "Label", lbl, target))
|
||||
|
||||
|
||||
def pragmaSpace(ppt, line, result):
|
||||
"Reserves space in a data segment for a variable"
|
||||
lbl = line.expect("LABEL").value
|
||||
size = line.expect("NUM").value
|
||||
line.expect("EOL")
|
||||
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):
|
||||
"Switches to a text segment"
|
||||
@ -132,6 +148,7 @@ def pragmaText(ppt, line, result):
|
||||
segment = "*text-default*"
|
||||
result.append(IR.Node(ppt, "TextSegment", segment))
|
||||
|
||||
|
||||
def pragmaData(ppt, line, result):
|
||||
"Switches to a data segment (no output allowed)"
|
||||
next = line.expect("LABEL", "EOL")
|
||||
@ -142,67 +159,80 @@ def pragmaData(ppt, line, result):
|
||||
segment = "*data-default*"
|
||||
result.append(IR.Node(ppt, "DataSegment", segment))
|
||||
|
||||
|
||||
def readData(line):
|
||||
"Read raw data from a comma-separated list"
|
||||
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:
|
||||
data = [FE.parse_expr(line)]
|
||||
next = line.expect(',', 'EOL').type
|
||||
while next == ',':
|
||||
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:
|
||||
data.append(FE.parse_expr(line))
|
||||
next = line.expect(',', 'EOL').type
|
||||
return data
|
||||
|
||||
|
||||
def pragmaByte(ppt, line, result):
|
||||
"Raw data, a byte at a time"
|
||||
bytes = readData(line)
|
||||
result.append(IR.Node(ppt, "Byte", *bytes))
|
||||
|
||||
|
||||
def pragmaWord(ppt, line, result):
|
||||
"Raw data, a word at a time, little-endian"
|
||||
words = readData(line)
|
||||
result.append(IR.Node(ppt, "Word", *words))
|
||||
|
||||
|
||||
def pragmaDword(ppt, line, result):
|
||||
"Raw data, a double-word at a time, little-endian"
|
||||
dwords = readData(line)
|
||||
result.append(IR.Node(ppt, "Dword", *dwords))
|
||||
|
||||
|
||||
def pragmaWordbe(ppt, line, result):
|
||||
"Raw data, a word at a time, big-endian"
|
||||
words = readData(line)
|
||||
result.append(IR.Node(ppt, "WordBE", *words))
|
||||
|
||||
|
||||
def pragmaDwordbe(ppt, line, result):
|
||||
"Raw data, a dword at a time, big-endian"
|
||||
dwords = readData(line)
|
||||
result.append(IR.Node(ppt, "DwordBE", *dwords))
|
||||
|
||||
|
||||
def pragmaScope(ppt, line, result):
|
||||
"Create a new lexical scoping block"
|
||||
line.expect("EOL")
|
||||
result.append(IR.Node(ppt, "ScopeBegin"))
|
||||
|
||||
|
||||
def pragmaScend(ppt, line, result):
|
||||
"End the innermost lexical scoping block"
|
||||
line.expect("EOL")
|
||||
result.append(IR.Node(ppt, "ScopeEnd"))
|
||||
|
||||
|
||||
def pragmaMacro(ppt, line, result):
|
||||
"Begin a macro definition"
|
||||
lbl = line.expect("LABEL").value
|
||||
line.expect("EOL")
|
||||
result.append(IR.Node(ppt, "MacroBegin", lbl))
|
||||
|
||||
|
||||
def pragmaMacend(ppt, line, result):
|
||||
"End a macro definition"
|
||||
line.expect("EOL")
|
||||
result.append(IR.Node(ppt, "MacroEnd"))
|
||||
|
||||
|
||||
def pragmaInvoke(ppt, line, result):
|
||||
macro = line.expect("LABEL").value
|
||||
if line.lookahead(0).type == "EOL":
|
||||
|
@ -9,6 +9,7 @@
|
||||
|
||||
import Ophis.Errors as Err
|
||||
|
||||
|
||||
class Environment(object):
|
||||
"""Environment class.
|
||||
Controls the various scopes and global abstract execution variables."""
|
||||
@ -19,39 +20,52 @@ class Environment(object):
|
||||
self.segmentdict = {}
|
||||
self.segment = "*text-default*"
|
||||
self.scopecount = 0
|
||||
|
||||
def __contains__(self, item):
|
||||
if item[0] == '_':
|
||||
for dict in [self.dicts[i] for i in self.stack]:
|
||||
if item in dict: return 1
|
||||
return 0
|
||||
if item in dict:
|
||||
return True
|
||||
return False
|
||||
return item in self.dicts[0]
|
||||
|
||||
def __getitem__(self, item):
|
||||
if item[0] == '_':
|
||||
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:
|
||||
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)
|
||||
return 0
|
||||
|
||||
def __setitem__(self, item, value):
|
||||
if item[0] == '_':
|
||||
self.dicts[self.stack[0]][item] = value
|
||||
else:
|
||||
self.dicts[0][item] = value
|
||||
|
||||
def __str__(self):
|
||||
return str(self.dicts)
|
||||
|
||||
def getPC(self):
|
||||
return self.pc
|
||||
|
||||
def setPC(self, value):
|
||||
self.pc = value
|
||||
|
||||
def incPC(self, amount):
|
||||
self.pc += amount
|
||||
|
||||
def getsegment(self):
|
||||
return self.segment
|
||||
|
||||
def setsegment(self, segment):
|
||||
self.segmentdict[self.segment] = self.pc
|
||||
self.segment = segment
|
||||
self.pc = self.segmentdict.get(segment, 0)
|
||||
|
||||
def reset(self):
|
||||
"Clears out program counter, segment, and scoping information"
|
||||
self.pc = 0
|
||||
@ -61,14 +75,16 @@ class Environment(object):
|
||||
if len(self.stack) > 1:
|
||||
Err.log("Unmatched .scope")
|
||||
self.stack = [0]
|
||||
|
||||
def newscope(self):
|
||||
"Enters a new scope for temporary labels."
|
||||
self.scopecount += 1
|
||||
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):
|
||||
"Leaves a scope."
|
||||
if len(self.stack) == 1:
|
||||
Err.log("Unmatched .scend")
|
||||
self.stack.pop(0)
|
||||
|
||||
|
@ -12,15 +12,20 @@ import sys
|
||||
count = 0
|
||||
currentpoint = "<Top Level>"
|
||||
|
||||
|
||||
def log(err):
|
||||
"""Reports an error at the current program point, and increases
|
||||
the global error count."""
|
||||
global count
|
||||
count = count+1
|
||||
print>>sys.stderr, currentpoint+": "+err
|
||||
count = count + 1
|
||||
print>>sys.stderr, currentpoint + ": " + err
|
||||
|
||||
|
||||
def report():
|
||||
"Print out the number of errors."
|
||||
if count == 0: print>>sys.stderr, "No errors"
|
||||
elif count == 1: print>>sys.stderr, "1 error"
|
||||
else: print>>sys.stderr, str(count)+" errors"
|
||||
if count == 0:
|
||||
print>>sys.stderr, "No errors"
|
||||
elif count == 1:
|
||||
print>>sys.stderr, "1 error"
|
||||
else:
|
||||
print>>sys.stderr, str(count) + " errors"
|
||||
|
@ -13,35 +13,44 @@ import os
|
||||
# You may use, modify, and distribute this file under the MIT
|
||||
# license: See README for details.
|
||||
|
||||
|
||||
class Lexeme(object):
|
||||
"Class for lexer tokens. Used by lexer and parser."
|
||||
def __init__(self, type="UNKNOWN", value=None):
|
||||
self.type = type.upper()
|
||||
self.value = value
|
||||
|
||||
def __str__(self):
|
||||
if self.value == None:
|
||||
if self.value is None:
|
||||
return self.type
|
||||
else:
|
||||
return self.type+":"+str(self.value)
|
||||
return self.type + ":" + str(self.value)
|
||||
|
||||
def __repr__(self):
|
||||
return "Lexeme("+`self.type`+", "+`self.value`+")"
|
||||
return "Lexeme(" + repr(self.type) + ", " + repr(self.value) + ")"
|
||||
|
||||
def matches(self, other):
|
||||
"1 if Lexemes a and b have the same type."
|
||||
return self.type == other.type
|
||||
|
||||
bases = {"$":("hexadecimal", 16),
|
||||
"%":("binary", 2),
|
||||
"0":("octal", 8)}
|
||||
|
||||
bases = {"$": ("hexadecimal", 16),
|
||||
"%": ("binary", 2),
|
||||
"0": ("octal", 8)}
|
||||
|
||||
|
||||
punctuation = "#,`<>():.+-*/&|^[]"
|
||||
|
||||
|
||||
def lex(point, line):
|
||||
"""Turns a line of source into a sequence of lexemes."""
|
||||
Err.currentpoint = point
|
||||
result = []
|
||||
|
||||
def is_opcode(op):
|
||||
"Tests whether a string is an opcode or an identifier"
|
||||
return op in Ops.opcodes
|
||||
|
||||
def add_token(token):
|
||||
"Converts a substring into a single lexeme"
|
||||
if token == "":
|
||||
@ -59,7 +68,8 @@ def lex(point, line):
|
||||
result.append(Lexeme("NUM", long(rest, bases[firstchar][1])))
|
||||
return
|
||||
except ValueError:
|
||||
Err.log('Invalid '+bases[firstchar][0]+' constant: '+rest)
|
||||
Err.log('Invalid ' + bases[firstchar][0] + ' constant: ' +
|
||||
rest)
|
||||
result.append(Lexeme("NUM", 0))
|
||||
return
|
||||
elif firstchar.isdigit():
|
||||
@ -73,12 +83,12 @@ def lex(point, line):
|
||||
if len(rest) == 1:
|
||||
result.append(Lexeme("NUM", ord(rest)))
|
||||
else:
|
||||
Err.log("Invalid character constant '"+rest+"'")
|
||||
Err.log("Invalid character constant '" + rest + "'")
|
||||
result.append(Lexeme("NUM", 0))
|
||||
return
|
||||
elif firstchar in punctuation:
|
||||
if rest != "":
|
||||
Err.log("Internal lexer error! '"+token+"' can't happen!")
|
||||
Err.log("Internal lexer error! '" + token + "' can't happen!")
|
||||
result.append(Lexeme(firstchar))
|
||||
return
|
||||
else: # Label, opcode, or index register
|
||||
@ -94,22 +104,24 @@ def lex(point, line):
|
||||
return
|
||||
# should never reach here
|
||||
Err.log("Internal lexer error: add_token fall-through")
|
||||
|
||||
def add_EOL():
|
||||
"Adds an end-of-line lexeme"
|
||||
result.append(Lexeme("EOL"))
|
||||
|
||||
# Actual routine begins here
|
||||
value = ""
|
||||
quotemode = 0
|
||||
backslashmode = 0
|
||||
quotemode = False
|
||||
backslashmode = False
|
||||
for c in line.strip():
|
||||
if backslashmode:
|
||||
backslashmode = 0
|
||||
backslashmode = False
|
||||
value = value + c
|
||||
elif c == "\\":
|
||||
backslashmode = 1
|
||||
backslashmode = True
|
||||
elif quotemode:
|
||||
if c == '"':
|
||||
quotemode = 0
|
||||
quotemode = False
|
||||
else:
|
||||
value = value + c
|
||||
elif c == ';':
|
||||
@ -126,7 +138,7 @@ def lex(point, line):
|
||||
elif c == '"':
|
||||
add_token(value)
|
||||
value = '"'
|
||||
quotemode = 1
|
||||
quotemode = True
|
||||
else:
|
||||
value = value + c
|
||||
if backslashmode:
|
||||
@ -137,35 +149,45 @@ def lex(point, line):
|
||||
add_EOL()
|
||||
return result
|
||||
|
||||
|
||||
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):
|
||||
self.lexemes = lexemes
|
||||
self.location = 0
|
||||
|
||||
def lookahead(self, i):
|
||||
"""Returns the token i units ahead in the parse.
|
||||
lookahead(0) returns the next token; trying to read off the end of
|
||||
"""Returns the token i units ahead in the parse.
|
||||
lookahead(0) returns the next token; trying to read off the end of
|
||||
the sequence returns the last token in the sequence (usually EOL)."""
|
||||
target = self.location+i
|
||||
if target >= len(self.lexemes): target = -1
|
||||
target = self.location + i
|
||||
if target >= len(self.lexemes):
|
||||
target = -1
|
||||
return self.lexemes[target]
|
||||
|
||||
def pop(self):
|
||||
"Returns and removes the next element in the line."
|
||||
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]
|
||||
|
||||
def expect(self, *tokens):
|
||||
"""Reads a token from the ParseLine line and returns it if it's of a type
|
||||
in the sequence tokens. Otherwise, it logs an error."""
|
||||
"""Reads a token from the ParseLine line and returns it if it's of a
|
||||
type in the sequence tokens. Otherwise, it logs an error."""
|
||||
token = self.pop()
|
||||
if token.type not in tokens:
|
||||
Err.log('Expected: "'+'", "'.join(tokens)+'"')
|
||||
if token.type not in tokens:
|
||||
Err.log('Expected: "' + '", "'.join(tokens) + '"')
|
||||
return token
|
||||
|
||||
|
||||
pragma_modules = []
|
||||
|
||||
|
||||
def parse_expr(line):
|
||||
"Parses an Ophis arithmetic expression."
|
||||
|
||||
def atom():
|
||||
"Parses lowest-priority expression components."
|
||||
next = line.lookahead(0).type
|
||||
@ -187,14 +209,14 @@ def parse_expr(line):
|
||||
offset += 1
|
||||
line.expect("+")
|
||||
next = line.lookahead(0).type
|
||||
return IR.LabelExpr("*"+str(templabelcount+offset))
|
||||
return IR.LabelExpr("*" + str(templabelcount + offset))
|
||||
elif next == "-":
|
||||
offset = 1
|
||||
while next == "-":
|
||||
offset -= 1
|
||||
line.expect("-")
|
||||
next = line.lookahead(0).type
|
||||
return IR.LabelExpr("*"+str(templabelcount+offset))
|
||||
return IR.LabelExpr("*" + str(templabelcount + offset))
|
||||
elif next == ">":
|
||||
line.expect(">")
|
||||
return IR.HighByteExpr(atom())
|
||||
@ -203,6 +225,7 @@ def parse_expr(line):
|
||||
return IR.LowByteExpr(atom())
|
||||
else:
|
||||
Err.log('Expected: expression')
|
||||
|
||||
def precedence_read(constructor, reader, separators):
|
||||
"""Handles precedence. The reader argument is a function that returns
|
||||
expressions that bind more tightly than these; separators is a list
|
||||
@ -218,51 +241,60 @@ def parse_expr(line):
|
||||
result.append(nextop)
|
||||
result.append(reader())
|
||||
nextop = line.lookahead(0).type
|
||||
if len(result) == 1: return result[0]
|
||||
if len(result) == 1:
|
||||
return result[0]
|
||||
return constructor(result)
|
||||
|
||||
def term():
|
||||
"Parses * and /"
|
||||
return precedence_read(IR.SequenceExpr, atom, ["*", "/"])
|
||||
|
||||
def arith():
|
||||
"Parses + and -"
|
||||
return precedence_read(IR.SequenceExpr, term, ["+", "-"])
|
||||
|
||||
def bits():
|
||||
"Parses &, |, and ^"
|
||||
return precedence_read(IR.SequenceExpr, arith, ["&", "|", "^"])
|
||||
|
||||
return bits()
|
||||
|
||||
|
||||
def parse_line(ppt, lexemelist):
|
||||
"Turn a line of source into an IR Node."
|
||||
Err.currentpoint = ppt
|
||||
result = []
|
||||
line = ParseLine(lexemelist)
|
||||
|
||||
def aux():
|
||||
"Accumulates all IR nodes defined by this line."
|
||||
if line.lookahead(0).type == "EOL":
|
||||
pass
|
||||
elif line.lookahead(1).type == ":":
|
||||
newlabel=line.expect("LABEL").value
|
||||
newlabel = line.expect("LABEL").value
|
||||
line.expect(":")
|
||||
result.append(IR.Node(ppt, "Label", newlabel, IR.PCExpr()))
|
||||
aux()
|
||||
elif line.lookahead(0).type == "*":
|
||||
global templabelcount
|
||||
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("*")
|
||||
aux()
|
||||
elif line.lookahead(0).type == "." or line.lookahead(0).type == "`":
|
||||
which = line.expect(".", "`").type
|
||||
if (which == "."): pragma = line.expect("LABEL").value
|
||||
else: pragma = "invoke"
|
||||
pragmaFunction = "pragma"+pragma.title()
|
||||
if (which == "."):
|
||||
pragma = line.expect("LABEL").value
|
||||
else:
|
||||
pragma = "invoke"
|
||||
pragmaFunction = "pragma" + pragma.title()
|
||||
for mod in pragma_modules:
|
||||
if hasattr(mod, pragmaFunction):
|
||||
getattr(mod, pragmaFunction)(ppt, line, result)
|
||||
break
|
||||
else:
|
||||
Err.log("Unknown pragma "+pragma)
|
||||
|
||||
Err.log("Unknown pragma " + pragma)
|
||||
else: # Instruction
|
||||
opcode = line.expect("OPCODE").value
|
||||
if line.lookahead(0).type == "#":
|
||||
@ -296,23 +328,30 @@ def parse_line(ppt, lexemelist):
|
||||
tok = line.expect("EOL", ",").type
|
||||
if tok == ",":
|
||||
tok = line.expect("X", "Y").type
|
||||
if tok == "X": mode = "MemoryX"
|
||||
else: mode = "MemoryY"
|
||||
if tok == "X":
|
||||
mode = "MemoryX"
|
||||
else:
|
||||
mode = "MemoryY"
|
||||
line.expect("EOL")
|
||||
else: mode = "Memory"
|
||||
else:
|
||||
mode = "Memory"
|
||||
result.append(IR.Node(ppt, mode, opcode, arg))
|
||||
|
||||
aux()
|
||||
result = [node for node in result if node is not IR.NullNode]
|
||||
if len(result) == 0: return IR.NullNode
|
||||
if len(result) == 1: return result[0]
|
||||
if len(result) == 0:
|
||||
return IR.NullNode
|
||||
if len(result) == 1:
|
||||
return result[0]
|
||||
return IR.SequenceNode(ppt, result)
|
||||
|
||||
|
||||
def parse_file(ppt, filename):
|
||||
"Loads an Ophis source file, and returns an IR list."
|
||||
Err.currentpoint = ppt
|
||||
if Cmd.print_loaded_files:
|
||||
if filename != '-':
|
||||
print>>sys.stderr, "Loading "+filename
|
||||
print>>sys.stderr, "Loading " + filename
|
||||
else:
|
||||
print>>sys.stderr, "Loading from standard input"
|
||||
try:
|
||||
@ -322,18 +361,19 @@ def parse_file(ppt, filename):
|
||||
f.close()
|
||||
else:
|
||||
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)
|
||||
IRlist = map(parse_line, pptlist, lexlist)
|
||||
IRlist = [node for node in IRlist if node is not IR.NullNode]
|
||||
return IR.SequenceNode(ppt, IRlist)
|
||||
except IOError:
|
||||
Err.log ("Could not read "+filename)
|
||||
Err.log("Could not read " + filename)
|
||||
return IR.NullNode
|
||||
|
||||
|
||||
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
|
||||
templabelcount = 0
|
||||
return parse_file("<Top Level>", filename)
|
||||
|
||||
|
110
src/Ophis/IR.py
110
src/Ophis/IR.py
@ -9,6 +9,7 @@
|
||||
|
||||
import Ophis.Errors as Err
|
||||
|
||||
|
||||
class Node(object):
|
||||
"""The default IR Node
|
||||
Instances of Node always have the three fields ppt(Program Point),
|
||||
@ -17,27 +18,35 @@ class Node(object):
|
||||
self.ppt = ppt
|
||||
self.nodetype = nodetype
|
||||
self.data = list(data)
|
||||
|
||||
def accept(self, asmpass, env=None):
|
||||
"""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."""
|
||||
Err.currentpoint = self.ppt
|
||||
routine = getattr(asmpass, "visit"+self.nodetype, asmpass.visitUnknown)
|
||||
routine = getattr(asmpass, "visit" + self.nodetype,
|
||||
asmpass.visitUnknown)
|
||||
routine(self, env)
|
||||
|
||||
def __str__(self):
|
||||
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:
|
||||
return "\n".join(map(str, self.data))
|
||||
|
||||
def __repr__(self):
|
||||
args = [self.ppt, self.nodetype] + self.data
|
||||
return "Node(" + ", ".join(map(repr, args)) + ")"
|
||||
|
||||
|
||||
NullNode = Node("<none>", "None")
|
||||
|
||||
|
||||
def SequenceNode(ppt, nodelist):
|
||||
return Node(ppt, "SEQUENCE", *nodelist)
|
||||
|
||||
|
||||
class Expr(object):
|
||||
"""Base class for Ophis expressions
|
||||
All expressions have a field called "data" and a boolean field
|
||||
@ -45,78 +54,102 @@ class Expr(object):
|
||||
symbolic values in it."""
|
||||
def __init__(self, data):
|
||||
self.data = data
|
||||
self.hardcoded = 0
|
||||
self.hardcoded = False
|
||||
|
||||
def __str__(self):
|
||||
return "<UNKNOWN: "+`self.data`+">"
|
||||
def valid(self, env=None, PCvalid=0):
|
||||
return "<UNKNOWN: " + repr(self.data) + ">"
|
||||
|
||||
def valid(self, env=None, PCvalid=False):
|
||||
"""Returns true if the the expression can be successfully
|
||||
evaluated in the specified environment."""
|
||||
return 0
|
||||
return False
|
||||
|
||||
def value(self, env=None):
|
||||
"Evaluates this expression in the given environment."
|
||||
return None
|
||||
|
||||
|
||||
class ConstantExpr(Expr):
|
||||
"Represents a numeric constant"
|
||||
def __init__(self, data):
|
||||
self.data = data
|
||||
self.hardcoded = 1
|
||||
self.hardcoded = True
|
||||
|
||||
def __str__(self):
|
||||
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):
|
||||
return self.data
|
||||
|
||||
|
||||
class LabelExpr(Expr):
|
||||
"Represents a symbolic constant"
|
||||
def __init__(self, data):
|
||||
self.data = data
|
||||
self.hardcoded = 0
|
||||
self.hardcoded = False
|
||||
|
||||
def __str__(self):
|
||||
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
|
||||
|
||||
def value(self, env=None):
|
||||
return env[self.data]
|
||||
|
||||
|
||||
class PCExpr(Expr):
|
||||
"Represents the current program counter: ^"
|
||||
def __init__(self):
|
||||
self.hardcoded = 0
|
||||
self.hardcoded = False
|
||||
|
||||
def __str__(self):
|
||||
return "^"
|
||||
def valid(self, env=None, PCvalid=0):
|
||||
|
||||
def valid(self, env=None, PCvalid=False):
|
||||
return env is not None and PCvalid
|
||||
|
||||
def value(self, env=None):
|
||||
return env.getPC()
|
||||
|
||||
|
||||
class HighByteExpr(Expr):
|
||||
"Represents the expression >{data}"
|
||||
def __init__(self, data):
|
||||
self.data = data
|
||||
self.hardcoded = data.hardcoded
|
||||
|
||||
def __str__(self):
|
||||
return ">"+str(self.data)
|
||||
def valid(self, env=None, PCvalid=0):
|
||||
return ">" + str(self.data)
|
||||
|
||||
def valid(self, env=None, PCvalid=False):
|
||||
return self.data.valid(env, PCvalid)
|
||||
|
||||
def value(self, env=None):
|
||||
val = self.data.value(env)
|
||||
return (val >> 8) & 0xff
|
||||
|
||||
|
||||
|
||||
class LowByteExpr(Expr):
|
||||
"Represents the expression <{data}"
|
||||
def __init__(self, data):
|
||||
self.data = data
|
||||
self.hardcoded = data.hardcoded
|
||||
|
||||
def __str__(self):
|
||||
return "<"+str(self.data)
|
||||
def valid(self, env=None, PCvalid=0):
|
||||
return "<" + str(self.data)
|
||||
|
||||
def valid(self, env=None, PCvalid=False):
|
||||
return self.data.valid(env, PCvalid)
|
||||
|
||||
def value(self, env=None):
|
||||
val = self.data.value(env)
|
||||
return val & 0xff
|
||||
|
||||
|
||||
class SequenceExpr(Expr):
|
||||
"""Represents an interleaving of operands (of type Expr) and
|
||||
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]."""
|
||||
self.data = data
|
||||
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:
|
||||
if not i.hardcoded:
|
||||
self.hardcoded = 0
|
||||
self.hardcoded = False
|
||||
break
|
||||
else:
|
||||
self.hardcoded = 1
|
||||
self.hardcoded = True
|
||||
|
||||
def __str__(self):
|
||||
return "["+" ".join(map(str, self.data))+"]"
|
||||
def valid(self, env=None, PCvalid=0):
|
||||
return "[" + " ".join(map(str, self.data)) + "]"
|
||||
|
||||
def valid(self, env=None, PCvalid=False):
|
||||
for i in self.operands:
|
||||
if not i.valid(env, PCvalid):
|
||||
return 0
|
||||
return 1
|
||||
return False
|
||||
return True
|
||||
|
||||
def value(self, env=None):
|
||||
subs = map((lambda x: x.value(env)), self.operands)
|
||||
result = subs[0]
|
||||
@ -150,11 +186,19 @@ class SequenceExpr(Expr):
|
||||
result = self.operate(result, op, subs[index])
|
||||
index += 1
|
||||
return result
|
||||
|
||||
def operate(self, start, op, 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
|
||||
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
|
||||
if op == "-":
|
||||
return start - other
|
||||
if op == "&":
|
||||
return start & other
|
||||
if op == "|":
|
||||
return start | other
|
||||
if op == "^":
|
||||
return start ^ other
|
||||
|
@ -18,6 +18,7 @@ macros = {}
|
||||
currentname = None
|
||||
currentbody = None
|
||||
|
||||
|
||||
def newMacro(name):
|
||||
"Start creating a new macro with the specified name."
|
||||
global currentname
|
||||
@ -31,10 +32,12 @@ def newMacro(name):
|
||||
currentname = name
|
||||
currentbody = []
|
||||
|
||||
|
||||
def registerNode(node):
|
||||
global currentbody
|
||||
currentbody.append(IR.Node(node.ppt, node.nodetype, *node.data))
|
||||
|
||||
|
||||
def endMacro():
|
||||
global currentname
|
||||
global currentbody
|
||||
@ -46,21 +49,29 @@ def endMacro():
|
||||
currentname = None
|
||||
currentbody = None
|
||||
|
||||
|
||||
def expandMacro(ppt, name, arglist):
|
||||
global macros
|
||||
if name not in macros:
|
||||
Err.log("Undefined macro '%s'" % name)
|
||||
return IR.NullNode
|
||||
argexprs = [IR.Node(ppt, "Label", "_*%d" % i, arg) for (i, arg) in zip(xrange(1, sys.maxint), arglist)]
|
||||
bindexprs = [IR.Node(ppt, "Label", "_%d" % i, IR.LabelExpr("_*%d" % i)) 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")]
|
||||
argexprs = [IR.Node(ppt, "Label", "_*%d" % i, arg)
|
||||
for (i, arg) in zip(xrange(1, sys.maxint), arglist)]
|
||||
bindexprs = [IR.Node(ppt, "Label", "_%d" % i, IR.LabelExpr("_*%d" % i))
|
||||
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)
|
||||
|
||||
|
||||
def dump():
|
||||
global macros
|
||||
for mac in macros:
|
||||
body = macros[mac]
|
||||
print>>sys.stderr, "Macro: "+mac
|
||||
for node in body: print>>sys.stderr, node
|
||||
print>>sys.stderr, "Macro: " + mac
|
||||
for node in body:
|
||||
print>>sys.stderr, node
|
||||
print>>sys.stderr, ""
|
||||
|
@ -17,6 +17,7 @@ import Ophis.Environment
|
||||
import Ophis.CmdLine
|
||||
import Ophis.Opcodes
|
||||
|
||||
|
||||
def run_all(infile, outfile):
|
||||
"Transforms the source infile to a binary outfile."
|
||||
Err.count = 0
|
||||
@ -26,21 +27,31 @@ def run_all(infile, outfile):
|
||||
m = Ophis.Passes.ExpandMacros()
|
||||
i = Ophis.Passes.InitLabels()
|
||||
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 = 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()
|
||||
a = Ophis.Passes.Assembler()
|
||||
|
||||
passes = []
|
||||
passes.append(Ophis.Passes.DefineMacros())
|
||||
passes.append(Ophis.Passes.FixPoint("macro expansion", [m], lambda: m.changed == 0))
|
||||
passes.append(Ophis.Passes.FixPoint("label initialization", [i], lambda: i.changed == 0))
|
||||
passes.extend([Ophis.Passes.CircularityCheck(), Ophis.Passes.CheckExprs(), Ophis.Passes.EasyModes()])
|
||||
passes.append(Ophis.Passes.FixPoint("instruction selection 2", [c, b], lambda: b.expanded == 0))
|
||||
passes.extend([Ophis.Passes.NormalizeModes(), Ophis.Passes.UpdateLabels(), a])
|
||||
passes.append(Ophis.Passes.FixPoint("macro expansion", [m],
|
||||
lambda: not m.changed))
|
||||
passes.append(Ophis.Passes.FixPoint("label initialization", [i],
|
||||
lambda: not i.changed))
|
||||
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:
|
||||
try:
|
||||
@ -53,10 +64,11 @@ def run_all(infile, outfile):
|
||||
if outfile != '-':
|
||||
output.close()
|
||||
except IOError:
|
||||
print>>sys.stderr, "Could not write to "+outfile
|
||||
print>>sys.stderr, "Could not write to " + outfile
|
||||
else:
|
||||
Err.report()
|
||||
|
||||
|
||||
def run_ophis(args):
|
||||
Ophis.CmdLine.parse_args(args)
|
||||
Ophis.Frontend.pragma_modules.append(Ophis.CorePragmas)
|
||||
@ -69,5 +81,6 @@ def run_ophis(args):
|
||||
Ophis.CorePragmas.reset()
|
||||
run_all(Ophis.CmdLine.infile, Ophis.CmdLine.outfile)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
run_ophis(sys.argv[1:])
|
||||
|
@ -12,162 +12,291 @@
|
||||
# the tables in tools/opcodes. Edit those tables, not these.
|
||||
|
||||
# Names of addressing modes
|
||||
modes = ["Implied", # 0
|
||||
"Immediate", # 1
|
||||
"Zero Page", # 2
|
||||
"Zero Page, X", # 3
|
||||
"Zero Page, Y", # 4
|
||||
"Absolute", # 5
|
||||
"Absolute, X", # 6
|
||||
"Absolute, Y", # 7
|
||||
"(Absolute)", # 8
|
||||
"(Absolute, X)", # 9
|
||||
modes = ["Implied", # 0
|
||||
"Immediate", # 1
|
||||
"Zero Page", # 2
|
||||
"Zero Page, X", # 3
|
||||
"Zero Page, Y", # 4
|
||||
"Absolute", # 5
|
||||
"Absolute, X", # 6
|
||||
"Absolute, Y", # 7
|
||||
"(Absolute)", # 8
|
||||
"(Absolute, X)", # 9
|
||||
"(Absolute), Y", # 10
|
||||
"(Zero Page)", # 11
|
||||
"(Zero Page, X)", # 12
|
||||
"(Zero Page), Y", # 13
|
||||
"Relative"] # 14
|
||||
|
||||
|
||||
# Lengths of the argument
|
||||
lengths = [0, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1]
|
||||
|
||||
opcodes = {
|
||||
'adc': [None, 0x69, 0x65, 0x75, None, 0x6D, 0x7D, 0x79, None, None, None, None, 0x61, 0x71, None],
|
||||
'and': [None, 0x29, 0x25, 0x35, None, 0x2D, 0x3D, 0x39, None, None, None, None, 0x21, 0x31, None],
|
||||
'asl': [0x0A, None, 0x06, 0x16, None, 0x0E, 0x1E, None, None, None, None, None, None, None, None],
|
||||
'bcc': [None, None, None, None, None, None, None, None, None, None, None, None, None, None, 0x90],
|
||||
'bcs': [None, None, None, None, None, None, None, None, None, None, None, None, None, None, 0xB0],
|
||||
'beq': [None, None, None, None, None, None, None, None, None, None, None, None, None, None, 0xF0],
|
||||
'bit': [None, None, 0x24, None, None, 0x2C, None, None, None, None, None, None, None, None, None],
|
||||
'bmi': [None, None, None, None, None, None, None, None, None, None, None, None, None, None, 0x30],
|
||||
'bne': [None, None, None, None, None, None, None, None, None, None, None, None, None, None, 0xD0],
|
||||
'bpl': [None, None, None, None, None, None, None, None, None, None, None, None, None, None, 0x10],
|
||||
'brk': [0x00, None, None, None, None, None, None, None, None, None, None, None, None, None, None],
|
||||
'bvc': [None, None, None, None, None, None, None, None, None, None, None, None, None, None, 0x50],
|
||||
'bvs': [None, None, None, None, None, None, None, None, None, None, None, None, None, None, 0x70],
|
||||
'clc': [0x18, 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],
|
||||
'cli': [0x58, None, None, None, None, None, None, None, None, None, None, None, None, None, None],
|
||||
'clv': [0xB8, None, None, None, None, None, None, None, None, None, None, None, None, None, None],
|
||||
'cmp': [None, 0xC9, 0xC5, 0xD5, None, 0xCD, 0xDD, 0xD9, None, None, None, None, 0xC1, 0xD1, None],
|
||||
'cpx': [None, 0xE0, 0xE4, None, None, 0xEC, None, None, None, None, None, None, None, None, None],
|
||||
'cpy': [None, 0xC0, 0xC4, None, None, 0xCC, None, None, None, None, None, None, None, None, None],
|
||||
'dec': [None, None, 0xC6, 0xD6, None, 0xCE, 0xDE, None, None, None, None, None, None, None, None],
|
||||
'dex': [0xCA, 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],
|
||||
'eor': [None, 0x49, 0x45, 0x55, None, 0x4D, 0x5D, 0x59, None, None, None, None, 0x41, 0x51, None],
|
||||
'inc': [None, None, 0xE6, 0xF6, None, 0xEE, 0xFE, None, None, None, None, None, None, None, None],
|
||||
'inx': [0xE8, None, None, None, None, None, None, None, None, None, None, None, None, None, None],
|
||||
'iny': [0xC8, None, None, None, None, None, None, None, None, None, None, None, None, None, None],
|
||||
'jmp': [None, None, None, None, None, 0x4C, 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],
|
||||
'adc': [None, 0x69, 0x65, 0x75, None, 0x6D, 0x7D, 0x79,
|
||||
None, None, None, None, 0x61, 0x71, None],
|
||||
'and': [None, 0x29, 0x25, 0x35, None, 0x2D, 0x3D, 0x39,
|
||||
None, None, None, None, 0x21, 0x31, None],
|
||||
'asl': [0x0A, None, 0x06, 0x16, None, 0x0E, 0x1E, None,
|
||||
None, None, None, None, None, None, None],
|
||||
'bcc': [None, None, None, None, None, None, None, None,
|
||||
None, None, None, None, None, None, 0x90],
|
||||
'bcs': [None, None, None, None, None, None, None, None,
|
||||
None, None, None, None, None, None, 0xB0],
|
||||
'beq': [None, None, None, None, None, None, None, None,
|
||||
None, None, None, None, None, None, 0xF0],
|
||||
'bit': [None, None, 0x24, None, None, 0x2C, None, None,
|
||||
None, None, None, None, None, None, None],
|
||||
'bmi': [None, None, None, None, None, None, None, None,
|
||||
None, None, None, None, None, None, 0x30],
|
||||
'bne': [None, None, None, None, None, None, None, None,
|
||||
None, None, None, None, None, None, 0xD0],
|
||||
'bpl': [None, None, None, None, None, None, None, None,
|
||||
None, None, None, None, None, None, 0x10],
|
||||
'brk': [0x00, None, None, None, None, None, None, None,
|
||||
None, None, None, None, None, None, None],
|
||||
'bvc': [None, None, None, None, None, None, None, None,
|
||||
None, None, None, None, None, None, 0x50],
|
||||
'bvs': [None, None, None, None, None, None, None, None,
|
||||
None, None, None, None, None, None, 0x70],
|
||||
'clc': [0x18, 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],
|
||||
'cli': [0x58, None, None, None, None, None, None, None,
|
||||
None, None, None, None, None, None, None],
|
||||
'clv': [0xB8, None, None, None, None, None, None, None,
|
||||
None, None, None, None, None, None, None],
|
||||
'cmp': [None, 0xC9, 0xC5, 0xD5, None, 0xCD, 0xDD, 0xD9,
|
||||
None, None, None, None, 0xC1, 0xD1, None],
|
||||
'cpx': [None, 0xE0, 0xE4, None, None, 0xEC, None, None,
|
||||
None, None, None, None, None, None, None],
|
||||
'cpy': [None, 0xC0, 0xC4, None, None, 0xCC, None, None,
|
||||
None, None, None, None, None, None, None],
|
||||
'dec': [None, None, 0xC6, 0xD6, None, 0xCE, 0xDE, None,
|
||||
None, None, None, None, None, None, None],
|
||||
'dex': [0xCA, 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],
|
||||
'eor': [None, 0x49, 0x45, 0x55, None, 0x4D, 0x5D, 0x59,
|
||||
None, None, None, None, 0x41, 0x51, None],
|
||||
'inc': [None, None, 0xE6, 0xF6, None, 0xEE, 0xFE, None,
|
||||
None, None, None, None, None, None, None],
|
||||
'inx': [0xE8, None, None, None, None, None, None, None,
|
||||
None, None, None, None, None, None, None],
|
||||
'iny': [0xC8, None, None, None, None, None, None, None,
|
||||
None, None, None, None, None, None, None],
|
||||
'jmp': [None, None, None, None, None, 0x4C, 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 = {
|
||||
'anc': [None, 0x0B, None, None, None, None, None, None, None, None, None, None, None, None, None],
|
||||
'ane': [None, 0x8B, 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],
|
||||
'asr': [None, 0x4B, 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],
|
||||
'isb': [None, None, 0xE7, 0xF7, None, 0xEF, 0xFF, 0xFB, None, None, None, None, 0xE3, 0xF3, None],
|
||||
'las': [None, None, None, None, None, None, None, 0xBB, None, None, None, None, None, None, None],
|
||||
'lax': [None, None, 0xA7, None, 0xB7, 0xAF, None, 0xBF, None, None, None, None, 0xA3, 0xB3, None],
|
||||
'lxa': [None, 0xAB, None, None, None, None, None, None, None, None, None, None, None, None, 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],
|
||||
'anc': [None, 0x0B, None, None, None, None, None, None,
|
||||
None, None, None, None, None, None, None],
|
||||
'ane': [None, 0x8B, 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],
|
||||
'asr': [None, 0x4B, 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],
|
||||
'isb': [None, None, 0xE7, 0xF7, None, 0xEF, 0xFF, 0xFB,
|
||||
None, None, None, None, 0xE3, 0xF3, None],
|
||||
'las': [None, None, None, None, None, None, None, 0xBB,
|
||||
None, None, None, None, None, None, None],
|
||||
'lax': [None, None, 0xA7, None, 0xB7, 0xAF, None, 0xBF,
|
||||
None, None, None, None, 0xA3, 0xB3, None],
|
||||
'lxa': [None, 0xAB, None, None, None, None, None, None,
|
||||
None, None, None, None, None, None, 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 = {
|
||||
'adc': [None, 0x69, 0x65, 0x75, None, 0x6D, 0x7D, 0x79, None, None, None, 0x72, 0x61, 0x71, None],
|
||||
'and': [None, 0x29, 0x25, 0x35, None, 0x2D, 0x3D, 0x39, None, None, None, 0x32, 0x21, 0x31, None],
|
||||
'bbr0': [None, None, None, None, None, None, None, None, None, None, None, None, None, None, 0x0F],
|
||||
'bbr1': [None, None, None, None, None, None, None, None, None, None, None, None, None, None, 0x1F],
|
||||
'bbr2': [None, None, None, None, None, None, None, None, None, None, None, None, None, None, 0x2F],
|
||||
'bbr3': [None, None, None, None, None, None, None, None, None, None, None, None, None, None, 0x3F],
|
||||
'bbr4': [None, None, None, None, None, None, None, None, None, None, None, None, None, None, 0x4F],
|
||||
'bbr5': [None, None, None, None, None, None, None, None, None, None, None, None, None, None, 0x5F],
|
||||
'bbr6': [None, None, None, None, None, None, None, None, None, None, None, None, None, None, 0x6F],
|
||||
'bbr7': [None, None, None, None, None, None, None, None, None, None, None, None, None, None, 0x7F],
|
||||
'bbs0': [None, None, None, None, None, None, None, None, None, None, None, None, None, None, 0x8F],
|
||||
'bbs1': [None, None, None, None, None, None, None, None, None, None, None, None, None, None, 0x9F],
|
||||
'bbs2': [None, None, None, None, None, None, None, None, None, None, None, None, None, None, 0xAF],
|
||||
'bbs3': [None, None, None, None, None, None, None, None, None, None, None, None, None, None, 0xBF],
|
||||
'bbs4': [None, None, None, None, None, None, None, None, None, None, None, None, None, None, 0xCF],
|
||||
'bbs5': [None, None, None, None, None, None, None, None, None, None, None, None, None, None, 0xDF],
|
||||
'bbs6': [None, None, None, None, None, None, None, None, None, None, None, None, None, None, 0xEF],
|
||||
'bbs7': [None, None, None, None, None, None, None, None, None, None, None, None, None, None, 0xFF],
|
||||
'bit': [None, 0x89, 0x24, 0x34, None, 0x2C, 0x3C, None, None, None, None, None, None, None, None],
|
||||
'bra': [None, None, None, None, None, None, None, None, None, None, None, None, None, None, 0x80],
|
||||
'cmp': [None, 0xC9, 0xC5, 0xD5, None, 0xCD, 0xDD, 0xD9, None, None, None, 0xD2, 0xC1, 0xD1, None],
|
||||
'dea': [0x3A, None, None, None, None, None, None, None, None, None, None, None, None, None, None],
|
||||
'dec': [0x3A, None, 0xC6, 0xD6, None, 0xCE, 0xDE, None, None, None, None, None, None, None, None],
|
||||
'eor': [None, 0x49, 0x45, 0x55, None, 0x4D, 0x5D, 0x59, None, None, None, 0x52, 0x41, 0x51, None],
|
||||
'ina': [0x1A, None, None, None, None, None, None, None, None, None, None, None, None, None, None],
|
||||
'inc': [0x1A, None, 0xE6, 0xF6, None, 0xEE, 0xFE, None, None, None, None, None, None, None, None],
|
||||
'jmp': [None, None, None, None, None, 0x4C, None, None, 0x6C, 0x7C, None, None, None, None, None],
|
||||
'lda': [None, 0xA9, 0xA5, 0xB5, None, 0xAD, 0xBD, 0xB9, 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],
|
||||
'adc': [None, 0x69, 0x65, 0x75, None, 0x6D, 0x7D, 0x79,
|
||||
None, None, None, 0x72, 0x61, 0x71, None],
|
||||
'and': [None, 0x29, 0x25, 0x35, None, 0x2D, 0x3D, 0x39,
|
||||
None, None, None, 0x32, 0x21, 0x31, None],
|
||||
'bbr0': [None, None, None, None, None, None, None, None,
|
||||
None, None, None, None, None, None, 0x0F],
|
||||
'bbr1': [None, None, None, None, None, None, None, None,
|
||||
None, None, None, None, None, None, 0x1F],
|
||||
'bbr2': [None, None, None, None, None, None, None, None,
|
||||
None, None, None, None, None, None, 0x2F],
|
||||
'bbr3': [None, None, None, None, None, None, None, None,
|
||||
None, None, None, None, None, None, 0x3F],
|
||||
'bbr4': [None, None, None, None, None, None, None, None,
|
||||
None, None, None, None, None, None, 0x4F],
|
||||
'bbr5': [None, None, None, None, None, None, None, None,
|
||||
None, None, None, None, None, None, 0x5F],
|
||||
'bbr6': [None, None, None, None, None, None, None, None,
|
||||
None, None, None, None, None, None, 0x6F],
|
||||
'bbr7': [None, None, None, None, None, None, None, None,
|
||||
None, None, None, None, None, None, 0x7F],
|
||||
'bbs0': [None, None, None, None, None, None, None, None,
|
||||
None, None, None, None, None, None, 0x8F],
|
||||
'bbs1': [None, None, None, None, None, None, None, None,
|
||||
None, None, None, None, None, None, 0x9F],
|
||||
'bbs2': [None, None, None, None, None, None, None, None,
|
||||
None, None, None, None, None, None, 0xAF],
|
||||
'bbs3': [None, None, None, None, None, None, None, None,
|
||||
None, None, None, None, None, None, 0xBF],
|
||||
'bbs4': [None, None, None, None, None, None, None, None,
|
||||
None, None, None, None, None, None, 0xCF],
|
||||
'bbs5': [None, None, None, None, None, None, None, None,
|
||||
None, None, None, None, None, None, 0xDF],
|
||||
'bbs6': [None, None, None, None, None, None, None, None,
|
||||
None, None, None, None, None, None, 0xEF],
|
||||
'bbs7': [None, None, None, None, None, None, None, None,
|
||||
None, None, None, None, None, None, 0xFF],
|
||||
'bit': [None, 0x89, 0x24, 0x34, None, 0x2C, 0x3C, None,
|
||||
None, None, None, None, None, None, None],
|
||||
'bra': [None, None, None, None, None, None, None, None,
|
||||
None, None, None, None, None, None, 0x80],
|
||||
'cmp': [None, 0xC9, 0xC5, 0xD5, None, 0xCD, 0xDD, 0xD9,
|
||||
None, None, None, 0xD2, 0xC1, 0xD1, None],
|
||||
'dea': [0x3A, None, None, None, None, None, None, None,
|
||||
None, None, None, None, None, None, None],
|
||||
'dec': [0x3A, None, 0xC6, 0xD6, None, 0xCE, 0xDE, None,
|
||||
None, None, None, None, None, None, None],
|
||||
'eor': [None, 0x49, 0x45, 0x55, None, 0x4D, 0x5D, 0x59,
|
||||
None, None, None, 0x52, 0x41, 0x51, None],
|
||||
'ina': [0x1A, None, None, None, None, None, None, None,
|
||||
None, None, None, None, None, None, None],
|
||||
'inc': [0x1A, None, 0xE6, 0xF6, None, 0xEE, 0xFE, None,
|
||||
None, None, None, None, None, None, None],
|
||||
'jmp': [None, None, None, None, None, 0x4C, None, None,
|
||||
0x6C, 0x7C, None, None, None, None, None],
|
||||
'lda': [None, 0xA9, 0xA5, 0xB5, None, 0xAD, 0xBD, 0xB9,
|
||||
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],
|
||||
}
|
||||
|
||||
|
@ -6,7 +6,7 @@
|
||||
translation occurs. This structure also makes the assembler
|
||||
very extensible; additional analyses or optimizations may be
|
||||
added as new subclasses of Pass."""
|
||||
|
||||
|
||||
# Copyright 2002-2012 Michael C. Martin and additional contributors.
|
||||
# You may use, modify, and distribute this file under the MIT
|
||||
# license: See README for details.
|
||||
@ -20,41 +20,55 @@ import Ophis.Macro as Macro
|
||||
|
||||
# The passes themselves
|
||||
|
||||
|
||||
class Pass(object):
|
||||
"""Superclass for all assembler passes. Automatically handles IR
|
||||
types that modify the environent's structure, and by default
|
||||
raises an error on anything else. Override visitUnknown in your
|
||||
extension pass to produce a pass that accepts everything."""
|
||||
name = "Default Pass"
|
||||
|
||||
def __init__(self):
|
||||
self.writeOK = 1
|
||||
self.writeOK = True
|
||||
|
||||
def visitNone(self, node, env):
|
||||
pass
|
||||
|
||||
def visitSEQUENCE(self, node, env):
|
||||
Err.currentpoint = node.ppt
|
||||
for n in node.data:
|
||||
n.accept(self, env)
|
||||
|
||||
def visitDataSegment(self, node, env):
|
||||
self.writeOK = 0
|
||||
self.writeOK = False
|
||||
env.setsegment(node.data[0])
|
||||
|
||||
def visitTextSegment(self, node, env):
|
||||
self.writeOK = 1
|
||||
self.writeOK = True
|
||||
env.setsegment(node.data[0])
|
||||
|
||||
def visitScopeBegin(self, node, env):
|
||||
env.newscope()
|
||||
|
||||
def visitScopeEnd(self, node, env):
|
||||
env.endscope()
|
||||
|
||||
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):
|
||||
pass
|
||||
|
||||
def postPass(self):
|
||||
pass
|
||||
|
||||
def go(self, node, env):
|
||||
"""Prepares the environment and runs this pass, possibly
|
||||
"""Prepares the environment and runs this pass, possibly
|
||||
printing debugging information."""
|
||||
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()
|
||||
self.prePass()
|
||||
node.accept(self, env)
|
||||
@ -67,6 +81,7 @@ class Pass(object):
|
||||
print>>sys.stderr, "Current IR:"
|
||||
print>>sys.stderr, node
|
||||
|
||||
|
||||
class FixPoint(object):
|
||||
"""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."""
|
||||
@ -74,48 +89,60 @@ class FixPoint(object):
|
||||
self.name = name
|
||||
self.passes = passes
|
||||
self.fixpoint = fixpoint
|
||||
|
||||
def go(self, node, env):
|
||||
"""Runs this FixPoint's passes, in order, until the fixpoint
|
||||
is true. Always runs the passes at least once."""
|
||||
for i in xrange(100):
|
||||
if Err.count != 0: break
|
||||
if Err.count != 0:
|
||||
break
|
||||
for p in self.passes:
|
||||
p.go(node, env)
|
||||
if Err.count != 0: break
|
||||
if self.fixpoint(): break
|
||||
if Cmd.print_pass: print>>sys.stderr, "Fixpoint failed, looping back"
|
||||
if Err.count != 0:
|
||||
break
|
||||
if self.fixpoint():
|
||||
break
|
||||
if Cmd.print_pass:
|
||||
print>>sys.stderr, "Fixpoint failed, looping back"
|
||||
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):
|
||||
"Extract macro definitions and remove them from the IR"
|
||||
name = "Macro definition pass"
|
||||
|
||||
def prePass(self):
|
||||
self.inDef = 0
|
||||
self.nestedError = 0
|
||||
self.inDef = False
|
||||
self.nestedError = False
|
||||
|
||||
def postPass(self):
|
||||
if self.inDef:
|
||||
Err.log("Unmatched .macro")
|
||||
elif Cmd.print_ir:
|
||||
print>>sys.stderr, "Macro definitions:"
|
||||
Macro.dump()
|
||||
|
||||
def visitMacroBegin(self, node, env):
|
||||
if self.inDef:
|
||||
Err.log("Nested macro definition")
|
||||
self.nestedError = 1
|
||||
self.nestedError = True
|
||||
else:
|
||||
Macro.newMacro(node.data[0])
|
||||
node.nodetype = "None"
|
||||
node.data = []
|
||||
self.inDef = 1
|
||||
self.inDef = True
|
||||
|
||||
def visitMacroEnd(self, node, env):
|
||||
if self.inDef:
|
||||
Macro.endMacro()
|
||||
node.nodetype = "None"
|
||||
node.data = []
|
||||
self.inDef = 0
|
||||
self.inDef = False
|
||||
elif not self.nestedError:
|
||||
Err.log("Unmatched .macend")
|
||||
|
||||
def visitUnknown(self, node, env):
|
||||
if self.inDef:
|
||||
Macro.registerNode(node)
|
||||
@ -126,305 +153,438 @@ class DefineMacros(Pass):
|
||||
class ExpandMacros(Pass):
|
||||
"Replace macro invocations with the appropriate text"
|
||||
name = "Macro expansion pass"
|
||||
|
||||
def prePass(self):
|
||||
self.changed = 0
|
||||
self.changed = False
|
||||
|
||||
def visitMacroInvoke(self, node, env):
|
||||
replacement = Macro.expandMacro(node.ppt, node.data[0], node.data[1:])
|
||||
node.nodetype = replacement.nodetype
|
||||
node.data = replacement.data
|
||||
self.changed = 1
|
||||
self.changed = True
|
||||
|
||||
def visitUnknown(self, node, env):
|
||||
pass
|
||||
|
||||
|
||||
class InitLabels(Pass):
|
||||
"Finds all reachable labels"
|
||||
name = "Label initialization pass"
|
||||
|
||||
def __init__(self):
|
||||
Pass.__init__(self)
|
||||
self.labelmap = {}
|
||||
|
||||
def prePass(self):
|
||||
self.changed = 0
|
||||
self.PCvalid = 1
|
||||
self.changed = False
|
||||
self.PCvalid = True
|
||||
|
||||
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):
|
||||
self.PCvalid=node.data[0].valid(env, self.PCvalid)
|
||||
self.PCvalid = node.data[0].valid(env, self.PCvalid)
|
||||
|
||||
def visitLabel(self, node, env):
|
||||
(label, val) = node.data
|
||||
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)
|
||||
if fulllabel not in self.labelmap:
|
||||
self.labelmap[fulllabel] = node
|
||||
if val.valid(env, self.PCvalid) and label not in env:
|
||||
env[label]=0
|
||||
self.changed=1
|
||||
env[label] = 0
|
||||
self.changed = True
|
||||
|
||||
def visitUnknown(self, node, env):
|
||||
pass
|
||||
|
||||
|
||||
class CircularityCheck(Pass):
|
||||
"Checks for circular label dependencies"
|
||||
name = "Circularity check pass"
|
||||
|
||||
def prePass(self):
|
||||
self.changed=0
|
||||
self.PCvalid=1
|
||||
self.changed = False
|
||||
self.PCvalid = True
|
||||
|
||||
def visitAdvance(self, node, env):
|
||||
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):
|
||||
Err.log("Undefined or circular reference on .advance")
|
||||
|
||||
def visitSetPC(self, node, env):
|
||||
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):
|
||||
Err.log("Undefined or circular reference on program counter set")
|
||||
|
||||
def visitCheckPC(self, node, env):
|
||||
if not node.data[0].valid(env, self.PCvalid):
|
||||
Err.log("Undefined or circular reference on program counter check")
|
||||
|
||||
def visitLabel(self, node, env):
|
||||
(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)
|
||||
|
||||
def visitUnknown(self, node, env):
|
||||
pass
|
||||
|
||||
|
||||
class CheckExprs(Pass):
|
||||
"Ensures all expressions can resolve"
|
||||
name = "Expression checking pass"
|
||||
|
||||
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)]:
|
||||
i.value(env) # Throw away result, just confirm validity of all expressions
|
||||
i.value(env)
|
||||
|
||||
|
||||
class EasyModes(Pass):
|
||||
"Assigns address modes to hardcoded and branch instructions"
|
||||
name = "Easy addressing modes pass"
|
||||
|
||||
def visitMemory(self, node, env):
|
||||
if Ops.opcodes[node.data[0]][14] is not None:
|
||||
node.nodetype = "Relative"
|
||||
return
|
||||
if node.data[1].hardcoded:
|
||||
if node.data[1].hardcoded:
|
||||
if not collapse_no_index(node, env):
|
||||
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):
|
||||
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):
|
||||
node.nodetype = "AbsoluteY"
|
||||
|
||||
def visitPointer(self, node, env):
|
||||
if node.data[1].hardcoded:
|
||||
if not collapse_no_index_ind(node, env):
|
||||
node.nodetype = "Indirect"
|
||||
|
||||
def visitPointerX(self, node, env):
|
||||
if node.data[1].hardcoded:
|
||||
if not collapse_x_ind(node, env):
|
||||
node.nodetype = "AbsIndX"
|
||||
|
||||
def visitPointerY(self, node, env):
|
||||
if node.data[1].hardcoded:
|
||||
if not collapse_y_ind(node, env):
|
||||
node.nodetype = "AbsIndY"
|
||||
|
||||
def visitUnknown(self, node, env):
|
||||
pass
|
||||
|
||||
|
||||
class PCTracker(Pass):
|
||||
"Superclass for passes that need an accurate program counter."
|
||||
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 visitImplied(self, node, env): env.incPC(1)
|
||||
def visitImmediate(self, node, env): env.incPC(2)
|
||||
def visitIndirectX(self, node, env): env.incPC(2)
|
||||
def visitIndirectY(self, node, env): env.incPC(2)
|
||||
def visitZPIndirect(self, node, env): env.incPC(2)
|
||||
def visitZeroPage(self, node, env): env.incPC(2)
|
||||
def visitZeroPageX(self, node, env): env.incPC(2)
|
||||
def visitZeroPageY(self, node, env): 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)
|
||||
|
||||
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 visitImplied(self, node, env):
|
||||
env.incPC(1)
|
||||
|
||||
def visitImmediate(self, node, env):
|
||||
env.incPC(2)
|
||||
|
||||
def visitIndirectX(self, node, env):
|
||||
env.incPC(2)
|
||||
|
||||
def visitIndirectY(self, node, env):
|
||||
env.incPC(2)
|
||||
|
||||
def visitZPIndirect(self, node, env):
|
||||
env.incPC(2)
|
||||
|
||||
def visitZeroPage(self, node, env):
|
||||
env.incPC(2)
|
||||
|
||||
def visitZeroPageX(self, node, env):
|
||||
env.incPC(2)
|
||||
|
||||
def visitZeroPageY(self, node, env):
|
||||
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):
|
||||
"Computes the new values for all entries in the symbol table"
|
||||
name = "Label Update Pass"
|
||||
|
||||
def prePass(self):
|
||||
self.changed = 0
|
||||
self.changed = False
|
||||
|
||||
def visitLabel(self, node, env):
|
||||
(label, val) = node.data
|
||||
old = env[label]
|
||||
env[label] = val.value(env)
|
||||
if old != env[label]:
|
||||
self.changed = 1
|
||||
self.changed = True
|
||||
|
||||
|
||||
class Collapse(Pass):
|
||||
"""Selects as many zero-page instructions to convert as
|
||||
possible, and tracks how many instructions have been
|
||||
converted this pass."""
|
||||
"Selects as many zero-page instructions to convert as possible."
|
||||
name = "Instruction Collapse Pass"
|
||||
|
||||
def prePass(self):
|
||||
self.collapsed = 0
|
||||
self.changed = False
|
||||
|
||||
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):
|
||||
if collapse_x(node, env): self.collapsed += 1
|
||||
self.changed |= collapse_x(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):
|
||||
if collapse_no_index_ind(node, env): self.collapsed += 1
|
||||
self.changed |= collapse_no_index_ind(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):
|
||||
if collapse_y_ind(node, env): self.collapsed += 1
|
||||
self.changed |= collapse_y_ind(node, env)
|
||||
|
||||
def visitUnknown(self, node, env):
|
||||
pass
|
||||
|
||||
|
||||
def collapse_no_index(node, env):
|
||||
"""Transforms a Memory node into a ZeroPage one if possible.
|
||||
Returns 1 if it made the collapse, false otherwise."""
|
||||
if node.data[1].value(env) < 0x100 and Ops.opcodes[node.data[0]][2] is not None:
|
||||
node.nodetype = "ZeroPage"
|
||||
return 1
|
||||
else:
|
||||
return 0
|
||||
Returns boolean indicating whether or not it made the collapse."""
|
||||
if node.data[1].value(env) < 0x100:
|
||||
if Ops.opcodes[node.data[0]][2] is not None:
|
||||
node.nodetype = "ZeroPage"
|
||||
return True
|
||||
return False
|
||||
|
||||
|
||||
def collapse_x(node, env):
|
||||
"""Transforms a MemoryX node into a ZeroPageX one if possible.
|
||||
Returns 1 if it made the collapse, false otherwise."""
|
||||
if node.data[1].value(env) < 0x100 and Ops.opcodes[node.data[0]][3] is not None:
|
||||
node.nodetype = "ZeroPageX"
|
||||
return 1
|
||||
else:
|
||||
return 0
|
||||
Returns boolean indicating whether or not it made the collapse."""
|
||||
if node.data[1].value(env) < 0x100:
|
||||
if Ops.opcodes[node.data[0]][3] is not None:
|
||||
node.nodetype = "ZeroPageX"
|
||||
return True
|
||||
return False
|
||||
|
||||
|
||||
def collapse_y(node, env):
|
||||
"""Transforms a MemoryY node into a ZeroPageY one if possible.
|
||||
Returns 1 if it made the collapse, false otherwise."""
|
||||
if node.data[1].value(env) < 0x100 and Ops.opcodes[node.data[0]][4] is not None:
|
||||
node.nodetype = "ZeroPageY"
|
||||
return 1
|
||||
else:
|
||||
return 0
|
||||
Returns boolean indicating whether or not it made the collapse."""
|
||||
if node.data[1].value(env) < 0x100:
|
||||
if Ops.opcodes[node.data[0]][4] is not None:
|
||||
node.nodetype = "ZeroPageY"
|
||||
return True
|
||||
return False
|
||||
|
||||
|
||||
def collapse_no_index_ind(node, env):
|
||||
"""Transforms a Pointer node into a ZPIndirect one if possible.
|
||||
Returns 1 if it made the collapse, false otherwise."""
|
||||
if node.data[1].value(env) < 0x100 and Ops.opcodes[node.data[0]][11] is not None:
|
||||
node.nodetype = "ZPIndirect"
|
||||
return 1
|
||||
else:
|
||||
return 0
|
||||
Returns boolean indicating whether or not it made the collapse."""
|
||||
if node.data[1].value(env) < 0x100:
|
||||
if Ops.opcodes[node.data[0]][11] is not None:
|
||||
node.nodetype = "ZPIndirect"
|
||||
return True
|
||||
return False
|
||||
|
||||
|
||||
def collapse_x_ind(node, env):
|
||||
"""Transforms a PointerX node into an IndirectX one if possible.
|
||||
Returns 1 if it made the collapse, false otherwise."""
|
||||
if node.data[1].value(env) < 0x100 and Ops.opcodes[node.data[0]][12] is not None:
|
||||
node.nodetype = "IndirectX"
|
||||
return 1
|
||||
else:
|
||||
return 0
|
||||
Returns boolean indicating whether or not it made the collapse."""
|
||||
if node.data[1].value(env) < 0x100:
|
||||
if Ops.opcodes[node.data[0]][12] is not None:
|
||||
node.nodetype = "IndirectX"
|
||||
return True
|
||||
return False
|
||||
|
||||
|
||||
def collapse_y_ind(node, env):
|
||||
"""Transforms a PointerY node into an IndirectY one if possible.
|
||||
Returns 1 if it made the collapse, false otherwise."""
|
||||
if node.data[1].value(env) < 0x100 and Ops.opcodes[node.data[0]][13] is not None:
|
||||
node.nodetype = "IndirectY"
|
||||
return 1
|
||||
else:
|
||||
return 0
|
||||
Returns boolean indicating whether or not it made the collapse."""
|
||||
if node.data[1].value(env) < 0x100:
|
||||
if Ops.opcodes[node.data[0]][13] is not None:
|
||||
node.nodetype = "IndirectY"
|
||||
return True
|
||||
return False
|
||||
|
||||
|
||||
class ExtendBranches(PCTracker):
|
||||
"""Eliminates any branch instructions that would end up going past
|
||||
the 128-byte range, and replaces them with a branch-jump
|
||||
pair. Also tracks how many elements where changed this pass."""
|
||||
the 128-byte range, and replaces them with a branch-jump pair."""
|
||||
name = "Branch Expansion Pass"
|
||||
reversed = { 'bcc': 'bcs',
|
||||
'bcs': 'bcc',
|
||||
'beq': 'bne',
|
||||
'bmi': 'bpl',
|
||||
'bne': 'beq',
|
||||
'bpl': 'bmi',
|
||||
'bvc': 'bvs',
|
||||
'bvs': 'bvc',
|
||||
# 65c02 ones. 'bra' is special, though, having no inverse
|
||||
'bbr0': 'bbs0',
|
||||
'bbs0': 'bbr0',
|
||||
'bbr1': 'bbs1',
|
||||
'bbs1': 'bbr1',
|
||||
'bbr2': 'bbs2',
|
||||
'bbs2': 'bbr2',
|
||||
'bbr3': 'bbs3',
|
||||
'bbs3': 'bbr3',
|
||||
'bbr4': 'bbs4',
|
||||
'bbs4': 'bbr4',
|
||||
'bbr5': 'bbs5',
|
||||
'bbs5': 'bbr5',
|
||||
'bbr6': 'bbs6',
|
||||
'bbs6': 'bbr6',
|
||||
'bbr7': 'bbs7',
|
||||
'bbs7': 'bbr7'
|
||||
}
|
||||
reversed = {'bcc': 'bcs',
|
||||
'bcs': 'bcc',
|
||||
'beq': 'bne',
|
||||
'bmi': 'bpl',
|
||||
'bne': 'beq',
|
||||
'bpl': 'bmi',
|
||||
'bvc': 'bvs',
|
||||
'bvs': 'bvc',
|
||||
# 65c02 ones. 'bra' is special, though, having no inverse
|
||||
'bbr0': 'bbs0',
|
||||
'bbs0': 'bbr0',
|
||||
'bbr1': 'bbs1',
|
||||
'bbs1': 'bbr1',
|
||||
'bbr2': 'bbs2',
|
||||
'bbs2': 'bbr2',
|
||||
'bbr3': 'bbs3',
|
||||
'bbs3': 'bbr3',
|
||||
'bbr4': 'bbs4',
|
||||
'bbs4': 'bbr4',
|
||||
'bbr5': 'bbs5',
|
||||
'bbs5': 'bbr5',
|
||||
'bbr6': 'bbs6',
|
||||
'bbs6': 'bbr6',
|
||||
'bbr7': 'bbs7',
|
||||
'bbs7': 'bbr7'
|
||||
}
|
||||
|
||||
def prePass(self):
|
||||
self.expanded = 0
|
||||
self.changed = False
|
||||
|
||||
def visitRelative(self, node, env):
|
||||
(opcode, expr) = node.data
|
||||
arg = expr.value(env)
|
||||
arg = arg-(env.getPC()+2)
|
||||
arg = arg - (env.getPC() + 2)
|
||||
if arg < -128 or arg > 127:
|
||||
if opcode == 'bra':
|
||||
# If BRA - BRanch Always - is out of range, it's a JMP.
|
||||
node.data = ('jmp', expr)
|
||||
node.nodetype = "Absolute"
|
||||
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:
|
||||
# Otherwise, we replace it with a 'macro' of sorts by hand:
|
||||
# $branch LOC -> $reversed_branch ^+5; JMP LOC
|
||||
# We don't use temp labels here because labels need to have been fixed
|
||||
# in place by this point, and JMP is always 3 bytes long.
|
||||
expansion = [IR.Node(node.ppt, "Relative", ExtendBranches.reversed[opcode], IR.SequenceExpr([IR.PCExpr(), "+", IR.ConstantExpr(5)])),
|
||||
# We don't use temp labels here because labels need to have
|
||||
# been fixed in place by this point, and JMP is always 3
|
||||
# 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)]
|
||||
node.nodetype='SEQUENCE'
|
||||
node.nodetype = 'SEQUENCE'
|
||||
node.data = expansion
|
||||
if Cmd.warn_on_branch_extend:
|
||||
print>>sys.stderr, str(node.ppt) + ": WARNING: "+opcode+" out of range, replacing with "+ExtendBranches.reversed[opcode] +"/jmp combo"
|
||||
self.expanded += 1
|
||||
print>>sys.stderr, str(node.ppt) + ": WARNING: " + \
|
||||
opcode + " out of range, " \
|
||||
"replacing with " + \
|
||||
ExtendBranches.reversed[opcode] + \
|
||||
"/jmp combo"
|
||||
self.changed = True
|
||||
node.accept(self, env)
|
||||
else:
|
||||
env.incPC(2)
|
||||
|
||||
|
||||
class NormalizeModes(Pass):
|
||||
"""Eliminates the intermediate "Memory" and "Pointer" nodes,
|
||||
converting them to "Absolute"."""
|
||||
name = "Mode Normalization pass"
|
||||
def visitMemory(self, node, env): node.nodetype = "Absolute"
|
||||
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"
|
||||
|
||||
def visitMemory(self, node, env):
|
||||
node.nodetype = "Absolute"
|
||||
|
||||
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.
|
||||
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):
|
||||
"""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."""
|
||||
name = "Assembler"
|
||||
|
||||
@ -436,36 +596,40 @@ class Assembler(Pass):
|
||||
|
||||
def postPass(self):
|
||||
if Cmd.print_summary and Err.count == 0:
|
||||
print>>sys.stderr, "Assembly complete: %s bytes output (%s code, %s data, %s filler)" \
|
||||
% (len(self.output), self.code, self.data, self.filler)
|
||||
print>>sys.stderr, "Assembly complete: %s bytes output " \
|
||||
"(%s code, %s data, %s filler)" \
|
||||
% (len(self.output),
|
||||
self.code, self.data, self.filler)
|
||||
|
||||
def outputbyte(self, expr, env):
|
||||
'Outputs a byte, with range checking'
|
||||
if self.writeOK:
|
||||
val = expr.value(env)
|
||||
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
|
||||
self.output.append(int(val))
|
||||
else:
|
||||
Err.log("Attempt to write to data segment")
|
||||
|
||||
def outputword(self, expr, env):
|
||||
'Outputs a little-endian word, with range checking'
|
||||
if self.writeOK:
|
||||
val = expr.value(env)
|
||||
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
|
||||
self.output.append(int(val & 0xFF))
|
||||
self.output.append(int((val >> 8) & 0xFF))
|
||||
else:
|
||||
Err.log("Attempt to write to data segment")
|
||||
|
||||
def outputdword(self, expr, env):
|
||||
'Outputs a little-endian dword, with range checking'
|
||||
if self.writeOK:
|
||||
val = expr.value(env)
|
||||
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
|
||||
self.output.append(int(val & 0xFF))
|
||||
self.output.append(int((val >> 8) & 0xFF))
|
||||
@ -479,18 +643,19 @@ class Assembler(Pass):
|
||||
if self.writeOK:
|
||||
val = expr.value(env)
|
||||
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
|
||||
self.output.append(int((val >> 8) & 0xFF))
|
||||
self.output.append(int(val & 0xFF))
|
||||
else:
|
||||
Err.log("Attempt to write to data segment")
|
||||
|
||||
def outputdword_be(self, expr, env):
|
||||
'Outputs a big-endian dword, with range checking'
|
||||
if self.writeOK:
|
||||
val = expr.value(env)
|
||||
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
|
||||
self.output.append(int((val >> 24) & 0xFF))
|
||||
self.output.append(int((val >> 16) & 0xFF))
|
||||
@ -504,77 +669,122 @@ class Assembler(Pass):
|
||||
(opcode, expr) = node.data
|
||||
bin_op = Ops.opcodes[opcode][mode]
|
||||
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
|
||||
self.outputbyte(IR.ConstantExpr(bin_op), env)
|
||||
arglen = Ops.lengths[mode]
|
||||
if mode == 14: # Special handling for relative mode
|
||||
arg = expr.value(env)
|
||||
arg = arg-(env.getPC()+2)
|
||||
arg = arg - (env.getPC() + 2)
|
||||
if arg < -128 or arg > 127:
|
||||
Err.log("Branch target out of bounds")
|
||||
arg = 0
|
||||
if arg < 0: arg += 256
|
||||
if arg < 0:
|
||||
arg += 256
|
||||
expr = IR.ConstantExpr(arg)
|
||||
if arglen == 1: self.outputbyte(expr, env)
|
||||
if arglen == 2: self.outputword(expr, env)
|
||||
env.incPC(1+arglen)
|
||||
self.code += 1+arglen
|
||||
if arglen == 1:
|
||||
self.outputbyte(expr, env)
|
||||
if arglen == 2:
|
||||
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):
|
||||
for expr in node.data:
|
||||
self.outputbyte(expr, env)
|
||||
env.incPC(len(node.data))
|
||||
self.data += len(node.data)
|
||||
|
||||
def visitWord(self, node, env):
|
||||
for expr in node.data:
|
||||
self.outputword(expr, env)
|
||||
env.incPC(len(node.data)*2)
|
||||
self.data += len(node.data)*2
|
||||
env.incPC(len(node.data) * 2)
|
||||
self.data += len(node.data) * 2
|
||||
|
||||
def visitDword(self, node, env):
|
||||
for expr in node.data:
|
||||
self.outputdword(expr, env)
|
||||
env.incPC(len(node.data)*4)
|
||||
self.data += len(node.data)*4
|
||||
env.incPC(len(node.data) * 4)
|
||||
self.data += len(node.data) * 4
|
||||
|
||||
def visitWordBE(self, node, env):
|
||||
for expr in node.data:
|
||||
self.outputword_be(expr, env)
|
||||
env.incPC(len(node.data)*2)
|
||||
self.data += len(node.data)*2
|
||||
env.incPC(len(node.data) * 2)
|
||||
self.data += len(node.data) * 2
|
||||
|
||||
def visitDwordBE(self, node, env):
|
||||
for expr in node.data:
|
||||
self.outputdword_be(expr, env)
|
||||
env.incPC(len(node.data)*4)
|
||||
self.data += len(node.data)*4
|
||||
def visitSetPC(self, node, env):
|
||||
env.incPC(len(node.data) * 4)
|
||||
self.data += len(node.data) * 4
|
||||
|
||||
def visitSetPC(self, node, env):
|
||||
env.setPC(node.data[0].value(env))
|
||||
|
||||
def visitCheckPC(self, node, env):
|
||||
pc = env.getPC()
|
||||
target = node.data[0].value(env)
|
||||
if (pc > target):
|
||||
Err.log(".checkpc assertion failed: $%x > $%x" % (pc, target))
|
||||
def visitAdvance(self, node, env):
|
||||
|
||||
def visitAdvance(self, node, env):
|
||||
pc = env.getPC()
|
||||
target = node.data[0].value(env)
|
||||
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:
|
||||
for i in xrange(target-pc): self.outputbyte(node.data[1], env)
|
||||
self.filler += target-pc
|
||||
for i in xrange(target - pc):
|
||||
self.outputbyte(node.data[1], env)
|
||||
self.filler += target - pc
|
||||
env.setPC(target)
|
||||
|
@ -155,4 +155,4 @@ Section Uninstall
|
||||
DeleteRegKey ${PRODUCT_UNINST_ROOT_KEY} "${PRODUCT_UNINST_KEY}"
|
||||
DeleteRegKey HKLM "${PRODUCT_DIR_REGKEY}"
|
||||
SetAutoClose true
|
||||
SectionEnd
|
||||
SectionEnd
|
||||
|
@ -6,6 +6,11 @@ setup(name='Ophis',
|
||||
author="Michael Martin",
|
||||
author_email="mcmartin@gmail.com",
|
||||
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'],
|
||||
scripts=['scripts/ophis'])
|
||||
|
@ -1,9 +1,10 @@
|
||||
from distutils.core import setup
|
||||
import py2exe, sys
|
||||
import py2exe
|
||||
import sys
|
||||
|
||||
sys.argv.append('py2exe')
|
||||
|
||||
setup(options = {'py2exe': {'bundle_files': 1}},
|
||||
packages = ['Ophis'],
|
||||
zipfile = None,
|
||||
console = [{'script': "scripts/ophis"}])
|
||||
setup(options={'py2exe': {'bundle_files': 1}},
|
||||
packages=['Ophis'],
|
||||
zipfile=None,
|
||||
console=[{'script': "scripts/ophis"}])
|
||||
|
@ -51,4 +51,4 @@ late:
|
||||
jmp early
|
||||
* bne +
|
||||
jmp early
|
||||
*
|
||||
*
|
||||
|
@ -76,4 +76,4 @@
|
||||
ISB $F7, X
|
||||
ISB $FBFB, Y
|
||||
ISB $FFFF, X
|
||||
|
||||
|
||||
|
@ -25,7 +25,7 @@
|
||||
AND ($32) ; 32: AND - (Zero Page)
|
||||
BIT $34, X ; 34: BIT - Zero Page, X
|
||||
RMB3 $37 ; 37: RMB3 - Zero Page
|
||||
DEA ; 3A: DEA - Implied
|
||||
DEA ; 3A: DEA - Implied
|
||||
DEC ; 3A: DEC - Implied
|
||||
BIT $3C3C,X ; 3C: BIT - Absolute, X
|
||||
BBR3 ^+$41 ; 3F: BBR3 - Relative
|
||||
|
@ -1,157 +1,157 @@
|
||||
; Test file for base 6502 opcode compliance
|
||||
; This odd little source file uses every addressing mode
|
||||
; of every opcode, and uses the opcode itself as the argument
|
||||
; to each instruction that takes one. The resulting binary's
|
||||
; bytes are thus in strictly increasing numerical order.
|
||||
|
||||
BRK
|
||||
ORA ($01, X)
|
||||
ORA $05
|
||||
ASL $06
|
||||
PHP
|
||||
ORA #$09
|
||||
ASL
|
||||
ORA $0D0D
|
||||
ASL $0E0E
|
||||
BPL ^+$12
|
||||
ORA ($11), Y
|
||||
ORA $15, X
|
||||
ASL $16, X
|
||||
CLC
|
||||
ORA $1919, Y
|
||||
ORA $1D1D, X
|
||||
ASL $1E1E, X
|
||||
JSR $2020
|
||||
AND ($21, X)
|
||||
BIT $24
|
||||
AND $25
|
||||
ROL $26
|
||||
PLP
|
||||
AND #$29
|
||||
ROL
|
||||
BIT $2C2C
|
||||
AND $2D2D
|
||||
ROL $2E2E
|
||||
BMI ^+$32
|
||||
AND ($31), Y
|
||||
AND $35, X
|
||||
ROL $36, X
|
||||
SEC
|
||||
AND $3939, Y
|
||||
AND $3D3D, X
|
||||
ROL $3E3E, X
|
||||
RTI
|
||||
EOR ($41, X)
|
||||
EOR $45
|
||||
LSR $46
|
||||
PHA
|
||||
EOR #$49
|
||||
LSR
|
||||
JMP $4C4C
|
||||
EOR $4D4D
|
||||
LSR $4E4E
|
||||
BVC ^+$52
|
||||
EOR ($51), Y
|
||||
EOR $55, X
|
||||
LSR $56, X
|
||||
CLI
|
||||
EOR $5959, Y
|
||||
EOR $5D5D, X
|
||||
LSR $5E5E, X
|
||||
RTS
|
||||
ADC ($61, X)
|
||||
ADC $65
|
||||
ROR $66
|
||||
PLA
|
||||
ADC #$69
|
||||
ROR
|
||||
JMP ($6C6C)
|
||||
ADC $6D6D
|
||||
ROR $6E6E
|
||||
BVS ^+$72
|
||||
ADC ($71), Y
|
||||
ADC $75, X
|
||||
ROR $76, X
|
||||
SEI
|
||||
ADC $7979, Y
|
||||
ADC $7D7D, X
|
||||
ROR $7E7E, X
|
||||
STA ($81, X)
|
||||
STY $84
|
||||
STA $85
|
||||
STX $86
|
||||
DEY
|
||||
TXA
|
||||
STY $8C8C
|
||||
STA $8D8D
|
||||
STX $8E8E
|
||||
BCC ^-$6E
|
||||
STA ($91), Y
|
||||
STY $94, X
|
||||
STA $95, X
|
||||
STX $96, Y
|
||||
TYA
|
||||
STA $9999, Y
|
||||
TXS
|
||||
STA $9D9D, X
|
||||
LDY #$A0
|
||||
LDA ($A1, X)
|
||||
LDX #$A2
|
||||
LDY $A4
|
||||
LDA $A5
|
||||
LDX $A6
|
||||
TAY
|
||||
LDA #$A9
|
||||
TAX
|
||||
LDY $ACAC
|
||||
LDA $ADAD
|
||||
LDX $AEAE
|
||||
BCS ^-$4e
|
||||
LDA ($B1), Y
|
||||
LDY $B4, X
|
||||
LDA $B5, X
|
||||
LDX $B6, Y
|
||||
CLV
|
||||
LDA $B9B9,Y
|
||||
TSX
|
||||
LDY $BCBC, X
|
||||
LDA $BDBD, X
|
||||
LDX $BEBE, Y
|
||||
CPY #$C0
|
||||
CMP ($C1, X)
|
||||
CPY $C4
|
||||
CMP $C5
|
||||
DEC $C6
|
||||
INY
|
||||
CMP #$C9
|
||||
DEX
|
||||
CPY $CCCC
|
||||
CMP $CDCD
|
||||
DEC $CECE
|
||||
BNE ^-$2E
|
||||
CMP ($D1), Y
|
||||
CMP $D5, X
|
||||
DEC $D6, X
|
||||
CLD
|
||||
CMP $D9D9, Y
|
||||
CMP $DDDD, X
|
||||
DEC $DEDE, X
|
||||
CPX #$E0
|
||||
SBC ($E1, X)
|
||||
CPX $E4
|
||||
SBC $E5
|
||||
INC $E6
|
||||
INX
|
||||
SBC #$E9
|
||||
NOP
|
||||
CPX $ECEC
|
||||
SBC $EDED
|
||||
INC $EEEE
|
||||
BEQ ^-$0E
|
||||
SBC ($F1), Y
|
||||
SBC $F5, X
|
||||
INC $F6, X
|
||||
SED
|
||||
SBC $F9F9, Y
|
||||
SBC $FDFD, X
|
||||
INC $FEFE, X
|
||||
; Test file for base 6502 opcode compliance
|
||||
; This odd little source file uses every addressing mode
|
||||
; of every opcode, and uses the opcode itself as the argument
|
||||
; to each instruction that takes one. The resulting binary's
|
||||
; bytes are thus in strictly increasing numerical order.
|
||||
|
||||
BRK
|
||||
ORA ($01, X)
|
||||
ORA $05
|
||||
ASL $06
|
||||
PHP
|
||||
ORA #$09
|
||||
ASL
|
||||
ORA $0D0D
|
||||
ASL $0E0E
|
||||
BPL ^+$12
|
||||
ORA ($11), Y
|
||||
ORA $15, X
|
||||
ASL $16, X
|
||||
CLC
|
||||
ORA $1919, Y
|
||||
ORA $1D1D, X
|
||||
ASL $1E1E, X
|
||||
JSR $2020
|
||||
AND ($21, X)
|
||||
BIT $24
|
||||
AND $25
|
||||
ROL $26
|
||||
PLP
|
||||
AND #$29
|
||||
ROL
|
||||
BIT $2C2C
|
||||
AND $2D2D
|
||||
ROL $2E2E
|
||||
BMI ^+$32
|
||||
AND ($31), Y
|
||||
AND $35, X
|
||||
ROL $36, X
|
||||
SEC
|
||||
AND $3939, Y
|
||||
AND $3D3D, X
|
||||
ROL $3E3E, X
|
||||
RTI
|
||||
EOR ($41, X)
|
||||
EOR $45
|
||||
LSR $46
|
||||
PHA
|
||||
EOR #$49
|
||||
LSR
|
||||
JMP $4C4C
|
||||
EOR $4D4D
|
||||
LSR $4E4E
|
||||
BVC ^+$52
|
||||
EOR ($51), Y
|
||||
EOR $55, X
|
||||
LSR $56, X
|
||||
CLI
|
||||
EOR $5959, Y
|
||||
EOR $5D5D, X
|
||||
LSR $5E5E, X
|
||||
RTS
|
||||
ADC ($61, X)
|
||||
ADC $65
|
||||
ROR $66
|
||||
PLA
|
||||
ADC #$69
|
||||
ROR
|
||||
JMP ($6C6C)
|
||||
ADC $6D6D
|
||||
ROR $6E6E
|
||||
BVS ^+$72
|
||||
ADC ($71), Y
|
||||
ADC $75, X
|
||||
ROR $76, X
|
||||
SEI
|
||||
ADC $7979, Y
|
||||
ADC $7D7D, X
|
||||
ROR $7E7E, X
|
||||
STA ($81, X)
|
||||
STY $84
|
||||
STA $85
|
||||
STX $86
|
||||
DEY
|
||||
TXA
|
||||
STY $8C8C
|
||||
STA $8D8D
|
||||
STX $8E8E
|
||||
BCC ^-$6E
|
||||
STA ($91), Y
|
||||
STY $94, X
|
||||
STA $95, X
|
||||
STX $96, Y
|
||||
TYA
|
||||
STA $9999, Y
|
||||
TXS
|
||||
STA $9D9D, X
|
||||
LDY #$A0
|
||||
LDA ($A1, X)
|
||||
LDX #$A2
|
||||
LDY $A4
|
||||
LDA $A5
|
||||
LDX $A6
|
||||
TAY
|
||||
LDA #$A9
|
||||
TAX
|
||||
LDY $ACAC
|
||||
LDA $ADAD
|
||||
LDX $AEAE
|
||||
BCS ^-$4e
|
||||
LDA ($B1), Y
|
||||
LDY $B4, X
|
||||
LDA $B5, X
|
||||
LDX $B6, Y
|
||||
CLV
|
||||
LDA $B9B9,Y
|
||||
TSX
|
||||
LDY $BCBC, X
|
||||
LDA $BDBD, X
|
||||
LDX $BEBE, Y
|
||||
CPY #$C0
|
||||
CMP ($C1, X)
|
||||
CPY $C4
|
||||
CMP $C5
|
||||
DEC $C6
|
||||
INY
|
||||
CMP #$C9
|
||||
DEX
|
||||
CPY $CCCC
|
||||
CMP $CDCD
|
||||
DEC $CECE
|
||||
BNE ^-$2E
|
||||
CMP ($D1), Y
|
||||
CMP $D5, X
|
||||
DEC $D6, X
|
||||
CLD
|
||||
CMP $D9D9, Y
|
||||
CMP $DDDD, X
|
||||
DEC $DEDE, X
|
||||
CPX #$E0
|
||||
SBC ($E1, X)
|
||||
CPX $E4
|
||||
SBC $E5
|
||||
INC $E6
|
||||
INX
|
||||
SBC #$E9
|
||||
NOP
|
||||
CPX $ECEC
|
||||
SBC $EDED
|
||||
INC $EEEE
|
||||
BEQ ^-$0E
|
||||
SBC ($F1), Y
|
||||
SBC $F5, X
|
||||
INC $F6, X
|
||||
SED
|
||||
SBC $F9F9, Y
|
||||
SBC $FDFD, X
|
||||
INC $FEFE, X
|
||||
|
@ -10,11 +10,13 @@ normmap = ''.join([bits[x] for x in norm])
|
||||
ivrsmap = ''.join([bits[x] for x in ivrs])
|
||||
blnkmap = ''.join([bits[x] for x in blnk])
|
||||
|
||||
|
||||
def dumpfile(n, m):
|
||||
f = file(n, 'wb')
|
||||
f.write(m)
|
||||
f.close()
|
||||
|
||||
|
||||
dumpfile('a2normal.map', normmap)
|
||||
dumpfile('a2inverse.map', ivrsmap)
|
||||
dumpfile('a2blink.map', blnkmap)
|
||||
|
@ -3,7 +3,7 @@ import sys
|
||||
|
||||
verbose = 0
|
||||
|
||||
prologue = '"""' +"""Opcodes file.
|
||||
prologue = '"""' + """Opcodes file.
|
||||
|
||||
Tables for the assembly of 6502-family instructions, mapping
|
||||
opcodes and addressing modes to binary instructions.""" + '"""' + """
|
||||
@ -17,37 +17,38 @@ prologue = '"""' +"""Opcodes file.
|
||||
# the tables in tools/opcodes. Edit those tables, not these.
|
||||
|
||||
# Names of addressing modes
|
||||
modes = ["Implied", # 0
|
||||
"Immediate", # 1
|
||||
"Zero Page", # 2
|
||||
"Zero Page, X", # 3
|
||||
"Zero Page, Y", # 4
|
||||
"Absolute", # 5
|
||||
"Absolute, X", # 6
|
||||
"Absolute, Y", # 7
|
||||
"(Absolute)", # 8
|
||||
"(Absolute, X)", # 9
|
||||
modes = ["Implied", # 0
|
||||
"Immediate", # 1
|
||||
"Zero Page", # 2
|
||||
"Zero Page, X", # 3
|
||||
"Zero Page, Y", # 4
|
||||
"Absolute", # 5
|
||||
"Absolute, X", # 6
|
||||
"Absolute, Y", # 7
|
||||
"(Absolute)", # 8
|
||||
"(Absolute, X)", # 9
|
||||
"(Absolute), Y", # 10
|
||||
"(Zero Page)", # 11
|
||||
"(Zero Page, X)", # 12
|
||||
"(Zero Page), Y", # 13
|
||||
"Relative"] # 14
|
||||
|
||||
|
||||
# Lengths of the argument
|
||||
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.
|
||||
modes = ["Implied", # 0
|
||||
"Immediate", # 1
|
||||
"Zero Page", # 2
|
||||
"Zero Page, X", # 3
|
||||
"Zero Page, Y", # 4
|
||||
"Absolute", # 5
|
||||
"Absolute, X", # 6
|
||||
"Absolute, Y", # 7
|
||||
"(Absolute)", # 8
|
||||
"(Absolute, X)", # 9
|
||||
modes = ["Implied", # 0
|
||||
"Immediate", # 1
|
||||
"Zero Page", # 2
|
||||
"Zero Page, X", # 3
|
||||
"Zero Page, Y", # 4
|
||||
"Absolute", # 5
|
||||
"Absolute, X", # 6
|
||||
"Absolute, Y", # 7
|
||||
"(Absolute)", # 8
|
||||
"(Absolute, X)", # 9
|
||||
"(Absolute), Y", # 10
|
||||
"(Zero Page)", # 11
|
||||
"(Zero Page, X)", # 12
|
||||
@ -56,24 +57,28 @@ modes = ["Implied", # 0
|
||||
|
||||
flatmodes = [x.lower() for x in modes]
|
||||
|
||||
|
||||
# WARNING: This decommenter assumes that # never appears anywhere else
|
||||
# in a line.
|
||||
def decomment (l):
|
||||
def decomment(l):
|
||||
if '#' in l:
|
||||
l = l[:l.index('#')]
|
||||
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
|
||||
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:
|
||||
if len(l) == 2:
|
||||
try:
|
||||
op = int (l[0], 16)
|
||||
op = int(l[0], 16)
|
||||
syns = l[1].split(';')
|
||||
for s in syns:
|
||||
s_p = s.split('-')
|
||||
@ -81,19 +86,20 @@ def parse_chipset_file (fname):
|
||||
mnem = s_p[0].lower().strip()
|
||||
mode = s_p[1].lower().strip()
|
||||
if mode in flatmodes:
|
||||
if result[op] == None:
|
||||
if result[op] is None:
|
||||
result[op] = []
|
||||
result[op].append((mnem, flatmodes.index(mode)))
|
||||
else:
|
||||
print "Unknown mode '%s'" % s_p[1]
|
||||
except ValueError:
|
||||
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 = {}
|
||||
for (opcode, insts) in zip (range(256), cs_list):
|
||||
if insts != None:
|
||||
for (opcode, insts) in zip(range(256), cs_list):
|
||||
if insts is not None:
|
||||
for inst in insts:
|
||||
(mnem, mode) = inst
|
||||
if mnem not in result:
|
||||
@ -115,19 +121,26 @@ def collate_chipset_map (cs_list, base):
|
||||
del result[x]
|
||||
return result
|
||||
|
||||
|
||||
def mapval(x):
|
||||
if x is None:
|
||||
return "None"
|
||||
else:
|
||||
return "0x%02X" % x
|
||||
|
||||
def dump_map (m, prologue = ''):
|
||||
|
||||
def dump_map(m, prologue=''):
|
||||
mnems = m.keys()
|
||||
mnems.sort()
|
||||
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:
|
||||
chipsets = argv[1:]
|
||||
else:
|
||||
@ -135,7 +148,8 @@ if __name__=='__main__':
|
||||
archs = []
|
||||
for x in chipsets:
|
||||
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:
|
||||
if len(l) != 2:
|
||||
print "Could not parse the chipset line '%s'" % ":".join(l)
|
||||
@ -147,10 +161,9 @@ if __name__=='__main__':
|
||||
baseset = None
|
||||
for (field, fname) in archs:
|
||||
chipset_list = parse_chipset_file(fname)
|
||||
instruction_map = collate_chipset_map (chipset_list, baseset)
|
||||
if baseset == None:
|
||||
instruction_map = collate_chipset_map(chipset_list, baseset)
|
||||
if baseset is None:
|
||||
baseset = instruction_map
|
||||
print "%s = {" % field
|
||||
dump_map (instruction_map, ' ' * (len(field) + 4))
|
||||
dump_map(instruction_map, ' ' * (len(field) + 4))
|
||||
print "%s}" % (' ' * (len(field) + 3))
|
||||
print ""
|
||||
|
@ -1,256 +1,256 @@
|
||||
00: BRK - Implied
|
||||
01: ORA - (Zero Page, X)
|
||||
02:
|
||||
03:
|
||||
04:
|
||||
02:
|
||||
03:
|
||||
04:
|
||||
05: ORA - Zero Page
|
||||
06: ASL - Zero Page
|
||||
07:
|
||||
07:
|
||||
08: PHP - Implied
|
||||
09: ORA - Immediate
|
||||
0A: ASL - Implied
|
||||
0B:
|
||||
0C:
|
||||
0B:
|
||||
0C:
|
||||
0D: ORA - Absolute
|
||||
0E: ASL - Absolute
|
||||
0F:
|
||||
0F:
|
||||
10: BPL - Relative
|
||||
11: ORA - (Zero Page), Y
|
||||
12:
|
||||
13:
|
||||
14:
|
||||
12:
|
||||
13:
|
||||
14:
|
||||
15: ORA - Zero Page, X
|
||||
16: ASL - Zero Page, X
|
||||
17:
|
||||
17:
|
||||
18: CLC - Implied
|
||||
19: ORA - Absolute, Y
|
||||
1A:
|
||||
1B:
|
||||
1C:
|
||||
1A:
|
||||
1B:
|
||||
1C:
|
||||
1D: ORA - Absolute, X
|
||||
1E: ASL - Absolute, X
|
||||
1F:
|
||||
1F:
|
||||
20: JSR - Absolute
|
||||
21: AND - (Zero Page, X)
|
||||
22:
|
||||
23:
|
||||
22:
|
||||
23:
|
||||
24: BIT - Zero Page
|
||||
25: AND - Zero Page
|
||||
26: ROL - Zero Page
|
||||
27:
|
||||
27:
|
||||
28: PLP - Implied
|
||||
29: AND - Immediate
|
||||
2A: ROL - Implied
|
||||
2B:
|
||||
2B:
|
||||
2C: BIT - Absolute
|
||||
2D: AND - Absolute
|
||||
2E: ROL - Absolute
|
||||
2F:
|
||||
2F:
|
||||
30: BMI - Relative
|
||||
31: AND - (Zero Page), Y
|
||||
32:
|
||||
33:
|
||||
34:
|
||||
32:
|
||||
33:
|
||||
34:
|
||||
35: AND - Zero Page, X
|
||||
36: ROL - Zero Page, X
|
||||
37:
|
||||
37:
|
||||
38: SEC - Implied
|
||||
39: AND - Absolute, Y
|
||||
3A:
|
||||
3B:
|
||||
3C:
|
||||
3A:
|
||||
3B:
|
||||
3C:
|
||||
3D: AND - Absolute, X
|
||||
3E: ROL - Absolute, X
|
||||
3F:
|
||||
3F:
|
||||
40: RTI - Implied
|
||||
41: EOR - (Zero Page, X)
|
||||
42:
|
||||
43:
|
||||
44:
|
||||
42:
|
||||
43:
|
||||
44:
|
||||
45: EOR - Zero Page
|
||||
46: LSR - Zero Page
|
||||
47:
|
||||
47:
|
||||
48: PHA - Implied
|
||||
49: EOR - Immediate
|
||||
4A: LSR - Implied
|
||||
4B:
|
||||
4B:
|
||||
4C: JMP - Absolute
|
||||
4D: EOR - Absolute
|
||||
4E: LSR - Absolute
|
||||
4F:
|
||||
4F:
|
||||
50: BVC - Relative
|
||||
51: EOR - (Zero Page), Y
|
||||
52:
|
||||
53:
|
||||
54:
|
||||
52:
|
||||
53:
|
||||
54:
|
||||
55: EOR - Zero Page, X
|
||||
56: LSR - Zero Page, X
|
||||
57:
|
||||
57:
|
||||
58: CLI - Implied
|
||||
59: EOR - Absolute, Y
|
||||
5A:
|
||||
5B:
|
||||
5C:
|
||||
5A:
|
||||
5B:
|
||||
5C:
|
||||
5D: EOR - Absolute, X
|
||||
5E: LSR - Absolute, X
|
||||
5F:
|
||||
5F:
|
||||
60: RTS - Implied
|
||||
61: ADC - (Zero Page, X)
|
||||
62:
|
||||
63:
|
||||
64:
|
||||
62:
|
||||
63:
|
||||
64:
|
||||
65: ADC - Zero Page
|
||||
66: ROR - Zero Page
|
||||
67:
|
||||
67:
|
||||
68: PLA - Implied
|
||||
69: ADC - Immediate
|
||||
6A: ROR - Implied
|
||||
6B:
|
||||
6B:
|
||||
6C: JMP - (Absolute)
|
||||
6D: ADC - Absolute
|
||||
6E: ROR - Absolute
|
||||
6F:
|
||||
6F:
|
||||
70: BVS - Relative
|
||||
71: ADC - (Zero Page), Y
|
||||
72:
|
||||
73:
|
||||
74:
|
||||
72:
|
||||
73:
|
||||
74:
|
||||
75: ADC - Zero Page, X
|
||||
76: ROR - Zero Page, X
|
||||
77:
|
||||
77:
|
||||
78: SEI - Implied
|
||||
79: ADC - Absolute, Y
|
||||
7A:
|
||||
7B:
|
||||
7C:
|
||||
7A:
|
||||
7B:
|
||||
7C:
|
||||
7D: ADC - Absolute, X
|
||||
7E: ROR - Absolute, X
|
||||
7F:
|
||||
80:
|
||||
7F:
|
||||
80:
|
||||
81: STA - (Zero Page, X)
|
||||
82:
|
||||
83:
|
||||
82:
|
||||
83:
|
||||
84: STY - Zero Page
|
||||
85: STA - Zero Page
|
||||
86: STX - Zero Page
|
||||
87:
|
||||
87:
|
||||
88: DEY - Implied
|
||||
89:
|
||||
89:
|
||||
8A: TXA - Implied
|
||||
8B:
|
||||
8B:
|
||||
8C: STY - Absolute
|
||||
8D: STA - Absolute
|
||||
8E: STX - Absolute
|
||||
8F:
|
||||
8F:
|
||||
90: BCC - Relative
|
||||
91: STA - (Zero Page), Y
|
||||
92:
|
||||
93:
|
||||
92:
|
||||
93:
|
||||
94: STY - Zero Page, X
|
||||
95: STA - Zero Page, X
|
||||
96: STX - Zero Page, Y
|
||||
97:
|
||||
97:
|
||||
98: TYA - Implied
|
||||
99: STA - Absolute, Y
|
||||
9A: TXS - Implied
|
||||
9B:
|
||||
9C:
|
||||
9B:
|
||||
9C:
|
||||
9D: STA - Absolute, X
|
||||
9E:
|
||||
9F:
|
||||
9E:
|
||||
9F:
|
||||
A0: LDY - Immediate
|
||||
A1: LDA - (Zero Page, X)
|
||||
A2: LDX - Immediate
|
||||
A3:
|
||||
A3:
|
||||
A4: LDY - Zero Page
|
||||
A5: LDA - Zero Page
|
||||
A6: LDX - Zero Page
|
||||
A7:
|
||||
A7:
|
||||
A8: TAY - Implied
|
||||
A9: LDA - Immediate
|
||||
AA: TAX - Implied
|
||||
AB:
|
||||
AB:
|
||||
AC: LDY - Absolute
|
||||
AD: LDA - Absolute
|
||||
AE: LDX - Absolute
|
||||
AF:
|
||||
AF:
|
||||
B0: BCS - Relative
|
||||
B1: LDA - (Zero Page), Y
|
||||
B2:
|
||||
B3:
|
||||
B2:
|
||||
B3:
|
||||
B4: LDY - Zero Page, X
|
||||
B5: LDA - Zero Page, X
|
||||
B6: LDX - Zero Page, Y
|
||||
B7:
|
||||
B7:
|
||||
B8: CLV - Implied
|
||||
B9: LDA - Absolute, Y
|
||||
BA: TSX - Implied
|
||||
BB:
|
||||
BB:
|
||||
BC: LDY - Absolute, X
|
||||
BD: LDA - Absolute, X
|
||||
BE: LDX - Absolute, Y
|
||||
BF:
|
||||
BF:
|
||||
C0: CPY - Immediate
|
||||
C1: CMP - (Zero Page, X)
|
||||
C2:
|
||||
C3:
|
||||
C2:
|
||||
C3:
|
||||
C4: CPY - Zero Page
|
||||
C5: CMP - Zero Page
|
||||
C6: DEC - Zero Page
|
||||
C7:
|
||||
C7:
|
||||
C8: INY - Implied
|
||||
C9: CMP - Immediate
|
||||
CA: DEX - Implied
|
||||
CB:
|
||||
CB:
|
||||
CC: CPY - Absolute
|
||||
CD: CMP - Absolute
|
||||
CE: DEC - Absolute
|
||||
CF:
|
||||
CF:
|
||||
D0: BNE - Relative
|
||||
D1: CMP - (Zero Page), Y
|
||||
D2:
|
||||
D3:
|
||||
D4:
|
||||
D2:
|
||||
D3:
|
||||
D4:
|
||||
D5: CMP - Zero Page, X
|
||||
D6: DEC - Zero Page, X
|
||||
D7:
|
||||
D7:
|
||||
D8: CLD - Implied
|
||||
D9: CMP - Absolute, Y
|
||||
DA:
|
||||
DB:
|
||||
DC:
|
||||
DA:
|
||||
DB:
|
||||
DC:
|
||||
DD: CMP - Absolute, X
|
||||
DE: DEC - Absolute, X
|
||||
DF:
|
||||
DF:
|
||||
E0: CPX - Immediate
|
||||
E1: SBC - (Zero Page, X)
|
||||
E2:
|
||||
E3:
|
||||
E2:
|
||||
E3:
|
||||
E4: CPX - Zero Page
|
||||
E5: SBC - Zero Page
|
||||
E6: INC - Zero Page
|
||||
E7:
|
||||
E7:
|
||||
E8: INX - Implied
|
||||
E9: SBC - Immediate
|
||||
EA: NOP - Implied
|
||||
EB:
|
||||
EB:
|
||||
EC: CPX - Absolute
|
||||
ED: SBC - Absolute
|
||||
EE: INC - Absolute
|
||||
EF:
|
||||
EF:
|
||||
F0: BEQ - Relative
|
||||
F1: SBC - (Zero Page), Y
|
||||
F2:
|
||||
F3:
|
||||
F4:
|
||||
F2:
|
||||
F3:
|
||||
F4:
|
||||
F5: SBC - Zero Page, X
|
||||
F6: INC - Zero Page, X
|
||||
F7:
|
||||
F7:
|
||||
F8: SED - Implied
|
||||
F9: SBC - Absolute, Y
|
||||
FA:
|
||||
FB:
|
||||
FC:
|
||||
FA:
|
||||
FB:
|
||||
FC:
|
||||
FD: SBC - Absolute, X
|
||||
FE: INC - Absolute, X
|
||||
FF:
|
||||
FF:
|
||||
|
@ -1,8 +1,8 @@
|
||||
00: BRK - Implied
|
||||
01: ORA - (Zero Page, X)
|
||||
02:
|
||||
02:
|
||||
03: SLO - (Zero Page, X)
|
||||
04: NOP - Zero Page
|
||||
04: NOP - Zero Page
|
||||
05: ORA - Zero Page
|
||||
06: ASL - Zero Page
|
||||
07: SLO - Zero Page
|
||||
@ -10,29 +10,29 @@
|
||||
09: ORA - Immediate
|
||||
0A: ASL - Implied
|
||||
0B: ANC - Immediate
|
||||
0C:
|
||||
0C:
|
||||
0D: ORA - Absolute
|
||||
0E: ASL - Absolute
|
||||
0F: SLO - Absolute
|
||||
10: BPL - Relative
|
||||
11: ORA - (Zero Page), Y
|
||||
12:
|
||||
12:
|
||||
13: SLO - (Zero Page), Y
|
||||
14:
|
||||
14:
|
||||
15: ORA - Zero Page, X
|
||||
16: ASL - Zero Page, X
|
||||
17: SLO - Zero Page, X
|
||||
18: CLC - Implied
|
||||
19: ORA - Absolute, Y
|
||||
1A:
|
||||
1A:
|
||||
1B: SLO - Absolute, Y
|
||||
1C:
|
||||
1C:
|
||||
1D: ORA - Absolute, X
|
||||
1E: ASL - Absolute, X
|
||||
1F: SLO - Absolute, X
|
||||
20: JSR - Absolute
|
||||
21: AND - (Zero Page, X)
|
||||
22:
|
||||
22:
|
||||
23: RLA - (Zero Page, X)
|
||||
24: BIT - Zero Page
|
||||
25: AND - Zero Page
|
||||
@ -41,32 +41,32 @@
|
||||
28: PLP - Implied
|
||||
29: AND - Immediate
|
||||
2A: ROL - Implied
|
||||
2B:
|
||||
2B:
|
||||
2C: BIT - Absolute
|
||||
2D: AND - Absolute
|
||||
2E: ROL - Absolute
|
||||
2F: RLA - Absolute
|
||||
30: BMI - Relative
|
||||
31: AND - (Zero Page), Y
|
||||
32:
|
||||
32:
|
||||
33: RLA - (Zero Page), Y
|
||||
34:
|
||||
34:
|
||||
35: AND - Zero Page, X
|
||||
36: ROL - Zero Page, X
|
||||
37: RLA - Zero Page, X
|
||||
38: SEC - Implied
|
||||
39: AND - Absolute, Y
|
||||
3A:
|
||||
3A:
|
||||
3B: RLA - Absolute, Y
|
||||
3C:
|
||||
3C:
|
||||
3D: AND - Absolute, X
|
||||
3E: ROL - Absolute, X
|
||||
3F: RLA - Absolute, X
|
||||
40: RTI - Implied
|
||||
41: EOR - (Zero Page, X)
|
||||
42:
|
||||
42:
|
||||
43: SRE - (Zero Page, X)
|
||||
44:
|
||||
44:
|
||||
45: EOR - Zero Page
|
||||
46: LSR - Zero Page
|
||||
47: SRE - Zero Page
|
||||
@ -80,25 +80,25 @@
|
||||
4F: SRE - Absolute
|
||||
50: BVC - Relative
|
||||
51: EOR - (Zero Page), Y
|
||||
52:
|
||||
52:
|
||||
53: SRE - (Zero Page), Y
|
||||
54:
|
||||
54:
|
||||
55: EOR - Zero Page, X
|
||||
56: LSR - Zero Page, X
|
||||
57: SRE - Zero Page, X
|
||||
58: CLI - Implied
|
||||
59: EOR - Absolute, Y
|
||||
5A:
|
||||
5A:
|
||||
5B: SRE - Absolute, Y
|
||||
5C:
|
||||
5C:
|
||||
5D: EOR - Absolute, X
|
||||
5E: LSR - Absolute, X
|
||||
5F: SRE - Absolute, X
|
||||
60: RTS - Implied
|
||||
61: ADC - (Zero Page, X)
|
||||
62:
|
||||
62:
|
||||
63: RRA - (Zero Page, X)
|
||||
64:
|
||||
64:
|
||||
65: ADC - Zero Page
|
||||
66: ROR - Zero Page
|
||||
67: RRA - Zero Page
|
||||
@ -112,30 +112,30 @@
|
||||
6F: RRA - Absolute
|
||||
70: BVS - Relative
|
||||
71: ADC - (Zero Page), Y
|
||||
72:
|
||||
72:
|
||||
73: RRA - (Zero Page), Y
|
||||
74:
|
||||
74:
|
||||
75: ADC - Zero Page, X
|
||||
76: ROR - Zero Page, X
|
||||
77: RRA - Zero Page, X
|
||||
78: SEI - Implied
|
||||
79: ADC - Absolute, Y
|
||||
7A:
|
||||
7A:
|
||||
7B: RRA - Absolute, Y
|
||||
7C:
|
||||
7C:
|
||||
7D: ADC - Absolute, X
|
||||
7E: ROR - Absolute, X
|
||||
7F: RRA - Absolute, X
|
||||
80:
|
||||
80:
|
||||
81: STA - (Zero Page, X)
|
||||
82:
|
||||
82:
|
||||
83: SAX - (Zero Page, X)
|
||||
84: STY - Zero Page
|
||||
85: STA - Zero Page
|
||||
86: STX - Zero Page
|
||||
87: SAX - Zero Page
|
||||
88: DEY - Implied
|
||||
89:
|
||||
89:
|
||||
8A: TXA - Implied
|
||||
8B: ANE - Immediate
|
||||
8C: STY - Absolute
|
||||
@ -144,7 +144,7 @@
|
||||
8F: SAX - Absolute
|
||||
90: BCC - Relative
|
||||
91: STA - (Zero Page), Y
|
||||
92:
|
||||
92:
|
||||
93: SHA - (Zero Page), Y
|
||||
94: STY - Zero Page, X
|
||||
95: STA - Zero Page, X
|
||||
@ -154,7 +154,7 @@
|
||||
99: STA - Absolute, Y
|
||||
9A: TXS - Implied
|
||||
9B: SHS - Absolute, Y
|
||||
9C:
|
||||
9C:
|
||||
9D: STA - Absolute, X
|
||||
9E: SHX - Absolute, Y
|
||||
9F: SHA - Absolute, Y
|
||||
@ -176,7 +176,7 @@
|
||||
AF: LAX - Absolute
|
||||
B0: BCS - Relative
|
||||
B1: LDA - (Zero Page), Y
|
||||
B2:
|
||||
B2:
|
||||
B3: LAX - (Zero Page), Y
|
||||
B4: LDY - Zero Page, X
|
||||
B5: LDA - Zero Page, X
|
||||
@ -192,7 +192,7 @@
|
||||
BF: LAX - Absolute, Y
|
||||
C0: CPY - Immediate
|
||||
C1: CMP - (Zero Page, X)
|
||||
C2:
|
||||
C2:
|
||||
C3: DCP - (Zero Page, X)
|
||||
C4: CPY - Zero Page
|
||||
C5: CMP - Zero Page
|
||||
@ -208,23 +208,23 @@
|
||||
CF: DCP - Absolute
|
||||
D0: BNE - Relative
|
||||
D1: CMP - (Zero Page), Y
|
||||
D2:
|
||||
D2:
|
||||
D3: DCP - (Zero Page), Y
|
||||
D4:
|
||||
D4:
|
||||
D5: CMP - Zero Page, X
|
||||
D6: DEC - Zero Page, X
|
||||
D7: DCP - Zero Page, X
|
||||
D8: CLD - Implied
|
||||
D9: CMP - Absolute, Y
|
||||
DA:
|
||||
DA:
|
||||
DB: DCP - Absolute, Y
|
||||
DC:
|
||||
DC:
|
||||
DD: CMP - Absolute, X
|
||||
DE: DEC - Absolute, X
|
||||
DF: DCP - Absolute, X
|
||||
E0: CPX - Immediate
|
||||
E1: SBC - (Zero Page, X)
|
||||
E2:
|
||||
E2:
|
||||
E3: ISB - (Zero Page, X)
|
||||
E4: CPX - Zero Page
|
||||
E5: SBC - Zero Page
|
||||
@ -233,24 +233,24 @@
|
||||
E8: INX - Implied
|
||||
E9: SBC - Immediate
|
||||
EA: NOP - Implied
|
||||
EB:
|
||||
EB:
|
||||
EC: CPX - Absolute
|
||||
ED: SBC - Absolute
|
||||
EE: INC - Absolute
|
||||
EF: ISB - Absolute
|
||||
F0: BEQ - Relative
|
||||
F1: SBC - (Zero Page), Y
|
||||
F2:
|
||||
F2:
|
||||
F3: ISB - (Zero Page), Y
|
||||
F4:
|
||||
F4:
|
||||
F5: SBC - Zero Page, X
|
||||
F6: INC - Zero Page, X
|
||||
F7: ISB - Zero Page, X
|
||||
F8: SED - Implied
|
||||
F9: SBC - Absolute, Y
|
||||
FA:
|
||||
FA:
|
||||
FB: ISB - Absolute, Y
|
||||
FC:
|
||||
FC:
|
||||
FD: SBC - Absolute, X
|
||||
FE: INC - Absolute, X
|
||||
FF: ISB - Absolute, X
|
||||
|
@ -1,7 +1,7 @@
|
||||
00: BRK - Implied
|
||||
01: ORA - (Zero Page, X)
|
||||
02:
|
||||
03:
|
||||
02:
|
||||
03:
|
||||
04: TSB - Zero Page
|
||||
05: ORA - Zero Page
|
||||
06: ASL - Zero Page
|
||||
@ -9,7 +9,7 @@
|
||||
08: PHP - Implied
|
||||
09: ORA - Immediate
|
||||
0A: ASL - Implied
|
||||
0B:
|
||||
0B:
|
||||
0C: TSB - Absolute
|
||||
0D: ORA - Absolute
|
||||
0E: ASL - Absolute
|
||||
@ -17,7 +17,7 @@
|
||||
10: BPL - Relative
|
||||
11: ORA - (Zero Page), Y
|
||||
12: ORA - (Zero Page)
|
||||
13:
|
||||
13:
|
||||
14: TRB - Zero Page
|
||||
15: ORA - Zero Page, X
|
||||
16: ASL - Zero Page, X
|
||||
@ -25,15 +25,15 @@
|
||||
18: CLC - Implied
|
||||
19: ORA - Absolute, Y
|
||||
1A: INA - Implied; INC - Implied
|
||||
1B:
|
||||
1B:
|
||||
1C: TRB - Absolute
|
||||
1D: ORA - Absolute, X
|
||||
1E: ASL - Absolute, X
|
||||
1F: BBR1 - Relative
|
||||
20: JSR - Absolute
|
||||
21: AND - (Zero Page, X)
|
||||
22:
|
||||
23:
|
||||
22:
|
||||
23:
|
||||
24: BIT - Zero Page
|
||||
25: AND - Zero Page
|
||||
26: ROL - Zero Page
|
||||
@ -41,7 +41,7 @@
|
||||
28: PLP - Implied
|
||||
29: AND - Immediate
|
||||
2A: ROL - Implied
|
||||
2B:
|
||||
2B:
|
||||
2C: BIT - Absolute
|
||||
2D: AND - Absolute
|
||||
2E: ROL - Absolute
|
||||
@ -49,7 +49,7 @@
|
||||
30: BMI - Relative
|
||||
31: AND - (Zero Page), Y
|
||||
32: AND - (Zero Page)
|
||||
33:
|
||||
33:
|
||||
34: BIT - Zero Page, X
|
||||
35: AND - Zero Page, X
|
||||
36: ROL - Zero Page, X
|
||||
@ -57,23 +57,23 @@
|
||||
38: SEC - Implied
|
||||
39: AND - Absolute, Y
|
||||
3A: DEA - Implied; DEC - Implied
|
||||
3B:
|
||||
3B:
|
||||
3C: BIT - Absolute, X
|
||||
3D: AND - Absolute, X
|
||||
3E: ROL - Absolute, X
|
||||
3F: BBR3 - Relative
|
||||
40: RTI - Implied
|
||||
41: EOR - (Zero Page, X)
|
||||
42:
|
||||
43:
|
||||
44:
|
||||
42:
|
||||
43:
|
||||
44:
|
||||
45: EOR - Zero Page
|
||||
46: LSR - Zero Page
|
||||
47: RMB4 - Zero Page
|
||||
48: PHA - Implied
|
||||
49: EOR - Immediate
|
||||
4A: LSR - Implied
|
||||
4B:
|
||||
4B:
|
||||
4C: JMP - Absolute
|
||||
4D: EOR - Absolute
|
||||
4E: LSR - Absolute
|
||||
@ -81,23 +81,23 @@
|
||||
50: BVC - Relative
|
||||
51: EOR - (Zero Page), Y
|
||||
52: EOR - (Zero Page)
|
||||
53:
|
||||
54:
|
||||
53:
|
||||
54:
|
||||
55: EOR - Zero Page, X
|
||||
56: LSR - Zero Page, X
|
||||
57: RMB5 - Zero Page
|
||||
58: CLI - Implied
|
||||
59: EOR - Absolute, Y
|
||||
5A: PHY - Implied
|
||||
5B:
|
||||
5C:
|
||||
5B:
|
||||
5C:
|
||||
5D: EOR - Absolute, X
|
||||
5E: LSR - Absolute, X
|
||||
5F: BBR5 - Relative
|
||||
60: RTS - Implied
|
||||
61: ADC - (Zero Page, X)
|
||||
62:
|
||||
63:
|
||||
62:
|
||||
63:
|
||||
64: STZ - Zero Page
|
||||
65: ADC - Zero Page
|
||||
66: ROR - Zero Page
|
||||
@ -105,7 +105,7 @@
|
||||
68: PLA - Implied
|
||||
69: ADC - Immediate
|
||||
6A: ROR - Implied
|
||||
6B:
|
||||
6B:
|
||||
6C: JMP - (Absolute)
|
||||
6D: ADC - Absolute
|
||||
6E: ROR - Absolute
|
||||
@ -113,7 +113,7 @@
|
||||
70: BVS - Relative
|
||||
71: ADC - (Zero Page), Y
|
||||
72: ADC - (Zero Page)
|
||||
73:
|
||||
73:
|
||||
74: STZ - Zero Page, X
|
||||
75: ADC - Zero Page, X
|
||||
76: ROR - Zero Page, X
|
||||
@ -121,15 +121,15 @@
|
||||
78: SEI - Implied
|
||||
79: ADC - Absolute, Y
|
||||
7A: PLY - Implied
|
||||
7B:
|
||||
7B:
|
||||
7C: JMP - (Absolute, X)
|
||||
7D: ADC - Absolute, X
|
||||
7E: ROR - Absolute, X
|
||||
7F: BBR7 - Relative
|
||||
80: BRA - Relative
|
||||
81: STA - (Zero Page, X)
|
||||
82:
|
||||
83:
|
||||
82:
|
||||
83:
|
||||
84: STY - Zero Page
|
||||
85: STA - Zero Page
|
||||
86: STX - Zero Page
|
||||
@ -137,7 +137,7 @@
|
||||
88: DEY - Implied
|
||||
89: BIT - Immediate
|
||||
8A: TXA - Implied
|
||||
8B:
|
||||
8B:
|
||||
8C: STY - Absolute
|
||||
8D: STA - Absolute
|
||||
8E: STX - Absolute
|
||||
@ -145,7 +145,7 @@
|
||||
90: BCC - Relative
|
||||
91: STA - (Zero Page), Y
|
||||
92: STA - (Zero Page)
|
||||
93:
|
||||
93:
|
||||
94: STY - Zero Page, X
|
||||
95: STA - Zero Page, X
|
||||
96: STX - Zero Page, Y
|
||||
@ -153,7 +153,7 @@
|
||||
98: TYA - Implied
|
||||
99: STA - Absolute, Y
|
||||
9A: TXS - Implied
|
||||
9B:
|
||||
9B:
|
||||
9C: STZ - Absolute
|
||||
9D: STA - Absolute, X
|
||||
9E: STZ - Absolute, X
|
||||
@ -161,7 +161,7 @@
|
||||
A0: LDY - Immediate
|
||||
A1: LDA - (Zero Page, X)
|
||||
A2: LDX - Immediate
|
||||
A3:
|
||||
A3:
|
||||
A4: LDY - Zero Page
|
||||
A5: LDA - Zero Page
|
||||
A6: LDX - Zero Page
|
||||
@ -169,7 +169,7 @@
|
||||
A8: TAY - Implied
|
||||
A9: LDA - Immediate
|
||||
AA: TAX - Implied
|
||||
AB:
|
||||
AB:
|
||||
AC: LDY - Absolute
|
||||
AD: LDA - Absolute
|
||||
AE: LDX - Absolute
|
||||
@ -177,7 +177,7 @@
|
||||
B0: BCS - Relative
|
||||
B1: LDA - (Zero Page), Y
|
||||
B2: LDA - (Zero Page)
|
||||
B3:
|
||||
B3:
|
||||
B4: LDY - Zero Page, X
|
||||
B5: LDA - Zero Page, X
|
||||
B6: LDX - Zero Page, Y
|
||||
@ -185,15 +185,15 @@
|
||||
B8: CLV - Implied
|
||||
B9: LDA - Absolute, Y
|
||||
BA: TSX - Implied
|
||||
BB:
|
||||
BB:
|
||||
BC: LDY - Absolute, X
|
||||
BD: LDA - Absolute, X
|
||||
BE: LDX - Absolute, Y
|
||||
BF: BBS3 - Relative
|
||||
C0: CPY - Immediate
|
||||
C1: CMP - (Zero Page, X)
|
||||
C2:
|
||||
C3:
|
||||
C2:
|
||||
C3:
|
||||
C4: CPY - Zero Page
|
||||
C5: CMP - Zero Page
|
||||
C6: DEC - Zero Page
|
||||
@ -209,8 +209,8 @@
|
||||
D0: BNE - Relative
|
||||
D1: CMP - (Zero Page), Y
|
||||
D2: CMP - (Zero Page)
|
||||
D3:
|
||||
D4:
|
||||
D3:
|
||||
D4:
|
||||
D5: CMP - Zero Page, X
|
||||
D6: DEC - Zero Page, X
|
||||
D7: SMB5 - Zero Page
|
||||
@ -218,14 +218,14 @@
|
||||
D9: CMP - Absolute, Y
|
||||
DA: PHX - Implied
|
||||
DB: STP - Implied
|
||||
DC:
|
||||
DC:
|
||||
DD: CMP - Absolute, X
|
||||
DE: DEC - Absolute, X
|
||||
DF: BBS5 - Relative
|
||||
E0: CPX - Immediate
|
||||
E1: SBC - (Zero Page, X)
|
||||
E2:
|
||||
E3:
|
||||
E2:
|
||||
E3:
|
||||
E4: CPX - Zero Page
|
||||
E5: SBC - Zero Page
|
||||
E6: INC - Zero Page
|
||||
@ -233,7 +233,7 @@
|
||||
E8: INX - Implied
|
||||
E9: SBC - Immediate
|
||||
EA: NOP - Implied
|
||||
EB:
|
||||
EB:
|
||||
EC: CPX - Absolute
|
||||
ED: SBC - Absolute
|
||||
EE: INC - Absolute
|
||||
@ -241,16 +241,16 @@
|
||||
F0: BEQ - Relative
|
||||
F1: SBC - (Zero Page), Y
|
||||
F2: SBC - (Zero Page)
|
||||
F3:
|
||||
F4:
|
||||
F3:
|
||||
F4:
|
||||
F5: SBC - Zero Page, X
|
||||
F6: INC - Zero Page, X
|
||||
F7: SMB7 - Zero Page
|
||||
F8: SED - Implied
|
||||
F9: SBC - Absolute, Y
|
||||
FA: PLX - Implied
|
||||
FB:
|
||||
FC:
|
||||
FB:
|
||||
FC:
|
||||
FD: SBC - Absolute, X
|
||||
FE: INC - Absolute, X
|
||||
FF: BBS7 - Relative
|
||||
|
Loading…
x
Reference in New Issue
Block a user