To follow up with Bruce's NEXT in ZP and the importance of a quick DROP, I actually put DROP right in front of NEXT in ZP. Since I use a split stack, this consists of 'INX'.
Talk about a coincidence, I just organized by DROP in a similar way yesterday afternoon ... my NEXT is in the dictionary except when it calls the single indirect jump in zero page, but DROP is the first header and the DROP primitive is just the INX before the NEXT code.
____________
My
UM/MOD takes a couple hundred cycles more worst case because of all the indexing but is quite small and transforms everything in-place instead of needing any additional "workspace". Did someone mention something about tradeoffs?
[My browser's grammar checker thinks I try to use too many commas, so I've been heeding its advice. Should I?]
One of the things I did Saturday afternoon was to copy your UM/MOD and convert it to my assembly terms ... and I don't recall off the top of my head, but is the UM* written in a similar style yours as well? ... to knock off the code multiple/divide in the Z80 Camel Forth port.
I think the broken version of xForth that I have sitting on a hard drive waiting to be attached to a working computer used the non-indexed version, which of course meant more copying of operands from the stack to my W and V vectors and N space, but for the target for this time around, working mostly on the stack to avoid the code footprint of moving all that stuff off the stack and back again. I did copy the divisor to my V zp vector, since it wouldn't have to be copied back, but I left the dividend->quotient on the stack.
One of the very slightly ungainly aspects of the "mongrel" split stack is that STY a,X doesn't exist, so the high byte part of SWAP is not 4 clocks more than a pure ZP split stack, but 6 clocks:
Code: Select all
SWAP:
LDA DL,X
LDY DL+1,X
STA DL+1,X
STY DL,X
LDA DH,X
LDY DH+1,X
STA DH+1,X
TYA
STA DH,X
JMP NEXT
But, again, since I'm not sweating an extra clock here or there in this implementation, it's not "nail on a chalkboard" irritating.
I also try to save a modest amount space (compared to my space spendthrift habits) by refraining from coding ROT and -ROT, but instead to code the shorter FLIP ( u1 u2 u3 -- u3 u2 u1 ) so that ROT and -ROT are:
Code: Select all
: ROT ( x1 x2 x3 -- x2 x3 x1 ) SWAP FLIP ;
: -ROT ( x1 x2 x3 -- x3 x1 x2 ) FLIP SWAP ;