diff options
Diffstat (limited to 'boost/atomic/detail/ops_gcc_x86_dcas.hpp')
-rw-r--r-- | boost/atomic/detail/ops_gcc_x86_dcas.hpp | 64 |
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( |