diff --git a/asm.py b/asm.py index 04d03df..8f39388 100755 --- a/asm.py +++ b/asm.py @@ -32,11 +32,13 @@ REGISTERS = { 'I': 0x06, 'J': 0x07, 'SP': 0x1b, 'PC': 0x1c, 'EX': 0x1d } + class ASM(SimpleNamespace): + @staticmethod def addr(arg, is_a): if type(arg) == Expr: - arg = arg.value + return (0x1f, arg) if type(arg) == Register: return (REGISTERS[arg.name], None) elif type(arg) == int: @@ -45,12 +47,8 @@ class ASM(SimpleNamespace): else: return (0x1f, arg) elif type(arg) == Indirect: - if type(arg.disp) == Expr: - disp = getattr(arg.disp, "value", 0) - else: - disp = arg.disp if arg.reg is None: - return (0x1e, disp) + return (0x1e, arg.disp) else: if arg.reg == 'SP': sp = getattr(arg, 'sp', None) @@ -75,7 +73,8 @@ class ASM(SimpleNamespace): if arg.disp == 0: return (0x08+REGISTERS[r], None) else: - return (0x10+REGISTERS[r], disp) + return (0x10+REGISTERS[r], arg.disp) + def code(self): o, b = OPCODES[self.op] a_bits, a_extra = self.addr(self.a, True) @@ -84,27 +83,15 @@ class ASM(SimpleNamespace): else: b_bits, b_extra = self.addr(self.b, False) r = [o | (a_bits << 10) | (b_bits << 5)] - for e in a_extra, b_extra: + for e in b_extra, a_extra: if e is not None: r.append(e) + print("Assembing: %s %r, %r -> %r" % (self.op, self.b, self.a, r)) return r + def words(self): - r = 1 - if type(self.a) in (Expr, int): # literal (FIXME: optimize short literals) - if type(self.a) == int: - if not (-1 <= self.a <= 30): - r += 1 - else: - r += 1 - elif type(self.a) == Indirect: - if self.a.disp != 0: - r += 1 - if type(self.b) in (Expr, int): # literal - r += 1 - elif type(self.b) == Indirect: - if self.b.disp != 0: - r += 1 - return r + return len(self.code()) + class Expr(SimpleNamespace): def eval(self, ctx): @@ -347,65 +334,64 @@ def expr_sym(p): lexer = lg.build() parser = pg.build() -def assemble(ctx, inst, step=1): +def assemble(ctx, inst): if inst.label is not None: - if step == 1 and inst.label in ctx: - print(f"Redefining symbol {inst.label}") ctx[inst.label] = ctx['.addr'] if type(inst) == Directive: if inst.directive == ".org": ctx['.addr'] = inst.args.eval(ctx) + return None elif inst.directive in (".data", ".word", "DAT"): al = [] for a in inst.args: if type(a) == str: al.extend([ord(x) for x in a]) else: - if step == 1: - al.append(a) - else: - al.append(a.eval(ctx)) - if step > 1: - print(ctx['.addr'], al) + al.append(a.simplify(ctx)) ctx['.addr'] += len(al) + return al elif type(inst) == ASM: - try: - if type(inst.a) == Expr: - inst.a = inst.a.eval(ctx) - if type(inst.b) == Expr: - inst.b = inst.b.eval(ctx) - except KeyError as e: - if step != 1: - raise e + if type(inst.a) == Expr: + inst.a = inst.a.simplify(ctx) + if type(inst.b) == Expr: + inst.b = inst.b.simplify(ctx) if inst.b is not None: print(f"{ctx['.addr']} {inst.op} {inst.b}, {inst.a} [len={inst.words()}]") else: print(f"{ctx['.addr']} {inst.op} {inst.a} [len={inst.words()}]") ctx['.addr'] += inst.words() - - if step != 1: - return inst.code() + return inst.code() if __name__ == '__main__': import sys sym = {} sym['.addr'] = 0 + insns = [] for filename in sys.argv[1:]: with open(filename, 'r') as sourcefile: code = parser.parse(lexer.lex(sourcefile.read())) for inst in code: # pylint: disable=E1133 # print(sym['.addr'], inst) - assemble(sym, inst) + a = sym['.addr'] + c = assemble(sym, inst) + if c is not None: + insns.append((a, c)) print(sym) + print(insns) sym['.addr'] = 0 binimage = b'' - for inst in code: # pylint: disable=E1133 - a = assemble(sym, inst, 2) - if a is not None: - print(["%04x" % x for x in a]) - for w in a: + for a, c in insns: # pylint: disable=E1133 + words = [] + for w in c: + if type(w) == int: + words.append(w) + else: + words.append(w.eval(sym)) + if words: + print(["%04x" % x for x in words]) + for w in words: binimage += struct.pack("