]> granicus.if.org Git - libatomic_ops/commitdiff
Fix AO_compare_double_and_swap_double_full for gcc/x86 (PIC mode)
authorIvan Maidanski <ivmai@mail.ru>
Wed, 7 Mar 2012 15:12:49 +0000 (19:12 +0400)
committerIvan Maidanski <ivmai@mail.ru>
Wed, 7 Mar 2012 15:37:14 +0000 (19:37 +0400)
* src/atomic_ops/sysdeps/gcc/x86.h
(AO_compare_double_and_swap_double_full): Use EDI register for
"new_val1" argument instead of a memory operand and use XCHG assembler
instruction instead of push/pop in case of PIC mode (to workaround
a bug in GCC 4.6.1); update the comment.

src/atomic_ops/sysdeps/gcc/x86.h

index f3560b09bf1023f5873d61a742c0d4b425d3448d..df02a4613ea4bb2769bbd4aee40cef96cd939148 100644 (file)
@@ -141,13 +141,16 @@ AO_compare_double_and_swap_double_full(volatile AO_double_t *addr,
   /* 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 */
+  /* We use %edi (for new_val1) instead of a memory operand and swap    */
+  /* instruction instead of push/pop because some GCC releases have     */
+  /* a bug in processing memory operands (if address base is %esp) in   */
+  /* the inline assembly after push.                                    */
+  __asm__ __volatile__("xchg %%ebx,%6;" /* swap GOT ptr and new_val1 */
                        "lock; cmpxchg8b %0; setz %1;"
-                       "pop %%ebx;"     /* restore %ebx */
+                       "xchg %%ebx,%6;" /* restore ebx and edi */
                        : "=m"(*addr), "=a"(result)
                        : "m"(*addr), "d" (old_val2), "a" (old_val1),
-                         "c" (new_val2), "m" (new_val1) : "memory");
+                         "c" (new_val2), "D" (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