| |||
| Home > Using the Inline and Embedded Assemblers of the ARM Compiler > Inline assembler and register access in C and C++ code | |||
The inline assembler provides no direct access to the physical registers of an ARM processor. If an ARM register name is used as an operand in an inline assembler instruction it becomes a reference to a variable of the same name, and not the physical ARM register. (The variable can be thought of as a virtual register.)
The compiler declares variables for physical registers as
appropriate during optimization and code generation. However, the
physical register used in the assembled code might be different to
that specified in the instruction, or it might be stored on the
stack. You can explicitly declare variables representing physical
registers as normal C or C++ variables. The compiler implicitly declares
registers R0 to R12 and r0 to r12 as auto
signed int local variables, regardless of whether or not
they are used. If you want to declare them to be of a different
data type, you can do so. For example, in the following code, the
compiler does not implicitly declare r1 and r2 as auto
signed int because they are explicitly declared as char and float types
respectively:
void bar(float *);
int add(int x)
{
int a = 0;
char r1 = 0;
float r2 = 0.0;
bar(&r2);
__asm
{
ADD r1, a, #100
}
...
return r1;
}
The compiler does not implicitly declare variables for any
other registers, so you must explicitly declare variables for registers
other than R0 to R12 and r0 to r12 in
your C or C++ code. No variables are declared for the sp (r13), lr (r14),
and pc (r15) registers, and
they cannot be read or directly modified in inline assembly code.
There is no virtual Processor Status Register (PSR).
Any references to the PSR are always to the physical PSR.
The size of the variables is the same as the physical registers.
The compiler-declared variables have function local scope, that is, within a single function, multiple asm statements or declarations that reference the same variable name access the same virtual register.
Existing inline assembler code that conforms to previously documented guidelines continues to perform the same function as in previous versions of the compiler, although the actual registers used in each instruction might be different.
The initial value in each variable representing a physical
register is unknown. You
must write to these variables before reading them. The compiler
generates an error if you attempt to read such a variable before
writing to it, for example, if you attempt to read the variable
associated with the physical register r1.
Any variables that you use in inline assembler to refer to
registers must be explicitly declared in your C or C++ code, unless
they are implicitly declared by the compiler. However, it is better to explicitly declare
them in your C or C++ code. You do not have to declare them to be
of the same data type as the implicit declarations. For example,
although the compiler implicitly declares register R0 to
be of type signed int, you can explicitly declare R0 as
an unsigned integer variable if required.
It is also better to use C or C++ variables as instruction
operands. The compiler generates a warning the first time a variable
or physical register name is used, regardless of whether it is implicitly
or explicitly declared, and only once for each translation unit.
For example, if you use register r3 without declaring
it, a warning is displayed. You can suppress the warning with --diag_suppress.