Sunday, July 5, 2015

Implementing ;CODE in AArch32 Jonesforth

So I got a new Raspberry Pi and me being me got sidetracked playing with a toy Forth implementation, pijFORTHos (https://github.com/organix/pijFORTHos),which is a standalone AArch32 port of Jonesforth (https://rwmj.wordpress.com/2010/08/07/jonesforth-git-repository/), which is/was an IA32-only affair. Of course I've always been amused by the idea of writing a kernel in Forth...so why not? Sadly, I probably won't do much with this...

Anyway. To cut to the chase, pijFORTHos was missing the ;CODE functionality from Jonesforth 47, which let you define native machine words in Forth... i.e. an assembler, basically. A couple of completely empty and useless examples that do nothing (and yet not crash) would look like:
: FOO ;CODE
: BAR $NEXT ;CODE
The later is redundant, since $NEXT is already emitted by ;CODE. The implementation is straighforward.. Although I took the liberty of sticking it into jonesforth.s instead of the Forth prelude, and in the actual commit I'm a bit smarter about defining $NEXT and the actual _NEXT/NEXT bits used by the Forth core itself. You wonder why bother emitting the NEXT bits inline instead of branching, but the later would take up 3 cells as well (ldr, bx and immed for ldr) and also involve a branch. Look at how the $NEXT word is defined. Isn't this crazy? It's an IMMEDIATE word that writes literals, which just happen to be machine code, at HERE, effectively compiling them into the current word definition when used in compiler mode (such as a colon definition).
@
@ $NEXT ( -- ) emits the _NEXT body at HERE, to be used
@ in ;CODE or ;CODE-defined words.
@
defword "$NEXT",F_IMM,ASMNEXT
       .int LIT
        ldr r0, [FIP], #4
       .int COMMA
       .int LIT
        ldr r1, [r0]
       .int COMMA
       .int LIT
        bx r1
       .int COMMA
       .int EXIT
@
@ Finishes a machine code colon definition in Forth, as
@ a really basic assembler.
@
defword ";CODE",F_IMM,SEMICODE
       .int ASMNEXT                      @ end the word with NEXT macro
       .int LATEST, FETCH, DUP           @ LATEST points to the compiled word
       .int HIDDEN                       @ unhide the compiled word
       .int DUP, TDFA, SWAP, TCFA, STORE @ set codeword to data instead of DOCOL
       .int LBRAC                        @ just like ";" exit compile mode
       .int EXIT

No comments:

Post a Comment