Previous: Global Reg Vars, Up: Explicit Reg Vars


6.42.5.2 Specifying Registers for Local Variables

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 asm operand guarantees that the specified register is used for the operand.

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));