register int *foo asm ("r12");
is the name of the register that should be used. Note that this is the same syntax used for defining global register variables, but for a local variable the declaration appears within a function. The
keyword is required, and cannot be combined with
. The register name must be a valid register name for the target platform.
As with global register variables, it is recommended that you choose a register that is normally saved and restored by function calls on your machine, so that calls to library routines will not clobber it.
The only supported use for this feature is to specify registers for input and output operands when calling Extended
(see Extended Asm
). This may be necessary if the constraints for a particular machine don't provide sufficient control to select the desired register. To force an operand into a register, create a local variable and specify the register name after the variable's declaration. Then use the local variable for the
operand and specify any constraint letter that matches the register:
register int *p1 asm ("r0") = ...; register int *p2 asm ("r1") = ...; register int *result asm ("r0"); asm ("sysint" : "=r" (result) : "0" (p1), "r" (p2));
In the above example, be aware that a register (for example
) can be call-clobbered by subsequent code, including function calls and library calls for arithmetic operators on other variables (for example the initialization of
). In this case, use temporary variables for expressions between the register assignments:
int t1 = ...; register int *p1 asm ("r0") = ...; register int *p2 asm ("r1") = t1; register int *result asm ("r0"); asm ("sysint" : "=r" (result) : "0" (p1), "r" (p2));
Defining a register variable does not reserve the register. Other than when invoking the Extended
, the contents of the specified register are not guaranteed. For this reason, the following uses are explicitly not
supported. If they appear to work, it is only happenstance, and may stop working as intended due to (seemingly) unrelated changes in surrounding code, or even minor changes in the optimization of a future version of gcc:
asmwithout using input or output operands.
Some developers use Local Register Variables in an attempt to improve gcc's allocation of registers, especially in large functions. In this case the register name is essentially a hint to the register allocator. While in some instances this can generate better code, improvements are subject to the whims of the allocator/optimizers. Since there are no guarantees that your improvements won't be lost, this usage of Local Register Variables is discouraged.
On the MIPS platform, there is related use for local register variables with slightly different characteristics (see Defining coprocessor specifics for MIPS targets ).