When I started extending Dr. C.H. Ting's STM8EF with board support (e.g. the venerable W1209) I wrote low level HW abstractions in assembly code, taking full advantage of the STM8 instruction set (e.g. bit set/reset operations, memory-to-memory moves).
I takes a while until one understands that in Forth a lot more is possible than in traditional interpreting (BASIC) or compiling (C) language approaches. It's easy to write compiler extensions in Forth, very easy in fact!
Here is an example:
The BSET/BRES instructions have the following opcode/adressing structure:
72 1n MSB LSB BSET: n: 2*b BRES: n: 2*b+1
Bit adressing is very for working with µC peripherals (in most cases read-modify-write can be used, too, but changing individual bit that takes more memory, and more cycles).
One of the first things I added to STM8EF last year was the B! instruction, that builds a BSET or a BRES instruction on the stack, and runs it. This takes a lot of cycles, but it allows using bit instructions with non-immediate addressing.
Now, sometimes just immediate addressing is required, and storing bit value, address, and bit position is all but a waste of memory!
: PC_ODR $500A ; : PC5set 1 PC_ODR 5 B! ;
The solution is compiling BSET/BRES instructions directly into the execution code, just like an optimizing C compiler would do it:
\ STM8S assembly words \ (c) TG9541, refer to license at github.com/TG9541/stm8ef : bit! ( b a c -- ) rot 0= 1 and swap 2* $10 + + $72 c, c, , ; immediate : bres ( a c -- ) [ 0 ] [compile] bit! ; immediate : bset ( a c -- ) [ 1 ] [compile] bit! ; immediate
The PC5set example above now looks like this:
: PC5set [ PC_ODR 5 ] bset ; ' PC5set 10 dump F9 72 1A 50 A 81 65 1 4 64 75 6D 70 65 74 0 0 r_P__e__dumpet__ ok
As the dump shows, this definition compiles to the assembly instruction BSET PC_ODR,#5.
Using the new library features in the upcoming STM8EF v2.2.13.snapshot the above "inline assembler" words can be loaded into RAM, and the words bit!, bres, bset take up no space in the Flash ROM.