From 8e64f8ba4e49662a1ab79e5921c1a3bfb73d888e Mon Sep 17 00:00:00 2001 From: Ulrich Drepper Date: Wed, 25 Aug 2004 23:24:20 +0000 Subject: (__arch_compare_and_exchange_bool_32_acq): Fix case where oldval is negative. (__arch_compare_and_exchange_bool_32_rel): Likewise. --- sysdeps/powerpc/powerpc64/bits/atomic.h | 42 +++++++++++++++------------------ 1 file changed, 19 insertions(+), 23 deletions(-) (limited to 'sysdeps/powerpc') diff --git a/sysdeps/powerpc/powerpc64/bits/atomic.h b/sysdeps/powerpc/powerpc64/bits/atomic.h index 16bb994601..1a20e3f0fd 100644 --- a/sysdeps/powerpc/powerpc64/bits/atomic.h +++ b/sysdeps/powerpc/powerpc64/bits/atomic.h @@ -18,44 +18,40 @@ Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -/* - * The 32-bit exchange_bool is different on powerpc64 because the subf - * does signed 64-bit arthmatic while the lwarx is 32-bit unsigned - * (a load word and zero (high 32) form) load. - * In powerpc64 register values are 64-bit by default, including oldval. - * Net we need to extend sign word the result of lwarx to 64-bit so the - * 64-bit subtract from gives the expected result and sets the condition - * correctly. - */ +/* The 32-bit exchange_bool is different on powerpc64 because the subf + does signed 64-bit arthmatic while the lwarx is 32-bit unsigned + (a load word and zero (high 32) form) load. + In powerpc64 register values are 64-bit by default, including oldval. + The value in old val unknown sign extension, lwarx loads the 32-bit + value as unsigned. So we explicitly clear the high 32 bits in oldval. */ # define __arch_compare_and_exchange_bool_32_acq(mem, newval, oldval) \ ({ \ - unsigned int __tmp; \ - __asm __volatile ( \ - "1: lwarx %0,0,%1\n" \ - " extsw %0,%0\n" \ - " subf. %0,%2,%0\n" \ + unsigned int __tmp, __tmp2; \ + __asm __volatile (" clrldi %1,%1,32\n" \ + "1: lwarx %0,0,%2\n" \ + " subf. %0,%1,%0\n" \ " bne 2f\n" \ - " stwcx. %3,0,%1\n" \ + " stwcx. %4,0,%2\n" \ " bne- 1b\n" \ "2: " __ARCH_ACQ_INSTR \ - : "=&r" (__tmp) \ - : "b" (mem), "r" (oldval), "r" (newval) \ + : "=&r" (__tmp), "=r" (__tmp2) \ + : "b" (mem), "1" (oldval), "r" (newval) \ : "cr0", "memory"); \ __tmp != 0; \ }) # define __arch_compare_and_exchange_bool_32_rel(mem, newval, oldval) \ ({ \ - unsigned int __tmp; \ + unsigned int __tmp, __tmp2; \ __asm __volatile (__ARCH_REL_INSTR "\n" \ - "1: lwarx %0,0,%1\n" \ - " extsw %0,%0\n" \ - " subf. %0,%2,%0\n" \ + " clrldi %1,%1,32\n" \ + "1: lwarx %0,0,%2\n" \ + " subf. %0,%1,%0\n" \ " bne 2f\n" \ - " stwcx. %3,0,%1\n" \ + " stwcx. %4,0,%2\n" \ " bne- 1b\n" \ "2: " \ - : "=&r" (__tmp) \ + : "=&r" (__tmp), "=r" (__tmp2) \ : "b" (mem), "r" (oldval), "r" (newval) \ : "cr0", "memory"); \ __tmp != 0; \ -- cgit 1.4.1