Definition of macro instructions

published: 11 April 2021 / updated 11 April 2021

Lire cette page en français

 

 

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.