GARTHWILSON wrote:
There again it might be a matter of terminology. I would say for example that STC does have a CFA, but its use is limited to compilation, and the compiler uses it to look up the address to put in the operand field of a JSR instruction. (There may be more to it too, for example so it knows that if it's shorter than a threshold you choose, just straightline it rather than putting in the JSR/RTS overhead.)
But there is no code field, so in what sense does it have an address?
"CFA" is not a generic term for Forth, it's a term specific to Forth implemented with indirect threaded code (or some other code done with a similar indirection).
In other words, the address to put into the operand field of a JSR instruction is NOT the address of a field that contains the address of an executable routine. The address to compile for direct threaded cde is NOT the address of a field that contains the address of an executable routine. Both are the addresses of executable routines themselves.
"Compile a list of values that specify which words to execute" is something that every Forth will do. "Compile a list of values that point to the address of a field that contains an address of an executable routine" is something that an Indirect Threaded model Forth will do ...
... after all, that is the INDIRECT in Indirect Threaded: point to something which points to the thing that you execute.
Code:
EXIT: PLX
NEXT: INX
INX
JMP ($0000,X)
ENTER: PHX
STX W
LDA $0000,X
TAX
INX
INX
INX
JMP ($0000,X)
... doesn't USE "an address that points to an address that points to executable code" to do that, it uses an address that points directly to executable code. The trade-off is that a compiled definition has to be prefaced by an executable stub.
Or consider a bit-threaded model where definitions are composed of cells aligned on even addresses, primitives are called with subroutine vectors (so are always odd) and compiled words called with the address of their definition. As well, executable code is all in the range of $8000-$FFFF, so any address in $0000-$7FFF is assumed to be a branch to code in the $8000-$FFFF range, rather than a call.
Code:
NEXT: INY
INY
NEXT1: LDA $0000,Y
BPL BRANCH
BIT #$0001
BEQ ENTER
PHA
RTS
ENTER: PHY
TAY
BRA NEXT1
BRANCH: ORA #$8000
TAY
BRA NEXT1
BigEd wrote:
If I've understood correctly, and I'm not at all expert in this, then I feel perhaps a bit confused by, for example, Garth's statement
Quote:
The CFA of a primitive usually points to...
because it doesn't seem clear if that's the CFA (an address) or the CF itself (a piece of data, which might well be a two byte address.) ...
... is right, here ... for a primitive, the code field
contents points to the parameter field, so for a primitive, the CFA "points to the pointer to," the parameter field". In other words, for fig-Forth primitives, the CFA is not a pointer to the primitive code, it's a handle to the primitive code.
The fig-Forth
word CFA is a shorthand, which in a verbose system could be named PFA>CFA to make clear what it translates from as well as what it translates to -- but I like the fig-Forth version better, perhaps because I started with a version of fig-Forth customized for the C64.