Finally go around to making INLINE[ ] work without the need to create a new CODE word.
This version relies on 2 new words. ASM[ ]ASM.
By themselves these words let you insert inline assembly language inside a Forth definition, like you might see in a C compiler.
ASM[ simply compiles the addresses into the Forth list of addresses that make it look like a new CODE word.
(Notice why it's called "indirect threaded code". (ITC) It take 2 addresses to point to a machine language word.)
ASM[ also turns off the compiler!
Fun FACT: The Forth assembler interprets text.
The only compiler is the comma operator which "compiles" a number into memory.
]ASM is a macro that compiles 2 instructions after the inline machine code
R9 is the Forth instruction pointer (IP). We need to advance IP past the machine code that we compiled into the definition
R10 holds the address of the NEXT routine, which is the 3 instruction Forth "inner" interpreter in ITC Forth.
An example of what can be done with it is shown in this COMPARE routine that is written in Forth.
There are long strings of CODE WORDs in this routine that are wasting time between each word
by going through the inner interpreter. When we inline[ ] the words inside the loop we get a 56% speed up.
There is no reason to inline the words outside the loop because the size will increase with little improvement.
: A$ S" THIS IS A LONG STRING FOR COMPARING TO ANOTHER" ;
: B$ S" THIS IS A LONG STRING FOR COMPARING TO ANOTHER TOO" ;
: COMPARE ( addr1 u1 addr2 u2 --- diff )
\ Compare two strings. diff is negative if addr1 u1 is smaller, 0 if it
\ is equal and positive if it is greater than addr2 u2.
ROT 2DUP - >R \ compute U2-U1, push to RSTACK.
>R \ loop counter push to RSTACK
OVER C@ OVER C@ -
IF SWAP C@ SWAP C@ -
2R> 2DROP \ clean Rstack
EXIT \ & get out of this word
CHAR+ SWAP CHAR+ SWAP \ incr. addr2 & addr1
R> 1- DUP >R \ get rstack loop counter, decr, copy, push back
0= UNTIL \ loop until loop counter=0
R> \ get the U2-U1 value
DROP 2DROP R> NEGATE ;
: COMPTEST 100 0 DO A$ B$ COMPARE DROP LOOP ; \ 9.4 seconds
: FCOMPARE ( addr1 u1 addr2 u2 --- diff )
ROT 2DUP - >R MIN DUP
INLINE[ OVER C@ OVER C@ - ]
IF INLINE[ SWAP C@ SWAP C@ - 2R> 2DROP ]
INLINE[ CHAR+ SWAP CHAR+ SWAP R> 1- DUP >R ]
DROP 2DROP R> NEGATE ;
: FCOMPTEST 100 0 DO A$ B$ FCOMPARE DROP LOOP ; \ 6 seconds
In the new version I also removed some the word names and just put the code inside the definition of INLINE[.
This bad form in Forth which favours short definitions, but I wanted to save some space.
TI-99 is not the most generous environment.
New version is in the spoiler for those who are curious.
Edited by TheBF, Thu Nov 30, 2017 5:52 AM.