Hi,
I am using GCC 4.4.4 for PowerPC (6xx series), and I've come across a bug in
some software that I'm trying to solve the best way.
The problem came to light around some atomic operator code, such as the
following:
static inline int atomic_post_inc(volatile int* ptr)
{
register int temp1, temp2;
asm volatile (
"1: lwarx %0, 0, %2 \n"
" mr %1, %0 \n"
" addi %0, %0, 1 \n"
" stwcx. %0, 0, %2 \n"
" bne- 1b \n"
: "=&r" (temp1), "=&r" (temp2) : "r" (ptr) : "cc", "memory"
);
return temp2;
}
The problem comes when using -O1, -O2 or -O3 when GCC chooses register r0
for 'temp1'. This changes the addi line to 'addi 0, 0, 1' but on the
PowerPC platform this particular instruction has a special meaning for '0'
as the second parameter, so basically rather than adding 1 to register 0, it
instead sets register 0 to 1. Obviously this breaks the functionality of
this code.
A simple solution in this case is to change the 'addi' opcode to 'addic'
which doesn't have this special meaning for '0' as the second parameter, and
add "xer" to the list of clobbered registers.
All well and good in this example, but there are other places where such a
simple instruction alteration is not the answer. What I was wondering is,
is there a way to tell GCC to avoid certain registers, in particular to
avoid register r0, when assigning registers for inline assembly?
I know it is possible to directly define which register a temporary variable
would have (e.g. by "register int temp1 asm ("r5");" for example), but this
then means that GCC is not free to choose the best register in order to
avoid unnecessary register copy instructions.
Is it therefore possible to tell GCC simply to just avoid using a particular
register?
Thanks for any and all help!
Andy