From aafe40ab62e78405cfafb5549fb4d11e01956190 Mon Sep 17 00:00:00 2001 From: Ivan Maidanski Date: Wed, 7 Mar 2012 19:12:49 +0400 Subject: Fix AO_compare_double_and_swap_double_full for gcc/x86 (PIC mode) * 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 | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/src/atomic_ops/sysdeps/gcc/x86.h b/src/atomic_ops/sysdeps/gcc/x86.h index f3560b0..df02a46 100644 --- a/src/atomic_ops/sysdeps/gcc/x86.h +++ b/src/atomic_ops/sysdeps/gcc/x86.h @@ -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 -- cgit v1.2.1