Write and read to target memory
published: 13 April 2021 / updated 14 April 2021
Preamble
We are fortunate to use gForth, a version of the FORTH language available under Windows, Linux and even ANDROID. gForth has the following advantages that we are interested in metacompilation:
- 32-bit addressable memory
- 64-bit integers
- vocabulary management
gForth therefore offers sufficient workspace to allow the generation of targets of significant size.
Definition of target memory space
For our generation of ARDUINO code, we will reserve a memory space of 32 kilobytes:
forth definitions
1024 constant PAGE-SIZE
\ allot n pages in memory
create META-TARGET
PAGE-SIZE 32 * allot
META-TARGET
is our target memory space. We must now graft this space
memory to the metacompiler. We compile the metacompiler, then we assign to ADR-T
defined
in the META vocabulary the address of our metacompilation workspace:
meta META-TARGET ADR-T !
File access meta.txt.
Compilation direction of 16-bit words
gForth uses the words c @ c! @!
to access the content of variables and
memory space. If c @ c!
handles 8-bit data perfectly, it doesn't.
words @!
which deal with 64-bit data! Our meta-compiler will need to take
specifically supports 8 and 16 bit data processing.
Entering a 16-bit word into memory is specific to each type of target processor. It exists two models for recording 16-bit words:
- the LITTLE-ENDIAN model. The least significant byte of the 16-bit word is saved first;
- the BIG-ENDIAN model. The most significant byte of the 16-bit word is recorded first.
In FORTH the execution on ARDUINO of a sequence $ 1234 i,
gives this:
flash create TEST $1234 i, ok<#,flash> TEST $10 dump 800e :34 12 02 80 83 2d 61 73 0e 94 8d 7b 1c 80 00 00 4....-as...{.... ok<$,ram>
As we can see on the line for restoring the code in memory, we see the sequence 800e :34 12 ... which demonstrates that memory management on an ARDUINO card conforms to the LITTLE-ENDIAN model.
To manage a model without worry in meta-compilation, we define:
true value LITTLE-ENDIAN
: byte-invert ( w -- w')
LITTLE-ENDIAN invert if
$100 /mod
swap $100 * +
then
;
The word byte-invert
inverts the pair of bytes in a 16-bit word at destination
target memory that is not LITTLE-ENDIAN model. For AVR processors, select
the LITTLE-ENDIAN model.
The word byte-invert
is used by our metacompiler.
File access forthExtend.txt.
Management of target memory space
In the meta.txt file, we start by defining two variables allowing access to the target memory space:
\ Memory access variables in the target variable ADR-T \ memorize target address; ADRment-Target variable DP-T \ and Target offset; Dict.Pointer-Target \ convert target-addr in physical-address : taddr-calc ( taddr -- phys-addr) ADR-T @ + ;
The ADR-T
variable stores the target memory address (see above).
The DP-T
variable is our dictionary pointer to this target memory.
The word taddr-calc
transforms a relative pointing address in memory
target in physical address exploitable by gForth.
Reading target memory
The words c@-t
and @-t
allow reading of 8 and 16 bit values
in the target memory pointed to by taddr.
\ get a byte in the target : c@-t ( taddr -- c ) taddr-calc c@ ; \ get a 16-bit word from the target : @-t ( taddr -- w ) dup 1+ c@-t $100 * swap c@-t + byte-invert ;
taddr is a value between 0 and the maximum value of the size of the target memory space.
Write to target memory
The words c!-t
and !-t
allow the writing of 8 and 16 bit values
in the target memory pointed to by taddr.
\ store a byte in the target : c!-t ( char taddr -- ) taddr-calc c! ; \ store a 16-bit word in the target : !-t { word taddr -- } \ CAUTION: local variables word byte-invert $100 /mod swap taddr c!-t taddr 1+ c!-t ;
WARNING the definition of the word !-t
uses locals variables
in order to make the code more readable.
Pointing and allocation in target memory
The words here-t
and allot-t
handle dictionary pointers in the
target.
\ target dictionary pointer stacks : here-t ( -- taddr ) DP-T @ ; \ allocate n bytes in the target : allot-t ( n -- ) DP-T +! ;
Their operation is similar to the words here
and allot
for
FORTH dictionary.
Injecting data into target memory
These words are used to inject bytes, 16-bit values and character strings.
\ compile a byte in the target : c,-t ( char -- ) here-t c!-t 1 allot-t ; \ compile a 16-bit word into the target : ,-t ( w -- ) here-t !-t 2 allot-t ; \ compile a string in the target : string,-t ( addr len -- ) 0 ?do count c,-t loop drop ;
The words c,-t
and ,-t
work as their
equivalent c, ,
of FORTH vocabulary.
The word string,-t
compiles a string in space
target memory. Examples:
$5678 0 !-t ok META-TARGET $20 dump 7FC1E6B1BB90: 78 56 00 00 00 00 00 00 - 00 00 00 00 00 00 00 00 .V.............. 7FC1E6B1BBA0: 00 00 00 00 00 00 00 00 - 00 00 00 00 00 00 00 00 ................ $2345 ,-t ok META-TARGET $20 dump 7FC1E6B1BB90: 45 23 00 00 00 00 00 00 - 00 00 00 00 00 00 00 00 E#.............. 7FC1E6B1BBA0: 00 00 00 00 00 00 00 00 - 00 00 00 00 00 00 00 00 ................ s" MENU GENERAL" string,-t ok META-TARGET $20 dump 7FC1E6B1BB90: 45 23 4D 45 4E 55 20 47 - 45 4E 45 52 41 4C 00 00 E#MENU GENERAL.. 7FC1E6B1BBA0: 00 00 00 00 00 00 00 00 - 00 00 00 00 00 00 00 00 ................
At this point, I hope you are beginning to sense the interest of the
metacompilation. If you go back to the Xassembleur code, you will have noticed
that the words c,
and ,
in the Xassembler vocabulary are
execution word defined by DEFER
. So we can change their behavior.
If we have compiled the contents of meta.txt and Xassembler.txt, we can do our first test of AVR code metacompilation with gForth:
meta ' c,-t Xassembler is c,
meta ' ,-t Xassembler is ,
meta 0 DP-T ! \ reset DP-T
Xassembler
r16 constant t0
r17 constant t1
r24 constant tosl
r25 constant tosh
: plus
[ t0 Y+ ld, ]
[ t1 Y+ ld, ]
[ tosl t0 add, ]
[ tosh t1 adc, ]
[ ret, ]
;
We can find in the dump of META-TARGET
the generated binary code
by our very first metacompilation test:
META-TARGET $20 dump 7FC1E6B1BB90: 09 91 19 91 80 0F 91 1F - 08 95 00 00 00 00 00 00 ................ 7FC1E6B1BBA0: 00 00 00 00 00 00 00 00 - 00 00 00 00 00 00 00 00 ................
There are still many steps to take before having a metacompiler fully operational. This will be the subject of future articles ...