asm Macros

The enhanced asm facility allows you to define constructs that behave syntactically like static C functions. Each asm macro has one definition and zero or more uses per source file. The definition must appear in the same file with the uses (or be #included), and the same asm macro may be defined multiply (and differently) in several files.

The asm macro definition declares a return type for the macro code, specifies patterns for the formal parameters, and provides bodies of code to expand when the patterns match. When it encounters an asm macro call, the compiler replaces uses of the formal parameters by its idea of the assembly language locations of the actual arguments as it expands the code body. This constitutes an important difference between C functions and asm macros. An asm macro can therefore have the effect of changing the value of its arguments, whereas a C function can only change a copy of its argument values.

The use of an asm macro look exactly like normal C function calls. They may be used in expressions and they may return values. The arguments to an asm macro may be arbitrary expressions, except that they may not contain uses of the same or other asm macros.

When the argument to an asm macro is a function name or a structure contained in memory, the compiler generates code to compute a pointer to the structure or function, and then resulting pointer is used as the actual argument of the macro. Structures contained in registers are passed directly to the function. Addresses are loaded into a temporary variable before being passed along; these will usually be allocated to a register. The following example shows how passing addresses work:

Example

asm void make10(addr)
{
%reg addr
li r3, 10
stw r3, 0(addr)
%nearmem addr
lwz r4, addr
li r3, 10
stw r3, 0(r4)
%error
}

void func()
{
int i, array[10];
make10(&i);
make10(array);
make10(&array[3]);

}

Definition

The syntactic descriptions that follow are presented in the style used in "C Language Compilers." The syntactic classes type-specifier, identifier, and parameter-list have the same form as in that chapter. A syntactic description enclosed in square brackets ([ ]) is optional, unless the right bracket is followed by +. A + means "one or more repetitions" of a description. Similarly, * means "zero or more repetitions."

asm macro:
asm [type-specifier]identifier ([parameter-list])
{
[storage-mode-specification-line
asm-body] *
}

An asm macro consists of the keyword asm, followed by what looks like a C function declaration. Inside the macro body there are one for more pairs of storage-mode-specification-line(s) (patterns) and corresponding asm-body(ies). If the type-specifier is other than void, the asm macro should return a value of the declared type.

storage-mode-specification-line:
% [storage-mode [identifier [, identifier]* ]; ]+

A storage-mode-specification-line consists of a single line (no continuation with \ is permitted) that begins with % and contains the names (identifier(s)) and storage mode(s) of the formal parameters. Modes for all formal parameters must be given in each storage-mode-specification-line (except for error). The % must be the first character on a line. If an asm macro has no parameter-list, the storage-mode-specification-line may be omitted.

Storage Modes

These are the storage modes that the compiler recognizes in asm macros.

treg A compiler-selected temporary register.

ureg A C register variable that the compiler has allocated in a machine register.

farmem A location in memory that cannot be accessed with a single load instruction. These may need to be broken up into multiple load instructions, and the steps for doing this may depend on the compilation mode.

nearmem A location in memory that can be accessed with a single load instruction (such as nearby stack variables or variables in a small data area).

reg A treg or ureg.

con A compile time constant.

mem A mem operand matches any allowed machine addressing mode, with the exception of reg and con.

lab A compiler-generated unique label. The identifier(s) that are specified as being of mode lab do not appear as formal parameters in the asm macro definition, unlike the preceding modes. Such identifiers must be unique. Example:

asm void check_for_bit_set(r)
{
%reg r %lab endlab
b_if_not_bit_set r, endlab
software_trap
endlab:
%error
}

void check_status(int i, int j)
{
/* Using the macro twice would cause the "endlab" */
/* label to be defined twice if it was not specified
/* as a unique label */
check_for_bit_set(i);
check_for_bit_set(j);
}

error Generate a compiler error. This mode exists to allow you to flag errors at compile time if no appropriate pattern exists for a set of actual arguments.

farsprel A location on the stack that is too far away to be accessed in a single instruction.

Note: For an asm macro that does not take any arguments, use a blank storage mode (%).

asm Body

The asm body represents (presumed) assembly code that the compiler will generate when the modes of all of the formal parameters match the associated pattern. Syntactically, the asm body consists of the text between two pattern lines (that begin with %) or between the last pattern line and the } that ends the asm macro. C language comment lines are not recognized as such in the asm body. Instead they are simply considered part of the text to be expanded.

Formal parameter names may appear in any context in the asm body, delimited by non-alphanumeric characters. For each instance of a formal parameter in the asm body the compiler substitutes the appropriate assembly language operand syntax that will access the actual argument at run time. As an example, if one of the actual arguments to an asm macro is x, an automatic variable, a string like 4(%fp) would be substituted for occurrences of the corresponding formal parameter. An important consequence of this macro substitution behavior is that asm macros can change the value of their arguments. This differs from standard C semantics.

For lab parameters a unique label is chosen for each new expansion.

If an asm macro is declared to return a value, it must be coded to return a value of the proper type in the machine register that is appropriate for the implementation.

An implementation restriction requires that no line in the asm body may start with %.

The MCore compiler also supports the following primitives in the body of an asm statement.

%SPOFF(m)

Given that m is of the farsprel storage class, this expands to an integer containing its offset from the stack pointer.

Example:

%farsprel m
lrw r3, %SPOFF(m)
add r3,r0
ld.w r3,(r3,0)

Previous

Next



Copyright © 1999, Green Hills Software. All rights reserved.