You copied the Doc URL to your clipboard.

-ffixed-rN

Prevents the compiler from using the specified core register, unless the use is required for Arm ABI compliance. You must use this option if you want to reserve registers for use as a global named register variable.

Default

By default, the compiler is free to use core registers for any purpose, such as for temporary storage of local variables, within the requirements of the Arm ABI.

Syntax

-ffixed-rN

Parameters

N specifies the register number, which can be any number from 5 to 11. This enables you to reserve core registers R5 to R11.

Restrictions

This feature is only available for AArch32 state.

If you use -mpixolib, then you must not use the following registers as global named register variables:

  • R8
  • R9

If you use -fwrpi or -fwrpi-lowering, then you must not use register R9 as a global named register variable.

Arm recommends that you do not use the following registers as global named register variables because the Arm ABI reserves them for use as a frame pointer if needed. You must carefully analyze your code, to avoid side effects, if you want to use these registers as global named register variables:

  • R7 in T32 state.
  • R11 in A32 state.
Code size

Declaring a core register as a global named register variable means that the register is not available to the compiler for other operations. If you declare too many global named register variables, code size increases significantly. In some cases, your program might not compile, for example if there are insufficient registers available to compute a particular expression.

Operation

-ffixed-rN reserves the specified core register so that the compiler does not use the specified register unless required for Arm ABI compliance. You must reserve the register if you want to use the register as a global named register variable. You can also use -ffixed-rN for generating compatible objects, for example to generate objects that you want to link with other objects that have been built with -frwpi.

For example -ffixed-r5 reserves register R5 so that the compiler cannot use R5 for storing temporary variables.

Note

The specified registers might still be used in other object files, for example library code, that have not been compiled using the -ffixed-rN option.

Examples

The following example demonstrates the effect of the -ffixed-rN option.

Source file foo.c contains the code below:

int foo(int a1, int a2, int a3, int a4, int a5, int a6)
{
   return  a1/a2 + a3/a4 + a5/a6;
}

Compile the above code without any -ffixed-rN option:

armclang --target=arm-arm-none-eabi -march=armv8-a -O0 -S foo.c -o foo.s

The generated assembly file, foo.s, saves the registers it needs to use, which are {r4, r5, r6, r7, r11, lr}:

foo:
        .fnstart
@ %bb.0:
        .save   {r4, r5, r6, r7, r11, lr}
        push    {r4, r5, r6, r7, r11, lr}
        .pad    #40
        sub     sp, sp, #40
       
        /* Code in between is hidden */

        add     sp, sp, #40
        pop     {r4, r5, r6, r7, r11, pc}
.Lfunc_end0:

To ensure that the compiler does not use registers R5 and R6, compile the same code in foo.c with the -ffixed-r5 and -ffixed-r6 options:

armclang --target=arm-arm-none-eabi -march=armv8-a -O0 -ffixed-r5 -ffixed-r6 -S foo.c -o foo.s

The generated assembly file, foo.s, saves the registers it needs to use, which are {r4, r7, r8, r9, r11, lr}. In this foo.s, the compiler uses registers R8 and R9 instead of R5 and R6:

foo:
        .fnstart
@ %bb.0:
        .save   {r4, r7, r8, r9, r11, lr}
        push    {r4, r7, r8, r9, r11, lr}
        .pad    #40
        sub     sp, sp, #40
       
        /* Code in between is hidden */

        add     sp, sp, #40
        pop     {r4, r7, r8, r9, r11, pc}
.Lfunc_end0:
Was this page helpful? Yes No