Definition of macro instructions
published: 11 April 2021 / updated 11 April 2021
FlashForth's assembly listing uses a macros.inc file. The content of we are interested in this file, because it contains definitions of necessary macro instructions to rewrite the FORTH kernel for Atmega.
In this article, we will see how to rewrite the code of the macros.inc file in a new macros.txt file.
Code rewrite of macros.inc
We are not going to explain the whole rewrite of the assembly code of macros.inc in its entirety, but only give here the outline of this rewrite.
To begin with, we make a copy of the macros.inc file and rename macros.txt
Using the editor, we start by transforming all the characters ; into \. Before:
; Register definitions .def upl = r2 ; not in interrupt .def uph = r3 ; not in interrupt .def r_zero = r5 ; read only zero .def r_one = r6 ; read only one .def r_two = r7 ; read only two .def t8 = r8 ; Not in interrupt .def wflags = r9 ; not in interrupt
After:
\ Register definitions .def upl = r2 \ not in interrupt .def uph = r3 \ not in interrupt .def r_zero = r5 \ read only zero .def r_one = r6 \ read only one .def r_two = r7 \ read only two .def t8 = r8 \ Not in interrupt .def wflags = r9 \ not in interrupt
Rewrite in Xassembler compatible syntax
In a previous article, Extending Xassembler with directives, we have seen the creation of assembly directives that complement the FlashForth assembler.
These directives rewritten in FORTH language have their own syntax which differs from that of their equivalent in assembler. Our code before rewriting:
\ Register definitions .def upl = r2 \ not in interrupt .def uph = r3 \ not in interrupt .def r_zero = r5 \ read only zero .def r_one = r6 \ read only one .def r_two = r7 \ read only two .def t8 = r8 \ Not in interrupt .def wflags = r9 \ not in interrupt
After rewriting:
\ Register definitions R2 .def upl \ not in interrupt R3 .def uph \ not in interrupt R5 .def r_zero \ read only zero R6 .def r_one \ read only one R7 .def r_two \ read only two R8 .def t8 \ Not in interrupt R9 .def wflags \ not in interrupt
It is possible to write directives in FORTH capable of parsing the assembly code. But their development is more complex, because of assembly code syntax specifics.
The other advantage of rewriting assembly code in a FORTH syntax compatible with Xassembler also means cleaning up the lines of assembly code by leaving comment out the parts not used in our code in general. Example:
\ xl = r26 \ xh = r27 \ yl = r28 \ StackPointer Ylo \ yh = r29 \ StackPointer Yhi \ zl = r30 \ zh = r31
The words xl through zh are already defined in Xassembler.
Definition of macros
In the file code Xassembler.txt we find the redefinition of the directives .macro and .endmacro defined as follows:
: .macro ( exec: --) : ; : .endmacro ( --) postpone ; ; immediate
Here is our first macro in assembler:
.macro poptos ld tosl, Y+ ld tosh, Y+ .endmacro
Rewrite in FORTH of poptos
:
r24 .def tosl r25 .def tosh .macro poptos tosl Y+ ld, tosh Y+ ld, .endmacro
Testing macros with gForth
As long as the metacompiler has not redirected the execution of assembly codes, it is possible to see this code generated in hexadecimal form.
Gforth 0.7.3, Copyright (C) 1995-2008 Free Software Foundation, Inc. Gforth comes with ABSOLUTELY NO WARRANTY; for details type `license' Type `bye' to exit include Xassembler.txt Xassembler.txt loaded ok Xassembler ok r24 .def tosl ok r25 .def tosh ok .macro poptos compiled tosl Y+ ld, compiled tosh Y+ ld, compiled .endmacro ok : tt [ poptos ] ; 9189 9199 ok
We see the result of the execution of poptos
which restores the
values 9189 9199. This result confirms the correct execution of our macro instruction.
Conditional compilation
Conditional assembly directives are found throughout the AVR assembly code: .if .else .endif .then. These directives make it possible to adapt an assembly code according to of the following conditions .if, example in assembler:
.macro mijmp .if (FLASHEND > 0xffff) eijmp .else ijmp .endif .endmacro
gForth has the words if
, else
and endif
allowing to replace
their assembler equivalent. Result in FORTH:
$3fff .equ FLASHEND \ defined in other file compimled before macros.txt .macro mijmp FLASHEND 65535 > if eijmp, else ijmp, endif .endmacro
File access macros.inc.