http://gcc.gnu.org/bugzilla/show_bug.cgi?id=46164
Summary: Local variables in specified registers don't work correctly with inline asm operands Product: gcc Version: 4.5.1 Status: UNCONFIRMED Severity: normal Priority: P3 Component: middle-end AssignedTo: unassig...@gcc.gnu.org ReportedBy: siarhei.siamas...@gmail.com When testing with gcc 4.5.1 ==== ARM ==== $ cat test.c int f(int a) { register int result asm("r0"); asm ( "add r0, %[a], #123\n" : [result] "=&r" (result) : [a] "r" (a) ); return result; } $ gcc -O2 -c test.c $ objdump -d test.o 00000000 <f>: 0: e280007b add r0, r0, #123 ; 0x7b 4: e1a00003 mov r0, r3 8: e12fff1e bx lr Here the local variable 'result' gets assigned to register r3 instead of r0 causing all kind of problems. ==== x86-64 ==== $ cat test.c int f(int a) { register int result asm("edi"); asm ( "lea 0x7b(%[a]), %%edi\n" : [result] "=&r" (result) : [a] "r" (a) ); return result; } $ gcc -O2 -c test.c $ objdump -d test.o 0000000000000000 <f>: 0: 67 8d 7f 7b addr32 lea 0x7b(%edi),%edi 4: c3 retq ================================= And some final bits. http://gcc.gnu.org/onlinedocs/gcc/Local-Reg-Vars.html#Local-Reg-Vars http://gcc.gnu.org/onlinedocs/gcc/Extended-Asm.html The documantation is a bit confusing, but it gives at least one example of assigining variables to specified registers: "Sometimes you need to make an asm operand be a specific register, but there's no matching constraint letter for that register by itself. To force the operand into that register, use a local variable for the operand and specify the register in the variable declaration. See Explicit Reg Vars. Then for the asm operand, use any register 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));" Let's try to use something like that with x86-64: /********************/ void abort(); int __attribute__((noinline)) f(int a) { register int p1 asm ("edi"); register int result asm ("edi"); asm ( "mov %2, %0\n" "add %2, %0\n" "add %2, %0\n" : "=r" (result) : "0" (p1), "r" (a)); return result; } int main() { if (f(1) != 3) abort(); } /********************/ This testcase fails. So is it a bug in gcc? Or the documentation is wrong? Or I'm missing something?