scotws wrote:
The BMI is from the code for underflow checking, which after seing this I'm wondering if should go into a subroutine after all, I hadn't really realized how many times we call that.
BMI? I'm curious, how did you implement underflow checking? My Forth also uses the lower part of zero page for the data stack. It's for a Commodore 64 so the stack can't grow as far down as locations 0 and 1 ( 6510 data direction register and data register built into the cpu ). It is also an ITC Forth.
I only implemented underflow checking in addition to
INTERPRET's stack checking where I could get it with zero overhead. The x-register = hex 7E when the stack is empty.
The code for
2DROP and
DROP checks for underflow just before jumping to
NEXTCode:
SCR# 7
// POPTWO POP
HEX
SUB 2DROP.BODY ( N1 N2 -- )
HERE TIS POPTWO
INX, INX, // 2DROP'S CFA POINTS HERE
HERE TIS POP
INX, INX, // DROP'S CFA POINTS HERE
NEXT 0< NOT BRAN,
80 # LDX,
NEXT JMP, END-CODE
The line with
BRAN, compiles a
BPL to
NEXTIf there is an underflow, set it to underflow by one cell ( 2 bytes ) to protect the Forth virtual machine registers (
XSAVE,
UP,
N scratchpad area etc ) while keeping an underflow condition that will be caught and delt with by
INTERPRET.
(DO) does something similar ( it doesn't jump to
NEXT ).
If you were wondering,
SUB compiles a constant in the host dictionary which points to the target's current free memory location, its version of
HERE in virtual memory ( the C64 REU ), and sets up the metacompiler assembler.