How to implement atomic swap with asm on PowerPC

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



I implemented the atomic swap operation on PowerPC with the following code:

$ cat t.c
void * swap(volatile void * ptr, void * val)
{
 void * old;

 __asm__ __volatile__(
     "1:"
     "ldarx %0,0,%2\n"
     "stdcx. %1,0,%2\n"
     "bne- 1b\n"
     : "=r" (old)
     : "r" (val), "r" (ptr)
     : "cc" );

 return old;
}

Which is compiled to:

$ gcc -g -O2 -c t.c
$ gdb t.o
Reading symbols from /home/cy6/t.o...done.
(gdb) disas swap
Dump of assembler code for function swap:
  0x0000000000000000 <+0>:	ldarx   r3,0,r3
  0x0000000000000004 <+4>:	stdcx.  r4,0,r3
  0x0000000000000008 <+8>:	bne-    0x0 <swap>
  0x000000000000000c <+12>:	blr
  0x0000000000000010 <+16>:	.long 0x0
  0x0000000000000014 <+20>:	.long 0x0
  0x0000000000000018 <+24>:	.long 0x0
End of assembler dump.
(gdb) q

Notice that the ldarx instruction used the same register for both src and destination, which overwrites the pointer. This leads to the stdcx instruction to fail, because r3 no longer holds the pointer.

Since I specified ptr as an input, I assume GCC should not try to reuse the register. Am I missing a constraint here? What should I do to tell GCC to not to use the same register for ldarx instruction?

I’m using GCC 4.4.7.

Thanks,
Chaoran




[Index of Archives]     [Linux C Programming]     [Linux Kernel]     [eCos]     [Fedora Development]     [Fedora Announce]     [Autoconf]     [The DWARVES Debugging Tools]     [Yosemite Campsites]     [Yosemite News]     [Linux GCC]

  Powered by Linux