2020-03-08 04:13:15 +11:00
|
|
|
; The Parameter stack (PS) is maintained by SP and the Return stack (RS) is
|
|
|
|
; maintained by IX. This allows us to generally use push and pop freely because
|
|
|
|
; PS is the most frequently used. However, this causes a problem with routine
|
|
|
|
; calls: because in Forth, the stack isn't balanced within each call, our return
|
|
|
|
; offset, when placed by a CALL, messes everything up. This is one of the
|
2020-03-09 23:49:51 +11:00
|
|
|
; reasons why we need stack management routines below. IX always points to RS'
|
|
|
|
; Top Of Stack (TOS)
|
2020-03-08 04:13:15 +11:00
|
|
|
;
|
|
|
|
; This return stack contain "Interpreter pointers", that is a pointer to the
|
|
|
|
; address of a word, as seen in a compiled list of words.
|
|
|
|
|
|
|
|
; Push value HL to RS
|
|
|
|
pushRS:
|
|
|
|
inc ix
|
|
|
|
inc ix
|
2020-03-09 23:49:51 +11:00
|
|
|
ld (ix), l
|
|
|
|
ld (ix+1), h
|
2020-03-08 04:13:15 +11:00
|
|
|
ret
|
|
|
|
|
|
|
|
; Pop RS' TOS to HL
|
|
|
|
popRS:
|
2020-03-09 23:49:51 +11:00
|
|
|
ld l, (ix)
|
|
|
|
ld h, (ix+1)
|
2020-03-08 04:13:15 +11:00
|
|
|
dec ix
|
|
|
|
dec ix
|
|
|
|
ret
|
2020-03-08 12:20:11 +11:00
|
|
|
|
2020-03-11 12:37:06 +11:00
|
|
|
; Skip the next two bytes in RS' TOS
|
|
|
|
skipRS:
|
|
|
|
push hl
|
|
|
|
ld l, (ix)
|
|
|
|
ld h, (ix+1)
|
|
|
|
inc hl \ inc hl
|
|
|
|
ld (ix), l
|
|
|
|
ld (ix+1), h
|
|
|
|
pop hl
|
|
|
|
ret
|
|
|
|
|
2020-03-08 12:20:11 +11:00
|
|
|
; Verifies that SP is within bounds. If it's not, call ABORT
|
|
|
|
chkPS:
|
|
|
|
ld hl, (INITIAL_SP)
|
|
|
|
; We have the return address for this very call on the stack. Let's
|
|
|
|
; compensate
|
|
|
|
dec hl \ dec hl
|
|
|
|
or a ; clear carry
|
|
|
|
sbc hl, sp
|
|
|
|
ret nc ; (INITIAL_SP) >= SP? good
|
|
|
|
; underflow
|
|
|
|
ld hl, .msg
|
|
|
|
call printstr
|
2020-03-08 14:18:14 +11:00
|
|
|
jp abort
|
2020-03-08 12:20:11 +11:00
|
|
|
.msg:
|
|
|
|
.db "stack underflow", 0
|