diff options
Diffstat (limited to 'src/corelib/arch/qatomic_armv6.h')
-rw-r--r-- | src/corelib/arch/qatomic_armv6.h | 132 |
1 files changed, 132 insertions, 0 deletions
diff --git a/src/corelib/arch/qatomic_armv6.h b/src/corelib/arch/qatomic_armv6.h index 6eb9a7b..28655df 100644 --- a/src/corelib/arch/qatomic_armv6.h +++ b/src/corelib/arch/qatomic_armv6.h @@ -259,6 +259,138 @@ Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndAddOrdered(qptrdiff valueTo #else // This is Q_CC_RVCT +// RVCT inline assembly documentation: +// http://www.keil.com/support/man/docs/armcc/armcc_chdcffdb.htm +// RVCT embedded assembly documentation: +// http://www.keil.com/support/man/docs/armcc/armcc_chddbeib.htm + +// save our pragma state and switch to ARM mode +#pragma push +#pragma arm + +inline bool QBasicAtomicInt::ref() +{ + register int newValue; + register int result; + retry: + __asm { + ldrex newValue, [&_q_value] + add newValue, newValue, #1 + strex result, newValue, [&_q_value] + teq result, #0 + bne retry + } + return newValue != 0; +} + +inline bool QBasicAtomicInt::deref() +{ + register int newValue; + register int result; + retry: + __asm { + ldrex newValue, [&_q_value] + sub newValue, newValue, #1 + strex result, newValue, [&_q_value] + teq result, #0 + bne retry + } + return newValue != 0; +} + +inline bool QBasicAtomicInt::testAndSetOrdered(int expectedValue, int newValue) +{ + register int result; + retry: + __asm { + ldrex result, [&_q_value] + eors result, result, expectedValue + strexeq result, newValue, [&_q_value] + teqeq result, #1 + beq retry + } + return result == 0; +} + +inline int QBasicAtomicInt::fetchAndStoreOrdered(int newValue) +{ + register int originalValue; + register int result; + retry: + __asm { + ldrex originalValue, [&_q_value] + strex result, newValue, [&_q_value] + teq result, #0 + bne retry + } + return originalValue; +} + +inline int QBasicAtomicInt::fetchAndAddOrdered(int valueToAdd) +{ + register int originalValue; + register int newValue; + register int result; + retry: + __asm { + ldrex originalValue, [&_q_value] + add newValue, originalValue, valueToAdd + strex result, newValue, [&_q_value] + teq result, #0 + bne retry + } + return originalValue; +} + +template <typename T> +Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::testAndSetOrdered(T *expectedValue, T *newValue) +{ + register T *result; + retry: + __asm { + ldrex result, [&_q_value] + eors result, result, expectedValue + strexeq result, newValue, [&_q_value] + teqeq result, #1 + beq retry + } + return result == 0; +} + +template <typename T> +Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndStoreOrdered(T *newValue) +{ + register T *originalValue; + register int result; + retry: + __asm { + ldrex originalValue, [&_q_value] + strex result, newValue, [&_q_value] + teq result, #0 + bne retry + } + return originalValue; +} + +template <typename T> +Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndAddOrdered(qptrdiff valueToAdd) +{ + register T *originalValue; + register T *newValue; + register int result; + retry: + __asm { + ldrex originalValue, [&_q_value] + add newValue, originalValue, valueToAdd * sizeof(T) + strex result, newValue, [&_q_value] + teq result, #0 + bne retry + } + return originalValue; +} + +// go back to the previous pragma state (probably Thumb mode) +#pragma pop #endif // common code |