From 6813a21c522631e5388b2cbf3f8e4e273b0d27ce Mon Sep 17 00:00:00 2001 From: Eskil Abrahamsen Blomfeldt Date: Mon, 24 Feb 2014 14:05:58 +0100 Subject: Fix compilation on armv5 Two changes broke compilation on armv5, where we're currently not CI-testing: 634f82f1f1fda7983abf70b58e43c580b1f01df0 changed the signature in a function definition without changing its declaration, while it was actually intending to add this as a new overload. bfe0db6fbea6376dbe395af6d76995a54bbc3b49 added an #error condition without fixing compilation on armv5. I don't know if the fix is correct, but at least it compiles. Task-number: QTBUG-37034 Change-Id: If99142fafb9bd55afc20b17f8b3cce5ee0ffec13 Reviewed-by: Thiago Macieira --- src/corelib/arch/qatomic_armv5.h | 14 ++++++++++++++ 1 file changed, 14 insertions(+) (limited to 'src/corelib/arch') diff --git a/src/corelib/arch/qatomic_armv5.h b/src/corelib/arch/qatomic_armv5.h index 6939650c54..253b9263de 100644 --- a/src/corelib/arch/qatomic_armv5.h +++ b/src/corelib/arch/qatomic_armv5.h @@ -54,6 +54,7 @@ QT_END_NAMESPACE #pragma qt_sync_stop_processing #endif +#define Q_ATOMIC_INT32_IS_SUPPORTED #define Q_ATOMIC_INT_REFERENCE_COUNTING_IS_NOT_NATIVE #define Q_ATOMIC_INT_TEST_AND_SET_IS_NOT_NATIVE #define Q_ATOMIC_INT_FETCH_AND_STORE_IS_ALWAYS_NATIVE @@ -98,6 +99,7 @@ template struct QBasicAtomicOps: QGenericAtomicOps static bool testAndSetRelaxed(T &_q_value, T expectedValue, T newValue) Q_DECL_NOTHROW; + template static bool testAndSetRelaxed(T &_q_value, T expectedValue, T newValue, T *currentValue) Q_DECL_NOTHROW; template static T fetchAndStoreRelaxed(T &_q_value, T newValue) Q_DECL_NOTHROW; template static T fetchAndAddRelaxed(T &_q_value, typename QAtomicAdditiveType::AdditiveT valueToAdd) Q_DECL_NOTHROW; @@ -132,6 +134,18 @@ bool QBasicAtomicOps<4>::deref(T &_q_value) Q_DECL_NOTHROW return newValue != 0; } +template<> template inline +bool QBasicAtomicOps<4>::testAndSetRelaxed(T &_q_value, T expectedValue, T newValue) Q_DECL_NOTHROW +{ + T originalValue; + do { + originalValue = _q_value; + if (originalValue != expectedValue) + return false; + } while (_q_cmpxchg(expectedValue, newValue, &_q_value) != 0); + return true; +} + template<> template inline bool QBasicAtomicOps<4>::testAndSetRelaxed(T &_q_value, T expectedValue, T newValue, T *currentValue) Q_DECL_NOTHROW { -- cgit v1.2.3 From c8cde619a5f53521c86114cec64b9dbe73e6fa55 Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Mon, 24 Feb 2014 16:21:02 -0800 Subject: Fix ARM atomics for 8- and 16-bit types This has apparently never worked for any negative value. That's because the compiler sign-extends the incoming expectedValue to fill the 32-bit register, instead of zero-extending it, and it also expects any returned values to also be sign-extended. Task-number: QTBUG-37031 Change-Id: I836eddba7b1acc56bb0ac1d41de7001d06255b9b Reviewed-by: Sergio Ahumada --- src/corelib/arch/qatomic_armv6.h | 54 ++++++++++++++++++++++++++++++++-------- 1 file changed, 44 insertions(+), 10 deletions(-) (limited to 'src/corelib/arch') diff --git a/src/corelib/arch/qatomic_armv6.h b/src/corelib/arch/qatomic_armv6.h index 4f1c758ded..31a06541ed 100644 --- a/src/corelib/arch/qatomic_armv6.h +++ b/src/corelib/arch/qatomic_armv6.h @@ -90,6 +90,10 @@ template struct QBasicAtomicOps: QGenericAtomicOps static T fetchAndAddRelaxed(T &_q_value, typename QAtomicAdditiveType::AdditiveT valueToAdd) Q_DECL_NOTHROW; + +private: + template static inline T shrinkFrom32Bit(T value); + template static inline T extendTo32Bit(T value); }; template struct QAtomicOps : QBasicAtomicOps @@ -257,6 +261,36 @@ template<> struct QAtomicOpsSupport<8> { enum { IsSupported = 1 }; }; #define Q_ATOMIC_INT64_FETCH_AND_STORE_IS_ALWAYS_NATIVE #define Q_ATOMIC_INT64_FETCH_AND_ADD_IS_ALWAYS_NATIVE +// note: if T is signed, parameters are passed sign-extended in the +// registers. However, our 8- and 16-bit operations don't do sign +// extension. So we need to clear out the input on entry and sign-extend again +// on exit. +template template +T QBasicAtomicOps::shrinkFrom32Bit(T value) +{ + Q_STATIC_ASSERT(Size == 1 || Size == 2); + if (T(-1) > T(0)) + return value; // unsigned, ABI will zero extend + if (Size == 1) + asm volatile("and %0, %0, %1" : "+r" (value) : "I" (0xff)); + else + asm volatile("and %0, %0, %1" : "+r" (value) : "r" (0xffff)); + return value; +} + +template template +T QBasicAtomicOps::extendTo32Bit(T value) +{ + Q_STATIC_ASSERT(Size == 1 || Size == 2); + if (T(-1) > T(0)) + return value; // unsigned, ABI will zero extend + if (Size == 1) + asm volatile("sxtb %0, %0" : "+r" (value)); + else + asm volatile("sxth %0, %0" : "+r" (value)); + return value; +} + template<> template inline bool QBasicAtomicOps<1>::ref(T &_q_value) Q_DECL_NOTHROW { @@ -308,7 +342,7 @@ bool QBasicAtomicOps<1>::testAndSetRelaxed(T &_q_value, T expectedValue, T newVa "beq 0b\n" : [result] "=&r" (result), "+m" (_q_value) - : [expectedValue] "r" (expectedValue), + : [expectedValue] "r" (shrinkFrom32Bit(expectedValue)), [newValue] "r" (newValue), [_q_value] "r" (&_q_value) : "cc"); @@ -330,11 +364,11 @@ bool QBasicAtomicOps<1>::testAndSetRelaxed(T &_q_value, T expectedValue, T newVa : [result] "=&r" (result), [tempValue] "=&r" (tempValue), "+m" (_q_value) - : [expectedValue] "r" (expectedValue), + : [expectedValue] "r" (shrinkFrom32Bit(expectedValue)), [newValue] "r" (newValue), [_q_value] "r" (&_q_value) : "cc"); - *currentValue = tempValue; + *currentValue = extendTo32Bit(tempValue); return result == 0; } @@ -354,7 +388,7 @@ T QBasicAtomicOps<1>::fetchAndStoreRelaxed(T &_q_value, T newValue) Q_DECL_NOTHR : [newValue] "r" (newValue), [_q_value] "r" (&_q_value) : "cc"); - return originalValue; + return extendTo32Bit(originalValue); } template<> template inline @@ -376,7 +410,7 @@ T QBasicAtomicOps<1>::fetchAndAddRelaxed(T &_q_value, typename QAtomicAdditiveTy : [valueToAdd] "r" (valueToAdd * QAtomicAdditiveType::AddScale), [_q_value] "r" (&_q_value) : "cc"); - return originalValue; + return extendTo32Bit(originalValue); } template<> template inline @@ -430,7 +464,7 @@ bool QBasicAtomicOps<2>::testAndSetRelaxed(T &_q_value, T expectedValue, T newVa "beq 0b\n" : [result] "=&r" (result), "+m" (_q_value) - : [expectedValue] "r" (expectedValue), + : [expectedValue] "r" (shrinkFrom32Bit(expectedValue)), [newValue] "r" (newValue), [_q_value] "r" (&_q_value) : "cc"); @@ -452,11 +486,11 @@ bool QBasicAtomicOps<2>::testAndSetRelaxed(T &_q_value, T expectedValue, T newVa : [result] "=&r" (result), [tempValue] "=&r" (tempValue), "+m" (_q_value) - : [expectedValue] "r" (expectedValue), + : [expectedValue] "r" (shrinkFrom32Bit(expectedValue)), [newValue] "r" (newValue), [_q_value] "r" (&_q_value) : "cc"); - *currentValue = tempValue; + *currentValue = extendTo32Bit(tempValue); return result == 0; } @@ -476,7 +510,7 @@ T QBasicAtomicOps<2>::fetchAndStoreRelaxed(T &_q_value, T newValue) Q_DECL_NOTHR : [newValue] "r" (newValue), [_q_value] "r" (&_q_value) : "cc"); - return originalValue; + return extendTo32Bit(originalValue); } template<> template inline @@ -498,7 +532,7 @@ T QBasicAtomicOps<2>::fetchAndAddRelaxed(T &_q_value, typename QAtomicAdditiveTy : [valueToAdd] "r" (valueToAdd * QAtomicAdditiveType::AddScale), [_q_value] "r" (&_q_value) : "cc"); - return originalValue; + return extendTo32Bit(originalValue); } // Explanation from GCC's source code (config/arm/arm.c) on the modifiers below: -- cgit v1.2.3