diff options
| author | Jan Tuomi <jan@jantuomi.fi> | 2024-04-14 17:20:34 +0300 |
|---|---|---|
| committer | Jan Tuomi <jan@jantuomi.fi> | 2024-04-14 17:20:34 +0300 |
| commit | 367813568d723e598a38a7327fc2bb4abcfc598c (patch) | |
| tree | f4c72a5e3f3992d8b43ed0a5e695c8e9aa790ecf | |
| parent | 2f69a9ac8c2de9d37248baa5c774c2813f070ba0 (diff) | |
Add data_segment feature, refactor
| -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 | ||||
| -rw-r--r-- | resources/asm/text_mode.atk16 | 3 | ||||
| -rw-r--r-- | test/e2e/call_stack/lib.atk16 | 92 | ||||
| -rw-r--r-- | test/e2e/call_stack/run_fact.atk16 | 2 | ||||
| -rw-r--r-- | test/e2e/call_stack/run_mul.atk16 | 8 | ||||
| -rw-r--r-- | test/e2e/fibo/fibo.atk16 | 3 | ||||
| -rw-r--r-- | test/e2e/std_bump_alloc/run_bump_alloc_overlap.atk16 | 3 | ||||
| -rw-r--r-- | test/e2e/std_mem/run_memcopy.atk16 | 6 | ||||
| -rw-r--r-- | test/e2e/std_mem/run_memset.atk16 | 3 |
13 files changed, 76 insertions, 127 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) diff --git a/resources/asm/text_mode.atk16 b/resources/asm/text_mode.atk16 index cab9562..1761361 100644 --- a/resources/asm/text_mode.atk16 +++ b/resources/asm/text_mode.atk16 @@ -3,8 +3,7 @@ @include %bootstrap @include %std_mem -@label text_buffer_size - 2048 +@data text_buffer_size 2048 @label main ; use memset to clear the text buffer diff --git a/test/e2e/call_stack/lib.atk16 b/test/e2e/call_stack/lib.atk16 deleted file mode 100644 index 58b9cdb..0000000 --- a/test/e2e/call_stack/lib.atk16 +++ /dev/null @@ -1,92 +0,0 @@ -@label mul_sign_mask - ${2 ** 15} -@label mul_not_mask - 0xFFFF - -@label mul - ; multiply a signed (a) and a signed (b) - ; parameters RA = a - ; RB = b - ; return RG = a * b - - stack_stash RA RB RC RD - ldi 0 RG ; initialize return value in RG to 0 - - ldi mul_sign_mask RD - ldr RD RD ; RD := 2 ** 16 - and RA RD RC ; RC := 2 ** 16 if a is negative, 0 otherwise - and RB RD RD ; RD := 2 ** 16 if b is negative, 0 otherwise - xor RC RD RC ; RC := 2 ** 16 if exactly one of a or b is negative, 0 otherwise - - ldi mul_not_mask RD - ldr RD RD ; RD := 0xFFFF - - ; RA := abs(a) - subi RA 0 RA - bri sign mul_a_negative - jpi mul_a_negative_done -@label mul_a_negative - xor RA RD RA ; RA := ~a - inc RA ; negate twos complement a -@label mul_a_negative_done - - ; RB := abs(b) - subi RB 0 RB - bri sign mul_b_negative - jpi mul_b_negative_done -@label mul_b_negative - xor RB RD RB ; RB := ~b - inc RB ; negate twos complement b -@label mul_b_negative_done - - ; the algorithms iterates b times, adding a to RG each time - ; so b should be as small as possible - sub RB RA RD ; if a <= b, swap a and b - bri sign mul_loop - - mov RA RD - mov RB RA - mov RD RB -@label mul_loop - ; if b == 0, we are done - subi RB 0 RB - bri zero mul_done - ; RG += RA - add RA RG RG - dec RB - jpi mul_loop -@label mul_done - ; set the most significant bit to the precomputed sign - subi RC 0 RC - bri sign mul_negate_result - jpi mul_return -@label mul_negate_result - ldi mul_not_mask RD - ldr RD RD ; RD := 0xFFFF - xor RG RD RG - inc RG -@label mul_return - stack_restore RA RB RC RD - return - -; Recursive impl of the factorial -; Calling convention is that arguments are in registers RA..RG (max 7 arguments since RH = SP) -; and the return value is in RG (note: overwriting arg in RG) - -@label fact - ; parameters RA = n - ; return RG = factorial(n) - subi RA 0 RA - bri zero fact_basecase -@label fact_reccase - stack_stash RA RB - mov RA RB ; RB := n - subi RA 1 RA ; RA := n - 1 - calli fact ; RG := fact(n - 1) - mov RG RA ; RA := fact(n - 1) - calli mul ; RG := n * fact(n - 1) - stack_restore RA RB - return -@label fact_basecase - ldi 1 RG - return diff --git a/test/e2e/call_stack/run_fact.atk16 b/test/e2e/call_stack/run_fact.atk16 index e0b8bf1..9a282ff 100644 --- a/test/e2e/call_stack/run_fact.atk16 +++ b/test/e2e/call_stack/run_fact.atk16 @@ -1,5 +1,5 @@ @include %bootstrap -@include lib +@include %std_math @let INPUT %INPUT% ; value replaced by test driver code diff --git a/test/e2e/call_stack/run_mul.atk16 b/test/e2e/call_stack/run_mul.atk16 index 377e61c..f47e19b 100644 --- a/test/e2e/call_stack/run_mul.atk16 +++ b/test/e2e/call_stack/run_mul.atk16 @@ -1,11 +1,9 @@ @include %bootstrap -@include lib +@include %std_math ; values replaced by test driver code -@label INPUT_A - %INPUT_A% -@label INPUT_B - %INPUT_B% +@data INPUT_A %INPUT_A% +@data INPUT_B %INPUT_B% @label main ldi INPUT_A RA diff --git a/test/e2e/fibo/fibo.atk16 b/test/e2e/fibo/fibo.atk16 index a817a1c..5b9030b 100644 --- a/test/e2e/fibo/fibo.atk16 +++ b/test/e2e/fibo/fibo.atk16 @@ -1,7 +1,6 @@ @include %bootstrap -@label iters - 51 +@data iters 51 @label main ldi iters RA diff --git a/test/e2e/std_bump_alloc/run_bump_alloc_overlap.atk16 b/test/e2e/std_bump_alloc/run_bump_alloc_overlap.atk16 index 8dcc6fa..08ced49 100644 --- a/test/e2e/std_bump_alloc/run_bump_alloc_overlap.atk16 +++ b/test/e2e/std_bump_alloc/run_bump_alloc_overlap.atk16 @@ -1,8 +1,7 @@ @include %bootstrap @include %std_bump_alloc -@label n - 0x8000 +@data n 0x8000 @label main calli bump_reset diff --git a/test/e2e/std_mem/run_memcopy.atk16 b/test/e2e/std_mem/run_memcopy.atk16 index 66f3c1d..a011cb9 100644 --- a/test/e2e/std_mem/run_memcopy.atk16 +++ b/test/e2e/std_mem/run_memcopy.atk16 @@ -1,10 +1,8 @@ @include %bootstrap @include %std_mem -@label mem_offset_from - 0x9000 -@label mem_offset_to - 0x9100 +@data mem_offset_from 0x9000 +@data mem_offset_to 0x9100 @label main ; set values 0x0000..0x0004 to 3 diff --git a/test/e2e/std_mem/run_memset.atk16 b/test/e2e/std_mem/run_memset.atk16 index 07e7666..b6a012c 100644 --- a/test/e2e/std_mem/run_memset.atk16 +++ b/test/e2e/std_mem/run_memset.atk16 @@ -1,8 +1,7 @@ @include %bootstrap @include %std_mem -@label mem_offset - 0x9000 +@data mem_offset 0x9000 @label main ; set 0x9005 to value 4 |
