116 lines
3.9 KiB
Python
116 lines
3.9 KiB
Python
"""Main controller routines for the Ophis assembler.
|
|
|
|
When invoked as main, interprets its command line and goes from there.
|
|
Otherwise, use run_ophis(cmdline-list) to use it inside a script."""
|
|
|
|
# Copyright 2002-2014 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 os
|
|
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 run_all():
|
|
"""Transforms the source infiles to a binary outfile.
|
|
|
|
Returns a shell-style exit code: 1 if there were errors, 0 if there
|
|
were no errors.
|
|
|
|
"""
|
|
Err.count = 0
|
|
z = Ophis.Frontend.parse(Ophis.CmdLine.infiles)
|
|
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: not l_basic.changed)
|
|
|
|
# The instruction selector is a bunch of fixpoints, and which
|
|
# passes run depends on the command line options a bit.
|
|
c_basic = Ophis.Passes.Collapse()
|
|
c = Ophis.Passes.FixPoint("instruction selection 1", [l, c_basic],
|
|
lambda: not c_basic.changed)
|
|
|
|
if Ophis.CmdLine.enable_branch_extend:
|
|
b = Ophis.Passes.ExtendBranches()
|
|
instruction_select = Ophis.Passes.FixPoint("instruction selection 2",
|
|
[c, b],
|
|
lambda: not b.changed)
|
|
else:
|
|
instruction_select = c
|
|
a = Ophis.Passes.Assembler()
|
|
|
|
passes = []
|
|
passes.append(Ophis.Passes.DefineMacros())
|
|
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(instruction_select)
|
|
passes.extend([Ophis.Passes.NormalizeModes(),
|
|
Ophis.Passes.UpdateLabels(),
|
|
a])
|
|
|
|
for p in passes:
|
|
p.go(z, env)
|
|
|
|
if Err.count == 0:
|
|
try:
|
|
outfile = Ophis.CmdLine.outfile
|
|
if outfile == '-':
|
|
output = sys.stdout.buffer
|
|
if sys.platform == "win32":
|
|
# We can't dump our binary in text mode; that would be
|
|
# disastrous. So, we'll do some platform-specific
|
|
# things here to force our stdout to binary mode.
|
|
import msvcrt
|
|
msvcrt.setmode(sys.stdout.fileno(), os.O_BINARY)
|
|
elif outfile is None:
|
|
output = open('ophis.bin', 'wb')
|
|
else:
|
|
output = open(outfile, 'wb')
|
|
output.write(bytes(a.output))
|
|
output.flush()
|
|
if outfile != '-':
|
|
output.close()
|
|
return 0
|
|
except IOError:
|
|
print("Could not write to " + outfile, file=sys.stderr)
|
|
return 1
|
|
else:
|
|
Err.report()
|
|
return 1
|
|
|
|
|
|
def run_ophis(args):
|
|
Ophis.CmdLine.parse_args(args)
|
|
Ophis.Frontend.pragma_modules.append(Ophis.CorePragmas)
|
|
|
|
if Ophis.CmdLine.enable_undoc_ops:
|
|
Ophis.Opcodes.opcodes.update(Ophis.Opcodes.undocops)
|
|
elif Ophis.CmdLine.enable_65c02_exts:
|
|
Ophis.Opcodes.opcodes.update(Ophis.Opcodes.c02extensions)
|
|
elif Ophis.CmdLine.enable_4502_exts:
|
|
Ophis.Opcodes.opcodes.update(Ophis.Opcodes.csg4502extensions)
|
|
|
|
Ophis.CorePragmas.reset()
|
|
return run_all()
|
|
|
|
|
|
if __name__ == '__main__':
|
|
sys.exit(run_ophis(sys.argv[1:]))
|