Arguments in included assembler instructions
> >Many times I have found it necessary to include asm instructions
> >in a C program. It should be possible to do this in such a way
> >that the compiler will substitute the locations of variables for
> >the variable names in the asm instructions. I know of ways to do
> >the job; one person to whom I showed this pointed out that if the
> >compiler were changed this could break. This would not be the case
> >if the suggested enhancement were made.
> Yes. Someone suggested a 'printf-like' capability for asm() a while back.
> EG on a 68000 machine, to get the user stack pointer in supervisor code:
The WE32K compiler that AT&T-IS puts out has what looks like a rather nice
new kind of "asm" facility. To quote from the release notes from S5R2.1 on
The enhanced "asm" facility allows the user to define constructs
that look 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 can 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.
The uses of an "asm" macro look like normal C function calls.
They can be used in expressions and they can return values. The
arguments to an "asm" macro can be arbitrary expressions, except
that they can not contain uses of the same or other "asm" macros.
When the argument to an "asm" macro is a function name or
structure, the compiler generates code to compute a pointer to the
structure or function, and the resulting pointer is used as the
actual argument of the macro.
The example they give:
asm void SPL(newpri)
% reg newpri;
% con newpri;
This says that "SPL" is a function returning no value and taking one
argument. If the argument is in a register, it just generates an "spl"
instruction using that register. If it's a constant, it generates a "movw"
to move it into r0 and then generates an "spl" using r0.
The set of storage modes it recognizes are:
"treg" - a compiler-selected temporary register.
"ureg" - a register variable.
"reg" - a "treg" or "ureg".
"con" - a compile-time constant.
"mem" - any allowed machine addressing mode, including "reg"
"lab" - a new label. This is not used with a formal parameter;
it causes a new label to be generated.
"error" - generates an error. This is used if code cannot be
generated for certain operand types.
If a value is returned, the code generated by the macro must "do the right
thing", e.g. return the value in the register used for function return
So if you say
it will generate
The example given for getting the user stack pointer from supervisor mode on
a 68K would look something like:
asm char *
(assuming an implementation where pointer types are returned in A0).
If you wanted something that copied the user SP into its argument (this is a
function that modifies its argument - "asm" functions can do this), it would
% reg user_sp;
% mem user_sp;
(I am assuming that this would just generate a "movec" if "user_sp" was a
register and the "movec"/"movea" pair otherwise).