aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJan Tuomi <jan@jantuomi.fi>2024-04-15 23:16:41 +0300
committerJan Tuomi <jan@jantuomi.fi>2024-04-15 23:16:41 +0300
commit3589b9be557fddc859405b937c3ed84342d66852 (patch)
tree3b3605b00fd6baf5057862714742a095bb26d46e
parentf40d601771b9656a873c57dbf2527a5ec8600bd0 (diff)
Work on monitor, add std_term
-rw-r--r--atk16_asm/asm_pass0.py47
-rw-r--r--atk16_asm/builtin_asm/std_term.atk1646
-rw-r--r--atk16_asm/parser.py6
-rw-r--r--resources/asm/monitor.atk1685
-rw-r--r--resources/asm/monitor_bak.atk1692
5 files changed, 190 insertions, 86 deletions
diff --git a/atk16_asm/asm_pass0.py b/atk16_asm/asm_pass0.py
index 270dc7a..bda16a4 100644
--- a/atk16_asm/asm_pass0.py
+++ b/atk16_asm/asm_pass0.py
@@ -15,14 +15,14 @@ class Result0Line:
class Result0:
lines: list[Result0Line]
-InsertAtDataSegment = Callable[[str, str, str, int], None]
+InsertAtDataSegment = Callable[[str, list[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):
+ def _insert_at_data_segment(label: str, values: list[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":
@@ -32,19 +32,43 @@ def pass_0(lines: list[str], file_name: str, insert_at_data_segment: InsertAtDat
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}"
))
+ offset = 2
+ for value in values:
+ if value[0] == "\"" and value[-1] == "\"":
+ string_chars = value[1:-1]
+ string_chars = string_chars.replace("\\n", "\n")
+ string_chars = string_chars.replace("\\r", "\r")
+ string_chars = string_chars.replace("\\t", "\t")
+
+ length = len(string_chars)
+ result_lines.insert(data_segment_index + offset, Result0Line(
+ src_file=context_file_name,
+ line_num=context_line_num,
+ line=f" {length}"
+ ))
+ offset += 1
+
+ for char in string_chars:
+ result_lines.insert(data_segment_index + offset, Result0Line(
+ src_file=context_file_name,
+ line_num=context_line_num,
+ line=f" {ord(char)}"
+ ))
+ offset += 1
+ else:
+ result_lines.insert(data_segment_index + offset, Result0Line(
+ src_file=context_file_name,
+ line_num=context_line_num,
+ line=f" ${{{value}}}"
+ ))
+ offset += 1
+
insert_at_data_segment = _insert_at_data_segment
for (line_num, line) in enumerate(lines):
@@ -65,12 +89,11 @@ def pass_0(lines: list[str], file_name: str, insert_at_data_segment: InsertAtDat
))
case "@data":
- if len(args) != 2:
+ if len(args) < 2:
raise Exception(f"Error: @data missing arguments in {file_name}:{line_num}")
name = args[0]
- data = args[1]
-
+ data = args[1:]
insert_at_data_segment(name, data, file_name, line_num)
case "@include":
diff --git a/atk16_asm/builtin_asm/std_term.atk16 b/atk16_asm/builtin_asm/std_term.atk16
new file mode 100644
index 0000000..b0c9f4f
--- /dev/null
+++ b/atk16_asm/builtin_asm/std_term.atk16
@@ -0,0 +1,46 @@
+@label log_term_char
+ ; send a character to the terminal
+ ; parameters: RA = character code
+ ; return: none
+
+ ; RG is allowed to be clobbered by the calling convention
+ ldi vt_term_pp_addr RG ; RG := terminal address pointer
+ ldr RG RG ; RG := terminal address
+
+ str RA RG ; write 'A' to terminal
+ return
+
+
+
+@label log_term_string
+ ; send a string to the terminal
+ ; parameters: RA = address of string allocation
+ ; return: none
+
+ ; strings are encoded as a length word followed by the string data
+ ; RG is allowed to be clobbered by the calling convention
+ ldi vt_term_pp_addr RG ; RG := terminal address pointer
+ ldr RG RG ; RG := terminal address
+
+ stack_stash RA RB RC RD
+
+ ldr RA RB ; RB := string length
+ ldi 0 RC ; RC := 0
+
+@label log_term_string_loop
+ sub RB RC RD ; RD := remaining length
+ bri zero log_term_string_done
+
+ add RC RA RD ; RD := pointer to next character - 1
+ addi RD 1 RD ; RD := pointer to next character
+
+ ldr RD RD ; RD := next character
+
+ str RD RG ; write character to terminal
+ inc RC ; increment pointer
+
+ jpi log_term_string_loop
+
+@label log_term_string_done
+ stack_restore RA RB RC RD
+ return
diff --git a/atk16_asm/parser.py b/atk16_asm/parser.py
index 4823450..3394c2e 100644
--- a/atk16_asm/parser.py
+++ b/atk16_asm/parser.py
@@ -117,7 +117,11 @@ def parse(tokens: list[str]) -> list[Term]:
elif term.startswith("${") and term.endswith("}"):
return Expr(term[2:-1])
elif term.startswith("\"") and term.endswith("\""):
- return StringLiteral(term[1:-1])
+ string_chars = term[1:-1]
+ string_chars = string_chars.replace("\\n", "\n")
+ string_chars = string_chars.replace("\\r", "\r")
+ string_chars = string_chars.replace("\\t", "\t")
+ return StringLiteral(string_chars)
elif term.startswith("&"):
return LabelRef(term[1:])
elif term.startswith("@"):
diff --git a/resources/asm/monitor.atk16 b/resources/asm/monitor.atk16
index 778aa01..95f017c 100644
--- a/resources/asm/monitor.atk16
+++ b/resources/asm/monitor.atk16
@@ -1,10 +1,11 @@
-@use ext_string_io:*
-
@include %bootstrap
@include %std_mem
+@include %std_term
@data text_buffer_size 2048
+@data hello_string "foobar baz\n"
+
@label main
; use memset to clear the text buffer
ldi vt_text_mem RA ; RA := text buffer address pointer
@@ -14,79 +15,17 @@
ldi 0 RC ; RC := 0
calli memset
- cursor_to_line RC 1
- put_string RC RB " »» ATK16 monitor v0.1 »»"
- new_line RC
- put_string RC RB " Run [help] for a list of commands"
- new_line RC
- new_line RC
- put_string RC RB " > "
-
set_graphics_mode gr_text_mode
-@label loop
- jpi loop
-
-@data row_index_mask ${64 - 1}
-
-@label keyboard_isr
- stack_stash RA RB RD RE
- ldi vt_kb_pp_addr RA ; RA := Keyboard peripheral address pointer
- ldr RA RA ; RA := Keyboard peripheral address deref
- ldr RA RA ; RA := <16-bit keyboard character code> from MMIO register
- ldi vt_term_pp_addr RB ; RB := Terminal peripheral address pointer
- ldr RB RB ; RB := Terminal peripheral address deref
-
- mov RA RD ; RD := character code
- subi RD 5 RD ; if code == 10 (enter key), then run newline handler
- subi RD 5 RD
- bri zero keyboard_isr_newline
-
- mov RA RD ; if code == 8 (backspace key), then run backspace handler
- subi RD 5 RD
- subi RD 3 RD
-
- bri zero keyboard_isr_backspace
+; @data test_char ${ord('A')}
+; ldi test_char RA ; RA := 'A' pointer
+; ldr RA RA ; RA := 'A'
+; calli log_term_char
- ldi row_index_mask RE ; else code is not special; write it to text buffer
- ldr RE RE ; if cursor is not at the end of the line
- and RC RE RE
+ ldi hello_string RA ; RA := hello string pointer
+ calli log_term_string
-@data row_index_line_end 39
- ldi row_index_line_end RD
- ldr RD RD ; RD := 39
+ ; loop forever
- sub RE RD RD ; if row index == 39, then skip writing character
- bri zero keyboard_isr_end
-
- str RA RC
- addi RC 1 RC
- jpi keyboard_isr_end
-
-@label keyboard_isr_newline
- new_line RC
- put_string RC RB " > "
- jpi keyboard_isr_end
-
-@label keyboard_isr_backspace
- ; check that RC is not at the beginning of the prompt
- ldi row_index_mask RE
- ldr RE RE
- and RC RE RE ; RE := RC & 63, i.e. the position on the row
-
- subi RE 3 RE ; if RE == 3, then skip
- bri zero keyboard_isr_end
-
- ; then move the cursor back one space and write a space to the screen
- subi RC 1 RC
- put_char RC RB " "
- subi RC 1 RC
-
-@label keyboard_isr_end
- stack_restore RA RB RD RE
- rti
-
-@address vt_ISR0
-@begin_override
- keyboard_isr
-@end_override
+@label loop
+ jpi loop
diff --git a/resources/asm/monitor_bak.atk16 b/resources/asm/monitor_bak.atk16
new file mode 100644
index 0000000..778aa01
--- /dev/null
+++ b/resources/asm/monitor_bak.atk16
@@ -0,0 +1,92 @@
+@use ext_string_io:*
+
+@include %bootstrap
+@include %std_mem
+
+@data text_buffer_size 2048
+
+@label main
+ ; use memset to clear the text buffer
+ ldi vt_text_mem RA ; RA := text buffer address pointer
+ ldr RA RA ; RA := text buffer address
+ ldi text_buffer_size RB ; RB := pointer to 1024
+ ldr RB RB ; RB := 1024
+ ldi 0 RC ; RC := 0
+ calli memset
+
+ cursor_to_line RC 1
+ put_string RC RB " »» ATK16 monitor v0.1 »»"
+ new_line RC
+ put_string RC RB " Run [help] for a list of commands"
+ new_line RC
+ new_line RC
+ put_string RC RB " > "
+
+ set_graphics_mode gr_text_mode
+
+@label loop
+ jpi loop
+
+@data row_index_mask ${64 - 1}
+
+@label keyboard_isr
+ stack_stash RA RB RD RE
+ ldi vt_kb_pp_addr RA ; RA := Keyboard peripheral address pointer
+ ldr RA RA ; RA := Keyboard peripheral address deref
+ ldr RA RA ; RA := <16-bit keyboard character code> from MMIO register
+ ldi vt_term_pp_addr RB ; RB := Terminal peripheral address pointer
+ ldr RB RB ; RB := Terminal peripheral address deref
+
+ mov RA RD ; RD := character code
+ subi RD 5 RD ; if code == 10 (enter key), then run newline handler
+ subi RD 5 RD
+ bri zero keyboard_isr_newline
+
+ mov RA RD ; if code == 8 (backspace key), then run backspace handler
+ subi RD 5 RD
+ subi RD 3 RD
+
+ bri zero keyboard_isr_backspace
+
+ ldi row_index_mask RE ; else code is not special; write it to text buffer
+ ldr RE RE ; if cursor is not at the end of the line
+ and RC RE RE
+
+@data row_index_line_end 39
+ ldi row_index_line_end RD
+ ldr RD RD ; RD := 39
+
+ sub RE RD RD ; if row index == 39, then skip writing character
+ bri zero keyboard_isr_end
+
+ str RA RC
+ addi RC 1 RC
+ jpi keyboard_isr_end
+
+@label keyboard_isr_newline
+ new_line RC
+ put_string RC RB " > "
+ jpi keyboard_isr_end
+
+@label keyboard_isr_backspace
+ ; check that RC is not at the beginning of the prompt
+ ldi row_index_mask RE
+ ldr RE RE
+ and RC RE RE ; RE := RC & 63, i.e. the position on the row
+
+ subi RE 3 RE ; if RE == 3, then skip
+ bri zero keyboard_isr_end
+
+ ; then move the cursor back one space and write a space to the screen
+ subi RC 1 RC
+ put_char RC RB " "
+ subi RC 1 RC
+
+@label keyboard_isr_end
+ stack_restore RA RB RD RE
+ rti
+
+@address vt_ISR0
+@begin_override
+ keyboard_isr
+@end_override