aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--atk16_asm/asm_pass0.py50
-rw-r--r--atk16_asm/asm_pass1.py3
-rw-r--r--atk16_asm/builtin_asm/bootstrap.atk1618
-rw-r--r--atk16_asm/builtin_asm/std_bump_alloc.atk166
-rw-r--r--atk16_asm/builtin_asm/std_math.atk166
-rw-r--r--resources/asm/text_mode.atk163
-rw-r--r--test/e2e/call_stack/lib.atk1692
-rw-r--r--test/e2e/call_stack/run_fact.atk162
-rw-r--r--test/e2e/call_stack/run_mul.atk168
-rw-r--r--test/e2e/fibo/fibo.atk163
-rw-r--r--test/e2e/std_bump_alloc/run_bump_alloc_overlap.atk163
-rw-r--r--test/e2e/std_mem/run_memcopy.atk166
-rw-r--r--test/e2e/std_mem/run_memset.atk163
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