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 ;;; At fasm compilation: reset previous_word to make a new word list
110 ;;; Words above belong to the SYSTEM wordlist, and the following
111 ;;; belong to the FORTH wordlist.
114 WORD p_system,'SYSTEM',dovariable
116 ;; The SYSTEM word list
117 dq last_system_word ; tfa of last SYSTEM word
118 dq p_forth_DFA ; dfa of successor word list
120 WORD inline_code,'[ASM]',fasm
122 ;; This transitions execution into inline assembler in the
123 ;; calling word defintion. Note that it stops advancing rsi;
124 ;; code should use FORTH macro to reenter forth execution, or
125 ;; exit to the calling definition via "jmp exit".
128 WORD p_execute,'EXECUTE',fasm
132 jmp qword [rax] ; goto code of that FORTH word (64 bit jump)
134 WORD p_exit, 'EXIT',fasm
135 ;; ( -- ) ( R: addr -- )
136 ;; Returns execution to the calling definition as per the
142 ;; TERMINATE0 terminates the program with code 0
144 WORD p_terminate, 'TERMINATE0',fasm
150 ;;; ========================================
151 ;;; Core extension(s)
153 ;segment readable writable executable
155 include 'control.asm'
156 include 'wordlists.asm'
162 include 'compile.asm'
164 WORD p_program_version,'PROGRAM_VERSION',dostring
165 STRING 'RRQ Forth version 0.1 - 2021-05-22',10
167 WORD p_stdin,'STDIN',dovalue
168 ;; Initialised to hold a STREAM for fd 0
171 WORD p_args,'MAIN-ARGS',dovalue
172 ;; Pointer to initial argument block
173 dq 0 ; *(int argc,(char*[argc]) argv)
175 WORD p_verboseQ,'VERBOSE?',dovariable
176 ;; Flags whether the running is in verbose mode ot not
179 WORD p_lparen,'(',fasm,IMMEDIATE
182 DOFORTH p_stdin, p_read_word
185 cmp rax,0 ; end of stream
200 ;;; ******** The main entry point. ********
201 ;;; This could be set up as a WORD but it isn't
204 ;; Initial rsp points to the arguments block of size (64 bits)
205 ;; followed by the argument pointers.
206 mov qword [p_args_DFA],rsp
208 mov qword [p_verboseQ_DFA],rdx
209 jmp p_quit_DFA ; QUIT
211 ;; Subroutine to check the command line for a "-v"
212 ;; return boolean in rdx
213 ;; implementation for that 2 byte asciiz string
214 main_is_verbose_data:
215 dq main_is_verbose_data_end - $ ; length of data
217 main_is_verbose_data_end:
220 mov rbx,qword [p_args_DFA] ; Pointer to main arguments
224 main_is_verbose_next:
226 jl main_is_not_verbose
229 mov rdi,main_is_verbose_data
232 main_is_verbose_loop:
234 jne main_is_verbose_next
236 jg 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
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