summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorFrederic Recoules <frederic.recoules@orange.fr>2020-03-05 19:14:31 +0100
committerIvan Maidanski <ivmai@mail.ru>2020-03-11 23:27:29 +0300
commit3e2cb6d98d5a0d081380ca992f7685a4569fcd8f (patch)
treea2e23548e81c4bd47535bc0bb400a468f2a7ba6f /src
parentbf8c33a37b4a0d5a8f04f459a972569f24dc24d3 (diff)
downloadlibatomic_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.h38
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