1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
|
; jewelforth
;; MACROS {{{
%macro pspush 1
lea r14, [r14-8]
mov qword [r14], %1
%endmacro
%macro pspop 1
mov %1, qword [r14]
lea r14, [r14+8]
%endmacro
;;; dictionary macros {{{
%define mac_latest 0 ; updated through defdict
%macro defdict 3 ; name asm-label flags
%strlen slen %1
global lfa_%2
lfa_%2: dq mac_latest
%define mac_latest lfa_%2
ffa_%2: db %3 ; FFA
nfa_%2: dw slen ; NFA
db %1
%endmacro
%macro defword 3
defdict %1, %2, %3
%2:
%endmacro
%macro defconst 4 ; ... value
defdict %1, %2, %3
%define %2 %4
pspush qword %4
ret
%endmacro
%macro defvar 4 ; ... default-value
%2: dq %4
defdict %1, %2, %3
pspush qword %2
ret
%endmacro
%assign smudge_mask 0x1
%assign immemdiate_mask 0x2
;;; }}}
;; syscall
%assign __NR_read 0
%assign __NR_write 1
%assign __NR_brk 12
%assign __NR_exit 60
;; }}}
section .bss
wstack_b: resq 2047
wstack: resq 1
section .text
global _start
_start:
; init
mov r14, wstack ; point SP to top
mov rdi, 0
mov rax, __NR_exit
syscall
defword "bye", bye, 0
mov rdi, 0
mov rax, __NR_exit
syscall
ret ; will not be reached
defword "@", fetch, 0
pspop r11
mov r12, qword [r11]
pspush r12
ret
defword "c@", cfetch, 0
pspop r11
xor r12, r12
mov r12b, [r11]
pspush r12
ret
defword "!", store, 0
pspop r11
pspop r12
mov qword [r11], r12
ret
defword "c!", cstore, 0
pspop r11
pspop r12
mov [r11], r12b
ret
; stage 1 parser. very rudimentary, does not recognise numbers,
; only recognises newlines and spaces as whitespace.
; since it will only parse a little bit of the init file
; there won't be any error checking either.
defword "parse", parse, 0
mov r13, qword [to_in]
add r13, initfile
mov r12b, byte [r13]
.wsloop: ; skip initial ws
cmp r12b, 0x20
je .wsloop_cont
cmp r12b, 0x0a
jne .wordloop_start
.wsloop_cont:
inc r13
mov r12b, byte [r13]
jmp .wsloop
.wordloop_start:
push r13 ; keep start address of this word for later
mov r11, 1 ; W: word length count
.wordloop:
cmp r12b, 0x20
je .wordloop_end
cmp r12b, 0x0a
je .wordloop_end
inc r11
inc r13
mov r12b, byte [r13]
jmp .wordloop
.wordloop_end:
sub r13, initfile
mov qword [to_in], r13
pop r13
pspush r13 ; c-addr
pspush r11 ; u
ret
defword "find", find, 0
ret
; stage 1 interpreter, just reads from initfile
defword "interpret", interpret, 0
ret
defvar ">in", to_in, 0, initfile
initfile:
incbin "jefs.fs"
initlen equ $ - initfile
initfile_end:
|