commit d03eb65da9ad16272c07b03e1577f535f26c5109
parent 6231546dd400848f912edf00580553396f0a6a98
Author: Christian Ermann <christianermann@gmail.com>
Date: Fri, 25 Oct 2024 14:08:20 -0700
Add 'find', '>cfa', and 'execute'
Diffstat:
| M | forth.s | | | 70 | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++- |
1 file changed, 69 insertions(+), 1 deletion(-)
diff --git a/forth.s b/forth.s
@@ -10,6 +10,9 @@
#define rsp s2
#define cell 4
+#define flag_offset 4
+#define name_len_offset 5
+#define name_offset 6
#define load_cell lw
#define store_cell sw
@@ -138,17 +141,79 @@ _word_end:
addi ra, s6, 0
ret
+defcode "find", 4, 0, find, word
+ pop x
+ pop w
+ jal find_impl # w = word address or 0, if not found
+ push w
+ next
+
+find_impl:
+ # w = word name address
+ # x = word name length
+ la s3, latest
+ load_cell s3, 0(s3)
+_check_word_hidden:
+ lb t0, flag_offset(s3)
+ # beq t0, ?, _next_word
+_check_word_length:
+ lb t0, name_len_offset(s3)
+ bne t0, x, _next_word
+_check_word_match:
+ mv t0, w
+ mv t1, x
+ addi t2, s3, name_offset
+_check_char_match:
+ lb t3, 0(t0)
+ lb t4, 0(t2)
+ bne t3, t4, _next_word
+ addi t0, t0, 1
+ addi t2, t2, 1
+ addi t1, t1, -1
+ bgtz t1, _check_char_match
+ j _found_or_out_of_words
+_next_word:
+ load_cell s3, 0(s3)
+ bnez s3, _check_word_hidden
+_found_or_out_of_words:
+ mv w, s3
+ ret
+
+defcode ">cfa", 4, 0, to_cfa, find
+ pop w
+ jal to_cfa_impl
+ push w
+ next
+
+to_cfa_impl:
+ li t0, name_offset
+ lb t1, name_len_offset(w)
+ add t0, t0, t1
+ add w, w, t0
+ addi w, w, 3
+ andi w, w, 0xFFFFFFF4
+ ret
+
+defcode "execute", 7, 0, execute, to_cfa
+ pop w
+ load_cell x, 0(w)
+ jr x
+ # 'next' should be called by the executed word
+
.section ".rodata"
program:
.int type
.int word
- .int type
+ .int find
+ .int to_cfa
+ .int execute
version_string:
.ascii "soup forth rv32\n"
version_string_len = (. - version_string)
word_buffer: .space 255
+latest: .int name_find
.section ".text.boot"
start:
@@ -158,5 +223,8 @@ start:
push_addr version_string
push_imm version_string_len
+ push_addr version_string
+ push_imm version_string_len
+
next