Devlog 8 Reviewing Primitives Again
November 24, 2022
Reviewing primitives again
Continuing from the last session, I’ll look at the primitives and see what needs to be adjusted.
Log 8
In this session, I want to fix the remaining # OK primitives.
Simple fixes
We’ll begin by looking at ZEQU:
# 0= ( x -- f ) 1 if top of stack is 0, 0 otherwise
defcode "0=", 0x025970b2, ZEQU, RSPFETCH
seqz s3, s3 # store 1 in TOS if TOS is equal to 0, otherwise store 0
NEXT
This is a very short primitive because it only works on the TOS register. RISC-V’s pseudo-instruction seqz is very useful in this case for checking if the TOS is equal to zero. Next, we’ll look at the ADD primitive, which takes the TOS and top of the DSP, moves the DSP pointer up by 1 cell and stores the result in the TOS.
# + ( x1 x2 -- n ) Add the two values at the top of the stack
defcode "+", 0x0102b5d0, ADD, ZEQU
addi sp, sp, CELL # move the DSP up by 1 cell
lw t0, -CELL(sp) # load value to temporary
add s3, s3, t0 # add values and store in TOS
NEXT
Part of the above operation looks very similar to a POP, so we’ll move that to a macro:
# pop top of stack to register
.macro POP reg
addi sp, sp, CELL # move the DSP up by 1 cell
lw \reg, -CELL(sp) # load DSP value to temporary
.endm
# + ( x1 x2 -- n ) Add the two values at the top of the stack
defcode "+", 0x0102b5d0, ADD, ZEQU
POP t0 # pop value into temporary
add s3, s3, t0 # add values and store in TOS
NEXT
The following primitive, bitwise NAND, built from RISC-V’s and and not instructions (similar to & and ~ in C).
This is simplified below:
# nand ( x1 x2 -- n ) bitwise NAND the two values at the top of the stack
defcode "nand", 0x049b0c66, NAND, ADD
POP t0 # pop value into temporary
and s3, s3, t0 # store bitwise AND of temporary and TOS into TOS
not s3, s3 # store bitwise NOT of TOS into TOS
NEXT
Finally, the EXIT primitive restores the address at the top of the return stack into the instruction pointer IP:
# exit ( r:addr -- ) Resume execution at address at the top of the return stack
defcode "exit", 0x04967e3f, EXIT, NAND
POPRSP s1 # pop RSP into IP
NEXT
Reviewing variables
The 5 variables TIB STATE TOIN HERE LATEST are almost identical, where we simply want move the current TOS to the top of the DSP, and then load the address stored in the variable to the TOS. That’s basically a PUSH operation so we’ll define a new macro PUSHVAR for that:
# push variable to top of stack
.macro PUSHVAR var
sw s3, -CELL(sp) # store the value in the TOS to the top of the DSP
li t0, \var # load variable into temporary
lw s3, 0(t0) # load variable address value into TOS
addi sp, sp, -CELL # move the DSP down by 1 cell
.endm
Our new tib variable looks like this:
defcode "tib", 0x0388ae44, TIB, EMIT
PUSHVAR TIB # store TIB variable value in TOS
NEXT
Not bad! Now we can do the same for the other variables.
Closing Thoughts
It was nice to restore the macro for POP. That completes the review of primitive words and variables. Next I’ll be able to tackle COLON and SEMI.. and whatever else is missing haha.