forth: make prev word field relative

This should help with upcoming challenges in bootstrapping z80 code
compiled through Forth.
This commit is contained in:
Virgil Dupras 2020-03-22 17:41:59 -04:00
parent 00de336976
commit ffe61a12f8
6 changed files with 110 additions and 88 deletions

View File

@ -7,7 +7,7 @@ AVRABIN = zasm/avra
SHELLAPPS = zasm ed SHELLAPPS = zasm ed
SHELLTGTS = ${SHELLAPPS:%=cfsin/%} SHELLTGTS = ${SHELLAPPS:%=cfsin/%}
# Those Forth source files are in a particular order # Those Forth source files are in a particular order
FORTHSRCS = core.fs str.fs parse.fs readln.fs fmt.fs high.fs z80a.fs FORTHSRCS = core.fs str.fs parse.fs readln.fs fmt.fs high.fs z80a.fs dummy.fs
FORTHSRC_PATHS = ${FORTHSRCS:%=../forth/%} FORTHSRC_PATHS = ${FORTHSRCS:%=../forth/%}
CFSIN_CONTENTS = $(SHELLTGTS) cfsin/user.h CFSIN_CONTENTS = $(SHELLTGTS) cfsin/user.h
OBJS = emul.o libz80/libz80.o OBJS = emul.o libz80/libz80.o

View File

@ -34,6 +34,6 @@ emulPutC:
out (STDIO_PORT), a out (STDIO_PORT), a
ret ret
.dw 0 ; placeholder used in glue1.
CODE_END: CODE_END:
.out LATEST
.out $ ; should be the same as in glue1 .out $ ; should be the same as in glue1

View File

@ -1,6 +1,6 @@
; Warning: The offsets of native dict entries must be exactly the same between ; Warning: The offsets of native dict entries must be exactly the same between
; glue0.asm and glue1.asm ; glue0.asm and glue1.asm
.equ LATEST CODE_END ; override .equ LATEST RAMSTART ; override
.equ STDIO_PORT 0x00 .equ STDIO_PORT 0x00
jp init jp init
@ -26,9 +26,6 @@ emulPutC:
out (STDIO_PORT), a out (STDIO_PORT), a
ret ret
.out $ ; should be the same as in glue0, minus 2 .out $ ; should be the same as in glue0
; stage0 spits, at the beginning of the binary, the address of the latest word
; Therefore, we can set the LATEST label to here and we should be good.
CODE_END:
.bin "core.bin" .bin "core.bin"
RAMSTART: RAMSTART:

View File

@ -71,9 +71,6 @@ int main(int argc, char *argv[])
#ifndef DEBUG #ifndef DEBUG
// We're done, now let's spit dict data // We're done, now let's spit dict data
// let's start with LATEST spitting.
putchar(m->mem[CURRENT]);
putchar(m->mem[CURRENT+1]);
uint16_t here = m->mem[HERE] + (m->mem[HERE+1] << 8); uint16_t here = m->mem[HERE] + (m->mem[HERE+1] << 8);
for (int i=sizeof(KERNEL); i<here; i++) { for (int i=sizeof(KERNEL); i<here; i++) {
putchar(m->mem[i]); putchar(m->mem[i]);

4
forth/dummy.fs Normal file
View File

@ -0,0 +1,4 @@
( When building a compiled dict, always include this unit at
the end of it so that Forth knows how to hook LATEST into
it )
WORD _______ (entry)

View File

@ -119,12 +119,10 @@ forthMain:
push af \ push af \ push af push af \ push af \ push af
ld (INITIAL_SP), sp ld (INITIAL_SP), sp
ld ix, RS_ADDR ld ix, RS_ADDR
; LATEST is a *indirect* label to the latest entry of the dict. See ; LATEST is a label to the latest entry of the dict. This can be
; default at the bottom of dict.asm. This indirection allows us to ; overridden if a binary dict has been grafted to the end of this
; override latest to a value set in a binary dict compiled separately, ; binary
; for example by the stage0 bin.
ld hl, LATEST ld hl, LATEST
call intoHL
ld (CURRENT), hl ld (CURRENT), hl
ld hl, HERE_INITIAL ld hl, HERE_INITIAL
ld (HERE), hl ld (HERE), hl
@ -416,9 +414,12 @@ find:
call strncmp call strncmp
pop de ; <-- lvl 1, return to wordref pop de ; <-- lvl 1, return to wordref
jr z, .end ; found jr z, .end ; found
push hl ; .prev destroys HL
call .prev call .prev
pop hl
jr nz, .inner jr nz, .inner
; Z set? end of dict unset Z ; Z set? end of dict unset Z
xor a
inc a inc a
.end: .end:
pop bc pop bc
@ -429,15 +430,21 @@ find:
; Z is set if DE point to 0 (no entry). NZ if not. ; Z is set if DE point to 0 (no entry). NZ if not.
.prev: .prev:
dec de \ dec de \ dec de ; prev field dec de \ dec de \ dec de ; prev field
push de ; --> lvl 1
ex de, hl ex de, hl
call intoHL call intoHL
ex de, hl ; de preserved by intoHL, so no push/pop needed ex de, hl ; DE contains prev offset
; DE points to prev. Is it zero? pop hl ; <-- lvl 1
xor a ; HL is prev field's addr
or d ; Is offset zero?
ld a, d
or e or e
; Z will be set if DE is zero ret z ; no prev entry
ret ; get absolute addr from offset
; carry cleared from "or e"
sbc hl, de
ex de, hl ; result in DE
ret ; NZ set from SBC
; Checks flags Z and S and sets BC to 0 if Z, 1 if C and -1 otherwise ; Checks flags Z and S and sets BC to 0 if Z, 1 if C and -1 otherwise
flagsToBC: flagsToBC:
@ -519,11 +526,14 @@ chkPS:
; It's important that this part is at the end of the resulting binary. ; It's important that this part is at the end of the resulting binary.
; A dictionary entry has this structure: ; A dictionary entry has this structure:
; - 7b name (zero-padded) ; - 7b name (zero-padded)
; - 2b prev pointer ; - 2b prev offset
; - 1b flags (bit 0: IMMEDIATE) ; - 1b flags (bit 0: IMMEDIATE)
; - 2b code pointer ; - 2b code pointer
; - Parameter field (PF) ; - Parameter field (PF)
; ;
; The prev offset is the number of bytes between the prev field and the
; previous word's code pointer.
;
; The code pointer point to "word routines". These routines expect to be called ; The code pointer point to "word routines". These routines expect to be called
; with IY pointing to the PF. They themselves are expected to end by jumping ; with IY pointing to the PF. They themselves are expected to end by jumping
; to the address at (IP). They will usually do so with "jp next". ; to the address at (IP). They will usually do so with "jp next".
@ -642,7 +652,7 @@ EXIT:
; ( R:I -- ) ; ( R:I -- )
.db "QUIT" .db "QUIT"
.fill 3 .fill 3
.dw EXIT .dw $-EXIT
.db 0 .db 0
QUIT: QUIT:
.dw compiledWord .dw compiledWord
@ -659,7 +669,7 @@ QUIT:
.db "ABORT" .db "ABORT"
.fill 2 .fill 2
.dw QUIT .dw $-QUIT
.db 0 .db 0
ABORT: ABORT:
.dw compiledWord .dw compiledWord
@ -685,7 +695,7 @@ abortUnderflow:
.db "BYE" .db "BYE"
.fill 4 .fill 4
.dw ABORT .dw $-ABORT
.db 0 .db 0
BYE: BYE:
.dw nativeWord .dw nativeWord
@ -700,7 +710,7 @@ BYE:
; ( c -- ) ; ( c -- )
.db "EMIT" .db "EMIT"
.fill 3 .fill 3
.dw BYE .dw $-BYE
.db 0 .db 0
EMIT: EMIT:
.dw nativeWord .dw nativeWord
@ -711,7 +721,7 @@ EMIT:
jp next jp next
.db "(print)" .db "(print)"
.dw EMIT .dw $-EMIT
.db 0 .db 0
PRINT: PRINT:
.dw nativeWord .dw nativeWord
@ -728,7 +738,7 @@ PRINT:
; ( c port -- ) ; ( c port -- )
.db "PC!" .db "PC!"
.fill 4 .fill 4
.dw PRINT .dw $-PRINT
.db 0 .db 0
PSTORE: PSTORE:
.dw nativeWord .dw nativeWord
@ -741,7 +751,7 @@ PSTORE:
; ( port -- c ) ; ( port -- c )
.db "PC@" .db "PC@"
.fill 4 .fill 4
.dw PSTORE .dw $-PSTORE
.db 0 .db 0
PFETCH: PFETCH:
.dw nativeWord .dw nativeWord
@ -754,7 +764,7 @@ PFETCH:
.db "C," .db "C,"
.fill 5 .fill 5
.dw PFETCH .dw $-PFETCH
.db 0 .db 0
CWR: CWR:
.dw nativeWord .dw nativeWord
@ -769,7 +779,7 @@ CWR:
.db "," .db ","
.fill 6 .fill 6
.dw CWR .dw $-CWR
.db 0 .db 0
WR: WR:
.dw nativeWord .dw nativeWord
@ -782,7 +792,7 @@ WR:
.db "ROUTINE" .db "ROUTINE"
.dw WR .dw $-WR
.db 1 ; IMMEDIATE .db 1 ; IMMEDIATE
ROUTINE: ROUTINE:
.dw compiledWord .dw compiledWord
@ -818,6 +828,9 @@ ROUTINE:
jr z, .end jr z, .end
ld de, NUMBER ld de, NUMBER
cp 'N' cp 'N'
jr z, .end
ld de, chkPS
cp 'P'
jr nz, .notgood jr nz, .notgood
; continue to end on match ; continue to end on match
.end: .end:
@ -834,7 +847,7 @@ ROUTINE:
; ( addr -- ) ; ( addr -- )
.db "EXECUTE" .db "EXECUTE"
.dw ROUTINE .dw $-ROUTINE
.db 0 .db 0
EXECUTE: EXECUTE:
.dw nativeWord .dw nativeWord
@ -851,7 +864,7 @@ EXECUTE:
.db ";" .db ";"
.fill 6 .fill 6
.dw EXECUTE .dw $-EXECUTE
.db 1 ; IMMEDIATE .db 1 ; IMMEDIATE
ENDDEF: ENDDEF:
.dw compiledWord .dw compiledWord
@ -866,7 +879,7 @@ ENDDEF:
.db ":" .db ":"
.fill 6 .fill 6
.dw ENDDEF .dw $-ENDDEF
.db 1 ; IMMEDIATE .db 1 ; IMMEDIATE
DEFINE: DEFINE:
.dw compiledWord .dw compiledWord
@ -911,7 +924,7 @@ DEFINE:
.db "DOES>" .db "DOES>"
.fill 2 .fill 2
.dw DEFINE .dw $-DEFINE
.db 0 .db 0
DOES: DOES:
.dw nativeWord .dw nativeWord
@ -932,7 +945,7 @@ DOES:
.db "IMMEDIA" .db "IMMEDIA"
.dw DOES .dw $-DOES
.db 0 .db 0
IMMEDIATE: IMMEDIATE:
.dw nativeWord .dw nativeWord
@ -944,7 +957,7 @@ IMMEDIATE:
.db "IMMED?" .db "IMMED?"
.fill 1 .fill 1
.dw IMMEDIATE .dw $-IMMEDIATE
.db 0 .db 0
ISIMMED: ISIMMED:
.dw nativeWord .dw nativeWord
@ -962,7 +975,7 @@ ISIMMED:
; ( n -- ) ; ( n -- )
.db "LITN" .db "LITN"
.fill 3 .fill 3
.dw ISIMMED .dw $-ISIMMED
.db 0 .db 0
LITN: LITN:
.dw nativeWord .dw nativeWord
@ -977,7 +990,7 @@ LITN:
.db "SCPY" .db "SCPY"
.fill 3 .fill 3
.dw LITN .dw $-LITN
.db 0 .db 0
SCPY: SCPY:
.dw nativeWord .dw nativeWord
@ -990,7 +1003,7 @@ SCPY:
.db "(find)" .db "(find)"
.fill 1 .fill 1
.dw SCPY .dw $-SCPY
.db 0 .db 0
FIND_: FIND_:
.dw nativeWord .dw nativeWord
@ -1010,7 +1023,7 @@ FIND_:
.db "'" .db "'"
.fill 6 .fill 6
.dw FIND_ .dw $-FIND_
.db 0 .db 0
FIND: FIND:
.dw compiledWord .dw compiledWord
@ -1022,7 +1035,7 @@ FIND:
.db "[']" .db "[']"
.fill 4 .fill 4
.dw FIND .dw $-FIND
.db 0b01 ; IMMEDIATE .db 0b01 ; IMMEDIATE
FINDI: FINDI:
.dw compiledWord .dw compiledWord
@ -1044,7 +1057,7 @@ FINDERR:
; ( -- c ) ; ( -- c )
.db "KEY" .db "KEY"
.fill 4 .fill 4
.dw FINDI .dw $-FINDI
.db 0 .db 0
KEY: KEY:
.dw nativeWord .dw nativeWord
@ -1073,7 +1086,7 @@ CIN:
; 32 CMP 1 - ; 32 CMP 1 -
.db "WS?" .db "WS?"
.fill 4 .fill 4
.dw KEY .dw $-KEY
.db 0 .db 0
ISWS: ISWS:
.dw compiledWord .dw compiledWord
@ -1087,7 +1100,7 @@ ISWS:
.db "NOT" .db "NOT"
.fill 4 .fill 4
.dw ISWS .dw $-ISWS
.db 0 .db 0
NOT: NOT:
.dw nativeWord .dw nativeWord
@ -1107,7 +1120,7 @@ NOT:
; C< DUP 32 CMP 1 - SKIP? EXIT DROP TOWORD ; C< DUP 32 CMP 1 - SKIP? EXIT DROP TOWORD
.db "TOWORD" .db "TOWORD"
.fill 1 .fill 1
.dw NOT .dw $-NOT
.db 0 .db 0
TOWORD: TOWORD:
.dw compiledWord .dw compiledWord
@ -1124,7 +1137,7 @@ TOWORD:
; HL point to WORDBUF. ; HL point to WORDBUF.
.db "WORD" .db "WORD"
.fill 3 .fill 3
.dw TOWORD .dw $-TOWORD
.db 0 .db 0
WORD: WORD:
.dw compiledWord .dw compiledWord
@ -1171,7 +1184,7 @@ WORD:
.db "(parsed" .db "(parsed"
.dw WORD .dw $-WORD
.db 0 .db 0
PARSED: PARSED:
.dw nativeWord .dw nativeWord
@ -1192,7 +1205,7 @@ PARSED:
.db "(parse)" .db "(parse)"
.dw PARSED .dw $-PARSED
.db 0 .db 0
PARSE: PARSE:
.dw compiledWord .dw compiledWord
@ -1222,7 +1235,7 @@ PARSEI:
; Spit name (in (HL)) + prev in (HERE) and adjust (HERE) and (CURRENT) ; Spit name (in (HL)) + prev in (HERE) and adjust (HERE) and (CURRENT)
; HL points to new (HERE) ; HL points to new (HERE)
.db "(entry)" .db "(entry)"
.dw PARSE .dw $-PARSE
.db 0 .db 0
ENTRYHEAD: ENTRYHEAD:
.dw nativeWord .dw nativeWord
@ -1233,6 +1246,11 @@ ENTRYHEAD:
ld de, (CURRENT) ld de, (CURRENT)
ld a, NAMELEN ld a, NAMELEN
call addHL call addHL
push hl ; --> lvl 1
or a ; clear carry
sbc hl, de
ex de, hl
pop hl ; <-- lvl 1
call DEinHL call DEinHL
; Set word flags: not IMMED, so it's 0 ; Set word flags: not IMMED, so it's 0
xor a xor a
@ -1250,7 +1268,7 @@ ENTRYHEAD:
; this word is not documented in dictionary.txt ; this word is not documented in dictionary.txt
.db "(sysv)" .db "(sysv)"
.fill 1 .fill 1
.dw ENTRYHEAD .dw $-ENTRYHEAD
.db 0 .db 0
SYSV: SYSV:
.dw compiledWord .dw compiledWord
@ -1278,21 +1296,21 @@ SYSV:
.db "HERE" .db "HERE"
.fill 3 .fill 3
.dw SYSV .dw $-SYSV
.db 0 .db 0
HERE_: ; Caution: conflicts with actual variable name HERE_: ; Caution: conflicts with actual variable name
.dw sysvarWord .dw sysvarWord
.dw HERE .dw HERE
.db "CURRENT" .db "CURRENT"
.dw HERE_ .dw $-HERE_
.db 0 .db 0
CURRENT_: CURRENT_:
.dw sysvarWord .dw sysvarWord
.dw CURRENT .dw CURRENT
.db "(parse*" .db "(parse*"
.dw CURRENT_ .dw $-CURRENT_
.db 0 .db 0
PARSEPTR_: PARSEPTR_:
.dw sysvarWord .dw sysvarWord
@ -1300,7 +1318,7 @@ PARSEPTR_:
.db "FLAGS" .db "FLAGS"
.fill 2 .fill 2
.dw PARSEPTR_ .dw $-PARSEPTR_
.db 0 .db 0
FLAGS_: FLAGS_:
.dw sysvarWord .dw sysvarWord
@ -1309,7 +1327,7 @@ FLAGS_:
; ( n a -- ) ; ( n a -- )
.db "!" .db "!"
.fill 6 .fill 6
.dw FLAGS_ .dw $-FLAGS_
.db 0 .db 0
STORE: STORE:
.dw nativeWord .dw nativeWord
@ -1323,7 +1341,7 @@ STORE:
; ( n a -- ) ; ( n a -- )
.db "C!" .db "C!"
.fill 5 .fill 5
.dw STORE .dw $-STORE
.db 0 .db 0
CSTORE: CSTORE:
.dw nativeWord .dw nativeWord
@ -1336,7 +1354,7 @@ CSTORE:
; ( a -- n ) ; ( a -- n )
.db "@" .db "@"
.fill 6 .fill 6
.dw CSTORE .dw $-CSTORE
.db 0 .db 0
FETCH: FETCH:
.dw nativeWord .dw nativeWord
@ -1349,7 +1367,7 @@ FETCH:
; ( a -- c ) ; ( a -- c )
.db "C@" .db "C@"
.fill 5 .fill 5
.dw FETCH .dw $-FETCH
.db 0 .db 0
CFETCH: CFETCH:
.dw nativeWord .dw nativeWord
@ -1363,7 +1381,7 @@ CFETCH:
; ( a -- ) ; ( a -- )
.db "DROP" .db "DROP"
.fill 3 .fill 3
.dw CFETCH .dw $-CFETCH
.db 0 .db 0
DROP: DROP:
.dw nativeWord .dw nativeWord
@ -1373,7 +1391,7 @@ DROP:
; ( a b -- b a ) ; ( a b -- b a )
.db "SWAP" .db "SWAP"
.fill 3 .fill 3
.dw DROP .dw $-DROP
.db 0 .db 0
SWAP: SWAP:
.dw nativeWord .dw nativeWord
@ -1386,7 +1404,7 @@ SWAP:
; ( a b c d -- c d a b ) ; ( a b c d -- c d a b )
.db "2SWAP" .db "2SWAP"
.fill 2 .fill 2
.dw SWAP .dw $-SWAP
.db 0 .db 0
SWAP2: SWAP2:
.dw nativeWord .dw nativeWord
@ -1404,7 +1422,7 @@ SWAP2:
; ( a -- a a ) ; ( a -- a a )
.db "DUP" .db "DUP"
.fill 4 .fill 4
.dw SWAP2 .dw $-SWAP2
.db 0 .db 0
DUP: DUP:
.dw nativeWord .dw nativeWord
@ -1417,7 +1435,7 @@ DUP:
; ( a b -- a b a b ) ; ( a b -- a b a b )
.db "2DUP" .db "2DUP"
.fill 3 .fill 3
.dw DUP .dw $-DUP
.db 0 .db 0
DUP2: DUP2:
.dw nativeWord .dw nativeWord
@ -1433,7 +1451,7 @@ DUP2:
; ( a b -- a b a ) ; ( a b -- a b a )
.db "OVER" .db "OVER"
.fill 3 .fill 3
.dw DUP2 .dw $-DUP2
.db 0 .db 0
OVER: OVER:
.dw nativeWord .dw nativeWord
@ -1448,7 +1466,7 @@ OVER:
; ( a b c d -- a b c d a b ) ; ( a b c d -- a b c d a b )
.db "2OVER" .db "2OVER"
.fill 2 .fill 2
.dw OVER .dw $-OVER
.db 0 .db 0
OVER2: OVER2:
.dw nativeWord .dw nativeWord
@ -1468,7 +1486,7 @@ OVER2:
; ( a b c -- b c a) ; ( a b c -- b c a)
.db "ROT" .db "ROT"
.fill 4 .fill 4
.dw OVER2 .dw $-OVER2
.db 0 .db 0
ROT: ROT:
.dw nativeWord .dw nativeWord
@ -1483,7 +1501,7 @@ ROT:
.db ">R" .db ">R"
.fill 5 .fill 5
.dw ROT .dw $-ROT
.db 0 .db 0
P2R: P2R:
.dw nativeWord .dw nativeWord
@ -1494,7 +1512,7 @@ P2R:
.db "R>" .db "R>"
.fill 5 .fill 5
.dw P2R .dw $-P2R
.db 0 .db 0
R2P: R2P:
.dw nativeWord .dw nativeWord
@ -1504,7 +1522,7 @@ R2P:
.db "I" .db "I"
.fill 6 .fill 6
.dw R2P .dw $-R2P
.db 0 .db 0
I: I:
.dw nativeWord .dw nativeWord
@ -1515,7 +1533,7 @@ I:
.db "I'" .db "I'"
.fill 5 .fill 5
.dw I .dw $-I
.db 0 .db 0
IPRIME: IPRIME:
.dw nativeWord .dw nativeWord
@ -1526,7 +1544,7 @@ IPRIME:
.db "J" .db "J"
.fill 6 .fill 6
.dw IPRIME .dw $-IPRIME
.db 0 .db 0
J: J:
.dw nativeWord .dw nativeWord
@ -1538,7 +1556,7 @@ J:
; ( a b -- c ) A + B ; ( a b -- c ) A + B
.db "+" .db "+"
.fill 6 .fill 6
.dw J .dw $-J
.db 0 .db 0
PLUS: PLUS:
.dw nativeWord .dw nativeWord
@ -1552,7 +1570,7 @@ PLUS:
; ( a b -- c ) A - B ; ( a b -- c ) A - B
.db "-" .db "-"
.fill 6 .fill 6
.dw PLUS .dw $-PLUS
.db 0 .db 0
MINUS: MINUS:
.dw nativeWord .dw nativeWord
@ -1567,7 +1585,7 @@ MINUS:
; ( a b -- c ) A * B ; ( a b -- c ) A * B
.db "*" .db "*"
.fill 6 .fill 6
.dw MINUS .dw $-MINUS
.db 0 .db 0
MULT: MULT:
.dw nativeWord .dw nativeWord
@ -1594,7 +1612,7 @@ MULT:
.db "/MOD" .db "/MOD"
.fill 3 .fill 3
.dw MULT .dw $-MULT
.db 0 .db 0
DIVMOD: DIVMOD:
.dw nativeWord .dw nativeWord
@ -1609,7 +1627,7 @@ DIVMOD:
.db "AND" .db "AND"
.fill 4 .fill 4
.dw DIVMOD .dw $-DIVMOD
.db 0 .db 0
AND: AND:
.dw nativeWord .dw nativeWord
@ -1627,7 +1645,7 @@ AND:
.db "OR" .db "OR"
.fill 5 .fill 5
.dw AND .dw $-AND
.db 0 .db 0
OR: OR:
.dw nativeWord .dw nativeWord
@ -1645,7 +1663,7 @@ OR:
.db "XOR" .db "XOR"
.fill 4 .fill 4
.dw OR .dw $-OR
.db 0 .db 0
XOR: XOR:
.dw nativeWord .dw nativeWord
@ -1667,7 +1685,7 @@ XOR:
.db "0" .db "0"
.fill 6 .fill 6
.dw XOR .dw $-XOR
.db 0 .db 0
ZERO: ZERO:
.dw nativeWord .dw nativeWord
@ -1677,7 +1695,7 @@ ZERO:
.db "1" .db "1"
.fill 6 .fill 6
.dw ZERO .dw $-ZERO
.db 0 .db 0
ONE: ONE:
.dw nativeWord .dw nativeWord
@ -1688,7 +1706,7 @@ ONE:
; ( a1 a2 -- b ) ; ( a1 a2 -- b )
.db "SCMP" .db "SCMP"
.fill 3 .fill 3
.dw ONE .dw $-ONE
.db 0 .db 0
SCMP: SCMP:
.dw nativeWord .dw nativeWord
@ -1703,7 +1721,7 @@ SCMP:
; ( n1 n2 -- f ) ; ( n1 n2 -- f )
.db "CMP" .db "CMP"
.fill 4 .fill 4
.dw SCMP .dw $-SCMP
.db 0 .db 0
CMP: CMP:
.dw nativeWord .dw nativeWord
@ -1721,7 +1739,7 @@ CMP:
; to after null-termination. ; to after null-termination.
.db "SKIP?" .db "SKIP?"
.fill 2 .fill 2
.dw CMP .dw $-CMP
.db 0 .db 0
CSKIP: CSKIP:
.dw nativeWord .dw nativeWord
@ -1779,7 +1797,7 @@ CSKIP:
; contain 3. Add this value to RS. ; contain 3. Add this value to RS.
.db "(fbr)" .db "(fbr)"
.fill 2 .fill 2
.dw CSKIP .dw $-CSKIP
.db 0 .db 0
FBR: FBR:
.dw nativeWord .dw nativeWord
@ -1793,7 +1811,7 @@ FBR:
.db "(bbr)" .db "(bbr)"
.fill 2 .fill 2
.dw FBR .dw $-FBR
.db 0 .db 0
BBR: BBR:
.dw nativeWord .dw nativeWord
@ -1805,5 +1823,11 @@ BBR:
ld (IP), hl ld (IP), hl
jp next jp next
; To allow dict binaries to "hook themselves up", we always end such binary
; with a dummy, *empty* entry. Therefore, we can have a predictable place for
; getting a prev label.
.db "_______"
.dw $-BBR
.db 0
LATEST: LATEST:
.dw BBR