forth-riscv

My forth
git clone git://git.electrosoup.com/forth-riscv
Log | Files | Refs

commit 38cc7345ce6b626acc2be223267ff7c997130c4f
parent 8847c6b5c1e8e0e9034895c5d0098079afd3be49
Author: Christian Ermann <christianermann@gmail.com>
Date:   Wed,  6 Nov 2024 14:48:49 -0800

Refactor 'defcode' and 'defword' macros

Diffstat:
Mforth.s | 250+++++++++++++++++++++++++++++++++++++++++--------------------------------------
1 file changed, 129 insertions(+), 121 deletions(-)

diff --git a/forth.s b/forth.s @@ -1,3 +1,5 @@ +.option norelax + .extern uart_put_char .extern uart_get_char .extern uart_put_string @@ -64,53 +66,61 @@ addi rsp, rsp, cell .endm -.macro defcode name, name_length, flags, hash, label, last + +.macro this_link + .globl link_\+ +link_\+: +.endm + +.macro prev_link + .int link_\+ +.endm + +.macro link + this_link + prev_link +.endm + +this_link +.int 0 + +.macro defhead name, label, hash, code, flags=0 .section ".rodata" .balign cell .globl name_\label name_\label: - .int name_\last # 1. Link to the previously defined word. + link .int \hash .int meta_\label - .byte \flags # 3. Set the flags. + .byte \flags - .balign cell # 6. Add any padding we may need. + .balign cell .globl \label \label: - .int code_\label # 7. Set the codeword. + .int \code +.endm - .section ".data.meta" +.macro defmeta name, label + .section ".rodata.meta" .global meta_\label meta_\label: - .byte \name_length + .byte length_\@ +1: .ascii "\name" + .equ length_\@, . - 1b +.endm +.macro defcode name, label, hash, flags=0 + defmeta "\name", \label + defhead "\name", \label, \hash, code_\label, flags=\flags .section ".text" .globl code_\label -code_\label: # 8. This is where our assembly code will go. +code_\label: .endm -.macro defword name, name_length, flags, hash, label, last - .section ".rodata" - .balign cell - .globl name_\label -name_\label: - .int name_\last - .int \hash - .int meta_\label - .byte \flags - - .section ".data.meta" - .global meta_\label -meta_\label: - .byte \name_length - .ascii "\name" - - .section ".rodata" - .balign cell - .globl \label -\label: - .int docol +.macro defword name, label, hash, flags=0 + defmeta "\name", \label + defhead "\name", \label, \hash, docol, flags=\flags .endm docol: @@ -129,29 +139,27 @@ docon: push w next -.equ name_null, 0 - -defcode "exit", 4, 0, 0xCDED1A85, exit, null +defcode "exit", exit, 0xCDED1A85 pop_ret ip next -defcode "type", 4, 0, 0x5127F14D, type, exit +defcode "type", type, 0x5127F14D pop a1 # length pop a0 # address jal uart_put_string next -defcode "emit", 4, 0, 0x2D88474A, emit, type +defcode "emit", emit, 0x2D88474A pop a0 jal uart_put_char next -defcode "key", 3, 0, 0x6815C86C, key, emit +defcode "key", key, 0x6815C86C jal uart_get_char push a0 next -defcode "accept", 6, 0, 0x08247E29, accept, key +defcode "accept", accept, 0x08247E29 pop w # max len pop x # address jal accept_impl @@ -180,7 +188,7 @@ accept_impl: pop_ret ra ret -defword "refill", 6, 0, 0x238BAA91, refill, accept +defword "refill", refill, 0x238BAA91 .int source_id, fetch, q_branch, _refill_tib _refill_fib: .int fib, read_line, q_branch, _refill_failed @@ -198,7 +206,7 @@ _refill_failed: .int drop, lit, 0 .int exit -defcode "source", 6, 0, 0x1BCF29D8, source, refill +defcode "source", source, 0x1BCF29D8 la w, _source load_cell w, 0(w) la x, _source_len @@ -207,27 +215,27 @@ defcode "source", 6, 0, 0x1BCF29D8, source, refill push x next -defcode "source-addr", 11, 0, 0x997F9EE8, source_addr, source +defcode "source-addr", source_addr, 0x997F9EE8 la w, _source push w next -defcode "source-len", 10, 0, 0x1B513E8E, source_len, source_addr +defcode "source-len", source_len, 0x1B513E8E la w, _source_len push w next -defcode "source-offset", 13, 0, 0x7F8C1674, source_offset, source_len +defcode "source-offset", source_offset, 0x7F8C1674 la w, _input_offset push w next -defcode "source-id", 9, 0, 0x965ED1E2, source_id, source_offset +defcode "source-id", source_id, 0x965ED1E2 la w, _source_id push w next -defcode "tib", 3, 0, 0xC90B0194, tib, source_id +defcode "tib", tib, 0xC90B0194 # ( -- addr len ) la w, _tib push w @@ -236,7 +244,7 @@ defcode "tib", 3, 0, 0xC90B0194, tib, source_id push w next -defcode "fib", 3, 0, 0xBCE49236, fib, tib +defcode "fib", fib, 0xBCE49236 # ( -- addr len ) la w, _fib push w @@ -245,7 +253,7 @@ defcode "fib", 3, 0, 0xBCE49236, fib, tib push w next -defcode "parse-key" 9, 0, 0xB78FDA4A, parse_key, fib +defcode "parse-key", parse_key, 0xB78FDA4A la w, _source load_cell w, 0(w) la x, _source_len @@ -266,7 +274,7 @@ defcode "parse-key" 9, 0, 0xB78FDA4A, parse_key, fib mv t0, zero j 1b -defcode "parse-char", 10, 0, 0xDF4F729B, parse_char, parse_key +defcode "parse-char", parse_char, 0xDF4F729B la w, _source load_cell w, 0(w) la x, _source_len @@ -295,7 +303,7 @@ defcode "parse-char", 10, 0, 0xDF4F729B, parse_char, parse_key mv t0, zero j 2b -defcode "parse-word", 10, 0, 0xB218226F, parse_word, parse_char +defcode "parse-word", parse_word, 0xB218226F la w, _source load_cell w, 0(w) # buff addr la x, _source_len @@ -333,7 +341,7 @@ defcode "parse-word", 10, 0, 0xB218226F, parse_word, parse_char push x # word len next -defcode ">number", 7, 0, 0x2F770E4C, to_number, parse_word +defcode ">number", to_number, 0x2F770E4C pop x # word len pop w # word addr mv y, zero # initial value @@ -388,13 +396,13 @@ _to_number_done: push x next -defcode "word>hash", 9, 0, 0x50E0A245, word_to_hash, to_number +defcode "word>hash", word_to_hash, 0x50E0A245 pop w # word address load_cell w, hash_offset(w) push w # word hash next -defword "find", 4, 0, 0xBDF0855A, find, word_to_hash +defword "find", find, 0xBDF0855A .int hash .int latest, fetch _find_loop: @@ -408,19 +416,19 @@ _find_next_word: .int fetch .int branch, _find_loop -defcode ">cfa", 4, 0, 0x8CAC3233, to_cfa, find +defcode ">cfa", to_cfa, 0x8CAC3233 pop w addi w, w, code_offset push w next -defcode "execute", 7, 0, 0xA01E3D98, execute, to_cfa +defcode "execute", execute, 0xA01E3D98 pop w load_cell x, 0(w) jr x # 'next' should be called by the executed word -defword "interpret", 9, 0, 0x1F98C57A, interpret, execute +defword "interpret", interpret, 0x1F98C57A _interpret_start: .int parse_word, q_dup, q_branch, _interpret_parse_area_empty .int two_dup @@ -443,7 +451,7 @@ _interpret_retry: _interpret_parse_area_empty: .int drop, exit -defword "evaluate", 8, 0, 0xACE4360A, evaluate, interpret +defword "evaluate", evaluate, 0xACE4360A .int lit, 1, source_id, store _evaluate_loop: .int refill, q_branch, _evaluate_done @@ -453,12 +461,12 @@ _evaluate_done: .int lit, 0, source_id, store .int exit -defcode "branch", 6, 0, 0xB6873945, branch, evaluate +defcode "branch", branch, 0xB6873945 load_cell w, 0(ip) mv ip, w next -defcode "?branch", 7, 0, 0x6AF3C1DE, q_branch, branch +defcode "?branch", q_branch, 0x6AF3C1DE pop w bnez w, _branch_done load_cell w, 0(ip) @@ -468,19 +476,19 @@ _branch_done: addi ip, ip, cell next -defcode "prompt", 6, 0, 0xDFE6493B, prompt, q_branch +defcode "prompt", prompt, 0xDFE6493B la w, _prompt la x, _prompt_len call uart_put_string next -defcode "okay", 6, 0, 0xBA9EEB49, okay, prompt +defcode "okay", okay, 0xBA9EEB49 la w, _okay la x, _okay_len call uart_put_string next -defword "quit", 4, 0, 0x47878736, quit, okay +defword "quit", quit, 0x47878736 _quit_top: .int rp_top, rp_store .int prompt @@ -488,38 +496,38 @@ _quit_top: .int interpret, okay .int branch, _quit_top -defword "abort", 5, 0, 0xA52BCAF9, abort, quit +defword "abort", abort, 0xA52BCAF9 .int sp_top, sp_store, quit # ----------------------------------------------------------------------------- # memory access # ----------------------------------------------------------------------------- -defcode "!", 1, 0, 0x240C8DEC, store, abort +defcode "!", store, 0x240C8DEC pop w # address pop x # value store_cell x, 0(w) next -defcode "@", 1, 0, 0xC50BF85F, fetch, store +defcode "@", fetch, 0xC50BF85F pop w # address load_cell x, 0(w) push x next -defcode "c!", 2, 0, 0x9829F909, char_store, fetch +defcode "c!", char_store, 0x9829F909 pop w pop x sb x, 0(w) next -defcode "c@", 2, 0, 0x37296056, char_fetch, char_store +defcode "c@", char_fetch, 0x37296056 pop w lb x, 0(w) push x next -defcode "+!", 2, 0, 0x08DC01D1, add_store, char_fetch +defcode "+!", add_store, 0x08DC01D1 pop w # address pop x # value to add load_cell t0, 0(w) @@ -527,7 +535,7 @@ defcode "+!", 2, 0, 0x08DC01D1, add_store, char_fetch store_cell t0, 0(w) next -defcode "-!", 2, 0, 0x24CD235B, sub_store, add_store +defcode "-!", sub_store, 0x24CD235B pop w # address pop x # value to add load_cell t0, 0(w) @@ -535,14 +543,14 @@ defcode "-!", 2, 0, 0x24CD235B, sub_store, add_store store_cell t0, 0(w) next -defcode "cells", 5, 0, 0xD94ACBB2, cells, sub_store +defcode "cells", cells, 0xD94ACBB2 pop w li x, cell mul w, w, x push w next -defcode "cell+", 5, 0, 0xB14A8CBA, cell_plus, cells +defcode "cell+", cell_plus, 0xB14A8CBA pop w addi w, w, cell push w @@ -552,29 +560,29 @@ defcode "cell+", 5, 0, 0xB14A8CBA, cell_plus, cells # dictionary management # ----------------------------------------------------------------------------- -defcode "dp", 2, 0, 0x491CB0B9, dp, cell_plus +defcode "dp", dp, 0x491CB0B9 la w, _here push w next -defcode "here", 4, 0, 0x213B65CB, here, dp +defcode "here", here, 0x213B65CB la w, _here load_cell x, 0(w) push x next -defcode "latest", 6, 0, 0x41704246, latest, here +defcode "latest", latest, 0x41704246 la w, _latest push w next -defcode "lit", 3, 0, 0x404CD5B6, lit, latest +defcode "lit", lit, 0x404CD5B6 load_cell w, 0(ip) addi ip, ip, cell push w next -defcode "lit-string", 10, 0, 0xC7BE567C, lit_string, lit +defcode "lit-string", lit_string, 0xC7BE567C load_cell x, 0(ip) # len addi ip, ip, cell mv w, ip # addr @@ -586,21 +594,21 @@ defcode "lit-string", 10, 0, 0xC7BE567C, lit_string, lit push x next -defword "allot", 5, 0, 0xADB1A69F, allot, lit_string +defword "allot", allot, 0xADB1A69F .int dp, add_store .int exit -defword ",", 1, 0, 0x290C95CB, comma, allot +defword ",", comma, 0x290C95CB .int here, store # store value .int lit, cell, allot # increment 'here' .int exit -defword "c,", 2, 0, 0xA32A0A5A, char_comma, comma +defword "c,", char_comma, 0xA32A0A5A .int here, char_store # store value .int lit, 1, allot # increment 'here' .int exit -defcode "align", 5, 0, 0x602C63DE, align, char_comma +defcode "align", align, 0x602C63DE la w, _here load_cell x, 0(w) addi x, x, 3 @@ -612,76 +620,76 @@ defcode "align", 5, 0, 0x602C63DE, align, char_comma # stack manipulation # ----------------------------------------------------------------------------- -defcode "sp0", 3, 0, 0x0C41B8B2, sp_top, align +defcode "sp0", sp_top, 0x0C41B8B2 # ( -- addr ) la w, __stacktop push w next -defcode "sp@", 3, 0, 0xFC419F82, sp_fetch, sp_top +defcode "sp@", sp_fetch, 0xFC419F82 # ( -- addr ) mv w, psp push w next -defcode "sp!", 3, 0, 0x1D41D375, sp_store, sp_fetch +defcode "sp!", sp_store, 0x1D41D375 # ( addr -- ) pop w mv psp, w next -defcode "rp0", 3, 0, 0x8AD91EDD, rp_top, sp_store +defcode "rp0", rp_top, 0x8AD91EDD # ( -- addr ) la w, __stacktop_ret push w next -defcode "rp@", 3, 0, 0x7AD905AD, rp_fetch, rp_top +defcode "rp@", rp_fetch, 0x7AD905AD # ( -- addr ) mv w, rsp push w next -defcode "rp!", 3, 0, 0x99D9367A, rp_store, rp_fetch +defcode "rp!", rp_store, 0x99D9367A # ( addr -- ) pop w mv rsp, w next -defcode "dup", 3, 0, 0xD330F226, dup, rp_store +defcode "dup", dup, 0xD330F226 load_cell w, 0(psp) push w next -defcode "?dup", 4, 0, 0xFD2928D3, q_dup, dup +defcode "?dup", q_dup, 0xFD2928D3 load_cell w, 0(psp) beqz w, _q_dup_done push w _q_dup_done: next -defcode "swap", 4, 0, 0x64ED874E, swap, q_dup +defcode "swap", swap, 0x64ED874E pop w pop x push w push x next -defcode "drop", 4, 0, 0xA9A58D8C, drop, swap +defcode "drop", drop, 0xA9A58D8C pop zero next -defcode "over", 4, 0, 0x31F6520F, over, drop +defcode "over", over, 0x31F6520F load_cell w, cell(psp) push w next -defcode "nip", 3, 0, 0x21A41868, nip, over +defcode "nip", nip, 0x21A41868 pop w store_cell w, 0(psp) next -defcode "2dup", 3, 0, 0x5E46F4D6, two_dup, nip +defcode "2dup", two_dup, 0x5E46F4D6 load_cell w, 0(psp) load_cell x, cell(psp) push x @@ -692,42 +700,42 @@ defcode "2dup", 3, 0, 0x5E46F4D6, two_dup, nip # math and logic # ----------------------------------------------------------------------------- -defcode "+", 1, 0, 0x2E0C9DAA, plus, two_dup +defcode "+", plus, 0x2E0C9DAA pop w pop x add w, w, x push w next -defcode "-", 1, 0, 0x280C9438, minus, plus +defcode "-", minus, 0x280C9438 pop x pop w sub w, w, x push w next -defcode "*", 1, 0, 0x2F0C9F3D, times, minus +defcode "*", times, 0x2F0C9F3D pop w pop x mul w, w, x push w next -defcode "or", 2, 0, 0x5D342984, or_, minus +defcode "or", or_, 0x5D342984 pop w pop x or w, w, x push w next -defcode "and", 3, 0, 0x0F29C2A6, and_, or_ +defcode "and", and_, 0x0F29C2A6 pop w pop x and w, w, x push w next -defcode "aligned", 7, 0, 0xC73174DF, aligned, and_ +defcode "aligned", aligned, 0xC73174DF pop w addi w, w, 3 andi w, w, 0xFFFFFFFC @@ -738,7 +746,7 @@ defcode "aligned", 7, 0, 0xC73174DF, aligned, and_ # comparison # ----------------------------------------------------------------------------- -defcode "0=", 2, 0, 0x14ED5DD6, zero_equal, aligned +defcode "0=", zero_equal, 0x14ED5DD6 pop w mv x, zero bnez w, _zero_done @@ -747,7 +755,7 @@ _zero_done: push x next -defcode "=", 1, 0, 0x380CAD68, equal, zero_equal +defcode "=", equal, 0x380CAD68 pop w pop x beq w, x, _equal @@ -757,7 +765,7 @@ _equal: push_imm -1 next -defcode "<>", 2, 0, 0x93F7201F, not_equal, equal +defcode "<>", not_equal, 0x93F7201F pop w pop x bne w, x, _not_equal @@ -767,7 +775,7 @@ _not_equal: push_imm -1 next -defcode ">", 1, 0, 0x3B0CB221, greater_than, not_equal +defcode ">", greater_than, 0x3B0CB221 pop w pop x bgt x, w, _greater_than @@ -777,7 +785,7 @@ _greater_than: push_imm -1 next -defcode "<", 1, 0, 0x390CAEFB, less_than, greater_than +defcode "<", less_than, 0x390CAEFB pop w pop x blt x, w, _less_than @@ -791,7 +799,7 @@ _less_than: # compiler # ----------------------------------------------------------------------------- -defword "create", 6, 0, 0x26BB595D, create, less_than +defword "create", create, 0x26BB595D .int parse_word .int latest, fetch, comma # link .int hash, comma # hash @@ -802,7 +810,7 @@ defword "create", 6, 0, 0x26BB595D, create, less_than .int lit, dovar, comma .int exit -defcode "hash", 4, 0, 0xEDBF0FE3, hash, create +defcode "hash", hash, 0xEDBF0FE3 pop x # string length pop w # string address jal hash_impl @@ -822,19 +830,19 @@ _hash_char: mv w, t0 ret -defcode "[", 1, flag_immediate, 0xDE0C1FBA, l_bracket, hash +defcode "[", l_bracket, 0xDE0C1FBA, flags=flag_immediate la w, _state li x, state_immediate store_cell x, 0(w) next -defcode "]", 1, 0, 0xD80C1648, r_bracket, l_bracket +defcode "]", r_bracket, 0xD80C1648 la w, _state li x, state_compile store_cell x, 0(w) next -defcode "hidden", 6, 0, 0xF618F139, hidden, r_bracket +defcode "hidden", hidden, 0xF618F139 pop w addi w, w, flag_offset lb x, 0(w) @@ -842,7 +850,7 @@ defcode "hidden", 6, 0, 0xF618F139, hidden, r_bracket sb x, 0(w) next -defword ":", 1, 0, 0x3F0CB86D, colon, hidden +defword ":", colon, 0x3F0CB86D .int create # create header .int lit, -cell, allot .int lit, docol, comma # append 'docol' @@ -850,20 +858,20 @@ defword ":", 1, 0, 0x3F0CB86D, colon, hidden .int r_bracket # enter 'compile' mode .int exit -defword ";", 1, flag_immediate, 0x3E0CB6DA, semicolon, colon +defword ";", semicolon, 0x3E0CB6DA, flags=flag_immediate .int lit, exit, comma # append 'exit' .int latest, fetch, hidden # show word .int l_bracket # enter 'immediate' mode .int exit -defcode "compiling?", 10, 0, 0x94652AE2, compiling_q, semicolon +defcode "compiling?", compiling_q, 0x94652AE2 la w, _state load_cell w, 0(w) andi w, w, state_compile push w next -defcode "immediate?", 10, 0, 0x89F23E9F, immediate_q, compiling_q +defcode "immediate?", immediate_q, 0x89F23E9F pop w addi w, w, flag_offset - code_offset lb w, 0(w) @@ -871,7 +879,7 @@ defcode "immediate?", 10, 0, 0x89F23E9F, immediate_q, compiling_q push w next -defword "postpone", 8, flag_immediate, 0x933F531F, postpone, immediate_q +defword "postpone", postpone, 0x933F531F, flags=flag_immediate .int parse_word, find # TODO: was word actually found? .int to_cfa, dup .int immediate_q, q_branch, _postpone_compile @@ -882,25 +890,25 @@ _postpone_compile: # stores "lit <xt> ," into the current definition .int lit, lit, comma, comma, lit, comma, comma, exit -defword "immediate", 9, 0, 0xF232267A, immediate, postpone +defword "immediate", immediate, 0xF232267A .int latest, fetch, lit, flag_offset, plus, dup .int fetch, lit, flag_immediate, or_ .int swap, store .int exit -defword "variable", 8, 0, 0x19385305, variable, immediate +defword "variable", variable, 0x19385305 .int create # create header .int lit, 0, comma # initialize to zero .int exit -defword "constant", 8, 0, 0x0691EA25, constant, variable +defword "constant", constant, 0x0691EA25 .int create # create header .int lit, -cell, allot .int lit, docon, comma # append 'docon' .int comma # initialize to value on stack .int exit -defcode "read-char", 10, 0, 0xF07E2044, read_char, variable +defcode "read-char", read_char, 0xF07E2044 jal _read_char_impl push w next @@ -926,27 +934,27 @@ _read_char_eof: mv w, zero ret -defword "buffer-open", 11, 0, 0x79AAD9CA, buffer_open, read_char +defword "buffer-open", buffer_open, 0x79AAD9CA # ( addr len -- addr end-addr cur-addr ) .int over, plus, over .int exit -defword "buffer-close", 12, 0, 0x42B7429E, buffer_close, buffer_open +defword "buffer-close", buffer_close, 0x42B7429E # ( open-buffer -- len ) .int nip, swap, minus .int exit -defword "buffer-emit", 11, 0, 0xEA240555, buffer_emit, buffer_close +defword "buffer-emit", buffer_emit, 0xEA240555 # ( open-buffer char -- open-buffer ) .int over, store, lit, 1, plus .int exit -defword "buffer-full?", 12, 0, 0x070A2E6C, buffer_full_q, buffer_emit +defword "buffer-full?", buffer_full_q, 0x070A2E6C # ( open-buffer -- flag ) .int two_dup, greater_than # TODO: >= .int exit -defword "read-line", 10, 0, 0xAF1308A2, read_line, buffer_full_q +defword "read-line", read_line, 0xAF1308A2 .int buffer_open _read_line_loop: .int read_char @@ -984,7 +992,7 @@ _okay: word_buffer: .space 255 .balign cell -_latest: .int name_constant +_latest: prev_link _here: .int __here_start _meta: .int __meta_start