1 ; This is a forth interpreter for x86_64 (elf64)
2 format elf64 executable
5 previous_word = 0 ; Used for chaining the words
9 ;;; ============================================================
11 segment readable executable
13 ;;; This is the very first word
15 ;; FORTH is the last word of WORDLIST FORTH
16 WORD p_forth,'FORTH',dowordlist
18 ;; Change to use this wordlist
21 WORD p_system,'SYSTEM',dowordlist
23 ;; Change to use this wordlist
27 WORD p_wordlists,'WORDLISTS',dowordlist
29 ;; Change to use this wordlist
32 ;;; ========================================
33 ;;; These are the core "execution semantics" words, which are placed
34 ;;; first so as to remain at the same binary address at successive
35 ;;; compilations, which is helful for declaring special debugging gdb
38 ;;; The DO* words are declared as "variables" to provide their
39 ;;; assembled address when used in FORTH.
41 ;;; The register context at entry to an "execution semantcs" code
43 ;;; rax = cfa* of word to execute
44 ;;; rsi = cell* in the calling definition, after calling cell
45 ;;; rsp = data stack pointer
46 ;;; rbp = return stack pointer
49 WORD p_dofasm,'doFASM',dovariable
50 ;; Execution semantics for assembly words.
55 WORD p_doforth,'doFORTH',dovariable ;
56 ;; Execution semantics for FORTH defition word.
59 lea rsi, [rax+8] ; rsi = the DFA of the rax word
62 WORD p_dodoes,'doDOES',dovariable
63 ;; Execution semantics for DOES>
64 ;; [cfa-8] holds the adjustment offset ("does offset")
67 lea rsi, [rax+8] ; rsi = the DFA of the rax word
68 add rsi,qword [rax-8] ; adjust rsi by the "does offset'
71 WORD p_dovariable,'doVARIABLE',dovariable
72 ;; Execution semantics for a variable ( -- addr )
73 ;; rax points to CFA field
75 lea rax, [rax+8] ; rsi = the DFA of the rax word
79 WORD p_dovalue,'doVALUE',dovariable
80 ;; Execution semantics for a value constant ( -- v )
81 ;; rax points to CFA field
83 lea rax, [rax+8] ; rsi = the DFA of the rax word
87 WORD p_dostring,'doSTRING',dovariable
88 ;; Execution semantics for a string constant ( -- addr n )
89 ;; rax points to CFA field
91 lea rax, [rax+8] ; rsi = the DFA of the rax word
95 WORD p_dowordlist,'doWORDLIST',dovariable
96 ;; Execution semantics for DOES>
97 ;; [cfa-8] holds the adjustment offset ("does offset")
100 lea rsi, [rax+8] ; rsi = the DFA of the rax word
101 add rsi,qword [rax-8] ; adjust rsi by the "does offset'
105 include 'syscalls.asm'
107 ;;; ========================================
108 ;;; The stacks are placed here.
110 segment readable writable
112 WORD return_stack,'RETURN-STACK',dovariable
115 rb 1048576 ; 1 Mb return stack
116 RS_TOP: ; The initial rbp
119 WORD data_stack,'DATA-STACK',dovariable
122 rb 1048576 ; 1 Mb data stack
123 DS_TOP: ; The initial rsp
125 ;;; ========================================
126 ;;; Core execution control words
128 segment readable executable
130 ;;; At fasm compilation: reset previous_word to make a new word list
131 ;;; Words above belong to the SYSTEM wordlist, and the following
132 ;;; belong to the FORTH wordlist.
133 previous_word = last_wordlists_word
135 WORD inline_code,'[ASM]',fasm
137 ;; This transitions execution into inline assembler in the
138 ;; calling word defintion. Note that it stops advancing rsi;
139 ;; code should use FORTH macro to reenter forth execution, or
140 ;; exit to the calling definition via "jmp exit".
143 WORD p_execute,'EXECUTE',fasm
148 jmp qword [rax] ; goto code of that FORTH word (64 bit jump)
150 WORD p_exit, 'EXIT',fasm
151 ;; ( -- ) ( R: addr -- )
152 ;; Returns execution to the calling definition as per the
158 ;; TERMINATE0 terminates the program with code 0
160 WORD p_terminate, 'TERMINATE0',fasm
166 WORD p_branch,'BRANCH',fasm
168 ;; Using subsequent inline cell as branch offset, branch
174 WORD p_zero_branch,'0BRANCH',fasm
176 ;; Using subsequent inline cell as branch offset, branch
177 ;; accordingly if the stacked value is zero, otherwise just
178 ;; skip over the branch offset
181 jne p_zero_branch_SKIP
187 ;;; ========================================
188 ;;; Core extension(s)
190 segment readable writable executable
192 include 'wordlists.asm'
198 include 'compile.asm'
200 WORD p_program_version,'PROGRAM_VERSION',dostring
201 STRING 'RRQ Forth version 0.1 - 2021-05-13',10
203 WORD p_stdin,'STDIN',dovalue
204 ;; Initialised to hold a STREAM for fd 0
207 ;;; The main entry point.
208 ;;; This word is also the last word before syscalls
210 WORD p_quit,'QUIT',fasm
211 ;; QUIT is the program entry point ********************
215 cmp qword [p_stdin_DFA],0
216 jne p_quit_INITIALIZED
221 pop qword [p_stdin_DFA] ; Assign STDIN
232 BRANCH 0,p_quit_ERROR
237 STRING 10,'*** Unknown word: '
246 mov rbp,RS_TOP ; reset the return stack
249 ;;; ========================================
251 segment readable writable
254 rb 1048576 ; +1 Mb heap
255 rb 1048576 ; +1 Mb heap
256 rb 1048576 ; +1 Mb heap
257 rb 1048576 ; +1 Mb heap
258 rb 1048576 ; +1 Mb heap