mirror of https://github.com/wwarthen/RomWBW.git
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
4464 lines
178 KiB
4464 lines
178 KiB
Z80MR VER 1.2 FILE CAMEL80
|
|
|
|
|
|
; Listing 2.
|
|
; ===============================================
|
|
; CamelForth for the Zilog Z80
|
|
; Copyright (c) 1994,1995 Bradford J. Rodriguez
|
|
;
|
|
; This program is free software; you can redistribute it and/or modify
|
|
; it under the terms of the GNU General Public License as published by
|
|
; the Free Software Foundation; either version 3 of the License, or
|
|
; (at your option) any later version.
|
|
;
|
|
; This program is distributed in the hope that it will be useful,
|
|
; but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
; GNU General Public License for more details.
|
|
;
|
|
; You should have received a copy of the GNU General Public License
|
|
; along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
; Commercial inquiries should be directed to the author at
|
|
; 115 First St., #105, Collingwood, Ontario L9Y 4W3 Canada
|
|
; or via email to bj@camelforth.com
|
|
;
|
|
; ===============================================
|
|
; CAMEL80.AZM: Code Primitives
|
|
; Source code is for the Z80MR macro assembler.
|
|
; Forth words are documented as follows:
|
|
;x NAME stack -- stack description
|
|
; where x=C for ANS Forth Core words, X for ANS
|
|
; Extensions, Z for internal or private words.
|
|
;
|
|
; Direct-Threaded Forth model for Zilog Z80
|
|
; 16 bit cell, 8 bit char, 8 bit (byte) adrs unit
|
|
; Z80 BC = Forth TOS (top Param Stack item)
|
|
; HL = W working register
|
|
; DE = IP Interpreter Pointer
|
|
; SP = PSP Param Stack Pointer
|
|
; IX = RSP Return Stack Pointer
|
|
; IY = UP User area Pointer
|
|
; A, alternate register set = temporaries
|
|
;
|
|
; Revision history:
|
|
; 19 Aug 94 v1.0
|
|
; 25 Jan 95 v1.01 now using BDOS function 0Ah
|
|
; for interpreter input; TIB at 82h.
|
|
; 02 Mar 95 v1.02 changed ALIGN to ALIGNED in
|
|
; S" (S"); changed ,BRANCH to ,XT in DO.
|
|
; ===============================================
|
|
; Macros to define Forth headers
|
|
; HEAD label,length,name,action
|
|
; IMMED label,length,name,action
|
|
; label = assembler name for this word
|
|
; (special characters not allowed)
|
|
; length = length of name field
|
|
; name = Forth's name for this word
|
|
; action = code routine for this word, e.g.
|
|
; DOCOLON, or DOCODE for code words
|
|
; IMMED defines a header for an IMMEDIATE word.
|
|
;
|
|
0000 DOCODE EQU 0 ; flag to indicate CODE words
|
|
0000 link DEFL 0 ; link to previous Forth word
|
|
|
|
head MACRO #label,#length,#name,#action
|
|
DW link
|
|
DB 0
|
|
link DEFL $
|
|
DB #length,'#name'
|
|
#label:
|
|
IF .NOT.(#action=DOCODE)
|
|
call #action
|
|
ENDIF
|
|
ENDM
|
|
|
|
immed MACRO #label,#length,#name,#action
|
|
DW link
|
|
DB 1
|
|
link DEFL $
|
|
DB #length,'#name'
|
|
#label:
|
|
IF .NOT.(#action=DOCODE)
|
|
call #action
|
|
ENDIF
|
|
ENDM
|
|
|
|
; The NEXT macro (7 bytes) assembles the 'next'
|
|
; code in-line in every Z80 CamelForth CODE word.
|
|
next MACRO
|
|
ex de,hl
|
|
ld e,(hl)
|
|
inc hl
|
|
ld d,(hl)
|
|
inc hl
|
|
ex de,hl
|
|
jp (hl)
|
|
ENDM
|
|
|
|
; NEXTHL is used when the IP is already in HL.
|
|
nexthl MACRO
|
|
ld e,(hl)
|
|
inc hl
|
|
ld d,(hl)
|
|
inc hl
|
|
ex de,hl
|
|
jp (hl)
|
|
ENDM
|
|
|
|
; RESET AND INTERRUPT VECTORS ===================
|
|
; ...are not used in the CP/M implementation
|
|
; Instead, we have the...
|
|
|
|
; CP/M ENTRY POINT
|
|
0100 org 100h
|
|
0100 2A0600 reset: ld hl,(6h) ; BDOS address, rounded down
|
|
0103 2E00 ld l,0 ; = end of avail.mem (EM)
|
|
0105 25 dec h ; EM-100h
|
|
0106 F9 ld sp,hl ; = top of param stack
|
|
0107 24 inc h ; EM
|
|
0108 E5 push hl
|
|
0109 DDE1 pop ix ; = top of return stack
|
|
010B 25 dec h ; EM-200h
|
|
010C 25 dec h
|
|
010D E5 push hl
|
|
010E FDE1 pop iy ; = bottom of user area
|
|
0110 110100 ld de,1 ; do reset if COLD returns
|
|
0113 C3A916 jp COLD ; enter top-level Forth word
|
|
|
|
; Memory map:
|
|
; 0080h Terminal Input Buffer, 128 bytes
|
|
; 0100h Forth kernel = start of CP/M TPA
|
|
; ? h Forth dictionary (user RAM)
|
|
; EM-200h User area, 128 bytes
|
|
; EM-180h Parameter stack, 128B, grows down
|
|
; EM-100h HOLD area, 40 bytes, grows down
|
|
; EM-0D8h PAD buffer, 88 bytes
|
|
; EM-80h Return stack, 128 B, grows down
|
|
; EM End of RAM = start of CP/M BDOS
|
|
; See also the definitions of U0, S0, and R0
|
|
; in the "system variables & constants" area.
|
|
; A task w/o terminal input requires 200h bytes.
|
|
; Double all except TIB and PAD for 32-bit CPUs.
|
|
|
|
; INTERPRETER LOGIC =============================
|
|
; See also "defining words" at end of this file
|
|
|
|
;C EXIT -- exit a colon definition
|
|
0116 head EXIT,4,EXIT,docode
|
|
0116 0000 + DW link
|
|
0118 00 + DB 0
|
|
0119 +link DEFL $
|
|
0119 04455849 + DB 4,'EXIT'
|
|
011E +EXIT:
|
|
+ IF .NOT.(DOCODE=DOCODE)
|
|
+ call DOCODE
|
|
+ ENDIF
|
|
011E DD5E00 ld e,(ix+0) ; pop old IP from ret stk
|
|
0121 DD23 inc ix
|
|
0123 DD5600 ld d,(ix+0)
|
|
0126 DD23 inc ix
|
|
0128 next
|
|
0128 EB + ex de,hl
|
|
0129 5E + ld e,(hl)
|
|
012A 23 + inc hl
|
|
012B 56 + ld d,(hl)
|
|
012C 23 + inc hl
|
|
012D EB + ex de,hl
|
|
012E E9 + jp (hl)
|
|
|
|
;Z lit -- x fetch inline literal to stack
|
|
; This is the primtive compiled by LITERAL.
|
|
012F head lit,3,lit,docode
|
|
012F 1901 + DW link
|
|
0131 00 + DB 0
|
|
0132 +link DEFL $
|
|
0132 034C4954 + DB 3,'LIT'
|
|
0136 +LIT:
|
|
+ IF .NOT.(DOCODE=DOCODE)
|
|
+ call DOCODE
|
|
+ ENDIF
|
|
0136 C5 push bc ; push old TOS
|
|
0137 1A ld a,(de) ; fetch cell at IP to TOS,
|
|
0138 4F ld c,a ; advancing IP
|
|
0139 13 inc de
|
|
013A 1A ld a,(de)
|
|
013B 47 ld b,a
|
|
013C 13 inc de
|
|
013D next
|
|
013D EB + ex de,hl
|
|
013E 5E + ld e,(hl)
|
|
013F 23 + inc hl
|
|
0140 56 + ld d,(hl)
|
|
0141 23 + inc hl
|
|
0142 EB + ex de,hl
|
|
0143 E9 + jp (hl)
|
|
|
|
;C EXECUTE i*x xt -- j*x execute Forth word
|
|
;C at 'xt'
|
|
0144 head EXECUTE,7,EXECUTE,docode
|
|
0144 3201 + DW link
|
|
0146 00 + DB 0
|
|
0147 +link DEFL $
|
|
0147 07455845 + DB 7,'EXECUTE'
|
|
014F +EXECUTE:
|
|
+ IF .NOT.(DOCODE=DOCODE)
|
|
+ call DOCODE
|
|
+ ENDIF
|
|
014F 60 ld h,b ; address of word -> HL
|
|
0150 69 ld l,c
|
|
0151 C1 pop bc ; get new TOS
|
|
0152 E9 jp (hl) ; go do Forth word
|
|
|
|
; DEFINING WORDS ================================
|
|
|
|
; ENTER, a.k.a. DOCOLON, entered by CALL ENTER
|
|
; to enter a new high-level thread (colon def'n.)
|
|
; (internal code fragment, not a Forth word)
|
|
; N.B.: DOCOLON must be defined before any
|
|
; appearance of 'docolon' in a 'word' macro!
|
|
0153 docolon: ; (alternate name)
|
|
0153 DD2B enter: dec ix ; push old IP on ret stack
|
|
0155 DD7200 ld (ix+0),d
|
|
0158 DD2B dec ix
|
|
015A DD7300 ld (ix+0),e
|
|
015D E1 pop hl ; param field adrs -> IP
|
|
015E nexthl ; use the faster 'nexthl'
|
|
015E 5E + ld e,(hl)
|
|
015F 23 + inc hl
|
|
0160 56 + ld d,(hl)
|
|
0161 23 + inc hl
|
|
0162 EB + ex de,hl
|
|
0163 E9 + jp (hl)
|
|
|
|
;C VARIABLE -- define a Forth variable
|
|
; CREATE 1 CELLS ALLOT ;
|
|
; Action of RAM variable is identical to CREATE,
|
|
; so we don't need a DOES> clause to change it.
|
|
0164 head VARIABLE,8,VARIABLE,docolon
|
|
0164 4701 + DW link
|
|
0166 00 + DB 0
|
|
0167 +link DEFL $
|
|
0167 08564152 + DB 8,'VARIABLE'
|
|
0170 +VARIABLE:
|
|
+ IF .NOT.(DOCOLON=DOCODE)
|
|
0170 CD5301 + call DOCOLON
|
|
+ ENDIF
|
|
0173 15133601 DW CREATE,LIT,1,CELLS,ALLOT,EXIT
|
|
; DOVAR, code action of VARIABLE, entered by CALL
|
|
; DOCREATE, code action of newly created words
|
|
017F docreate:
|
|
017F dovar: ; -- a-addr
|
|
017F E1 pop hl ; parameter field address
|
|
0180 C5 push bc ; push old TOS
|
|
0181 44 ld b,h ; pfa = variable's adrs -> TOS
|
|
0182 4D ld c,l
|
|
0183 next
|
|
0183 EB + ex de,hl
|
|
0184 5E + ld e,(hl)
|
|
0185 23 + inc hl
|
|
0186 56 + ld d,(hl)
|
|
0187 23 + inc hl
|
|
0188 EB + ex de,hl
|
|
0189 E9 + jp (hl)
|
|
|
|
;C CONSTANT n -- define a Forth constant
|
|
; CREATE , DOES> (machine code fragment)
|
|
018A head CONSTANT,8,CONSTANT,docolon
|
|
018A 6701 + DW link
|
|
018C 00 + DB 0
|
|
018D +link DEFL $
|
|
018D 08434F4E + DB 8,'CONSTANT'
|
|
0196 +CONSTANT:
|
|
+ IF .NOT.(DOCOLON=DOCODE)
|
|
0196 CD5301 + call DOCOLON
|
|
+ ENDIF
|
|
0199 1513310F DW CREATE,COMMA,XDOES
|
|
; DOCON, code action of CONSTANT,
|
|
; entered by CALL DOCON
|
|
019F docon: ; -- x
|
|
019F E1 pop hl ; parameter field address
|
|
01A0 C5 push bc ; push old TOS
|
|
01A1 4E ld c,(hl) ; fetch contents of parameter
|
|
01A2 23 inc hl ; field -> TOS
|
|
01A3 46 ld b,(hl)
|
|
01A4 next
|
|
01A4 EB + ex de,hl
|
|
01A5 5E + ld e,(hl)
|
|
01A6 23 + inc hl
|
|
01A7 56 + ld d,(hl)
|
|
01A8 23 + inc hl
|
|
01A9 EB + ex de,hl
|
|
01AA E9 + jp (hl)
|
|
|
|
;Z USER n -- define user variable 'n'
|
|
; CREATE , DOES> (machine code fragment)
|
|
01AB head USER,4,USER,docolon
|
|
01AB 8D01 + DW link
|
|
01AD 00 + DB 0
|
|
01AE +link DEFL $
|
|
01AE 04555345 + DB 4,'USER'
|
|
01B3 +USER:
|
|
+ IF .NOT.(DOCOLON=DOCODE)
|
|
01B3 CD5301 + call DOCOLON
|
|
+ ENDIF
|
|
01B6 1513310F DW CREATE,COMMA,XDOES
|
|
; DOUSER, code action of USER,
|
|
; entered by CALL DOUSER
|
|
01BC douser: ; -- a-addr
|
|
01BC E1 pop hl ; parameter field address
|
|
01BD C5 push bc ; push old TOS
|
|
01BE 4E ld c,(hl) ; fetch contents of parameter
|
|
01BF 23 inc hl ; field
|
|
01C0 46 ld b,(hl)
|
|
01C1 FDE5 push iy ; copy user base address to HL
|
|
01C3 E1 pop hl
|
|
01C4 09 add hl,bc ; and add offset
|
|
01C5 44 ld b,h ; put result in TOS
|
|
01C6 4D ld c,l
|
|
01C7 next
|
|
01C7 EB + ex de,hl
|
|
01C8 5E + ld e,(hl)
|
|
01C9 23 + inc hl
|
|
01CA 56 + ld d,(hl)
|
|
01CB 23 + inc hl
|
|
01CC EB + ex de,hl
|
|
01CD E9 + jp (hl)
|
|
|
|
; DODOES, code action of DOES> clause
|
|
; entered by CALL fragment
|
|
; parameter field
|
|
; ...
|
|
; fragment: CALL DODOES
|
|
; high-level thread
|
|
; Enters high-level thread with address of
|
|
; parameter field on top of stack.
|
|
; (internal code fragment, not a Forth word)
|
|
01CE dodoes: ; -- a-addr
|
|
01CE DD2B dec ix ; push old IP on ret stk
|
|
01D0 DD7200 ld (ix+0),d
|
|
01D3 DD2B dec ix
|
|
01D5 DD7300 ld (ix+0),e
|
|
01D8 D1 pop de ; adrs of new thread -> IP
|
|
01D9 E1 pop hl ; adrs of parameter field
|
|
01DA C5 push bc ; push old TOS onto stack
|
|
01DB 44 ld b,h ; pfa -> new TOS
|
|
01DC 4D ld c,l
|
|
01DD next
|
|
01DD EB + ex de,hl
|
|
01DE 5E + ld e,(hl)
|
|
01DF 23 + inc hl
|
|
01E0 56 + ld d,(hl)
|
|
01E1 23 + inc hl
|
|
01E2 EB + ex de,hl
|
|
01E3 E9 + jp (hl)
|
|
|
|
; CP/M TERMINAL I/O =============================
|
|
0005 cpmbdos EQU 5h ; CP/M BDOS entry point
|
|
|
|
;Z BDOS de c -- a call CP/M BDOS
|
|
01E4 head BDOS,4,BDOS,docode
|
|
01E4 AE01 + DW link
|
|
01E6 00 + DB 0
|
|
01E7 +link DEFL $
|
|
01E7 0442444F + DB 4,'BDOS'
|
|
01EC +BDOS:
|
|
+ IF .NOT.(DOCODE=DOCODE)
|
|
+ call DOCODE
|
|
+ ENDIF
|
|
01EC EB ex de,hl ; save important Forth regs
|
|
01ED D1 pop de ; (DE,IX,IY) & pop DE value
|
|
01EE E5 push hl
|
|
01EF DDE5 push ix
|
|
01F1 FDE5 push iy
|
|
01F3 CD0500 call cpmbdos
|
|
01F6 4F ld c,a ; result in TOS
|
|
01F7 0600 ld b,0
|
|
01F9 FDE1 pop iy ; restore Forth regs
|
|
01FB DDE1 pop ix
|
|
01FD D1 pop de
|
|
01FE next
|
|
01FE EB + ex de,hl
|
|
01FF 5E + ld e,(hl)
|
|
0200 23 + inc hl
|
|
0201 56 + ld d,(hl)
|
|
0202 23 + inc hl
|
|
0203 EB + ex de,hl
|
|
0204 E9 + jp (hl)
|
|
|
|
;C EMIT c -- output character to console
|
|
; 6 BDOS DROP ;
|
|
; warning: if c=0ffh, will read one keypress
|
|
0205 head EMIT,4,EMIT,docolon
|
|
0205 E701 + DW link
|
|
0207 00 + DB 0
|
|
0208 +link DEFL $
|
|
0208 04454D49 + DB 4,'EMIT'
|
|
020D +EMIT:
|
|
+ IF .NOT.(DOCOLON=DOCODE)
|
|
020D CD5301 + call DOCOLON
|
|
+ ENDIF
|
|
0210 36010600 DW LIT,06H,BDOS,DROP,EXIT
|
|
|
|
;Z SAVEKEY -- addr temporary storage for KEY?
|
|
021A head savekey,7,SAVEKEY,dovar
|
|
021A 0802 + DW link
|
|
021C 00 + DB 0
|
|
021D +link DEFL $
|
|
021D 07534156 + DB 7,'SAVEKEY'
|
|
0225 +SAVEKEY:
|
|
+ IF .NOT.(DOVAR=DOCODE)
|
|
0225 CD7F01 + call DOVAR
|
|
+ ENDIF
|
|
0228 0000 DW 0
|
|
|
|
;X KEY? -- f return true if char waiting
|
|
; 0FF 6 BDOS DUP SAVEKEY C! ; rtns 0 or key
|
|
; must use BDOS function 6 to work with KEY
|
|
022A head querykey,4,KEY?,docolon
|
|
022A 1D02 + DW link
|
|
022C 00 + DB 0
|
|
022D +link DEFL $
|
|
022D 044B4559 + DB 4,'KEY?'
|
|
0232 +QUERYKEY:
|
|
+ IF .NOT.(DOCOLON=DOCODE)
|
|
0232 CD5301 + call DOCOLON
|
|
+ ENDIF
|
|
0235 3601FF00 DW LIT,0FFH,LIT,06H,BDOS
|
|
023F B4022502 DW DUP,SAVEKEY,CSTORE,EXIT
|
|
|
|
;C KEY -- c get character from keyboard
|
|
; BEGIN SAVEKEY C@ 0= WHILE KEY? DROP REPEAT
|
|
; SAVEKEY C@ 0 SAVEKEY C! ;
|
|
; must use CP/M direct console I/O to avoid echo
|
|
; (BDOS function 6, contained within KEY?)
|
|
0247 head KEY,3,KEY,docolon
|
|
0247 2D02 + DW link
|
|
0249 00 + DB 0
|
|
024A +link DEFL $
|
|
024A 034B4559 + DB 3,'KEY'
|
|
024E +KEY:
|
|
+ IF .NOT.(DOCOLON=DOCODE)
|
|
024E CD5301 + call DOCOLON
|
|
+ ENDIF
|
|
0251 25020504 KEY1: DW SAVEKEY,CFETCH,ZEROEQUAL,qbranch,KEY2
|
|
025B 3202D702 DW QUERYKEY,DROP,branch,KEY1
|
|
0263 25020504 KEY2: DW SAVEKEY,CFETCH,LIT,0,SAVEKEY,CSTORE
|
|
026F 1E01 DW EXIT
|
|
|
|
;Z CPMACCEPT c-addr +n -- +n' get line of input
|
|
; SWAP 2 - TUCK C! max # of characters
|
|
; DUP 0A BDOS DROP CP/M Get Console Buffer
|
|
; 1+ C@ 0A EMIT ; get returned count
|
|
; Note: requires the two locations before c-addr
|
|
; to be available for use.
|
|
0271 head CPMACCEPT,9,CPMACCEPT,docolon
|
|
0271 4A02 + DW link
|
|
0273 00 + DB 0
|
|
0274 +link DEFL $
|
|
0274 0943504D + DB 9,'CPMACCEPT'
|
|
027E +CPMACCEPT:
|
|
+ IF .NOT.(DOCOLON=DOCODE)
|
|
027E CD5301 + call DOCOLON
|
|
+ ENDIF
|
|
0281 E7023601 DW SWOP,LIT,2,MINUS,TUCK,CSTORE
|
|
028D B4023601 DW DUP,LIT,0Ah,BDOS,DROP
|
|
0297 E1040504 DW ONEPLUS,CFETCH,LIT,0Ah,EMIT,EXIT
|
|
|
|
;X BYE i*x -- return to CP/M
|
|
02A3 head bye,3,bye,docode
|
|
02A3 7402 + DW link
|
|
02A5 00 + DB 0
|
|
02A6 +link DEFL $
|
|
02A6 03425945 + DB 3,'BYE'
|
|
02AA +BYE:
|
|
+ IF .NOT.(DOCODE=DOCODE)
|
|
+ call DOCODE
|
|
+ ENDIF
|
|
02AA C30000 jp 0
|
|
|
|
; STACK OPERATIONS ==============================
|
|
|
|
;C DUP x -- x x duplicate top of stack
|
|
02AD head DUP,3,DUP,docode
|
|
02AD A602 + DW link
|
|
02AF 00 + DB 0
|
|
02B0 +link DEFL $
|
|
02B0 03445550 + DB 3,'DUP'
|
|
02B4 +DUP:
|
|
+ IF .NOT.(DOCODE=DOCODE)
|
|
+ call DOCODE
|
|
+ ENDIF
|
|
02B4 C5 pushtos: push bc
|
|
02B5 next
|
|
02B5 EB + ex de,hl
|
|
02B6 5E + ld e,(hl)
|
|
02B7 23 + inc hl
|
|
02B8 56 + ld d,(hl)
|
|
02B9 23 + inc hl
|
|
02BA EB + ex de,hl
|
|
02BB E9 + jp (hl)
|
|
|
|
;C ?DUP x -- 0 | x x DUP if nonzero
|
|
02BC head QDUP,4,?DUP,docode
|
|
02BC B002 + DW link
|
|
02BE 00 + DB 0
|
|
02BF +link DEFL $
|
|
02BF 043F4455 + DB 4,'?DUP'
|
|
02C4 +QDUP:
|
|
+ IF .NOT.(DOCODE=DOCODE)
|
|
+ call DOCODE
|
|
+ ENDIF
|
|
02C4 78 ld a,b
|
|
02C5 B1 or c
|
|
02C6 20EC jr nz,pushtos
|
|
02C8 next
|
|
02C8 EB + ex de,hl
|
|
02C9 5E + ld e,(hl)
|
|
02CA 23 + inc hl
|
|
02CB 56 + ld d,(hl)
|
|
02CC 23 + inc hl
|
|
02CD EB + ex de,hl
|
|
02CE E9 + jp (hl)
|
|
|
|
;C DROP x -- drop top of stack
|
|
02CF head DROP,4,DROP,docode
|
|
02CF BF02 + DW link
|
|
02D1 00 + DB 0
|
|
02D2 +link DEFL $
|
|
02D2 0444524F + DB 4,'DROP'
|
|
02D7 +DROP:
|
|
+ IF .NOT.(DOCODE=DOCODE)
|
|
+ call DOCODE
|
|
+ ENDIF
|
|
02D7 C1 poptos: pop bc
|
|
02D8 next
|
|
02D8 EB + ex de,hl
|
|
02D9 5E + ld e,(hl)
|
|
02DA 23 + inc hl
|
|
02DB 56 + ld d,(hl)
|
|
02DC 23 + inc hl
|
|
02DD EB + ex de,hl
|
|
02DE E9 + jp (hl)
|
|
|
|
;C SWAP x1 x2 -- x2 x1 swap top two items
|
|
02DF head SWOP,4,SWAP,docode
|
|
02DF D202 + DW link
|
|
02E1 00 + DB 0
|
|
02E2 +link DEFL $
|
|
02E2 04535741 + DB 4,'SWAP'
|
|
02E7 +SWOP:
|
|
+ IF .NOT.(DOCODE=DOCODE)
|
|
+ call DOCODE
|
|
+ ENDIF
|
|
02E7 E1 pop hl
|
|
02E8 C5 push bc
|
|
02E9 44 ld b,h
|
|
02EA 4D ld c,l
|
|
02EB next
|
|
02EB EB + ex de,hl
|
|
02EC 5E + ld e,(hl)
|
|
02ED 23 + inc hl
|
|
02EE 56 + ld d,(hl)
|
|
02EF 23 + inc hl
|
|
02F0 EB + ex de,hl
|
|
02F1 E9 + jp (hl)
|
|
|
|
;C OVER x1 x2 -- x1 x2 x1 per stack diagram
|
|
02F2 head OVER,4,OVER,docode
|
|
02F2 E202 + DW link
|
|
02F4 00 + DB 0
|
|
02F5 +link DEFL $
|
|
02F5 044F5645 + DB 4,'OVER'
|
|
02FA +OVER:
|
|
+ IF .NOT.(DOCODE=DOCODE)
|
|
+ call DOCODE
|
|
+ ENDIF
|
|
02FA E1 pop hl
|
|
02FB E5 push hl
|
|
02FC C5 push bc
|
|
02FD 44 ld b,h
|
|
02FE 4D ld c,l
|
|
02FF next
|
|
02FF EB + ex de,hl
|
|
0300 5E + ld e,(hl)
|
|
0301 23 + inc hl
|
|
0302 56 + ld d,(hl)
|
|
0303 23 + inc hl
|
|
0304 EB + ex de,hl
|
|
0305 E9 + jp (hl)
|
|
|
|
;C ROT x1 x2 x3 -- x2 x3 x1 per stack diagram
|
|
0306 head ROT,3,ROT,docode
|
|
0306 F502 + DW link
|
|
0308 00 + DB 0
|
|
0309 +link DEFL $
|
|
0309 03524F54 + DB 3,'ROT'
|
|
030D +ROT:
|
|
+ IF .NOT.(DOCODE=DOCODE)
|
|
+ call DOCODE
|
|
+ ENDIF
|
|
; x3 is in TOS
|
|
030D E1 pop hl ; x2
|
|
030E E3 ex (sp),hl ; x2 on stack, x1 in hl
|
|
030F C5 push bc
|
|
0310 44 ld b,h
|
|
0311 4D ld c,l
|
|
0312 next
|
|
0312 EB + ex de,hl
|
|
0313 5E + ld e,(hl)
|
|
0314 23 + inc hl
|
|
0315 56 + ld d,(hl)
|
|
0316 23 + inc hl
|
|
0317 EB + ex de,hl
|
|
0318 E9 + jp (hl)
|
|
|
|
;X NIP x1 x2 -- x2 per stack diagram
|
|
0319 head NIP,3,NIP,docolon
|
|
0319 0903 + DW link
|
|
031B 00 + DB 0
|
|
031C +link DEFL $
|
|
031C 034E4950 + DB 3,'NIP'
|
|
0320 +NIP:
|
|
+ IF .NOT.(DOCOLON=DOCODE)
|
|
0320 CD5301 + call DOCOLON
|
|
+ ENDIF
|
|
0323 E702D702 DW SWOP,DROP,EXIT
|
|
|
|
;X TUCK x1 x2 -- x2 x1 x2 per stack diagram
|
|
0329 head TUCK,4,TUCK,docolon
|
|
0329 1C03 + DW link
|
|
032B 00 + DB 0
|
|
032C +link DEFL $
|
|
032C 04545543 + DB 4,'TUCK'
|
|
0331 +TUCK:
|
|
+ IF .NOT.(DOCOLON=DOCODE)
|
|
0331 CD5301 + call DOCOLON
|
|
+ ENDIF
|
|
0334 E702FA02 DW SWOP,OVER,EXIT
|
|
|
|
;C >R x -- R: -- x push to return stack
|
|
033A head TOR,2,>R,docode
|
|
033A 2C03 + DW link
|
|
033C 00 + DB 0
|
|
033D +link DEFL $
|
|
033D 023E52 + DB 2,'>R'
|
|
0340 +TOR:
|
|
+ IF .NOT.(DOCODE=DOCODE)
|
|
+ call DOCODE
|
|
+ ENDIF
|
|
0340 DD2B dec ix ; push TOS onto rtn stk
|
|
0342 DD7000 ld (ix+0),b
|
|
0345 DD2B dec ix
|
|
0347 DD7100 ld (ix+0),c
|
|
034A C1 pop bc ; pop new TOS
|
|
034B next
|
|
034B EB + ex de,hl
|
|
034C 5E + ld e,(hl)
|
|
034D 23 + inc hl
|
|
034E 56 + ld d,(hl)
|
|
034F 23 + inc hl
|
|
0350 EB + ex de,hl
|
|
0351 E9 + jp (hl)
|
|
|
|
;C R> -- x R: x -- pop from return stack
|
|
0352 head RFROM,2,R>,docode
|
|
0352 3D03 + DW link
|
|
0354 00 + DB 0
|
|
0355 +link DEFL $
|
|
0355 02523E + DB 2,'R>'
|
|
0358 +RFROM:
|
|
+ IF .NOT.(DOCODE=DOCODE)
|
|
+ call DOCODE
|
|
+ ENDIF
|
|
0358 C5 push bc ; push old TOS
|
|
0359 DD4E00 ld c,(ix+0) ; pop top rtn stk item
|
|
035C DD23 inc ix ; to TOS
|
|
035E DD4600 ld b,(ix+0)
|
|
0361 DD23 inc ix
|
|
0363 next
|
|
0363 EB + ex de,hl
|
|
0364 5E + ld e,(hl)
|
|
0365 23 + inc hl
|
|
0366 56 + ld d,(hl)
|
|
0367 23 + inc hl
|
|
0368 EB + ex de,hl
|
|
0369 E9 + jp (hl)
|
|
|
|
;C R@ -- x R: x -- x fetch from rtn stk
|
|
036A head RFETCH,2,R@,docode
|
|
036A 5503 + DW link
|
|
036C 00 + DB 0
|
|
036D +link DEFL $
|
|
036D 025240 + DB 2,'R@'
|
|
0370 +RFETCH:
|
|
+ IF .NOT.(DOCODE=DOCODE)
|
|
+ call DOCODE
|
|
+ ENDIF
|
|
0370 C5 push bc ; push old TOS
|
|
0371 DD4E00 ld c,(ix+0) ; fetch top rtn stk item
|
|
0374 DD4601 ld b,(ix+1) ; to TOS
|
|
0377 next
|
|
0377 EB + ex de,hl
|
|
0378 5E + ld e,(hl)
|
|
0379 23 + inc hl
|
|
037A 56 + ld d,(hl)
|
|
037B 23 + inc hl
|
|
037C EB + ex de,hl
|
|
037D E9 + jp (hl)
|
|
|
|
;Z SP@ -- a-addr get data stack pointer
|
|
037E head SPFETCH,3,SP@,docode
|
|
037E 6D03 + DW link
|
|
0380 00 + DB 0
|
|
0381 +link DEFL $
|
|
0381 03535040 + DB 3,'SP@'
|
|
0385 +SPFETCH:
|
|
+ IF .NOT.(DOCODE=DOCODE)
|
|
+ call DOCODE
|
|
+ ENDIF
|
|
0385 C5 push bc
|
|
0386 210000 ld hl,0
|
|
0389 39 add hl,sp
|
|
038A 44 ld b,h
|
|
038B 4D ld c,l
|
|
038C next
|
|
038C EB + ex de,hl
|
|
038D 5E + ld e,(hl)
|
|
038E 23 + inc hl
|
|
038F 56 + ld d,(hl)
|
|
0390 23 + inc hl
|
|
0391 EB + ex de,hl
|
|
0392 E9 + jp (hl)
|
|
|
|
;Z SP! a-addr -- set data stack pointer
|
|
0393 head SPSTORE,3,SP!,docode
|
|
0393 8103 + DW link
|
|
0395 00 + DB 0
|
|
0396 +link DEFL $
|
|
0396 03535021 + DB 3,'SP!'
|
|
039A +SPSTORE:
|
|
+ IF .NOT.(DOCODE=DOCODE)
|
|
+ call DOCODE
|
|
+ ENDIF
|
|
039A 60 ld h,b
|
|
039B 69 ld l,c
|
|
039C F9 ld sp,hl
|
|
039D C1 pop bc ; get new TOS
|
|
039E next
|
|
039E EB + ex de,hl
|
|
039F 5E + ld e,(hl)
|
|
03A0 23 + inc hl
|
|
03A1 56 + ld d,(hl)
|
|
03A2 23 + inc hl
|
|
03A3 EB + ex de,hl
|
|
03A4 E9 + jp (hl)
|
|
|
|
;Z RP@ -- a-addr get return stack pointer
|
|
03A5 head RPFETCH,3,RP@,docode
|
|
03A5 9603 + DW link
|
|
03A7 00 + DB 0
|
|
03A8 +link DEFL $
|
|
03A8 03525040 + DB 3,'RP@'
|
|
03AC +RPFETCH:
|
|
+ IF .NOT.(DOCODE=DOCODE)
|
|
+ call DOCODE
|
|
+ ENDIF
|
|
03AC C5 push bc
|
|
03AD DDE5 push ix
|
|
03AF C1 pop bc
|
|
03B0 next
|
|
03B0 EB + ex de,hl
|
|
03B1 5E + ld e,(hl)
|
|
03B2 23 + inc hl
|
|
03B3 56 + ld d,(hl)
|
|
03B4 23 + inc hl
|
|
03B5 EB + ex de,hl
|
|
03B6 E9 + jp (hl)
|
|
|
|
;Z RP! a-addr -- set return stack pointer
|
|
03B7 head RPSTORE,3,RP!,docode
|
|
03B7 A803 + DW link
|
|
03B9 00 + DB 0
|
|
03BA +link DEFL $
|
|
03BA 03525021 + DB 3,'RP!'
|
|
03BE +RPSTORE:
|
|
+ IF .NOT.(DOCODE=DOCODE)
|
|
+ call DOCODE
|
|
+ ENDIF
|
|
03BE C5 push bc
|
|
03BF DDE1 pop ix
|
|
03C1 C1 pop bc
|
|
03C2 next
|
|
03C2 EB + ex de,hl
|
|
03C3 5E + ld e,(hl)
|
|
03C4 23 + inc hl
|
|
03C5 56 + ld d,(hl)
|
|
03C6 23 + inc hl
|
|
03C7 EB + ex de,hl
|
|
03C8 E9 + jp (hl)
|
|
|
|
; MEMORY AND I/O OPERATIONS =====================
|
|
|
|
;C ! x a-addr -- store cell in memory
|
|
03C9 head STORE,1,!,docode
|
|
03C9 BA03 + DW link
|
|
03CB 00 + DB 0
|
|
03CC +link DEFL $
|
|
03CC 0121 + DB 1,'!'
|
|
03CE +STORE:
|
|
+ IF .NOT.(DOCODE=DOCODE)
|
|
+ call DOCODE
|
|
+ ENDIF
|
|
03CE 60 ld h,b ; address in hl
|
|
03CF 69 ld l,c
|
|
03D0 C1 pop bc ; data in bc
|
|
03D1 71 ld (hl),c
|
|
03D2 23 inc hl
|
|
03D3 70 ld (hl),b
|
|
03D4 C1 pop bc ; pop new TOS
|
|
03D5 next
|
|
03D5 EB + ex de,hl
|
|
03D6 5E + ld e,(hl)
|
|
03D7 23 + inc hl
|
|
03D8 56 + ld d,(hl)
|
|
03D9 23 + inc hl
|
|
03DA EB + ex de,hl
|
|
03DB E9 + jp (hl)
|
|
|
|
;C C! char c-addr -- store char in memory
|
|
03DC head CSTORE,2,C!,docode
|
|
03DC CC03 + DW link
|
|
03DE 00 + DB 0
|
|
03DF +link DEFL $
|
|
03DF 024321 + DB 2,'C!'
|
|
03E2 +CSTORE:
|
|
+ IF .NOT.(DOCODE=DOCODE)
|
|
+ call DOCODE
|
|
+ ENDIF
|
|
03E2 60 ld h,b ; address in hl
|
|
03E3 69 ld l,c
|
|
03E4 C1 pop bc ; data in bc
|
|
03E5 71 ld (hl),c
|
|
03E6 C1 pop bc ; pop new TOS
|
|
03E7 next
|
|
03E7 EB + ex de,hl
|
|
03E8 5E + ld e,(hl)
|
|
03E9 23 + inc hl
|
|
03EA 56 + ld d,(hl)
|
|
03EB 23 + inc hl
|
|
03EC EB + ex de,hl
|
|
03ED E9 + jp (hl)
|
|
|
|
;C @ a-addr -- x fetch cell from memory
|
|
03EE head FETCH,1,@,docode
|
|
03EE DF03 + DW link
|
|
03F0 00 + DB 0
|
|
03F1 +link DEFL $
|
|
03F1 0140 + DB 1,'@'
|
|
03F3 +FETCH:
|
|
+ IF .NOT.(DOCODE=DOCODE)
|
|
+ call DOCODE
|
|
+ ENDIF
|
|
03F3 60 ld h,b ; address in hl
|
|
03F4 69 ld l,c
|
|
03F5 4E ld c,(hl)
|
|
03F6 23 inc hl
|
|
03F7 46 ld b,(hl)
|
|
03F8 next
|
|
03F8 EB + ex de,hl
|
|
03F9 5E + ld e,(hl)
|
|
03FA 23 + inc hl
|
|
03FB 56 + ld d,(hl)
|
|
03FC 23 + inc hl
|
|
03FD EB + ex de,hl
|
|
03FE E9 + jp (hl)
|
|
|
|
;C C@ c-addr -- char fetch char from memory
|
|
03FF head CFETCH,2,C@,docode
|
|
03FF F103 + DW link
|
|
0401 00 + DB 0
|
|
0402 +link DEFL $
|
|
0402 024340 + DB 2,'C@'
|
|
0405 +CFETCH:
|
|
+ IF .NOT.(DOCODE=DOCODE)
|
|
+ call DOCODE
|
|
+ ENDIF
|
|
0405 0A ld a,(bc)
|
|
0406 4F ld c,a
|
|
0407 0600 ld b,0
|
|
0409 next
|
|
0409 EB + ex de,hl
|
|
040A 5E + ld e,(hl)
|
|
040B 23 + inc hl
|
|
040C 56 + ld d,(hl)
|
|
040D 23 + inc hl
|
|
040E EB + ex de,hl
|
|
040F E9 + jp (hl)
|
|
|
|
;Z PC! char c-addr -- output char to port
|
|
0410 head PCSTORE,3,PC!,docode
|
|
0410 0204 + DW link
|
|
0412 00 + DB 0
|
|
0413 +link DEFL $
|
|
0413 03504321 + DB 3,'PC!'
|
|
0417 +PCSTORE:
|
|
+ IF .NOT.(DOCODE=DOCODE)
|
|
+ call DOCODE
|
|
+ ENDIF
|
|
0417 E1 pop hl ; char in L
|
|
0418 ED69 out (c),l ; to port (BC)
|
|
041A C1 pop bc ; pop new TOS
|
|
041B next
|
|
041B EB + ex de,hl
|
|
041C 5E + ld e,(hl)
|
|
041D 23 + inc hl
|
|
041E 56 + ld d,(hl)
|
|
041F 23 + inc hl
|
|
0420 EB + ex de,hl
|
|
0421 E9 + jp (hl)
|
|
|
|
;Z PC@ c-addr -- char input char from port
|
|
0422 head PCFETCH,3,PC@,docode
|
|
0422 1304 + DW link
|
|
0424 00 + DB 0
|
|
0425 +link DEFL $
|
|
0425 03504340 + DB 3,'PC@'
|
|
0429 +PCFETCH:
|
|
+ IF .NOT.(DOCODE=DOCODE)
|
|
+ call DOCODE
|
|
+ ENDIF
|
|
0429 ED48 in c,(c) ; read port (BC) to C
|
|
042B 0600 ld b,0
|
|
042D next
|
|
042D EB + ex de,hl
|
|
042E 5E + ld e,(hl)
|
|
042F 23 + inc hl
|
|
0430 56 + ld d,(hl)
|
|
0431 23 + inc hl
|
|
0432 EB + ex de,hl
|
|
0433 E9 + jp (hl)
|
|
|
|
; ARITHMETIC AND LOGICAL OPERATIONS =============
|
|
|
|
;C + n1/u1 n2/u2 -- n3/u3 add n1+n2
|
|
0434 head PLUS,1,+,docode
|
|
0434 2504 + DW link
|
|
0436 00 + DB 0
|
|
0437 +link DEFL $
|
|
0437 012B + DB 1,'+'
|
|
0439 +PLUS:
|
|
+ IF .NOT.(DOCODE=DOCODE)
|
|
+ call DOCODE
|
|
+ ENDIF
|
|
0439 E1 pop hl
|
|
043A 09 add hl,bc
|
|
043B 44 ld b,h
|
|
043C 4D ld c,l
|
|
043D next
|
|
043D EB + ex de,hl
|
|
043E 5E + ld e,(hl)
|
|
043F 23 + inc hl
|
|
0440 56 + ld d,(hl)
|
|
0441 23 + inc hl
|
|
0442 EB + ex de,hl
|
|
0443 E9 + jp (hl)
|
|
|
|
;X M+ d n -- d add single to double
|
|
0444 head MPLUS,2,M+,docode
|
|
0444 3704 + DW link
|
|
0446 00 + DB 0
|
|
0447 +link DEFL $
|
|
0447 024D2B + DB 2,'M+'
|
|
044A +MPLUS:
|
|
+ IF .NOT.(DOCODE=DOCODE)
|
|
+ call DOCODE
|
|
+ ENDIF
|
|
044A EB ex de,hl
|
|
044B D1 pop de ; hi cell
|
|
044C E3 ex (sp),hl ; lo cell, save IP
|
|
044D 09 add hl,bc
|
|
044E 42 ld b,d ; hi result in BC (TOS)
|
|
044F 4B ld c,e
|
|
0450 3001 jr nc,mplus1
|
|
0452 03 inc bc
|
|
0453 D1 mplus1: pop de ; restore saved IP
|
|
0454 E5 push hl ; push lo result
|
|
0455 next
|
|
0455 EB + ex de,hl
|
|
0456 5E + ld e,(hl)
|
|
0457 23 + inc hl
|
|
0458 56 + ld d,(hl)
|
|
0459 23 + inc hl
|
|
045A EB + ex de,hl
|
|
045B E9 + jp (hl)
|
|
|
|
;C - n1/u1 n2/u2 -- n3/u3 subtract n1-n2
|
|
045C head MINUS,1,-,docode
|
|
045C 4704 + DW link
|
|
045E 00 + DB 0
|
|
045F +link DEFL $
|
|
045F 012D + DB 1,'-'
|
|
0461 +MINUS:
|
|
+ IF .NOT.(DOCODE=DOCODE)
|
|
+ call DOCODE
|
|
+ ENDIF
|
|
0461 E1 pop hl
|
|
0462 B7 or a
|
|
0463 ED42 sbc hl,bc
|
|
0465 44 ld b,h
|
|
0466 4D ld c,l
|
|
0467 next
|
|
0467 EB + ex de,hl
|
|
0468 5E + ld e,(hl)
|
|
0469 23 + inc hl
|
|
046A 56 + ld d,(hl)
|
|
046B 23 + inc hl
|
|
046C EB + ex de,hl
|
|
046D E9 + jp (hl)
|
|
|
|
;C AND x1 x2 -- x3 logical AND
|
|
046E head AND,3,AND,docode
|
|
046E 5F04 + DW link
|
|
0470 00 + DB 0
|
|
0471 +link DEFL $
|
|
0471 03414E44 + DB 3,'AND'
|
|
0475 +AND:
|
|
+ IF .NOT.(DOCODE=DOCODE)
|
|
+ call DOCODE
|
|
+ ENDIF
|
|
0475 E1 pop hl
|
|
0476 78 ld a,b
|
|
0477 A4 and h
|
|
0478 47 ld b,a
|
|
0479 79 ld a,c
|
|
047A A5 and l
|
|
047B 4F ld c,a
|
|
047C next
|
|
047C EB + ex de,hl
|
|
047D 5E + ld e,(hl)
|
|
047E 23 + inc hl
|
|
047F 56 + ld d,(hl)
|
|
0480 23 + inc hl
|
|
0481 EB + ex de,hl
|
|
0482 E9 + jp (hl)
|
|
|
|
;C OR x1 x2 -- x3 logical OR
|
|
0483 head OR,2,OR,docode
|
|
0483 7104 + DW link
|
|
0485 00 + DB 0
|
|
0486 +link DEFL $
|
|
0486 024F52 + DB 2,'OR'
|
|
0489 +OR:
|
|
+ IF .NOT.(DOCODE=DOCODE)
|
|
+ call DOCODE
|
|
+ ENDIF
|
|
0489 E1 pop hl
|
|
048A 78 ld a,b
|
|
048B B4 or h
|
|
048C 47 ld b,a
|
|
048D 79 ld a,c
|
|
048E B5 or l
|
|
048F 4F ld c,a
|
|
0490 next
|
|
0490 EB + ex de,hl
|
|
0491 5E + ld e,(hl)
|
|
0492 23 + inc hl
|
|
0493 56 + ld d,(hl)
|
|
0494 23 + inc hl
|
|
0495 EB + ex de,hl
|
|
0496 E9 + jp (hl)
|
|
|
|
;C XOR x1 x2 -- x3 logical XOR
|
|
0497 head XOR,3,XOR,docode
|
|
0497 8604 + DW link
|
|
0499 00 + DB 0
|
|
049A +link DEFL $
|
|
049A 03584F52 + DB 3,'XOR'
|
|
049E +XOR:
|
|
+ IF .NOT.(DOCODE=DOCODE)
|
|
+ call DOCODE
|
|
+ ENDIF
|
|
049E E1 pop hl
|
|
049F 78 ld a,b
|
|
04A0 AC xor h
|
|
04A1 47 ld b,a
|
|
04A2 79 ld a,c
|
|
04A3 AD xor l
|
|
04A4 4F ld c,a
|
|
04A5 next
|
|
04A5 EB + ex de,hl
|
|
04A6 5E + ld e,(hl)
|
|
04A7 23 + inc hl
|
|
04A8 56 + ld d,(hl)
|
|
04A9 23 + inc hl
|
|
04AA EB + ex de,hl
|
|
04AB E9 + jp (hl)
|
|
|
|
;C INVERT x1 -- x2 bitwise inversion
|
|
04AC head INVERT,6,INVERT,docode
|
|
04AC 9A04 + DW link
|
|
04AE 00 + DB 0
|
|
04AF +link DEFL $
|
|
04AF 06494E56 + DB 6,'INVERT'
|
|
04B6 +INVERT:
|
|
+ IF .NOT.(DOCODE=DOCODE)
|
|
+ call DOCODE
|
|
+ ENDIF
|
|
04B6 78 ld a,b
|
|
04B7 2F cpl
|
|
04B8 47 ld b,a
|
|
04B9 79 ld a,c
|
|
04BA 2F cpl
|
|
04BB 4F ld c,a
|
|
04BC next
|
|
04BC EB + ex de,hl
|
|
04BD 5E + ld e,(hl)
|
|
04BE 23 + inc hl
|
|
04BF 56 + ld d,(hl)
|
|
04C0 23 + inc hl
|
|
04C1 EB + ex de,hl
|
|
04C2 E9 + jp (hl)
|
|
|
|
;C NEGATE x1 -- x2 two's complement
|
|
04C3 head NEGATE,6,NEGATE,docode
|
|
04C3 AF04 + DW link
|
|
04C5 00 + DB 0
|
|
04C6 +link DEFL $
|
|
04C6 064E4547 + DB 6,'NEGATE'
|
|
04CD +NEGATE:
|
|
+ IF .NOT.(DOCODE=DOCODE)
|
|
+ call DOCODE
|
|
+ ENDIF
|
|
04CD 78 ld a,b
|
|
04CE 2F cpl
|
|
04CF 47 ld b,a
|
|
04D0 79 ld a,c
|
|
04D1 2F cpl
|
|
04D2 4F ld c,a
|
|
04D3 03 inc bc
|
|
04D4 next
|
|
04D4 EB + ex de,hl
|
|
04D5 5E + ld e,(hl)
|
|
04D6 23 + inc hl
|
|
04D7 56 + ld d,(hl)
|
|
04D8 23 + inc hl
|
|
04D9 EB + ex de,hl
|
|
04DA E9 + jp (hl)
|
|
|
|
;C 1+ n1/u1 -- n2/u2 add 1 to TOS
|
|
04DB head ONEPLUS,2,1+,docode
|
|
04DB C604 + DW link
|
|
04DD 00 + DB 0
|
|
04DE +link DEFL $
|
|
04DE 02312B + DB 2,'1+'
|
|
04E1 +ONEPLUS:
|
|
+ IF .NOT.(DOCODE=DOCODE)
|
|
+ call DOCODE
|
|
+ ENDIF
|
|
04E1 03 inc bc
|
|
04E2 next
|
|
04E2 EB + ex de,hl
|
|
04E3 5E + ld e,(hl)
|
|
04E4 23 + inc hl
|
|
04E5 56 + ld d,(hl)
|
|
04E6 23 + inc hl
|
|
04E7 EB + ex de,hl
|
|
04E8 E9 + jp (hl)
|
|
|
|
;C 1- n1/u1 -- n2/u2 subtract 1 from TOS
|
|
04E9 head ONEMINUS,2,1-,docode
|
|
04E9 DE04 + DW link
|
|
04EB 00 + DB 0
|
|
04EC +link DEFL $
|
|
04EC 02312D + DB 2,'1-'
|
|
04EF +ONEMINUS:
|
|
+ IF .NOT.(DOCODE=DOCODE)
|
|
+ call DOCODE
|
|
+ ENDIF
|
|
04EF 0B dec bc
|
|
04F0 next
|
|
04F0 EB + ex de,hl
|
|
04F1 5E + ld e,(hl)
|
|
04F2 23 + inc hl
|
|
04F3 56 + ld d,(hl)
|
|
04F4 23 + inc hl
|
|
04F5 EB + ex de,hl
|
|
04F6 E9 + jp (hl)
|
|
|
|
;Z >< x1 -- x2 swap bytes (not ANSI)
|
|
04F7 head swapbytes,2,><,docode
|
|
04F7 EC04 + DW link
|
|
04F9 00 + DB 0
|
|
04FA +link DEFL $
|
|
04FA 023E3C + DB 2,'><'
|
|
04FD +SWAPBYTES:
|
|
+ IF .NOT.(DOCODE=DOCODE)
|
|
+ call DOCODE
|
|
+ ENDIF
|
|
04FD 78 ld a,b
|
|
04FE 41 ld b,c
|
|
04FF 4F ld c,a
|
|
0500 next
|
|
0500 EB + ex de,hl
|
|
0501 5E + ld e,(hl)
|
|
0502 23 + inc hl
|
|
0503 56 + ld d,(hl)
|
|
0504 23 + inc hl
|
|
0505 EB + ex de,hl
|
|
0506 E9 + jp (hl)
|
|
|
|
;C 2* x1 -- x2 arithmetic left shift
|
|
0507 head TWOSTAR,2,2*,docode
|
|
0507 FA04 + DW link
|
|
0509 00 + DB 0
|
|
050A +link DEFL $
|
|
050A 02322A + DB 2,'2*'
|
|
050D +TWOSTAR:
|
|
+ IF .NOT.(DOCODE=DOCODE)
|
|
+ call DOCODE
|
|
+ ENDIF
|
|
050D CB21 sla c
|
|
050F CB10 rl b
|
|
0511 next
|
|
0511 EB + ex de,hl
|
|
0512 5E + ld e,(hl)
|
|
0513 23 + inc hl
|
|
0514 56 + ld d,(hl)
|
|
0515 23 + inc hl
|
|
0516 EB + ex de,hl
|
|
0517 E9 + jp (hl)
|
|
|
|
;C 2/ x1 -- x2 arithmetic right shift
|
|
0518 head TWOSLASH,2,2/,docode
|
|
0518 0A05 + DW link
|
|
051A 00 + DB 0
|
|
051B +link DEFL $
|
|
051B 02322F + DB 2,'2/'
|
|
051E +TWOSLASH:
|
|
+ IF .NOT.(DOCODE=DOCODE)
|
|
+ call DOCODE
|
|
+ ENDIF
|
|
051E CB28 sra b
|
|
0520 CB19 rr c
|
|
0522 next
|
|
0522 EB + ex de,hl
|
|
0523 5E + ld e,(hl)
|
|
0524 23 + inc hl
|
|
0525 56 + ld d,(hl)
|
|
0526 23 + inc hl
|
|
0527 EB + ex de,hl
|
|
0528 E9 + jp (hl)
|
|
|
|
;C LSHIFT x1 u -- x2 logical L shift u places
|
|
0529 head LSHIFT,6,LSHIFT,docode
|
|
0529 1B05 + DW link
|
|
052B 00 + DB 0
|
|
052C +link DEFL $
|
|
052C 064C5348 + DB 6,'LSHIFT'
|
|
0533 +LSHIFT:
|
|
+ IF .NOT.(DOCODE=DOCODE)
|
|
+ call DOCODE
|
|
+ ENDIF
|
|
0533 41 ld b,c ; b = loop counter
|
|
0534 E1 pop hl ; NB: hi 8 bits ignored!
|
|
0535 04 inc b ; test for counter=0 case
|
|
0536 1801 jr lsh2
|
|
0538 29 lsh1: add hl,hl ; left shift HL, n times
|
|
0539 10FD lsh2: djnz lsh1
|
|
053B 44 ld b,h ; result is new TOS
|
|
053C 4D ld c,l
|
|
053D next
|
|
053D EB + ex de,hl
|
|
053E 5E + ld e,(hl)
|
|
053F 23 + inc hl
|
|
0540 56 + ld d,(hl)
|
|
0541 23 + inc hl
|
|
0542 EB + ex de,hl
|
|
0543 E9 + jp (hl)
|
|
|
|
;C RSHIFT x1 u -- x2 logical R shift u places
|
|
0544 head RSHIFT,6,RSHIFT,docode
|
|
0544 2C05 + DW link
|
|
0546 00 + DB 0
|
|
0547 +link DEFL $
|
|
0547 06525348 + DB 6,'RSHIFT'
|
|
054E +RSHIFT:
|
|
+ IF .NOT.(DOCODE=DOCODE)
|
|
+ call DOCODE
|
|
+ ENDIF
|
|
054E 41 ld b,c ; b = loop counter
|
|
054F E1 pop hl ; NB: hi 8 bits ignored!
|
|
0550 04 inc b ; test for counter=0 case
|
|
0551 1804 jr rsh2
|
|
0553 CB3C rsh1: srl h ; right shift HL, n times
|
|
0555 CB1D rr l
|
|
0557 10FA rsh2: djnz rsh1
|
|
0559 44 ld b,h ; result is new TOS
|
|
055A 4D ld c,l
|
|
055B next
|
|
055B EB + ex de,hl
|
|
055C 5E + ld e,(hl)
|
|
055D 23 + inc hl
|
|
055E 56 + ld d,(hl)
|
|
055F 23 + inc hl
|
|
0560 EB + ex de,hl
|
|
0561 E9 + jp (hl)
|
|
|
|
;C +! n/u a-addr -- add cell to memory
|
|
0562 head PLUSSTORE,2,+!,docode
|
|
0562 4705 + DW link
|
|
0564 00 + DB 0
|
|
0565 +link DEFL $
|
|
0565 022B21 + DB 2,'+!'
|
|
0568 +PLUSSTORE:
|
|
+ IF .NOT.(DOCODE=DOCODE)
|
|
+ call DOCODE
|
|
+ ENDIF
|
|
0568 E1 pop hl
|
|
0569 0A ld a,(bc) ; low byte
|
|
056A 85 add a,l
|
|
056B 02 ld (bc),a
|
|
056C 03 inc bc
|
|
056D 0A ld a,(bc) ; high byte
|
|
056E 8C adc a,h
|
|
056F 02 ld (bc),a
|
|
0570 C1 pop bc ; pop new TOS
|
|
0571 next
|
|
0571 EB + ex de,hl
|
|
0572 5E + ld e,(hl)
|
|
0573 23 + inc hl
|
|
0574 56 + ld d,(hl)
|
|
0575 23 + inc hl
|
|
0576 EB + ex de,hl
|
|
0577 E9 + jp (hl)
|
|
|
|
; COMPARISON OPERATIONS =========================
|
|
|
|
;C 0= n/u -- flag return true if TOS=0
|
|
0578 head ZEROEQUAL,2,0=,docode
|
|
0578 6505 + DW link
|
|
057A 00 + DB 0
|
|
057B +link DEFL $
|
|
057B 02303D + DB 2,'0='
|
|
057E +ZEROEQUAL:
|
|
+ IF .NOT.(DOCODE=DOCODE)
|
|
+ call DOCODE
|
|
+ ENDIF
|
|
057E 78 ld a,b
|
|
057F B1 or c ; result=0 if bc was 0
|
|
0580 D601 sub 1 ; cy set if bc was 0
|
|
0582 9F sbc a,a ; propagate cy through A
|
|
0583 47 ld b,a ; put 0000 or FFFF in TOS
|
|
0584 4F ld c,a
|
|
0585 next
|
|
0585 EB + ex de,hl
|
|
0586 5E + ld e,(hl)
|
|
0587 23 + inc hl
|
|
0588 56 + ld d,(hl)
|
|
0589 23 + inc hl
|
|
058A EB + ex de,hl
|
|
058B E9 + jp (hl)
|
|
|
|
;C 0< n -- flag true if TOS negative
|
|
058C head ZEROLESS,2,0<,docode
|
|
058C 7B05 + DW link
|
|
058E 00 + DB 0
|
|
058F +link DEFL $
|
|
058F 02303C + DB 2,'0<'
|
|
0592 +ZEROLESS:
|
|
+ IF .NOT.(DOCODE=DOCODE)
|
|
+ call DOCODE
|
|
+ ENDIF
|
|
0592 CB20 sla b ; sign bit -> cy flag
|
|
0594 9F sbc a,a ; propagate cy through A
|
|
0595 47 ld b,a ; put 0000 or FFFF in TOS
|
|
0596 4F ld c,a
|
|
0597 next
|
|
0597 EB + ex de,hl
|
|
0598 5E + ld e,(hl)
|
|
0599 23 + inc hl
|
|
059A 56 + ld d,(hl)
|
|
059B 23 + inc hl
|
|
059C EB + ex de,hl
|
|
059D E9 + jp (hl)
|
|
|
|
;C = x1 x2 -- flag test x1=x2
|
|
059E head EQUAL,1,=,docode
|
|
059E 8F05 + DW link
|
|
05A0 00 + DB 0
|
|
05A1 +link DEFL $
|
|
05A1 013D + DB 1,'='
|
|
05A3 +EQUAL:
|
|
+ IF .NOT.(DOCODE=DOCODE)
|
|
+ call DOCODE
|
|
+ ENDIF
|
|
05A3 E1 pop hl
|
|
05A4 B7 or a
|
|
05A5 ED42 sbc hl,bc ; x1-x2 in HL, SZVC valid
|
|
05A7 2828 jr z,tostrue
|
|
05A9 010000 tosfalse: ld bc,0
|
|
05AC next
|
|
05AC EB + ex de,hl
|
|
05AD 5E + ld e,(hl)
|
|
05AE 23 + inc hl
|
|
05AF 56 + ld d,(hl)
|
|
05B0 23 + inc hl
|
|
05B1 EB + ex de,hl
|
|
05B2 E9 + jp (hl)
|
|
|
|
;X <> x1 x2 -- flag test not eq (not ANSI)
|
|
05B3 head NOTEQUAL,2,<>,docolon
|
|
05B3 A105 + DW link
|
|
05B5 00 + DB 0
|
|
05B6 +link DEFL $
|
|
05B6 023C3E + DB 2,'<>'
|
|
05B9 +NOTEQUAL:
|
|
+ IF .NOT.(DOCOLON=DOCODE)
|
|
05B9 CD5301 + call DOCOLON
|
|
+ ENDIF
|
|
05BC A3057E05 DW EQUAL,ZEROEQUAL,EXIT
|
|
|
|
;C < n1 n2 -- flag test n1<n2, signed
|
|
05C2 head LESS,1,<,docode
|
|
05C2 B605 + DW link
|
|
05C4 00 + DB 0
|
|
05C5 +link DEFL $
|
|
05C5 013C + DB 1,'<'
|
|
05C7 +LESS:
|
|
+ IF .NOT.(DOCODE=DOCODE)
|
|
+ call DOCODE
|
|
+ ENDIF
|
|
05C7 E1 pop hl
|
|
05C8 B7 or a
|
|
05C9 ED42 sbc hl,bc ; n1-n2 in HL, SZVC valid
|
|
; if result negative & not OV, n1<n2
|
|
; neg. & OV => n1 +ve, n2 -ve, rslt -ve, so n1>n2
|
|
; if result positive & not OV, n1>=n2
|
|
; pos. & OV => n1 -ve, n2 +ve, rslt +ve, so n1<n2
|
|
; thus OV reverses the sense of the sign bit
|
|
05CB EADB05 jp pe,revsense ; if OV, use rev. sense
|
|
05CE F2A905 jp p,tosfalse ; if +ve, result false
|
|
05D1 01FFFF tostrue: ld bc,0ffffh ; if -ve, result true
|
|
05D4 next
|
|
05D4 EB + ex de,hl
|
|
05D5 5E + ld e,(hl)
|
|
05D6 23 + inc hl
|
|
05D7 56 + ld d,(hl)
|
|
05D8 23 + inc hl
|
|
05D9 EB + ex de,hl
|
|
05DA E9 + jp (hl)
|
|
05DB FAA905 revsense: jp m,tosfalse ; OV: if -ve, reslt false
|
|
05DE 18F1 jr tostrue ; if +ve, result true
|
|
|
|
;C > n1 n2 -- flag test n1>n2, signed
|
|
05E0 head GREATER,1,>,docolon
|
|
05E0 C505 + DW link
|
|
05E2 00 + DB 0
|
|
05E3 +link DEFL $
|
|
05E3 013E + DB 1,'>'
|
|
05E5 +GREATER:
|
|
+ IF .NOT.(DOCOLON=DOCODE)
|
|
05E5 CD5301 + call DOCOLON
|
|
+ ENDIF
|
|
05E8 E702C705 DW SWOP,LESS,EXIT
|
|
|
|
;C U< u1 u2 -- flag test u1<n2, unsigned
|
|
05EE head ULESS,2,U<,docode
|
|
05EE E305 + DW link
|
|
05F0 00 + DB 0
|
|
05F1 +link DEFL $
|
|
05F1 02553C + DB 2,'U<'
|
|
05F4 +ULESS:
|
|
+ IF .NOT.(DOCODE=DOCODE)
|
|
+ call DOCODE
|
|
+ ENDIF
|
|
05F4 E1 pop hl
|
|
05F5 B7 or a
|
|
05F6 ED42 sbc hl,bc ; u1-u2 in HL, SZVC valid
|
|
05F8 9F sbc a,a ; propagate cy through A
|
|
05F9 47 ld b,a ; put 0000 or FFFF in TOS
|
|
05FA 4F ld c,a
|
|
05FB next
|
|
05FB EB + ex de,hl
|
|
05FC 5E + ld e,(hl)
|
|
05FD 23 + inc hl
|
|
05FE 56 + ld d,(hl)
|
|
05FF 23 + inc hl
|
|
0600 EB + ex de,hl
|
|
0601 E9 + jp (hl)
|
|
|
|
;X U> u1 u2 -- flag u1>u2 unsgd (not ANSI)
|
|
0602 head UGREATER,2,U>,docolon
|
|
0602 F105 + DW link
|
|
0604 00 + DB 0
|
|
0605 +link DEFL $
|
|
0605 02553E + DB 2,'U>'
|
|
0608 +UGREATER:
|
|
+ IF .NOT.(DOCOLON=DOCODE)
|
|
0608 CD5301 + call DOCOLON
|
|
+ ENDIF
|
|
060B E702F405 DW SWOP,ULESS,EXIT
|
|
|
|
; LOOP AND BRANCH OPERATIONS ====================
|
|
|
|
;Z branch -- branch always
|
|
0611 head branch,6,branch,docode
|
|
0611 0506 + DW link
|
|
0613 00 + DB 0
|
|
0614 +link DEFL $
|
|
0614 06425241 + DB 6,'BRANCH'
|
|
061B +BRANCH:
|
|
+ IF .NOT.(DOCODE=DOCODE)
|
|
+ call DOCODE
|
|
+ ENDIF
|
|
061B 1A dobranch: ld a,(de) ; get inline value => IP
|
|
061C 6F ld l,a
|
|
061D 13 inc de
|
|
061E 1A ld a,(de)
|
|
061F 67 ld h,a
|
|
0620 nexthl
|
|
0620 5E + ld e,(hl)
|
|
0621 23 + inc hl
|
|
0622 56 + ld d,(hl)
|
|
0623 23 + inc hl
|
|
0624 EB + ex de,hl
|
|
0625 E9 + jp (hl)
|
|
|
|
;Z ?branch x -- branch if TOS zero
|
|
0626 head qbranch,7,?branch,docode
|
|
0626 1406 + DW link
|
|
0628 00 + DB 0
|
|
0629 +link DEFL $
|
|
0629 073F4252 + DB 7,'?BRANCH'
|
|
0631 +QBRANCH:
|
|
+ IF .NOT.(DOCODE=DOCODE)
|
|
+ call DOCODE
|
|
+ ENDIF
|
|
0631 78 ld a,b
|
|
0632 B1 or c ; test old TOS
|
|
0633 C1 pop bc ; pop new TOS
|
|
0634 28E5 jr z,dobranch ; if old TOS=0, branch
|
|
0636 13 inc de ; else skip inline value
|
|
0637 13 inc de
|
|
0638 next
|
|
0638 EB + ex de,hl
|
|
0639 5E + ld e,(hl)
|
|
063A 23 + inc hl
|
|
063B 56 + ld d,(hl)
|
|
063C 23 + inc hl
|
|
063D EB + ex de,hl
|
|
063E E9 + jp (hl)
|
|
|
|
;Z (do) n1|u1 n2|u2 -- R: -- sys1 sys2
|
|
;Z run-time code for DO
|
|
; '83 and ANSI standard loops terminate when the
|
|
; boundary of limit-1 and limit is crossed, in
|
|
; either direction. This can be conveniently
|
|
; implemented by making the limit 8000h, so that
|
|
; arithmetic overflow logic can detect crossing.
|
|
; I learned this trick from Laxen & Perry F83.
|
|
; fudge factor = 8000h-limit, to be added to
|
|
; the start value.
|
|
063F head xdo,4,(do),docode
|
|
063F 2906 + DW link
|
|
0641 00 + DB 0
|
|
0642 +link DEFL $
|
|
0642 0428444F + DB 4,'(DO)'
|
|
0647 +XDO:
|
|
+ IF .NOT.(DOCODE=DOCODE)
|
|
+ call DOCODE
|
|
+ ENDIF
|
|
0647 EB ex de,hl
|
|
0648 E3 ex (sp),hl ; IP on stack, limit in HL
|
|
0649 EB ex de,hl
|
|
064A 210080 ld hl,8000h
|
|
064D B7 or a
|
|
064E ED52 sbc hl,de ; 8000-limit in HL
|
|
0650 DD2B dec ix ; push this fudge factor
|
|
0652 DD7400 ld (ix+0),h ; onto return stack
|
|
0655 DD2B dec ix ; for later use by 'I'
|
|
0657 DD7500 ld (ix+0),l
|
|
065A 09 add hl,bc ; add fudge to start value
|
|
065B DD2B dec ix ; push adjusted start value
|
|
065D DD7400 ld (ix+0),h ; onto return stack
|
|
0660 DD2B dec ix ; as the loop index.
|
|
0662 DD7500 ld (ix+0),l
|
|
0665 D1 pop de ; restore the saved IP
|
|
0666 C1 pop bc ; pop new TOS
|
|
0667 next
|
|
0667 EB + ex de,hl
|
|
0668 5E + ld e,(hl)
|
|
0669 23 + inc hl
|
|
066A 56 + ld d,(hl)
|
|
066B 23 + inc hl
|
|
066C EB + ex de,hl
|
|
066D E9 + jp (hl)
|
|
|
|
;Z (loop) R: sys1 sys2 -- | sys1 sys2
|
|
;Z run-time code for LOOP
|
|
; Add 1 to the loop index. If loop terminates,
|
|
; clean up the return stack and skip the branch.
|
|
; Else take the inline branch. Note that LOOP
|
|
; terminates when index=8000h.
|
|
066E head xloop,6,(loop),docode
|
|
066E 4206 + DW link
|
|
0670 00 + DB 0
|
|
0671 +link DEFL $
|
|
0671 06284C4F + DB 6,'(LOOP)'
|
|
0678 +XLOOP:
|
|
+ IF .NOT.(DOCODE=DOCODE)
|
|
+ call DOCODE
|
|
+ ENDIF
|
|
0678 D9 exx
|
|
0679 010100 ld bc,1
|
|
067C DD6E00 looptst: ld l,(ix+0) ; get the loop index
|
|
067F DD6601 ld h,(ix+1)
|
|
0682 B7 or a
|
|
0683 ED4A adc hl,bc ; increment w/overflow test
|
|
0685 EA9106 jp pe,loopterm ; overflow=loop done
|
|
; continue the loop
|
|
0688 DD7500 ld (ix+0),l ; save the updated index
|
|
068B DD7401 ld (ix+1),h
|
|
068E D9 exx
|
|
068F 188A jr dobranch ; take the inline branch
|
|
0691 loopterm: ; terminate the loop
|
|
0691 010400 ld bc,4 ; discard the loop info
|
|
0694 DD09 add ix,bc
|
|
0696 D9 exx
|
|
0697 13 inc de ; skip the inline branch
|
|
0698 13 inc de
|
|
0699 next
|
|
0699 EB + ex de,hl
|
|
069A 5E + ld e,(hl)
|
|
069B 23 + inc hl
|
|
069C 56 + ld d,(hl)
|
|
069D 23 + inc hl
|
|
069E EB + ex de,hl
|
|
069F E9 + jp (hl)
|
|
|
|
;Z (+loop) n -- R: sys1 sys2 -- | sys1 sys2
|
|
;Z run-time code for +LOOP
|
|
; Add n to the loop index. If loop terminates,
|
|
; clean up the return stack and skip the branch.
|
|
; Else take the inline branch.
|
|
06A0 head xplusloop,7,(+loop),docode
|
|
06A0 7106 + DW link
|
|
06A2 00 + DB 0
|
|
06A3 +link DEFL $
|
|
06A3 07282B4C + DB 7,'(+LOOP)'
|
|
06AB +XPLUSLOOP:
|
|
+ IF .NOT.(DOCODE=DOCODE)
|
|
+ call DOCODE
|
|
+ ENDIF
|
|
06AB E1 pop hl ; this will be the new TOS
|
|
06AC C5 push bc
|
|
06AD 44 ld b,h
|
|
06AE 4D ld c,l
|
|
06AF D9 exx
|
|
06B0 C1 pop bc ; old TOS = loop increment
|
|
06B1 18C9 jr looptst
|
|
|
|
;C I -- n R: sys1 sys2 -- sys1 sys2
|
|
;C get the innermost loop index
|
|
06B3 head II,1,I,docode
|
|
06B3 A306 + DW link
|
|
06B5 00 + DB 0
|
|
06B6 +link DEFL $
|
|
06B6 0149 + DB 1,'I'
|
|
06B8 +II:
|
|
+ IF .NOT.(DOCODE=DOCODE)
|
|
+ call DOCODE
|
|
+ ENDIF
|
|
06B8 C5 push bc ; push old TOS
|
|
06B9 DD6E00 ld l,(ix+0) ; get current loop index
|
|
06BC DD6601 ld h,(ix+1)
|
|
06BF DD4E02 ld c,(ix+2) ; get fudge factor
|
|
06C2 DD4603 ld b,(ix+3)
|
|
06C5 B7 or a
|
|
06C6 ED42 sbc hl,bc ; subtract fudge factor,
|
|
06C8 44 ld b,h ; returning true index
|
|
06C9 4D ld c,l
|
|
06CA next
|
|
06CA EB + ex de,hl
|
|
06CB 5E + ld e,(hl)
|
|
06CC 23 + inc hl
|
|
06CD 56 + ld d,(hl)
|
|
06CE 23 + inc hl
|
|
06CF EB + ex de,hl
|
|
06D0 E9 + jp (hl)
|
|
|
|
;C J -- n R: 4*sys -- 4*sys
|
|
;C get the second loop index
|
|
06D1 head JJ,1,J,docode
|
|
06D1 B606 + DW link
|
|
06D3 00 + DB 0
|
|
06D4 +link DEFL $
|
|
06D4 014A + DB 1,'J'
|
|
06D6 +JJ:
|
|
+ IF .NOT.(DOCODE=DOCODE)
|
|
+ call DOCODE
|
|
+ ENDIF
|
|
06D6 C5 push bc ; push old TOS
|
|
06D7 DD6E04 ld l,(ix+4) ; get current loop index
|
|
06DA DD6605 ld h,(ix+5)
|
|
06DD DD4E06 ld c,(ix+6) ; get fudge factor
|
|
06E0 DD4607 ld b,(ix+7)
|
|
06E3 B7 or a
|
|
06E4 ED42 sbc hl,bc ; subtract fudge factor,
|
|
06E6 44 ld b,h ; returning true index
|
|
06E7 4D ld c,l
|
|
06E8 next
|
|
06E8 EB + ex de,hl
|
|
06E9 5E + ld e,(hl)
|
|
06EA 23 + inc hl
|
|
06EB 56 + ld d,(hl)
|
|
06EC 23 + inc hl
|
|
06ED EB + ex de,hl
|
|
06EE E9 + jp (hl)
|
|
|
|
;C UNLOOP -- R: sys1 sys2 -- drop loop parms
|
|
06EF head UNLOOP,6,UNLOOP,docode
|
|
06EF D406 + DW link
|
|
06F1 00 + DB 0
|
|
06F2 +link DEFL $
|
|
06F2 06554E4C + DB 6,'UNLOOP'
|
|
06F9 +UNLOOP:
|
|
+ IF .NOT.(DOCODE=DOCODE)
|
|
+ call DOCODE
|
|
+ ENDIF
|
|
06F9 DD23 inc ix
|
|
06FB DD23 inc ix
|
|
06FD DD23 inc ix
|
|
06FF DD23 inc ix
|
|
0701 next
|
|
0701 EB + ex de,hl
|
|
0702 5E + ld e,(hl)
|
|
0703 23 + inc hl
|
|
0704 56 + ld d,(hl)
|
|
0705 23 + inc hl
|
|
0706 EB + ex de,hl
|
|
0707 E9 + jp (hl)
|
|
|
|
; MULTIPLY AND DIVIDE ===========================
|
|
|
|
;C UM* u1 u2 -- ud unsigned 16x16->32 mult.
|
|
0708 head UMSTAR,3,UM*,docode
|
|
0708 F206 + DW link
|
|
070A 00 + DB 0
|
|
070B +link DEFL $
|
|
070B 03554D2A + DB 3,'UM*'
|
|
070F +UMSTAR:
|
|
+ IF .NOT.(DOCODE=DOCODE)
|
|
+ call DOCODE
|
|
+ ENDIF
|
|
070F C5 push bc
|
|
0710 D9 exx
|
|
0711 C1 pop bc ; u2 in BC
|
|
0712 D1 pop de ; u1 in DE
|
|
0713 210000 ld hl,0 ; result will be in HLDE
|
|
0716 3E11 ld a,17 ; loop counter
|
|
0718 B7 or a ; clear cy
|
|
0719 CB1C umloop: rr h
|
|
071B CB1D rr l
|
|
071D CB1A rr d
|
|
071F CB1B rr e
|
|
0721 3001 jr nc,noadd
|
|
0723 09 add hl,bc
|
|
0724 3D noadd: dec a
|
|
0725 20F2 jr nz,umloop
|
|
0727 D5 push de ; lo result
|
|
0728 E5 push hl ; hi result
|
|
0729 D9 exx
|
|
072A C1 pop bc ; put TOS back in BC
|
|
072B next
|
|
072B EB + ex de,hl
|
|
072C 5E + ld e,(hl)
|
|
072D 23 + inc hl
|
|
072E 56 + ld d,(hl)
|
|
072F 23 + inc hl
|
|
0730 EB + ex de,hl
|
|
0731 E9 + jp (hl)
|
|
|
|
;C UM/MOD ud u1 -- u2 u3 unsigned 32/16->16
|
|
0732 head UMSLASHMOD,6,UM/MOD,docode
|
|
0732 0B07 + DW link
|
|
0734 00 + DB 0
|
|
0735 +link DEFL $
|
|
0735 06554D2F + DB 6,'UM/MOD'
|
|
073C +UMSLASHMOD:
|
|
+ IF .NOT.(DOCODE=DOCODE)
|
|
+ call DOCODE
|
|
+ ENDIF
|
|
073C C5 push bc
|
|
073D D9 exx
|
|
073E C1 pop bc ; BC = divisor
|
|
073F E1 pop hl ; HLDE = dividend
|
|
0740 D1 pop de
|
|
0741 3E10 ld a,16 ; loop counter
|
|
0743 CB23 sla e
|
|
0745 CB12 rl d ; hi bit DE -> carry
|
|
0747 ED6A udloop: adc hl,hl ; rot left w/ carry
|
|
0749 3006 jr nc,udiv3
|
|
; case 1: 17 bit, cy:HL = 1xxxx
|
|
074B B7 or a ; we know we can subtract
|
|
074C ED42 sbc hl,bc
|
|
074E B7 or a ; clear cy to indicate sub ok
|
|
074F 1806 jr udiv4
|
|
; case 2: 16 bit, cy:HL = 0xxxx
|
|
0751 ED42 udiv3: sbc hl,bc ; try the subtract
|
|
0753 3002 jr nc,udiv4 ; if no cy, subtract ok
|
|
0755 09 add hl,bc ; else cancel the subtract
|
|
0756 37 scf ; and set cy to indicate
|
|
0757 CB13 udiv4: rl e ; rotate result bit into DE,
|
|
0759 CB12 rl d ; and next bit of DE into cy
|
|
075B 3D dec a
|
|
075C 20E9 jr nz,udloop
|
|
; now have complemented quotient in DE,
|
|
; and remainder in HL
|
|
075E 7A ld a,d
|
|
075F 2F cpl
|
|
0760 47 ld b,a
|
|
0761 7B ld a,e
|
|
0762 2F cpl
|
|
0763 4F ld c,a
|
|
0764 E5 push hl ; push remainder
|
|
0765 C5 push bc
|
|
0766 D9 exx
|
|
0767 C1 pop bc ; quotient remains in TOS
|
|
0768 next
|
|
0768 EB + ex de,hl
|
|
0769 5E + ld e,(hl)
|
|
076A 23 + inc hl
|
|
076B 56 + ld d,(hl)
|
|
076C 23 + inc hl
|
|
076D EB + ex de,hl
|
|
076E E9 + jp (hl)
|
|
|
|
; BLOCK AND STRING OPERATIONS ===================
|
|
|
|
;C FILL c-addr u char -- fill memory with char
|
|
076F head FILL,4,FILL,docode
|
|
076F 3507 + DW link
|
|
0771 00 + DB 0
|
|
0772 +link DEFL $
|
|
0772 0446494C + DB 4,'FILL'
|
|
0777 +FILL:
|
|
+ IF .NOT.(DOCODE=DOCODE)
|
|
+ call DOCODE
|
|
+ ENDIF
|
|
0777 79 ld a,c ; character in a
|
|
0778 D9 exx ; use alt. register set
|
|
0779 C1 pop bc ; count in bc
|
|
077A D1 pop de ; address in de
|
|
077B B7 or a ; clear carry flag
|
|
077C 21FFFF ld hl,0ffffh
|
|
077F ED4A adc hl,bc ; test for count=0 or 1
|
|
0781 3009 jr nc,filldone ; no cy: count=0, skip
|
|
0783 12 ld (de),a ; fill first byte
|
|
0784 2806 jr z,filldone ; zero, count=1, done
|
|
0786 0B dec bc ; else adjust count,
|
|
0787 62 ld h,d ; let hl = start adrs,
|
|
0788 6B ld l,e
|
|
0789 13 inc de ; let de = start adrs+1
|
|
078A EDB0 ldir ; copy (hl)->(de)
|
|
078C D9 filldone: exx ; back to main reg set
|
|
078D C1 pop bc ; pop new TOS
|
|
078E next
|
|
078E EB + ex de,hl
|
|
078F 5E + ld e,(hl)
|
|
0790 23 + inc hl
|
|
0791 56 + ld d,(hl)
|
|
0792 23 + inc hl
|
|
0793 EB + ex de,hl
|
|
0794 E9 + jp (hl)
|
|
|
|
;X CMOVE c-addr1 c-addr2 u -- move from bottom
|
|
; as defined in the ANSI optional String word set
|
|
; On byte machines, CMOVE and CMOVE> are logical
|
|
; factors of MOVE. They are easy to implement on
|
|
; CPUs which have a block-move instruction.
|
|
0795 head CMOVE,5,CMOVE,docode
|
|
0795 7207 + DW link
|
|
0797 00 + DB 0
|
|
0798 +link DEFL $
|
|
0798 05434D4F + DB 5,'CMOVE'
|
|
079E +CMOVE:
|
|
+ IF .NOT.(DOCODE=DOCODE)
|
|
+ call DOCODE
|
|
+ ENDIF
|
|
079E C5 push bc
|
|
079F D9 exx
|
|
07A0 C1 pop bc ; count
|
|
07A1 D1 pop de ; destination adrs
|
|
07A2 E1 pop hl ; source adrs
|
|
07A3 78 ld a,b ; test for count=0
|
|
07A4 B1 or c
|
|
07A5 2802 jr z,cmovedone
|
|
07A7 EDB0 ldir ; move from bottom to top
|
|
07A9 D9 cmovedone: exx
|
|
07AA C1 pop bc ; pop new TOS
|
|
07AB next
|
|
07AB EB + ex de,hl
|
|
07AC 5E + ld e,(hl)
|
|
07AD 23 + inc hl
|
|
07AE 56 + ld d,(hl)
|
|
07AF 23 + inc hl
|
|
07B0 EB + ex de,hl
|
|
07B1 E9 + jp (hl)
|
|
|
|
;X CMOVE> c-addr1 c-addr2 u -- move from top
|
|
; as defined in the ANSI optional String word set
|
|
07B2 head CMOVEUP,6,CMOVE>,docode
|
|
07B2 9807 + DW link
|
|
07B4 00 + DB 0
|
|
07B5 +link DEFL $
|
|
07B5 06434D4F + DB 6,'CMOVE>'
|
|
07BC +CMOVEUP:
|
|
+ IF .NOT.(DOCODE=DOCODE)
|
|
+ call DOCODE
|
|
+ ENDIF
|
|
07BC C5 push bc
|
|
07BD D9 exx
|
|
07BE C1 pop bc ; count
|
|
07BF E1 pop hl ; destination adrs
|
|
07C0 D1 pop de ; source adrs
|
|
07C1 78 ld a,b ; test for count=0
|
|
07C2 B1 or c
|
|
07C3 2807 jr z,umovedone
|
|
07C5 09 add hl,bc ; last byte in destination
|
|
07C6 2B dec hl
|
|
07C7 EB ex de,hl
|
|
07C8 09 add hl,bc ; last byte in source
|
|
07C9 2B dec hl
|
|
07CA EDB8 lddr ; move from top to bottom
|
|
07CC D9 umovedone: exx
|
|
07CD C1 pop bc ; pop new TOS
|
|
07CE next
|
|
07CE EB + ex de,hl
|
|
07CF 5E + ld e,(hl)
|
|
07D0 23 + inc hl
|
|
07D1 56 + ld d,(hl)
|
|
07D2 23 + inc hl
|
|
07D3 EB + ex de,hl
|
|
07D4 E9 + jp (hl)
|
|
|
|
;Z SKIP c-addr u c -- c-addr' u'
|
|
;Z skip matching chars
|
|
; Although SKIP, SCAN, and S= are perhaps not the
|
|
; ideal factors of WORD and FIND, they closely
|
|
; follow the string operations available on many
|
|
; CPUs, and so are easy to implement and fast.
|
|
07D5 head skip,4,SKIP,docode
|
|
07D5 B507 + DW link
|
|
07D7 00 + DB 0
|
|
07D8 +link DEFL $
|
|
07D8 04534B49 + DB 4,'SKIP'
|
|
07DD +SKIP:
|
|
+ IF .NOT.(DOCODE=DOCODE)
|
|
+ call DOCODE
|
|
+ ENDIF
|
|
07DD 79 ld a,c ; skip character
|
|
07DE D9 exx
|
|
07DF C1 pop bc ; count
|
|
07E0 E1 pop hl ; address
|
|
07E1 5F ld e,a ; test for count=0
|
|
07E2 78 ld a,b
|
|
07E3 B1 or c
|
|
07E4 280C jr z,skipdone
|
|
07E6 7B ld a,e
|
|
07E7 EDA1 skiploop: cpi
|
|
07E9 2005 jr nz,skipmis ; char mismatch: exit
|
|
07EB EAE707 jp pe,skiploop ; count not exhausted
|
|
07EE 1802 jr skipdone ; count 0, no mismatch
|
|
07F0 03 skipmis: inc bc ; mismatch! undo last to
|
|
07F1 2B dec hl ; point at mismatch char
|
|
07F2 E5 skipdone: push hl ; updated address
|
|
07F3 C5 push bc ; updated count
|
|
07F4 D9 exx
|
|
07F5 C1 pop bc ; TOS in bc
|
|
07F6 next
|
|
07F6 EB + ex de,hl
|
|
07F7 5E + ld e,(hl)
|
|
07F8 23 + inc hl
|
|
07F9 56 + ld d,(hl)
|
|
07FA 23 + inc hl
|
|
07FB EB + ex de,hl
|
|
07FC E9 + jp (hl)
|
|
|
|
;Z SCAN c-addr u c -- c-addr' u'
|
|
;Z find matching char
|
|
07FD head scan,4,SCAN,docode
|
|
07FD D807 + DW link
|
|
07FF 00 + DB 0
|
|
0800 +link DEFL $
|
|
0800 04534341 + DB 4,'SCAN'
|
|
0805 +SCAN:
|
|
+ IF .NOT.(DOCODE=DOCODE)
|
|
+ call DOCODE
|
|
+ ENDIF
|
|
0805 79 ld a,c ; scan character
|
|
0806 D9 exx
|
|
0807 C1 pop bc ; count
|
|
0808 E1 pop hl ; address
|
|
0809 5F ld e,a ; test for count=0
|
|
080A 78 ld a,b
|
|
080B B1 or c
|
|
080C 2807 jr z,scandone
|
|
080E 7B ld a,e
|
|
080F EDB1 cpir ; scan 'til match or count=0
|
|
0811 2002 jr nz,scandone ; no match, BC & HL ok
|
|
0813 03 inc bc ; match! undo last to
|
|
0814 2B dec hl ; point at match char
|
|
0815 E5 scandone: push hl ; updated address
|
|
0816 C5 push bc ; updated count
|
|
0817 D9 exx
|
|
0818 C1 pop bc ; TOS in bc
|
|
0819 next
|
|
0819 EB + ex de,hl
|
|
081A 5E + ld e,(hl)
|
|
081B 23 + inc hl
|
|
081C 56 + ld d,(hl)
|
|
081D 23 + inc hl
|
|
081E EB + ex de,hl
|
|
081F E9 + jp (hl)
|
|
|
|
;Z S= c-addr1 c-addr2 u -- n string compare
|
|
;Z n<0: s1<s2, n=0: s1=s2, n>0: s1>s2
|
|
0820 head sequal,2,S=,docode
|
|
0820 0008 + DW link
|
|
0822 00 + DB 0
|
|
0823 +link DEFL $
|
|
0823 02533D + DB 2,'S='
|
|
0826 +SEQUAL:
|
|
+ IF .NOT.(DOCODE=DOCODE)
|
|
+ call DOCODE
|
|
+ ENDIF
|
|
0826 C5 push bc
|
|
0827 D9 exx
|
|
0828 C1 pop bc ; count
|
|
0829 E1 pop hl ; addr2
|
|
082A D1 pop de ; addr1
|
|
082B 78 ld a,b ; test for count=0
|
|
082C B1 or c
|
|
082D 2809 jr z,smatch ; by definition, match!
|
|
082F 1A sloop: ld a,(de)
|
|
0830 13 inc de
|
|
0831 EDA1 cpi
|
|
0833 2009 jr nz,sdiff ; char mismatch: exit
|
|
0835 EA2F08 jp pe,sloop ; count not exhausted
|
|
0838 smatch: ; count exhausted & no mismatch found
|
|
0838 D9 exx
|
|
0839 010000 ld bc,0 ; bc=0000 (s1=s2)
|
|
083C 1808 jr snext
|
|
083E sdiff: ; mismatch! undo last 'cpi' increment
|
|
083E 2B dec hl ; point at mismatch char
|
|
083F BE cp (hl) ; set cy if char1 < char2
|
|
0840 9F sbc a,a ; propagate cy thru A
|
|
0841 D9 exx
|
|
0842 47 ld b,a ; bc=FFFF if cy (s1<s2)
|
|
0843 F601 or 1 ; bc=0001 if ncy (s1>s2)
|
|
0845 4F ld c,a
|
|
0846 snext: next
|
|
0846 EB + ex de,hl
|
|
0847 5E + ld e,(hl)
|
|
0848 23 + inc hl
|
|
0849 56 + ld d,(hl)
|
|
084A 23 + inc hl
|
|
084B EB + ex de,hl
|
|
084C E9 + jp (hl)
|
|
|
|
*INCLUDE camel80d.azm ; CPU Dependencies
|
|
; LISTING 3.
|
|
;
|
|
; ===============================================
|
|
; CamelForth for the Zilog Z80
|
|
; Copyright (c) 1994,1995 Bradford J. Rodriguez
|
|
;
|
|
; This program is free software; you can redistribute it and/or modify
|
|
; it under the terms of the GNU General Public License as published by
|
|
; the Free Software Foundation; either version 3 of the License, or
|
|
; (at your option) any later version.
|
|
;
|
|
; This program is distributed in the hope that it will be useful,
|
|
; but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
; GNU General Public License for more details.
|
|
;
|
|
; You should have received a copy of the GNU General Public License
|
|
; along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
; Commercial inquiries should be directed to the author at
|
|
; 115 First St., #105, Collingwood, Ontario L9Y 4W3 Canada
|
|
; or via email to bj@camelforth.com
|
|
;
|
|
; ===============================================
|
|
; CAMEL80D.AZM: CPU and Model Dependencies
|
|
; Source code is for the Z80MR macro assembler.
|
|
; Forth words are documented as follows:
|
|
;* NAME stack -- stack description
|
|
; Word names in upper case are from the ANS
|
|
; Forth Core word set. Names in lower case are
|
|
; "internal" implementation words & extensions.
|
|
;
|
|
; Direct-Threaded Forth model for Zilog Z80
|
|
; cell size is 16 bits (2 bytes)
|
|
; char size is 8 bits (1 byte)
|
|
; address unit is 8 bits (1 byte), i.e.,
|
|
; addresses are byte-aligned.
|
|
; ===============================================
|
|
|
|
; ALIGNMENT AND PORTABILITY OPERATORS ===========
|
|
; Many of these are synonyms for other words,
|
|
; and so are defined as CODE words.
|
|
|
|
;C ALIGN -- align HERE
|
|
084D head ALIGN,5,ALIGN,docode
|
|
084D 2308 + DW link
|
|
084F 00 + DB 0
|
|
0850 +link DEFL $
|
|
0850 05414C49 + DB 5,'ALIGN'
|
|
0856 +ALIGN:
|
|
+ IF .NOT.(DOCODE=DOCODE)
|
|
+ call DOCODE
|
|
+ ENDIF
|
|
0856 noop: next
|
|
0856 EB + ex de,hl
|
|
0857 5E + ld e,(hl)
|
|
0858 23 + inc hl
|
|
0859 56 + ld d,(hl)
|
|
085A 23 + inc hl
|
|
085B EB + ex de,hl
|
|
085C E9 + jp (hl)
|
|
|
|
;C ALIGNED addr -- a-addr align given addr
|
|
085D head ALIGNED,7,ALIGNED,docode
|
|
085D 5008 + DW link
|
|
085F 00 + DB 0
|
|
0860 +link DEFL $
|
|
0860 07414C49 + DB 7,'ALIGNED'
|
|
0868 +ALIGNED:
|
|
+ IF .NOT.(DOCODE=DOCODE)
|
|
+ call DOCODE
|
|
+ ENDIF
|
|
0868 18EC jr noop
|
|
|
|
;Z CELL -- n size of one cell
|
|
086A head CELL,4,CELL,docon
|
|
086A 6008 + DW link
|
|
086C 00 + DB 0
|
|
086D +link DEFL $
|
|
086D 0443454C + DB 4,'CELL'
|
|
0872 +CELL:
|
|
+ IF .NOT.(DOCON=DOCODE)
|
|
0872 CD9F01 + call DOCON
|
|
+ ENDIF
|
|
0875 0200 dw 2
|
|
|
|
;C CELL+ a-addr1 -- a-addr2 add cell size
|
|
; 2 + ;
|
|
0877 head CELLPLUS,5,CELL+,docode
|
|
0877 6D08 + DW link
|
|
0879 00 + DB 0
|
|
087A +link DEFL $
|
|
087A 0543454C + DB 5,'CELL+'
|
|
0880 +CELLPLUS:
|
|
+ IF .NOT.(DOCODE=DOCODE)
|
|
+ call DOCODE
|
|
+ ENDIF
|
|
0880 03 inc bc
|
|
0881 03 inc bc
|
|
0882 next
|
|
0882 EB + ex de,hl
|
|
0883 5E + ld e,(hl)
|
|
0884 23 + inc hl
|
|
0885 56 + ld d,(hl)
|
|
0886 23 + inc hl
|
|
0887 EB + ex de,hl
|
|
0888 E9 + jp (hl)
|
|
|
|
;C CELLS n1 -- n2 cells->adrs units
|
|
0889 head CELLS,5,CELLS,docode
|
|
0889 7A08 + DW link
|
|
088B 00 + DB 0
|
|
088C +link DEFL $
|
|
088C 0543454C + DB 5,'CELLS'
|
|
0892 +CELLS:
|
|
+ IF .NOT.(DOCODE=DOCODE)
|
|
+ call DOCODE
|
|
+ ENDIF
|
|
0892 C30D05 jp twostar
|
|
|
|
;C CHAR+ c-addr1 -- c-addr2 add char size
|
|
0895 head CHARPLUS,5,CHAR+,docode
|
|
0895 8C08 + DW link
|
|
0897 00 + DB 0
|
|
0898 +link DEFL $
|
|
0898 05434841 + DB 5,'CHAR+'
|
|
089E +CHARPLUS:
|
|
+ IF .NOT.(DOCODE=DOCODE)
|
|
+ call DOCODE
|
|
+ ENDIF
|
|
089E C3E104 jp oneplus
|
|
|
|
;C CHARS n1 -- n2 chars->adrs units
|
|
08A1 head CHARS,5,CHARS,docode
|
|
08A1 9808 + DW link
|
|
08A3 00 + DB 0
|
|
08A4 +link DEFL $
|
|
08A4 05434841 + DB 5,'CHARS'
|
|
08AA +CHARS:
|
|
+ IF .NOT.(DOCODE=DOCODE)
|
|
+ call DOCODE
|
|
+ ENDIF
|
|
08AA 18AA jr noop
|
|
|
|
;C >BODY xt -- a-addr adrs of param field
|
|
; 3 + ; Z80 (3 byte CALL)
|
|
08AC head TOBODY,5,>BODY,docolon
|
|
08AC A408 + DW link
|
|
08AE 00 + DB 0
|
|
08AF +link DEFL $
|
|
08AF 053E424F + DB 5,'>BODY'
|
|
08B5 +TOBODY:
|
|
+ IF .NOT.(DOCOLON=DOCODE)
|
|
08B5 CD5301 + call DOCOLON
|
|
+ ENDIF
|
|
08B8 36010300 DW LIT,3,PLUS,EXIT
|
|
|
|
;X COMPILE, xt -- append execution token
|
|
; I called this word ,XT before I discovered that
|
|
; it is defined in the ANSI standard as COMPILE,.
|
|
; On a DTC Forth this simply appends xt (like , )
|
|
; but on an STC Forth this must append 'CALL xt'.
|
|
08C0 head COMMAXT,8,'COMPILE,',docode
|
|
08C0 AF08 + DW link
|
|
08C2 00 + DB 0
|
|
08C3 +link DEFL $
|
|
08C3 08434F4D + DB 8,'COMPILE,'
|
|
08CC +COMMAXT:
|
|
+ IF .NOT.(DOCODE=DOCODE)
|
|
+ call DOCODE
|
|
+ ENDIF
|
|
08CC C3310F jp COMMA
|
|
|
|
;Z !CF adrs cfa -- set code action of a word
|
|
; 0CD OVER C! store 'CALL adrs' instr
|
|
; 1+ ! ; Z80 VERSION
|
|
; Depending on the implementation this could
|
|
; append CALL adrs or JUMP adrs.
|
|
08CF head STORECF,3,!CF,docolon
|
|
08CF C308 + DW link
|
|
08D1 00 + DB 0
|
|
08D2 +link DEFL $
|
|
08D2 03214346 + DB 3,'!CF'
|
|
08D6 +STORECF:
|
|
+ IF .NOT.(DOCOLON=DOCODE)
|
|
08D6 CD5301 + call DOCOLON
|
|
+ ENDIF
|
|
08D9 3601CD00 DW LIT,0CDH,OVER,CSTORE
|
|
08E1 E104CE03 DW ONEPLUS,STORE,EXIT
|
|
|
|
;Z ,CF adrs -- append a code field
|
|
; HERE !CF 3 ALLOT ; Z80 VERSION (3 bytes)
|
|
08E7 head COMMACF,3,',CF',docolon
|
|
08E7 D208 + DW link
|
|
08E9 00 + DB 0
|
|
08EA +link DEFL $
|
|
08EA 032C4346 + DB 3,',CF'
|
|
08EE +COMMACF:
|
|
+ IF .NOT.(DOCOLON=DOCODE)
|
|
08EE CD5301 + call DOCOLON
|
|
+ ENDIF
|
|
08F1 110FD608 DW HERE,STORECF,LIT,3,ALLOT,EXIT
|
|
|
|
;Z !COLON -- change code field to docolon
|
|
; -3 ALLOT docolon-adrs ,CF ;
|
|
; This should be used immediately after CREATE.
|
|
; This is made a distinct word, because on an STC
|
|
; Forth, colon definitions have no code field.
|
|
08FD head STORCOLON,6,'!COLON',docolon
|
|
08FD EA08 + DW link
|
|
08FF 00 + DB 0
|
|
0900 +link DEFL $
|
|
0900 0621434F + DB 6,'!COLON'
|
|
0907 +STORCOLON:
|
|
+ IF .NOT.(DOCOLON=DOCODE)
|
|
0907 CD5301 + call DOCOLON
|
|
+ ENDIF
|
|
090A 3601FDFF DW LIT,-3,ALLOT
|
|
0910 36015301 DW LIT,docolon,COMMACF,EXIT
|
|
|
|
;Z ,EXIT -- append hi-level EXIT action
|
|
; ['] EXIT ,XT ;
|
|
; This is made a distinct word, because on an STC
|
|
; Forth, it appends a RET instruction, not an xt.
|
|
0918 head CEXIT,5,',EXIT',docolon
|
|
0918 0009 + DW link
|
|
091A 00 + DB 0
|
|
091B +link DEFL $
|
|
091B 052C4558 + DB 5,',EXIT'
|
|
0921 +CEXIT:
|
|
+ IF .NOT.(DOCOLON=DOCODE)
|
|
0921 CD5301 + call DOCOLON
|
|
+ ENDIF
|
|
0924 36011E01 DW LIT,EXIT,COMMAXT,EXIT
|
|
|
|
; CONTROL STRUCTURES ============================
|
|
; These words allow Forth control structure words
|
|
; to be defined portably.
|
|
|
|
;Z ,BRANCH xt -- append a branch instruction
|
|
; xt is the branch operator to use, e.g. qbranch
|
|
; or (loop). It does NOT append the destination
|
|
; address. On the Z80 this is equivalent to ,XT.
|
|
092C head COMMABRANCH,7,',BRANCH',docode
|
|
092C 1B09 + DW link
|
|
092E 00 + DB 0
|
|
092F +link DEFL $
|
|
092F 072C4252 + DB 7,',BRANCH'
|
|
0937 +COMMABRANCH:
|
|
+ IF .NOT.(DOCODE=DOCODE)
|
|
+ call DOCODE
|
|
+ ENDIF
|
|
0937 C3310F jp COMMA
|
|
|
|
;Z ,DEST dest -- append a branch address
|
|
; This appends the given destination address to
|
|
; the branch instruction. On the Z80 this is ','
|
|
; ...other CPUs may use relative addressing.
|
|
093A head COMMADEST,5,',DEST',docode
|
|
093A 2F09 + DW link
|
|
093C 00 + DB 0
|
|
093D +link DEFL $
|
|
093D 052C4445 + DB 5,',DEST'
|
|
0943 +COMMADEST:
|
|
+ IF .NOT.(DOCODE=DOCODE)
|
|
+ call DOCODE
|
|
+ ENDIF
|
|
0943 C3310F jp COMMA
|
|
|
|
;Z !DEST dest adrs -- change a branch dest'n
|
|
; Changes the destination address found at 'adrs'
|
|
; to the given 'dest'. On the Z80 this is '!'
|
|
; ...other CPUs may need relative addressing.
|
|
0946 head STOREDEST,5,'!DEST',docode
|
|
0946 3D09 + DW link
|
|
0948 00 + DB 0
|
|
0949 +link DEFL $
|
|
0949 05214445 + DB 5,'!DEST'
|
|
094F +STOREDEST:
|
|
+ IF .NOT.(DOCODE=DOCODE)
|
|
+ call DOCODE
|
|
+ ENDIF
|
|
094F C3CE03 jp STORE
|
|
|
|
; HEADER STRUCTURE ==============================
|
|
; The structure of the Forth dictionary headers
|
|
; (name, link, immediate flag, and "smudge" bit)
|
|
; does not necessarily differ across CPUs. This
|
|
; structure is not easily factored into distinct
|
|
; "portable" words; instead, it is implicit in
|
|
; the definitions of FIND and CREATE, and also in
|
|
; NFA>LFA, NFA>CFA, IMMED?, IMMEDIATE, HIDE, and
|
|
; REVEAL. These words must be (substantially)
|
|
; rewritten if either the header structure or its
|
|
; inherent assumptions are changed.
|
|
|
|
*INCLUDE camel80h.azm ; High Level words
|
|
; LISTING 2.
|
|
;
|
|
; ===============================================
|
|
; CamelForth for the Zilog Z80
|
|
; Copyright (c) 1994,1995 Bradford J. Rodriguez
|
|
;
|
|
; This program is free software; you can redistribute it and/or modify
|
|
; it under the terms of the GNU General Public License as published by
|
|
; the Free Software Foundation; either version 3 of the License, or
|
|
; (at your option) any later version.
|
|
;
|
|
; This program is distributed in the hope that it will be useful,
|
|
; but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
; GNU General Public License for more details.
|
|
;
|
|
; You should have received a copy of the GNU General Public License
|
|
; along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
; Commercial inquiries should be directed to the author at
|
|
; 115 First St., #105, Collingwood, Ontario L9Y 4W3 Canada
|
|
; or via email to bj@camelforth.com
|
|
;
|
|
; ===============================================
|
|
; CAMEL80H.AZM: High Level Words
|
|
; Source code is for the Z80MR macro assembler.
|
|
; Forth words are documented as follows:
|
|
;* NAME stack -- stack description
|
|
; Word names in upper case are from the ANS
|
|
; Forth Core word set. Names in lower case are
|
|
; "internal" implementation words & extensions.
|
|
; ===============================================
|
|
|
|
; SYSTEM VARIABLES & CONSTANTS ==================
|
|
|
|
;C BL -- char an ASCII space
|
|
0952 head BL,2,BL,docon
|
|
0952 4909 + DW link
|
|
0954 00 + DB 0
|
|
0955 +link DEFL $
|
|
0955 02424C + DB 2,'BL'
|
|
0958 +BL:
|
|
+ IF .NOT.(DOCON=DOCODE)
|
|
0958 CD9F01 + call DOCON
|
|
+ ENDIF
|
|
095B 2000 dw 20h
|
|
|
|
;Z tibsize -- n size of TIB
|
|
095D head TIBSIZE,7,TIBSIZE,docon
|
|
095D 5509 + DW link
|
|
095F 00 + DB 0
|
|
0960 +link DEFL $
|
|
0960 07544942 + DB 7,'TIBSIZE'
|
|
0968 +TIBSIZE:
|
|
+ IF .NOT.(DOCON=DOCODE)
|
|
0968 CD9F01 + call DOCON
|
|
+ ENDIF
|
|
096B 7C00 dw 124 ; 2 chars safety zone
|
|
|
|
;X tib -- a-addr Terminal Input Buffer
|
|
; HEX 82 CONSTANT TIB CP/M systems: 126 bytes
|
|
; HEX -80 USER TIB others: below user area
|
|
096D head TIB,3,TIB,docon
|
|
096D 6009 + DW link
|
|
096F 00 + DB 0
|
|
0970 +link DEFL $
|
|
0970 03544942 + DB 3,'TIB'
|
|
0974 +TIB:
|
|
+ IF .NOT.(DOCON=DOCODE)
|
|
0974 CD9F01 + call DOCON
|
|
+ ENDIF
|
|
0977 8200 dw 82h
|
|
|
|
;Z u0 -- a-addr current user area adrs
|
|
; 0 USER U0
|
|
0979 head U0,2,U0,douser
|
|
0979 7009 + DW link
|
|
097B 00 + DB 0
|
|
097C +link DEFL $
|
|
097C 025530 + DB 2,'U0'
|
|
097F +U0:
|
|
+ IF .NOT.(DOUSER=DOCODE)
|
|
097F CDBC01 + call DOUSER
|
|
+ ENDIF
|
|
0982 0000 dw 0
|
|
|
|
;C >IN -- a-addr holds offset into TIB
|
|
; 2 USER >IN
|
|
0984 head TOIN,3,>IN,douser
|
|
0984 7C09 + DW link
|
|
0986 00 + DB 0
|
|
0987 +link DEFL $
|
|
0987 033E494E + DB 3,'>IN'
|
|
098B +TOIN:
|
|
+ IF .NOT.(DOUSER=DOCODE)
|
|
098B CDBC01 + call DOUSER
|
|
+ ENDIF
|
|
098E 0200 dw 2
|
|
|
|
;C BASE -- a-addr holds conversion radix
|
|
; 4 USER BASE
|
|
0990 head BASE,4,BASE,douser
|
|
0990 8709 + DW link
|
|
0992 00 + DB 0
|
|
0993 +link DEFL $
|
|
0993 04424153 + DB 4,'BASE'
|
|
0998 +BASE:
|
|
+ IF .NOT.(DOUSER=DOCODE)
|
|
0998 CDBC01 + call DOUSER
|
|
+ ENDIF
|
|
099B 0400 dw 4
|
|
|
|
;C STATE -- a-addr holds compiler state
|
|
; 6 USER STATE
|
|
099D head STATE,5,STATE,douser
|
|
099D 9309 + DW link
|
|
099F 00 + DB 0
|
|
09A0 +link DEFL $
|
|
09A0 05535441 + DB 5,'STATE'
|
|
09A6 +STATE:
|
|
+ IF .NOT.(DOUSER=DOCODE)
|
|
09A6 CDBC01 + call DOUSER
|
|
+ ENDIF
|
|
09A9 0600 dw 6
|
|
|
|
;Z dp -- a-addr holds dictionary ptr
|
|
; 8 USER DP
|
|
09AB head DP,2,DP,douser
|
|
09AB A009 + DW link
|
|
09AD 00 + DB 0
|
|
09AE +link DEFL $
|
|
09AE 024450 + DB 2,'DP'
|
|
09B1 +DP:
|
|
+ IF .NOT.(DOUSER=DOCODE)
|
|
09B1 CDBC01 + call DOUSER
|
|
+ ENDIF
|
|
09B4 0800 dw 8
|
|
|
|
;Z 'source -- a-addr two cells: len, adrs
|
|
; 10 USER 'SOURCE
|
|
; head TICKSOURCE,7,'SOURCE,douser
|
|
09B6 AE09 DW link ; must expand
|
|
09B8 00 DB 0 ; manually
|
|
09B9 link DEFL $ ; because of
|
|
09B9 0727534F DB 7,27h,'SOURCE' ; tick character
|
|
09C1 CDBC01 TICKSOURCE: call douser ; in name!
|
|
09C4 0A00 dw 10
|
|
|
|
;Z latest -- a-addr last word in dict.
|
|
; 14 USER LATEST
|
|
09C6 head LATEST,6,LATEST,douser
|
|
09C6 B909 + DW link
|
|
09C8 00 + DB 0
|
|
09C9 +link DEFL $
|
|
09C9 064C4154 + DB 6,'LATEST'
|
|
09D0 +LATEST:
|
|
+ IF .NOT.(DOUSER=DOCODE)
|
|
09D0 CDBC01 + call DOUSER
|
|
+ ENDIF
|
|
09D3 0E00 dw 14
|
|
|
|
;Z hp -- a-addr HOLD pointer
|
|
; 16 USER HP
|
|
09D5 head HP,2,HP,douser
|
|
09D5 C909 + DW link
|
|
09D7 00 + DB 0
|
|
09D8 +link DEFL $
|
|
09D8 024850 + DB 2,'HP'
|
|
09DB +HP:
|
|
+ IF .NOT.(DOUSER=DOCODE)
|
|
09DB CDBC01 + call DOUSER
|
|
+ ENDIF
|
|
09DE 1000 dw 16
|
|
|
|
;Z LP -- a-addr Leave-stack pointer
|
|
; 18 USER LP
|
|
09E0 head LP,2,LP,douser
|
|
09E0 D809 + DW link
|
|
09E2 00 + DB 0
|
|
09E3 +link DEFL $
|
|
09E3 024C50 + DB 2,'LP'
|
|
09E6 +LP:
|
|
+ IF .NOT.(DOUSER=DOCODE)
|
|
09E6 CDBC01 + call DOUSER
|
|
+ ENDIF
|
|
09E9 1200 dw 18
|
|
|
|
;Z s0 -- a-addr end of parameter stack
|
|
09EB head S0,2,S0,douser
|
|
09EB E309 + DW link
|
|
09ED 00 + DB 0
|
|
09EE +link DEFL $
|
|
09EE 025330 + DB 2,'S0'
|
|
09F1 +S0:
|
|
+ IF .NOT.(DOUSER=DOCODE)
|
|
09F1 CDBC01 + call DOUSER
|
|
+ ENDIF
|
|
09F4 0001 dw 100h
|
|
|
|
;X PAD -- a-addr user PAD buffer
|
|
; = end of hold area!
|
|
09F6 head PAD,3,PAD,douser
|
|
09F6 EE09 + DW link
|
|
09F8 00 + DB 0
|
|
09F9 +link DEFL $
|
|
09F9 03504144 + DB 3,'PAD'
|
|
09FD +PAD:
|
|
+ IF .NOT.(DOUSER=DOCODE)
|
|
09FD CDBC01 + call DOUSER
|
|
+ ENDIF
|
|
0A00 2801 dw 128h
|
|
|
|
;Z l0 -- a-addr bottom of Leave stack
|
|
0A02 head L0,2,L0,douser
|
|
0A02 F909 + DW link
|
|
0A04 00 + DB 0
|
|
0A05 +link DEFL $
|
|
0A05 024C30 + DB 2,'L0'
|
|
0A08 +L0:
|
|
+ IF .NOT.(DOUSER=DOCODE)
|
|
0A08 CDBC01 + call DOUSER
|
|
+ ENDIF
|
|
0A0B 8001 dw 180h
|
|
|
|
;Z r0 -- a-addr end of return stack
|
|
0A0D head R0,2,R0,douser
|
|
0A0D 050A + DW link
|
|
0A0F 00 + DB 0
|
|
0A10 +link DEFL $
|
|
0A10 025230 + DB 2,'R0'
|
|
0A13 +R0:
|
|
+ IF .NOT.(DOUSER=DOCODE)
|
|
0A13 CDBC01 + call DOUSER
|
|
+ ENDIF
|
|
0A16 0002 dw 200h
|
|
|
|
;Z uinit -- addr initial values for user area
|
|
0A18 head UINIT,5,UINIT,docreate
|
|
0A18 100A + DW link
|
|
0A1A 00 + DB 0
|
|
0A1B +link DEFL $
|
|
0A1B 0555494E + DB 5,'UINIT'
|
|
0A21 +UINIT:
|
|
+ IF .NOT.(DOCREATE=DOCODE)
|
|
0A21 CD7F01 + call DOCREATE
|
|
+ ENDIF
|
|
0A24 00000000 DW 0,0,10,0 ; reserved,>IN,BASE,STATE
|
|
0A2C E616 DW enddict ; DP
|
|
0A2E 00000000 DW 0,0 ; SOURCE init'd elsewhere
|
|
0A32 A416 DW lastword ; LATEST
|
|
0A34 0000 DW 0 ; HP init'd elsewhere
|
|
|
|
;Z #init -- n #bytes of user area init data
|
|
0A36 head NINIT,5,#INIT,docon
|
|
0A36 1B0A + DW link
|
|
0A38 00 + DB 0
|
|
0A39 +link DEFL $
|
|
0A39 0523494E + DB 5,'#INIT'
|
|
0A3F +NINIT:
|
|
+ IF .NOT.(DOCON=DOCODE)
|
|
0A3F CD9F01 + call DOCON
|
|
+ ENDIF
|
|
0A42 1200 DW 18
|
|
|
|
; ARITHMETIC OPERATORS ==========================
|
|
|
|
;C S>D n -- d single -> double prec.
|
|
; DUP 0< ;
|
|
0A44 head STOD,3,S>D,docolon
|
|
0A44 390A + DW link
|
|
0A46 00 + DB 0
|
|
0A47 +link DEFL $
|
|
0A47 03533E44 + DB 3,'S>D'
|
|
0A4B +STOD:
|
|
+ IF .NOT.(DOCOLON=DOCODE)
|
|
0A4B CD5301 + call DOCOLON
|
|
+ ENDIF
|
|
0A4E B4029205 dw DUP,ZEROLESS,EXIT
|
|
|
|
;Z ?NEGATE n1 n2 -- n3 negate n1 if n2 negative
|
|
; 0< IF NEGATE THEN ; ...a common factor
|
|
0A54 head QNEGATE,7,?NEGATE,docolon
|
|
0A54 470A + DW link
|
|
0A56 00 + DB 0
|
|
0A57 +link DEFL $
|
|
0A57 073F4E45 + DB 7,'?NEGATE'
|
|
0A5F +QNEGATE:
|
|
+ IF .NOT.(DOCOLON=DOCODE)
|
|
0A5F CD5301 + call DOCOLON
|
|
+ ENDIF
|
|
0A62 92053106 DW ZEROLESS,qbranch,QNEG1,NEGATE
|
|
0A6A 1E01 QNEG1: DW EXIT
|
|
|
|
;C ABS n1 -- +n2 absolute value
|
|
; DUP ?NEGATE ;
|
|
0A6C head ABS,3,ABS,docolon
|
|
0A6C 570A + DW link
|
|
0A6E 00 + DB 0
|
|
0A6F +link DEFL $
|
|
0A6F 03414253 + DB 3,'ABS'
|
|
0A73 +ABS:
|
|
+ IF .NOT.(DOCOLON=DOCODE)
|
|
0A73 CD5301 + call DOCOLON
|
|
+ ENDIF
|
|
0A76 B4025F0A DW DUP,QNEGATE,EXIT
|
|
|
|
;X DNEGATE d1 -- d2 negate double precision
|
|
; SWAP INVERT SWAP INVERT 1 M+ ;
|
|
0A7C head DNEGATE,7,DNEGATE,docolon
|
|
0A7C 6F0A + DW link
|
|
0A7E 00 + DB 0
|
|
0A7F +link DEFL $
|
|
0A7F 07444E45 + DB 7,'DNEGATE'
|
|
0A87 +DNEGATE:
|
|
+ IF .NOT.(DOCOLON=DOCODE)
|
|
0A87 CD5301 + call DOCOLON
|
|
+ ENDIF
|
|
0A8A E702B604 DW SWOP,INVERT,SWOP,INVERT,LIT,1,MPLUS
|
|
0A98 1E01 DW EXIT
|
|
|
|
;Z ?DNEGATE d1 n -- d2 negate d1 if n negative
|
|
; 0< IF DNEGATE THEN ; ...a common factor
|
|
0A9A head QDNEGATE,8,?DNEGATE,docolon
|
|
0A9A 7F0A + DW link
|
|
0A9C 00 + DB 0
|
|
0A9D +link DEFL $
|
|
0A9D 083F444E + DB 8,'?DNEGATE'
|
|
0AA6 +QDNEGATE:
|
|
+ IF .NOT.(DOCOLON=DOCODE)
|
|
0AA6 CD5301 + call DOCOLON
|
|
+ ENDIF
|
|
0AA9 92053106 DW ZEROLESS,qbranch,DNEG1,DNEGATE
|
|
0AB1 1E01 DNEG1: DW EXIT
|
|
|
|
;X DABS d1 -- +d2 absolute value dbl.prec.
|
|
; DUP ?DNEGATE ;
|
|
0AB3 head DABS,4,DABS,docolon
|
|
0AB3 9D0A + DW link
|
|
0AB5 00 + DB 0
|
|
0AB6 +link DEFL $
|
|
0AB6 04444142 + DB 4,'DABS'
|
|
0ABB +DABS:
|
|
+ IF .NOT.(DOCOLON=DOCODE)
|
|
0ABB CD5301 + call DOCOLON
|
|
+ ENDIF
|
|
0ABE B402A60A DW DUP,QDNEGATE,EXIT
|
|
|
|
;C M* n1 n2 -- d signed 16*16->32 multiply
|
|
; 2DUP XOR >R carries sign of the result
|
|
; SWAP ABS SWAP ABS UM*
|
|
; R> ?DNEGATE ;
|
|
0AC4 head MSTAR,2,M*,docolon
|
|
0AC4 B60A + DW link
|
|
0AC6 00 + DB 0
|
|
0AC7 +link DEFL $
|
|
0AC7 024D2A + DB 2,'M*'
|
|
0ACA +MSTAR:
|
|
+ IF .NOT.(DOCOLON=DOCODE)
|
|
0ACA CD5301 + call DOCOLON
|
|
+ ENDIF
|
|
0ACD 1B0C9E04 DW TWODUP,XOR,TOR
|
|
0AD3 E702730A DW SWOP,ABS,SWOP,ABS,UMSTAR
|
|
0ADD 5803A60A DW RFROM,QDNEGATE,EXIT
|
|
|
|
;C SM/REM d1 n1 -- n2 n3 symmetric signed div
|
|
; 2DUP XOR >R sign of quotient
|
|
; OVER >R sign of remainder
|
|
; ABS >R DABS R> UM/MOD
|
|
; SWAP R> ?NEGATE
|
|
; SWAP R> ?NEGATE ;
|
|
; Ref. dpANS-6 section 3.2.2.1.
|
|
0AE3 head SMSLASHREM,6,SM/REM,docolon
|
|
0AE3 C70A + DW link
|
|
0AE5 00 + DB 0
|
|
0AE6 +link DEFL $
|
|
0AE6 06534D2F + DB 6,'SM/REM'
|
|
0AED +SMSLASHREM:
|
|
+ IF .NOT.(DOCOLON=DOCODE)
|
|
0AED CD5301 + call DOCOLON
|
|
+ ENDIF
|
|
0AF0 1B0C9E04 DW TWODUP,XOR,TOR,OVER,TOR
|
|
0AFA 730A4003 DW ABS,TOR,DABS,RFROM,UMSLASHMOD
|
|
0B04 E7025803 DW SWOP,RFROM,QNEGATE,SWOP,RFROM,QNEGATE
|
|
0B10 1E01 DW EXIT
|
|
|
|
;C FM/MOD d1 n1 -- n2 n3 floored signed div'n
|
|
; DUP >R save divisor
|
|
; SM/REM
|
|
; DUP 0< IF if quotient negative,
|
|
; SWAP R> + add divisor to rem'dr
|
|
; SWAP 1- decrement quotient
|
|
; ELSE R> DROP THEN ;
|
|
; Ref. dpANS-6 section 3.2.2.1.
|
|
0B12 head FMSLASHMOD,6,FM/MOD,docolon
|
|
0B12 E60A + DW link
|
|
0B14 00 + DB 0
|
|
0B15 +link DEFL $
|
|
0B15 06464D2F + DB 6,'FM/MOD'
|
|
0B1C +FMSLASHMOD:
|
|
+ IF .NOT.(DOCOLON=DOCODE)
|
|
0B1C CD5301 + call DOCOLON
|
|
+ ENDIF
|
|
0B1F B4024003 DW DUP,TOR,SMSLASHREM
|
|
0B25 B4029205 DW DUP,ZEROLESS,qbranch,FMMOD1
|
|
0B2D E7025803 DW SWOP,RFROM,PLUS,SWOP,ONEMINUS
|
|
0B37 1B063F0B DW branch,FMMOD2
|
|
0B3B 5803D702 FMMOD1: DW RFROM,DROP
|
|
0B3F 1E01 FMMOD2: DW EXIT
|
|
|
|
;C * n1 n2 -- n3 signed multiply
|
|
; M* DROP ;
|
|
0B41 head STAR,1,*,docolon
|
|
0B41 150B + DW link
|
|
0B43 00 + DB 0
|
|
0B44 +link DEFL $
|
|
0B44 012A + DB 1,'*'
|
|
0B46 +STAR:
|
|
+ IF .NOT.(DOCOLON=DOCODE)
|
|
0B46 CD5301 + call DOCOLON
|
|
+ ENDIF
|
|
0B49 CA0AD702 dw MSTAR,DROP,EXIT
|
|
|
|
;C /MOD n1 n2 -- n3 n4 signed divide/rem'dr
|
|
; >R S>D R> FM/MOD ;
|
|
0B4F head SLASHMOD,4,/MOD,docolon
|
|
0B4F 440B + DW link
|
|
0B51 00 + DB 0
|
|
0B52 +link DEFL $
|
|
0B52 042F4D4F + DB 4,'/MOD'
|
|
0B57 +SLASHMOD:
|
|
+ IF .NOT.(DOCOLON=DOCODE)
|
|
0B57 CD5301 + call DOCOLON
|
|
+ ENDIF
|
|
0B5A 40034B0A dw TOR,STOD,RFROM,FMSLASHMOD,EXIT
|
|
|
|
;C / n1 n2 -- n3 signed divide
|
|
; /MOD nip ;
|
|
0B64 head SLASH,1,/,docolon
|
|
0B64 520B + DW link
|
|
0B66 00 + DB 0
|
|
0B67 +link DEFL $
|
|
0B67 012F + DB 1,'/'
|
|
0B69 +SLASH:
|
|
+ IF .NOT.(DOCOLON=DOCODE)
|
|
0B69 CD5301 + call DOCOLON
|
|
+ ENDIF
|
|
0B6C 570B2003 dw SLASHMOD,NIP,EXIT
|
|
|
|
;C MOD n1 n2 -- n3 signed remainder
|
|
; /MOD DROP ;
|
|
0B72 head MOD,3,MOD,docolon
|
|
0B72 670B + DW link
|
|
0B74 00 + DB 0
|
|
0B75 +link DEFL $
|
|
0B75 034D4F44 + DB 3,'MOD'
|
|
0B79 +MOD:
|
|
+ IF .NOT.(DOCOLON=DOCODE)
|
|
0B79 CD5301 + call DOCOLON
|
|
+ ENDIF
|
|
0B7C 570BD702 dw SLASHMOD,DROP,EXIT
|
|
|
|
;C */MOD n1 n2 n3 -- n4 n5 n1*n2/n3, rem"
|
|
; >R M* R> FM/MOD ;
|
|
0B82 head SSMOD,5,*/MOD,docolon
|
|
0B82 750B + DW link
|
|
0B84 00 + DB 0
|
|
0B85 +link DEFL $
|
|
0B85 052A2F4D + DB 5,'*/MOD'
|
|
0B8B +SSMOD:
|
|
+ IF .NOT.(DOCOLON=DOCODE)
|
|
0B8B CD5301 + call DOCOLON
|
|
+ ENDIF
|
|
0B8E 4003CA0A dw TOR,MSTAR,RFROM,FMSLASHMOD,EXIT
|
|
|
|
;C */ n1 n2 n3 -- n4 n1*n2/n3
|
|
; */MOD nip ;
|
|
0B98 head STARSLASH,2,*/,docolon
|
|
0B98 850B + DW link
|
|
0B9A 00 + DB 0
|
|
0B9B +link DEFL $
|
|
0B9B 022A2F + DB 2,'*/'
|
|
0B9E +STARSLASH:
|
|
+ IF .NOT.(DOCOLON=DOCODE)
|
|
0B9E CD5301 + call DOCOLON
|
|
+ ENDIF
|
|
0BA1 8B0B2003 dw SSMOD,NIP,EXIT
|
|
|
|
;C MAX n1 n2 -- n3 signed maximum
|
|
; 2DUP < IF SWAP THEN DROP ;
|
|
0BA7 head MAX,3,MAX,docolon
|
|
0BA7 9B0B + DW link
|
|
0BA9 00 + DB 0
|
|
0BAA +link DEFL $
|
|
0BAA 034D4158 + DB 3,'MAX'
|
|
0BAE +MAX:
|
|
+ IF .NOT.(DOCOLON=DOCODE)
|
|
0BAE CD5301 + call DOCOLON
|
|
+ ENDIF
|
|
0BB1 1B0CC705 dw TWODUP,LESS,qbranch,MAX1,SWOP
|
|
0BBB D7021E01 MAX1: dw DROP,EXIT
|
|
|
|
;C MIN n1 n2 -- n3 signed minimum
|
|
; 2DUP > IF SWAP THEN DROP ;
|
|
0BBF head MIN,3,MIN,docolon
|
|
0BBF AA0B + DW link
|
|
0BC1 00 + DB 0
|
|
0BC2 +link DEFL $
|
|
0BC2 034D494E + DB 3,'MIN'
|
|
0BC6 +MIN:
|
|
+ IF .NOT.(DOCOLON=DOCODE)
|
|
0BC6 CD5301 + call DOCOLON
|
|
+ ENDIF
|
|
0BC9 1B0CE505 dw TWODUP,GREATER,qbranch,MIN1,SWOP
|
|
0BD3 D7021E01 MIN1: dw DROP,EXIT
|
|
|
|
; DOUBLE OPERATORS ==============================
|
|
|
|
;C 2@ a-addr -- x1 x2 fetch 2 cells
|
|
; DUP CELL+ @ SWAP @ ;
|
|
; the lower address will appear on top of stack
|
|
0BD7 head TWOFETCH,2,2@,docolon
|
|
0BD7 C20B + DW link
|
|
0BD9 00 + DB 0
|
|
0BDA +link DEFL $
|
|
0BDA 023240 + DB 2,'2@'
|
|
0BDD +TWOFETCH:
|
|
+ IF .NOT.(DOCOLON=DOCODE)
|
|
0BDD CD5301 + call DOCOLON
|
|
+ ENDIF
|
|
0BE0 B4028008 dw DUP,CELLPLUS,FETCH,SWOP,FETCH,EXIT
|
|
|
|
;C 2! x1 x2 a-addr -- store 2 cells
|
|
; SWAP OVER ! CELL+ ! ;
|
|
; the top of stack is stored at the lower adrs
|
|
0BEC head TWOSTORE,2,2!,docolon
|
|
0BEC DA0B + DW link
|
|
0BEE 00 + DB 0
|
|
0BEF +link DEFL $
|
|
0BEF 023221 + DB 2,'2!'
|
|
0BF2 +TWOSTORE:
|
|
+ IF .NOT.(DOCOLON=DOCODE)
|
|
0BF2 CD5301 + call DOCOLON
|
|
+ ENDIF
|
|
0BF5 E702FA02 dw SWOP,OVER,STORE,CELLPLUS,STORE,EXIT
|
|
|
|
;C 2DROP x1 x2 -- drop 2 cells
|
|
; DROP DROP ;
|
|
0C01 head TWODROP,5,2DROP,docolon
|
|
0C01 EF0B + DW link
|
|
0C03 00 + DB 0
|
|
0C04 +link DEFL $
|
|
0C04 05324452 + DB 5,'2DROP'
|
|
0C0A +TWODROP:
|
|
+ IF .NOT.(DOCOLON=DOCODE)
|
|
0C0A CD5301 + call DOCOLON
|
|
+ ENDIF
|
|
0C0D D702D702 dw DROP,DROP,EXIT
|
|
|
|
;C 2DUP x1 x2 -- x1 x2 x1 x2 dup top 2 cells
|
|
; OVER OVER ;
|
|
0C13 head TWODUP,4,2DUP,docolon
|
|
0C13 040C + DW link
|
|
0C15 00 + DB 0
|
|
0C16 +link DEFL $
|
|
0C16 04324455 + DB 4,'2DUP'
|
|
0C1B +TWODUP:
|
|
+ IF .NOT.(DOCOLON=DOCODE)
|
|
0C1B CD5301 + call DOCOLON
|
|
+ ENDIF
|
|
0C1E FA02FA02 dw OVER,OVER,EXIT
|
|
|
|
;C 2SWAP x1 x2 x3 x4 -- x3 x4 x1 x2 per diagram
|
|
; ROT >R ROT R> ;
|
|
0C24 head TWOSWAP,5,2SWAP,docolon
|
|
0C24 160C + DW link
|
|
0C26 00 + DB 0
|
|
0C27 +link DEFL $
|
|
0C27 05325357 + DB 5,'2SWAP'
|
|
0C2D +TWOSWAP:
|
|
+ IF .NOT.(DOCOLON=DOCODE)
|
|
0C2D CD5301 + call DOCOLON
|
|
+ ENDIF
|
|
0C30 0D034003 dw ROT,TOR,ROT,RFROM,EXIT
|
|
|
|
;C 2OVER x1 x2 x3 x4 -- x1 x2 x3 x4 x1 x2
|
|
; >R >R 2DUP R> R> 2SWAP ;
|
|
0C3A head TWOOVER,5,2OVER,docolon
|
|
0C3A 270C + DW link
|
|
0C3C 00 + DB 0
|
|
0C3D +link DEFL $
|
|
0C3D 05324F56 + DB 5,'2OVER'
|
|
0C43 +TWOOVER:
|
|
+ IF .NOT.(DOCOLON=DOCODE)
|
|
0C43 CD5301 + call DOCOLON
|
|
+ ENDIF
|
|
0C46 40034003 dw TOR,TOR,TWODUP,RFROM,RFROM
|
|
0C50 2D0C1E01 dw TWOSWAP,EXIT
|
|
|
|
; INPUT/OUTPUT ==================================
|
|
|
|
;C COUNT c-addr1 -- c-addr2 u counted->adr/len
|
|
; DUP CHAR+ SWAP C@ ;
|
|
0C54 head COUNT,5,COUNT,docolon
|
|
0C54 3D0C + DW link
|
|
0C56 00 + DB 0
|
|
0C57 +link DEFL $
|
|
0C57 05434F55 + DB 5,'COUNT'
|
|
0C5D +COUNT:
|
|
+ IF .NOT.(DOCOLON=DOCODE)
|
|
0C5D CD5301 + call DOCOLON
|
|
+ ENDIF
|
|
0C60 B4029E08 dw DUP,CHARPLUS,SWOP,CFETCH,EXIT
|
|
|
|
;C CR -- output newline
|
|
; 0D EMIT 0A EMIT ;
|
|
0C6A head CR,2,CR,docolon
|
|
0C6A 570C + DW link
|
|
0C6C 00 + DB 0
|
|
0C6D +link DEFL $
|
|
0C6D 024352 + DB 2,'CR'
|
|
0C70 +CR:
|
|
+ IF .NOT.(DOCOLON=DOCODE)
|
|
0C70 CD5301 + call DOCOLON
|
|
+ ENDIF
|
|
0C73 36010D00 dw lit,0dh,EMIT,lit,0ah,EMIT,EXIT
|
|
|
|
;C SPACE -- output a space
|
|
; BL EMIT ;
|
|
0C81 head SPACE,5,SPACE,docolon
|
|
0C81 6D0C + DW link
|
|
0C83 00 + DB 0
|
|
0C84 +link DEFL $
|
|
0C84 05535041 + DB 5,'SPACE'
|
|
0C8A +SPACE:
|
|
+ IF .NOT.(DOCOLON=DOCODE)
|
|
0C8A CD5301 + call DOCOLON
|
|
+ ENDIF
|
|
0C8D 58090D02 dw BL,EMIT,EXIT
|
|
|
|
;C SPACES n -- output n spaces
|
|
; BEGIN DUP WHILE SPACE 1- REPEAT DROP ;
|
|
0C93 head SPACES,6,SPACES,docolon
|
|
0C93 840C + DW link
|
|
0C95 00 + DB 0
|
|
0C96 +link DEFL $
|
|
0C96 06535041 + DB 6,'SPACES'
|
|
0C9D +SPACES:
|
|
+ IF .NOT.(DOCOLON=DOCODE)
|
|
0C9D CD5301 + call DOCOLON
|
|
+ ENDIF
|
|
0CA0 B4023106 SPCS1: DW DUP,qbranch,SPCS2
|
|
0CA6 8A0CEF04 DW SPACE,ONEMINUS,branch,SPCS1
|
|
0CAE D7021E01 SPCS2: DW DROP,EXIT
|
|
|
|
;Z umin u1 u2 -- u unsigned minimum
|
|
; 2DUP U> IF SWAP THEN DROP ;
|
|
0CB2 head UMIN,4,UMIN,docolon
|
|
0CB2 960C + DW link
|
|
0CB4 00 + DB 0
|
|
0CB5 +link DEFL $
|
|
0CB5 04554D49 + DB 4,'UMIN'
|
|
0CBA +UMIN:
|
|
+ IF .NOT.(DOCOLON=DOCODE)
|
|
0CBA CD5301 + call DOCOLON
|
|
+ ENDIF
|
|
0CBD 1B0C0806 DW TWODUP,UGREATER,QBRANCH,UMIN1,SWOP
|
|
0CC7 D7021E01 UMIN1: DW DROP,EXIT
|
|
|
|
;Z umax u1 u2 -- u unsigned maximum
|
|
; 2DUP U< IF SWAP THEN DROP ;
|
|
0CCB head UMAX,4,UMAX,docolon
|
|
0CCB B50C + DW link
|
|
0CCD 00 + DB 0
|
|
0CCE +link DEFL $
|
|
0CCE 04554D41 + DB 4,'UMAX'
|
|
0CD3 +UMAX:
|
|
+ IF .NOT.(DOCOLON=DOCODE)
|
|
0CD3 CD5301 + call DOCOLON
|
|
+ ENDIF
|
|
0CD6 1B0CF405 DW TWODUP,ULESS,QBRANCH,UMAX1,SWOP
|
|
0CE0 D7021E01 UMAX1: DW DROP,EXIT
|
|
|
|
;C ACCEPT c-addr +n -- +n' get line from term'l
|
|
; OVER + 1- OVER -- sa ea a
|
|
; BEGIN KEY -- sa ea a c
|
|
; DUP 0D <> WHILE
|
|
; DUP EMIT -- sa ea a c
|
|
; DUP 8 = IF DROP 1- >R OVER R> UMAX
|
|
; ELSE OVER C! 1+ OVER UMIN
|
|
; THEN -- sa ea a
|
|
; REPEAT -- sa ea a c
|
|
; DROP NIP SWAP - ;
|
|
0CE4 head ACCEPT,6,ACCEPT,docolon
|
|
0CE4 CE0C + DW link
|
|
0CE6 00 + DB 0
|
|
0CE7 +link DEFL $
|
|
0CE7 06414343 + DB 6,'ACCEPT'
|
|
0CEE +ACCEPT:
|
|
+ IF .NOT.(DOCOLON=DOCODE)
|
|
0CEE CD5301 + call DOCOLON
|
|
+ ENDIF
|
|
0CF1 FA023904 DW OVER,PLUS,ONEMINUS,OVER
|
|
0CF9 4E02B402 ACC1: DW KEY,DUP,LIT,0DH,NOTEQUAL,QBRANCH,ACC5
|
|
0D07 B4020D02 DW DUP,EMIT,DUP,LIT,8,EQUAL,QBRANCH,ACC3
|
|
0D17 D702EF04 DW DROP,ONEMINUS,TOR,OVER,RFROM,UMAX
|
|
0D23 1B06310D DW BRANCH,ACC4
|
|
0D27 FA02E203 ACC3: DW OVER,CSTORE,ONEPLUS,OVER,UMIN
|
|
0D31 1B06F90C ACC4: DW BRANCH,ACC1
|
|
0D35 D7022003 ACC5: DW DROP,NIP,SWOP,MINUS,EXIT
|
|
|
|
;C TYPE c-addr +n -- type line to term'l
|
|
; ?DUP IF
|
|
; OVER + SWAP DO I C@ EMIT LOOP
|
|
; ELSE DROP THEN ;
|
|
0D3F head TYPE,4,TYPE,docolon
|
|
0D3F E70C + DW link
|
|
0D41 00 + DB 0
|
|
0D42 +link DEFL $
|
|
0D42 04545950 + DB 4,'TYPE'
|
|
0D47 +TYPE:
|
|
+ IF .NOT.(DOCOLON=DOCODE)
|
|
0D47 CD5301 + call DOCOLON
|
|
+ ENDIF
|
|
0D4A C4023106 DW QDUP,QBRANCH,TYP4
|
|
0D50 FA023904 DW OVER,PLUS,SWOP,XDO
|
|
0D58 B8060504 TYP3: DW II,CFETCH,EMIT,XLOOP,TYP3
|
|
0D62 1B06680D DW BRANCH,TYP5
|
|
0D66 D702 TYP4: DW DROP
|
|
0D68 1E01 TYP5: DW EXIT
|
|
|
|
;Z (S") -- c-addr u run-time code for S"
|
|
; R> COUNT 2DUP + ALIGNED >R ;
|
|
0D6A head XSQUOTE,4,(S"),docolon
|
|
0D6A 420D + DW link
|
|
0D6C 00 + DB 0
|
|
0D6D +link DEFL $
|
|
0D6D 04285322 + DB 4,'(S")'
|
|
0D72 +XSQUOTE:
|
|
+ IF .NOT.(DOCOLON=DOCODE)
|
|
0D72 CD5301 + call DOCOLON
|
|
+ ENDIF
|
|
0D75 58035D0C DW RFROM,COUNT,TWODUP,PLUS,ALIGNED,TOR
|
|
0D81 1E01 DW EXIT
|
|
|
|
;C S" -- compile in-line string
|
|
; COMPILE (S") [ HEX ]
|
|
; 22 WORD C@ 1+ ALIGNED ALLOT ; IMMEDIATE
|
|
0D83 immed SQUOTE,2,S",docolon
|
|
0D83 6D0D + DW link
|
|
0D85 01 + DB 1
|
|
0D86 +link DEFL $
|
|
0D86 025322 + DB 2,'S"'
|
|
0D89 +SQUOTE:
|
|
+ IF .NOT.(DOCOLON=DOCODE)
|
|
0D89 CD5301 + call DOCOLON
|
|
+ ENDIF
|
|
0D8C 3601720D DW LIT,XSQUOTE,COMMAXT
|
|
0D92 36012200 DW LIT,22H,WORD,CFETCH,ONEPLUS
|
|
0D9C 6808230F DW ALIGNED,ALLOT,EXIT
|
|
|
|
;C ." -- compile string to print
|
|
; POSTPONE S" POSTPONE TYPE ; IMMEDIATE
|
|
0DA2 immed DOTQUOTE,2,.",docolon
|
|
0DA2 860D + DW link
|
|
0DA4 01 + DB 1
|
|
0DA5 +link DEFL $
|
|
0DA5 022E22 + DB 2,'."'
|
|
0DA8 +DOTQUOTE:
|
|
+ IF .NOT.(DOCOLON=DOCODE)
|
|
0DA8 CD5301 + call DOCOLON
|
|
+ ENDIF
|
|
0DAB 890D DW SQUOTE
|
|
0DAD 3601470D DW LIT,TYPE,COMMAXT
|
|
0DB3 1E01 DW EXIT
|
|
|
|
; NUMERIC OUTPUT ================================
|
|
; Numeric conversion is done l.s.digit first, so
|
|
; the output buffer is built backwards in memory.
|
|
|
|
; Some double-precision arithmetic operators are
|
|
; needed to implement ANSI numeric conversion.
|
|
|
|
;Z UD/MOD ud1 u2 -- u3 ud4 32/16->32 divide
|
|
; >R 0 R@ UM/MOD ROT ROT R> UM/MOD ROT ;
|
|
0DB5 head UDSLASHMOD,6,UD/MOD,docolon
|
|
0DB5 A50D + DW link
|
|
0DB7 00 + DB 0
|
|
0DB8 +link DEFL $
|
|
0DB8 0655442F + DB 6,'UD/MOD'
|
|
0DBF +UDSLASHMOD:
|
|
+ IF .NOT.(DOCOLON=DOCODE)
|
|
0DBF CD5301 + call DOCOLON
|
|
+ ENDIF
|
|
0DC2 40033601 DW TOR,LIT,0,RFETCH,UMSLASHMOD,ROT,ROT
|
|
0DD0 58033C07 DW RFROM,UMSLASHMOD,ROT,EXIT
|
|
|
|
;Z UD* ud1 d2 -- ud3 32*16->32 multiply
|
|
; DUP >R UM* DROP SWAP R> UM* ROT + ;
|
|
0DD8 head UDSTAR,3,UD*,docolon
|
|
0DD8 B80D + DW link
|
|
0DDA 00 + DB 0
|
|
0DDB +link DEFL $
|
|
0DDB 0355442A + DB 3,'UD*'
|
|
0DDF +UDSTAR:
|
|
+ IF .NOT.(DOCOLON=DOCODE)
|
|
0DDF CD5301 + call DOCOLON
|
|
+ ENDIF
|
|
0DE2 B4024003 DW DUP,TOR,UMSTAR,DROP
|
|
0DEA E7025803 DW SWOP,RFROM,UMSTAR,ROT,PLUS,EXIT
|
|
|
|
;C HOLD char -- add char to output string
|
|
; -1 HP +! HP @ C! ;
|
|
0DF6 head HOLD,4,HOLD,docolon
|
|
0DF6 DB0D + DW link
|
|
0DF8 00 + DB 0
|
|
0DF9 +link DEFL $
|
|
0DF9 04484F4C + DB 4,'HOLD'
|
|
0DFE +HOLD:
|
|
+ IF .NOT.(DOCOLON=DOCODE)
|
|
0DFE CD5301 + call DOCOLON
|
|
+ ENDIF
|
|
0E01 3601FFFF DW LIT,-1,HP,PLUSSTORE
|
|
0E09 DB09F303 DW HP,FETCH,CSTORE,EXIT
|
|
|
|
;C <# -- begin numeric conversion
|
|
; PAD HP ! ; (initialize Hold Pointer)
|
|
0E11 head LESSNUM,2,<#,docolon
|
|
0E11 F90D + DW link
|
|
0E13 00 + DB 0
|
|
0E14 +link DEFL $
|
|
0E14 023C23 + DB 2,'<#'
|
|
0E17 +LESSNUM:
|
|
+ IF .NOT.(DOCOLON=DOCODE)
|
|
0E17 CD5301 + call DOCOLON
|
|
+ ENDIF
|
|
0E1A FD09DB09 DW PAD,HP,STORE,EXIT
|
|
|
|
;Z >digit n -- c convert to 0..9A..Z
|
|
; [ HEX ] DUP 9 > 7 AND + 30 + ;
|
|
0E22 head TODIGIT,6,>DIGIT,docolon
|
|
0E22 140E + DW link
|
|
0E24 00 + DB 0
|
|
0E25 +link DEFL $
|
|
0E25 063E4449 + DB 6,'>DIGIT'
|
|
0E2C +TODIGIT:
|
|
+ IF .NOT.(DOCOLON=DOCODE)
|
|
0E2C CD5301 + call DOCOLON
|
|
+ ENDIF
|
|
0E2F B4023601 DW DUP,LIT,9,GREATER,LIT,7,AND,PLUS
|
|
0E3F 36013000 DW LIT,30H,PLUS,EXIT
|
|
|
|
;C # ud1 -- ud2 convert 1 digit of output
|
|
; BASE @ UD/MOD ROT >digit HOLD ;
|
|
0E47 head NUM,1,#,docolon
|
|
0E47 250E + DW link
|
|
0E49 00 + DB 0
|
|
0E4A +link DEFL $
|
|
0E4A 0123 + DB 1,'#'
|
|
0E4C +NUM:
|
|
+ IF .NOT.(DOCOLON=DOCODE)
|
|
0E4C CD5301 + call DOCOLON
|
|
+ ENDIF
|
|
0E4F 9809F303 DW BASE,FETCH,UDSLASHMOD,ROT,TODIGIT
|
|
0E59 FE0D1E01 DW HOLD,EXIT
|
|
|
|
;C #S ud1 -- ud2 convert remaining digits
|
|
; BEGIN # 2DUP OR 0= UNTIL ;
|
|
0E5D head NUMS,2,#S,docolon
|
|
0E5D 4A0E + DW link
|
|
0E5F 00 + DB 0
|
|
0E60 +link DEFL $
|
|
0E60 022353 + DB 2,'#S'
|
|
0E63 +NUMS:
|
|
+ IF .NOT.(DOCOLON=DOCODE)
|
|
0E63 CD5301 + call DOCOLON
|
|
+ ENDIF
|
|
0E66 4C0E1B0C NUMS1: DW NUM,TWODUP,OR,ZEROEQUAL,qbranch,NUMS1
|
|
0E72 1E01 DW EXIT
|
|
|
|
;C #> ud1 -- c-addr u end conv., get string
|
|
; 2DROP HP @ PAD OVER - ;
|
|
0E74 head NUMGREATER,2,#>,docolon
|
|
0E74 600E + DW link
|
|
0E76 00 + DB 0
|
|
0E77 +link DEFL $
|
|
0E77 02233E + DB 2,'#>'
|
|
0E7A +NUMGREATER:
|
|
+ IF .NOT.(DOCOLON=DOCODE)
|
|
0E7A CD5301 + call DOCOLON
|
|
+ ENDIF
|
|
0E7D 0A0CDB09 DW TWODROP,HP,FETCH,PAD,OVER,MINUS,EXIT
|
|
|
|
;C SIGN n -- add minus sign if n<0
|
|
; 0< IF 2D HOLD THEN ;
|
|
0E8B head SIGN,4,SIGN,docolon
|
|
0E8B 770E + DW link
|
|
0E8D 00 + DB 0
|
|
0E8E +link DEFL $
|
|
0E8E 04534947 + DB 4,'SIGN'
|
|
0E93 +SIGN:
|
|
+ IF .NOT.(DOCOLON=DOCODE)
|
|
0E93 CD5301 + call DOCOLON
|
|
+ ENDIF
|
|
0E96 92053106 DW ZEROLESS,qbranch,SIGN1,LIT,2DH,HOLD
|
|
0EA2 1E01 SIGN1: DW EXIT
|
|
|
|
;C U. u -- display u unsigned
|
|
; <# 0 #S #> TYPE SPACE ;
|
|
0EA4 head UDOT,2,U.,docolon
|
|
0EA4 8E0E + DW link
|
|
0EA6 00 + DB 0
|
|
0EA7 +link DEFL $
|
|
0EA7 02552E + DB 2,'U.'
|
|
0EAA +UDOT:
|
|
+ IF .NOT.(DOCOLON=DOCODE)
|
|
0EAA CD5301 + call DOCOLON
|
|
+ ENDIF
|
|
0EAD 170E3601 DW LESSNUM,LIT,0,NUMS,NUMGREATER,TYPE
|
|
0EB9 8A0C1E01 DW SPACE,EXIT
|
|
|
|
;C . n -- display n signed
|
|
; <# DUP ABS 0 #S ROT SIGN #> TYPE SPACE ;
|
|
0EBD head DOT,1,'.',docolon
|
|
0EBD A70E + DW link
|
|
0EBF 00 + DB 0
|
|
0EC0 +link DEFL $
|
|
0EC0 012E + DB 1,'.'
|
|
0EC2 +DOT:
|
|
+ IF .NOT.(DOCOLON=DOCODE)
|
|
0EC2 CD5301 + call DOCOLON
|
|
+ ENDIF
|
|
0EC5 170EB402 DW LESSNUM,DUP,ABS,LIT,0,NUMS
|
|
0ED1 0D03930E DW ROT,SIGN,NUMGREATER,TYPE,SPACE,EXIT
|
|
|
|
;C DECIMAL -- set number base to decimal
|
|
; 10 BASE ! ;
|
|
0EDD head DECIMAL,7,DECIMAL,docolon
|
|
0EDD C00E + DW link
|
|
0EDF 00 + DB 0
|
|
0EE0 +link DEFL $
|
|
0EE0 07444543 + DB 7,'DECIMAL'
|
|
0EE8 +DECIMAL:
|
|
+ IF .NOT.(DOCOLON=DOCODE)
|
|
0EE8 CD5301 + call DOCOLON
|
|
+ ENDIF
|
|
0EEB 36010A00 DW LIT,10,BASE,STORE,EXIT
|
|
|
|
;X HEX -- set number base to hex
|
|
; 16 BASE ! ;
|
|
0EF5 head HEX,3,HEX,docolon
|
|
0EF5 E00E + DW link
|
|
0EF7 00 + DB 0
|
|
0EF8 +link DEFL $
|
|
0EF8 03484558 + DB 3,'HEX'
|
|
0EFC +HEX:
|
|
+ IF .NOT.(DOCOLON=DOCODE)
|
|
0EFC CD5301 + call DOCOLON
|
|
+ ENDIF
|
|
0EFF 36011000 DW LIT,16,BASE,STORE,EXIT
|
|
|
|
; DICTIONARY MANAGEMENT =========================
|
|
|
|
;C HERE -- addr returns dictionary ptr
|
|
; DP @ ;
|
|
0F09 head HERE,4,HERE,docolon
|
|
0F09 F80E + DW link
|
|
0F0B 00 + DB 0
|
|
0F0C +link DEFL $
|
|
0F0C 04484552 + DB 4,'HERE'
|
|
0F11 +HERE:
|
|
+ IF .NOT.(DOCOLON=DOCODE)
|
|
0F11 CD5301 + call DOCOLON
|
|
+ ENDIF
|
|
0F14 B109F303 dw DP,FETCH,EXIT
|
|
|
|
;C ALLOT n -- allocate n bytes in dict
|
|
; DP +! ;
|
|
0F1A head ALLOT,5,ALLOT,docolon
|
|
0F1A 0C0F + DW link
|
|
0F1C 00 + DB 0
|
|
0F1D +link DEFL $
|
|
0F1D 05414C4C + DB 5,'ALLOT'
|
|
0F23 +ALLOT:
|
|
+ IF .NOT.(DOCOLON=DOCODE)
|
|
0F23 CD5301 + call DOCOLON
|
|
+ ENDIF
|
|
0F26 B1096805 dw DP,PLUSSTORE,EXIT
|
|
|
|
; Note: , and C, are only valid for combined
|
|
; Code and Data spaces.
|
|
|
|
;C , x -- append cell to dict
|
|
; HERE ! 1 CELLS ALLOT ;
|
|
0F2C head COMMA,1,',',docolon
|
|
0F2C 1D0F + DW link
|
|
0F2E 00 + DB 0
|
|
0F2F +link DEFL $
|
|
0F2F 012C + DB 1,','
|
|
0F31 +COMMA:
|
|
+ IF .NOT.(DOCOLON=DOCODE)
|
|
0F31 CD5301 + call DOCOLON
|
|
+ ENDIF
|
|
0F34 110FCE03 dw HERE,STORE,lit,1,CELLS,ALLOT,EXIT
|
|
|
|
;C C, char -- append char to dict
|
|
; HERE C! 1 CHARS ALLOT ;
|
|
0F42 head CCOMMA,2,'C,',docolon
|
|
0F42 2F0F + DW link
|
|
0F44 00 + DB 0
|
|
0F45 +link DEFL $
|
|
0F45 02432C + DB 2,'C,'
|
|
0F48 +CCOMMA:
|
|
+ IF .NOT.(DOCOLON=DOCODE)
|
|
0F48 CD5301 + call DOCOLON
|
|
+ ENDIF
|
|
0F4B 110FE203 dw HERE,CSTORE,lit,1,CHARS,ALLOT,EXIT
|
|
|
|
; INTERPRETER ===================================
|
|
; Note that NFA>LFA, NFA>CFA, IMMED?, and FIND
|
|
; are dependent on the structure of the Forth
|
|
; header. This may be common across many CPUs,
|
|
; or it may be different.
|
|
|
|
;C SOURCE -- adr n current input buffer
|
|
; 'SOURCE 2@ ; length is at lower adrs
|
|
0F59 head SOURCE,6,SOURCE,docolon
|
|
0F59 450F + DW link
|
|
0F5B 00 + DB 0
|
|
0F5C +link DEFL $
|
|
0F5C 06534F55 + DB 6,'SOURCE'
|
|
0F63 +SOURCE:
|
|
+ IF .NOT.(DOCOLON=DOCODE)
|
|
0F63 CD5301 + call DOCOLON
|
|
+ ENDIF
|
|
0F66 C109DD0B DW TICKSOURCE,TWOFETCH,EXIT
|
|
|
|
;X /STRING a u n -- a+n u-n trim string
|
|
; ROT OVER + ROT ROT - ;
|
|
0F6C head SLASHSTRING,7,/STRING,docolon
|
|
0F6C 5C0F + DW link
|
|
0F6E 00 + DB 0
|
|
0F6F +link DEFL $
|
|
0F6F 072F5354 + DB 7,'/STRING'
|
|
0F77 +SLASHSTRING:
|
|
+ IF .NOT.(DOCOLON=DOCODE)
|
|
0F77 CD5301 + call DOCOLON
|
|
+ ENDIF
|
|
0F7A 0D03FA02 DW ROT,OVER,PLUS,ROT,ROT,MINUS,EXIT
|
|
|
|
;Z >counted src n dst -- copy to counted str
|
|
; 2DUP C! CHAR+ SWAP CMOVE ;
|
|
0F88 head TOCOUNTED,8,>COUNTED,docolon
|
|
0F88 6F0F + DW link
|
|
0F8A 00 + DB 0
|
|
0F8B +link DEFL $
|
|
0F8B 083E434F + DB 8,'>COUNTED'
|
|
0F94 +TOCOUNTED:
|
|
+ IF .NOT.(DOCOLON=DOCODE)
|
|
0F94 CD5301 + call DOCOLON
|
|
+ ENDIF
|
|
0F97 1B0CE203 DW TWODUP,CSTORE,CHARPLUS,SWOP,CMOVE,EXIT
|
|
|
|
;C WORD char -- c-addr n word delim'd by char
|
|
; DUP SOURCE >IN @ /STRING -- c c adr n
|
|
; DUP >R ROT SKIP -- c adr' n'
|
|
; OVER >R ROT SCAN -- adr" n"
|
|
; DUP IF CHAR- THEN skip trailing delim.
|
|
; R> R> ROT - >IN +! update >IN offset
|
|
; TUCK - -- adr' N
|
|
; HERE >counted --
|
|
; HERE -- a
|
|
; BL OVER COUNT + C! ; append trailing blank
|
|
0FA3 head WORD,4,WORD,docolon
|
|
0FA3 8B0F + DW link
|
|
0FA5 00 + DB 0
|
|
0FA6 +link DEFL $
|
|
0FA6 04574F52 + DB 4,'WORD'
|
|
0FAB +WORD:
|
|
+ IF .NOT.(DOCOLON=DOCODE)
|
|
0FAB CD5301 + call DOCOLON
|
|
+ ENDIF
|
|
0FAE B402630F DW DUP,SOURCE,TOIN,FETCH,SLASHSTRING
|
|
0FB8 B4024003 DW DUP,TOR,ROT,SKIP
|
|
0FC0 FA024003 DW OVER,TOR,ROT,SCAN
|
|
0FC8 B4023106 DW DUP,qbranch,WORD1,ONEMINUS ; char-
|
|
0FD0 58035803 WORD1: DW RFROM,RFROM,ROT,MINUS,TOIN,PLUSSTORE
|
|
0FDC 31036104 DW TUCK,MINUS
|
|
0FE0 110F940F DW HERE,TOCOUNTED,HERE
|
|
0FE6 5809FA02 DW BL,OVER,COUNT,PLUS,CSTORE,EXIT
|
|
|
|
;Z NFA>LFA nfa -- lfa name adr -> link field
|
|
; 3 - ;
|
|
0FF2 head NFATOLFA,7,NFA>LFA,docolon
|
|
0FF2 A60F + DW link
|
|
0FF4 00 + DB 0
|
|
0FF5 +link DEFL $
|
|
0FF5 074E4641 + DB 7,'NFA>LFA'
|
|
0FFD +NFATOLFA:
|
|
+ IF .NOT.(DOCOLON=DOCODE)
|
|
0FFD CD5301 + call DOCOLON
|
|
+ ENDIF
|
|
1000 36010300 DW LIT,3,MINUS,EXIT
|
|
|
|
;Z NFA>CFA nfa -- cfa name adr -> code field
|
|
; COUNT 7F AND + ; mask off 'smudge' bit
|
|
1008 head NFATOCFA,7,NFA>CFA,docolon
|
|
1008 F50F + DW link
|
|
100A 00 + DB 0
|
|
100B +link DEFL $
|
|
100B 074E4641 + DB 7,'NFA>CFA'
|
|
1013 +NFATOCFA:
|
|
+ IF .NOT.(DOCOLON=DOCODE)
|
|
1013 CD5301 + call DOCOLON
|
|
+ ENDIF
|
|
1016 5D0C3601 DW COUNT,LIT,07FH,AND,PLUS,EXIT
|
|
|
|
;Z IMMED? nfa -- f fetch immediate flag
|
|
; 1- C@ ; nonzero if immed
|
|
1022 head IMMEDQ,6,IMMED?,docolon
|
|
1022 0B10 + DW link
|
|
1024 00 + DB 0
|
|
1025 +link DEFL $
|
|
1025 06494D4D + DB 6,'IMMED?'
|
|
102C +IMMEDQ:
|
|
+ IF .NOT.(DOCOLON=DOCODE)
|
|
102C CD5301 + call DOCOLON
|
|
+ ENDIF
|
|
102F EF040504 DW ONEMINUS,CFETCH,EXIT
|
|
|
|
;C FIND c-addr -- c-addr 0 if not found
|
|
;C xt 1 if immediate
|
|
;C xt -1 if "normal"
|
|
; LATEST @ BEGIN -- a nfa
|
|
; 2DUP OVER C@ CHAR+ -- a nfa a nfa n+1
|
|
; S= -- a nfa f
|
|
; DUP IF
|
|
; DROP
|
|
; NFA>LFA @ DUP -- a link link
|
|
; THEN
|
|
; 0= UNTIL -- a nfa OR a 0
|
|
; DUP IF
|
|
; NIP DUP NFA>CFA -- nfa xt
|
|
; SWAP IMMED? -- xt iflag
|
|
; 0= 1 OR -- xt 1/-1
|
|
; THEN ;
|
|
1035 head FIND,4,FIND,docolon
|
|
1035 2510 + DW link
|
|
1037 00 + DB 0
|
|
1038 +link DEFL $
|
|
1038 0446494E + DB 4,'FIND'
|
|
103D +FIND:
|
|
+ IF .NOT.(DOCOLON=DOCODE)
|
|
103D CD5301 + call DOCOLON
|
|
+ ENDIF
|
|
1040 D009F303 DW LATEST,FETCH
|
|
1044 1B0CFA02 FIND1: DW TWODUP,OVER,CFETCH,CHARPLUS
|
|
104C 2608B402 DW SEQUAL,DUP,qbranch,FIND2
|
|
1054 D702FD0F DW DROP,NFATOLFA,FETCH,DUP
|
|
105C 7E053106 FIND2: DW ZEROEQUAL,qbranch,FIND1
|
|
1062 B4023106 DW DUP,qbranch,FIND3
|
|
1068 2003B402 DW NIP,DUP,NFATOCFA
|
|
106E E7022C10 DW SWOP,IMMEDQ,ZEROEQUAL,LIT,1,OR
|
|
107A 1E01 FIND3: DW EXIT
|
|
|
|
;C LITERAL x -- append numeric literal
|
|
; STATE @ IF ['] LIT ,XT , THEN ; IMMEDIATE
|
|
; This tests STATE so that it can also be used
|
|
; interpretively. (ANSI doesn't require this.)
|
|
107C immed LITERAL,7,LITERAL,docolon
|
|
107C 3810 + DW link
|
|
107E 01 + DB 1
|
|
107F +link DEFL $
|
|
107F 074C4954 + DB 7,'LITERAL'
|
|
1087 +LITERAL:
|
|
+ IF .NOT.(DOCOLON=DOCODE)
|
|
1087 CD5301 + call DOCOLON
|
|
+ ENDIF
|
|
108A A609F303 DW STATE,FETCH,qbranch,LITER1
|
|
1092 36013601 DW LIT,LIT,COMMAXT,COMMA
|
|
109A 1E01 LITER1: DW EXIT
|
|
|
|
;Z DIGIT? c -- n -1 if c is a valid digit
|
|
;Z -- x 0 otherwise
|
|
; [ HEX ] DUP 39 > 100 AND + silly looking
|
|
; DUP 140 > 107 AND - 30 - but it works!
|
|
; DUP BASE @ U< ;
|
|
109C head DIGITQ,6,DIGIT?,docolon
|
|
109C 7F10 + DW link
|
|
109E 00 + DB 0
|
|
109F +link DEFL $
|
|
109F 06444947 + DB 6,'DIGIT?'
|
|
10A6 +DIGITQ:
|
|
+ IF .NOT.(DOCOLON=DOCODE)
|
|
10A6 CD5301 + call DOCOLON
|
|
+ ENDIF
|
|
10A9 B4023601 DW DUP,LIT,39H,GREATER,LIT,100H,AND,PLUS
|
|
10B9 B4023601 DW DUP,LIT,140H,GREATER,LIT,107H,AND
|
|
10C7 61043601 DW MINUS,LIT,30H,MINUS
|
|
10CF B4029809 DW DUP,BASE,FETCH,ULESS,EXIT
|
|
|
|
;Z ?SIGN adr n -- adr' n' f get optional sign
|
|
;Z advance adr/n if sign; return NZ if negative
|
|
; OVER C@ -- adr n c
|
|
; 2C - DUP ABS 1 = AND -- +=-1, -=+1, else 0
|
|
; DUP IF 1+ -- +=0, -=+2
|
|
; >R 1 /STRING R> -- adr' n' f
|
|
; THEN ;
|
|
10D9 head QSIGN,5,?SIGN,docolon
|
|
10D9 9F10 + DW link
|
|
10DB 00 + DB 0
|
|
10DC +link DEFL $
|
|
10DC 053F5349 + DB 5,'?SIGN'
|
|
10E2 +QSIGN:
|
|
+ IF .NOT.(DOCOLON=DOCODE)
|
|
10E2 CD5301 + call DOCOLON
|
|
+ ENDIF
|
|
10E5 FA020504 DW OVER,CFETCH,LIT,2CH,MINUS,DUP,ABS
|
|
10F3 36010100 DW LIT,1,EQUAL,AND,DUP,qbranch,QSIGN1
|
|
1101 E1044003 DW ONEPLUS,TOR,LIT,1,SLASHSTRING,RFROM
|
|
110D 1E01 QSIGN1: DW EXIT
|
|
|
|
;C >NUMBER ud adr u -- ud' adr' u'
|
|
;C convert string to number
|
|
; BEGIN
|
|
; DUP WHILE
|
|
; OVER C@ DIGIT?
|
|
; 0= IF DROP EXIT THEN
|
|
; >R 2SWAP BASE @ UD*
|
|
; R> M+ 2SWAP
|
|
; 1 /STRING
|
|
; REPEAT ;
|
|
110F head TONUMBER,7,>NUMBER,docolon
|
|
110F DC10 + DW link
|
|
1111 00 + DB 0
|
|
1112 +link DEFL $
|
|
1112 073E4E55 + DB 7,'>NUMBER'
|
|
111A +TONUMBER:
|
|
+ IF .NOT.(DOCOLON=DOCODE)
|
|
111A CD5301 + call DOCOLON
|
|
+ ENDIF
|
|
111D B4023106 TONUM1: DW DUP,qbranch,TONUM3
|
|
1123 FA020504 DW OVER,CFETCH,DIGITQ
|
|
1129 7E053106 DW ZEROEQUAL,qbranch,TONUM2,DROP,EXIT
|
|
1133 40032D0C TONUM2: DW TOR,TWOSWAP,BASE,FETCH,UDSTAR
|
|
113D 58034A04 DW RFROM,MPLUS,TWOSWAP
|
|
1143 36010100 DW LIT,1,SLASHSTRING,branch,TONUM1
|
|
114D 1E01 TONUM3: DW EXIT
|
|
|
|
;Z ?NUMBER c-addr -- n -1 string->number
|
|
;Z -- c-addr 0 if convert error
|
|
; DUP 0 0 ROT COUNT -- ca ud adr n
|
|
; ?SIGN >R >NUMBER -- ca ud adr' n'
|
|
; IF R> 2DROP 2DROP 0 -- ca 0 (error)
|
|
; ELSE 2DROP NIP R>
|
|
; IF NEGATE THEN -1 -- n -1 (ok)
|
|
; THEN ;
|
|
114F head QNUMBER,7,?NUMBER,docolon
|
|
114F 1211 + DW link
|
|
1151 00 + DB 0
|
|
1152 +link DEFL $
|
|
1152 073F4E55 + DB 7,'?NUMBER'
|
|
115A +QNUMBER:
|
|
+ IF .NOT.(DOCOLON=DOCODE)
|
|
115A CD5301 + call DOCOLON
|
|
+ ENDIF
|
|
115D B4023601 DW DUP,LIT,0,DUP,ROT,COUNT
|
|
1169 E2104003 DW QSIGN,TOR,TONUMBER,qbranch,QNUM1
|
|
1173 58030A0C DW RFROM,TWODROP,TWODROP,LIT,0
|
|
117D 1B069111 DW branch,QNUM3
|
|
1181 0A0C2003 QNUM1: DW TWODROP,NIP,RFROM,qbranch,QNUM2,NEGATE
|
|
118D 3601FFFF QNUM2: DW LIT,-1
|
|
1191 1E01 QNUM3: DW EXIT
|
|
|
|
;Z INTERPRET i*x c-addr u -- j*x
|
|
;Z interpret given buffer
|
|
; This is a common factor of EVALUATE and QUIT.
|
|
; ref. dpANS-6, 3.4 The Forth Text Interpreter
|
|
; 'SOURCE 2! 0 >IN !
|
|
; BEGIN
|
|
; BL WORD DUP C@ WHILE -- textadr
|
|
; FIND -- a 0/1/-1
|
|
; ?DUP IF -- xt 1/-1
|
|
; 1+ STATE @ 0= OR immed or interp?
|
|
; IF EXECUTE ELSE ,XT THEN
|
|
; ELSE -- textadr
|
|
; ?NUMBER
|
|
; IF POSTPONE LITERAL converted ok
|
|
; ELSE COUNT TYPE 3F EMIT CR ABORT err
|
|
; THEN
|
|
; THEN
|
|
; REPEAT DROP ;
|
|
1193 head INTERPRET,9,INTERPRET,docolon
|
|
1193 5211 + DW link
|
|
1195 00 + DB 0
|
|
1196 +link DEFL $
|
|
1196 09494E54 + DB 9,'INTERPRET'
|
|
11A0 +INTERPRET:
|
|
+ IF .NOT.(DOCOLON=DOCODE)
|
|
11A0 CD5301 + call DOCOLON
|
|
+ ENDIF
|
|
11A3 C109F20B DW TICKSOURCE,TWOSTORE,LIT,0,TOIN,STORE
|
|
11AF 5809AB0F INTER1: DW BL,WORD,DUP,CFETCH,qbranch,INTER9
|
|
11BB 3D10C402 DW FIND,QDUP,qbranch,INTER4
|
|
11C3 E104A609 DW ONEPLUS,STATE,FETCH,ZEROEQUAL,OR
|
|
11CD 3106D711 DW qbranch,INTER2
|
|
11D1 4F011B06 DW EXECUTE,branch,INTER3
|
|
11D7 CC08 INTER2: DW COMMAXT
|
|
11D9 1B06F711 INTER3: DW branch,INTER8
|
|
11DD 5A113106 INTER4: DW QNUMBER,qbranch,INTER5
|
|
11E3 87101B06 DW LITERAL,branch,INTER6
|
|
11E9 5D0C470D INTER5: DW COUNT,TYPE,LIT,3FH,EMIT,CR,ABORT
|
|
11F7 INTER6:
|
|
11F7 1B06AF11 INTER8: DW branch,INTER1
|
|
11FB D7021E01 INTER9: DW DROP,EXIT
|
|
|
|
;C EVALUATE i*x c-addr u -- j*x interprt string
|
|
; 'SOURCE 2@ >R >R >IN @ >R
|
|
; INTERPRET
|
|
; R> >IN ! R> R> 'SOURCE 2! ;
|
|
11FF head EVALUATE,8,EVALUATE,docolon
|
|
11FF 9611 + DW link
|
|
1201 00 + DB 0
|
|
1202 +link DEFL $
|
|
1202 08455641 + DB 8,'EVALUATE'
|
|
120B +EVALUATE:
|
|
+ IF .NOT.(DOCOLON=DOCODE)
|
|
120B CD5301 + call DOCOLON
|
|
+ ENDIF
|
|
120E C109DD0B DW TICKSOURCE,TWOFETCH,TOR,TOR
|
|
1216 8B09F303 DW TOIN,FETCH,TOR,INTERPRET
|
|
121E 58038B09 DW RFROM,TOIN,STORE,RFROM,RFROM
|
|
1228 C109F20B DW TICKSOURCE,TWOSTORE,EXIT
|
|
|
|
;C QUIT -- R: i*x -- interpret from kbd
|
|
; L0 LP ! R0 RP! 0 STATE !
|
|
; BEGIN
|
|
; TIB DUP TIBSIZE ACCEPT SPACE
|
|
; INTERPRET
|
|
; STATE @ 0= IF CR ." OK" THEN
|
|
; AGAIN ;
|
|
122E head QUIT,4,QUIT,docolon
|
|
122E 0212 + DW link
|
|
1230 00 + DB 0
|
|
1231 +link DEFL $
|
|
1231 04515549 + DB 4,'QUIT'
|
|
1236 +QUIT:
|
|
+ IF .NOT.(DOCOLON=DOCODE)
|
|
1236 CD5301 + call DOCOLON
|
|
+ ENDIF
|
|
1239 080AE609 DW L0,LP,STORE
|
|
123F 130ABE03 DW R0,RPSTORE,LIT,0,STATE,STORE
|
|
124B 7409B402 QUIT1: DW TIB,DUP,TIBSIZE,CPMACCEPT,SPACE
|
|
1255 A011 DW INTERPRET
|
|
1257 A609F303 DW STATE,FETCH,ZEROEQUAL,qbranch,QUIT2
|
|
1261 700C720D DW CR,XSQUOTE
|
|
1265 036F6B20 DB 3,'ok '
|
|
1269 470D DW TYPE
|
|
126B 1B064B12 QUIT2: DW branch,QUIT1
|
|
|
|
;C ABORT i*x -- R: j*x -- clear stk & QUIT
|
|
; S0 SP! QUIT ;
|
|
126F head ABORT,5,ABORT,docolon
|
|
126F 3112 + DW link
|
|
1271 00 + DB 0
|
|
1272 +link DEFL $
|
|
1272 0541424F + DB 5,'ABORT'
|
|
1278 +ABORT:
|
|
+ IF .NOT.(DOCOLON=DOCODE)
|
|
1278 CD5301 + call DOCOLON
|
|
+ ENDIF
|
|
127B F1099A03 DW S0,SPSTORE,QUIT ; QUIT never returns
|
|
|
|
;Z ?ABORT f c-addr u -- abort & print msg
|
|
; ROT IF TYPE ABORT THEN 2DROP ;
|
|
1281 head QABORT,6,?ABORT,docolon
|
|
1281 7212 + DW link
|
|
1283 00 + DB 0
|
|
1284 +link DEFL $
|
|
1284 063F4142 + DB 6,'?ABORT'
|
|
128B +QABORT:
|
|
+ IF .NOT.(DOCOLON=DOCODE)
|
|
128B CD5301 + call DOCOLON
|
|
+ ENDIF
|
|
128E 0D033106 DW ROT,qbranch,QABO1,TYPE,ABORT
|
|
1298 0A0C1E01 QABO1: DW TWODROP,EXIT
|
|
|
|
;C ABORT" i*x 0 -- i*x R: j*x -- j*x x1=0
|
|
;C i*x x1 -- R: j*x -- x1<>0
|
|
; POSTPONE S" POSTPONE ?ABORT ; IMMEDIATE
|
|
129C immed ABORTQUOTE,6,ABORT",docolon
|
|
129C 8412 + DW link
|
|
129E 01 + DB 1
|
|
129F +link DEFL $
|
|
129F 0641424F + DB 6,'ABORT"'
|
|
12A6 +ABORTQUOTE:
|
|
+ IF .NOT.(DOCOLON=DOCODE)
|
|
12A6 CD5301 + call DOCOLON
|
|
+ ENDIF
|
|
12A9 890D DW SQUOTE
|
|
12AB 36018B12 DW LIT,QABORT,COMMAXT
|
|
12B1 1E01 DW EXIT
|
|
|
|
;C ' -- xt find word in dictionary
|
|
; BL WORD FIND
|
|
; 0= ABORT" ?" ;
|
|
; head TICK,1,',docolon
|
|
12B3 9F12 DW link ; must expand
|
|
12B5 00 DB 0 ; manually
|
|
12B6 link DEFL $ ; because of
|
|
12B6 0127 DB 1,27h ; tick character
|
|
12B8 CD5301 TICK: call docolon
|
|
12BB 5809AB0F DW BL,WORD,FIND,ZEROEQUAL,XSQUOTE
|
|
12C5 013F DB 1,'?'
|
|
12C7 8B121E01 DW QABORT,EXIT
|
|
|
|
;C CHAR -- char parse ASCII character
|
|
; BL WORD 1+ C@ ;
|
|
12CB head CHAR,4,CHAR,docolon
|
|
12CB B612 + DW link
|
|
12CD 00 + DB 0
|
|
12CE +link DEFL $
|
|
12CE 04434841 + DB 4,'CHAR'
|
|
12D3 +CHAR:
|
|
+ IF .NOT.(DOCOLON=DOCODE)
|
|
12D3 CD5301 + call DOCOLON
|
|
+ ENDIF
|
|
12D6 5809AB0F DW BL,WORD,ONEPLUS,CFETCH,EXIT
|
|
|
|
;C [CHAR] -- compile character literal
|
|
; CHAR ['] LIT ,XT , ; IMMEDIATE
|
|
12E0 immed BRACCHAR,6,[CHAR],docolon
|
|
12E0 CE12 + DW link
|
|
12E2 01 + DB 1
|
|
12E3 +link DEFL $
|
|
12E3 065B4348 + DB 6,'[CHAR]'
|
|
12EA +BRACCHAR:
|
|
+ IF .NOT.(DOCOLON=DOCODE)
|
|
12EA CD5301 + call DOCOLON
|
|
+ ENDIF
|
|
12ED D312 DW CHAR
|
|
12EF 36013601 DW LIT,LIT,COMMAXT
|
|
12F5 310F1E01 DW COMMA,EXIT
|
|
|
|
;C ( -- skip input until )
|
|
; [ HEX ] 29 WORD DROP ; IMMEDIATE
|
|
12F9 immed PAREN,1,(,docolon
|
|
12F9 E312 + DW link
|
|
12FB 01 + DB 1
|
|
12FC +link DEFL $
|
|
12FC 0128 + DB 1,'('
|
|
12FE +PAREN:
|
|
+ IF .NOT.(DOCOLON=DOCODE)
|
|
12FE CD5301 + call DOCOLON
|
|
+ ENDIF
|
|
1301 36012900 DW LIT,29H,WORD,DROP,EXIT
|
|
|
|
; COMPILER ======================================
|
|
|
|
;C CREATE -- create an empty definition
|
|
; LATEST @ , 0 C, link & immed field
|
|
; HERE LATEST ! new "latest" link
|
|
; BL WORD C@ 1+ ALLOT name field
|
|
; docreate ,CF code field
|
|
130B head CREATE,6,CREATE,docolon
|
|
130B FC12 + DW link
|
|
130D 00 + DB 0
|
|
130E +link DEFL $
|
|
130E 06435245 + DB 6,'CREATE'
|
|
1315 +CREATE:
|
|
+ IF .NOT.(DOCOLON=DOCODE)
|
|
1315 CD5301 + call DOCOLON
|
|
+ ENDIF
|
|
1318 D009F303 DW LATEST,FETCH,COMMA,LIT,0,CCOMMA
|
|
1324 110FD009 DW HERE,LATEST,STORE
|
|
132A 5809AB0F DW BL,WORD,CFETCH,ONEPLUS,ALLOT
|
|
1334 36017F01 DW LIT,docreate,COMMACF,EXIT
|
|
|
|
;Z (DOES>) -- run-time action of DOES>
|
|
; R> adrs of headless DOES> def'n
|
|
; LATEST @ NFA>CFA code field to fix up
|
|
; !CF ;
|
|
133C head XDOES,7,(DOES>),docolon
|
|
133C 0E13 + DW link
|
|
133E 00 + DB 0
|
|
133F +link DEFL $
|
|
133F 0728444F + DB 7,'(DOES>)'
|
|
1347 +XDOES:
|
|
+ IF .NOT.(DOCOLON=DOCODE)
|
|
1347 CD5301 + call DOCOLON
|
|
+ ENDIF
|
|
134A 5803D009 DW RFROM,LATEST,FETCH,NFATOCFA,STORECF
|
|
1354 1E01 DW EXIT
|
|
|
|
;C DOES> -- change action of latest def'n
|
|
; COMPILE (DOES>)
|
|
; dodoes ,CF ; IMMEDIATE
|
|
1356 immed DOES,5,DOES>,docolon
|
|
1356 3F13 + DW link
|
|
1358 01 + DB 1
|
|
1359 +link DEFL $
|
|
1359 05444F45 + DB 5,'DOES>'
|
|
135F +DOES:
|
|
+ IF .NOT.(DOCOLON=DOCODE)
|
|
135F CD5301 + call DOCOLON
|
|
+ ENDIF
|
|
1362 36014713 DW LIT,XDOES,COMMAXT
|
|
1368 3601CE01 DW LIT,dodoes,COMMACF,EXIT
|
|
|
|
;C RECURSE -- recurse current definition
|
|
; LATEST @ NFA>CFA ,XT ; IMMEDIATE
|
|
1370 immed RECURSE,7,RECURSE,docolon
|
|
1370 5913 + DW link
|
|
1372 01 + DB 1
|
|
1373 +link DEFL $
|
|
1373 07524543 + DB 7,'RECURSE'
|
|
137B +RECURSE:
|
|
+ IF .NOT.(DOCOLON=DOCODE)
|
|
137B CD5301 + call DOCOLON
|
|
+ ENDIF
|
|
137E D009F303 DW LATEST,FETCH,NFATOCFA,COMMAXT,EXIT
|
|
|
|
;C [ -- enter interpretive state
|
|
; 0 STATE ! ; IMMEDIATE
|
|
1388 immed LEFTBRACKET,1,[,docolon
|
|
1388 7313 + DW link
|
|
138A 01 + DB 1
|
|
138B +link DEFL $
|
|
138B 015B + DB 1,'['
|
|
138D +LEFTBRACKET:
|
|
+ IF .NOT.(DOCOLON=DOCODE)
|
|
138D CD5301 + call DOCOLON
|
|
+ ENDIF
|
|
1390 36010000 DW LIT,0,STATE,STORE,EXIT
|
|
|
|
;C ] -- enter compiling state
|
|
; -1 STATE ! ;
|
|
139A head RIGHTBRACKET,1,],docolon
|
|
139A 8B13 + DW link
|
|
139C 00 + DB 0
|
|
139D +link DEFL $
|
|
139D 015D + DB 1,']'
|
|
139F +RIGHTBRACKET:
|
|
+ IF .NOT.(DOCOLON=DOCODE)
|
|
139F CD5301 + call DOCOLON
|
|
+ ENDIF
|
|
13A2 3601FFFF DW LIT,-1,STATE,STORE,EXIT
|
|
|
|
;Z HIDE -- "hide" latest definition
|
|
; LATEST @ DUP C@ 80 OR SWAP C! ;
|
|
13AC head HIDE,4,HIDE,docolon
|
|
13AC 9D13 + DW link
|
|
13AE 00 + DB 0
|
|
13AF +link DEFL $
|
|
13AF 04484944 + DB 4,'HIDE'
|
|
13B4 +HIDE:
|
|
+ IF .NOT.(DOCOLON=DOCODE)
|
|
13B4 CD5301 + call DOCOLON
|
|
+ ENDIF
|
|
13B7 D009F303 DW LATEST,FETCH,DUP,CFETCH,LIT,80H,OR
|
|
13C5 E702E203 DW SWOP,CSTORE,EXIT
|
|
|
|
;Z REVEAL -- "reveal" latest definition
|
|
; LATEST @ DUP C@ 7F AND SWAP C! ;
|
|
13CB head REVEAL,6,REVEAL,docolon
|
|
13CB AF13 + DW link
|
|
13CD 00 + DB 0
|
|
13CE +link DEFL $
|
|
13CE 06524556 + DB 6,'REVEAL'
|
|
13D5 +REVEAL:
|
|
+ IF .NOT.(DOCOLON=DOCODE)
|
|
13D5 CD5301 + call DOCOLON
|
|
+ ENDIF
|
|
13D8 D009F303 DW LATEST,FETCH,DUP,CFETCH,LIT,7FH,AND
|
|
13E6 E702E203 DW SWOP,CSTORE,EXIT
|
|
|
|
;C IMMEDIATE -- make last def'n immediate
|
|
; 1 LATEST @ 1- C! ; set immediate flag
|
|
13EC head IMMEDIATE,9,IMMEDIATE,docolon
|
|
13EC CE13 + DW link
|
|
13EE 00 + DB 0
|
|
13EF +link DEFL $
|
|
13EF 09494D4D + DB 9,'IMMEDIATE'
|
|
13F9 +IMMEDIATE:
|
|
+ IF .NOT.(DOCOLON=DOCODE)
|
|
13F9 CD5301 + call DOCOLON
|
|
+ ENDIF
|
|
13FC 36010100 DW LIT,1,LATEST,FETCH,ONEMINUS,CSTORE
|
|
1408 1E01 DW EXIT
|
|
|
|
;C : -- begin a colon definition
|
|
; CREATE HIDE ] !COLON ;
|
|
140A head COLON,1,:,docode
|
|
140A EF13 + DW link
|
|
140C 00 + DB 0
|
|
140D +link DEFL $
|
|
140D 013A + DB 1,':'
|
|
140F +COLON:
|
|
+ IF .NOT.(DOCODE=DOCODE)
|
|
+ call DOCODE
|
|
+ ENDIF
|
|
140F CD5301 CALL docolon ; code fwd ref explicitly
|
|
1412 1513B413 DW CREATE,HIDE,RIGHTBRACKET,STORCOLON
|
|
141A 1E01 DW EXIT
|
|
|
|
;C ;
|
|
; REVEAL ,EXIT
|
|
; POSTPONE [ ; IMMEDIATE
|
|
141C immed SEMICOLON,1,';',docolon
|
|
141C 0D14 + DW link
|
|
141E 01 + DB 1
|
|
141F +link DEFL $
|
|
141F 013B + DB 1,';'
|
|
1421 +SEMICOLON:
|
|
+ IF .NOT.(DOCOLON=DOCODE)
|
|
1421 CD5301 + call DOCOLON
|
|
+ ENDIF
|
|
1424 D5132109 DW REVEAL,CEXIT
|
|
1428 8D131E01 DW LEFTBRACKET,EXIT
|
|
|
|
;C ['] -- find word & compile as literal
|
|
; ' ['] LIT ,XT , ; IMMEDIATE
|
|
; When encountered in a colon definition, the
|
|
; phrase ['] xxx will cause LIT,xxt to be
|
|
; compiled into the colon definition (where
|
|
; (where xxt is the execution token of word xxx).
|
|
; When the colon definition executes, xxt will
|
|
; be put on the stack. (All xt's are one cell.)
|
|
; immed BRACTICK,3,['],docolon
|
|
142C 1F14 DW link ; must expand
|
|
142E 01 DB 1 ; manually
|
|
142F link DEFL $ ; because of
|
|
142F 035B275D DB 3,5Bh,27h,5Dh ; tick character
|
|
1433 CD5301 BRACTICK: call docolon
|
|
1436 B812 DW TICK ; get xt of 'xxx'
|
|
1438 36013601 DW LIT,LIT,COMMAXT ; append LIT action
|
|
143E 310F1E01 DW COMMA,EXIT ; append xt literal
|
|
|
|
;C POSTPONE -- postpone compile action of word
|
|
; BL WORD FIND
|
|
; DUP 0= ABORT" ?"
|
|
; 0< IF -- xt non immed: add code to current
|
|
; def'n to compile xt later.
|
|
; ['] LIT ,XT , add "LIT,xt,COMMAXT"
|
|
; ['] ,XT ,XT to current definition
|
|
; ELSE ,XT immed: compile into cur. def'n
|
|
; THEN ; IMMEDIATE
|
|
1442 immed POSTPONE,8,POSTPONE,docolon
|
|
1442 2F14 + DW link
|
|
1444 01 + DB 1
|
|
1445 +link DEFL $
|
|
1445 08504F53 + DB 8,'POSTPONE'
|
|
144E +POSTPONE:
|
|
+ IF .NOT.(DOCOLON=DOCODE)
|
|
144E CD5301 + call DOCOLON
|
|
+ ENDIF
|
|
1451 5809AB0F DW BL,WORD,FIND,DUP,ZEROEQUAL,XSQUOTE
|
|
145D 013F DB 1,'?'
|
|
145F 8B129205 DW QABORT,ZEROLESS,qbranch,POST1
|
|
1467 36013601 DW LIT,LIT,COMMAXT,COMMA
|
|
146F 3601CC08 DW LIT,COMMAXT,COMMAXT,branch,POST2
|
|
1479 CC08 POST1: DW COMMAXT
|
|
147B 1E01 POST2: DW EXIT
|
|
|
|
;Z COMPILE -- append inline execution token
|
|
; R> DUP CELL+ >R @ ,XT ;
|
|
; The phrase ['] xxx ,XT appears so often that
|
|
; this word was created to combine the actions
|
|
; of LIT and ,XT. It takes an inline literal
|
|
; execution token and appends it to the dict.
|
|
; head COMPILE,7,COMPILE,docolon
|
|
; DW RFROM,DUP,CELLPLUS,TOR
|
|
; DW FETCH,COMMAXT,EXIT
|
|
; N.B.: not used in the current implementation
|
|
|
|
; CONTROL STRUCTURES ============================
|
|
|
|
;C IF -- adrs conditional forward branch
|
|
; ['] qbranch ,BRANCH HERE DUP ,DEST ;
|
|
; IMMEDIATE
|
|
147D immed IF,2,IF,docolon
|
|
147D 4514 + DW link
|
|
147F 01 + DB 1
|
|
1480 +link DEFL $
|
|
1480 024946 + DB 2,'IF'
|
|
1483 +IF:
|
|
+ IF .NOT.(DOCOLON=DOCODE)
|
|
1483 CD5301 + call DOCOLON
|
|
+ ENDIF
|
|
1486 36013106 DW LIT,qbranch,COMMABRANCH
|
|
148C 110FB402 DW HERE,DUP,COMMADEST,EXIT
|
|
|
|
;C THEN adrs -- resolve forward branch
|
|
; HERE SWAP !DEST ; IMMEDIATE
|
|
1494 immed THEN,4,THEN,docolon
|
|
1494 8014 + DW link
|
|
1496 01 + DB 1
|
|
1497 +link DEFL $
|
|
1497 04544845 + DB 4,'THEN'
|
|
149C +THEN:
|
|
+ IF .NOT.(DOCOLON=DOCODE)
|
|
149C CD5301 + call DOCOLON
|
|
+ ENDIF
|
|
149F 110FE702 DW HERE,SWOP,STOREDEST,EXIT
|
|
|
|
;C ELSE adrs1 -- adrs2 branch for IF..ELSE
|
|
; ['] branch ,BRANCH HERE DUP ,DEST
|
|
; SWAP POSTPONE THEN ; IMMEDIATE
|
|
14A7 immed ELSE,4,ELSE,docolon
|
|
14A7 9714 + DW link
|
|
14A9 01 + DB 1
|
|
14AA +link DEFL $
|
|
14AA 04454C53 + DB 4,'ELSE'
|
|
14AF +ELSE:
|
|
+ IF .NOT.(DOCOLON=DOCODE)
|
|
14AF CD5301 + call DOCOLON
|
|
+ ENDIF
|
|
14B2 36011B06 DW LIT,branch,COMMABRANCH
|
|
14B8 110FB402 DW HERE,DUP,COMMADEST
|
|
14BE E7029C14 DW SWOP,THEN,EXIT
|
|
|
|
;C BEGIN -- adrs target for bwd. branch
|
|
; HERE ; IMMEDIATE
|
|
14C4 immed BEGIN,5,BEGIN,docode
|
|
14C4 AA14 + DW link
|
|
14C6 01 + DB 1
|
|
14C7 +link DEFL $
|
|
14C7 05424547 + DB 5,'BEGIN'
|
|
14CD +BEGIN:
|
|
+ IF .NOT.(DOCODE=DOCODE)
|
|
+ call DOCODE
|
|
+ ENDIF
|
|
14CD C3110F jp HERE
|
|
|
|
;C UNTIL adrs -- conditional backward branch
|
|
; ['] qbranch ,BRANCH ,DEST ; IMMEDIATE
|
|
; conditional backward branch
|
|
14D0 immed UNTIL,5,UNTIL,docolon
|
|
14D0 C714 + DW link
|
|
14D2 01 + DB 1
|
|
14D3 +link DEFL $
|
|
14D3 05554E54 + DB 5,'UNTIL'
|
|
14D9 +UNTIL:
|
|
+ IF .NOT.(DOCOLON=DOCODE)
|
|
14D9 CD5301 + call DOCOLON
|
|
+ ENDIF
|
|
14DC 36013106 DW LIT,qbranch,COMMABRANCH
|
|
14E2 43091E01 DW COMMADEST,EXIT
|
|
|
|
;X AGAIN adrs -- uncond'l backward branch
|
|
; ['] branch ,BRANCH ,DEST ; IMMEDIATE
|
|
; unconditional backward branch
|
|
14E6 immed AGAIN,5,AGAIN,docolon
|
|
14E6 D314 + DW link
|
|
14E8 01 + DB 1
|
|
14E9 +link DEFL $
|
|
14E9 05414741 + DB 5,'AGAIN'
|
|
14EF +AGAIN:
|
|
+ IF .NOT.(DOCOLON=DOCODE)
|
|
14EF CD5301 + call DOCOLON
|
|
+ ENDIF
|
|
14F2 36011B06 DW LIT,branch,COMMABRANCH
|
|
14F8 43091E01 DW COMMADEST,EXIT
|
|
|
|
;C WHILE -- adrs branch for WHILE loop
|
|
; POSTPONE IF ; IMMEDIATE
|
|
14FC immed WHILE,5,WHILE,docode
|
|
14FC E914 + DW link
|
|
14FE 01 + DB 1
|
|
14FF +link DEFL $
|
|
14FF 05574849 + DB 5,'WHILE'
|
|
1505 +WHILE:
|
|
+ IF .NOT.(DOCODE=DOCODE)
|
|
+ call DOCODE
|
|
+ ENDIF
|
|
1505 C38314 jp IF
|
|
|
|
;C REPEAT adrs1 adrs2 -- resolve WHILE loop
|
|
; SWAP POSTPONE AGAIN POSTPONE THEN ; IMMEDIATE
|
|
1508 immed REPEAT,6,REPEAT,docolon
|
|
1508 FF14 + DW link
|
|
150A 01 + DB 1
|
|
150B +link DEFL $
|
|
150B 06524550 + DB 6,'REPEAT'
|
|
1512 +REPEAT:
|
|
+ IF .NOT.(DOCOLON=DOCODE)
|
|
1512 CD5301 + call DOCOLON
|
|
+ ENDIF
|
|
1515 E702EF14 DW SWOP,AGAIN,THEN,EXIT
|
|
|
|
;Z >L x -- L: -- x move to leave stack
|
|
; CELL LP +! LP @ ! ; (L stack grows up)
|
|
151D head TOL,2,>L,docolon
|
|
151D 0B15 + DW link
|
|
151F 00 + DB 0
|
|
1520 +link DEFL $
|
|
1520 023E4C + DB 2,'>L'
|
|
1523 +TOL:
|
|
+ IF .NOT.(DOCOLON=DOCODE)
|
|
1523 CD5301 + call DOCOLON
|
|
+ ENDIF
|
|
1526 7208E609 DW CELL,LP,PLUSSTORE,LP,FETCH,STORE,EXIT
|
|
|
|
;Z L> -- x L: x -- move from leave stack
|
|
; LP @ @ CELL NEGATE LP +! ;
|
|
1534 head LFROM,2,L>,docolon
|
|
1534 2015 + DW link
|
|
1536 00 + DB 0
|
|
1537 +link DEFL $
|
|
1537 024C3E + DB 2,'L>'
|
|
153A +LFROM:
|
|
+ IF .NOT.(DOCOLON=DOCODE)
|
|
153A CD5301 + call DOCOLON
|
|
+ ENDIF
|
|
153D E609F303 DW LP,FETCH,FETCH
|
|
1543 7208CD04 DW CELL,NEGATE,LP,PLUSSTORE,EXIT
|
|
|
|
;C DO -- adrs L: -- 0
|
|
; ['] xdo ,XT HERE target for bwd branch
|
|
; 0 >L ; IMMEDIATE marker for LEAVEs
|
|
154D immed DO,2,DO,docolon
|
|
154D 3715 + DW link
|
|
154F 01 + DB 1
|
|
1550 +link DEFL $
|
|
1550 02444F + DB 2,'DO'
|
|
1553 +DO:
|
|
+ IF .NOT.(DOCOLON=DOCODE)
|
|
1553 CD5301 + call DOCOLON
|
|
+ ENDIF
|
|
1556 36014706 DW LIT,xdo,COMMAXT,HERE
|
|
155E 36010000 DW LIT,0,TOL,EXIT
|
|
|
|
;Z ENDLOOP adrs xt -- L: 0 a1 a2 .. aN --
|
|
; ,BRANCH ,DEST backward loop
|
|
; BEGIN L> ?DUP WHILE POSTPONE THEN REPEAT ;
|
|
; resolve LEAVEs
|
|
; This is a common factor of LOOP and +LOOP.
|
|
1566 head ENDLOOP,7,ENDLOOP,docolon
|
|
1566 5015 + DW link
|
|
1568 00 + DB 0
|
|
1569 +link DEFL $
|
|
1569 07454E44 + DB 7,'ENDLOOP'
|
|
1571 +ENDLOOP:
|
|
+ IF .NOT.(DOCOLON=DOCODE)
|
|
1571 CD5301 + call DOCOLON
|
|
+ ENDIF
|
|
1574 37094309 DW COMMABRANCH,COMMADEST
|
|
1578 3A15C402 LOOP1: DW LFROM,QDUP,qbranch,LOOP2
|
|
1580 9C141B06 DW THEN,branch,LOOP1
|
|
1586 1E01 LOOP2: DW EXIT
|
|
|
|
;C LOOP adrs -- L: 0 a1 a2 .. aN --
|
|
; ['] xloop ENDLOOP ; IMMEDIATE
|
|
1588 immed LOOP,4,LOOP,docolon
|
|
1588 6915 + DW link
|
|
158A 01 + DB 1
|
|
158B +link DEFL $
|
|
158B 044C4F4F + DB 4,'LOOP'
|
|
1590 +LOOP:
|
|
+ IF .NOT.(DOCOLON=DOCODE)
|
|
1590 CD5301 + call DOCOLON
|
|
+ ENDIF
|
|
1593 36017806 DW LIT,xloop,ENDLOOP,EXIT
|
|
|
|
;C +LOOP adrs -- L: 0 a1 a2 .. aN --
|
|
; ['] xplusloop ENDLOOP ; IMMEDIATE
|
|
159B immed PLUSLOOP,5,+LOOP,docolon
|
|
159B 8B15 + DW link
|
|
159D 01 + DB 1
|
|
159E +link DEFL $
|
|
159E 052B4C4F + DB 5,'+LOOP'
|
|
15A4 +PLUSLOOP:
|
|
+ IF .NOT.(DOCOLON=DOCODE)
|
|
15A4 CD5301 + call DOCOLON
|
|
+ ENDIF
|
|
15A7 3601AB06 DW LIT,xplusloop,ENDLOOP,EXIT
|
|
|
|
;C LEAVE -- L: -- adrs
|
|
; ['] UNLOOP ,XT
|
|
; ['] branch ,BRANCH HERE DUP ,DEST >L
|
|
; ; IMMEDIATE unconditional forward branch
|
|
15AF immed LEAVE,5,LEAVE,docolon
|
|
15AF 9E15 + DW link
|
|
15B1 01 + DB 1
|
|
15B2 +link DEFL $
|
|
15B2 054C4541 + DB 5,'LEAVE'
|
|
15B8 +LEAVE:
|
|
+ IF .NOT.(DOCOLON=DOCODE)
|
|
15B8 CD5301 + call DOCOLON
|
|
+ ENDIF
|
|
15BB 3601F906 DW LIT,unloop,COMMAXT
|
|
15C1 36011B06 DW LIT,branch,COMMABRANCH
|
|
15C7 110FB402 DW HERE,DUP,COMMADEST,TOL,EXIT
|
|
|
|
; OTHER OPERATIONS ==============================
|
|
|
|
;X WITHIN n1|u1 n2|u2 n3|u3 -- f n2<=n1<n3?
|
|
; OVER - >R - R> U< ; per ANS document
|
|
15D1 head WITHIN,6,WITHIN,docolon
|
|
15D1 B215 + DW link
|
|
15D3 00 + DB 0
|
|
15D4 +link DEFL $
|
|
15D4 06574954 + DB 6,'WITHIN'
|
|
15DB +WITHIN:
|
|
+ IF .NOT.(DOCOLON=DOCODE)
|
|
15DB CD5301 + call DOCOLON
|
|
+ ENDIF
|
|
15DE FA026104 DW OVER,MINUS,TOR,MINUS,RFROM,ULESS,EXIT
|
|
|
|
;C MOVE addr1 addr2 u -- smart move
|
|
; VERSION FOR 1 ADDRESS UNIT = 1 CHAR
|
|
; >R 2DUP SWAP DUP R@ + -- ... dst src src+n
|
|
; WITHIN IF R> CMOVE> src <= dst < src+n
|
|
; ELSE R> CMOVE THEN ; otherwise
|
|
15EC head MOVE,4,MOVE,docolon
|
|
15EC D415 + DW link
|
|
15EE 00 + DB 0
|
|
15EF +link DEFL $
|
|
15EF 044D4F56 + DB 4,'MOVE'
|
|
15F4 +MOVE:
|
|
+ IF .NOT.(DOCOLON=DOCODE)
|
|
15F4 CD5301 + call DOCOLON
|
|
+ ENDIF
|
|
15F7 40031B0C DW TOR,TWODUP,SWOP,DUP,RFETCH,PLUS
|
|
1603 DB153106 DW WITHIN,qbranch,MOVE1
|
|
1609 5803BC07 DW RFROM,CMOVEUP,branch,MOVE2
|
|
1611 58039E07 MOVE1: DW RFROM,CMOVE
|
|
1615 1E01 MOVE2: DW EXIT
|
|
|
|
;C DEPTH -- +n number of items on stack
|
|
; SP@ S0 SWAP - 2/ ; 16-BIT VERSION!
|
|
1617 head DEPTH,5,DEPTH,docolon
|
|
1617 EF15 + DW link
|
|
1619 00 + DB 0
|
|
161A +link DEFL $
|
|
161A 05444550 + DB 5,'DEPTH'
|
|
1620 +DEPTH:
|
|
+ IF .NOT.(DOCOLON=DOCODE)
|
|
1620 CD5301 + call DOCOLON
|
|
+ ENDIF
|
|
1623 8503F109 DW SPFETCH,S0,SWOP,MINUS,TWOSLASH,EXIT
|
|
|
|
;C ENVIRONMENT? c-addr u -- false system query
|
|
; -- i*x true
|
|
; 2DROP 0 ; the minimal definition!
|
|
162F head ENVIRONMENTQ,12,ENVIRONMENT?,docolon
|
|
162F 1A16 + DW link
|
|
1631 00 + DB 0
|
|
1632 +link DEFL $
|
|
1632 0C454E56 + DB 12,'ENVIRONMENT?'
|
|
163F +ENVIRONMENTQ:
|
|
+ IF .NOT.(DOCOLON=DOCODE)
|
|
163F CD5301 + call DOCOLON
|
|
+ ENDIF
|
|
1642 0A0C3601 DW TWODROP,LIT,0,EXIT
|
|
|
|
; UTILITY WORDS AND STARTUP =====================
|
|
|
|
;X WORDS -- list all words in dict.
|
|
; LATEST @ BEGIN
|
|
; DUP COUNT TYPE SPACE
|
|
; NFA>LFA @
|
|
; DUP 0= UNTIL
|
|
; DROP ;
|
|
164A head WORDS,5,WORDS,docolon
|
|
164A 3216 + DW link
|
|
164C 00 + DB 0
|
|
164D +link DEFL $
|
|
164D 05574F52 + DB 5,'WORDS'
|
|
1653 +WORDS:
|
|
+ IF .NOT.(DOCOLON=DOCODE)
|
|
1653 CD5301 + call DOCOLON
|
|
+ ENDIF
|
|
1656 D009F303 DW LATEST,FETCH
|
|
165A B4025D0C WDS1: DW DUP,COUNT,TYPE,SPACE,NFATOLFA,FETCH
|
|
1666 B4027E05 DW DUP,ZEROEQUAL,qbranch,WDS1
|
|
166E D7021E01 DW DROP,EXIT
|
|
|
|
;X .S -- print stack contents
|
|
; SP@ S0 - IF
|
|
; SP@ S0 2 - DO I @ U. -2 +LOOP
|
|
; THEN ;
|
|
1672 head DOTS,2,.S,docolon
|
|
1672 4D16 + DW link
|
|
1674 00 + DB 0
|
|
1675 +link DEFL $
|
|
1675 022E53 + DB 2,'.S'
|
|
1678 +DOTS:
|
|
+ IF .NOT.(DOCOLON=DOCODE)
|
|
1678 CD5301 + call DOCOLON
|
|
+ ENDIF
|
|
167B 8503F109 DW SPFETCH,S0,MINUS,qbranch,DOTS2
|
|
1685 8503F109 DW SPFETCH,S0,LIT,2,MINUS,XDO
|
|
1691 B806F303 DOTS1: DW II,FETCH,UDOT,LIT,-2,XPLUSLOOP,DOTS1
|
|
169F 1E01 DOTS2: DW EXIT
|
|
|
|
;Z COLD -- cold start Forth system
|
|
; UINIT U0 #INIT CMOVE init user area
|
|
; 80 COUNT INTERPRET interpret CP/M cmd
|
|
; ." Z80 CamelForth etc."
|
|
; ABORT ;
|
|
16A1 head COLD,4,COLD,docolon
|
|
16A1 7516 + DW link
|
|
16A3 00 + DB 0
|
|
16A4 +link DEFL $
|
|
16A4 04434F4C + DB 4,'COLD'
|
|
16A9 +COLD:
|
|
+ IF .NOT.(DOCOLON=DOCODE)
|
|
16A9 CD5301 + call DOCOLON
|
|
+ ENDIF
|
|
16AC 210A7F09 DW UINIT,U0,NINIT,CMOVE
|
|
16B4 36018000 DW LIT,80h,COUNT,INTERPRET
|
|
16BC 720D DW XSQUOTE
|
|
16BE 235A3830 DB 35,'Z80 CamelForth v1.01 25 Jan 1995'
|
|
16E0 0D0A DB 0dh,0ah
|
|
16E2 470D7812 DW TYPE,ABORT ; ABORT never returns
|
|
|
|
16A4 lastword EQU link ; nfa of last word in dict.
|
|
16E6 enddict EQU $ ; user's code starts here
|
|
16E6 END
|
|
|
|
|
|
REDEFINED SYMBOLS
|
|
|
|
LINK 16A4
|
|
|
|
ASEG SYMBOLS
|
|
|
|
ABORT 1278 ABORTQ 12A6 ABS 0A73 ACC1 0CF9 ACC3 0D27
|
|
ACC4 0D31 ACC5 0D35 ACCEPT 0CEE AGAIN 14EF ALIGN 0856
|
|
ALIGNE 0868 ALLOT 0F23 AND 0475 BASE 0998 BDOS 01EC
|
|
BEGIN 14CD BL 0958 BRACCH 12EA BRACTI 1433 BRANCH 061B
|
|
BYE 02AA CCOMMA 0F48 CELL 0872 CELLPL 0880 CELLS 0892
|
|
CEXIT 0921 CFETCH 0405 CHAR 12D3 CHARPL 089E CHARS 08AA
|
|
CMOVE 079E CMOVED 07A9 CMOVEU 07BC COLD 16A9 COLON 140F
|
|
COMMA 0F31 COMMAB 0937 COMMAC 08EE COMMAD 0943 COMMAX 08CC
|
|
CONSTA 0196 COUNT 0C5D CPMACC 027E CPMBDO 0005 CR 0C70
|
|
CREATE 1315 CSTORE 03E2 DABS 0ABB DECIMA 0EE8 DEPTH 1620
|
|
DIGITQ 10A6 DNEG1 0AB1 DNEGAT 0A87 DO 1553 DOBRAN 061B
|
|
DOCODE 0000 DOCOLO 0153 DOCON 019F DOCREA 017F DODOES 01CE
|
|
DOES 135F DOT 0EC2 DOTQUO 0DA8 DOTS 1678 DOTS1 1691
|
|
DOTS2 169F DOUSER 01BC DOVAR 017F DP 09B1 DROP 02D7
|
|
DUP 02B4 ELSE 14AF EMIT 020D ENDDIC 16E6 ENDLOO 1571
|
|
ENTER 0153 ENVIRO 163F EQUAL 05A3 EVALUA 120B EXECUT 014F
|
|
EXIT 011E FETCH 03F3 FILL 0777 FILLDO 078C FIND 103D
|
|
FIND1 1044 FIND2 105C FIND3 107A FMMOD1 0B3B FMMOD2 0B3F
|
|
FMSLAS 0B1C GREATE 05E5 HERE 0F11 HEX 0EFC HIDE 13B4
|
|
HOLD 0DFE HP 09DB IF 1483 II 06B8 IMMEDI 13F9
|
|
IMMEDQ 102C INTER1 11AF INTER2 11D7 INTER3 11D9 INTER4 11DD
|
|
INTER5 11E9 INTER6 11F7 INTER8 11F7 INTER9 11FB INTERP 11A0
|
|
INVERT 04B6 JJ 06D6 KEY 024E KEY1 0251 KEY2 0263
|
|
L0 0A08 LASTWO 16A4 LATEST 09D0 LEAVE 15B8 LEFTBR 138D
|
|
LESS 05C7 LESSNU 0E17 LFROM 153A LINK 16A4 LIT 0136
|
|
LITER1 109A LITERA 1087 LOOP 1590 LOOP1 1578 LOOP2 1586
|
|
LOOPTE 0691 LOOPTS 067C LP 09E6 LSH1 0538 LSH2 0539
|
|
LSHIFT 0533 MAX 0BAE MAX1 0BBB MIN 0BC6 MIN1 0BD3
|
|
MINUS 0461 MOD 0B79 MOVE 15F4 MOVE1 1611 MOVE2 1615
|
|
MPLUS 044A MPLUS1 0453 MSTAR 0ACA NEGATE 04CD NFATOC 1013
|
|
NFATOL 0FFD NINIT 0A3F NIP 0320 NOADD 0724 NOOP 0856
|
|
NOTEQU 05B9 NUM 0E4C NUMGRE 0E7A NUMS 0E63 NUMS1 0E66
|
|
ONEMIN 04EF ONEPLU 04E1 OR 0489 OVER 02FA PAD 09FD
|
|
PAREN 12FE PCFETC 0429 PCSTOR 0417 PLUS 0439 PLUSLO 15A4
|
|
PLUSST 0568 POPTOS 02D7 POST1 1479 POST2 147B POSTPO 144E
|
|
PUSHTO 02B4 QABO1 1298 QABORT 128B QBRANC 0631 QDNEGA 0AA6
|
|
QDUP 02C4 QNEG1 0A6A QNEGAT 0A5F QNUM1 1181 QNUM2 118D
|
|
QNUM3 1191 QNUMBE 115A QSIGN 10E2 QSIGN1 110D QUERYK 0232
|
|
QUIT 1236 QUIT1 124B QUIT2 126B R0 0A13 RECURS 137B
|
|
REPEAT 1512 RESET 0100 REVEAL 13D5 REVSEN 05DB RFETCH 0370
|
|
RFROM 0358 RIGHTB 139F ROT 030D RPFETC 03AC RPSTOR 03BE
|
|
RSH1 0553 RSH2 0557 RSHIFT 054E S0 09F1 SAVEKE 0225
|
|
SCAN 0805 SCANDO 0815 SDIFF 083E SEMICO 1421 SEQUAL 0826
|
|
SIGN 0E93 SIGN1 0EA2 SKIP 07DD SKIPDO 07F2 SKIPLO 07E7
|
|
SKIPMI 07F0 SLASH 0B69 SLASHM 0B57 SLASHS 0F77 SLOOP 082F
|
|
SMATCH 0838 SMSLAS 0AED SNEXT 0846 SOURCE 0F63 SPACE 0C8A
|
|
SPACES 0C9D SPCS1 0CA0 SPCS2 0CAE SPFETC 0385 SPSTOR 039A
|
|
SQUOTE 0D89 SSMOD 0B8B STAR 0B46 STARSL 0B9E STATE 09A6
|
|
STOD 0A4B STORCO 0907 STORE 03CE STOREC 08D6 STORED 094F
|
|
SWAPBY 04FD SWOP 02E7 THEN 149C TIB 0974 TIBSIZ 0968
|
|
TICK 12B8 TICKSO 09C1 TOBODY 08B5 TOCOUN 0F94 TODIGI 0E2C
|
|
TOIN 098B TOL 1523 TONUM1 111D TONUM2 1133 TONUM3 114D
|
|
TONUMB 111A TOR 0340 TOSFAL 05A9 TOSTRU 05D1 TUCK 0331
|
|
TWODRO 0C0A TWODUP 0C1B TWOFET 0BDD TWOOVE 0C43 TWOSLA 051E
|
|
TWOSTA 050D TWOSTO 0BF2 TWOSWA 0C2D TYP3 0D58 TYP4 0D66
|
|
TYP5 0D68 TYPE 0D47 U0 097F UDIV3 0751 UDIV4 0757
|
|
UDLOOP 0747 UDOT 0EAA UDSLAS 0DBF UDSTAR 0DDF UGREAT 0608
|
|
UINIT 0A21 ULESS 05F4 UMAX 0CD3 UMAX1 0CE0 UMIN 0CBA
|
|
UMIN1 0CC7 UMLOOP 0719 UMOVED 07CC UMSLAS 073C UMSTAR 070F
|
|
UNLOOP 06F9 UNTIL 14D9 USER 01B3 VARIAB 0170 WDS1 165A
|
|
WHILE 1505 WITHIN 15DB WORD 0FAB WORD1 0FD0 WORDS 1653
|
|
XDO 0647 XDOES 1347 XLOOP 0678 XOR 049E XPLUSL 06AB
|
|
XSQUOT 0D72 ZEROEQ 057E ZEROLE 0592
|
|
|
|
0000 ERROR(S) ASSEMBLY COMPLETE
|
|
47 XDOES 1347 XLOOP 0678 XOR 049E XPLUSL 06AB
|
|
XSQUOT 0D72 ZEROEQ 057E ZEROLE 0592
|
|
|
|
|