diff options
| author | Jan Tuomi <jans.tuomi@gmail.com> | 2024-02-22 08:52:20 +0200 |
|---|---|---|
| committer | Jan Tuomi <jans.tuomi@gmail.com> | 2024-02-22 08:52:20 +0200 |
| commit | 416e896956d3b05793337da6609fe1544797c0a9 (patch) | |
| tree | 9fa0cf3b622d4c9c086e4c08c5011ab12fdd4a77 /atk16_asm | |
| parent | aefe0cf3874c542669051b2b3cc21c9590aa970b (diff) | |
Add stuff, refactor
Diffstat (limited to 'atk16_asm')
| -rw-r--r-- | atk16_asm/__init__.py | 1 | ||||
| -rw-r--r-- | atk16_asm/asm_ops.py | 166 | ||||
| -rw-r--r-- | atk16_asm/asm_pass0.py | 6 | ||||
| -rw-r--r-- | atk16_asm/asm_pass1.py | 10 | ||||
| -rw-r--r-- | atk16_asm/asm_pass2.py | 6 | ||||
| -rw-r--r-- | atk16_asm/asm_pass3.py | 6 | ||||
| -rw-r--r-- | atk16_asm/asm_pass4.py | 6 | ||||
| -rwxr-xr-x | atk16_asm/assembler.py | 115 | ||||
| -rw-r--r-- | atk16_asm/optimizer.py | 2 |
9 files changed, 228 insertions, 90 deletions
diff --git a/atk16_asm/__init__.py b/atk16_asm/__init__.py new file mode 100644 index 0000000..abebbfb --- /dev/null +++ b/atk16_asm/__init__.py @@ -0,0 +1 @@ +from .assembler import assemble diff --git a/atk16_asm/asm_ops.py b/atk16_asm/asm_ops.py index 885c275..394a643 100644 --- a/atk16_asm/asm_ops.py +++ b/atk16_asm/asm_ops.py @@ -1,6 +1,10 @@ from typing import Callable -from asm_eval import * from dataclasses import dataclass +from .asm_eval import * + +ExpandResult = list[list[str]] +ExpandFn = Callable[..., ExpandResult] +OpExpansionDict = dict[str, ExpandFn] @dataclass class Meta: @@ -130,14 +134,131 @@ operations: OpWordDict = { "hlt": make_hlt, } -ExpandResult = list[list[str]] -ExpandFn = Callable[..., ExpandResult] -OpExpansionDict = dict[str, ExpandFn] - def expand_id(*parts: str) -> ExpandResult: return [list(parts)] -default_expansions: OpExpansionDict = { +def expand_add(left: str, right: str, target: str) -> ExpandResult: + return [["alr", "al_plus", left, right, target]] + +def expand_sub(left: str, right: str, target: str) -> ExpandResult: + return [["alr", "al_minus", left, right, target]] + +def expand_addi(left: str, imm: str, target: str) -> ExpandResult: + return [["ali", "al_plus", left, imm, target]] + +def expand_subi(left: str, imm: str, target: str) -> ExpandResult: + return [["ali", "al_minus", left, imm, target]] + +def expand_not(reg: str, target: str) -> ExpandResult: + return [["alr", "al_xor", reg, "0xFFFF", target]] + +def expand_noti(imm: str, target: str) -> ExpandResult: + return [["ali", "al_xor", imm, "0xFFFF", target]] + +def expand_and(left: str, right: str, target: str) -> ExpandResult: + return [["alr", "al_and", left, right, target]] + +def expand_andi(left: str, imm: str, target: str) -> ExpandResult: + return [["ali", "al_and", left, imm, target]] + +def expand_or(left: str, right: str, target: str) -> ExpandResult: + return [["alr", "al_or", left, right, target]] + +def expand_ori(left: str, imm: str, target: str) -> ExpandResult: + return [["ali", "al_or", left, imm, target]] + +def expand_xor(left: str, imm: str, target: str) -> ExpandResult: + return [["alr", "al_xor", left, imm, target]] + +def expand_xori(left: str, right: str, target: str) -> ExpandResult: + return [["ali", "al_xor", left, right, target]] + +def expand_sll(left: str, right: str, target: str) -> ExpandResult: + return [["alr", "al_sll", left, right, target]] + +def expand_slr(left: str, right: str, target: str) -> ExpandResult: + return [["alr", "al_slr", left, right, target]] + +def expand_sar(left: str, right: str, target: str) -> ExpandResult: + return [["alr", "al_sar", left, right, target]] + +def expand_slli(left: str, imm: str, target: str) -> ExpandResult: + return [["ali", "al_sll", left, imm, target]] + +def expand_slri(left: str, imm: str, target: str) -> ExpandResult: + return [["ali", "al_slr", left, imm, target]] + +def expand_sari(left: str, imm: str, target: str) -> ExpandResult: + return [["ali", "al_sar", left, imm, target]] + +def expand_inc(reg: str) -> ExpandResult: + return [["ali", "al_plus", reg, "1", reg]] + +def expand_dec(reg: str) -> ExpandResult: + return [["ali", "al_minus", reg, "1", reg]] + +def expand_mov(from_reg: str, to_reg: str) -> ExpandResult: + return [["ali", "al_plus", from_reg, "0", to_reg]] + +def expand_nop() -> ExpandResult: + return [["ali", "al_plus", "RA", "0", "RA"]] + +def expand_spu(reg: str) -> ExpandResult: + return [["str", reg, "SP"]] + expand_inc("SP") + +def expand_spo(reg: str) -> ExpandResult: + return expand_dec("SP") + [["ldr", "SP", reg]] + +def expand_sinc(imm: str) -> ExpandResult: + return expand_addi("SP", imm, "SP") + +def expand_sdec(imm: str) -> ExpandResult: + return expand_subi("SP", imm, "SP") + +def expand_csr(addr_reg: str, stratch_reg: str) -> ExpandResult: + return [ + ["lpc", stratch_reg], + *expand_addi(stratch_reg, "4", stratch_reg), + *expand_spu(stratch_reg), + ["jpr", addr_reg] + ] + +def expand_csi(addr_imm: str, stratch_reg: str) -> ExpandResult: + return [ + ["lpc", stratch_reg], + *expand_addi(stratch_reg, "4", stratch_reg), + *expand_spu(stratch_reg), + ["jpi", addr_imm] + ] + +def expand_rsr(stratch_reg: str) -> ExpandResult: + return expand_spo(stratch_reg) + [["jpr", stratch_reg]] + + +def stack_stash(*rs: str) -> ExpandResult: + result: ExpandResult = [] + for r in rs: + result += expand_spu(r) + + return result + +def stack_restore(*rs: str) -> ExpandResult: + result: ExpandResult = [] + for r in rs: + prefix = expand_spu(r) + result = prefix + result + + return result + +def set_graphics_mode(mode: str) -> ExpandResult: + return [ + ["ldi", "vt_gr_mode_addr", "RA"], + ["ldr", "RA", "RA"], + ["ldi", mode, "RB"], + ["str", "RB", "RA"], + ] + +expansions: OpExpansionDict = { "alr": lambda *args: expand_id("alr", *args), "ali": lambda *args: expand_id("ali", *args), "ldr": lambda *args: expand_id("ldr", *args), @@ -150,5 +271,38 @@ default_expansions: OpExpansionDict = { "lpc": lambda *args: expand_id("lpc", *args), "rti": lambda *args: expand_id("rti", *args), "hlt": lambda *args: expand_id("hlt", *args), + + "add": expand_add, + "sub": expand_sub, + "addi": expand_addi, + "subi": expand_subi, + "not": expand_not, + "noti": expand_noti, + "and": expand_and, + "andi": expand_andi, + "or": expand_or, + "ori": expand_ori, + "xor": expand_xor, + "xori": expand_xori, + "sll": expand_sll, + "slr": expand_slr, + "sar": expand_sar, + "slli": expand_slli, + "slri": expand_slri, + "sari": expand_sari, + "inc": expand_inc, + "dec": expand_dec, + "mov": expand_mov, + "nop": expand_nop, + "spu": expand_spu, + "spo": expand_spo, + "sinc": expand_sinc, + "sdec": expand_sdec, + "csr": expand_csr, + "csi": expand_csi, + "rsr": expand_rsr, + "stack_stash": stack_stash, + "stack_restore": stack_restore, + "set_graphics_mode": set_graphics_mode, } diff --git a/atk16_asm/asm_pass0.py b/atk16_asm/asm_pass0.py index f5b6b0b..262e5c1 100644 --- a/atk16_asm/asm_pass0.py +++ b/atk16_asm/asm_pass0.py @@ -1,8 +1,8 @@ from dataclasses import dataclass import os.path -from asm_ops import * -from asm_eval import * -from tokenizer import * +from .asm_ops import * +from .asm_eval import * +from .tokenizer import * @dataclass class Result0Line: diff --git a/atk16_asm/asm_pass1.py b/atk16_asm/asm_pass1.py index 0b06738..4786afa 100644 --- a/atk16_asm/asm_pass1.py +++ b/atk16_asm/asm_pass1.py @@ -2,10 +2,10 @@ import importlib import sys import os.path from dataclasses import dataclass -from asm_ops import * -from asm_eval import * -from asm_pass0 import * -from tokenizer import tokenize +from .asm_ops import * +from .asm_eval import * +from .asm_pass0 import * +from .tokenizer import tokenize @dataclass class Result1Line: @@ -20,7 +20,7 @@ class Result1: def pass_1(result0: Result0) -> Result1: result_lines: list[Result1Line] = [] - operations: OpExpansionDict = default_expansions.copy() + operations: OpExpansionDict = expansions.copy() for line in result0.lines: keyword, *args = tokenize(line.line) diff --git a/atk16_asm/asm_pass2.py b/atk16_asm/asm_pass2.py index e2ad4ec..cf6b10d 100644 --- a/atk16_asm/asm_pass2.py +++ b/atk16_asm/asm_pass2.py @@ -1,7 +1,7 @@ from dataclasses import dataclass -from asm_ops import * -from asm_eval import * -from asm_pass1 import * +from .asm_ops import * +from .asm_eval import * +from .asm_pass1 import * @dataclass class Result2Line: diff --git a/atk16_asm/asm_pass3.py b/atk16_asm/asm_pass3.py index 9c8cb34..09f58fa 100644 --- a/atk16_asm/asm_pass3.py +++ b/atk16_asm/asm_pass3.py @@ -1,7 +1,7 @@ from dataclasses import dataclass -from asm_ops import * -from asm_eval import * -from asm_pass2 import * +from .asm_ops import * +from .asm_eval import * +from .asm_pass2 import * @dataclass class Result3Line: diff --git a/atk16_asm/asm_pass4.py b/atk16_asm/asm_pass4.py index 2fff870..7365416 100644 --- a/atk16_asm/asm_pass4.py +++ b/atk16_asm/asm_pass4.py @@ -1,7 +1,7 @@ from dataclasses import dataclass -from asm_ops import * -from asm_eval import * -from asm_pass3 import * +from .asm_ops import * +from .asm_eval import * +from .asm_pass3 import * @dataclass class Result4Line: diff --git a/atk16_asm/assembler.py b/atk16_asm/assembler.py index c678ba0..1451d47 100755 --- a/atk16_asm/assembler.py +++ b/atk16_asm/assembler.py @@ -2,81 +2,64 @@ # Assemble ATK16 assembly to bytecode import sys -from asm_ops import * -from asm_eval import * -from asm_pass0 import pass_0 -from asm_pass1 import pass_1 -from asm_pass2 import pass_2 -from asm_pass3 import pass_3 -from asm_pass4 import pass_4 +from .asm_ops import * +from .asm_eval import * +from .asm_pass0 import pass_0 +from .asm_pass1 import pass_1 +from .asm_pass2 import pass_2 +from .asm_pass3 import pass_3 +from .asm_pass4 import pass_4 -if len(sys.argv) != 3: - print("usage: assembler.py <infile> <outfile> # read from file") - print(" assembler.py - <outfile> # read from stdin") - sys.exit(1) +def assemble(source: str, file_name: str) -> bytearray: + src_lines = source.splitlines() -infile_path = sys.argv[1] -outfile_path = sys.argv[2] + result0 = pass_0(src_lines, file_name) + result1 = pass_1(result0) + result2 = pass_2(result1) + result3 = pass_3(result2) + result4 = pass_4(result3) -src = "" -if (infile_path == "-"): - for line in sys.stdin: - src += line -else: - with open(infile_path, "r") as f: - src = f.read() + nop = bytearray([0b1000_0000, 0]) + result = bytearray() + # initially one nop + result.extend(nop) -src_lines = src.splitlines() + for line in result4.lines: + for (symbol, symbol_value) in result4.symbols.items(): + if line.address == symbol_value: + print(f"{symbol}:") -### Utils + if len(result) < 2 * line.address + 1: + result.extend((2 * line.address + 1 - len(result)) * nop) -def parse(line: str) -> list[str]: - depth = 0 - result: list[str] = [] - acc: str = "" - for c in line: - if c.isspace() and depth == 0: - result.append(acc) - acc = "" - elif c == "(": - depth += 1 - acc += "(" - elif c == ")": - depth -= 1 - acc += ")" - else: - acc += c + out_line = f"{line.address:>08x} 0x{line.word:>04x} {line.text}" + out_spaces_n = (42 - len(out_line)) + out_spaces = out_spaces_n * " " if out_spaces_n > 0 else 4 * " " + print(f"{out_line}{out_spaces}{line.original_text}") + result[2 * line.address + 0] = ((line.word >> 8) & 0xff) + result[2 * line.address + 1] = ((line.word >> 0) & 0xff) - result.append(acc) - return list(filter(lambda x: len(x) > 0, result)) + return result -result0 = pass_0(src_lines, infile_path) -result1 = pass_1(result0) -result2 = pass_2(result1) -result3 = pass_3(result2) -result4 = pass_4(result3) +if __name__ == "__main__": + if len(sys.argv) != 3: + print("usage: assembler.py <infile> <outfile> # read from file") + print(" assembler.py - <outfile> # read from stdin") + sys.exit(1) -nop = bytearray([0b1000_0000, 0]) -result = bytearray() -# initially one nop -result.extend(nop) + infile_path = sys.argv[1] + outfile_path = sys.argv[2] -for line in result4.lines: - for (symbol, symbol_value) in result4.symbols.items(): - if line.address == symbol_value: - print(f"{symbol}:") + src: str = "" + if (infile_path == "-"): + for line in sys.stdin: + src += line + else: + with open(infile_path, "r") as f: + src = f.read() - if len(result) < 2 * line.address + 1: - result.extend((2 * line.address + 1 - len(result)) * nop) + result = assemble(src, infile_path) + with open(outfile_path, "wb") as f: + f.write(result) - out_line = f"{line.address:>08x} 0x{line.word:>04x} {line.text}" - out_spaces_n = (42 - len(out_line)) - out_spaces = out_spaces_n * " " if out_spaces_n > 0 else 4 * " " - print(f"{out_line}{out_spaces}{line.original_text}") - result[2 * line.address + 0] = ((line.word >> 8) & 0xff) - result[2 * line.address + 1] = ((line.word >> 0) & 0xff) - -with open(outfile_path, "wb") as f: - f.write(result) - -print(f"Wrote {len(result)} bytes to {outfile_path}") + print(f"Wrote {len(result)} bytes to {outfile_path}") diff --git a/atk16_asm/optimizer.py b/atk16_asm/optimizer.py index 0ee2837..f08bec8 100644 --- a/atk16_asm/optimizer.py +++ b/atk16_asm/optimizer.py @@ -1,4 +1,4 @@ -from tokenizer import tokenize +from .tokenizer import tokenize def format_asm_row(asm: str) -> str: if not (asm.startswith("@") or asm.startswith(";")) and not asm.startswith(" ") and len(asm) > 0: |
