1 ; This is a forth interpreter for x86_64 (elf64)
2 format elf64 executable
7 ;;; ============================================================
9 segment readable writable executable
11 ;;; ========================================
12 ;;; These are the core "execution semantics" words, which are placed
13 ;;; first so as to remain at the same binary address at successive
14 ;;; compilations, which is helful for declaring special debugging gdb
17 ;;; The DO* words are declared as "variables" to provide their
18 ;;; assembled address when used in FORTH.
20 ;;; The register context at entry to an "execution semantcs" code
22 ;;; rax = cfa* of word to execute
23 ;;; rsi = cell* in the calling definition, after calling cell
24 ;;; rsp = data stack pointer
25 ;;; rbp = return stack pointer
28 previous_word = 0 ; Used for chaining the words
30 WORD p_dofasm,'doFASM',dovariable
31 ;; Execution semantics for assembly words.
36 WORD p_doforth,'doFORTH',dovariable ;
37 ;; Execution semantics for FORTH defition word.
40 lea rsi, [rax+8] ; rsi = the DFA of the rax word
43 WORD p_dodoes,'doDOES',dovariable
44 ;; Execution semantics for DOES>
45 ;; [cfa-8] holds the adjustment offset ("does offset")
48 lea rsi, [rax+8] ; rsi = the DFA of the rax word
49 add rsi,qword [rax-8] ; adjust rsi by the "does offset'
52 WORD p_dovariable,'doVARIABLE',dovariable
53 ;; Execution semantics for a variable ( -- addr )
54 ;; rax points to CFA field
56 lea rax, [rax+8] ; rsi = the DFA of the rax word
60 WORD p_dovalue,'doVALUE',dovariable
61 ;; Execution semantics for a value constant ( -- v )
62 ;; rax points to CFA field
64 lea rax, [rax+8] ; rsi = the DFA of the rax word
68 WORD p_dostring,'doSTRING',dovariable
69 ;; Execution semantics for a string constant ( -- addr n )
70 ;; rax points to CFA field
72 lea rax, [rax+8] ; rsi = the DFA of the rax word
76 WORD p_calltrace,'[calltrace]',dovalue
77 ;; Common call point for debugging
78 ;; rax = cfa of called word
79 ;; rsi = cell* of next forth word
80 ;; [$rsp] = from where the call was
83 include 'syscalls.asm'
85 ;;; ========================================
86 ;;; The stacks are placed here.
88 ;segment readable writable
90 WORD return_stack,'RETURN-STACK',dovariable
93 rb 1048576 ; 1 Mb return stack
94 RS_TOP: ; The initial rbp
97 WORD data_stack,'DATA-STACK',dovariable
100 rb 1048576 ; 1 Mb data stack
101 DS_TOP: ; The initial rsp
104 ;;; ========================================
105 ;;; Core execution control words
107 ;segment readable executable
109 include 'signals.asm'
111 ;;; At fasm compilation: reset previous_word to make a new word list
112 ;;; Words above belong to the SYSTEM wordlist, and the following
113 ;;; belong to the FORTH wordlist.
116 WORD p_system,'SYSTEM',dovariable
118 ;; The SYSTEM word list
119 dq last_system_word ; tfa of last SYSTEM word
120 dq p_forth_DFA ; dfa of successor word list
122 WORD inline_code,'[ASM]',fasm
124 ;; This transitions execution into inline assembler in the
125 ;; calling word defintion. Note that it stops advancing rsi;
126 ;; code should use FORTH macro to reenter forth execution, or
127 ;; exit to the calling definition via "jmp exit".
130 WORD p_execute,'EXECUTE',fasm
134 jmp qword [rax] ; goto code of that FORTH word (64 bit jump)
136 WORD p_exit, 'EXIT',fasm
137 ;; ( -- ) ( R: addr -- )
138 ;; Returns execution to the calling definition as per the
144 ;; TERMINATE0 terminates the program with code 0
146 WORD p_terminate, 'TERMINATE0',fasm
152 ;;; ========================================
153 ;;; Core extension(s)
155 ;segment readable writable executable
157 include 'control.asm'
158 include 'wordlists.asm'
164 include 'compile.asm'
166 WORD p_program_version,'PROGRAM_VERSION',dostring
167 STRING 'RRQ Forth version 0.1 - 2021-05-22',10
169 WORD p_stdin,'STDIN',dovalue
170 ;; Initialised to hold a STREAM for fd 0
173 WORD p_args,'MAIN-ARGS',dovalue
174 ;; Pointer to initial argument block
175 dq 0 ; *(int argc,(char*[argc]) argv)
177 WORD p_verboseQ,'VERBOSE?',dovariable
178 ;; Flags whether the running is in verbose mode ot not
181 WORD p_lparen,'(',fasm,IMMEDIATE
184 DOFORTH p_stdin, p_read_word
187 cmp rax,0 ; end of stream
202 ;;; ******** The main entry point. ********
203 ;;; This could be set up as a WORD but it isn't
206 ;; Initial rsp points to the arguments block of size (64 bits)
207 ;; followed by the argument pointers.
208 mov qword [p_args_DFA],rsp
210 call p_setup_signals_DFA
212 mov qword [p_verboseQ_DFA],rdx
213 jmp p_quit_DFA ; QUIT
215 ;; Subroutine to check the command line for a "-v"
216 ;; return boolean in rdx
217 ;; implementation for that 2 byte asciiz string
218 main_is_verbose_data:
222 mov rbx,qword [p_args_DFA] ; Pointer to main arguments
223 mov r8,qword [rbx] ; r8 = count of pointers
226 main_is_verbose_next:
228 jl main_is_not_verbose
231 mov rdi,main_is_verbose_data
232 main_is_verbose_loop:
234 jne main_is_verbose_next
236 jne main_is_verbose_loop
241 ;;; This word is also the last word before syscalls
243 WORD p_quit,'QUIT',fasm
244 ;; QUIT is the program entry point ********************
248 cmp qword [p_stdin_DFA],0
249 jne p_quit_INITIALIZED
254 pop qword [p_stdin_DFA] ; Assign STDIN
267 BRANCH 0,p_quit_ERROR
272 STRING 10,'*** Unknown word: '
281 mov rbp,RS_TOP ; reset the return stack
282 jmp p_quit_INITIALIZED
284 ;;; ========================================
286 ;segment readable writable
289 rb 1048576 ; +1 Mb heap
290 rb 1048576 ; +1 Mb heap
291 rb 1048576 ; +1 Mb heap
292 rb 1048576 ; +1 Mb heap
293 rb 1048576 ; +1 Mb heap