
Jerry Lawson wrote:
The cas _asm_ instruction for the gcc/sparc environment has a slight flaw: it does not prevent the gcc compiler from generating assembly that contains a invalid register/offset. In other words, the existing _asm_ can cause gcc to generate something like:
cas [%i0+80], %i1, %i2
the relative offset is an illegal address mode for cas instruction.
I'm not a sparc assembly guy, by any stretch of the imagination, but doing some reading at http://blogs.sun.com/wesolows/entry/gcc_inline_assembly_part_2 would seem to indicate that this code:
inline int32_t compare_and_swap( int32_t * dest_, int32_t compare_, int32_t swap_ ) { __asm__ __volatile__( "cas %0, %2, %1"
: "+m" (*dest_), "+r" (swap_) : "r" (compare_) : "memory" );
return swap_; }
is not exactly correct. When using -O3 optimization option to gcc, the aforementioned "bad" cas instruction is generated.
Sounds like a gcc bug. Which versions of gcc have you tried?
I'm done some experimenting and with the following code, gcc seems to generate the proper code:
inline int32_t compare_and_swap( int32_t * dest_, int32_t compare_, int32_t swap_ ) { __asm__ __volatile__( "cas [%2], %3, %0"
: "=&r" (swap_) : "0" (swap_), "r" (dest_), "r" (compare_) : "memory" );
return swap_; }
We might be able to use that as a fix if it works, but it's not correct in principle. One case where it fails is on 64 bit machines that use 32 bit pointers. This may not be a problem on SPARCs though.