mirror of
https://github.com/michaelcmartin/Ophis.git
synced 2024-06-08 19:29:28 +00:00
f8bc917601
This pass actually isn't an optimizer in that it produces larger binaries when it triggers. However, the larger binaries created will actually assemble properly. The ExtendBranches pass detects Relative instructions (that is, branches) that extend past the signed-8-bit range Relative instructions permit, and replaces them with a branch-jump combination with identical semantics. Since this may be evidence of a program bug, Ophis will warn when the optimization is triggered. Due to similarities between this pass and UpdateLabels, both passes have been refactored in passing.
118 lines
3.5 KiB
Python
118 lines
3.5 KiB
Python
"""Main controller routines for the Ophis assembler.
|
|
|
|
When invoked as main, interprets its command line and goes from there.
|
|
Otherwise, use run_all to interpret a file set."""
|
|
|
|
# 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.
|
|
|
|
import sys
|
|
import Ophis.Frontend
|
|
import Ophis.IR
|
|
import Ophis.CorePragmas
|
|
import Ophis.Passes
|
|
import Ophis.Errors as Err
|
|
import Ophis.Environment
|
|
import Ophis.CmdLine
|
|
import Ophis.Opcodes
|
|
|
|
|
|
def usage():
|
|
"Prints a usage message and quits."
|
|
print "Usage:"
|
|
print "\tOphis [options] infile outfile"
|
|
print ""
|
|
print "Options:"
|
|
print "\t-6510 Allow 6510 undocumented opcodes"
|
|
print "\t-65c02 Enable 65c02 extensions"
|
|
print "\t-v n Set verbosity to n (0-4, 1=default)"
|
|
sys.exit(1)
|
|
|
|
def run_all(infile, outfile):
|
|
"Transforms the source infile to a binary outfile."
|
|
Err.count = 0
|
|
z = Ophis.Frontend.parse(infile)
|
|
env = Ophis.Environment.Environment()
|
|
|
|
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)
|
|
c = Ophis.Passes.Collapse()
|
|
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", [l, c, b], lambda: c.collapsed == 0 and b.expanded == 0))
|
|
passes.extend([Ophis.Passes.NormalizeModes(), Ophis.Passes.UpdateLabels(), a])
|
|
|
|
for p in passes: p.go(z, env)
|
|
|
|
if Err.count == 0:
|
|
try:
|
|
output = file(outfile, 'wb')
|
|
output.write("".join(map(chr, a.output)))
|
|
except IOError:
|
|
print "Could not write to "+outfile
|
|
else:
|
|
Err.report()
|
|
|
|
def run_ophis():
|
|
infile = None
|
|
outfile = None
|
|
|
|
p65_compatibility_mode = 0
|
|
chip_extension = None
|
|
|
|
reading_arg = 0
|
|
|
|
for x in sys.argv[1:]:
|
|
if reading_arg:
|
|
try:
|
|
Ophis.CmdLine.verbose = int(x)
|
|
reading_arg = 0
|
|
except ValueError:
|
|
print "FATAL: Non-integer passed as argument to -v"
|
|
usage()
|
|
elif x[0] == '-':
|
|
if x == '-v':
|
|
reading_arg = 1
|
|
elif x == '-6510':
|
|
chip_extension = Ophis.Opcodes.undocops
|
|
elif x == '-65c02':
|
|
chip_extension = Ophis.Opcodes.c02extensions
|
|
else:
|
|
print "FATAL: Unknown option "+x
|
|
usage()
|
|
elif infile == None:
|
|
infile = x
|
|
elif outfile == None:
|
|
outfile = x
|
|
else:
|
|
print "FATAL: Too many files specified"
|
|
usage()
|
|
|
|
if infile is None:
|
|
print "FATAL: No files specified"
|
|
usage()
|
|
|
|
if outfile is None:
|
|
print "FATAL: No output file specified"
|
|
usage()
|
|
|
|
Ophis.Frontend.pragma_modules.append(Ophis.CorePragmas)
|
|
|
|
if chip_extension is not None:
|
|
Ophis.Opcodes.opcodes.update(chip_extension)
|
|
|
|
Ophis.CorePragmas.reset()
|
|
run_all(infile, outfile)
|
|
|
|
if __name__ == '__main__':
|
|
run_ophis()
|