I've written a small function with C-code and a short inline assembly statement.
Inside the inline assembly statement I need 2 "temporary" registers to load and compare some memory values.
To allow the compiler to choose "optimal temporary registers" I would like to avoid hard-coding those temp registers (and putting them into the clobber list).
Instead I decided to create 2 local variables in the surrounding C-function just for this purpose. I used "=r" to add these local variables to the output operands specification of the inline asm statement and then used them for my load/compare purposes.
These local variables are not used elsewhere in the C-function and (maybe because of this fact) the compiler decided to assign the same register to the two related output operands which makes my code unusable (comparison is always true).
Is the compiler allowed to use overlapping registers for different output operands or is this a compiler bug (I tend to rate this as a bug)?
I only found information regarding early clobbers which prevent overlapping of register for inputs and outputs... but no statement for just output operands.
A workaround is to initialize my temporary variables and to use "+r" instead of "=r" for them in the output operand specification. But in this case the compiler emits initialization instructions which I would like to avoid.
Is there any clean way to let the compiler choose optimal registers that do not overlap each other just for "internal inline assembly usage"?
非常感谢你!
P.S.: I code for some "exotic" target using a "non-GNU" compiler that supports "GNU inline assembly".
P.P.S.: I also don't understand in the example below why the compiler doesn't generate code for "int eq=0;" (e.g. 'mov d2, 0'). Maybe I totally misunderstood the "=" constraint modifier?
下面共有useless and stupid个例子来说明(关注)问题:
int foo(const int *s1, const int *s2)
{
int eq = 0;
#ifdef WORKAROUND
int t1=0, t2=1;
#else
int t1, t2;
#endif
__asm__ volatile(
"ld.w %[t1], [%[s1]] \n\t"
"ld.w %[t2], [%[s2]] \n\t"
"jne %[t1], %[t2], 1f \n\t"
"mov %[eq], 1 \n\t"
"1:"
: [eq] "=d" (eq),
[s1] "+a" (s1), [s2] "+a" (s2),
#ifdef WORKAROUND
[t1] "+d" (t1), [t2] "+d" (t2)
#else
[t1] "=d" (t1), [t2] "=d" (t2)
#endif
);
return eq;
}
在创建的asm中,编译器对操作数"t1"和"t2"使用寄存器"d8":
foo:
; 'mov d2, 0' is missing
ld.w d8, [a4] ; 'd8' allocated for 't1'
ld.w d8, [a5] ; 'd8' allocated for 't2' too!
jne d8, d8, 1f
mov d2, 1
1:
ret16
编译w/"-DWORKAROUND":
foo:
; 'mov d2, 0' is missing
mov16 d9,1
mov16 d8,0
ld.w d9, [a5]
jne d8, d9, 1f
mov d2, 1
1:
ret16
此机器的EABI:
- 返回寄存器(非指针/指针):d2,a2
- 非指针args:d4..D7
- 指针参数:a4..a7