diff options
Diffstat (limited to 'atk16_asm')
| -rw-r--r-- | atk16_asm/asm_pass0.py | 50 | ||||
| -rw-r--r-- | atk16_asm/asm_pass1.py | 3 | ||||
| -rw-r--r-- | atk16_asm/builtin_asm/bootstrap.atk16 | 18 | ||||
| -rw-r--r-- | atk16_asm/builtin_asm/std_bump_alloc.atk16 | 6 | ||||
| -rw-r--r-- | atk16_asm/builtin_asm/std_math.atk16 | 6 |
5 files changed, 66 insertions, 17 deletions
diff --git a/atk16_asm/asm_pass0.py b/atk16_asm/asm_pass0.py index b30ddc0..270dc7a 100644 --- a/atk16_asm/asm_pass0.py +++ b/atk16_asm/asm_pass0.py @@ -1,5 +1,6 @@ from dataclasses import dataclass import os.path +from typing import Callable from .asm_ops import * from .asm_eval import * from .tokenizer import * @@ -14,10 +15,38 @@ class Result0Line: class Result0: lines: list[Result0Line] -def pass_0(lines: list[str], file_name: str) -> Result0: +InsertAtDataSegment = Callable[[str, str, str, int], None] + +def pass_0(lines: list[str], file_name: str, insert_at_data_segment: InsertAtDataSegment | None = None) -> Result0: file_name = file_name if file_name.endswith(".atk16") else file_name + ".atk16" result_lines: list[Result0Line] = [] + if not insert_at_data_segment: + def _insert_at_data_segment(label: str, value: str, context_file_name: str, context_line_num: int): + data_segment_index = None + for idx, result_line in enumerate(result_lines): + if result_line.line == "%%data_segment": + data_segment_index = idx + break + + if data_segment_index is None: + raise Exception(f"Error: @data before @data_segment in {context_file_name}:{context_line_num}") + + # Inverted order because of insert semantics + result_lines.insert(data_segment_index + 1, Result0Line( + src_file=context_file_name, + line_num=context_line_num, + line=f"${{{value}}}" + )) + + result_lines.insert(data_segment_index + 1, Result0Line( + src_file=context_file_name, + line_num=context_line_num, + line=f"@label {label}" + )) + + insert_at_data_segment = _insert_at_data_segment + for (line_num, line) in enumerate(lines): line_num += 1 # line numbers are 1-based @@ -27,6 +56,23 @@ def pass_0(lines: list[str], file_name: str) -> Result0: keyword, *args = tokenize(line) match keyword: + case "@data_segment": + data_segment_sentinel = "%%data_segment" + result_lines.append(Result0Line( + src_file=file_name, + line_num=line_num, + line=data_segment_sentinel + )) + + case "@data": + if len(args) != 2: + raise Exception(f"Error: @data missing arguments in {file_name}:{line_num}") + + name = args[0] + data = args[1] + + insert_at_data_segment(name, data, file_name, line_num) + case "@include": asm_file_name = args[0] if args[0].endswith(".atk16") else args[0] + ".atk16" # if starts with %, use the path relative to this source file, not the current working directory @@ -40,7 +86,7 @@ def pass_0(lines: list[str], file_name: str) -> Result0: with open(path, "r") as f: incl_lines = f.readlines() - incl_result0 = pass_0(incl_lines, asm_file_name) + incl_result0 = pass_0(incl_lines, asm_file_name, insert_at_data_segment) for incl_line in incl_result0.lines: result_lines.append(Result0Line( src_file=incl_line.src_file, diff --git a/atk16_asm/asm_pass1.py b/atk16_asm/asm_pass1.py index 4786afa..d192b5e 100644 --- a/atk16_asm/asm_pass1.py +++ b/atk16_asm/asm_pass1.py @@ -35,6 +35,9 @@ def pass_1(result0: Result0) -> Result1: expansion = mod_expansions[op] if ops == "*" or op in ops_split: operations[op] = expansion + case "%%data_segment": + # drop the data_segment sentinel + continue case _: result_lines.append(Result1Line( src_file=line.src_file, diff --git a/atk16_asm/builtin_asm/bootstrap.atk16 b/atk16_asm/builtin_asm/bootstrap.atk16 index 28d8aa1..b3b4254 100644 --- a/atk16_asm/builtin_asm/bootstrap.atk16 +++ b/atk16_asm/builtin_asm/bootstrap.atk16 @@ -31,10 +31,10 @@ @let vt_text_mem 0x19 ; Text memory buffer address @address vector_table - hlt_isr ; 0x10 - hlt_isr ; 0x11 - hlt_isr ; 0x12 - hlt_isr ; 0x13 + no_op_isr ; 0x10 + no_op_isr ; 0x11 + no_op_isr ; 0x12 + no_op_isr ; 0x13 stack_segment ; 0x14 terminal_addr ; 0x15 keyboard_addr ; 0x16 @@ -42,9 +42,13 @@ sprite_mem ; 0x18 text_mem ; 0x19 -@label hlt_isr - ldi 0x55 RE - hlt +@label no_op_isr + rti + +; Define data segment location to this address +; Programs can use `@data label value` to inject data here +@label data_segment +@data_segment ; Example ISR for keyboard to terminal ; @label keyboard_to_terminal_isr diff --git a/atk16_asm/builtin_asm/std_bump_alloc.atk16 b/atk16_asm/builtin_asm/std_bump_alloc.atk16 index 1d87435..32516bc 100644 --- a/atk16_asm/builtin_asm/std_bump_alloc.atk16 +++ b/atk16_asm/builtin_asm/std_bump_alloc.atk16 @@ -21,10 +21,8 @@ ; The alloc_next value is a pointer to the next free word in the heap. ; It is stored in the first word of the heap. -@label bump_next_p - heap_segment -@label bump_arena_start - ${heap_segment - 1} +@data bump_next_p heap_segment +@data bump_arena_start ${heap_segment - 1} @label bump_reset ; reset the heap to its initial state (zero allocated blocks) diff --git a/atk16_asm/builtin_asm/std_math.atk16 b/atk16_asm/builtin_asm/std_math.atk16 index 58b9cdb..6544b32 100644 --- a/atk16_asm/builtin_asm/std_math.atk16 +++ b/atk16_asm/builtin_asm/std_math.atk16 @@ -1,7 +1,5 @@ -@label mul_sign_mask - ${2 ** 15} -@label mul_not_mask - 0xFFFF +@data mul_sign_mask ${2 ** 15} +@data mul_not_mask 0xFFFF @label mul ; multiply a signed (a) and a signed (b) |
