Implement compare_double_and_swap_double for SunCC/x86
authorIvan Maidanski <ivmai@mail.ru>
Wed, 5 Sep 2012 04:55:04 +0000 (08:55 +0400)
committerIvan Maidanski <ivmai@mail.ru>
Wed, 5 Sep 2012 13:14:32 +0000 (17:14 +0400)
(Tested only with Sun C 5.11 SunOS_i386.)

* src/atomic_ops/sysdeps/sunc/x86.h
(AO_compare_double_and_swap_double_full): Implement (define only if
AO_NO_CMPXCHG8B unset) using same algorithm as for gcc/x86 non-PIC.

src/atomic_ops/sysdeps/sunc/x86.h

index 45f1d4a..1b0850c 100644 (file)
@@ -162,41 +162,24 @@ AO_fetch_compare_and_swap_full(volatile AO_t *addr, AO_t old_val,
 }
 #define AO_HAVE_fetch_compare_and_swap_full
 
-#if 0
-/* FIXME: not tested (and probably wrong). Besides,     */
-/* it tickles a bug in Sun C 5.10 (when optimizing).    */
-/* Returns nonzero if the comparison succeeded. */
-/* Really requires at least a Pentium.          */
-AO_INLINE int
-AO_compare_double_and_swap_double_full(volatile AO_double_t *addr,
-                                       AO_t old_val1, AO_t old_val2,
-                                       AO_t new_val1, AO_t new_val2)
-{
-  char result;
-#if __PIC__
-  /* If PIC is turned on, we can't use %ebx as it is reserved for the
-     GOT pointer.  We can save and restore %ebx because GCC won't be
-     using it for anything else (such as any of the m operands) */
-  __asm__ __volatile__("pushl %%ebx;"   /* save ebx used for PIC GOT ptr */
-                       "movl %6,%%ebx;" /* move new_val1 to %ebx */
-                       "lock; cmpxchg8b %0; setz %1;"
-                       "pop %%ebx;"     /* restore %ebx */
-                       : "=m"(*addr), "=a"(result)
-                       : "m"(*addr), "d" (old_val2), "a" (old_val1),
-                         "c" (new_val2), "m" (new_val1) : "memory");
-#else
-  /* We can't just do the same thing in non-PIC mode, because GCC
-   * might be using %ebx as the memory operand.  We could have ifdef'd
-   * in a clobber, but there's no point doing the push/pop if we don't
-   * have to. */
-  __asm__ __volatile__("lock; cmpxchg8b %0; setz %1;"
-                       : "=m"(*addr), "=a"(result)
-                       : /* "m"(*addr), */ "d" (old_val2), "a" (old_val1),
-                         "c" (new_val2), "b" (new_val1) : "memory");
-#endif
-  return (int) result;
-}
-#define AO_HAVE_compare_double_and_swap_double_full
-#endif
+#ifndef AO_NO_CMPXCHG8B
+  /* Returns nonzero if the comparison succeeded.       */
+  /* Really requires at least a Pentium.                */
+  AO_INLINE int
+  AO_compare_double_and_swap_double_full(volatile AO_double_t *addr,
+                                         AO_t old_val1, AO_t old_val2,
+                                         AO_t new_val1, AO_t new_val2)
+  {
+    char result;
+
+    __asm__ __volatile__("lock; cmpxchg8b %0; setz %1"
+                        : "=m" (*addr), "=a" (result)
+                        : /* "m" (*addr), */ "d" (old_val2), "a" (old_val1),
+                          "c" (new_val2), "b" (new_val1)
+                        : "memory");
+    return (int) result;
+  }
+# define AO_HAVE_compare_double_and_swap_double_full
+#endif /* !AO_NO_CMPXCHG8B */
 
 #define AO_T_IS_INT