(__arch_compare_and_exchange_bool_32_acq): Fix case where oldval is negative. (__arch_compare_and_exchange_bool_32_rel): Likewise.

This commit is contained in:
Ulrich Drepper 2004-08-25 23:24:20 +00:00
parent effeb660b7
commit 8e64f8ba4e
1 changed files with 19 additions and 23 deletions

View File

@ -18,44 +18,40 @@
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
02111-1307 USA. */ 02111-1307 USA. */
/* /* The 32-bit exchange_bool is different on powerpc64 because the subf
* The 32-bit exchange_bool is different on powerpc64 because the subf does signed 64-bit arthmatic while the lwarx is 32-bit unsigned
* does signed 64-bit arthmatic while the lwarx is 32-bit unsigned (a load word and zero (high 32) form) load.
* (a load word and zero (high 32) form) load. In powerpc64 register values are 64-bit by default, including oldval.
* In powerpc64 register values are 64-bit by default, including oldval. The value in old val unknown sign extension, lwarx loads the 32-bit
* Net we need to extend sign word the result of lwarx to 64-bit so the value as unsigned. So we explicitly clear the high 32 bits in oldval. */
* 64-bit subtract from gives the expected result and sets the condition
* correctly.
*/
# define __arch_compare_and_exchange_bool_32_acq(mem, newval, oldval) \ # define __arch_compare_and_exchange_bool_32_acq(mem, newval, oldval) \
({ \ ({ \
unsigned int __tmp; \ unsigned int __tmp, __tmp2; \
__asm __volatile ( \ __asm __volatile (" clrldi %1,%1,32\n" \
"1: lwarx %0,0,%1\n" \ "1: lwarx %0,0,%2\n" \
" extsw %0,%0\n" \ " subf. %0,%1,%0\n" \
" subf. %0,%2,%0\n" \
" bne 2f\n" \ " bne 2f\n" \
" stwcx. %3,0,%1\n" \ " stwcx. %4,0,%2\n" \
" bne- 1b\n" \ " bne- 1b\n" \
"2: " __ARCH_ACQ_INSTR \ "2: " __ARCH_ACQ_INSTR \
: "=&r" (__tmp) \ : "=&r" (__tmp), "=r" (__tmp2) \
: "b" (mem), "r" (oldval), "r" (newval) \ : "b" (mem), "1" (oldval), "r" (newval) \
: "cr0", "memory"); \ : "cr0", "memory"); \
__tmp != 0; \ __tmp != 0; \
}) })
# define __arch_compare_and_exchange_bool_32_rel(mem, newval, oldval) \ # define __arch_compare_and_exchange_bool_32_rel(mem, newval, oldval) \
({ \ ({ \
unsigned int __tmp; \ unsigned int __tmp, __tmp2; \
__asm __volatile (__ARCH_REL_INSTR "\n" \ __asm __volatile (__ARCH_REL_INSTR "\n" \
"1: lwarx %0,0,%1\n" \ " clrldi %1,%1,32\n" \
" extsw %0,%0\n" \ "1: lwarx %0,0,%2\n" \
" subf. %0,%2,%0\n" \ " subf. %0,%1,%0\n" \
" bne 2f\n" \ " bne 2f\n" \
" stwcx. %3,0,%1\n" \ " stwcx. %4,0,%2\n" \
" bne- 1b\n" \ " bne- 1b\n" \
"2: " \ "2: " \
: "=&r" (__tmp) \ : "=&r" (__tmp), "=r" (__tmp2) \
: "b" (mem), "r" (oldval), "r" (newval) \ : "b" (mem), "r" (oldval), "r" (newval) \
: "cr0", "memory"); \ : "cr0", "memory"); \
__tmp != 0; \ __tmp != 0; \