summary refs log tree commit diff
path: root/sysdeps
diff options
context:
space:
mode:
authorUlrich Drepper <drepper@redhat.com>2004-08-25 23:24:20 +0000
committerUlrich Drepper <drepper@redhat.com>2004-08-25 23:24:20 +0000
commit8e64f8ba4e49662a1ab79e5921c1a3bfb73d888e (patch)
treea8ca7925f1e62824b5c2d6776f5cc1a30dd66022 /sysdeps
parenteffeb660b7506f735067d37e0fba39b3acf87d0b (diff)
downloadglibc-8e64f8ba4e49662a1ab79e5921c1a3bfb73d888e.tar.gz
glibc-8e64f8ba4e49662a1ab79e5921c1a3bfb73d888e.tar.xz
glibc-8e64f8ba4e49662a1ab79e5921c1a3bfb73d888e.zip
(__arch_compare_and_exchange_bool_32_acq): Fix case where oldval is negative. (__arch_compare_and_exchange_bool_32_rel): Likewise.
Diffstat (limited to 'sysdeps')
-rw-r--r--sysdeps/powerpc/powerpc64/bits/atomic.h42
1 files changed, 19 insertions, 23 deletions
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;								      \