EM_CODE(3ACK)

NAME
emcode - EM code interface for compilers

SYNOPSIS
#include <em.h>

C_init(wsize, psize)
arith wsize, psize;

int C_open(filename)
C_close()
int C_busy()
char *filename;

C_magic()

C_df_dlb(l)
C_df_dnam(s)
C_df_ilb(l)
label l; char *s;

C_pro(s, l)
C_pro_narg(s)
C_end(l)
C_end_narg()
char *s; arith l;

C_exa_dlb(l)
C_exa_dnam(s)
C_exp(s)
C_ina_dlb(l)
C_ina_dnam(s)
C_inp(s)
char *s; label l;

C_bss_cstp()
C_hol_cstp()
C_con_cstp()
C_rom_cstp()

#include <em_mes.h>
C_mes_begin(ms)
C_cstp()
C_mes_end()
int ms;

C_exc(c1, c2)
arith c1, c2;

C_mnem()
C_mnem_dlb()
C_mnem_dnam()
C_mnem_narg()

C_insertpart(id)
int id;

C_beginpart(id)
int id;

C_endpart(id)
int id;

int C_getid()

char *C_tmpdir;

DESCRIPTION
This package provides a procedural EM code interface to be used in compilers and other EM code producing programs. The basic idea behind this package is to simplify the program writer's task of producing EM code in any form, either compact or human-readable EM assembly code or a sequence of procedure calls.

The named types arith and label refer to types on the local machine that are suitable for doing arithmetics and storing EM numeric labels respectively. Common definitions are long for arith and unsigned int for label.

C_init() should be called to initialize the module. Wsize is the word size and psize the pointer size on the target machine. Checking implementations of this module use these values to check whether arguments of an instruction are legal.

C_open(filename) should be invoked as initialiser for a sequence of calls that produce EM code on file filename. When filename is a null pointer, the code is produced on standard output. Some implementations, such as fast back ends, may ignore the parameter. C_close causes some internal buffers to be flushed and the output file to be closed. All subsequent routines, except for C_busy, must be invoked between the calls to C_open and C_close.

C_busy can be invoked in order to detect whether EM code is currently being generated, i.e. whether you are in between calls to C_open and C_close. If this is the case, C_busy returns a 1.

C_magic() produces the EM magic word.

Two routines can be used to generate code for the definitions of global data labels: C_df_dlb(l) for numeric labels .l and C_df_dnam(s) for alphanumeric labels s.

C_df_ilb(l) produces EM code for instruction label l.

The routines for producing the EM procedure delimiters are:

    routine | EM pattern
    C_pro(s, l) | pro s, l
    C_pro_narg(s) | pro s, ?
    C_end(l) | end l
    C_end_narg() | end ?

A set of routines, concerning the scope definition pseudo instructions, is:

    routine | EM pattern
    C_exa_dnam(s) | exa s
    C_exa_dlb(l) | exa .l
    C_exp(s) | exp $s
    C_ina_dnam(s) | ina s
    C_ina_dlb(l) | ina .l
    C_inp(s) | inp $s

In the set of storage-declaration pseudo instructions, we can distinguish four groups, one for each type of storage declaration: con, rom, bss and hol.

The con/rom instructions are generated by C_con_cstp and C_rom_cstp, respectively. The type of the initialization value and the number and type of the parameters are determined by cstp according to the following table:

    cstp | number of | type of | description
     | parameters | parameters
    cst | 1 | arith | word-sized integer of arith-type
    icon | 2 | char * | integer in string representation
     |  | arith | number of bytes on target machine
    ucon | 2 | char * | unsigned integer in string representation
     |  | arith | number of bytes on target machine
    fcon | 2 | char * | floating in string representation
     |  | arith | number of bytes on target machine
    scon | 2 | char * | row of bytes
     |  | arith | length of the row of bytes
    dnam | 2 | char * | alphanumeric global data label
     |  | arith | offset (possibly 0)
    dlb | 2 | label | numeric global data label
     |  | arith | offset (possibly 0)
    ilb | 1 | label | instruction label
    pnam | 1 | char * | procedure identifier

As an example of the use of the con/rom routines, consider the following con instruction:
    con 23I4, "hello world", .12, table + 12, *33
A sequence of calls to get this, is
    C_con_icon("23", (arith)4);
    C_con_scon("hello world", (arith) 11);
    C_con_dlb((label)12, (arith)0);
    C_con_dnam("table", (arith)12);
    C_con_ilb((label)33);

A bss or hol instruction is produced by invoking C_bss_cstp or C_hol_cstp where cstp indicates the type of value that is used at initialisation. The parameter list of C_bss_cstp and C_hol_cstp is similar to that of the corresponding C_con_cstp, except that it is preceeded by an arith-typed operand nbytes, and followed by an int-typed operand init; nbytes indicates the number of bytes to reserve for the data; init has value 1 if the initialization is strictly necessary and 0 if not. Note that, according to the EM definition, an initialisation type of scon is not allowed in the bss/hol instruction.

Another set of routines is that of the EM mes pseudo instructions. As there is an undefined number of messages and each type of message has its own number of parameters and each parameter its own type, the user is responsible for building his own message lists. Such a list consists of a list of C_cstp routine calls enclosed by C_mes_begin(ms) where ms is the message number, and C_mes_end().

C_exc produces the EM exc c1,c2 instruction. The use of this function may cause trouble in some implementations of this module. A fast back end, for instance, may refuse to implement C_exc. The use of this function is therefore not recommended.

The final class of routines is that of the EM machine-instruction generating routines C_mnem, C_mnem_dlb, C_mnem_dnam and C_mnem_narg. The best way to describe them is according to section 11.3 of [EM]. Depending on the class of the argument (as indicated by a letter), one or more routines are available for each machine instruction. The following table gives an overview of the available routines for the EM machine instruction mnem:

    class | routine(s) | number of | type of
     |  | parameters | parameter(s)
    [cdflnorsz] | C_mnem | 1 | arith
    w | C_mnem | 1 | arith
     | C_mnem_narg | 0
    g | C_mnem | 1 | arith
     | C_mnem_dnam | 2 | char *
     |  |  | arith
     | C_mnem_dlb | 2 | label
     |  |  | arith
    p | C_mnem | 1 | char *
    b | C_mnem | 1 | label
    - | C_mnem | 0

The available routines for, for example, the EM machine instruction adi (with argument class w) are C_adi(w) for adi with a given argument, and C_adi_narg() for adi with an argument on top of the stack. Likewise are the available routines for loe (which instruction has argument class g): C_loe(g) where g is a constant, C_loe_dnam(g,o) where g is an alphanumeric label, and C_loe_dlb(g,o) where g is a numeric label. The latter two routines have the (possibly zero) offset o as second parameter.

The C_insertpart, C_beginpart, and C_endpart routines together implement a mechanism for re-arranging the generated code. A call to C_insertpart indicates that part id is to be inserted at the current position. The routines C_beginpart and C_endpart indicate begin and end of part id. The order in which the parts are defined is not significant. However, when C_close is called, all parts that have been inserted, must also be defined. Parts may themselves again have sub-parts.

The routine C_getid can be used to obtain a valid and unique part id.

On implementations with limited memory, the mechanism is implemented with a temporary file. The directory in which this file resides is indicated by C_tmpdir. The default is the #define TMP_DIR from ~em/h/em_path.h. The user can change this by just changing C_tmpdir before calling C_open.

FILES
~em/modules/h/em.h
~em/modules/lib/libemk.a: library for generating compact EM code
~em/modules/lib/libeme.a: library for generating human-readable EM code

MODULES
libemk.a: alloc(3), system(3), string(3)
libeme.a: alloc(3), print(3), system(3), string(3)

SEE ALSO
read_em(3), em_mes(3)

REFERENCES

[EM]
    Andrew S. Tanenbaum, Hans van Staveren, Ed G. Keizer, Johan W. Stevenson, "Description of a Machine Architecture for use with Block Structured Languages", Informatica Rapport IR-81, Vrije Universiteit, Amsterdam, 1983.

DIAGNOSTICS
C_open returns 1 if the open is successful and 0 if not.

When a read, write or open fails, the routine C_failed is called. The user can override its default definition by supplying his own. The default just gives an error message and quits.

When an error occurs with the C_insertpart mechanism, the routine C_internal_error is called. Again, the user can override its default definition by supplying his own. Such errors, however, are caused by a programming error of the user.

BUGS
It is not possible to indicate that the argument of C_con_cst () must be seen as an unsigned value.