mirror of
https://github.com/hsoft/collapseos.git
synced 2024-11-26 10:28:05 +11:00
Compare commits
5 Commits
a8e573c84a
...
d0d92a4559
Author | SHA1 | Date | |
---|---|---|---|
|
d0d92a4559 | ||
|
d5a7d5faf8 | ||
|
fb54fd51af | ||
|
3819dbc083 | ||
|
ff281f69a8 |
@ -1,8 +1,15 @@
|
|||||||
|
: H HERE @ ;
|
||||||
|
: -^ SWAP - ;
|
||||||
: ? @ . ;
|
: ? @ . ;
|
||||||
: +! SWAP OVER @ + SWAP ! ;
|
: +! SWAP OVER @ + SWAP ! ;
|
||||||
: ALLOT HERE +! ;
|
: ALLOT HERE +! ;
|
||||||
: VARIABLE CREATE 2 ALLOT ;
|
: VARIABLE CREATE 2 ALLOT ;
|
||||||
: CONSTANT CREATE HERE @ ! DOES> @ ;
|
: CONSTANT CREATE H ! DOES> @ ;
|
||||||
|
: , H ! 2 ALLOT ;
|
||||||
|
: C, H C! 1 ALLOT ;
|
||||||
|
: IF ['] (fbr?) , H 0 C, ; IMMEDIATE
|
||||||
|
: THEN DUP H -^ SWAP C! ; IMMEDIATE
|
||||||
|
: ELSE ['] (fbr) , 0 C, DUP H -^ SWAP C! H 1 - ; IMMEDIATE
|
||||||
: NOT IF 0 ELSE 1 THEN ;
|
: NOT IF 0 ELSE 1 THEN ;
|
||||||
: = CMP NOT ;
|
: = CMP NOT ;
|
||||||
: < CMP 0 1 - = ;
|
: < CMP 0 1 - = ;
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
; A dictionary entry has this structure:
|
; A dictionary entry has this structure:
|
||||||
; - 7b name (zero-padded)
|
; - 7b name (zero-padded)
|
||||||
; - 1b flags (bit 0: IMMEDIATE)
|
|
||||||
; - 2b prev pointer
|
; - 2b prev pointer
|
||||||
|
; - 1b flags (bit 0: IMMEDIATE. bit 1: UNWORD)
|
||||||
; - 2b code pointer
|
; - 2b code pointer
|
||||||
; - Parameter field (PF)
|
; - Parameter field (PF)
|
||||||
;
|
;
|
||||||
@ -9,6 +9,11 @@
|
|||||||
; 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 the top of the Return Stack. They will usually do so with
|
; to the address at the top of the Return Stack. They will usually do so with
|
||||||
; "jp exit".
|
; "jp exit".
|
||||||
|
;
|
||||||
|
; That's for "regular" words (words that are part of the dict chain). There are
|
||||||
|
; also "special words", for example NUMBER, LIT, FBR, that have a slightly
|
||||||
|
; different structure. They're also a pointer to an executable, but as for the
|
||||||
|
; other fields, the only one they have is the "flags" field.
|
||||||
|
|
||||||
; Execute a word containing native code at its PF address (PFA)
|
; Execute a word containing native code at its PF address (PFA)
|
||||||
nativeWord:
|
nativeWord:
|
||||||
@ -51,40 +56,6 @@ doesWord:
|
|||||||
push hl \ pop iy
|
push hl \ pop iy
|
||||||
jr compiledWord
|
jr compiledWord
|
||||||
|
|
||||||
; This word is followed by 1b *relative* offset (to the cell's addr) to where to
|
|
||||||
; branch to. For example, The branching cell of "IF THEN" would contain 3. Add
|
|
||||||
; this value to RS.
|
|
||||||
branchWord:
|
|
||||||
push de
|
|
||||||
ld l, (ix)
|
|
||||||
ld h, (ix+1)
|
|
||||||
ld a, (hl)
|
|
||||||
call addHL
|
|
||||||
ld (ix), l
|
|
||||||
ld (ix+1), h
|
|
||||||
pop de
|
|
||||||
jp exit
|
|
||||||
|
|
||||||
BRANCH:
|
|
||||||
.dw branchWord
|
|
||||||
|
|
||||||
; Conditional branch, only branch if TOS is zero
|
|
||||||
cbranchWord:
|
|
||||||
pop hl
|
|
||||||
ld a, h
|
|
||||||
or l
|
|
||||||
jr z, branchWord
|
|
||||||
; skip next byte in RS
|
|
||||||
ld l, (ix)
|
|
||||||
ld h, (ix+1)
|
|
||||||
inc hl
|
|
||||||
ld (ix), l
|
|
||||||
ld (ix+1), h
|
|
||||||
jp exit
|
|
||||||
|
|
||||||
CBRANCH:
|
|
||||||
.dw cbranchWord
|
|
||||||
|
|
||||||
; This is not a word, but a number literal. This works a bit differently than
|
; This is not a word, but a number literal. This works a bit differently than
|
||||||
; others: PF means nothing and the actual number is placed next to the
|
; others: PF means nothing and the actual number is placed next to the
|
||||||
; numberWord reference in the compiled word list. What we need to do to fetch
|
; numberWord reference in the compiled word list. What we need to do to fetch
|
||||||
@ -102,6 +73,8 @@ numberWord:
|
|||||||
ld (ix+1), h
|
ld (ix+1), h
|
||||||
push de
|
push de
|
||||||
jp exit
|
jp exit
|
||||||
|
|
||||||
|
.db 0b10 ; Flags
|
||||||
NUMBER:
|
NUMBER:
|
||||||
.dw numberWord
|
.dw numberWord
|
||||||
|
|
||||||
@ -119,6 +92,8 @@ litWord:
|
|||||||
jp abort
|
jp abort
|
||||||
.msg:
|
.msg:
|
||||||
.db "undefined word", 0
|
.db "undefined word", 0
|
||||||
|
|
||||||
|
.db 0b10 ; Flags
|
||||||
LIT:
|
LIT:
|
||||||
.dw litWord
|
.dw litWord
|
||||||
|
|
||||||
@ -143,16 +118,18 @@ exit:
|
|||||||
|
|
||||||
; ( R:I -- )
|
; ( R:I -- )
|
||||||
.db "QUIT"
|
.db "QUIT"
|
||||||
.fill 4
|
.fill 3
|
||||||
.dw EXIT
|
.dw EXIT
|
||||||
|
.db 0
|
||||||
QUIT:
|
QUIT:
|
||||||
.dw nativeWord
|
.dw nativeWord
|
||||||
quit:
|
quit:
|
||||||
jp forthRdLine
|
jp forthRdLine
|
||||||
|
|
||||||
.db "ABORT"
|
.db "ABORT"
|
||||||
.fill 3
|
.fill 2
|
||||||
.dw QUIT
|
.dw QUIT
|
||||||
|
.db 0
|
||||||
ABORT:
|
ABORT:
|
||||||
.dw nativeWord
|
.dw nativeWord
|
||||||
abort:
|
abort:
|
||||||
@ -163,8 +140,9 @@ ABORTREF:
|
|||||||
.dw ABORT
|
.dw ABORT
|
||||||
|
|
||||||
.db "BYE"
|
.db "BYE"
|
||||||
.fill 5
|
.fill 4
|
||||||
.dw ABORT
|
.dw ABORT
|
||||||
|
.db 0
|
||||||
BYE:
|
BYE:
|
||||||
.dw nativeWord
|
.dw nativeWord
|
||||||
; Goodbye Forth! Before we go, let's restore the stack
|
; Goodbye Forth! Before we go, let's restore the stack
|
||||||
@ -177,8 +155,9 @@ BYE:
|
|||||||
|
|
||||||
; ( c -- )
|
; ( c -- )
|
||||||
.db "EMIT"
|
.db "EMIT"
|
||||||
.fill 4
|
.fill 3
|
||||||
.dw BYE
|
.dw BYE
|
||||||
|
.db 0
|
||||||
EMIT:
|
EMIT:
|
||||||
.dw nativeWord
|
.dw nativeWord
|
||||||
pop hl
|
pop hl
|
||||||
@ -188,8 +167,9 @@ EMIT:
|
|||||||
|
|
||||||
; ( c port -- )
|
; ( c port -- )
|
||||||
.db "PC!"
|
.db "PC!"
|
||||||
.fill 5
|
.fill 4
|
||||||
.dw EMIT
|
.dw EMIT
|
||||||
|
.db 0
|
||||||
PSTORE:
|
PSTORE:
|
||||||
.dw nativeWord
|
.dw nativeWord
|
||||||
pop bc
|
pop bc
|
||||||
@ -199,8 +179,9 @@ PSTORE:
|
|||||||
|
|
||||||
; ( port -- c )
|
; ( port -- c )
|
||||||
.db "PC@"
|
.db "PC@"
|
||||||
.fill 5
|
.fill 4
|
||||||
.dw PSTORE
|
.dw PSTORE
|
||||||
|
.db 0
|
||||||
PFETCH:
|
PFETCH:
|
||||||
.dw nativeWord
|
.dw nativeWord
|
||||||
pop bc
|
pop bc
|
||||||
@ -211,8 +192,8 @@ PFETCH:
|
|||||||
|
|
||||||
; ( addr -- )
|
; ( addr -- )
|
||||||
.db "EXECUTE"
|
.db "EXECUTE"
|
||||||
.db 0
|
|
||||||
.dw PFETCH
|
.dw PFETCH
|
||||||
|
.db 0
|
||||||
EXECUTE:
|
EXECUTE:
|
||||||
.dw nativeWord
|
.dw nativeWord
|
||||||
pop iy ; is a wordref
|
pop iy ; is a wordref
|
||||||
@ -226,8 +207,9 @@ executeCodeLink:
|
|||||||
jp (hl) ; go!
|
jp (hl) ; go!
|
||||||
|
|
||||||
.db ":"
|
.db ":"
|
||||||
.fill 7
|
.fill 6
|
||||||
.dw EXECUTE
|
.dw EXECUTE
|
||||||
|
.db 0
|
||||||
DEFINE:
|
DEFINE:
|
||||||
.dw nativeWord
|
.dw nativeWord
|
||||||
call entryhead
|
call entryhead
|
||||||
@ -273,8 +255,9 @@ DEFINE:
|
|||||||
|
|
||||||
|
|
||||||
.db "DOES>"
|
.db "DOES>"
|
||||||
.fill 3
|
.fill 2
|
||||||
.dw DEFINE
|
.dw DEFINE
|
||||||
|
.db 0
|
||||||
DOES:
|
DOES:
|
||||||
.dw nativeWord
|
.dw nativeWord
|
||||||
; We run this when we're in an entry creation context. Many things we
|
; We run this when we're in an entry creation context. Many things we
|
||||||
@ -296,35 +279,77 @@ DOES:
|
|||||||
|
|
||||||
|
|
||||||
.db "IMMEDIA"
|
.db "IMMEDIA"
|
||||||
.db 0
|
|
||||||
.dw DOES
|
.dw DOES
|
||||||
|
.db 0
|
||||||
IMMEDIATE:
|
IMMEDIATE:
|
||||||
.dw nativeWord
|
.dw nativeWord
|
||||||
ld hl, (CURRENT)
|
ld hl, (CURRENT)
|
||||||
dec hl
|
dec hl
|
||||||
dec hl
|
set FLAG_IMMED, (hl)
|
||||||
dec hl
|
|
||||||
inc (hl)
|
|
||||||
jp exit
|
jp exit
|
||||||
|
|
||||||
; ( n -- )
|
; ( n -- )
|
||||||
.db "LITERAL"
|
.db "LITERAL"
|
||||||
.db 1 ; IMMEDIATE
|
|
||||||
.dw IMMEDIATE
|
.dw IMMEDIATE
|
||||||
|
.db 1 ; IMMEDIATE
|
||||||
LITERAL:
|
LITERAL:
|
||||||
.dw nativeWord
|
.dw nativeWord
|
||||||
ld hl, (CMPDST)
|
ld hl, (HERE)
|
||||||
ld de, NUMBER
|
ld de, NUMBER
|
||||||
call DEinHL
|
call DEinHL
|
||||||
pop de ; number from stack
|
pop de ; number from stack
|
||||||
call DEinHL
|
call DEinHL
|
||||||
ld (CMPDST), hl
|
ld (HERE), hl
|
||||||
jp exit
|
jp exit
|
||||||
|
|
||||||
|
|
||||||
|
.db "'"
|
||||||
|
.fill 6
|
||||||
|
.dw LITERAL
|
||||||
|
.db 0
|
||||||
|
APOS:
|
||||||
|
.dw nativeWord
|
||||||
|
call readLITBOS
|
||||||
|
call find
|
||||||
|
jr nz, .notfound
|
||||||
|
push de
|
||||||
|
jp exit
|
||||||
|
.notfound:
|
||||||
|
ld hl, .msg
|
||||||
|
call printstr
|
||||||
|
jp abort
|
||||||
|
.msg:
|
||||||
|
.db "word not found", 0
|
||||||
|
|
||||||
|
.db "[']"
|
||||||
|
.fill 4
|
||||||
|
.dw APOS
|
||||||
|
.db 0b01 ; IMMEDIATE
|
||||||
|
APOSI:
|
||||||
|
.dw nativeWord
|
||||||
|
call readword
|
||||||
|
call find
|
||||||
|
jr nz, .notfound
|
||||||
|
ld hl, (HERE)
|
||||||
|
push de ; --> lvl 1
|
||||||
|
ld de, NUMBER
|
||||||
|
call DEinHL
|
||||||
|
pop de ; <-- lvl 1
|
||||||
|
call DEinHL
|
||||||
|
ld (HERE), hl
|
||||||
|
jp exit
|
||||||
|
.notfound:
|
||||||
|
ld hl, .msg
|
||||||
|
call printstr
|
||||||
|
jp abort
|
||||||
|
.msg:
|
||||||
|
.db "word not found", 0
|
||||||
|
|
||||||
; ( -- c )
|
; ( -- c )
|
||||||
.db "KEY"
|
.db "KEY"
|
||||||
.fill 5
|
.fill 4
|
||||||
.dw LITERAL
|
.dw APOSI
|
||||||
|
.db 0
|
||||||
KEY:
|
KEY:
|
||||||
.dw nativeWord
|
.dw nativeWord
|
||||||
call stdioGetC
|
call stdioGetC
|
||||||
@ -334,8 +359,9 @@ KEY:
|
|||||||
jp exit
|
jp exit
|
||||||
|
|
||||||
.db "CREATE"
|
.db "CREATE"
|
||||||
.fill 2
|
.fill 1
|
||||||
.dw KEY
|
.dw KEY
|
||||||
|
.db 0
|
||||||
CREATE:
|
CREATE:
|
||||||
.dw nativeWord
|
.dw nativeWord
|
||||||
call entryhead
|
call entryhead
|
||||||
@ -349,23 +375,25 @@ CREATE:
|
|||||||
jp exit
|
jp exit
|
||||||
|
|
||||||
.db "HERE"
|
.db "HERE"
|
||||||
.fill 4
|
.fill 3
|
||||||
.dw CREATE
|
.dw CREATE
|
||||||
|
.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"
|
||||||
.db 0
|
|
||||||
.dw HERE_
|
.dw HERE_
|
||||||
|
.db 0
|
||||||
CURRENT_:
|
CURRENT_:
|
||||||
.dw sysvarWord
|
.dw sysvarWord
|
||||||
.dw CURRENT
|
.dw CURRENT
|
||||||
|
|
||||||
; ( n -- )
|
; ( n -- )
|
||||||
.db "."
|
.db "."
|
||||||
.fill 7
|
.fill 6
|
||||||
.dw CURRENT_
|
.dw CURRENT_
|
||||||
|
.db 0
|
||||||
DOT:
|
DOT:
|
||||||
.dw nativeWord
|
.dw nativeWord
|
||||||
pop de
|
pop de
|
||||||
@ -379,8 +407,9 @@ DOT:
|
|||||||
|
|
||||||
; ( n a -- )
|
; ( n a -- )
|
||||||
.db "!"
|
.db "!"
|
||||||
.fill 7
|
.fill 6
|
||||||
.dw DOT
|
.dw DOT
|
||||||
|
.db 0
|
||||||
STORE:
|
STORE:
|
||||||
.dw nativeWord
|
.dw nativeWord
|
||||||
pop iy
|
pop iy
|
||||||
@ -391,8 +420,9 @@ STORE:
|
|||||||
|
|
||||||
; ( n a -- )
|
; ( n a -- )
|
||||||
.db "C!"
|
.db "C!"
|
||||||
.fill 6
|
.fill 5
|
||||||
.dw STORE
|
.dw STORE
|
||||||
|
.db 0
|
||||||
CSTORE:
|
CSTORE:
|
||||||
.dw nativeWord
|
.dw nativeWord
|
||||||
pop hl
|
pop hl
|
||||||
@ -402,8 +432,9 @@ CSTORE:
|
|||||||
|
|
||||||
; ( a -- n )
|
; ( a -- n )
|
||||||
.db "@"
|
.db "@"
|
||||||
.fill 7
|
.fill 6
|
||||||
.dw CSTORE
|
.dw CSTORE
|
||||||
|
.db 0
|
||||||
FETCH:
|
FETCH:
|
||||||
.dw nativeWord
|
.dw nativeWord
|
||||||
pop hl
|
pop hl
|
||||||
@ -413,8 +444,9 @@ FETCH:
|
|||||||
|
|
||||||
; ( a -- c )
|
; ( a -- c )
|
||||||
.db "C@"
|
.db "C@"
|
||||||
.fill 6
|
.fill 5
|
||||||
.dw FETCH
|
.dw FETCH
|
||||||
|
.db 0
|
||||||
CFETCH:
|
CFETCH:
|
||||||
.dw nativeWord
|
.dw nativeWord
|
||||||
pop hl
|
pop hl
|
||||||
@ -425,8 +457,9 @@ CFETCH:
|
|||||||
|
|
||||||
; ( -- a )
|
; ( -- a )
|
||||||
.db "LIT@"
|
.db "LIT@"
|
||||||
.fill 4
|
.fill 3
|
||||||
.dw CFETCH
|
.dw CFETCH
|
||||||
|
.db 0
|
||||||
LITFETCH:
|
LITFETCH:
|
||||||
.dw nativeWord
|
.dw nativeWord
|
||||||
call readLITTOS
|
call readLITTOS
|
||||||
@ -435,8 +468,9 @@ LITFETCH:
|
|||||||
|
|
||||||
; ( a b -- b a )
|
; ( a b -- b a )
|
||||||
.db "SWAP"
|
.db "SWAP"
|
||||||
.fill 4
|
.fill 3
|
||||||
.dw LITFETCH
|
.dw LITFETCH
|
||||||
|
.db 0
|
||||||
SWAP:
|
SWAP:
|
||||||
.dw nativeWord
|
.dw nativeWord
|
||||||
pop hl
|
pop hl
|
||||||
@ -446,8 +480,9 @@ SWAP:
|
|||||||
|
|
||||||
; ( a b c d -- c d a b )
|
; ( a b c d -- c d a b )
|
||||||
.db "2SWAP"
|
.db "2SWAP"
|
||||||
.fill 3
|
.fill 2
|
||||||
.dw SWAP
|
.dw SWAP
|
||||||
|
.db 0
|
||||||
SWAP2:
|
SWAP2:
|
||||||
.dw nativeWord
|
.dw nativeWord
|
||||||
pop de ; D
|
pop de ; D
|
||||||
@ -462,8 +497,9 @@ SWAP2:
|
|||||||
|
|
||||||
; ( a -- a a )
|
; ( a -- a a )
|
||||||
.db "DUP"
|
.db "DUP"
|
||||||
.fill 5
|
.fill 4
|
||||||
.dw SWAP2
|
.dw SWAP2
|
||||||
|
.db 0
|
||||||
DUP:
|
DUP:
|
||||||
.dw nativeWord
|
.dw nativeWord
|
||||||
pop hl
|
pop hl
|
||||||
@ -473,8 +509,9 @@ DUP:
|
|||||||
|
|
||||||
; ( a b -- a b a b )
|
; ( a b -- a b a b )
|
||||||
.db "2DUP"
|
.db "2DUP"
|
||||||
.fill 4
|
.fill 3
|
||||||
.dw DUP
|
.dw DUP
|
||||||
|
.db 0
|
||||||
DUP2:
|
DUP2:
|
||||||
.dw nativeWord
|
.dw nativeWord
|
||||||
pop hl ; B
|
pop hl ; B
|
||||||
@ -487,8 +524,9 @@ DUP2:
|
|||||||
|
|
||||||
; ( a b -- a b a )
|
; ( a b -- a b a )
|
||||||
.db "OVER"
|
.db "OVER"
|
||||||
.fill 4
|
.fill 3
|
||||||
.dw DUP2
|
.dw DUP2
|
||||||
|
.db 0
|
||||||
OVER:
|
OVER:
|
||||||
.dw nativeWord
|
.dw nativeWord
|
||||||
pop hl ; B
|
pop hl ; B
|
||||||
@ -500,8 +538,9 @@ 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 3
|
.fill 2
|
||||||
.dw OVER
|
.dw OVER
|
||||||
|
.db 0
|
||||||
OVER2:
|
OVER2:
|
||||||
.dw nativeWord
|
.dw nativeWord
|
||||||
pop hl ; D
|
pop hl ; D
|
||||||
@ -518,8 +557,9 @@ OVER2:
|
|||||||
|
|
||||||
; ( a b -- c ) A + B
|
; ( a b -- c ) A + B
|
||||||
.db "+"
|
.db "+"
|
||||||
.fill 7
|
.fill 6
|
||||||
.dw OVER2
|
.dw OVER2
|
||||||
|
.db 0
|
||||||
PLUS:
|
PLUS:
|
||||||
.dw nativeWord
|
.dw nativeWord
|
||||||
pop hl
|
pop hl
|
||||||
@ -530,8 +570,9 @@ PLUS:
|
|||||||
|
|
||||||
; ( a b -- c ) A - B
|
; ( a b -- c ) A - B
|
||||||
.db "-"
|
.db "-"
|
||||||
.fill 7
|
.fill 6
|
||||||
.dw PLUS
|
.dw PLUS
|
||||||
|
.db 0
|
||||||
MINUS:
|
MINUS:
|
||||||
.dw nativeWord
|
.dw nativeWord
|
||||||
pop de ; B
|
pop de ; B
|
||||||
@ -543,8 +584,9 @@ MINUS:
|
|||||||
|
|
||||||
; ( a b -- c ) A * B
|
; ( a b -- c ) A * B
|
||||||
.db "*"
|
.db "*"
|
||||||
.fill 7
|
.fill 6
|
||||||
.dw MINUS
|
.dw MINUS
|
||||||
|
.db 0
|
||||||
MULT:
|
MULT:
|
||||||
.dw nativeWord
|
.dw nativeWord
|
||||||
pop de
|
pop de
|
||||||
@ -555,8 +597,9 @@ MULT:
|
|||||||
|
|
||||||
; ( a b -- c ) A / B
|
; ( a b -- c ) A / B
|
||||||
.db "/"
|
.db "/"
|
||||||
.fill 7
|
.fill 6
|
||||||
.dw MULT
|
.dw MULT
|
||||||
|
.db 0
|
||||||
DIV:
|
DIV:
|
||||||
.dw nativeWord
|
.dw nativeWord
|
||||||
pop de
|
pop de
|
||||||
@ -567,8 +610,9 @@ DIV:
|
|||||||
|
|
||||||
; ( a1 a2 -- b )
|
; ( a1 a2 -- b )
|
||||||
.db "SCMP"
|
.db "SCMP"
|
||||||
.fill 4
|
.fill 3
|
||||||
.dw DIV
|
.dw DIV
|
||||||
|
.db 0
|
||||||
SCMP:
|
SCMP:
|
||||||
.dw nativeWord
|
.dw nativeWord
|
||||||
pop de
|
pop de
|
||||||
@ -580,8 +624,9 @@ SCMP:
|
|||||||
|
|
||||||
; ( n1 n2 -- f )
|
; ( n1 n2 -- f )
|
||||||
.db "CMP"
|
.db "CMP"
|
||||||
.fill 5
|
.fill 4
|
||||||
.dw SCMP
|
.dw SCMP
|
||||||
|
.db 0
|
||||||
CMP:
|
CMP:
|
||||||
.dw nativeWord
|
.dw nativeWord
|
||||||
pop hl
|
pop hl
|
||||||
@ -592,68 +637,48 @@ CMP:
|
|||||||
push bc
|
push bc
|
||||||
jp exit
|
jp exit
|
||||||
|
|
||||||
.db "IF"
|
; This word's atom is followed by 1b *relative* offset (to the cell's addr) to
|
||||||
.fill 5
|
; where to branch to. For example, The branching cell of "IF THEN" would
|
||||||
.db 1 ; IMMEDIATE
|
; contain 3. Add this value to RS.
|
||||||
.dw CMP
|
.db "(fbr)"
|
||||||
IF:
|
.fill 2
|
||||||
.dw nativeWord
|
.dw CMP
|
||||||
; Spit a conditional branching atom, followed by an empty 1b cell. Then,
|
.db 0
|
||||||
; push the address of that cell on the PS. ELSE or THEN will pick
|
FBR:
|
||||||
; them up and set the offset.
|
.dw nativeWord
|
||||||
ld hl, (CMPDST)
|
push de
|
||||||
ld de, CBRANCH
|
ld l, (ix)
|
||||||
call DEinHL
|
ld h, (ix+1)
|
||||||
push hl ; address of cell to fill
|
ld a, (hl)
|
||||||
inc hl ; empty 1b cell
|
call addHL
|
||||||
ld (CMPDST), hl
|
ld (ix), l
|
||||||
|
ld (ix+1), h
|
||||||
|
pop de
|
||||||
jp exit
|
jp exit
|
||||||
|
|
||||||
.db "ELSE"
|
; Conditional branch, only branch if TOS is zero
|
||||||
.fill 3
|
.db "(fbr?)"
|
||||||
.db 1 ; IMMEDIATE
|
.fill 1
|
||||||
.dw IF
|
.dw FBR
|
||||||
ELSE:
|
.db 0
|
||||||
.dw nativeWord
|
FBRC:
|
||||||
; First, let's set IF's branching cell.
|
.dw nativeWord
|
||||||
pop de ; cell's address
|
pop hl
|
||||||
ld hl, (CMPDST)
|
ld a, h
|
||||||
; also skip ELSE word.
|
or l
|
||||||
inc hl \ inc hl \ inc hl
|
jr z, FBR+2
|
||||||
or a ; clear carry
|
; skip next byte in RS
|
||||||
sbc hl, de ; HL now has relative offset
|
ld l, (ix)
|
||||||
ld a, l
|
ld h, (ix+1)
|
||||||
ld (de), a
|
inc hl
|
||||||
; Set IF's branching cell to current atom address and spit our own
|
ld (ix), l
|
||||||
; uncondition branching cell, which will then be picked up by THEN.
|
ld (ix+1), h
|
||||||
; First, let's spit our 4 bytes
|
|
||||||
ld hl, (CMPDST)
|
|
||||||
ld de, BRANCH
|
|
||||||
call DEinHL
|
|
||||||
push hl ; address of cell to fill
|
|
||||||
inc hl ; empty 1b cell
|
|
||||||
ld (CMPDST), hl
|
|
||||||
jp exit
|
jp exit
|
||||||
|
|
||||||
.db "THEN"
|
|
||||||
.fill 3
|
|
||||||
.db 1 ; IMMEDIATE
|
|
||||||
.dw ELSE
|
|
||||||
THEN:
|
|
||||||
.dw nativeWord
|
|
||||||
; See comments in IF and ELSE
|
|
||||||
pop de ; cell's address
|
|
||||||
ld hl, (CMPDST)
|
|
||||||
; There is nothing to skip because THEN leaves nothing.
|
|
||||||
or a ; clear carry
|
|
||||||
sbc hl, de ; HL now has relative offset
|
|
||||||
ld a, l
|
|
||||||
ld (de), a
|
|
||||||
jp exit
|
|
||||||
|
|
||||||
.db "RECURSE"
|
.db "RECURSE"
|
||||||
|
.dw FBRC
|
||||||
.db 0
|
.db 0
|
||||||
.dw THEN
|
|
||||||
RECURSE:
|
RECURSE:
|
||||||
.dw nativeWord
|
.dw nativeWord
|
||||||
call popRS
|
call popRS
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
Stack notation: "<stack before> -- <stack after>". Rightmost is top of stack
|
Stack notation: "<stack before> -- <stack after>". Rightmost is top of stack
|
||||||
(TOS). For example, in "a b -- c d", b is TOS before, d is TOS after. "R:" means
|
(TOS). For example, in "a b -- c d", b is TOS before, d is TOS after. "R:" means
|
||||||
that the Return Stack is modified.
|
that the Return Stack is modified. "I:" prefix means "IMMEDIATE", that is, that
|
||||||
|
this stack transformation is made at compile time.
|
||||||
|
|
||||||
DOES>: Used inside a colon definition that itself uses CREATE, DOES> transforms
|
DOES>: Used inside a colon definition that itself uses CREATE, DOES> transforms
|
||||||
that newly created word into a "does cell", that is, a regular cell ( when
|
that newly created word into a "does cell", that is, a regular cell ( when
|
||||||
@ -25,27 +26,39 @@ Atom: A word of the type compiledWord contains, in its PF, a list of what we
|
|||||||
call "atoms". Those atoms are most of the time word references, but they can
|
call "atoms". Those atoms are most of the time word references, but they can
|
||||||
also be references to NUMBER and LIT.
|
also be references to NUMBER and LIT.
|
||||||
|
|
||||||
|
Words between "()" are "support words" that aren't really meant to be used
|
||||||
|
directly, but as part of another word.
|
||||||
|
|
||||||
|
"*I*" in description indicates an IMMEDIATE word.
|
||||||
|
|
||||||
*** Defining words ***
|
*** Defining words ***
|
||||||
: x ... -- Define a new word
|
: x ... -- Define a new word
|
||||||
; R:I -- Exit a colon definition
|
; R:I -- Exit a colon definition
|
||||||
|
, n -- Write n in HERE and advance it.
|
||||||
|
' x -- a Push addr of word x to a.
|
||||||
|
['] x -- *I* Like "'", but spits the addr as a number literal.
|
||||||
ALLOT n -- Move HERE by n bytes
|
ALLOT n -- Move HERE by n bytes
|
||||||
|
C, b -- Write byte b in HERE and advance it.
|
||||||
CREATE x -- Create cell named x. Doesn't allocate a PF.
|
CREATE x -- Create cell named x. Doesn't allocate a PF.
|
||||||
CONSTANT x n -- Creates cell x that when called pushes its value
|
CONSTANT x n -- Creates cell x that when called pushes its value
|
||||||
DOES> -- See description at top of file
|
DOES> -- See description at top of file
|
||||||
IMMEDIATE -- Flag the latest defined word as immediate.
|
IMMEDIATE -- Flag the latest defined word as immediate.
|
||||||
LITERAL n -- Inserts number from TOS as a literal
|
LITERAL n -- *I* Inserts number from TOS as a literal
|
||||||
VARIABLE c -- Creates cell x with 2 bytes allocation.
|
VARIABLE c -- Creates cell x with 2 bytes allocation.
|
||||||
|
|
||||||
*** Flow ***
|
*** Flow ***
|
||||||
ELSE -- Branch to THEN
|
(fbr?) f -- Conditionally branches forward by the number
|
||||||
|
specified in its atom's cell.
|
||||||
|
(fbr) -- Branches forward by the number specified in its
|
||||||
|
atom's cell.
|
||||||
|
ELSE I:a -- *I* Compiles a (fbr) and set branching cell at a.
|
||||||
EXECUTE a -- Execute wordref at addr a
|
EXECUTE a -- Execute wordref at addr a
|
||||||
IF n -- Branch to ELSE or THEN if n is zero
|
IF -- I:a *I* Compiles a (fbr?) and pushes its cell's addr
|
||||||
INTERPRET -- Get a line from stdin, compile it in tmp memory,
|
INTERPRET -- Get a line from stdin, compile it in tmp memory,
|
||||||
then execute the compiled contents.
|
then execute the compiled contents.
|
||||||
QUIT R:drop -- Return to interpreter promp immediately
|
QUIT R:drop -- Return to interpreter promp immediately
|
||||||
RECURSE R:I -- R:I-2 Run the current word again.
|
RECURSE R:I -- R:I-2 Run the current word again.
|
||||||
THEN -- Does nothing. Serves as a branching merker for IF
|
THEN I:a -- *I* Set branching cell at a.
|
||||||
and ELSE.
|
|
||||||
|
|
||||||
*** Stack ***
|
*** Stack ***
|
||||||
DUP a -- a a
|
DUP a -- a a
|
||||||
@ -64,11 +77,13 @@ C@ a -- c Set c to byte at address a
|
|||||||
C! c a -- Store byte c in address a
|
C! c a -- Store byte c in address a
|
||||||
CURRENT -- n Set n to wordref of last added entry.
|
CURRENT -- n Set n to wordref of last added entry.
|
||||||
HERE -- a Push HERE's address
|
HERE -- a Push HERE's address
|
||||||
|
H -- a HERE @
|
||||||
|
|
||||||
*** Arithmetic ***
|
*** Arithmetic ***
|
||||||
|
|
||||||
+ a b -- c a + b -> c
|
+ a b -- c a + b -> c
|
||||||
- a b -- c a - b -> c
|
- a b -- c a - b -> c
|
||||||
|
-^ a b -- c b - a -> c
|
||||||
* a b -- c a * b -> c
|
* a b -- c a * b -> c
|
||||||
/ a b -- c a / b -> c
|
/ a b -- c a / b -> c
|
||||||
|
|
||||||
|
@ -8,15 +8,20 @@
|
|||||||
; Offset of the code link relative to the beginning of the word
|
; Offset of the code link relative to the beginning of the word
|
||||||
.equ CODELINK_OFFSET NAMELEN+3
|
.equ CODELINK_OFFSET NAMELEN+3
|
||||||
|
|
||||||
|
; Flags for the "flag field" of the word structure
|
||||||
|
; IMMEDIATE word
|
||||||
|
.equ FLAG_IMMED 0
|
||||||
|
; This wordref is not a regular word (it's not preceeded by a name). It's one
|
||||||
|
; of the NUMBER, LIT, BRANCH etc. entities.
|
||||||
|
.equ FLAG_UNWORD 1
|
||||||
|
|
||||||
; *** Variables ***
|
; *** Variables ***
|
||||||
.equ INITIAL_SP FORTH_RAMSTART
|
.equ INITIAL_SP FORTH_RAMSTART
|
||||||
.equ CURRENT @+2
|
.equ CURRENT @+2
|
||||||
.equ HERE @+2
|
.equ HERE @+2
|
||||||
|
.equ OLDHERE @+2
|
||||||
; Pointer to where we currently are in the interpretation of the current line.
|
; Pointer to where we currently are in the interpretation of the current line.
|
||||||
.equ INPUTPOS @+2
|
.equ INPUTPOS @+2
|
||||||
; Pointer to where compiling words should output. During interpret, it's a
|
|
||||||
; moving target in (COMPBUF). During DEFINE, it's (HERE).
|
|
||||||
.equ CMPDST @+2
|
|
||||||
; Buffer where we compile the current input line. Same size as STDIO_BUFSIZE.
|
; Buffer where we compile the current input line. Same size as STDIO_BUFSIZE.
|
||||||
.equ COMPBUF @+2
|
.equ COMPBUF @+2
|
||||||
.equ FORTH_RAMEND @+0x40
|
.equ FORTH_RAMEND @+0x40
|
||||||
@ -31,19 +36,29 @@
|
|||||||
;
|
;
|
||||||
; 1. read single word from line
|
; 1. read single word from line
|
||||||
; 2. compile word to atom
|
; 2. compile word to atom
|
||||||
; 3. execute atom
|
; 3. if immediate, execute atom
|
||||||
; 4. goto 1
|
; 4. goto 1 until we exhaust words
|
||||||
|
; 5. Execute compiled atom list as if it was a regular compiledWord.
|
||||||
;
|
;
|
||||||
; During step 3, it's possible that atom read from input, so INPUTPOS might
|
; Because the Parameter Stack uses SP, we can't just go around calling routines:
|
||||||
; have moved between 3 and 4.
|
|
||||||
;
|
|
||||||
; Because the Parameter Stack uses PS, we can't just go around calling routines:
|
|
||||||
; This messes with the PS. This is why we almost always jump (unless our call
|
; This messes with the PS. This is why we almost always jump (unless our call
|
||||||
; doesn't involve Forth words in any way).
|
; doesn't involve Forth words in any way).
|
||||||
;
|
;
|
||||||
; This presents a challenge for our interpret loop because step 4, "goto 1"
|
; This presents a challenge for our interpret loop because step 4, "goto 1"
|
||||||
; isn't obvious. To be able to do that, we must push a "return routine" to the
|
; isn't obvious. To be able to do that, we must push a "return routine" to the
|
||||||
; Return Stack before step 3.
|
; Return Stack before step 3.
|
||||||
|
;
|
||||||
|
; HERE and IMMEDIATE: When compiling in step 2, we spit compiled atoms in
|
||||||
|
; (HERE) to simplify "," semantic in Forth (spitting, in all cases, is done in
|
||||||
|
; (HERE)). However, suring input line compilation, it isn't like during ":", we
|
||||||
|
; aren't creating a new entry.
|
||||||
|
;
|
||||||
|
; Compiling and executing from (HERE) would be dangerous because an
|
||||||
|
; entry-creation word, during runtime, could end up overwriting the atom list
|
||||||
|
; we're executing. This is why we have this list in COMPBUF.
|
||||||
|
;
|
||||||
|
; During IMMEDIATE mode, (HERE) is temporarily set to COMPBUF, and when we're
|
||||||
|
; done, we restore (HERE) for runtime. This way, everyone is happy.
|
||||||
|
|
||||||
; *** Code ***
|
; *** Code ***
|
||||||
forthMain:
|
forthMain:
|
||||||
@ -71,8 +86,12 @@ forthRdLine:
|
|||||||
call stdioReadLine
|
call stdioReadLine
|
||||||
ld ix, RS_ADDR-2 ; -2 because we inc-before-push
|
ld ix, RS_ADDR-2 ; -2 because we inc-before-push
|
||||||
ld (INPUTPOS), hl
|
ld (INPUTPOS), hl
|
||||||
|
; We're about to compile the line and possibly execute IMMEDIATE words.
|
||||||
|
; Let's save current (HERE) and temporarily set it to COMPBUF.
|
||||||
|
ld hl, (HERE)
|
||||||
|
ld (OLDHERE), hl
|
||||||
ld hl, COMPBUF
|
ld hl, COMPBUF
|
||||||
ld (CMPDST), hl
|
ld (HERE), hl
|
||||||
forthInterpret:
|
forthInterpret:
|
||||||
call readword
|
call readword
|
||||||
jr nz, .execute
|
jr nz, .execute
|
||||||
@ -104,9 +123,9 @@ forthInterpret:
|
|||||||
; called, triggering an abort.
|
; called, triggering an abort.
|
||||||
ld de, LIT
|
ld de, LIT
|
||||||
call .writeDE
|
call .writeDE
|
||||||
ld de, (CMPDST)
|
ld de, (HERE)
|
||||||
call strcpyM
|
call strcpyM
|
||||||
ld (CMPDST), de
|
ld (HERE), de
|
||||||
jr forthInterpret
|
jr forthInterpret
|
||||||
.immed:
|
.immed:
|
||||||
push hl ; --> lvl 1
|
push hl ; --> lvl 1
|
||||||
@ -117,16 +136,19 @@ forthInterpret:
|
|||||||
.execute:
|
.execute:
|
||||||
ld de, QUIT
|
ld de, QUIT
|
||||||
call .writeDE
|
call .writeDE
|
||||||
|
; Compilation done, let's restore (HERE) and execute!
|
||||||
|
ld hl, (OLDHERE)
|
||||||
|
ld (HERE), hl
|
||||||
ld iy, COMPBUF
|
ld iy, COMPBUF
|
||||||
jp compiledWord
|
jp compiledWord
|
||||||
.writeDE:
|
.writeDE:
|
||||||
push hl
|
push hl
|
||||||
ld hl, (CMPDST)
|
ld hl, (HERE)
|
||||||
ld (hl), e
|
ld (hl), e
|
||||||
inc hl
|
inc hl
|
||||||
ld (hl), d
|
ld (hl), d
|
||||||
inc hl
|
inc hl
|
||||||
ld (CMPDST), hl
|
ld (HERE), hl
|
||||||
pop hl
|
pop hl
|
||||||
ret
|
ret
|
||||||
|
|
||||||
|
@ -69,12 +69,12 @@ HLPointsLIT:
|
|||||||
pop de
|
pop de
|
||||||
ret
|
ret
|
||||||
|
|
||||||
HLPointsBRANCH:
|
HLPointsBR:
|
||||||
push de
|
push de
|
||||||
ld de, BRANCH
|
ld de, FBR
|
||||||
call HLPointsDE
|
call HLPointsDE
|
||||||
jr z, .end
|
jr z, .end
|
||||||
ld de, CBRANCH
|
ld de, FBRC
|
||||||
call HLPointsDE
|
call HLPointsDE
|
||||||
.end:
|
.end:
|
||||||
pop de
|
pop de
|
||||||
@ -87,20 +87,13 @@ HLPointsEXIT:
|
|||||||
pop de
|
pop de
|
||||||
ret
|
ret
|
||||||
|
|
||||||
HLPointsQUIT:
|
|
||||||
push de
|
|
||||||
ld de, QUIT
|
|
||||||
call HLPointsDE
|
|
||||||
pop de
|
|
||||||
ret
|
|
||||||
|
|
||||||
; Skip the compword where HL is currently pointing. If it's a regular word,
|
; Skip the compword where HL is currently pointing. If it's a regular word,
|
||||||
; it's easy: we inc by 2. If it's a NUMBER, we inc by 4. If it's a LIT, we skip
|
; it's easy: we inc by 2. If it's a NUMBER, we inc by 4. If it's a LIT, we skip
|
||||||
; to after null-termination.
|
; to after null-termination.
|
||||||
compSkip:
|
compSkip:
|
||||||
call HLPointsNUMBER
|
call HLPointsNUMBER
|
||||||
jr z, .isNum
|
jr z, .isNum
|
||||||
call HLPointsBRANCH
|
call HLPointsBR
|
||||||
jr z, .isBranch
|
jr z, .isBranch
|
||||||
call HLPointsLIT
|
call HLPointsLIT
|
||||||
jr nz, .isWord
|
jr nz, .isWord
|
||||||
@ -176,15 +169,8 @@ readLIT:
|
|||||||
ex de, hl
|
ex de, hl
|
||||||
ret
|
ret
|
||||||
.notLIT:
|
.notLIT:
|
||||||
; Alright, not a literal, but is it a word? If it's not a number, then
|
; Alright, not a literal, but is it a word?
|
||||||
; it's a word.
|
call HLPointsUNWORD
|
||||||
call HLPointsNUMBER
|
|
||||||
jr z, .notWord
|
|
||||||
call HLPointsBRANCH
|
|
||||||
jr z, .notWord
|
|
||||||
call HLPointsEXIT
|
|
||||||
jr z, .notWord
|
|
||||||
call HLPointsQUIT
|
|
||||||
jr z, .notWord
|
jr z, .notWord
|
||||||
; Not a number, then it's a word. Copy word to pad and point to it.
|
; Not a number, then it's a word. Copy word to pad and point to it.
|
||||||
push hl ; --> lvl 1. we need it to set DE later
|
push hl ; --> lvl 1. we need it to set DE later
|
||||||
@ -233,18 +219,6 @@ readLITTOS:
|
|||||||
pop de
|
pop de
|
||||||
ret
|
ret
|
||||||
|
|
||||||
; For DE being a wordref, move DE to the previous wordref.
|
|
||||||
; Z is set if DE point to 0 (no entry). NZ if not.
|
|
||||||
prev:
|
|
||||||
dec de \ dec de ; prev field
|
|
||||||
call intoDE
|
|
||||||
; DE points to prev. Is it zero?
|
|
||||||
xor a
|
|
||||||
or d
|
|
||||||
or e
|
|
||||||
; Z will be set if DE is zero
|
|
||||||
ret
|
|
||||||
|
|
||||||
; Find the entry corresponding to word where (HL) points to and sets DE to
|
; Find the entry corresponding to word where (HL) points to and sets DE to
|
||||||
; point to that entry.
|
; point to that entry.
|
||||||
; Z if found, NZ if not.
|
; Z if found, NZ if not.
|
||||||
@ -264,7 +238,7 @@ 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
|
||||||
call prev
|
call .prev
|
||||||
jr nz, .inner
|
jr nz, .inner
|
||||||
; Z set? end of dict unset Z
|
; Z set? end of dict unset Z
|
||||||
inc a
|
inc a
|
||||||
@ -273,6 +247,18 @@ find:
|
|||||||
pop hl
|
pop hl
|
||||||
ret
|
ret
|
||||||
|
|
||||||
|
; For DE being a wordref, move DE to the previous wordref.
|
||||||
|
; Z is set if DE point to 0 (no entry). NZ if not.
|
||||||
|
.prev:
|
||||||
|
dec de \ dec de \ dec de ; prev field
|
||||||
|
call intoDE
|
||||||
|
; DE points to prev. Is it zero?
|
||||||
|
xor a
|
||||||
|
or d
|
||||||
|
or e
|
||||||
|
; Z will be set if DE is zero
|
||||||
|
ret
|
||||||
|
|
||||||
; Write compiled data from HL into IY, advancing IY at the same time.
|
; Write compiled data from HL into IY, advancing IY at the same time.
|
||||||
wrCompHL:
|
wrCompHL:
|
||||||
ld (iy), l
|
ld (iy), l
|
||||||
@ -291,13 +277,11 @@ entryhead:
|
|||||||
ld de, (CURRENT)
|
ld de, (CURRENT)
|
||||||
ld a, NAMELEN
|
ld a, NAMELEN
|
||||||
call addHL
|
call addHL
|
||||||
xor a ; IMMED
|
call DEinHL
|
||||||
|
; Set word flags: not IMMED, not UNWORD, so it's 0
|
||||||
|
xor a
|
||||||
ld (hl), a
|
ld (hl), a
|
||||||
inc hl
|
inc hl
|
||||||
ld (hl), e
|
|
||||||
inc hl
|
|
||||||
ld (hl), d
|
|
||||||
inc hl
|
|
||||||
ld (CURRENT), hl
|
ld (CURRENT), hl
|
||||||
ld (HERE), hl
|
ld (HERE), hl
|
||||||
xor a ; set Z
|
xor a ; set Z
|
||||||
@ -306,16 +290,10 @@ entryhead:
|
|||||||
; Sets Z if wordref at HL is of the IMMEDIATE type
|
; Sets Z if wordref at HL is of the IMMEDIATE type
|
||||||
HLisIMMED:
|
HLisIMMED:
|
||||||
dec hl
|
dec hl
|
||||||
dec hl
|
bit FLAG_IMMED, (hl)
|
||||||
dec hl
|
inc hl
|
||||||
; We need an invert flag. We want to Z to be set when flag is non-zero.
|
; We need an invert flag. We want to Z to be set when flag is non-zero.
|
||||||
ld a, 1
|
jp toggleZ
|
||||||
and (hl)
|
|
||||||
dec a ; if A was 1, Z is set. Otherwise, Z is unset
|
|
||||||
inc hl
|
|
||||||
inc hl
|
|
||||||
inc hl
|
|
||||||
ret
|
|
||||||
|
|
||||||
; Sets Z if wordref at (HL) is of the IMMEDIATE type
|
; Sets Z if wordref at (HL) is of the IMMEDIATE type
|
||||||
HLPointsIMMED:
|
HLPointsIMMED:
|
||||||
@ -325,6 +303,22 @@ HLPointsIMMED:
|
|||||||
pop hl
|
pop hl
|
||||||
ret
|
ret
|
||||||
|
|
||||||
|
; Sets Z if wordref at HL is of the UNWORD type
|
||||||
|
HLisUNWORD:
|
||||||
|
dec hl
|
||||||
|
bit FLAG_UNWORD, (hl)
|
||||||
|
inc hl
|
||||||
|
; We need an invert flag. We want to Z to be set when flag is non-zero.
|
||||||
|
jp toggleZ
|
||||||
|
|
||||||
|
; Sets Z if wordref at (HL) is of the IMMEDIATE type
|
||||||
|
HLPointsUNWORD:
|
||||||
|
push hl
|
||||||
|
call intoHL
|
||||||
|
call HLisUNWORD
|
||||||
|
pop hl
|
||||||
|
ret
|
||||||
|
|
||||||
; Checks flags Z and C and sets BC to 0 if Z, 1 if C and -1 otherwise
|
; Checks flags Z and C and sets BC to 0 if Z, 1 if C and -1 otherwise
|
||||||
flagsToBC:
|
flagsToBC:
|
||||||
ld bc, 0
|
ld bc, 0
|
||||||
|
@ -105,3 +105,10 @@ strlen:
|
|||||||
dec a
|
dec a
|
||||||
pop bc
|
pop bc
|
||||||
ret
|
ret
|
||||||
|
|
||||||
|
; make Z the opposite of what it is now
|
||||||
|
toggleZ:
|
||||||
|
jp z, unsetZ
|
||||||
|
cp a
|
||||||
|
ret
|
||||||
|
|
||||||
|
@ -24,12 +24,6 @@ subDEFromHL:
|
|||||||
pop af
|
pop af
|
||||||
ret
|
ret
|
||||||
|
|
||||||
; make Z the opposite of what it is now
|
|
||||||
toggleZ:
|
|
||||||
jp z, unsetZ
|
|
||||||
cp a
|
|
||||||
ret
|
|
||||||
|
|
||||||
; Compares strings pointed to by HL and DE up to A count of characters in a
|
; Compares strings pointed to by HL and DE up to A count of characters in a
|
||||||
; case-insensitive manner.
|
; case-insensitive manner.
|
||||||
; If equal, Z is set. If not equal, Z is reset.
|
; If equal, Z is set. If not equal, Z is reset.
|
||||||
|
Loading…
Reference in New Issue
Block a user