it's closer to compiling sslbp; my mock makeinc (not yet committed)
doesn't give right results for _byte, _flag, etc
This commit is contained in:
Jeff Epler 2014-08-16 22:15:10 -05:00
parent d3f308ee5d
commit d6eb374b12
3 changed files with 90 additions and 21 deletions

View file

@ -78,6 +78,7 @@ Insn("STAB SP", I0, 0x0f80)
# BIT OPERAND, PROGRAM ADDRESS FOR JUMPS
# iiii 0aaa aaaa aaaa DIRECT INSTRUCTIONS
Insn("JMP *", I11, 0x1000)
Insn("JMPA *", I11, 0x1000)
Insn("JMPNZ *", I11, 0x2000)
Insn("JMPZ *", I11, 0x3000)
Insn("JMPNC *", I11, 0x4000)

View file

@ -99,9 +99,10 @@ HexNumberPrefix = Regex("\$[0-9a-fA-f]+").setParseAction(
HexNumberSuffix = Regex("[0-9][0-9a-fA-F]*[hH]").setParseAction(
lambda toks: [str(int(toks[0][:-1], 16))])
StringLiteral = Regex(r'\"(\\.|[^"\\])*\"')
Number = (CharConstant ^ BinaryNumberPrefix ^ BinaryNumberSuffix ^ OctalNumberPrefix ^
OctalNumberSuffix ^ DecimalNumberSuffix ^
HexNumberPrefix ^ HexNumberSuffix ^ DecimalNumberNeutral)
HexNumberPrefix ^ HexNumberSuffix ^ DecimalNumberNeutral ^ StringLiteral)
Colon = Literal(":")
Label = Identifier.copy().setParseAction(

107
ptasm.py
View file

@ -106,17 +106,27 @@ class Macro:
self.name = name
self.filename = filename
self.firstline = firstline+1
self.sig = sig.split(",")
self.re = re.compile(r"\b(" + "|".join(sig) + ")\b")
self.sig = sig.strip().split(",")
if sig:
self.re = re.compile(r"\b(" + "|".join(self.sig) + r")\b")
print "RX", name, (r"\b(" + "|".join(self.sig) + r")\b")
else:
self.re = None
self.lines = []
self.append = self.lines.append
def subst(self, line, d):
return self.re.subn(lambda x: d.get(x.group(0)), line)[0]
def subst(self, (filename, lno, line), d):
if self.re:
line = self.re.subn(lambda x: d.get(x.group(0)), line)[0]
return line
def __call__(self, assembler, args, target):
values = args.split(",", 1)
lines = [self.subst(l, dict(zip(self.sig, values))) for l in self.lines]
if self.sig:
values = args.strip().split(",")
lines = [self.subst(l, dict(zip(self.sig, values)))
for l in self.lines]
print "| Expansion of", self.name
for i in lines: print "||", i
assembler.preprocess(self.filename, target, lines, self.firstline)
class Assembler(object):
@ -131,7 +141,8 @@ class Assembler(object):
IP = Optional(Instr ^ Pseudo)
self.Grammar = (
(White() + IP + OptComment) ^
Pseudo ^
(White() + Instr + OptComment) ^
(Identifier.copy().setResultsName("label") + Optional(Colon) + IP + OptComment) ^
OptComment)
@ -150,6 +161,7 @@ class Assembler(object):
def pseudo_equ(self, no, label, expr):
print "equ", repr(label), repr(expr)
if no == 1: self.assignexpr(label, expr)
pseudo_set = pseudo_equ
def pseudo_org(self, no, label, expr):
value = self.expr(expr)
@ -172,6 +184,13 @@ class Assembler(object):
def pseudo_lsfirst(self, no, label, expr):
self.msfirst = False
def pseudo_echo(self, no, label, expr):
if expr.startswith('"'): print "ECHO:", expr
else: print self.expr(expr)
def pseudo_label(self, no, label, expr):
self.assign(expr, self.addr)
def pseudo_end(self, no, label, expr):
Empty().parseString(expr, True)
pass # should touch flow control
@ -198,12 +217,16 @@ class Assembler(object):
self.rom = {}
self.symbols = {}
self.macros = {}
self.defines = {}
self.nunique = 0
self.lstack = []
self.defines = {'LABEL': self.label, 'UNIQUE': self.unique, 'DUP': self.dup, 'SWAP': self.swap}
self.lines = []
self.preprocess(filename)
print "pass1"
self.pass1()
print "pass2"
self.pass2()
def ismacro(self, line):
@ -215,6 +238,7 @@ class Assembler(object):
parts = line.split(None, 1)
if not parts: return False
macro = self.macros.get(parts[0])
print "expandmacro", repr(parts[0]), macro
if not macro: return False
macro(self, parts[1] if len(parts) > 1 else "", target)
return True
@ -229,44 +253,87 @@ class Assembler(object):
def replace(s):
s = s.group(0)
print "%s -> %s" % (s, self.defines.get(s, s))
return self.defines.get(s, s)
s = self.defines.get(s, s)
if callable(s): s = s()
return s
return word_re.subn(replace, line)[0]
def preprocess(self, filename, target = None, lines = None, firstline=1):
if not target: target = self.lines.append
def unique(self):
self.nunique += 1
print ">> UNIQUE", self.lstack, len(self.lstack),
self.lstack.append("__u_%d" % self.nunique)
print self.lstack, len(self.lstack)
return ''
def dup(self):
print ">> DUP", self.lstack, len(self.lstack),
self.lstack.append(self.lstack[-1])
print self.lstack, len(self.lstack)
return ''
def swap(self):
print ">> SWAP", self.lstack, len(self.lstack),
a = self.lstack.pop()
b = self.lstack.pop()
self.lstack.append(a)
self.lstack.append(b)
print self.lstack, len(self.lstack)
return ''
def label(self):
if self.lstack:
print ">> LABEL", self.lstack, len(self.lstack),
result = self.lstack.pop()
print self.lstack, len(self.lstack)
return result
else:
print "!!! pop from empty list"
return 'undefined'
def preprocess(self, filename, target = None, lines = None, firstline=1):
def basetarget((filename, lno, line)):
line = self.expand_defines(line)
print "%s:%d: %r" % (filename, lno, line)
self.lines.append((filename, lno,
self.Grammar.parseString(line, True)))
if not target: target = basetarget
if lines is None:
if filename == '-':
line = list(sys.stdin)
else:
with open(filename, "U") as f: lines = list(f)
self.symbols['__filename__'] = filename
for lno, line in enumerate(lines, firstline):
self.symbols['__filename__'] = filename
self.symbols['__lno__'] = lno
print "%s:%d: %s" % (filename, lno, line.rstrip())
if line.startswith("#include"):
line = line.rsplit(";", 1)[0]
if line.startswith("#include") or line.startswith(".include"):
self.preprocess(line.strip().split()[1], target)
continue
elif line.startswith("#define"):
elif line.lower().startswith("#define"):
self.create_define(line)
print self.defines.keys()
continue
line = self.expand_defines(line)
print "%s:%d: %s" % (filename, lno, line.rstrip())
if line.startswith(".macro"):
_, name, sig = line.split(None, 2)
parts = line.split(None, 2)
if len(parts) == 2:
name, sig = parts[1], ''
else:
_, name, sig = parts
self.macros[name] = mac = Macro(name, sig, filename, lno)
self.target = mac.append
target = mac.append
elif line.startswith(".endm"):
self.target = self.lines.append
self.target = basetarget
elif line.startswith(".end"):
return
elif self.expandmacro(line, target):
pass
else:
target((filename, lno, self.Grammar.parseString(line.rstrip(), True)))
print "%s:%d: %s" % (filename, lno, line.rstrip())
target((filename, lno, line.rstrip()))
def value(self, expr):
if not expr: return 0