Reputation: 247
I'm wondering how I can load a register with a the value of a label in inline assembly.
I tried naively doing it in this fashion:
#define inline_macro(a) \
asm volatile("1: movw %[rega], #:lower16:1b\n" \
" movt %[rega], #:upper16:1b\n" \
: [rega] "+r" (a) \
: \
: \
);
int main(void){
register int i asm("r2");
register void* value asm("r1");
i++;
i += 2;
inline_macro(value);
return i;
}
However, the object dump shows this assembly code being generated:
00000000 <main>:
0: e52db004 push {fp} ; (str fp, [sp, #-4]!)
4: e28db000 add fp, sp, #0
8: e1a03002 mov r3, r2
c: e2833001 add r3, r3, #1
10: e1a02003 mov r2, r3
14: e1a03002 mov r3, r2
18: e2833002 add r3, r3, #2
1c: e1a02003 mov r2, r3
00000020 <.L11>:
20: e3001000 movw r1, #0
24: e3401000 movt r1, #0
28: e1a03002 mov r3, r2
2c: e1a00003 mov r0, r3
30: e24bd000 sub sp, fp, #0
34: e49db004 pop {fp} ; (ldr fp, [sp], #4)
38: e12fff1e bx lr
What I want is for the value 0x20 to be loaded into register r1.
Upvotes: 2
Views: 559
Reputation: 20924
There is actually a whole instruction for getting the address of a label into a register: ADR
.
Since it works by arithmetic on the PC, it's completely position-independent and doesn't have unlimited range, but neither seems an issue here - taking advantage of the assembler's "current instruction" pseudo-label .
, the example in the question becomes:
#define inline_macro(a) \
asm volatile("adr %[rega], . \n" \
: [rega] "=r" (a) \
: \
: \
);
Upvotes: 2
Reputation: 364180
I don't know arm asm, but you're trying to get the address of the movw
instruction? Does ARM really require two separate 16bit mov
instructions for that?
It looks like you're disassembling the .o
, where the linker hasn't replaced symbol references with their actual values, and you're seeing 0
as a placeholder.
Since I think your code doesn't depend on the old value of the register, you should use it as a write-only output operand (=r
), not a read-write operand (+r
).
Upvotes: 1