1 ; This is a forth interpreter for x86_64 (elf64)
2 format elf64 executable
5 ;;; ========================================
6 ;;; The pushr macro pushes x onto the return stack
7 ;;; The popr macro pops x from the return stack
18 ;;; ========================================
19 ;;; The next macro "moves" execution to the next FORTH instruction,
20 ;;; using rsi as instruction pointer. It points to the doer field of a
21 ;;; word, which points to the assembly code that implements the
22 ;;; execution effect of the word. That doer code is entered with rsi
23 ;;; referring to the subsequent address in the colling word, and rax
24 ;;; referring to the doer field of the called word.
27 lodsq ; mov rax, [rsi] + add rsi,8
28 jmp qword [rax] ; goto code of that FORTH word (64 bit jump)
31 ;;; ========================================
32 ;;; The FORTH macro transitions to inline FORTH execution.
41 ;;; ========================================
42 ;;; The ENDFORTH macro transitions back to inline assembler after FORTH
43 ;;; ========================================
48 ;;; ========================================
49 ;;; The DOFORTH lays out a single FORTH call
50 ;;; ========================================
57 ;;; Macro WORD starts a FORTH word definition in this code
59 previous_word = 0 ; Used for chaining the words
61 IMMEDIATE = 1 ; optional flag
63 macro WORD label, name, doer, flags {
68 previous_word = label#_TFA
78 dq 0 ; The DOES offset. Defaults to 0.
79 ;; also CFA = pointer to "doer"
94 ;;; ============================================================
95 ;;; FORTH machine model
96 ;;; rsp = data stack pointer
97 ;;; rbp = return stack pointer
98 ;;; rsi = instruction pointer
100 ;;; ============================================================
102 segment readable writable executable
104 WORD return_stack,'RS',dovariable
106 rb 1048576 ; 1 Mb return stack
107 RS_TOP: ; The initial rbp
109 WORD data_stack,'DS',dovariable
111 rb 1048576 ; 1 Mb data stack
112 DS_TOP: ; The initial rsp
114 WORD inline_code,'[ASM]',fasm
116 ;; This transitions execution into inline assembler in the
117 ;; calling word defintion. Note that it stops advancing rsi;
118 ;; code should use FORTH macro to reenter forth execution, or
119 ;; exit to the calling definition via "jmp exit".
122 ;;; Execution semantics for FORTH defition word
123 ;;; At entry, rsi points into the calling definition, at the cell
124 ;;; following the cell indicating this word, rax points to the CFA of
128 lea rsi, [rax+8] ; rsi = the DFA of the rax word
131 WORD p_exit, 'EXIT',fasm
132 ;; ( -- ) ( R: addr -- )
133 ;; Returns execution to the calling definition as per the
139 ;; Execution semantics for a variable ( -- addr )
140 ;; rax points to doer field
145 ;; Execution semantics for a constant ( -- v )
146 ;; rax points to doer field
151 ;; Execution semantics for a string constant ( -- addr n )
152 ;; rax points to doer field
160 include 'wordlists.asm'
161 include 'syscalls.asm'
167 WORD p_program_version,'PROGRAM_VERSION',dostring
169 program_version_string:
170 db 'RRQ Forth version 0.1 - 2021-05-13',10
171 length = $ - program_version_string
173 WORD p_stdin,'STDIN',dovalue
174 ;; Initialised to hold a STREAM for fd 0
177 WORD p_quit,'QUIT',fasm
178 ;; QUIT is the program entry point ********************
182 ;; Initialize STREAM STDIN
186 pop qword [p_stdin_DFA]
189 push qword 1 ; ( fd ) =stdout
190 push qword [p_stdin_DFA]
192 dq p_read_word ; ( fd s n )
196 push qword 1 ; stdout
197 push qword program_version_string ; address of string
198 push qword length ; length of string (cheating)
199 DOFORTH sys_write ; printout
200 pop rax ; ignore errors
205 ;; TERMINATE0 terminates the program with code 0
207 WORD terminate, 'TERMINATE',fasm
214 ;; FORTH is the last word of VOCABULARY FORTH
215 WORD forth,'FORTH',dovalue