GARTHWILSON wrote:
Even then, there's probably a lot that could be improved on the C64 Forth. The 6502 Forth I started with (I imagine they had common roots, maybe from Ragsdale), before I heavily modified it, had for example,
Code:
: DEPTH SP@ S0 @ SWAP - 2 / ;
Besides the fact that it would have taken less memory as a primitive something like this,
Code:
CODE DEPTH
STX N ; Put stack pointer in N.
LDA #S0adr ; Get the address of the 1st byte under the stack.
SEC
SBC N ; Subtract the data stack pointer value (X above).
LSR A ; Divide by 2, to get from number of bytes on stack
JMP CPUSH ; to number of cells.
END-CODE
;-------------------
they even used 2 / instead of 2/ , making it at least dozens of times as slow!
I imagine there's a lot that could be dramatically improved in the C64 Forth if someone wanted to get serious about it.
There's the rub. Different Forths for the 65XX with the same threading could have vastly different speeds depending on the ratio of primitives ( and which words are primitives ) in each kernel. Which words should be primitive? How do you strike a balance between compact size and speed of a Forth system?
I have some rules of thumb about what should be defined as a primitive. In my Forth I've defined the data stack operators and the math operators as primitives. Anything that is the same size or smaller as a primitive gets defined as a primitive.
S>D is the same size so it is defined as a primitive. If a pair of words have a combined size that is smaller as primitives ( possibly because they complement each other ) , they are defined as primitives.
[ and
] are an example of this. High level versions in my Forth are:
Code:
: ] ( -- ) STATE ON ;
: [ ( -- ) STATE OFF ; IMMEDIATE
The bodies are six bytes each for a total of twelve. The primitive versions are:
Code:
HEX
CODE ]
DEY,
STATE STY,
STATE 1+ STY,
NEXT JMP,
END-CODE
CODE [ IMMEDIATE
-2 ALLOT
' ] @ 1+ ,
END-CODE
The body of
] is ten bytes and the body of
[ is zero bytes for a net savings of two bytes.
Sometimes a high level word is simple and small but slow. Rewriting one of the words it uses as a primitive can result in the word being fast enough yet smaller than a version rewritten to be faster without resorting to redefining a component word as a primitive.
>BT ( to buffer table ) in my Forth is a word to access the
Nth entry in the block buffer table. The primitive is larger, yet helps the high level parts of
BLOCK and
BUFFER to be fast enough without convoluted ( at least not too badly convoluted ) high level code that would make them bigger.