forked from zeroflag/punyforth
-
Notifications
You must be signed in to change notification settings - Fork 0
/
primitives.S
262 lines (219 loc) · 5.24 KB
/
primitives.S
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
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
.intel_syntax noprefix
// Primitives are implemented in assembly language
defprimitive "dup",3,dup,REGULAR /* ( a -- a a ) */
mov eax, [esp]
push eax
NEXT
defprimitive "drop",4,drop,REGULAR /* ( a -- ) */
add esp, CELLS
NEXT
defprimitive "swap",4,swap,REGULAR /* ( a b -- b a ) */
pop eax
pop ebx
push eax
push ebx
NEXT
defprimitive "rot",3,rot,REGULAR /* ( a b c -- b c a ) */
pop ecx
pop ebx
pop eax
push ebx
push ecx
push eax
NEXT
defprimitive "2swap",5,swap2,REGULAR /* ( a b c d -- c d a b ) */
pop edx
pop ecx
pop ebx
pop eax
push ecx
push edx
push eax
push ebx
NEXT
defprimitive "2over",5,over2,REGULAR /* ( a b c d -- a b c d a b ) */
pop edx
pop ecx
pop ebx
pop eax
push eax
push ebx
push ecx
push edx
push eax
push ebx
NEXT
defprimitive "+",1,plus,REGULAR
pop eax
add [esp], eax
NEXT
defprimitive "-",1,minus,REGULAR
pop eax
sub [esp], eax
NEXT
defprimitive "*",1,multiply,REGULAR
pop eax
pop ebx
imul ebx
push eax
NEXT
defprimitive "/mod",4,divmod,REGULAR /* ( n d -- m q ) */
pop ebx
pop eax
xor edx, edx
cdq
idiv ebx
push edx
push eax
NEXT
defprimitive "or",2,or,REGULAR
pop eax
or [esp], eax
NEXT
defprimitive "and",3,and,REGULAR
pop eax
and [esp], eax
NEXT
defprimitive "xor",3,xor,REGULAR
pop eax
xor [esp], eax
NEXT
defprimitive "lshift",6,lshift,REGULAR
pop ecx
pop eax
shl eax, cl
push eax
NEXT
defprimitive "rshift",6,rshift,REGULAR
pop ecx
pop eax
shr eax, cl
push eax
NEXT
defprimitive "_emit",5,uemit,REGULAR
mov edx, 1 // length
mov ecx, esp // emit right off the stack
mov ebx, 1 // stdout
mov eax, 4 // sys_write
int 0x80
pop ebx
NEXT
defprimitive "abort",5,abort,REGULAR
mov esp, [stack_top]
mov eax, 1
int 0x80
defprimitive "@",1,fetch,REGULAR
pop eax
mov ebx, [eax]
push ebx
NEXT
defprimitive "!",1,store,REGULAR
pop edi
pop eax
stosd
NEXT
defprimitive "c!",2,storebyte,REGULAR
pop edi
pop eax
stosb
NEXT
defprimitive "[']",3,btick,REGULAR // compile only
lodsd
push eax
NEXT
defprimitive "<",1,lt,REGULAR // only need to define this, all other comparisions are implemented in terms of lt
pop eax
pop ebx
cmp ebx, eax
setl al
movzbd eax, al
neg eax
push eax
NEXT
defprimitive "invert",6,invert,REGULAR
not dword ptr [esp]
NEXT
defprimitive "branch",6,branch,REGULAR
add esi, dword ptr [esi]
NEXT
defprimitive "branch0",7,branch0,REGULAR
pop eax
test eax, eax
jz code_branch
lodsd // skip the the offs
NEXT
defprimitive ">r",2,rpush,REGULAR
pop eax
sub ebp, CELLS
mov [ebp], eax
NEXT
defprimitive "r>",2,rpop,REGULAR
mov eax, [ebp]
add ebp, CELLS
push eax
NEXT
defprimitive "i",1,i,REGULAR
mov eax, [ebp]
push eax
NEXT
defprimitive "j",1,j,REGULAR
mov eax, [ebp + 2 * CELLS]
push eax
NEXT
defprimitive "execute",7,execute,REGULAR
pop eax
jmp [eax]
// this exit primitive is only used by the compiler, this is used for detecting word endings works some as regular exit
defprimitive "<exit>",6,end_word,REGULAR
mov esi, [ebp]
add ebp, CELLS
NEXT
defprimitive "exit",4,exit,REGULAR
mov esi, [ebp]
add ebp, CELLS
NEXT
defprimitive "sp@",3,spat,REGULAR
push esp
NEXT
defprimitive "sp!",3,spstore,REGULAR
pop esp
NEXT
defprimitive "rp@",3,rpat,REGULAR
push ebp
NEXT
defprimitive "rp!",3,rpstore,REGULAR
pop ebp
NEXT
defprimitive "readchar",8,readchar,REGULAR
xor ebx, ebx // reads from stdin (FD 0)
push ebx // make room for buffer
mov ecx, esp
mov eax, 3 // use syscall 3 (read) to read from stdin
mov edx, 1 // read one character
int 0x80 // invoke system call to read from stdin
cmp eax, 0 // number bytes read
jbe code_abort
NEXT
// Different types of code words
ENTERCOL: // codeword for word (colon) definitions
sub ebp, CELLS
mov [ebp], esi // save esi (forth instruction pointer) to the return stack
add eax, CELLS // eax points to the ENTERCOL, skip this cell
mov esi, eax // set the instruction pointer to the body of this word
NEXT
ENTERDOES:
sub ebp, CELLS
mov [ebp], esi // save esi to return stack
add eax, CELLS // eax points to the codeword field, skip tshi
mov esi, [eax] // after the codeword there is the behaviour pointer
add eax, CELLS // after the behaviour pointer there is the data field
push eax
NEXT // jump to behavour
ENTERCONST:
mov eax, [eax + CELLS]
push eax
NEXT
ENTERVAR:
add eax, CELLS
push eax
NEXT