dclxvi wrote:
GARTHWILSON wrote:
Code:
HEADER "0branch", NOT_IMMEDIATE
0branch: PRIMITIVE
INX2
LDA FFFE,X
BEQ branch+2
.
.
.
By the way, you might want to make that $FFFFFE,X (i.e. long,X addressing) since abs,X will cross bank boundaries, so this will read from bank 1 (assuming the DBR is 0). I am guessing you're using this on a 64k 65C816 which ignores the bank byte.
OMG, I should read old threads more accurate ... trapped into this while porting Garth's Forth to C64 SuperCPU with a real 65816 ...
The long absolute variant went not into my mind ...
I found three places: ?EXIT, ?LEAVE and the mentioned 0BRANCH.
The way I solved this is based on reordering the code. I just used the faster 0,X for the (small, IMHO) cost to duplicate INX_INX. The reuse of code has been reversed. Considering 0BRANCH, BRANCH's CFA points to the branch code of 0BRANCH and in that way it's not a real primitive anymore from structural point of view.
(originally in C32 format, I transcoded the source into a Tass64 format)
Code:
#HEADER "branch", NOT_IMMEDIATE ; ( -- )
branch: .WORD branchcode
;-------------------
#HEADER "0branch", NOT_IMMEDIATE ; ( n -- )
Zbranch: #PRIMITIVE
;
; only on 65802 (64K wrap-around)
; #INX_INX
; LDA $FFFE,X ; Get the value that was at TOS before INX_INX .
; BEQ branchcode ; Do the branch if TOS was 0.
;
; fixed for 65816, no bank wrapping!
LDA 0,X
BEQ dbranch ; Do the branch if TOS was 0.
#INX_INX ; drop and bump
bump: LDA G.IP ; bump (advance) the instruction pointer by two
#INA_INA ; LDA, INA, INA, STA is faster than INC INC.
STA G.IP
#GO_NEXT
dbranch:
#INX_INX ; drop
branchcode: ; Set the G.IP to the absolute addr
LDA (G.IP) ; pointed to by the cell following the
STA G.IP ; execution token of branch. It's faster
#GO_NEXT ; this way not making it relative.
Code:
#HEADER "leave", NOT_IMMEDIATE ; ( -- )
USleave: .WORD USleavecode ; leave is compiled by LEAVE .
;-------------------
#HEADER "?leave", NOT_IMMEDIATE ; ( f -- )
QM_leave: #PRIMITIVE ; QM_leave is compiles by QMLEAVE
;
; only on 65802 (64K wrap-around)
; #INX_INX
; LDA $FFFE,X ; Get the value that was at TOS before INX_INX .
; BNE USleavecode ; If not 0, then do the same as USleave does.
;
; fixed for 65816, no bank wrapping!
LDA 0,X
BNE doleave ; If not 0, then do the same as USleave does.
#INX_INX ; drop TOS
#GO_NEXT
doleave:
#INX_INX ; drop TOS
USleavecode:
.AL
LDA #$FFFF
STA LOOP_LEAVEdata ; Show that LEAVE was taken,
BRA lv_lp ; then end the same way as when a loop finishes.
Code:
#HEADER "?EXIT", NOT_IMMEDIATE ; ( f -- ) IF R> DROP THEN
QMEXIT: #PRIMITIVE
;
; only on 65802 (64K wrap-around)
; #INX_INX
; LDA $FFFE,X ; Get the value that was at TOS before INX_INX .
; BNE unnestcode ; If not 0, then do the same as unnest does.
;
; fixed for 65816, no bank wrapping!
LDA 0,X
BEQ doexit
#INX_INX ; Drop
#GO_NEXT
doexit:
#INX_INX ; Drop
unnestcode:
PLA ; nest, and the same as EXIT.
STA G.IP ; It is often called SEMIS
#GO_NEXT ; because it's compiled by ;
Johann