3 * fig-FORTH FOR 6800 auto-converted to de-optimized 6809
4 * and hand-adjusted, maintaining principle structure.
5 * In particular, debugging by patching NEXT is maintained.
6 * ASSEMBLY SOURCE LISTING
10 * WITH COMPILER SECURITY
11 * AND VARIABLE LENGTH NAMES
13 * This public domain publication is provided
14 * through the courtesy of:
20 * P.O. Box 8231 - San Jose, CA 95155 - (408) 277-0668
21 * Further distribution must include this notice.
23 NAM Copyright:FORTH Interest Group
26 * === FORTH-6800 06-06-79 21:OO
29 * This listing is in the PUBLIC DOMAIN and
30 * may be freely copied or published with the
31 * restriction that a credit line is printed
32 * with the material, crediting the
33 * authors and the FORTH INTEREST GROUP.
39 * === The Forth Interest Group
41 * === San Carlos, CA 94070
43 * === Unbounded Computing
44 * === 1134-K Aster Ave.
45 * === Sunnyvale, CA 94086
47 * This version was developed on an AMI EVK 300 PROTO
48 * system using an ACIA for the I/O. All terminal 1/0
49 * is done in three subroutines:
50 * PEMIT ( word # 182 )
54 * The FORTH words for disc related I/O follow the model
55 * of the FORTH Interest Group, but have not been
56 * tested using a real disc.
58 * Addresses in this implementation reflect the fact that,
59 * on the development system, it was convenient to
60 * write-protect memory at hex 1000, and leave the first
61 * 4K bytes write-enabled. As a consequence, code from
62 * location $1000 to lable ZZZZ could be put in ROM.
63 * Minor deviations from the model were made in the
64 * initialization and words ?STACK and FORGET
65 * in order to do this.
70 NBLK EQU 4 # of disc buffer blocks for virtual memory
71 MEMEND EQU 132*NBLK+$3000 end of ram
72 * each block is 132 bytes in size,
73 * holding 128 characters
75 MEMTOP EQU $3FFF absolute end of all ram
76 ACIAC EQU $FBCE the ACIA control address and
77 ACIAD EQU ACIAC+1 data address for PROTO
79 * MEMORY MAP for this 16K system:
80 * ( positioned so that systems with 4k byte write-
81 * protected segments can write protect FORTH )
83 * addr. contents pointer init by
84 * **** ******************************* ******* ******
86 * substitute for disc mass memory
89 * 4 buffer sectors of VIRTUAL MEMORY
91 * >>>>>> memory from here up must be RAM <<<<<<
94 * 6k of romable "FORTH" <== IP ABORT
96 * the VIRTUAL FORTH MACHINE
98 * 1004 <<< WARM START ENTRY >>>
99 * 1000 <<< COLD START ENTRY >>>
101 * >>>>>> memory from here down must be RAM <<<<<<
102 * FFE RETURN STACK base <== RP RINIT
106 * holds up to 132 characters
107 * and is scanned upward by IN
110 * F2F DATA STACK <== SP SP0,SINIT
111 * | grows downward from F2F
115 * I DICTIONARY grows upward
117 * 183 end of ram-dictionary. <== DP DPINIT
120 * 150 "FORTH" ( a word ) <=, <== CONTEXT
122 * 148 start of ram-dictionary.
124 * 100 user #l table of variables <= UP DPINIT
125 * F0 registers & pointers for the virtual machine
126 * scratch area used by various words
127 * E0 lowest address used by FORTH
133 * CONVENTIONS USED IN THIS PROGRAM ARE AS FOLLOWS :
135 * IP points to the current instruction ( pre-increment mode )
136 * RP points to second free byte (first free word) in return stack
137 * SP (hardware SP) points to first free byte in data stack
139 * when A and B hold one 16 bit FORTH data word,
140 * A contains the high byte, B, the low byte.
149 N RMB 10 used as scratch by (FIND),ENCLOSE,CMOVE,EMIT,KEY,
150 * SP@,SWAP,DOES>,COLD
153 * These locations are used by the TRACE routine :
155 TRLIM RMB 1 the count for tracing without user intervention
156 TRACEM RMB 1 non-zero = trace mode
157 BRKPT RMB 2 the breakpoint address at which
158 * the program will go into trace mode
159 VECT RMB 2 vector to machine code
160 * (only needed if the TRACE routine is resident)
163 * Registers used by the FORTH virtual machine:
167 * Maybe W ends up cached in X anyway.
168 W RMB 2 the instruction register points to 6800 code
169 * IP moved to processor Y, but keeping this for saves, maybe.
170 IP RMB 2 the instruction pointer points to pointer to 6800 code
171 * RP moved to processor S
172 * SP moved to processor U
173 RP RMB 2 the return stack pointer
174 UP RMB 2 the pointer to base of current user's 'USER' table
175 * ( altered during multi-tasking )
178 * This system is shown with one user, but additional users
179 * may be added by allocating additional user tables:
180 * UORIG2 RMB 64 data table for user #2
183 * Some of this stuff gets initialized during
184 * COLD start and WARM start:
185 * [ names correspond to FORTH words of similar (no X) name ]
188 UORIG RMB 6 3 reserved variables
189 XSPZER RMB 2 initial top of data stack for this user
190 XRZERO RMB 2 initial top of return stack
191 XTIB RMB 2 start of terminal input buffer
192 XWIDTH RMB 2 name field width
193 XWARN RMB 2 warning message mode (0 = no disc)
194 XFENCE RMB 2 fence for FORGET
195 XDP RMB 2 dictionary pointer
196 XVOCL RMB 2 vocabulary linking
197 XBLK RMB 2 disc block being accessed
198 XIN RMB 2 scan pointer into the block
199 XOUT RMB 2 cursor position
200 XSCR RMB 2 disc screen being accessed ( O=terminal )
201 XOFSET RMB 2 disc sector offset for multi-disc
202 XCONT RMB 2 last word in primary search vocabulary
203 XCURR RMB 2 last word in extensible vocabulary
204 XSTATE RMB 2 flag for 'interpret' or 'compile' modes
205 XBASE RMB 2 number base for I/O numeric conversion
206 XDPL RMB 2 decimal point place
208 XCSP RMB 2 current stack position, for compile checks
211 XDELAY RMB 2 carriage return delay count
212 XCOLUM RMB 2 carriage width
213 IOSTAT RMB 2 last acia status from write/read
224 * end of user table, start of common system variables
233 * These things, up through the lable 'REND', are overwritten
234 * at time of cold load and should have the same contents
241 FORTH FDB DODOES,DOVOC,$81A0,TASK-7
244 FCC "(C) Forth Interest Group, 1979"
252 REND EQU * ( first empty location in dictionary )
255 * The FORTH program ( address $1000 to $27FF ) is written
256 * so that it can be in a ROM, or write-protected if desired
259 * ######>> screen 3 <<
261 ***************************
262 ** C O L D E N T R Y **
263 ***************************
266 ***************************
267 ** W A R M E N T R Y **
268 ***************************
270 JMP WENT warm-start code, keeps current dictionary intact
273 ******* startup parmeters **************************
275 FDB $6800,0000 cpu & revision
276 FDB 0 topmost word in FORTH vocabulary
277 BACKSP FDB $7F backspace character for editing
278 UPINIT FDB UORIG initial user area
279 SINIT FDB ORIG-$D0 initial top of data stack
280 RINIT FDB ORIG-2 initial top of return stack
281 FDB ORIG-$D0 terminal input buffer
282 FDB 31 initial name field width
283 FDB 0 initial warning mode (0 = no disc)
284 FENCIN FDB REND initial fence
285 DPINIT FDB REND cold start value for DP
287 COLINT FDB 132 initial terminal carriage width
288 DELINT FDB 4 initial carriage return delay
289 ****************************************************
293 * ######>> screen 13 <<
294 * This will probably disappear?
296 * PULS A ; 24 cycles until 'NEXT'
299 * STA 0,X 16 cycles until 'NEXT'
303 * LDA 0,X 18 cycles until 'NEXT'
306 * PSHU B ; 8 cycles until 'NEXT'
312 * "NEXT" takes 38 cycles if TRACE is removed,
314 * and 95 cycles if NOT tracing.
316 * = = = = = = = t h e v i r t u a l m a c h i n e = = = = =
318 * NEXT2 might disappear, as well, letting us use auto-inc mode.
321 * LEAX 1,X ; pre-increment mode
325 * LDX 0,X get W which points to CFA of word to be done
327 * LDX 0,X get VECT which points to executable code
329 * The next instruction could be patched to JMP TRACE =
330 * if a TRACE routine is available: =
335 * JMP TRACE ( an alternate for the above )
337 * = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
344 FCC 'LI' ; 'LIT' : NOTE: this is different from LITERAL
346 FDB 0 link of zero to terminate dictionary scan
352 LEAY 2,Y ; Might shift to post-inc?
358 * ######>> screen 14 <<
360 * But we should give it a header, after all, and link it in a different vocab.
361 CLITER FDB *+2 (this is an invisible word, with no header)
373 FCC 'EXECUT' ; 'EXECUTE'
378 * LDX 0,X get code field address (CFA)
379 * LEAS 1,U ; pop stack
384 * ######>> screen 15 <<
387 FCC 'BRANC' ; 'BRANCH'
390 BRAN FDB ZBYES Go steal code in ZBRANCH
394 FCC '0BRANC' ; '0BRANCH'
400 PSHU B ; ** emulating ABA:
404 ZBYES LDX IP Note: code is shared with BRANCH, (+LOOP), (LOOP)
412 ZBNO LDX IP no branch. This code is shared with (+LOOP), (LOOP).
413 LEAX 1,X ; jump over branch delta
418 * ######>> screen 16 <<
421 FCC '(LOOP' ; '(LOOP)'
426 LDB #1 get set to increment counter by 1
427 BRA XPLOP2 go steal other guy's code!
431 FCC '(+LOOP' ; '(+LOOP)'
434 XPLOOP FDB *+2 Note: +LOOP has an un-signed loop counter
435 PULS A ; get increment
438 BPL XPLOF forward looping
444 BRA XPLONO fall through
448 ADDB 3,X add it to counter
450 STB 3,X store new counter value
459 XPLONO LEAX 1,X ; done, don't branch back
464 BRA ZBNO use ZBRAN to skip over unused delta
466 * ######>> screen 17 <<
472 XDO FDB *+2 This is the RUNTIME DO, not the COMPILING DO
499 * ######>> screen 18 <<
505 DIGIT FDB *+2 NOTE: legal input range is 0-9, A-Z
509 BMI DIGIT2 IF LESS THAN '0', ILLEGAL
511 BMI DIGIT0 IF '9' OR LESS
513 BMI DIGIT2 if less than 'A'
515 BPL DIGIT2 if greater than 'Z'
516 SUBA #7 translate 'A' thru 'F'
518 BPL DIGIT2 if not less than the base
521 DIGIT1 STB 1,X store the flag
525 LEAS 1,U ; pop bottom number
527 STB 0,X make sure both bytes are 00
530 * ######>> screen 19 <<
532 * The word format in the dictionary is:
534 * char-count + $80 lowest address
539 * link high byte \___point to previous word
541 * CFA high byte \___pnt to 6800 code
550 FCC '(FIND' ; '(FIND)'
556 PD EQU N ptr to dict word being checked
562 PFIND0 PULS A ; loop to get arguments
569 PFIND1 LDB 0,X get count dict count
575 LDA 0,X get count from arg
578 PSHU B ; ** emulating CBA:
579 CMPA ,U+ ; compare lengths
589 TSTB ; is dict entry neg. ?
592 PSHU B ; ** emulating CBA:
595 PFIND3 LDX 0,X get new link
596 BNE PFIND1 continue if link not=0
603 PFIND8 PSHU B ; ** emulating CBA:
607 PFIND9 LDB 0,X scan forward to end of this name
614 FOUND LDA PD compute CFA
633 * ######>> screen 20 <<
636 FCC 'ENCLOS' ; 'ENCLOSE'
640 * FC means offset (bytes) to First Character of next word
641 * EW " " to End of Word
642 * NC " " to Next Character to start next enclose at
645 PULS B ; now, get the low byte, for an 8-bit delimiter
649 * wait for a non-delimiter or a NUL
652 PSHU B ; ** emulating CBA:
653 CMPA ,U+ ; CHECK FOR DELIM
658 * found first character. Push FC
659 ENCL3 LDA N found first char.
663 * wait for a delimiter or a NUL
666 PSHU B ; ** emulating CBA:
667 CMPA ,U+ ; ckech for delim.
677 * advance and push NC
680 * found NUL before non-delimiter, therefore there is no word
681 ENCL6 LDB N found NUL
686 * found NUL following the word instead of SPACE
695 * ######>> screen 21 <<
696 * The next 4 words call system dependant I/O routines
697 * which are listed after word "-->" ( lable: "arrow" )
712 ****WARNING**** HARD OFFSET: *+4 ****
730 FCC '?TERMINA' ; '?TERMINAL'
736 JMP PUSHBA stack the flag
747 * ######>> screen 22 <<
750 FCC 'CMOV' ; 'CMOVE' : source, destination, count
753 CMOVE FDB *+2 takes ( 43+47*count cycles )
757 STA 0,X move parameters to scratch area
779 * ######>> screen 23 <<
791 * The following is a subroutine which
792 * multiplies top 2 words on stack,
793 * leaving 32-bit result: high order word in A,B
794 * low order word in 2nd word of stack.
796 USTARS LDA #16 bits/word counter
801 USTAR2 ROR 5,X shift multiplier
811 USTAR4 LEAS 1,U ; dump counter
814 * ######>> screen 24 <<
831 USL2 ANDCC #~$01 ; CLC :
849 JMP SWAP+4 reverse quotient & remainder
851 * ######>> screen 25 <<
891 * ######>> screen 26 <<
911 TFR X,U ; TXS : watch it ! X and S are not equal.
919 LDX RINIT initialize from rom constant
933 LDX 0,X get address we have just finished.
934 JMP NEXT+2 increment the return address & do next word
936 * ######>> screen 27 <<
990 * ######>> screen 28 <<
1003 ZEQU2 TFR U,X ; TSX :
1013 LDA #$80 check the sign bit
1022 * ######>> screen 29 <<
1058 FCC 'MINU' ; 'MINUS'
1072 FCC 'DMINU' ; 'DMINUS'
1089 * ######>> screen 30 <<
1141 * ######>> screen 31 <<
1152 PULS A ; get stack data
1154 ADDB 1,X add & store low byte
1156 ADCA 0,X add & store hi byte
1162 FCC 'TOGGL' ; 'TOGGLE'
1165 TOGGLE FDB DOCOL,OVER,CAT,XOR,SWAP,CSTORE
1168 * ######>> screen 32 <<
1221 * ######>> screen 33 <<
1226 COLON FDB DOCOL,QEXEC,SCSP,CURENT,AT,CONTXT,STORE
1230 * Here is the IP pusher for allowing
1231 * nested words in the virtual machine:
1232 * ( ;S is the equivalent un-nester )
1234 DOCOL LDX RP make room in the stack
1240 STA 2,X Store address of the high level word
1241 STB 3,X that we are starting to execute
1242 LDX W Get first sub-word of that definition
1243 JMP NEXT+2 and execute it
1246 FCB $C1 ; imnediate code
1249 SEMI FDB DOCOL,QCSP,COMPIL,SEMIS,SMUDGE,LBRAK
1252 * ######>> screen 34 <<
1255 FCC 'CONSTAN' ; 'CONSTANT'
1258 CON FDB DOCOL,CREATE,SMUDGE,COMMA,PSCODE
1261 LDB 3,X A & B now contain the constant
1266 FCC 'VARIABL' ; 'VARIABLE'
1269 VAR FDB DOCOL,CON,PSCODE
1273 ADCA #0 A,B now contain the address of the variable
1281 USER FDB DOCOL,CON,PSCODE
1282 DOUSER LDX W get offset into user's table
1285 ADDB UP+1 add to users base address
1287 JMP PUSHBA push address of user's variable
1289 * ######>> screen 35 <<
1323 BL FDB DOCON ascii blank
1328 FCC 'FIRS' ; 'FIRST'
1332 FDB MEMEND-528 (132 * NBLK)
1336 FCC 'LIMI' ; 'LIMIT' : ( the end of memory +1 )
1344 FCC 'B/BU' ; 'B/BUF' : (bytes/buffer)
1352 FCC 'B/SC' ; 'B/SCR' : (blocks/screen)
1357 * blocks/screen = 1024 / "B/BUF" = 8
1361 FCC '+ORIGI' ; '+ORIGIN'
1364 PORIG FDB DOCOL,LIT,ORIG,PLUS
1367 * ######>> screen 36 <<
1394 FCC 'WIDT' ; 'WIDTH'
1402 FCC 'WARNIN' ; 'WARNING'
1410 FCC 'FENC' ; 'FENCE'
1418 FCC 'D' ; 'DP' : points to first free byte at end of dictionary
1426 FCC 'VOC-LIN' ; 'VOC-LINK'
1442 FCC 'I' ; 'IN' : scan pointer for input line buffer
1463 * ######>> screen 37 <<
1467 FCC 'OFFSE' ; 'OFFSET'
1475 FCC 'CONTEX' ; 'CONTEXT' : points to pointer to vocab to search first
1483 FCC 'CURREN' ; 'CURRENT' : points to ptr. to vocab being extended
1491 FCC 'STAT' ; 'STATE' : 1 if compiling, 0 if not
1499 FCC 'BAS' ; 'BASE' : number base for all input & output
1545 * ======>> 82.5 <<== SPECIAL
1547 FCC 'COLUMN' ; 'COLUMNS' : line width of terminal
1553 * ######>> screen 38 <<
1559 ONEP FDB DOCOL,ONE,PLUS
1567 TWOP FDB DOCOL,TWO,PLUS
1575 HERE FDB DOCOL,DP,AT
1580 FCC 'ALLO' ; 'ALLOT'
1583 ALLOT FDB DOCOL,DP,PSTORE
1590 COMMA FDB DOCOL,HERE,STORE,TWO,ALLOT
1598 CCOMM FDB DOCOL,HERE,CSTORE,ONE,ALLOT
1605 SUB FDB DOCOL,MINUS,PLUS
1612 EQUAL FDB DOCOL,SUB,ZEQU
1640 GREAT FDB DOCOL,SWAP,LESS
1648 ROT FDB DOCOL,TOR,SWAP,FROMR,SWAP
1653 FCC 'SPAC' ; 'SPACE'
1656 SPACE FDB DOCOL,BL,EMIT
1664 MIN FDB DOCOL,OVER,OVER,GREAT,ZBRAN
1675 MAX FDB DOCOL,OVER,OVER,LESS,ZBRAN
1686 DDUP FDB DOCOL,DUP,ZBRAN
1691 * ######>> screen 39 <<
1694 FCC 'TRAVERS' ; 'TRAVERSE'
1698 TRAV2 FDB OVER,PLUS,CLITER
1700 FDB OVER,CAT,LESS,ZBRAN
1707 FCC 'LATES' ; 'LATEST'
1710 LATEST FDB DOCOL,CURENT,AT,AT
1718 LFA FDB DOCOL,CLITER
1728 CFA FDB DOCOL,TWO,SUB
1736 NFA FDB DOCOL,CLITER
1738 FDB SUB,ONE,MINUS,TRAV
1746 PFA FDB DOCOL,ONE,TRAV,CLITER
1751 * ######>> screen 40 <<
1757 SCSP FDB DOCOL,SPAT,CSP,STORE
1762 FCC '?ERRO' ; '?ERROR'
1765 QERR FDB DOCOL,SWAP,ZBRAN
1774 FCC '?COM' ; '?COMP'
1777 QCOMP FDB DOCOL,STATE,AT,ZEQU,CLITER
1784 FCC '?EXE' ; '?EXEC'
1787 QEXEC FDB DOCOL,STATE,AT,CLITER
1794 FCC '?PAIR' ; '?PAIRS'
1797 QPAIRS FDB DOCOL,SUB,CLITER
1807 QCSP FDB DOCOL,SPAT,CSP,AT,SUB,CLITER
1814 FCC '?LOADIN' ; '?LOADING'
1817 QLOAD FDB DOCOL,BLK,AT,ZEQU,CLITER
1822 * ######>> screen 41 <<
1825 FCC 'COMPIL' ; 'COMPILE'
1828 COMPIL FDB DOCOL,QCOMP,FROMR,TWOP,DUP,TOR,AT,COMMA
1835 LBRAK FDB DOCOL,ZERO,STATE,STORE
1842 RBRAK FDB DOCOL,CLITER
1849 FCC 'SMUDG' ; 'SMUDGE'
1852 SMUDGE FDB DOCOL,LATEST,CLITER
1870 FCC 'DECIMA' ; 'DECIMAL'
1875 FCB 10 note: hex "A"
1879 * ######>> screen 42 <<
1882 FCC '(;CODE' ; '(;CODE)'
1885 PSCODE FDB DOCOL,FROMR,TWOP,LATEST,PFA,CFA,STORE
1890 FCC ';COD' ; ';CODE'
1893 SEMIC FDB DOCOL,QCSP,COMPIL,PSCODE,SMUDGE,LBRAK,QSTACK
1895 * note: "QSTACK" will be replaced by "ASSEMBLER" later
1897 * ######>> screen 43 <<
1900 FCC '<BUILD' ; '<BUILDS'
1903 BUILDS FDB DOCOL,ZERO,CON
1908 FCC 'DOES' ; 'DOES>'
1911 DOES FDB DOCOL,FROMR,TWOP,LATEST,PFA,STORE
1915 LDX RP make room on return stack
1919 STA 2,X push return address
1921 LDX W get addr of pointer to run-time code
1924 STX N stash it in scratch area
1927 CLRA ; get address of parameter
1931 PSHU B ; and push it on data stack
1935 * ######>> screen 44 <<
1938 FCC 'COUN' ; 'COUNT'
1941 COUNT FDB DOCOL,DUP,ONEP,SWAP,CAT
1949 TYPE FDB DOCOL,DDUP,ZBRAN
1951 FDB OVER,PLUS,SWAP,XDO
1952 TYPE2 FDB I,CAT,EMIT,XLOOP
1961 FCC '-TRAILIN' ; '-TRAILING'
1964 DTRAIL FDB DOCOL,DUP,ZERO,XDO
1965 DTRAL2 FDB OVER,OVER,PLUS,ONE,SUB,CAT,BL
1980 PDOTQ FDB DOCOL,R,TWOP,COUNT,DUP,ONEP
1981 FDB FROMR,PLUS,TOR,TYPE
1994 FDB COMPIL,PDOTQ,WORD
1995 FDB HERE,CAT,ONEP,ALLOT,BRAN
1997 DOTQ1 FDB WORD,HERE,COUNT,TYPE
2000 * ######>> screen 45 <<
2001 * ======>> 126 <<== MACHINE DEPENDENT
2003 FCC '?STAC' ; '?STACK'
2006 QSTACK FDB DOCOL,CLITER
2008 FDB PORIG,AT,TWO,SUB,SPAT,LESS,ONE
2010 * prints 'empty stack'
2013 * Here, we compare with a value at least 128
2014 * higher than dict. ptr. (DP)
2021 * prints 'full stack'
2025 * ======>> 127 << this word's function
2026 * is done by ?STACK in this version
2031 *QFREE FDB DOCOL,SPAT,HERE,CLITER
2033 * FDB PLUS,LESS,TWO,QERR,SEMIS
2035 * ######>> screen 46 <<
2038 FCC 'EXPEC' ; 'EXPECT'
2041 EXPECT FDB DOCOL,OVER,PLUS,OVER,XDO
2042 EXPEC2 FDB KEY,DUP,CLITER
2044 FDB PORIG,AT,EQUAL,ZBRAN
2047 FCB 8 ( backspace character to emit )
2048 FDB OVER,I,EQUAL,DUP,FROMR,TWO,SUB,PLUS
2051 EXPEC3 FDB DUP,CLITER
2052 FCB $D ( carriage return )
2055 FDB LEAVE,DROP,BL,ZERO,BRAN
2058 EXPEC5 FDB I,CSTORE,ZERO,I,ONEP,STORE
2059 EXPEC6 FDB EMIT,XLOOP
2066 FCC 'QUER' ; 'QUERY'
2069 QUERY FDB DOCOL,TIB,AT,COLUMS
2070 FDB AT,EXPECT,ZERO,IN,STORE
2074 FCB $C1 immediate < carriage return >
2077 NULL FDB DOCOL,BLK,AT,ZBRAN
2080 FDB ZERO,IN,STORE,BLK,AT,BSCR,MOD
2082 * check for end of screen
2085 FDB QEXEC,FROMR,DROP
2088 NULL2 FDB FROMR,DROP
2091 * ######>> screen 47 <<
2097 FILL FDB DOCOL,SWAP,TOR,OVER,CSTORE,DUP,ONEP
2098 FDB FROMR,ONE,SUB,CMOVE
2103 FCC 'ERAS' ; 'ERASE'
2106 ERASE FDB DOCOL,ZERO,FILL
2111 FCC 'BLANK' ; 'BLANKS'
2114 BLANKS FDB DOCOL,BL,FILL
2122 HOLD FDB DOCOL,LIT,$FFFF,HLD,PSTORE,HLD,AT,CSTORE
2130 PAD FDB DOCOL,HERE,CLITER
2135 * ######>> screen 48 <<
2141 WORD FDB DOCOL,BLK,AT,ZBRAN
2143 FDB BLK,AT,BLOCK,BRAN
2146 WORD3 FDB IN,AT,PLUS,SWAP,ENCLOS,HERE,CLITER
2148 FDB BLANKS,IN,PSTORE,OVER,SUB,TOR,R,HERE
2149 FDB CSTORE,PLUS,HERE,ONEP,FROMR,CMOVE
2152 * ######>> screen 49 <<
2155 FCC '(NUMBER' ; '(NUMBER)'
2159 PNUMB2 FDB ONEP,DUP,TOR,CAT,BASE,AT,DIGIT,ZBRAN
2161 FDB SWAP,BASE,AT,USTAR,DROP,ROT,BASE
2162 FDB AT,USTAR,DPLUS,DPL,AT,ONEP,ZBRAN
2165 PNUMB3 FDB FROMR,BRAN
2172 FCC 'NUMBE' ; 'NUMBER'
2175 NUMB FDB DOCOL,ZERO,ZERO,ROT,DUP,ONEP,CAT,CLITER
2177 FDB EQUAL,DUP,TOR,PLUS,LIT,$FFFF
2178 NUMB1 FDB DPL,STORE,PNUMB,DUP,CAT,BL,SUB
2183 FDB SUB,ZERO,QERR,ZERO,BRAN
2185 NUMB2 FDB DROP,FROMR,ZBRAN
2192 FCC '-FIN' ; '-FIND'
2195 DFIND FDB DOCOL,BL,WORD,HERE,CONTXT,AT,AT
2196 FDB PFIND,DUP,ZEQU,ZBRAN
2198 FDB DROP,HERE,LATEST,PFIND
2201 * ######>> screen 50 <<
2204 FCC '(ABORT' ; '(ABORT)'
2207 PABORT FDB DOCOL,ABORT
2212 FCC 'ERRO' ; 'ERROR'
2215 ERROR FDB DOCOL,WARN,AT,ZLESS
2217 * note: WARNING is -1 to abort, 0 to print error #
2218 * and 1 to print error message from disc
2221 ERROR2 FDB HERE,COUNT,TYPE,PDOTQ
2224 FDB MESS,SPSTOR,IN,AT,BLK,AT,QUIT
2232 IDDOT FDB DOCOL,PAD,CLITER
2235 FCB $5F ( underline )
2236 FDB FILL,DUP,PFA,LFA,OVER,SUB,PAD
2237 FDB SWAP,CMOVE,PAD,COUNT,CLITER
2242 * ######>> screen 51 <<
2245 FCC 'CREAT' ; 'CREATE'
2248 CREATE FDB DOCOL,DFIND,ZBRAN
2254 FDB NFA,IDDOT,CLITER
2257 CREAT2 FDB HERE,DUP,CAT,WIDTH,AT,MIN
2258 FDB ONEP,ALLOT,DUP,CLITER
2260 FDB TOGGLE,HERE,ONE,SUB,CLITER
2262 FDB TOGGLE,LATEST,COMMA,CURENT,AT,STORE
2266 * ######>> screen 52 <<
2269 FCC '[COMPILE' ; '[COMPILE]'
2272 BCOMP FDB DOCOL,DFIND,ZEQU,ZERO,QERR,DROP,CFA,COMMA
2277 FCC 'LITERA' ; 'LITERAL'
2280 LITER FDB DOCOL,STATE,AT,ZBRAN
2282 FDB COMPIL,LIT,COMMA
2287 FCC 'DLITERA' ; 'DLITERAL'
2290 DLITER FDB DOCOL,STATE,AT,ZBRAN
2292 FDB SWAP,LITER,LITER
2295 * ######>> screen 53 <<
2298 FCC 'INTERPRE' ; 'INTERPRET'
2302 INTER2 FDB DFIND,ZBRAN
2312 INTER5 FDB HERE,NUMB,DPL,AT,ONEP,ZBRAN
2316 INTER6 FDB DROP,LITER
2317 INTER7 FDB QSTACK,BRAN
2319 * FDB SEMIS never executed
2322 * ######>> screen 54 <<
2325 FCC 'IMMEDIAT' ; 'IMMEDIATE'
2328 IMMED FDB DOCOL,LATEST,CLITER
2335 FCC 'VOCABULAR' ; 'VOCABULARY'
2338 VOCAB FDB DOCOL,BUILDS,LIT,$81A0,COMMA,CURENT,AT,CFA
2339 FDB COMMA,HERE,VOCLIN,AT,COMMA,VOCLIN,STORE,DOES
2340 DOVOC FDB TWOP,CONTXT,STORE
2345 * Note: FORTH does not go here in the rom-able dictionary,
2346 * since FORTH is a type of variable.
2351 FCC 'DEFINITION' ; 'DEFINITIONS'
2354 DEFIN FDB DOCOL,CONTXT,AT,CURENT,STORE
2361 PAREN FDB DOCOL,CLITER
2366 * ######>> screen 55 <<
2372 QUIT FDB DOCOL,ZERO,BLK,STORE
2375 * Here is the outer interpretter
2376 * which gets a line of input, does it, prints " OK"
2378 QUIT2 FDB RPSTOR,CR,QUERY,INTERP,STATE,AT,ZEQU
2386 * FDB SEMIS ( never executed )
2390 FCC 'ABOR' ; 'ABORT'
2393 ABORT FDB DOCOL,SPSTOR,DEC,QSTACK,DRZERO,CR,PDOTQ
2398 * FDB SEMIS never executed
2401 * ######>> screen 56 <<
2402 * bootstrap code... moves rom contents to ram :
2409 CENT LDS #REND-1 top of destination
2410 LDX #ERAM top of stuff to move
2413 PSHU A ; move TASK & FORTH to ram
2417 LDS #XFENCE-1 put stack at a safe place for now
2430 WENT LDS #XFENCE-1 top of destination
2431 LDX #FENCIN top of stuff to move
2440 STX UP init user ram pointer
2443 NOP Here is a place to jump to special user
2444 NOP initializations such as I/0 interrups
2447 * For systems with TRACE:
2449 STX TRLIM clear trace mode
2451 STX BRKPT clear breakpoint address
2452 JMP RPSTOR+2 start the virtual machine running !
2454 * Here is the stuff that gets copied to ram :
2457 RAM FDB $3000,$3000,0,0
2461 FCC 'FORT' ; 'FORTH'
2464 RFORTH FDB DODOES,DOVOC,$81A0,TASK-7
2466 FCC "(C) Forth Interest Group, 1979"
2471 RTASK FDB DOCOL,SEMIS
2472 ERAM FCC "David Lion"
2475 * ######>> screen 57 <<
2481 STOD FDB DOCOL,DUP,ZLESS,MINUS
2501 SLMOD FDB DOCOL,TOR,STOD,FROMR,USLASH
2508 SLASH FDB DOCOL,SLMOD,SWAP,DROP
2516 MOD FDB DOCOL,SLMOD,DROP
2521 FCC '*/MO' ; '*/MOD'
2524 SSMOD FDB DOCOL,TOR,USTAR,FROMR,USLASH
2532 SSLASH FDB DOCOL,SSMOD,SWAP,DROP
2537 FCC 'M/MO' ; 'M/MOD'
2540 MSMOD FDB DOCOL,TOR,ZERO,R,USLASH
2541 FDB FROMR,SWAP,TOR,USLASH,FROMR
2549 ABS FDB DOCOL,DUP,ZLESS,ZBRAN
2559 DABS FDB DOCOL,DUP,ZLESS,ZBRAN
2564 * ######>> screen 58 <<
2585 PBUF FDB DOCOL,CLITER
2587 FDB PLUS,DUP,LIMIT,EQUAL,ZBRAN
2590 PBUF2 FDB DUP,PREV,AT,SUB
2595 FCC 'UPDAT' ; 'UPDATE'
2598 UPDATE FDB DOCOL,PREV,AT,AT,LIT,$8000,OR,PREV,AT,STORE
2603 FCC 'EMPTY-BUFFER' ; 'EMPTY-BUFFERS'
2606 MTBUF FDB DOCOL,FIRST,LIMIT,OVER,SUB,ERASE
2614 DRZERO FDB DOCOL,ZERO,OFSET,STORE
2617 * ======>> 174 <<== system dependant word
2622 DRONE FDB DOCOL,LIT,$07D0,OFSET,STORE
2625 * ######>> screen 59 <<
2628 FCC 'BUFFE' ; 'BUFFER'
2631 BUFFER FDB DOCOL,USE,AT,DUP,TOR
2632 BUFFR2 FDB PBUF,ZBRAN
2634 FDB USE,STORE,R,AT,ZLESS
2637 FDB R,TWOP,R,AT,LIT,$7FFF,AND,ZERO,RW
2638 BUFFR3 FDB R,STORE,R,PREV,STORE,FROMR,TWOP
2641 * ######>> screen 60 <<
2644 FCC 'BLOC' ; 'BLOCK'
2647 BLOCK FDB DOCOL,OFSET,AT,PLUS,TOR
2648 FDB PREV,AT,DUP,AT,R,SUB,DUP,PLUS,ZBRAN
2650 BLOCK3 FDB PBUF,ZEQU,ZBRAN
2652 FDB DROP,R,BUFFER,DUP,R,ONE,RW,TWO,SUB
2653 BLOCK4 FDB DUP,AT,R,SUB,DUP,PLUS,ZEQU,ZBRAN
2656 BLOCK5 FDB FROMR,DROP,TWOP
2659 * ######>> screen 61 <<
2662 FCC '(LINE' ; '(LINE)'
2665 PLINE FDB DOCOL,TOR,CLITER
2667 FDB BBUF,SSMOD,FROMR,BSCR,STAR,PLUS,BLOCK,PLUS,CLITER
2673 FCC '.LIN' ; '.LINE'
2676 DLINE FDB DOCOL,PLINE,DTRAIL,TYPE
2681 FCC 'MESSAG' ; 'MESSAGE'
2684 MESS FDB DOCOL,WARN,AT,ZBRAN
2690 FDB OFSET,AT,BSCR,SLASH,SUB,DLINE,BRAN
2694 FCC 'err # ' ; 'err # '
2700 FCC 'LOA' ; 'LOAD' : input:scr #
2703 LOAD FDB DOCOL,BLK,AT,TOR,IN,AT,TOR,ZERO,IN,STORE
2704 FDB BSCR,STAR,BLK,STORE
2705 FDB INTERP,FROMR,IN,STORE,FROMR,BLK,STORE
2713 ARROW FDB DOCOL,QLOAD,ZERO,IN,STORE,BSCR
2714 FDB BLK,AT,OVER,MOD,SUB,BLK,PSTORE
2719 * ######>> screen 63 <<
2720 * The next 4 subroutines are machine dependent, and are
2721 * called by words 13 through 16 in the dictionary.
2723 * ======>> 182 << code for EMIT
2727 BITB #2 check ready bit
2728 BEQ PEMIT+4 if not ready for more data
2734 RTS only A register may change
2735 * PEMIT JMP $E1D1 for MIKBUG
2736 * PEMIT FCB $3F,$11,$39 for PROTO
2737 * PEMIT JMP $D286 for Smoke Signal DOS
2739 * ======>> 183 << code for KEY
2744 BCC PKEY+4 no incoming data yet
2746 ANDA #$7F strip parity bit
2748 STB IOSTAT+1-UORIG,X
2752 * PKEY JMP $E1AC for MIKBUG
2753 * PKEY FCB $3F,$14,$39 for PROTO
2754 * PKEY JMP $D289 for Smoke Signal DOS
2756 * ######>> screen 64 <<
2757 * ======>> 184 << code for ?TERMINAL
2758 PQTER LDA ACIAC Test for 'break' condition
2759 ANDA #$11 mask framing error bit and
2762 LDA ACIAD clear input buffer
2769 * ======>> 185 << code for CR
2770 PCR LDA #$D carriage return
2776 LDB XDELAY+1-UORIG,X
2778 BMI PQTER2 return if minus
2779 PSHU B ; save counter
2780 BSR PEMIT print RUBOUTs to delay.....
2787 * ######>> screen 66 <<
2790 FCC '?DIS' ; '?DISC'
2796 * ######>> screen 67 <<
2799 FCC 'BLOCK-WRIT' ; 'BLOCK-WRITE'
2805 * ######>> screen 68 <<
2808 FCC 'BLOCK-REA' ; 'BLOCK-READ'
2814 *The next 3 words are written to create a substitute for disc
2815 * mass memory,located between $3210 & $3FFF in ram.
2822 FDB MEMEND a system dependent equate at front
2830 FDB MEMTOP ( $3FFF in this version )
2832 * ######>> screen 69 <<
2838 RW FDB DOCOL,TOR,BBUF,STAR,LO,PLUS,DUP,HI,GREAT,ZBRAN
2842 FCC ' Range ?' ; ' Range ?'
2850 * ######>> screen 72 <<
2855 TICK FDB DOCOL,DFIND,ZEQU,ZERO,QERR,DROP,LITER
2860 FCC 'FORGE' ; 'FORGET'
2863 FORGET FDB DOCOL,CURENT,AT,CONTXT,AT,SUB,CLITER
2865 FDB QERR,TICK,DUP,FENCE,AT,LESS,CLITER
2867 FDB QERR,DUP,ZERO,PORIG,GREAT,CLITER
2869 FDB QERR,DUP,NFA,DP,STORE,LFA,AT,CONTXT,AT,STORE
2872 * ######>> screen 73 <<
2878 BACK FDB DOCOL,HERE,SUB,COMMA
2883 FCC 'BEGI' ; 'BEGIN'
2886 BEGIN FDB DOCOL,QCOMP,HERE,ONE
2891 FCC 'ENDI' ; 'ENDIF'
2894 ENDIF FDB DOCOL,QCOMP,TWO,QPAIRS,HERE
2895 FDB OVER,SUB,SWAP,STORE
2903 THEN FDB DOCOL,ENDIF
2911 DO FDB DOCOL,COMPIL,XDO,HERE,THREE
2919 LOOP FDB DOCOL,THREE,QPAIRS,COMPIL,XLOOP,BACK
2924 FCC '+LOO' ; '+LOOP'
2927 PLOOP FDB DOCOL,THREE,QPAIRS,COMPIL,XPLOOP,BACK
2932 FCC 'UNTI' ; 'UNTIL' : ( same as END )
2935 UNTIL FDB DOCOL,ONE,QPAIRS,COMPIL,ZBRAN,BACK
2938 * ######>> screen 74 <<
2949 FCC 'AGAI' ; 'AGAIN'
2952 AGAIN FDB DOCOL,ONE,QPAIRS,COMPIL,BRAN,BACK
2957 FCC 'REPEA' ; 'REPEAT'
2960 REPEAT FDB DOCOL,TOR,TOR,AGAIN,FROMR,FROMR
2969 IF FDB DOCOL,COMPIL,ZBRAN,HERE,ZERO,COMMA,TWO
2977 ELSE FDB DOCOL,TWO,QPAIRS,COMPIL,BRAN,HERE
2978 FDB ZERO,COMMA,SWAP,TWO,ENDIF,TWO
2983 FCC 'WHIL' ; 'WHILE'
2986 WHILE FDB DOCOL,IF,TWOP
2989 * ######>> screen 75 <<
2992 FCC 'SPACE' ; 'SPACES'
2995 SPACES FDB DOCOL,ZERO,MAX,DDUP,ZBRAN
2998 SPACE2 FDB SPACE,XLOOP
3007 BDIGS FDB DOCOL,PAD,HLD,STORE
3015 EDIGS FDB DOCOL,DROP,DROP,HLD,AT,PAD,OVER,SUB
3023 SIGN FDB DOCOL,ROT,ZLESS,ZBRAN
3034 DIG FDB DOCOL,BASE,AT,MSMOD,ROT,CLITER
3052 DIGS2 FDB DIG,OVER,OVER,OR,ZEQU,ZBRAN
3056 * ######>> screen 76 <<
3062 DOTR FDB DOCOL,TOR,STOD,FROMR,DDOTR
3070 DDOTR FDB DOCOL,TOR,SWAP,OVER,DABS,BDIGS,DIGS,SIGN
3071 FDB EDIGS,FROMR,OVER,SUB,SPACES,TYPE
3079 DDOT FDB DOCOL,ZERO,DDOTR,SPACE
3086 DOT FDB DOCOL,STOD,DDOT
3093 QUEST FDB DOCOL,AT,DOT
3096 * ######>> screen 77 <<
3102 LIST FDB DOCOL,DEC,CR,DUP,SCR,STORE,PDOTQ
3108 LIST2 FDB CR,I,THREE
3109 FDB DOTR,SPACE,I,SCR,AT,DLINE,XLOOP
3116 FCC 'INDE' ; 'INDEX'
3119 INDEX FDB DOCOL,CR,ONEP,SWAP,XDO
3120 INDEX2 FDB CR,I,THREE
3121 FDB DOTR,SPACE,ZERO,I,DLINE
3131 FCC 'TRIA' ; 'TRIAD'
3134 TRIAD FDB DOCOL,THREE,SLASH,THREE,STAR
3135 FDB THREE,OVER,PLUS,SWAP,XDO
3137 FDB LIST,QTERM,ZBRAN
3147 * ######>> screen 78 <<
3150 FCC 'VLIS' ; 'VLIST'
3153 VLIST FDB DOCOL,CLITER
3155 FDB OUT,STORE,CONTXT,AT,AT
3156 VLIST1 FDB OUT,AT,COLUMS,AT,CLITER
3160 FDB CR,ZERO,OUT,STORE
3161 VLIST2 FDB DUP,IDDOT,SPACE,SPACE,PFA,LFA,AT
3162 FDB DUP,ZEQU,QTERM,OR,ZBRAN
3172 NOOP FDB NEXT a useful no-op
3173 ZZZZ FDB 0,0,0,0,0,0,0,0 end of rom program