Trying to save a variable in an arm register using inline assembly.
unsigned int lma_offset = 0x1234; // typically calculated, hardcoded for example
__asm volatile ("MOV R10, %[input]"
: [input] "=r" (lma_offset)
);
This changes lma_offset to 0xd100 in my case, instead of setting the register. What am I doing wrong?
PS: when I declare lma_offset as const
it gives a compiler error because lma_offset is used as output. So obviously something is wrong, still I cant find the correct syntax for this.
CodePudding user response:
For future reference, according to Erics comment
const unsigned int lma_offset = 0x10000;
__asm__ volatile ("MOV R10, %[input]"
: // no C variable outputs
: [input] "r" (lma_offset)
: "R10" // tell the compiler R10 is modified
);
using double :
and replacing the "=r" with "r" indeed solves the problem.
It would also be possible to ask the compiler to have that constant already in R10 for an asm statement, by using a register local variable to force the "r"
input to pick r10
. (Then we can omit the redundant mov r10, r10
).
register unsigned r10 __asm__("r10") = lma_offset; // picks r10 for "r" constraints, no other *guaranteed* effects
__asm__ volatile ("@ inline asm went here" // empty template, actually just a comment you can see if looking at the compiler's asm output
: // no C variable outputs
: [input] "r" (lma_offset)
: // no clobbers needed
);
When writing a register to some output C variable it would result in
unsigned int lma_offset = 0x0;
__asm__ volatile ("MOV %[output], R11"
: [output] "=r" (lma_offset)
// no clobbers needed; reading a register doesn't step on the compiler's toes
);