summaryrefslogtreecommitdiff
path: root/boost/atomic/detail/ops_gcc_x86_dcas.hpp
diff options
context:
space:
mode:
Diffstat (limited to 'boost/atomic/detail/ops_gcc_x86_dcas.hpp')
-rw-r--r--boost/atomic/detail/ops_gcc_x86_dcas.hpp64
1 files changed, 56 insertions, 8 deletions
diff --git a/boost/atomic/detail/ops_gcc_x86_dcas.hpp b/boost/atomic/detail/ops_gcc_x86_dcas.hpp
index 7f3962199a..28cbc225e3 100644
--- a/boost/atomic/detail/ops_gcc_x86_dcas.hpp
+++ b/boost/atomic/detail/ops_gcc_x86_dcas.hpp
@@ -204,11 +204,14 @@ struct gcc_dcas_x86
storage_type volatile& storage, storage_type& expected, storage_type desired, memory_order, memory_order) BOOST_NOEXCEPT
{
#if defined(__clang__)
+
// Clang cannot allocate eax:edx register pairs but it has sync intrinsics
storage_type old_expected = expected;
expected = __sync_val_compare_and_swap(&storage, old_expected, desired);
return expected == old_expected;
+
#elif defined(__PIC__)
+
// Make sure ebx is saved and restored properly in case
// of position independent code. To make this work
// setup register constraints such that ebx can not be
@@ -222,25 +225,50 @@ struct gcc_dcas_x86
uint32_t scratch;
bool success;
+#if defined(BOOST_ATOMIC_DETAIL_ASM_HAS_FLAG_OUTPUTS)
__asm__ __volatile__
(
"movl %%ebx, %[scratch]\n\t"
"movl %[desired_lo], %%ebx\n\t"
- "lock; cmpxchg8b %[dest]\n\t"
+ "lock; cmpxchg8b (%[dest])\n\t"
+ "movl %[scratch], %%ebx\n\t"
+ : "+A" (expected), [scratch] "=m" (scratch), [success] "=@ccz" (success)
+ : [desired_lo] "Sm" ((uint32_t)desired), "c" ((uint32_t)(desired >> 32)), [dest] "D" (&storage)
+ : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC_COMMA "memory"
+ );
+#else // defined(BOOST_ATOMIC_DETAIL_ASM_HAS_FLAG_OUTPUTS)
+ __asm__ __volatile__
+ (
+ "movl %%ebx, %[scratch]\n\t"
+ "movl %[desired_lo], %%ebx\n\t"
+ "lock; cmpxchg8b (%[dest])\n\t"
"movl %[scratch], %%ebx\n\t"
"sete %[success]\n\t"
#if !defined(BOOST_ATOMIC_DETAIL_NO_ASM_CONSTRAINT_ALTERNATIVES)
- : "+A,A,A,A,A,A" (expected), [dest] "+m,m,m,m,m,m" (storage), [scratch] "=m,m,m,m,m,m" (scratch), [success] "=q,m,q,m,q,m" (success)
- : [desired_lo] "S,S,D,D,m,m" ((uint32_t)desired), "c,c,c,c,c,c" ((uint32_t)(desired >> 32))
+ : "+A,A,A,A,A,A" (expected), [scratch] "=m,m,m,m,m,m" (scratch), [success] "=q,m,q,m,q,m" (success)
+ : [desired_lo] "S,S,D,D,m,m" ((uint32_t)desired), "c,c,c,c,c,c" ((uint32_t)(desired >> 32)), [dest] "D,D,S,S,D,D" (&storage)
#else
- : "+A" (expected), [dest] "+m" (storage), [scratch] "=m" (scratch), [success] "=q" (success)
- : [desired_lo] "S" ((uint32_t)desired), "c" ((uint32_t)(desired >> 32))
+ : "+A" (expected), [scratch] "=m" (scratch), [success] "=q" (success)
+ : [desired_lo] "S" ((uint32_t)desired), "c" ((uint32_t)(desired >> 32)), [dest] "D" (&storage)
#endif
: BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC_COMMA "memory"
);
+#endif // defined(BOOST_ATOMIC_DETAIL_ASM_HAS_FLAG_OUTPUTS)
+
return success;
-#else
+
+#else // defined(__PIC__)
+
bool success;
+#if defined(BOOST_ATOMIC_DETAIL_ASM_HAS_FLAG_OUTPUTS)
+ __asm__ __volatile__
+ (
+ "lock; cmpxchg8b %[dest]\n\t"
+ : "+A" (expected), [dest] "+m" (storage), [success] "=@ccz" (success)
+ : "b" ((uint32_t)desired), "c" ((uint32_t)(desired >> 32))
+ : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC_COMMA "memory"
+ );
+#else // defined(BOOST_ATOMIC_DETAIL_ASM_HAS_FLAG_OUTPUTS)
__asm__ __volatile__
(
"lock; cmpxchg8b %[dest]\n\t"
@@ -254,8 +282,11 @@ struct gcc_dcas_x86
#endif
: BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC_COMMA "memory"
);
+#endif // defined(BOOST_ATOMIC_DETAIL_ASM_HAS_FLAG_OUTPUTS)
+
return success;
-#endif
+
+#endif // defined(__PIC__)
}
static BOOST_FORCEINLINE bool compare_exchange_weak(
@@ -461,11 +492,14 @@ struct gcc_dcas_x86_64
storage_type volatile& storage, storage_type& expected, storage_type desired, memory_order, memory_order) BOOST_NOEXCEPT
{
#if defined(__clang__)
+
// Clang cannot allocate rax:rdx register pairs but it has sync intrinsics
storage_type old_expected = expected;
expected = __sync_val_compare_and_swap(&storage, old_expected, desired);
return expected == old_expected;
+
#elif defined(BOOST_ATOMIC_DETAIL_NO_ASM_RAX_RDX_PAIRS)
+
// GCC 4.4 can't allocate rax:rdx register pair either but it also doesn't support 128-bit __sync_val_compare_and_swap
uint64_t const* p_desired = (uint64_t const*)&desired;
const uint64_t desired_lo = p_desired[0], desired_hi = p_desired[1];
@@ -499,10 +533,21 @@ struct gcc_dcas_x86_64
#endif // !defined(BOOST_ATOMIC_DETAIL_NO_ASM_IMPLIED_ZERO_DISPLACEMENTS)
return success;
+
#else // defined(BOOST_ATOMIC_DETAIL_NO_ASM_RAX_RDX_PAIRS)
+
uint64_t const* p_desired = (uint64_t const*)&desired;
const uint64_t desired_lo = p_desired[0], desired_hi = p_desired[1];
bool success;
+#if defined(BOOST_ATOMIC_DETAIL_ASM_HAS_FLAG_OUTPUTS)
+ __asm__ __volatile__
+ (
+ "lock; cmpxchg16b %[dest]\n\t"
+ : "+A" (expected), [dest] "+m" (storage), [success] "=@ccz" (success)
+ : "b" (desired_lo), "c" (desired_hi)
+ : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC_COMMA "memory"
+ );
+#else // defined(BOOST_ATOMIC_DETAIL_ASM_HAS_FLAG_OUTPUTS)
__asm__ __volatile__
(
"lock; cmpxchg16b %[dest]\n\t"
@@ -516,8 +561,11 @@ struct gcc_dcas_x86_64
#endif
: BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC_COMMA "memory"
);
+#endif // defined(BOOST_ATOMIC_DETAIL_ASM_HAS_FLAG_OUTPUTS)
+
return success;
-#endif
+
+#endif // defined(BOOST_ATOMIC_DETAIL_NO_ASM_RAX_RDX_PAIRS)
}
static BOOST_FORCEINLINE bool compare_exchange_weak(