Create and manage labels in metacompilation

published: 2 April 2021 / updated 2 April 2021

Lire cette page en français

 

The labels

Labels are defined in assembler as the code unfolds. Here is a fragment of the code FlashForth source:

; EXIT --   Compile a return
;        variable link
        .dw     0
EXIT_L:
        .db     NFA|4,"exit",0
EXIT:
        m_pop_t0
        pop     t0
        pop     t0
        ret

        fdw     IFLUSH_L
OPERATOR_L:
        .db     NFA|8,"operator",0
OPERATOR:
        call    DOCREATE
        fdw     OPERATOR_AREA
OPERATOR_AREA:
        .dw     up0
        .dw     0, ursize
        .dw     ussize, utibsize

Here, each label is in red. Labels preceded by a colon are labels not defined and created, example EXIT:.

Labels, once defined, can be used as many times as needed. Example call DOCREATE.

Definition of labels in FORTH

Label definition code:

\ Coded labels without header in target 
: label  ( -- ) 
    forced 
    >IN @ Xassembler definitions 
    here-t constant                 \ create label in Xassembler vocabulary 
    >IN ! ?resolves unforced 
    ; 

This definition is written to the file meta.txt. The word label is followed by the name of the label to create. This label is recorded in the vocabulary Xassembler. Example, for this code in assembler:

DOUSER:
        m_pop_zh
        pop     zh
        pop     zl
        rcall   FETCHLIT
        add     tosl, upl
        adc     tosh, uph
        ret

Which is rewritten in FORTH assembler with a DOUSER label:

label DOUSER
    m_pop_zh
    zh pop,
    zl pop,
    FETCHLIT rcall,
    tosl upl add,
    tosh uph adc,
    ret,

A label is a constant created in the Xassembler vocabulary. This constant contains the value of the dp-t pointer in the target. This pointer increments as the meta-compilation progresses:

The meta-compilation target is pointed to by ADR-T. The pointer dp-t (Dictionnary Pointer in Target) is incremented each time that code is assembled or compiled into the target.

The value of this pointer is retrieved by the word here-t (HERE in Target).

Each label points to a relative address in the target. Running a label restores this relative address.

Use of labels

Once defined, any label can be used in FORTH or FORTH assembler code.

However, unlike pure assembly code, it is not possible to use a label before it is defined. Example:

label DOUSER
    .....
    FETCHLIT rcall,
    .....
    ret,
 
label FETCHLIT
    .....
    ret,

In our example, we try a subroutine call to FETCHLIT before its definition in the Xassembler vocabulary.

This is one of the drawbacks of the FORTH language.

To be able to make a connection to FETCHLIT, you must move the code:

label FETCHLIT
    .....
    ret,
 
   label DOUSER
    .....
    FETCHLIT rcall,
    .....
    ret,     

When rewriting the FlashForth assembly code, we will define a label for each CFA, example of assembly code:

        fdw     MPLUS_L
MINUS_L:
        .db     NFA|INLINE5|1, "-"
MINUS:
        ld      t0, Y+
        ld      t1, Y+
        sub     t0, tosl
        sbc     t1, tosh
        movw    tosl, t0
        ret

And its rewrite in FORTH assembler:

  label MINUS
    t0 Y+ ld,
    t1 Y+ ld,
    t0 tosl sub,
    t1 tosl sbc,
    tosl t0 movw,
    ret,

In this code:

The NFA field of a FORTH definition is written, in the original FlashForth code, Under the form:

        fdw     MPLUS_L
MINUS_L:
        .db     NFA|INLINE5|1, "-"

In metacompilation, this hardware is useless, because simply replaced by this:

code -

And this is how - is defined in the meta-compiled source code:

code - ( n1 n2 -- n1-n2)
  label MINUS
    t0 Y+ ld,
    t1 Y+ ld,
    t0 tosl sub,
    t1 tosl sbc,
    tosl t0 movw,
    ret,
end-code

The explanations on these mechanisms are explained in the following article...