Close

IF .. ELSE .. THEN with Relative Addressing - Changing the Compiler during Compilation

A project log for eForth for cheap STM8S gadgets

Turn cheap modules from AliExpress into interactive development kits!

thomasThomas 11/26/2020 at 06:320 Comments

When implementing a driver for the STM8 I2C peripheral I needed BTJx and JREQ branches in Forth code. This wasn't the first time I did that and I had prepared some code to calculated and fix the relative address at the target "label". When I also needed an ELSE block it struck me that this had been solved before - in IF ... ELSE ... THEN.

Here is the code:

\ STM8eForth : control structures with relative addressing         TG9541-201124
\ ------------------------------------------------------------------------------

#require >Y

: THEN ( -- ) [COMPILE] [ HERE OVER - 1- SWAP C! [COMPILE] ] ; IMMEDIATE

: >REL ( -- ) HERE 0 C, ;  \ like >MARK for rel. branch

: ELSE ( -- )  [COMPILE] [ $20 C, [COMPILE] ] >REL   \ JRA rel
    SWAP [COMPILE] THEN ; IMMEDIATE

: JREQ ( F:Z -- ) [COMPILE] [ $27 C, [COMPILE] ] >REL ; IMMEDIATE

: IF ( n -- ) COMPILE >Y [COMPILE] JREQ ; IMMEDIATE

After loading this redefinition of IF .. ELSE .. THEN to RAM, Forth code can be written just like before. When it's no longer needed the temporary compiler change can be discarded and the code using relative addressing remains valid.

The real difference is that now machine code for branch instructions can be used that work like the library words ]C! or ]B!:

#require >REL

: ]B@IF ( -- ) 2* $7201 + , , ] >REL ;  \ BTJF  a,#bit,rel

: ]@IF  ( -- ) $90CE , , ( LDW Y,a ) ] [COMPILE] JREQ ;

NVM
VARIABLE vt
: testb  [ vt 1 ]B@IF ."  set" ELSE ."  not set" THEN ;
: testNZ [ vt ]@IF ."  not " THEN ."  zero" ;
RAM

The word ]B@IF compiles to "BTJF addr,#bit,rel" and ]@IF compiles to  "LDW Y,#n  JREQ rel".

I plan to add these words and others like ]C@IF (LD A,addr  JREQ rel) or ]A<IF (CP A,#c JRPL rel) to the library that directly load >REL.

Discussions