* Imported Boehm-GC 7.1.
[cacao.git] / src / mm / boehm-gc / libatomic_ops-1.2 / src / atomic_ops / sysdeps / gcc / x86.h
index 27e047e580231adfb5666b89f66b2109c1bafd16..96fd2cb66dd2c77bf43e4784cf50b00610360441 100644 (file)
@@ -141,13 +141,30 @@ AO_compare_double_and_swap_double_full(volatile AO_double_t *addr,
                                       AO_t new_val1, AO_t new_val2) 
 {
   char result;
-  __asm__ __volatile__("lock; cmpxchg8b %0; setz %1"
+  #if __PIC__
+  /* If PIC is turned on, we can't use %ebx as it is reserved for the
+     GOT poiner.  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_val2 to %ebx */
+                      "lock; cmpxchg8b %0; setz %1;"
+                      "pop %%ebx;"     /* restore %ebx */
+                      : "=m"(*addr), "=q"(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), "=q"(result)
-                      : "m"(*addr), "d" (old_val1), "a" (old_val2),
-                        "c" (new_val1), "b" (new_val2) : "memory");
+                      : "m"(*addr), "d" (old_val2), "a" (old_val1),
+                        "c" (new_val2), "b" (new_val1) : "memory");
+  #endif
   return (int) result;
 }
 
-#define AO_HAVE_double_compare_and_swap_full
+#define AO_HAVE_compare_double_and_swap_double_full
 
 #include "../ao_t_is_int.h"