-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathloops.S
402 lines (358 loc) · 8.96 KB
/
loops.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
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
# offset for jumping
.equ CREATEOFFSET, 40
CODEHEADER EMIT, CONSTANT, 0x01
li a0, 1
mv a1, sp
li a2, 1
call write
addi sp, sp, STACKOFFSET
tail NEXT
CODEHEADER _J, EMIT, 0x0
ld t0, 24(s10)
PUSH t0
tail NEXT
CODEHEADER _I, _J, 0x0
ld t0, 0(s10)
PUSH t0
tail NEXT
CODEHEADER _LEAVE, _I, 0x0
addi s10, s10, 24 #unloop first
la t0, WA__LOOP
la t1, WA__PLUSLOOP
la t5, WA__MINUSLOOP
la t3, WA__DO
la t6, WA__QDO
mv t4, zero
leave_load_secondary:
ld t2, 0(s7)
beq t2, t6, leave_inc
bne t2, t3, leave_test
leave_inc:
addi t4, t4, 1 #account for nested loops
j leave_move_on
leave_test:
beq t2, t0, leave_maybe_leave
beq t2, t1, leave_maybe_leave
beq t2, t5, leave_maybe_leave
leave_move_on:
addi s7, s7, 8
j leave_load_secondary
leave_maybe_leave:
beqz t4, leave_leave
addi t4, t4, -1
j leave_move_on
leave_leave:
addi s7, s7, 8 #take us past loop
tail NEXT
CODEHEADER _UNLOOP, _LEAVE, 0x0
addi s10, s10, 24
tail NEXT
CODEHEADER _PLUSLOOP, _UNLOOP, 0x0
ld t3, 0(sp)
addi sp, sp, 8
ld t0, 0(s10)
add t0, t0, t3
ld t1, 8(s10) #limit
bge t0, t1, loop_over
ld s7, 16(s10) #return point
sd t0, 0(s10)
tail NEXT
CODEHEADER _MINUSLOOP, _PLUSLOOP, 0x0
#non-standard word
#(x --)
ld t3, 0(sp)
addi sp, sp, 8
ld t0, 0(s10)
add t0, t0, t3
# decrement on this path
ld t1, 8(s10)
bge t1, t0, loop_over #reverse check
ld s7, 16(s10)
sd t0, 0(s10)
tail NEXT
CODEHEADER _LOOP, _MINUSLOOP, 0x0
ld t0, 0(s10) #current value
addi t0, t0, 1
ld t1, 8(s10) #limit
bge t0, t1, loop_over
ld s7, 16(s10) #return point
sd t0, 0(s10)
tail NEXT
loop_over:
addi s10, s10, 24
tail NEXT
CODEHEADER _DO, _LOOP, 0x0
ld t0, 0(sp) #start value
ld t1, 8(sp) #limit
addi sp, sp, 16
_do_loop:
addi s10, s10, -24
addi s7, s7, 8
sd s7, 16(s10)
sd t1, 8(s10)
sd t0, 0(s10)
tail NEXT
#loop words that do nothing in immediate mode
CODEHEADER J, _DO, 0x01
tail NEXT
CODEHEADER _QDO, J, 0x0
ld t0, 0(sp)
ld t1, 8(sp)
addi sp, sp, 16
beq t0, t1, _qdo_no_loop
addi s10, s10, -24
addi s7, s7, 8
sd s7, 16(s10)
sd t1, 8(s10)
sd t0, 0(s10)
tail NEXT
_qdo_no_loop:
ld s7, 0(s7)
tail NEXT
CODEHEADERZ QDO, ?DO, _QDO, 0x01
tail NEXT
CODEHEADER I, QDO, 0x01
tail NEXT
CODEHEADER LEAVE, I, 0x01
tail NEXT
CODEHEADER UNLOOP, LEAVE, 0x01
tail NEXT
CODEHEADERZ PLUSLOOP, +LOOP, UNLOOP, 0x01
tail NEXT
CODEHEADERZ MINUSLOOP, -LOOP, PLUSLOOP, 0x01
tail NEXT
CODEHEADER LOOP, MINUSLOOP, 0x01
tail NEXT
CODEHEADER DO, LOOP, 0x01
tail NEXT
CODEHEADER BEGIN, DO, 0x01
tail NEXT #BEGIN and UNTIL do nothing in immediate mode
CODEHEADER UNTIL, BEGIN, 0x01
tail NEXT
CODEHEADER _UNTIL, UNTIL, 0x0 #subsitituted in compiled
POP t0
bnez t0, end_of_until
ld s7, 0(s7)
tail NEXT
end_of_until:
add s7, s7, 8
tail NEXT
CODEHEADER AGAIN, _UNTIL, 0x01
tail NEXT #do nothing in immediatre mode
CODEHEADER _AGAIN, AGAIN, 0x0
ld s7, 0(s7)
tail NEXT
CODEHEADER REPEAT, _AGAIN, 0x01
tail NEXT
CODEHEADER _REPEAT, REPEAT, 0x0
ld s7, 0(s7) #similar to _UNTIL but jump back is unconditional
tail NEXT
CODEHEADER CR, _REPEAT, 0x01
WRITECHAR 0x0A
tail NEXT
CODEHEADER SPACE, CR, 0x01
WRITECHAR 0x20
tail NEXT
CODEHEADER RDROP, SPACE, 0x01
addi s9, s9, STACKOFFSET
tail NEXT
CODEHEADERZ TWORDROP, 2RDROP, RDROP, 0x01
addi s9, s9, (2 * STACKOFFSET)
tail NEXT
CODEHEADERZ RFETCH, R@, TWORDROP, 0x01 #R@
ld t0, 0(s9)
PUSH t0
tail NEXT
CODEHEADERZ TWORFETCH, 2R@, RFETCH, 0x01 #2R@
ld t0, 0(s9)
ld t1, STACKOFFSET(s9)
addi sp, sp, -16
sd t1, 8(sp)
sd t0, 0(sp)
tail NEXT
CODEHEADERZ TOR2, 2>R, TWORFETCH, 0x01 #2>R
ld t0, 0(sp)
ld t1, 8(sp)
addi sp, sp, 16
add s9, s9, -(STACKOFFSET * 2)
sd t1, STACKOFFSET(s9)
sd t0, 0(s9)
tail NEXT
CODEHEADERZ TOR, >R, TOR2, 0x01 #>R
POP t0
addi s9, s9, -STACKOFFSET
sd t0, 0(s9)
tail NEXT
CODEHEADERZ RFROM2, 2R>, TOR, 0x01
ld t0, 0(s9)
ld t1, STACKOFFSET(s9)
addi s9, s9, (STACKOFFSET * 2)
addi sp, sp, -(STACKOFFSET * 2)
sd t1, STACKOFFSET(sp)
sd t0, 0(sp)
tail NEXT
CODEHEADERZ RFROM, R>, RFROM2, 0x01 #R>
ld t0, 0(s9)
PUSH t0
addi s9, s9, STACKOFFSET
tail NEXT
CODEHEADERZ STORE, !, RFROM, 0x01 #!
ld t0, 0(sp)
ld t1, 8(sp)
addi sp, sp, 16
sd t1, 0(t0)
tail NEXT
CODEHEADER SPACES, STORE, 0x01
ld a0, 0(sp) #how many spaces
sd s0, 0(sp)
mv s0, a0
spaces_go:
beq s0, zero, spaces_done
WRITECHAR 0x20
addi s0, s0, -1
j spaces_go
spaces_done:
POP s0 #honour ABI
tail NEXT
CODEHEADERZ COLONNONAME, :NONAME, SPACES, 0x01
#Execution (--xt)
la t0, CREATEFLAG
li t1, 0x01
sd t1, 0(t0) #set MODE to 1 (compile)
la t1, newdictionary
ld t3, 0(t1)
li t2, 0x0 #0 flag - make word invisble to WORDS
sd t2, 0(t3) #flag
#place on stack
addi t2, t3, ADDRWIDTH
addi sp, sp, -STACKOFFSET
sd t2, 0(sp)
addi t2, t3, 0x38 #word address of new word
sd t2, 8(t3)
la t0, dictionary
ld t1, 0(t0)
sd t1, 16(t3) #words address of previous word
sd zero, 24(t3) #zero length
li t2, 0XFFFFFFFFFFFFFFFF #now fill in name space
sd t2, 32(t3)
sd t2, 40(t3)
#now join colon code
j colon_name_written
CODEHEADERZ COLON, :, COLONNONAME, 0x01
#SHIFT TO COMPILE MODE
#WRITE OUT FLAGS
#WRITE OUT PTR
#WRITE OUT PTR
la t0, CREATEFLAG
li t1, 0x01
sd t1, 0(t0) #set MODE to 1 (compile)
la t1, newdictionary
ld t3, 0(t1)
li t2, 0x31 #49 for COLON word
sd t2, 0(t3) #flag
addi t2, t3, 0x38 #word address of new word
sd t2, 8(t3)
la t0, dictionary
ld t1, 0(t0)
sd t1, 16(t3) #words address of previous word
sd zero, 24(t3) #zero length
li t2, 0XFFFFFFFFFFFFFFFF #now fill in name space
sd t2, 32(t3)
sd t2, 40(t3)
sd t2, 48(t3)
#now read in the name
PUSH t3
ld a1, INPUT_END
ld a0, INPUT_START
addi t0, a0, 1 #account for minimal input
bltu t0, a1, colon_tokenize_have_data #buffer has data
colon_tokenize_all_over:
j colon_fail
colon_tokenize_have_data:
mv t0, a0 #t0 tracks start of token, t1 the end
li t2, 0x20 #t2 space
li t3, 0x0A #t3 CR
colon_tokenize_look_for_start:
lb t4, 0(t0)
beq t4, t2, colon_tokenize_keep_going
bne t4, t3, colon_tokenize_found_start
j colon_tokenize_all_over
colon_tokenize_keep_going:
addi t0, t0, 1
bltu t0, a1, colon_tokenize_look_for_start
j colon_tokenize_all_over #got nothing
colon_tokenize_found_start:
mv t1, t0 #t1 to track end of token
colon_tokenize_advance_search:
addi t1, t1, 1
bgeu t1, a1, colon_tokenize_end_token
lb t4, 0(t1)
beq t4, t2, colon_tokenize_end_token
beq t4, t3, colon_tokenize_end_token
j colon_tokenize_advance_search
colon_tokenize_end_token:
la t5, INPUT_START
ld a7, 0(t5)
sub a6, t1, a7
la a5, INPUT_DISPLACE
ld a7, 0(a5)
add a7, a7, a6
sd a7, 0(a5) #update for >IN
sd t1, INPUT_START, t5 #update the end point for subsequent searches
addi t1, t1, -1 # space or NL not part of token
mv t2, t0
li t5, 0x61 #lowercase a
li t6, 0x7B #lowercase z + 1
colon_tokenize_sanity_test:
lb t4, 0(t2)
blt t4, t5, colon_tokenize_next_sane
blt t4, t6, colon_tokenize_sanitize
j colon_tokenize_next_sane
colon_tokenize_sanitize:
li t3, 0x20
xor t4, t4, t3
sb t4, 0(t2)
colon_tokenize_next_sane:
addi t2, t2, 1
blt t1, t2, colon_tokenize_finished_sanitization
j colon_tokenize_sanity_test
colon_tokenize_finished_sanitization:
sd t0, TOKEN_START, t2
sd t1, TOKEN_END, t2
POP t3
sub t4, t1, t0
addi t4, t4, 1 #add 1 to get length
sd t4, 24(t3) #write out length
addi t1, t3, 32
colon_write_out_name:
lb t5, 0(t0)
sb t5, 0(t1)
addi t4, t4, -1
beqz t4, colon_name_written
addi t0, t0, 1
addi t1, t1, 1
j colon_write_out_name
colon_name_written:
mv a0, t3
addi a0, a0, 56
mv a1, a0
addi a1, a1, 40
la a2, NEXT
call utility_do_colon
#ensure we are aligned
li t4, 7
and t5, a0, t4
beqz t5, colon_finish
li t4, 8
sub t6, t4, t5
add a0, a0, t6
colon_finish:
la t3, createwritepoint
sd a0, 0(t3)
tail NEXT
colon_fail:
la t0, CREATEFLAG
sd zero, 0(t0) #set MODE to 0 (no compile)
addi sp, sp, STACKOFFSET
PRINT bad_colon
tail NEXT