diff options
author | hboehm <hboehm> | 2008-02-12 00:18:53 +0000 |
---|---|---|
committer | Ivan Maidanski <ivmai@mail.ru> | 2011-07-25 16:03:24 +0400 |
commit | 3bb7644ca4cd1809763b98ff69def08d297a4729 (patch) | |
tree | 68470dc35d1a9762ecb235baefe81c6061994ae7 | |
parent | 40accefecc78828c0a77803c34af7d8e457ca53a (diff) | |
download | libatomic_ops-3bb7644ca4cd1809763b98ff69def08d297a4729.tar.gz |
2008-02-11 Hans Boehm <Hans.Boehm@hp.com>gc7_1
(Really Ian Wienand & Debian maintainers)
* src/atomic_ops/sysdeps/gcc/x86.h
(AO_compare_double_and_swap_double_full): Correctly account for
ebx usage with PIC.
-rw-r--r-- | ChangeLog | 6 | ||||
-rw-r--r-- | src/atomic_ops/sysdeps/gcc/x86.h | 27 |
2 files changed, 26 insertions, 7 deletions
@@ -1,3 +1,9 @@ +2008-02-11 Hans Boehm <Hans.Boehm@hp.com> + (Really Ian Wienand & Debian maintainers) + * src/atomic_ops/sysdeps/gcc/x86.h + (AO_compare_double_and_swap_double_full): Correctly account for + ebx usage with PIC. + 2008-01-09 Hans Boehm <Hans.Boehm@hp.com> * src/atomic_ops/sysdeps/standard_ao_double_t.h: Let double_ptr_storage default to long long; define everywhere. diff --git a/src/atomic_ops/sysdeps/gcc/x86.h b/src/atomic_ops/sysdeps/gcc/x86.h index 0b344a7..96fd2cb 100644 --- a/src/atomic_ops/sysdeps/gcc/x86.h +++ b/src/atomic_ops/sysdeps/gcc/x86.h @@ -141,14 +141,27 @@ AO_compare_double_and_swap_double_full(volatile AO_double_t *addr, AO_t new_val1, AO_t new_val2) { char result; - register AO_t nv1 asm("%ebx") = new_val1; - /* The above hack seems to avoid a gcc error complaining */ - /* that ebx is unavailable. */ - - __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), "a" (old_val1), "d" (old_val2), - "b" (nv1), "c" (new_val2) : "memory"); + : "m"(*addr), "d" (old_val2), "a" (old_val1), + "c" (new_val2), "b" (new_val1) : "memory"); + #endif return (int) result; } |