-
Notifications
You must be signed in to change notification settings - Fork 8
/
Copy pathcmforth.txt
496 lines (317 loc) · 31.5 KB
/
cmforth.txt
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
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
cmFORTH shadow blocks (1987 December). Addresses are hex;
word timing in parentheses after ; ( cycles) .
1 LOAD compiles the compacting compiler (blocks 4-6). Block 6
exits in COMPILER vocabulary, anticipating additions.
0< is redefined to resolve timing conflict.
END terminates a definition.
REMEMBER; saves vocabulary heads (at compile time).
FORTH puts following words in interpretive vocabulary.
-MOD provides modular arithmetic. It does a subtract if the
result is non-negative.
THRU loads a sequence of blocks.
EMPTY empties the dictionary except for compacting compiler.
H' holds the next available address in the target dictionary.
2000 relocates target addresses from RAM (2000) to PROM (0).
{ } switches between host and target dictionary by exchanging
pointers and relocation offsets.
COMPILER } compiles an indirect reference for a headless word.
forget smudges a word that cannot execute in target dictionary.
RECOVER recovers a return (after AGAIN ).
SCAN finds the next word in target dictionary.
TRIM relocates the vocabulary link and erases the smudge bit.
CLIP constructs a target vocabulary and stores its head.
PRUNE relinks the target dictionary to produce a stand-alone
application (fixing the end-of-vocabulary word)
and restores the host dictionary.
3 LOAD recompiles cmFORTH. EMPTY clears dictionary for a new
application.
2 LOAD compiles the target compiler.
Target is compiled at 2000 which is initialized to 0.
BOOT copies PROM to RAM at power-up. The reference to -1
disables PROM and enables RAM (setting A15 clocks 74).
Low RAM (16-24) is initialized (see block 12).
# is the bottom of the target dictionary. PRUNE changes its
name to null and link to 0. This version of EXIT marks the
end of both vocabulary chains.
The address of RESET is relocated into the end of BOOT .
The end of target program is stored into TIB and HERE .
COMPILER head is selected for PRUNE .
GO emulates BOOT for testing: 3 LOAD GO
FORTH sets interpretive vocabulary for both searches and
definitions. Words are compiled in definitions.
COMPILER sets immediate vocabulary. Words are executed in : .
uCODE names a NC4016 micro-coded instruction. Compiled on use.
\ compiles a following compiler directive (that would normally
be executed). Named [COMPILE] in FORTH-83.
4016 instructions:
!- stores and decrements. I@! exchanges stack®ister.
NOP delays 1 cycle. TWO delays 2 cycles.
0+c Adds 0 with carry. MOD' conditionally subtracts R4.
N! stores and saves data. -1 fetches register 3
DUP? compacts preceeding DUP with current instruction. Used
to redefine I! and PUSH (previously >R ).
PACK sets the return bit, if an instruction does not reference
the Return stack. Otherwise it compiles a return. It exits
from EXIT with POP DROP .
EXIT optimizes return if permitted ( ?CODE nonzero):
For instructions (bit-15 = 1) it calls PACK except for jump
or 2-cycle instructions;
for calls to the same 4K page, it substitutes a jump.
; is redefined to use the new EXIT .
CONSTANT is redefined to take advantage of the new EXIT for
5-bit literals.
BINARY defines and compacts ALU instructions. If the previous
instruction was a fetch (ALU code 7) and not a store or DROP
the ALU code is merged; stack push is inhibited. Otherwise
a new instruction is compiled. ?CODE holds address of
candidate for compaction.
SHIFT defines and compacts shift instructions. Shift left
( 2* ) and right ( 2/) may be merged with an arithmetic
instruction; sign propagate ( 0< ) only with DUP .
DROP OR XOR AND + - SWAP- are redefined.
2* 2/ 0< likewise.
ROT is a slow way to reference into the stack.
0= returns false (0) if stack non-zero; otherwise true ( -1).
NOT same as 0=. FORTH-83 wants one's complement.
< > subtract and test sign bit. Range of difference limited
to 15 bits (-20000 is not less-than 20000).
= equality tested by XOR.
U< unsigned compare with 16-bit range (0 is less-than 40000).
{ ... } surround words defined into host dictionary. Used
during compilation, they will not be in target dictionary.
4016 instructions:
*' multiply step *- signed multiply step
D2* 32-bit left shift D2/ 32-bit right shift
/' divide step /'' final divide step
F* fraction multiply S' square-root step
M/MOD 30-bit dividend; 15-bit divisor, quotient, remainder.
M/ signed dividend; 15-bit divisor, quotient.
VNEGATE negates both multiplier and multiplicand.
M* 32-bit signed product; multiplier (on top) must be even.
/MOD 15-bit dividend, divisor, quotient, remainder.
MOD 15-bit dividend, divisor, remainder.
U*+ 15-bit multiplier, multiplicand, addend; 30-bit product.
*/ signed multiplier, multiplicand, result; 15-bit divisor;
multiplier (in middle) must be even.
* signed product; multiplier (on top) must be even.
/ signed dividend, quotient; 15-bit divisor.
2/MOD 16-bit unsigned dividend; 15-bit quotient, remainder.
\\ (break compaction) used to combine + 2/ ;
+! adds to memory.
Byte address is 2* cell address; high byte is byte 0. Range
restricted to low RAM (0-7FFF).
C! stores 8-bit data into byte address; other byte unaffected.
C@ fetches 8-bits from byte address.
2@ fetches 2 16-bit numbers; lower address on top.
2! stores 2 16-bit numbers.
MOVE the fastest move that does not stream to-from stack.
FILL fills RAM with constant.
EXECUTE executes code at an address by returning to it.
CYCLES delays n+4 cycles - count 'em.
?DUP copies stack if non-zero.
2DUP copies 32-bit (2 16-bit) stack item.
2DROP DROP DROP ; is faster and usually no longer.
WITHIN returns true if number within low (inclusive) and high
(non-inclusive) limits; all numbers 16 bits or signed.
ABS returns positive number (15-bits).
MAX returns larger of pair; 15-bit range.
MIN returns smaller. Intertwining code saves 2 cells; left in
as illustration of obscure but efficient code.
ARRAY defines an array that adds an index from stack in only
2 cycles. Similar to VARIABLE .
These low-RAM variables are used by cmFORTH (0-F are unused).
Change them cautiously! In particular, make sure a variable
is not used during compilation. For example, HEX is
redefined to set BASE . It can be used if BASE has not
moved; otherwise it must be forgetted.
Non-standard variables:
?CODE address of last instruction compiled. Zero indicates
no compaction permitted (ie, after THEN ).
dA offset to be added to compiled addresses. Normally 0.
Relocated code cannot be executed!
CURSOR tracks cursor (terminal dependent); used by EXPECT .
S0 serial output polarity; 1FF or 200.
C/B cycles/bit for serial I/O.
EMIT sets Xmask to 1E so that only X0 can be changed. Start/
stop bits are added and polarity set. I! emits bits at C/B
rate thru X0.
CR emits carriage-return and line-feed.
TYPE types a string with prefixed count byte. It returns an
incremented cell address. This is not FORTH-83 standard.
RX reads a bit from pin X4.
KEY reads 8-bits from X4. It waits for a start bit, then
delays until the middle of the first data bit. Each bit is
sampled then ored into bit 7 of the accumulated byte. It
does not exit until the stop bit (low) is detected.
SPACE emits a space.
SPACES emits n>0 spaces.
HOLD holds characters on the stack, maintaining a count.
It reverses the digits resulting from number conversion.
EXPECT accepts keystrokes and buffers them (at TIB ). An 8
will discard a character and emit a backspace; a D will
emit a space and exit; all other keys are stored and echoed
until the count is exhausted. Actual count is in SPAN .
DIGIT converts a digit (0-F) into an ASCII character.
<# starts conversion by tucking a count under the number.
#> ends conversion by emitting the string of digits.
SIGN stacks a minus sign, if needed.
# converts the low-order digit of a 16-bit number.
#S converts non-zero digits, at least one.
(.) formats a signed number.
. displays a 16-bit signed integer, followed by a space.
U.R displays a right-justified 16-bit unsigned number.
U. displays an unsigned number.
DUMP displays an address and 8 numbers from memory. It
returns an incremented address for a subsequent DUMP .
HERE returns next address in dictionary.
abort" types the current word (at HERE ) and an error message
(at I ) It also returns the current BLK to locate an
error during LOAD . It will end with QUIT , when defined.
It is a headless definition, referenced only by ABORT" .
dot" types a message whose address is pulled off the return
stack, incremented and replaced.
ABORT" compiles abort" and the following string. This is a
host COMPILER definition. The target definition is in
block 30.
." compiles dot" and the following string.
BUFFERS returns indexed address of buffer ID.
PREV current buffer number (0-NB).
OLDEST last buffer read. Next buffer is OLDEST @ 1 + .
ADDRESS calculates a buffer address from buffer number. NB is
1. If increased, ADDRESS and BUFFERS must be also.
ABSENT returns the block number when the requested block isn't
already in RAM. Otherwise it returns the buffer address and
exits from BLOCK .
UPDATED returns the buffer address and current block number if
the pending buffer has been UPDATEd . Otherwise it returns
the buffer address and exits from the calling routine ( BLOCK
or BUFFER ). Pending means oldest but not just used.
UPDATE marks the current buffer ( PREV ) to be rewritten.
ESTABLISH stores the block number of the current buffer.
IDENTIFY stores a block number into the current buffer. Used
to copy blocks.
## emits 3 bytes to host to start a block transfer; 0 followed
by block number.
buffer transmits an updated block and awaits acknowledgement.
BUFFER returns address of an empty (but assigned) buffer.
block reads a block.
BLOCK returns the buffer address of a specified block, writing
and reading as necessary.
FLUSH forces buffers to be written.
EMPTY-BUFFERS clears buffer IDs, without writing.
LETTER moves a string of characters from cell address a to
byte address b . Terminated by count ( # ) or delimitor
(register 6). Input pointer >IN is advanced.
-LETTER scans the source string for a non-delimiter. If found,
calls LETTER .
WORD locates text in either block buffer or TIB ( BLK is 0).
Reads word into HERE prefixing count and suffixing a space
(in case count even).
SAME compares the string at HERE with a name field. Cell
count is in register 6. High bit of each cell is ignored.
Returns address of parameter field; requires indirect
reference if high bit of count set (separated head).
COUNT extracts the cell count from the first word of a string.
HASH returns the address of the head of a vocabulary.
-FIND searches a vocabulary for match with HERE . Fails with
zero link field.
-DIGIT converts an ASCII character to a digit (0-Z).
Failure generates an error message.
C@+ increments address in register 6 and fetches character.
10*+ multiplies number by BASE and adds digit.
NUMBER converts given string to binary; stores BASE in R4;
saves minus sign; terminates on count; applies sign
-' searches vocabulary for following word.
' returns address of following word in current vocabulary
Error message on failure. forget to use host version.
INTERPRET accepts block number and offset. Searches FORTH
and executes words found; otherwise converts to binary.
QUIT accepts a character string into the text input buffer,
interprets and replies ok to signify success; repeats.
The address of QUIT is relocated into the end of abort" .
FORGET restores HERE and vocabulary heads to values saved at
compile time (by REMEMBER; ).
BPS awaits a start bit, assumes only the first data bit is
zero and computes C/B . Type a B or other even letter.
RS232 examines the serial input line and inverts serial I/O if
an inverting buffer is used (line rests low).
reset is executed at power-up or reset.
Carefully initializes I/O registers to avoid glitches.
Empties buffers at power-up only ( TIB contains garbage).
Calibrates serial I/O.
Cheerful hi and awaits command.
This is the beginning of the compiler. A turn-key application
might need only the code above.
Common words are defined for both interpreter and compiler.
Number base words defined together; DECIMAL required.
LOAD saves current input pointers, calls INTERPRET , restores
input pointers and returns to DECIMAL . >IN and BLK are
treated as a 32-bit pointer. forget so that host LOAD
will be used.
\\ breaks code compaction.
ALLOT increments the dictionary pointer to allot memory.
, compiles a number into the dictionary.
,C compiles an instruction available for compaction.
,A compiles a address relocated by dA .
LITERAL compiles a number as a short literal, if possible.
[ stops compilation by popping the return stack, thus returning
out of the infinite ] loop.
] unlike INTERPRET , searches both vocabularies before falling
into NUMBER . When a word is found in COMPILER it is
executed; if found in FORTH it is compiled. If it is a
single instruction, it is placed in-line; otherwise its
address is compiled for a call.
PREVIOUS returns the address and count of the name field of
the word just defined.
USE assigns to the previous word a specified code field.
DOES provides a behavior for a newly defined word. It is
executed when that word is defined.
SMUDGE smudges the name field to avoid recursion.
EXIT returns from a definition early ( FORTH version).
COMPILE pops the address of the following word and compiles it.
7FFF AND masks the carry bit from the return stack.
EXIT compiles a return instruction ( COMPILER version).
RECURSIVE unsmudges the name field so a new word can be found.
; terminates a definition. forget permits more definitions.
CREATE creates an entry in the dictionary. It saves space for
the link field, then fetches a word terminated by space. It
links the word into the proper vocabulary, allots space for
the name field and compiles the return-next-address
instruction appropriate for a variable.
: creates a definition; -1 ALLOT recovers the instruction
compiled by CREATE ; ] compiles the definition in its
place. forget permits more definitions.
CONSTANT names a number by compiling a literal.
VARIABLE initializes its variable to zero.
-SHORT checks if last instruction was a 5-bit literal.
FIX merges 5-bit literal with new instruction.
SHORT requires 5-bit literal (register, address or increment)
for current instruction. Error message.
@ and ! compile 5-bit or stack address instructions.
I@ and I! compile 5-bit register instuctions.
@+ and !+ compile 5-bit increment instructions.
PUSH and POP push and pop the return stack.
They are usually designated >R and R> .
I copies the return stack onto the parameter stack.
TIMES pushes the return stack to repeat the next instruction
for n + 2 cycles.
OR, compiles a 12-bit address with a backward jump instruction.
BEGIN saves HERE for backward jumps.
UNTIL compiles a conditional backward jump.
AGAIN compiles an unconditional backward jump.
THEN adds 12-bit current address into forward jump.
IF compiles a conditional forward jump.
WHILE compiles a conditional forward jump - out of structure.
REPEAT resolves a BEGIN ... WHILE ... loop.
ELSE inserts false clause in an IF ... THEN conditional.
FOR compiles return stack push for a down-counting loop.
NEXT compiles a backward decrement-and-jump.
STRING compiles a character string with a specified delimiter.
ABORT" DOT" are target versions of previously-defined host
words.
( skips over a comment. It must be defined in both FORTH and
COMPILER .
RESET restores dictionary to power-up status. It must be the
last word in the dictionary. It is called by reset .
Insert application code before this block, to avoid using these
common target words. Alternatively, forget them.