diff options
author | Frederic Recoules <frederic.recoules@orange.fr> | 2020-03-05 19:14:31 +0100 |
---|---|---|
committer | Ivan Maidanski <ivmai@mail.ru> | 2020-03-11 23:27:29 +0300 |
commit | 3e2cb6d98d5a0d081380ca992f7685a4569fcd8f (patch) | |
tree | a2e23548e81c4bd47535bc0bb400a468f2a7ba6f /src | |
parent | bf8c33a37b4a0d5a8f04f459a972569f24dc24d3 (diff) | |
download | libatomic_ops-3e2cb6d98d5a0d081380ca992f7685a4569fcd8f.tar.gz |
Replace x86 setz instruction by asm flag output operand (gcc)
If the compiler support flag outputs, then we can get rid of setz
instruction.
* src/atomic_ops/sysdeps/gcc/x86.h [AO_DISABLE_GCC_ATOMICS
&& !AO_GENERALIZE_ASM_BOOL_CAS && !AO_USE_SYNC_CAS_BUILTIN]
(AO_compare_and_swap_full): If __GCC_ASM_FLAG_OUTPUTS__ is defined,
then define dummy local variable and store cmpxchg result to it, fill
in "result" varaible using @ccz asm specification, do not use asm setz
instruction.
* src/atomic_ops/sysdeps/gcc/x86.h [AO_GCC_ATOMIC_TEST_AND_SET
&& !AO_SKIPATOMIC_double_compare_and_swap_ANY]
(AO_compare_double_and_swap_double_full): If __GCC_ASM_FLAG_OUTPUTS__
is defined, then do not define dummy local variable, fill in "result"
variable using @ccz asm specification, do not use asm setz instruction,
specify that old_val2 and old_val1 are modified by cmpxchg8/16b
instruction.
Diffstat (limited to 'src')
-rw-r--r-- | src/atomic_ops/sysdeps/gcc/x86.h | 38 |
1 files changed, 33 insertions, 5 deletions
diff --git a/src/atomic_ops/sysdeps/gcc/x86.h b/src/atomic_ops/sysdeps/gcc/x86.h index b9003ce..e34f649 100644 --- a/src/atomic_ops/sysdeps/gcc/x86.h +++ b/src/atomic_ops/sysdeps/gcc/x86.h @@ -282,10 +282,19 @@ AO_test_and_set_full(volatile AO_TS_t *addr) /* variables are protected. */ # else char result; - __asm__ __volatile__ ("lock; cmpxchg %2, %0; setz %1" +# if defined(__GCC_ASM_FLAG_OUTPUTS__) + AO_t dummy; + + __asm__ __volatile__ ("lock; cmpxchg %3, %0" + : "+m" (*addr), "=@ccz" (result), "=a" (dummy) + : "r" (new_val), "a" (old) + : "memory"); +# else + __asm__ __volatile__ ("lock; cmpxchg %2, %0; setz %1" : "+m" (*addr), "=a" (result) : "r" (new_val), "a" (old) : "memory"); +# endif return (int)result; # endif } @@ -457,10 +466,10 @@ AO_fetch_compare_and_swap_full(volatile AO_t *addr, AO_t old_val, AO_t old_val1, AO_t old_val2, AO_t new_val1, AO_t new_val2) { - AO_t dummy; /* an output for clobbered edx */ char result; # if defined(__PIC__) && !(AO_GNUC_PREREQ(5, 1) || AO_CLANG_PREREQ(4, 0)) AO_t saved_ebx; + AO_t dummy; /* The following applies to an ancient GCC (and, probably, it was */ /* never needed for Clang): */ @@ -509,11 +518,21 @@ AO_fetch_compare_and_swap_full(volatile AO_t *addr, AO_t old_val, /* register, instead of using a fixed register, is implemented */ /* in Clang and GCC 5.1+, at least. (Older GCC refused to compile */ /* such code for PIC mode). */ - __asm__ __volatile__ ("lock; cmpxchg8b %0; setz %1" +# if defined(__GCC_ASM_FLAG_OUTPUTS__) + __asm__ __volatile__ ("lock; cmpxchg8b %0" + : "+m" (*addr), "=@ccz" (result), + "+d" (old_val2), "+a" (old_val1) + : "c" (new_val2), "b" (new_val1) + : "memory"); +# else + AO_t dummy; /* an output for clobbered edx */ + + __asm__ __volatile__ ("lock; cmpxchg8b %0; setz %1" : "+m" (*addr), "=a" (result), "=d" (dummy) : "d" (old_val2), "a" (old_val1), "c" (new_val2), "b" (new_val1) : "memory"); +# endif # endif return (int) result; } @@ -574,14 +593,23 @@ AO_fetch_compare_and_swap_full(volatile AO_t *addr, AO_t old_val, AO_t old_val1, AO_t old_val2, AO_t new_val1, AO_t new_val2) { - AO_t dummy; /* an output for clobbered rdx */ char result; - __asm__ __volatile__("lock; cmpxchg16b %0; setz %1" +# if defined(__GCC_ASM_FLAG_OUTPUTS__) + __asm__ __volatile__("lock; cmpxchg16b %0" + : "+m" (*addr), "=@ccz" (result), + "+d" (old_val2), "+a" (old_val1) + : "c" (new_val2), "b" (new_val1) + : "memory"); +# else + AO_t dummy; /* an output for clobbered rdx */ + + __asm__ __volatile__("lock; cmpxchg16b %0; setz %1" : "+m" (*addr), "=a" (result), "=d" (dummy) : "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 |