debugging support
[rrq/rrqforth.git] / rrqforth.asm
1 ; This is a forth interpreter for x86_64 (elf64)
2         format elf64 executable
3         entry main
4
5 previous_word = 0       ; Used for chaining the words
6
7 include 'machine.asm'
8
9 ;;; ============================================================
10
11         segment readable executable
12
13 ;;; This is the very first word
14         
15         ;; FORTH is the last word of WORDLIST FORTH
16         WORD p_forth,'FORTH',dowordlist
17         ;; ( -- )
18         ;; Change to use this wordlist
19         dq last_forth_word
20         dq inline_code
21
22         WORD p_system,'SYSTEM',dowordlist
23         ;; ( -- )
24         ;; Change to use this wordlist
25         dq last_system_word
26         dq inline_code
27
28 last_wordlists_word:
29         WORD p_wordlists,'WORDLISTS',dowordlist
30         ;; ( -- )
31         ;; Change to use this wordlist
32         dq p_wordlists_TFA
33         dq inline_code
34
35 ;;; ========================================
36 ;;; These are the core "execution semantics" words, which are placed
37 ;;; first so as to remain at the same binary address at successive
38 ;;; compilations, which is helful for declaring special debugging gdb
39 ;;; aliases.
40 ;;; 
41 ;;; The DO* words are declared as "variables" to provide their
42 ;;; assembled address when used in FORTH.
43 ;;;
44 ;;; The register context at entry to an "execution semantcs" code
45 ;;; snippets is:
46 ;;; rax = cfa* of word to execute
47 ;;; rsi = cell* in the calling definition, after calling cell
48 ;;; rsp = data stack pointer
49 ;;; rbp = return stack pointer
50 ;;; 
51
52         WORD p_dofasm,'doFASM',dovariable
53         ;; Execution semantics for assembly words.
54 dofasm:
55         add rax,8
56         jmp rax
57
58         WORD p_doforth,'doFORTH',dovariable ;
59         ;; Execution semantics for FORTH defition word.
60 doforth:
61         pushr rsi
62         lea rsi, [rax+8]        ; rsi = the DFA of the rax word
63         next
64
65         WORD p_dodoes,'doDOES',dovariable
66         ;; Execution semantics for DOES>
67         ;; [cfa-8] holds the adjustment offset ("does offset")
68 dodoes:
69         pushr rsi
70         lea rsi, [rax+8]        ; rsi = the DFA of the rax word
71         add rsi,qword [rax-8]   ; adjust rsi by the "does offset'
72         next
73
74         WORD p_dovariable,'doVARIABLE',dovariable
75         ;; Execution semantics for a variable ( -- addr )
76         ;; rax points to CFA field
77 dovariable:
78         lea rax, [rax+8]        ; rsi = the DFA of the rax word
79         push rax
80         next
81
82         WORD p_dovalue,'doVALUE',dovariable
83         ;; Execution semantics for a value constant ( -- v )
84         ;; rax points to CFA field
85 dovalue:
86         lea rax, [rax+8]        ; rsi = the DFA of the rax word
87         push qword [rax]
88         next
89
90         WORD p_dostring,'doSTRING',dovariable
91         ;; Execution semantics for a string constant ( -- addr n )
92         ;; rax points to CFA field
93 dostring:
94         lea rax, [rax+8]        ; rsi = the DFA of the rax word
95         pushpname rax
96         next
97
98         WORD p_dowordlist,'doWORDLIST',dovariable
99         ;; Execution semantics for DOES>
100         ;; [cfa-8] holds the adjustment offset ("does offset")
101 dowordlist:
102         pushr rsi
103         lea rsi, [rax+8]        ; rsi = the DFA of the rax word
104         add rsi,qword [rax-8]   ; adjust rsi by the "does offset'
105         next
106
107
108 include 'syscalls.asm'
109
110 ;;; ========================================
111 ;;; The stacks are placed here.
112         
113         segment readable writable
114
115         WORD return_stack,'RETURN-STACK',dovariable
116         ;; The return stack
117         BLOCK RS_TOP
118         rb 1048576              ; 1 Mb return stack
119 RS_TOP:                         ; The initial rbp
120         
121 last_system_word:
122         WORD data_stack,'DATA-STACK',dovariable
123         ;; The data stack
124         BLOCK DS_TOP
125         rb 1048576              ; 1 Mb data stack
126 DS_TOP:                         ; The initial rsp
127
128 ;;; ========================================
129 ;;; Core execution control words
130
131         segment readable executable
132
133 ; At fasm compilation: reset previous_word to make a new word list
134 previous_word = last_wordlists_word
135
136         WORD inline_code,'[ASM]',fasm
137         ;; ( -- )
138         ;; This transitions execution into inline assembler in the
139         ;; calling word defintion. Note that it stops advancing rsi;
140         ;; code should use FORTH macro to reenter forth execution, or
141         ;; exit to the calling definition via "jmp exit".
142         jmp qword rsi
143
144         WORD p_execute,'EXECUTE',fasm
145         ;; ( tfa -- )
146         ;; Execute the word
147         pop rax
148         tfa2cfa rax
149         jmp qword [rax]         ; goto code of that FORTH word (64 bit jump)
150         
151         WORD p_exit, 'EXIT',fasm
152         ;; ( -- ) ( R: addr -- )
153         ;; Returns execution to the calling definition as per the
154         ;; return stack.
155 exit:
156         popr rsi
157         next
158
159         ;; TERMINATE0 terminates the program with code 0
160         ;; ( -- )
161         WORD p_terminate, 'TERMINATE0',fasm
162         pop rdx
163 terminate_special:
164         mov eax,60
165         syscall
166
167         WORD p_branch,'BRANCH',fasm
168         ;; ( -- )
169         ;; Using subsequent inline cell as branch offset, branch
170         ;; accordingly
171         add rsi,qword [rsi]     
172         add rsi,8
173         next
174         
175         WORD p_zero_branch,'0BRANCH',fasm
176         ;; ( v -- )
177         ;; Using subsequent inline cell as branch offset, branch
178         ;; accordingly if the stacked value is zero, otherwise just
179         ;; skip over the branch offset
180         pop rax
181         cmp rax,0
182         jne p_zero_branch_SKIP
183         add rsi,qword [rsi]
184 p_zero_branch_SKIP:
185         add rsi,8
186         next
187
188 ;;; ========================================
189 ;;; Core extension(s)
190
191         segment readable writable executable
192         
193 include 'wordlists.asm'
194 include 'memory.asm'
195 include 'stack.asm'
196 include 'math.asm'
197 include 'logic.asm'
198 include 'stdio.asm'
199 include 'compile.asm'
200
201         WORD p_program_version,'PROGRAM_VERSION',dostring
202         STRING 'RRQ Forth version 0.1 - 2021-05-13',10
203
204         WORD p_stdin,'STDIN',dovalue
205         ;; Initialised to hold a STREAM for fd 0
206         dq 0
207
208 ;;; The main entry point.
209 ;;; This word is also the last word before syscalls
210 last_forth_word:
211         WORD p_quit,'QUIT',fasm
212         ;; QUIT is the program entry point ********************
213 main:
214         mov rsp,DS_TOP
215         mov rbp,RS_TOP
216         cmp qword [p_stdin_DFA],0
217         jne p_quit_INITIALIZED
218         ;; Initialize STDIN
219         push 0
220         push 10000
221         DOFORTH p_stream
222         pop qword [p_stdin_DFA] ; Assign STDIN
223
224 p_quit_INITIALIZED:
225         ;; Initial blurb
226         FORTH
227         dq p_program_version
228         dq p_tell
229         dq p_stdin
230         dq p_clear_stream
231         dq p_stdin
232         dq p_evaluate_stream
233         BRANCH 0,p_quit_ERROR
234         dq p_false
235         dq sys_exit
236 p_quit_ERROR:
237         dq p_literal_string
238         STRING 10,'*** Unknown word: '
239         dq p_tell
240         dq p_this_word
241         dq p_2get
242         dq p_tell
243         dq p_literal_string
244         STRING 10
245         dq p_tell
246         ENDFORTH
247         mov rbp,RS_TOP          ; reset the return stack
248         jmp main
249
250 ;;; ========================================
251
252         segment readable writable
253         
254 heap_start:
255         rb 1048576              ; +1 Mb heap
256         rb 1048576              ; +1 Mb heap
257         rb 1048576              ; +1 Mb heap
258         rb 1048576              ; +1 Mb heap
259         rb 1048576              ; +1 Mb heap