diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/asm_eval.py | 16 | ||||
| -rw-r--r-- | src/asm_ops.py | 66 | ||||
| -rw-r--r-- | src/asm_pass0.py | 21 | ||||
| -rw-r--r-- | src/asm_pass3.py | 20 | ||||
| -rw-r--r-- | src/asm_pass4.py | 13 | ||||
| -rwxr-xr-x | src/assembler.py | 6 |
6 files changed, 74 insertions, 68 deletions
diff --git a/src/asm_eval.py b/src/asm_eval.py index 691e4eb..c05fc03 100644 --- a/src/asm_eval.py +++ b/src/asm_eval.py @@ -24,24 +24,24 @@ constants: dict[str, str] = { "sign": "3", } -Labels = dict[str, int] +Symbols = dict[str, int] def check_size(bits: int, val: int) -> None: if val >= 2 ** bits: - raise Exception(f"Value does not fit in {bits} bits: {val}") + raise Exception(f"Value does not fit in {bits} bits: 0x{val:>04x}") -def eval_symbol(labels: Labels, c: str) -> str: - if c in labels: - return str(labels[c]) +def eval_symbol(symbols: Symbols, c: str) -> str: + if c in symbols: + return str(symbols[c]) if c in constants: return constants[c] return c -def eval_expr(labels: Labels, expr: str, bits: int = 16) -> int: +def eval_expr(symbols: Symbols, expr: str, bits: int = 16) -> int: expr = expr.lower() - expr = eval_symbol(labels, expr) - ret = eval(expr, labels.copy()) # eval as Python expr + expr = eval_symbol(symbols, expr) + ret = eval(expr, symbols.copy()) # eval as Python expr check_size(bits, ret) return ret diff --git a/src/asm_ops.py b/src/asm_ops.py index 74e7930..61e2caa 100644 --- a/src/asm_ops.py +++ b/src/asm_ops.py @@ -11,12 +11,12 @@ class Options: class Meta: address: int -def make_alr(meta: Meta, labels: Labels, alu_op: str, left: str, right: str, target: str) -> int: +def make_alr(meta: Meta, symbols: Symbols, alu_op: str, left: str, right: str, target: str) -> int: """ALR 0000 TTTL LLRR RSSS""" - target_e = eval_expr(labels, target, bits=3) - left_e = eval_expr(labels, left, bits=3) - right_e = eval_expr(labels, right, bits=3) - alu_op_e = eval_expr(labels, alu_op, bits=3) + target_e = eval_expr(symbols, target, bits=3) + left_e = eval_expr(symbols, left, bits=3) + right_e = eval_expr(symbols, right, bits=3) + alu_op_e = eval_expr(symbols, alu_op, bits=3) word = (0b0000 << 12) + \ (target_e << 9) + \ (left_e << 6) + \ @@ -24,12 +24,12 @@ def make_alr(meta: Meta, labels: Labels, alu_op: str, left: str, right: str, tar alu_op_e return word -def make_ali(meta: Meta, labels: Labels, alu_op: str, left: str, imm: str, target: str) -> int: +def make_ali(meta: Meta, symbols: Symbols, alu_op: str, left: str, imm: str, target: str) -> int: """ALI 0001 TTTL LLII ISSS""" - target_e = eval_expr(labels, target, bits=3) - left_e = eval_expr(labels, left, bits=3) - imm_e = eval_expr(labels, imm, bits=3) - alu_op_e = eval_expr(labels, alu_op, bits=3) + target_e = eval_expr(symbols, target, bits=3) + left_e = eval_expr(symbols, left, bits=3) + imm_e = eval_expr(symbols, imm, bits=3) + alu_op_e = eval_expr(symbols, alu_op, bits=3) word = (0b0001 << 12) + \ (target_e << 9) + \ (left_e << 6) + \ @@ -37,62 +37,64 @@ def make_ali(meta: Meta, labels: Labels, alu_op: str, left: str, imm: str, targe alu_op_e return word -def make_ldr(meta: Meta, labels: Labels, addr_reg: str, to_reg: str) -> int: +def make_ldr(meta: Meta, symbols: Symbols, addr_reg: str, to_reg: str) -> int: """LDR 0010 TTTR RRXX XXXX""" - to_reg_e = eval_expr(labels, to_reg, bits=3) - addr_reg_e = eval_expr(labels, addr_reg, bits=3) + to_reg_e = eval_expr(symbols, to_reg, bits=3) + addr_reg_e = eval_expr(symbols, addr_reg, bits=3) word = (0b0010 << 12) + \ (to_reg_e << 9) + \ (addr_reg_e << 6) return word -def make_str(meta: Meta, labels: Labels, from_reg: str, addr_reg: str) -> int: +def make_str(meta: Meta, symbols: Symbols, from_reg: str, addr_reg: str) -> int: """STR 0011 XXXL LLRR RXXX""" - from_reg_e = eval_expr(labels, from_reg, bits=3) - addr_reg_e = eval_expr(labels, addr_reg, bits=3) + from_reg_e = eval_expr(symbols, from_reg, bits=3) + addr_reg_e = eval_expr(symbols, addr_reg, bits=3) word = (0b0011 << 12) + \ (addr_reg_e << 6) + \ (from_reg_e << 3) return word -def make_ldi(meta: Meta, labels: Labels, imm: str, to_reg: str) -> int: +def make_ldi(meta: Meta, symbols: Symbols, imm: str, to_reg: str) -> int: """LDI 0100 TTTI IIII IIII""" - to_reg_e = eval_expr(labels, to_reg, bits=3) - imm_e = eval_expr(labels, imm, bits=9) + to_reg_e = eval_expr(symbols, to_reg, bits=3) + imm_e = eval_expr(symbols, imm, bits=9) word = (0b0100 << 12) + \ (to_reg_e << 9) + \ imm_e return word -def make_jpr(meta: Meta, labels: Labels, addr_reg: str) -> int: +def make_jpr(meta: Meta, symbols: Symbols, addr_reg: str) -> int: """JPR 0101 XXXR RRXX XXXX""" - addr_reg_e = eval_expr(labels, addr_reg, bits=3) + addr_reg_e = eval_expr(symbols, addr_reg, bits=3) word = (0b0101 << 12) + \ (addr_reg_e << 6) return word -def make_jpi(meta: Meta, labels: Labels, imm: str) -> int: +def make_jpi(meta: Meta, symbols: Symbols, imm: str) -> int: """JPI 0110 XXXI IIII IIII""" - imm_e = eval_expr(labels, imm, bits=9) + imm_e = eval_expr(symbols, imm, bits=9) imm_e = imm_e - meta.address - 1 imm_e = imm_e & (0b111111111) + print("symbols:", symbols) + print(meta, imm, f"0x{imm_e:>0x}") word = (0b0110 << 12) + \ imm_e return word -def make_brr(meta: Meta, labels: Labels, flag_s: str, addr_reg: str) -> int: +def make_brr(meta: Meta, symbols: Symbols, flag_s: str, addr_reg: str) -> int: """brr 0111 XFFR RRXX XXXX""" - flag_s_e = eval_expr(labels, flag_s, bits=2) - addr_reg_e = eval_expr(labels, addr_reg, bits=3) + flag_s_e = eval_expr(symbols, flag_s, bits=2) + addr_reg_e = eval_expr(symbols, addr_reg, bits=3) word = (0b0111 << 12) + \ (flag_s_e << 9) + \ (addr_reg_e << 6) return word -def make_bri(meta: Meta, labels: Labels, flag_s: str, imm: str) -> int: +def make_bri(meta: Meta, symbols: Symbols, flag_s: str, imm: str) -> int: """BRI 1000 XFFI IIII IIII""" - flag_s_e = eval_expr(labels, flag_s, bits=2) - imm_e = eval_expr(labels, imm, bits=9) + flag_s_e = eval_expr(symbols, flag_s, bits=2) + imm_e = eval_expr(symbols, imm, bits=9) imm_e = imm_e - meta.address - 1 imm_e = imm_e & (0b111111111) word = (0b1000 << 12) + \ @@ -100,14 +102,14 @@ def make_bri(meta: Meta, labels: Labels, flag_s: str, imm: str) -> int: imm_e return word -def make_lpc(meta: Meta, labels: Labels, target: str) -> int: +def make_lpc(meta: Meta, symbols: Symbols, target: str) -> int: """LPC 1001 TTTX XXXX XXXX""" - target_e = eval_expr(labels, target, bits=3) + target_e = eval_expr(symbols, target, bits=3) word = (0b1001 << 12) + \ (target_e << 9) return word -def make_hlt(meta: Meta, labels: Labels) -> int: +def make_hlt(meta: Meta, symbols: Symbols) -> int: """HLT 1111 XXXX XXXX XXXX""" word = (0b1111 << 12) return word diff --git a/src/asm_pass0.py b/src/asm_pass0.py index a0ae56d..4913e4b 100644 --- a/src/asm_pass0.py +++ b/src/asm_pass0.py @@ -12,13 +12,9 @@ class Result0Line: @dataclass class Result0: lines: list[Result0Line] - options: Options - operations: OpExpansionDict def pass_0(lines: list[str], file_name: str) -> Result0: - options = Options() result_lines: list[Result0Line] = [] - operations: OpExpansionDict = default_expansions.copy() for (line_num, line) in enumerate(lines): line = line.split(";")[0].strip() @@ -29,12 +25,15 @@ def pass_0(lines: list[str], file_name: str) -> Result0: asm_file_name = args[0] path = os.path.join(os.path.dirname(file_name), asm_file_name + ".atk16") with open(path, "r") as f: - for incl_line in f.readlines(): - result_lines.append(Result0Line( - src_file=asm_file_name, - line_num=line_num, - line=incl_line - )) + incl_lines = f.readlines() + + incl_result0 = pass_0(incl_lines, asm_file_name) + for incl_line in incl_result0.lines: + result_lines.append(Result0Line( + src_file=incl_line.src_file, + line_num=incl_line.line_num, + line=incl_line.line + )) case _: result_lines.append(Result0Line( @@ -44,7 +43,5 @@ def pass_0(lines: list[str], file_name: str) -> Result0: )) return Result0( - operations=operations, - options=options, lines=result_lines ) diff --git a/src/asm_pass3.py b/src/asm_pass3.py index 76e7b84..5221f6d 100644 --- a/src/asm_pass3.py +++ b/src/asm_pass3.py @@ -16,21 +16,24 @@ class Result3: lines: list[Result3Line] options: Options operations: OpExpansionDict - labels: dict[str, int] + symbols: dict[str, int] def pass_3(result2: Result2) -> Result3: result_lines: list[Result3Line] = [] - labels: dict[str, int] = {} + symbols: dict[str, int] = {} address = 0 for line in result2.lines: keyword, *args = line.parts match keyword: case "@address": - address = eval(args[0]) + address = eval_expr(symbols, args[0]) continue case "@label": - labels[args[0]] = address + symbols[args[0]] = address + continue + case "@let": + symbols[args[0]] = eval_expr(symbols, args[1]) continue case _: result_lines.append(Result3Line( @@ -42,9 +45,16 @@ def pass_3(result2: Result2) -> Result3: )) address += 1 + result_lines.sort(key=lambda l: l.address) + for result_line in result_lines: + rows_with_same_addr = list(filter(lambda l: l.address == result_line.address, result_lines)) + n = len(rows_with_same_addr) + if n > 1: + formatted = "\n".join(map(lambda l: " ".join(l.parts), rows_with_same_addr)) + raise Exception(f"Overlapping segments: address 0x{result_line.address:>04x} has conflicting definitions:\n{formatted}") return Result3( operations=result2.operations, options=result2.options, lines=result_lines, - labels=labels, + symbols=symbols, ) diff --git a/src/asm_pass4.py b/src/asm_pass4.py index dc65b65..462707a 100644 --- a/src/asm_pass4.py +++ b/src/asm_pass4.py @@ -17,7 +17,7 @@ class Result4: lines: list[Result4Line] options: Options operations: OpExpansionDict - labels: dict[str, int] + symbols: dict[str, int] def translate_opt(arg: str, options: Options) -> str: match arg: @@ -27,12 +27,11 @@ def translate_opt(arg: str, options: Options) -> str: def pass_4(result3: Result3) -> Result4: result_lines: list[Result4Line] = [] - address = 0 for line in result3.lines: keyword, *args = line.parts meta = Meta( - address=address, + address=line.address, ) args = list(map(lambda a: translate_opt(a, result3.options), args)) @@ -41,7 +40,7 @@ def pass_4(result3: Result3) -> Result4: if keyword in operations: fn = operations[keyword] - word = fn(meta, result3.labels, *args) + word = fn(meta, result3.symbols, *args) result_lines.append(Result4Line( line_num=line.line_num, src_file=line.src_file, @@ -56,18 +55,16 @@ def pass_4(result3: Result3) -> Result4: line_num=line.line_num, src_file=line.src_file, address=line.address, - word=eval_expr(result3.labels, keyword), + word=eval_expr(result3.symbols, keyword), text=text, original_text=original_text, )) except: raise Exception(f"Invalid assembly at {line.src_file}:{line.line_num + 1}\n\n{line}") - address += 1 - return Result4( operations=result3.operations, - labels=result3.labels, + symbols=result3.symbols, options=result3.options, lines=result_lines, ) diff --git a/src/assembler.py b/src/assembler.py index 8f84288..c678ba0 100755 --- a/src/assembler.py +++ b/src/assembler.py @@ -62,9 +62,9 @@ result = bytearray() result.extend(nop) for line in result4.lines: - for (label, label_addr) in result4.labels.items(): - if line.address == label_addr: - print(f"{label}:") + for (symbol, symbol_value) in result4.symbols.items(): + if line.address == symbol_value: + print(f"{symbol}:") if len(result) < 2 * line.address + 1: result.extend((2 * line.address + 1 - len(result)) * nop) |
