diff options
| author | Jan Tuomi <jans.tuomi@gmail.com> | 2023-04-10 13:15:59 +0300 |
|---|---|---|
| committer | Jan Tuomi <jans.tuomi@gmail.com> | 2023-04-10 13:15:59 +0300 |
| commit | f07900a66952edb27114b8bdd68efc397b995796 (patch) | |
| tree | cbb13e08b222cab594332ae11d863e793528799a /src | |
| parent | a58375eee5d607fbb44620752195eafb9407685e (diff) | |
Add ext system
Diffstat (limited to 'src')
| -rwxr-xr-x | src/assembler.py | 215 | ||||
| -rw-r--r-- | src/assembler_eval.py | 39 | ||||
| -rw-r--r-- | src/assembler_ops.py | 108 | ||||
| -rw-r--r-- | src/ext_std.py | 24 | ||||
| -rw-r--r-- | src/test.atk16 | 2 | ||||
| -rwxr-xr-x | src/ucode.py | 2 |
6 files changed, 205 insertions, 185 deletions
diff --git a/src/assembler.py b/src/assembler.py index 7420a04..3a1d39f 100755 --- a/src/assembler.py +++ b/src/assembler.py @@ -2,6 +2,10 @@ # Assemble ATK16 assembly to bytecode import sys +from typing import Callable +import importlib +from assembler_ops import * +from assembler_eval import * if len(sys.argv) != 3: print("usage: assembler.py <infile> <outfile> # read from file") @@ -43,50 +47,11 @@ def parse(line: str) -> list[str]: result.append(acc) return list(filter(lambda x: len(x) > 0, result)) -def eval_expr(expr: str) -> int: - expr = eval_symbol(expr) - return eval(expr, labels.copy()) # eval as Python expr - -constants: dict[str, str] = { - # Registers - "rz": "0", - "ra": "1", - "rb": "2", - "rc": "3", - "rd": "4", - "rf": "5", - "rg": "6", - # ALU instructions - "al_plus": "0", - "al_minus": "1", - "al_and": "2", - "al_or": "3", - "al_xor": "4", - "al_shift_lr": "5", - "al_shift_ar": "6", - "al_shift_ll": "7", - # ALU flags - "f_carry": "0", - "f_overflow": "1", - "f_zero": "2", - "f_sign": "3", -} - -def eval_symbol(c: str): - if c in labels: - return str(labels[c]) - - if c in constants: - return constants[c] - - return c - -# 1st pass, gather labels, set options +# 1st pass, gather labels, set options, eval operations options: dict[str, str] = { "stack_pointer": "6" # RG } -labels: dict[str, int] = {} address: int = 0 for (lineNo, line) in enumerate(src_lines): @@ -104,6 +69,15 @@ for (lineNo, line) in enumerate(src_lines): opt_name = args[0] opt_value = constants.get(args[1], args[1]) options[opt_name] = opt_value + case "@use": + module_name, ops = args[0].split(":") + ops_split = ops.split(",") + module = importlib.import_module(module_name) + mod_operations: dict[str, Callable[..., list[int]]] = module.operations + for op in mod_operations: + callable = mod_operations[op] + if ops == "*" or op in ops_split: + operations[op] = callable case _: pass @@ -111,98 +85,6 @@ for (lineNo, line) in enumerate(src_lines): # 2nd pass -def make_alr(alu_op: str, left: str, right: str, target: str) -> list[int]: - """ALR 0000 TTTL LLRR RSSS""" - target_e = eval_expr(target) - left_e = eval_expr(left) - right_e = eval_expr(right) - alu_op_e = eval_expr(alu_op) - word = (0b0000 << 12) + \ - (target_e << 9) + \ - (left_e << 6) + \ - (right_e << 3) + \ - alu_op_e - return [word] - -def make_ali(alu_op: str, left: str, imm: str, target: str) -> list[int]: - """ALI 0001 TTTL LLII ISSS""" - target_e = eval_expr(target) - left_e = eval_expr(left) - imm_e = eval_expr(imm) - alu_op_e = eval_expr(alu_op) - word = (0b0001 << 12) + \ - (target_e << 9) + \ - (left_e << 6) + \ - (imm_e << 3) + \ - alu_op_e - return [word] - -def make_ldr(to_reg: str, addr_reg: str) -> list[int]: - """LDR 0010 TTTR RRXX XXXX""" - to_reg_e = eval_expr(to_reg) - addr_reg_e = eval_expr(addr_reg) - word = (0b0010 << 12) + \ - (to_reg_e << 9) + \ - (addr_reg_e << 6) - return [word] - -def make_str(from_reg: str, addr_reg: str) -> list[int]: - """STR 0011 TTTR RRXX XXXX""" - from_reg_e = eval_expr(from_reg) - addr_reg_e = eval_expr(addr_reg) - word = (0b0011 << 12) + \ - (from_reg_e << 9) + \ - (addr_reg_e << 6) - return [word] - -def make_ldi(to_reg: str, imm: str) -> list[int]: - """LDI 0100 TTTI IIII IIII""" - to_reg_e = eval_expr(to_reg) - imm_e = eval_expr(imm) - word = (0b0100 << 12) + \ - (to_reg_e << 9) + \ - imm_e - return [word] - -def make_jpr(addr_reg: str) -> list[int]: - """JPR 0101 XXXR RRXX XXXX""" - addr_reg_e = eval_expr(addr_reg) - word = (0b0101 << 12) + \ - (addr_reg_e << 6) - return [word] - -def make_jpi(address: int, imm: str) -> list[int]: - """JPI 0110 XXXI IIII IIII""" - imm_e = eval_expr(imm) - imm_e = imm_e - address - 1 - word = (0b0110 << 12) + \ - imm_e - return [word] - -def make_br(flag_s: str, addr_reg: str) -> list[int]: - """BR 0111 XFFR RRXX XXXX""" - flag_s_e = eval_expr(flag_s) - addr_reg_e = eval_expr(addr_reg) - word = (0b0111 << 12) + \ - (flag_s_e << 9) + \ - (addr_reg_e << 6) - return [word] - -def make_bri(address: int, flag_s: str, imm: str) -> list[int]: - """BRI 1000 XFFI IIII IIII""" - flag_s_e = eval_expr(flag_s) - imm_e = eval_expr(imm) - imm_e = imm_e - address - 1 - word = (0b1000 << 12) + \ - (flag_s_e << 9) + \ - imm_e - return [word] - -def make_hlt() -> list[int]: - """HLT 1111 XXXX XXXX XXXX""" - word = (0b1111 << 12) - return [word] - # def make_spu(reg: str) -> list[int]: # stack_pointer = options["stack_pointer"] # reg = eval_symbol(reg) @@ -210,7 +92,7 @@ def make_hlt() -> list[int]: # words_str: list[int] = make_str(reg, stack_pointer) # return words_inc + words_str -address = 0 +address: int = 0 nop = bytearray([0b1000_0000, 0]) result = bytearray() # initially one nop @@ -220,59 +102,24 @@ for (lineNo, line) in enumerate(src_lines): line = line.split(";")[0].strip() if line == "": continue keyword, *args = parse(line.lower()) - match keyword: - # Directives - case "@address": - address = eval_expr(args[0]) - continue - case "@label" | "@opt": - continue - # Instructions - case "alr": - words = make_alr(*args) - case "ali": - words = make_ali(*args) - case "ldr": - words = make_ldr(*args) - case "str": - words = make_str(*args) - case "ldi": - words = make_ldi(*args) - case "jpr": - words = make_jpr(*args) - case "jpi": - words = make_jpi(address, *args) - case "br": - words = make_br(*args) - case "bri": - words = make_bri(address, *args) - case "hlt": - words = make_hlt() + if keyword in operations: + words = operations[keyword](address, *args) + else: + match keyword: + # Directives + case "@address": + address = eval_expr(args[0]) + continue + case "@label" | "@opt" | "@use": + continue - # Pseudoinstructions - case "add": - words = make_alr("al_plus", *args) - case "sub": - words = make_alr("al_minus", *args) - case "inc": - words = make_ali("al_plus", args[0], "1", args[0]) - case "dec": - words = make_ali("al_minus", args[0], "1", args[0]) - case "mov": - words = make_ali("al_plus", args[0], "0", args[1]) - # case "csr": - # reg = args[0] - # words_spu = make_spu(reg) - # words = [] - # # todo finish this - - # Default case: evaluate as is (e.g. data word) - case _: - try: - words = [eval_expr(keyword)] - except: - raise Exception(f"Invalid assembly at {infile_path}:{lineNo + 1}\n\n{line}") + # Default case: evaluate as is (e.g. data word) + case _: + try: + words = [eval_expr(keyword)] + except: + raise Exception(f"Invalid assembly at {infile_path}:{lineNo + 1}\n\n{line}") if len(result) < 2 * address + 1: result.extend((2 * address + 1 - len(result)) * nop) diff --git a/src/assembler_eval.py b/src/assembler_eval.py new file mode 100644 index 0000000..3473ab8 --- /dev/null +++ b/src/assembler_eval.py @@ -0,0 +1,39 @@ +constants: dict[str, str] = { + # Registers + "rz": "0", + "ra": "1", + "rb": "2", + "rc": "3", + "rd": "4", + "rf": "5", + "rg": "6", + # ALU instructions + "al_plus": "0", + "al_minus": "1", + "al_and": "2", + "al_or": "3", + "al_xor": "4", + "al_shift_lr": "5", + "al_shift_ar": "6", + "al_shift_ll": "7", + # ALU flags + "f_carry": "0", + "f_overflow": "1", + "f_zero": "2", + "f_sign": "3", +} + +labels: dict[str, int] = {} + +def eval_symbol(c: str) -> str: + if c in labels: + return str(labels[c]) + + if c in constants: + return constants[c] + + return c + +def eval_expr(expr: str) -> int: + expr = eval_symbol(expr) + return eval(expr, labels.copy()) # eval as Python expr diff --git a/src/assembler_ops.py b/src/assembler_ops.py new file mode 100644 index 0000000..538dd78 --- /dev/null +++ b/src/assembler_ops.py @@ -0,0 +1,108 @@ +from typing import Callable +from assembler_eval import * + +def make_alr(address: int, alu_op: str, left: str, right: str, target: str) -> list[int]: + """ALR 0000 TTTL LLRR RSSS""" + target_e = eval_expr(target) + left_e = eval_expr(left) + right_e = eval_expr(right) + alu_op_e = eval_expr(alu_op) + word = (0b0000 << 12) + \ + (target_e << 9) + \ + (left_e << 6) + \ + (right_e << 3) + \ + alu_op_e + return [word] + +def make_ali(address: int, alu_op: str, left: str, imm: str, target: str) -> list[int]: + """ALI 0001 TTTL LLII ISSS""" + target_e = eval_expr(target) + left_e = eval_expr(left) + imm_e = eval_expr(imm) + alu_op_e = eval_expr(alu_op) + word = (0b0001 << 12) + \ + (target_e << 9) + \ + (left_e << 6) + \ + (imm_e << 3) + \ + alu_op_e + return [word] + +def make_ldr(address: int, to_reg: str, addr_reg: str) -> list[int]: + """LDR 0010 TTTR RRXX XXXX""" + to_reg_e = eval_expr(to_reg) + addr_reg_e = eval_expr(addr_reg) + word = (0b0010 << 12) + \ + (to_reg_e << 9) + \ + (addr_reg_e << 6) + return [word] + +def make_str(address: int, from_reg: str, addr_reg: str) -> list[int]: + """STR 0011 TTTR RRXX XXXX""" + from_reg_e = eval_expr(from_reg) + addr_reg_e = eval_expr(addr_reg) + word = (0b0011 << 12) + \ + (from_reg_e << 9) + \ + (addr_reg_e << 6) + return [word] + +def make_ldi(address: int, to_reg: str, imm: str) -> list[int]: + """LDI 0100 TTTI IIII IIII""" + to_reg_e = eval_expr(to_reg) + imm_e = eval_expr(imm) + word = (0b0100 << 12) + \ + (to_reg_e << 9) + \ + imm_e + return [word] + +def make_jpr(address: int, addr_reg: str) -> list[int]: + """JPR 0101 XXXR RRXX XXXX""" + addr_reg_e = eval_expr(addr_reg) + word = (0b0101 << 12) + \ + (addr_reg_e << 6) + return [word] + +def make_jpi(address: int, imm: str) -> list[int]: + """JPI 0110 XXXI IIII IIII""" + imm_e = eval_expr(imm) + imm_e = imm_e - address - 1 + word = (0b0110 << 12) + \ + imm_e + return [word] + +def make_br(address: int, flag_s: str, addr_reg: str) -> list[int]: + """brr 0111 XFFR RRXX XXXX""" + flag_s_e = eval_expr(flag_s) + addr_reg_e = eval_expr(addr_reg) + word = (0b0111 << 12) + \ + (flag_s_e << 9) + \ + (addr_reg_e << 6) + return [word] + +def make_bri(address: int, flag_s: str, imm: str) -> list[int]: + """BRI 1000 XFFI IIII IIII""" + flag_s_e = eval_expr(flag_s) + imm_e = eval_expr(imm) + imm_e = imm_e - address - 1 + word = (0b1000 << 12) + \ + (flag_s_e << 9) + \ + imm_e + return [word] + +def make_hlt(address: int, ) -> list[int]: + """HLT 1111 XXXX XXXX XXXX""" + word = (0b1111 << 12) + return [word] + +operations: dict[str, Callable[..., list[int]]] = { + "alr": make_alr, + "alr": make_alr, + "ali": make_ali, + "ldr": make_ldr, + "str": make_str, + "ldi": make_ldi, + "jpr": make_jpr, + "jpi": make_jpi, + "brr": make_br, + "bri": make_bri, + "hlt": make_hlt, +}
\ No newline at end of file diff --git a/src/ext_std.py b/src/ext_std.py new file mode 100644 index 0000000..017f40a --- /dev/null +++ b/src/ext_std.py @@ -0,0 +1,24 @@ +from assembler_ops import * + +def make_add(address:int, left: str, right: str, target: str) -> list[int]: + return make_alr(address, "al_plus", left, right, target) + +def make_sub(address: int, left: str, right: str, target: str) -> list[int]: + return make_alr(address, "al_minus", left, right, target) + +def make_inc(address: int, reg: str) -> list[int]: + return make_ali(address, "al_plus", reg, "1", reg) + +def make_dec(address: int, reg: str) -> list[int]: + return make_ali(address, "al_minus", reg, "1", reg) + +def make_mov(address: int, from_reg: str, to_reg: str) -> list[int]: + return make_ali(address, "al_plus", from_reg, "0", to_reg) + +operations = { + "add": make_add, + "sub": make_sub, + "inc": make_inc, + "dec": make_dec, + "mov": make_mov, +} diff --git a/src/test.atk16 b/src/test.atk16 index 1a7c773..1507430 100644 --- a/src/test.atk16 +++ b/src/test.atk16 @@ -1,5 +1,7 @@ ; Program: sum two values and store the result in RAM +@use ext_std:* + ; ROM (and program execution) starts at offset 0x0 @address 0x0 jpi program diff --git a/src/ucode.py b/src/ucode.py index a847a35..10dd853 100755 --- a/src/ucode.py +++ b/src/ucode.py @@ -59,7 +59,7 @@ ucode = [ not_branch([*fetch, R1_OE|PC_IE, US_RS, 0, 0, 0, 0]), # JPI 0110 XXXI IIII IIII not_branch([*fetch, IM_M|LI_OE|PC_IE, US_RS, 0, 0, 0, 0]), - # BR 0111 XFFR RRXX XXXX + # BRR 0111 XFFR RRXX XXXX branch([*fetch, US_RS, 0, 0, 0, 0, 0], [*fetch, R1_OE|PC_IE, US_RS, 0, 0, 0, 0]), # BRI 1000 XFFI IIII IIII |
