You can define a local register variable with a specified register like this:
register int *foo asm ("a5");
Here a5
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 it appears within a function.
Naturally the register name is CPU-dependent, but this is not a problem, since specific registers are most often useful with explicit assembler instructions (see Extended Asm). Both of these things generally require that you conditionalize your program according to CPU type.
In addition, operating systems on one type of CPU may differ in how they
name the registers; then you need additional conditionals. For
example, some 68000 operating systems call this register %a5
.
Defining such a register variable does not reserve the register; it remains available for other uses in places where flow control determines the variable's value is not live.
This option does not guarantee that GCC generates code that has
this variable in the register you specify at all times. You may not
code an explicit reference to this register in the assembler
instruction template part of an asm
statement and assume it
always refers to this variable.
However, using the variable as an input or output operand to the asm
guarantees that the specified register is used for that operand.
See Extended Asm, for more information.
Stores into local register variables may be deleted when they appear to be dead according to dataflow analysis. References to local register variables may be deleted or moved or simplified.
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 library routines will not clobber it.
Sometimes when writing inline asm
code, you need to make an operand be a
specific register, but there's no matching constraint letter for that
register. To force the operand into that register, create a local variable
and specify the register in the variable's declaration. Then use the local
variable for the asm 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));
Warning: In the above example, be aware that a register (for example r0) can be call-clobbered by subsequent code, including function calls and library calls for arithmetic operators on other variables (for example the initialization of p2). 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));