3607ea8d263f1c1330259e70c5c2dcbbe0ff0d70
[rrq/rrqforth.git] / rrqforth.asm
1 ; This is a forth interpreter for x86_64 (elf64)
2         format elf64 executable
3         entry main
4
5 include 'machine.asm'
6
7 ;;; ============================================================
8
9         segment readable writable executable
10
11 ;;; This is the very first word
12         
13         ;; FORTH is the last word of WORDLIST FORTH
14         WORD p_forth,'FORTH',dovalue
15         ;; ( -- )
16         ;; Change to use this wordlist
17         dq last_forth_word
18         dq inline_code
19         mov rax,qword [p_forth_DFA]
20         mov qword [p_wordlist],rax
21         popr rsi
22         next
23
24         WORD p_syscall,'SYSCALL',dodoes,,,8
25         ;; ( -- )
26         ;; Change to use this wordlist
27         dq last_syscall_word
28         dq inline_code
29         mov rax,qword [p_syscall_DFA]
30         mov qword [p_wordlist],rax
31         popr rsi
32         next
33
34 last_wordlists_word:
35         WORD p_wordlists,'WORDLISTS',dodoes,,,8
36         ;; ( -- )
37         ;; Change to use this wordlist
38         dq p_wordlists_TFA
39         dq inline_code
40         mov rax,qword [p_wordlists_DFA]
41         mov qword [p_wordlist],rax
42         popr rsi
43         next
44         
45 include 'wordlists.asm'
46
47         WORD return_stack,'RS',dovariable
48         ;; The return stack
49         rb 1048576              ; 1 Mb return stack
50 RS_TOP:                         ; The initial rbp
51         
52         WORD data_stack,'DS',dovariable
53         ;; The data stack
54         rb 1048576              ; 1 Mb data stack
55 DS_TOP:                         ; The initial rsp
56
57         WORD inline_code,'[ASM]',fasm
58         ;; ( -- )
59         ;; This transitions execution into inline assembler in the
60         ;; calling word defintion. Note that it stops advancing rsi;
61         ;; code should use FORTH macro to reenter forth execution, or
62         ;; exit to the calling definition via "jmp exit".
63         jmp qword rsi
64
65         WORD p_execute,'EXECUTE',fasm
66         ;; ( tfa -- )
67         ;; Execute the word
68         pop rax
69         tfa2cfa rax
70         jmp qword [rax]         ; goto code of that FORTH word (64 bit jump)
71         
72         WORD p_exit, 'EXIT',fasm
73         ;; ( -- ) ( R: addr -- )
74         ;; Returns execution to the calling definition as per the
75         ;; return stack.
76 exit:
77         popr rsi
78         next
79
80         ;; TERMINATE0 terminates the program with code 0
81         ;; ( -- )
82         WORD terminate, 'TERMINATE0',fasm
83         pop rdx
84 terminate_special:
85         mov eax,60
86         syscall
87
88         WORD p_branch,'BRANCH',fasm
89         ;; ( -- )
90         ;; Using subsequent inline cell as branch offset, branch
91         ;; accordingly
92         add rsi,qword [rsi]     
93         add rsi,8
94         next
95         
96         WORD p_zero_branch,'0BRANCH',fasm
97         ;; ( v -- )
98         ;; Using subsequent inline cell as branch offset, branch
99         ;; accordingly if the stacked value is zero, otherwise just
100         ;; skip over the branch offset
101         pop rax
102         cmp rax,0
103         jne p_zero_branch_SKIP
104         add rsi,qword [rsi]
105 p_zero_branch_SKIP:
106         add rsi,8
107         next
108
109 ;;; Execution semantics for FORTH defition word
110 ;;; At entry, rsi points into the calling definition, at the cell
111 ;;; following the cell indicating this word, rax points to the CFA of
112 ;;; this word.
113 doforth:
114         pushr rsi
115         lea rsi, [rax+8]        ; rsi = the DFA of the rax word
116         next
117
118 ;;; Execution semantics for DOES>
119 ;;; The cell at [cfa-8] holds an adjustment offset.
120 dodoes:
121         pushr rsi
122         lea rsi, [rax+8]        ; rsi = the DFA of the rax word
123         add rsi,[rax-8]         ; adjust rsi to the DOES> part
124         next
125
126         ;; Execution semantics for a variable ( -- addr )
127         ;; rax points to CFA field
128 dovariable:
129         add rax,8
130         push rax
131         next
132
133         ;; Execution semantics for a constant ( -- v )
134         ;; rax points to CFA field
135 dovalue:
136         push qword [rax+8]
137         next
138
139         ;; Execution semantics for a string constant ( -- addr n )
140         ;; rax points to CFA field
141 dostring:
142         cfa2dfa rax
143         pushpname rax
144         next
145
146 include 'memory.asm'
147 include 'stack.asm'
148 include 'math.asm'
149 include 'logic.asm'
150 include 'stdio.asm'
151 include 'compile.asm'
152
153         WORD p_program_version,'PROGRAM_VERSION',dostring
154         STRING 'RRQ Forth version 0.1 - 2021-05-13',10
155
156         WORD p_stdin,'STDIN',dovalue
157         ;; Initialised to hold a STREAM for fd 0
158         dq 0
159
160 ;;; The main entry point.
161 ;;; This word is also the last word before syscalls
162 last_forth_word:
163         WORD p_quit,'QUIT',fasm
164         ;; QUIT is the program entry point ********************
165 main:
166         mov rsp,DS_TOP
167         mov rbp,RS_TOP
168         ;; Initialize STREAM STDIN
169         push 0
170         push 10000
171         DOFORTH p_stream
172         pop qword [p_stdin_DFA]
173
174         ;; Initial blurb
175         FORTH
176         dq p_program_version
177         dq p_tell
178         dq p_stdin
179         dq p_read_word
180         dq p_tell
181         dq p_nl
182         dq p_emit
183         ENDFORTH
184         
185         ;; DOFORTH p_words
186         
187         push 0
188         DOFORTH sys_exit
189
190         previous_word = last_wordlists_word
191
192 include 'syscalls.asm'
193
194         
195 last_word:
196         
197 heap_start:
198         rb 1048576              ; +1 Mb heap
199         rb 1048576              ; +1 Mb heap
200         rb 1048576              ; +1 Mb heap