It seems the last commit was not done correctly. As a result, all of the changes...
[qt:qt-iphone-clone.git] / src / corelib / arch / qatomic_armv6.h
1 /****************************************************************************
2 **
3 ** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
4 ** All rights reserved.
5 ** Contact: Nokia Corporation (qt-info@nokia.com)
6 **
7 ** This file is part of the QtCore module of the Qt Toolkit.
8 **
9 ** $QT_BEGIN_LICENSE:LGPL$
10 ** No Commercial Usage
11 ** This file contains pre-release code and may not be distributed.
12 ** You may use this file in accordance with the terms and conditions
13 ** contained in the Technology Preview License Agreement accompanying
14 ** this package.
15 **
16 ** GNU Lesser General Public License Usage
17 ** Alternatively, this file may be used under the terms of the GNU Lesser
18 ** General Public License version 2.1 as published by the Free Software
19 ** Foundation and appearing in the file LICENSE.LGPL included in the
20 ** packaging of this file.  Please review the following information to
21 ** ensure the GNU Lesser General Public License version 2.1 requirements
22 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
23 **
24 ** In addition, as a special exception, Nokia gives you certain additional
25 ** rights.  These rights are described in the Nokia Qt LGPL Exception
26 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
27 **
28 ** If you have questions regarding the use of this file, please contact
29 ** Nokia at qt-info@nokia.com.
30 **
31 **
32 **
33 **
34 **
35 **
36 **
37 **
38 ** $QT_END_LICENSE$
39 **
40 ****************************************************************************/
41
42 #ifndef QATOMIC_ARMV6_H
43 #define QATOMIC_ARMV6_H
44
45 QT_BEGIN_HEADER
46
47 QT_BEGIN_NAMESPACE
48 #define Q_ATOMIC_INT_REFERENCE_COUNTING_IS_ALWAYS_NATIVE
49
50 inline bool QBasicAtomicInt::isReferenceCountingNative()
51 { return true; }
52 inline bool QBasicAtomicInt::isReferenceCountingWaitFree()
53 { return false; }
54
55 #define Q_ATOMIC_INT_TEST_AND_SET_IS_ALWAYS_NATIVE
56
57 inline bool QBasicAtomicInt::isTestAndSetNative()
58 { return true; }
59 inline bool QBasicAtomicInt::isTestAndSetWaitFree()
60 { return false; }
61
62 #define Q_ATOMIC_INT_FETCH_AND_STORE_IS_ALWAYS_NATIVE
63
64 inline bool QBasicAtomicInt::isFetchAndStoreNative()
65 { return true; }
66 inline bool QBasicAtomicInt::isFetchAndStoreWaitFree()
67 { return false; }
68
69 #define Q_ATOMIC_INT_FETCH_AND_ADD_IS_ALWAYS_NATIVE
70
71 inline bool QBasicAtomicInt::isFetchAndAddNative()
72 { return true; }
73 inline bool QBasicAtomicInt::isFetchAndAddWaitFree()
74 { return false; }
75
76 #define Q_ATOMIC_POINTER_TEST_AND_SET_IS_ALWAYS_NATIVE
77
78 template <typename T>
79 Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::isTestAndSetNative()
80 { return true; }
81 template <typename T>
82 Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::isTestAndSetWaitFree()
83 { return false; }
84
85 #define Q_ATOMIC_POINTER_FETCH_AND_STORE_IS_ALWAYS_NATIVE
86
87 template <typename T>
88 Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::isFetchAndStoreNative()
89 { return true; }
90 template <typename T>
91 Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::isFetchAndStoreWaitFree()
92 { return false; }
93
94 #define Q_ATOMIC_POINTER_FETCH_AND_ADD_IS_ALWAYS_NATIVE
95
96 template <typename T>
97 Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::isFetchAndAddNative()
98 { return true; }
99 template <typename T>
100 Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::isFetchAndAddWaitFree()
101 { return false; }
102
103 #ifndef Q_CC_RVCT
104
105 inline bool QBasicAtomicInt::ref()
106 {
107     register int newValue;
108     register int result;
109     asm volatile("0:\n"
110                  "ldrex %[newValue], [%[_q_value]]\n"
111                  "add %[newValue], %[newValue], #1\n"
112                  "strex %[result], %[newValue], [%[_q_value]]\n"
113                  "teq %[result], #0\n"
114                  "bne 0b\n"
115                  : [newValue] "=&r" (newValue),
116                    [result] "=&r" (result),
117                    "+m" (_q_value)
118                  : [_q_value] "r" (&_q_value)
119                  : "cc", "memory");
120     return newValue != 0;
121 }
122
123 inline bool QBasicAtomicInt::deref()
124 {
125     register int newValue;
126     register int result;
127     asm volatile("0:\n"
128                  "ldrex %[newValue], [%[_q_value]]\n"
129                  "sub %[newValue], %[newValue], #1\n"
130                  "strex %[result], %[newValue], [%[_q_value]]\n"
131                  "teq %[result], #0\n"
132                  "bne 0b\n"
133                  : [newValue] "=&r" (newValue),
134                    [result] "=&r" (result),
135                    "+m" (_q_value)
136                  : [_q_value] "r" (&_q_value)
137                  : "cc", "memory");
138     return newValue != 0;
139 }
140
141 inline bool QBasicAtomicInt::testAndSetOrdered(int expectedValue, int newValue)
142 {
143     register int result;
144     asm volatile("0:\n"
145                  "ldrex %[result], [%[_q_value]]\n"
146                  "eors %[result], %[result], %[expectedValue]\n"
147 #ifdef __thumb__
148                  "itt eq\n"
149 #endif
150                  "strexeq %[result], %[newValue], [%[_q_value]]\n"
151                  "teqeq %[result], #1\n"
152                  "beq 0b\n"
153                  : [result] "=&r" (result),
154                    "+m" (_q_value)
155                  : [expectedValue] "r" (expectedValue),
156                    [newValue] "r" (newValue),
157                    [_q_value] "r" (&_q_value)
158                  : "cc", "memory");
159     return result == 0;
160 }
161
162 inline int QBasicAtomicInt::fetchAndStoreOrdered(int newValue)
163 {
164     register int originalValue;
165     register int result;
166     asm volatile("0:\n"
167                  "ldrex %[originalValue], [%[_q_value]]\n"
168                  "strex %[result], %[newValue], [%[_q_value]]\n"
169                  "teq %[result], #0\n"
170                  "bne 0b\n"
171                  : [originalValue] "=&r" (originalValue),
172                    [result] "=&r" (result),
173                    "+m" (_q_value)
174                  : [newValue] "r" (newValue),
175                    [_q_value] "r" (&_q_value)
176                  : "cc", "memory");
177     return originalValue;
178 }
179
180 inline int QBasicAtomicInt::fetchAndAddOrdered(int valueToAdd)
181 {
182     register int originalValue;
183     register int newValue;
184     register int result;
185     asm volatile("0:\n"
186                  "ldrex %[originalValue], [%[_q_value]]\n"
187                  "add %[newValue], %[originalValue], %[valueToAdd]\n"
188                  "strex %[result], %[newValue], [%[_q_value]]\n"
189                  "teq %[result], #0\n"
190                  "bne 0b\n"
191                  : [originalValue] "=&r" (originalValue),
192                    [newValue] "=&r" (newValue),
193                    [result] "=&r" (result),
194                    "+m" (_q_value)
195                  : [valueToAdd] "r" (valueToAdd),
196                    [_q_value] "r" (&_q_value)
197                  : "cc", "memory");
198     return originalValue;
199 }
200
201 template <typename T>
202 Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::testAndSetOrdered(T *expectedValue, T *newValue)
203 {
204     register T *result;
205     asm volatile("0:\n"
206                  "ldrex %[result], [%[_q_value]]\n"
207                  "eors %[result], %[result], %[expectedValue]\n"
208 #ifdef __thumb__
209                  "itt eq\n"
210 #endif
211                  "strexeq %[result], %[newValue], [%[_q_value]]\n"
212                  "teqeq %[result], #1\n"
213                  "beq 0b\n"
214                  : [result] "=&r" (result),
215                    "+m" (_q_value)
216                  : [expectedValue] "r" (expectedValue),
217                    [newValue] "r" (newValue),
218                    [_q_value] "r" (&_q_value)
219                  : "cc", "memory");
220     return result == 0;
221 }
222
223 template <typename T>
224 Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndStoreOrdered(T *newValue)
225 {
226     register T *originalValue;
227     register int result;
228     asm volatile("0:\n"
229                  "ldrex %[originalValue], [%[_q_value]]\n"
230                  "strex %[result], %[newValue], [%[_q_value]]\n"
231                  "teq %[result], #0\n"
232                  "bne 0b\n"
233                  : [originalValue] "=&r" (originalValue),
234                    [result] "=&r" (result),
235                    "+m" (_q_value)
236                  : [newValue] "r" (newValue),
237                    [_q_value] "r" (&_q_value)
238                  : "cc", "memory");
239     return originalValue;
240 }
241
242 template <typename T>
243 Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndAddOrdered(qptrdiff valueToAdd)
244 {
245     register T *originalValue;
246     register T *newValue;
247     register int result;
248     asm volatile("0:\n"
249                  "ldrex %[originalValue], [%[_q_value]]\n"
250                  "add %[newValue], %[originalValue], %[valueToAdd]\n"
251                  "strex %[result], %[newValue], [%[_q_value]]\n"
252                  "teq %[result], #0\n"
253                  "bne 0b\n"
254                  : [originalValue] "=&r" (originalValue),
255                    [newValue] "=&r" (newValue),
256                    [result] "=&r" (result),
257                    "+m" (_q_value)
258                  : [valueToAdd] "r" (valueToAdd * sizeof(T)),
259                    [_q_value] "r" (&_q_value)
260                  : "cc", "memory");
261     return originalValue;
262 }
263
264 #else
265 // This is Q_CC_RVCT
266
267 // RVCT inline assembly documentation:
268 // http://www.keil.com/support/man/docs/armcc/armcc_chdcffdb.htm
269 // RVCT embedded assembly documentation:
270 // http://www.keil.com/support/man/docs/armcc/armcc_chddbeib.htm
271
272 // save our pragma state and switch to ARM mode
273 #pragma push
274 #pragma arm
275
276 inline bool QBasicAtomicInt::ref()
277 {
278     register int newValue;
279     register int result;
280     retry:
281     __asm {
282         ldrex   newValue, [&_q_value]
283         add     newValue, newValue, #1
284         strex   result, newValue, [&_q_value]
285         teq     result, #0
286         bne     retry
287     }
288     return newValue != 0;
289 }
290
291 inline bool QBasicAtomicInt::deref()
292 {
293     register int newValue;
294     register int result;
295     retry:
296     __asm {
297         ldrex   newValue, [&_q_value]
298         sub     newValue, newValue, #1
299         strex   result, newValue, [&_q_value]
300         teq     result, #0
301         bne     retry
302     }
303     return newValue != 0;
304 }
305
306 inline bool QBasicAtomicInt::testAndSetOrdered(int expectedValue, int newValue)
307 {
308     register int result;
309     retry:
310     __asm {
311         ldrex   result, [&_q_value]
312         eors    result, result, expectedValue
313         strexeq result, newValue, [&_q_value]
314         teqeq   result, #1
315         beq     retry
316     }
317     return result == 0;
318 }
319
320 inline int QBasicAtomicInt::fetchAndStoreOrdered(int newValue)
321 {
322     register int originalValue;
323     register int result;
324     retry:
325     __asm {
326         ldrex   originalValue, [&_q_value]
327         strex   result, newValue, [&_q_value]
328         teq     result, #0
329         bne     retry
330     }
331     return originalValue;
332 }
333
334 inline int QBasicAtomicInt::fetchAndAddOrdered(int valueToAdd)
335 {
336     register int originalValue;
337     register int newValue;
338     register int result;
339     retry:
340     __asm {
341         ldrex   originalValue, [&_q_value]
342         add     newValue, originalValue, valueToAdd
343         strex   result, newValue, [&_q_value]
344         teq     result, #0
345         bne     retry
346     }
347     return originalValue;
348 }
349
350 template <typename T>
351 Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::testAndSetOrdered(T *expectedValue, T *newValue)
352 {
353     register T *result;
354     retry:
355     __asm {
356         ldrex   result, [&_q_value]
357         eors    result, result, expectedValue
358         strexeq result, newValue, [&_q_value]
359         teqeq   result, #1
360         beq     retry
361     }
362     return result == 0;
363 }
364
365 template <typename T>
366 Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndStoreOrdered(T *newValue)
367 {
368     register T *originalValue;
369     register int result;
370     retry:
371     __asm {
372         ldrex   originalValue, [&_q_value]
373         strex   result, newValue, [&_q_value]
374         teq     result, #0
375         bne     retry
376     }
377     return originalValue;
378 }
379
380 template <typename T>
381 Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndAddOrdered(qptrdiff valueToAdd)
382 {
383     register T *originalValue;
384     register T *newValue;
385     register int result;
386     retry:
387     __asm {
388         ldrex   originalValue, [&_q_value]
389         add     newValue, originalValue, valueToAdd * sizeof(T)
390         strex   result, newValue, [&_q_value]
391         teq     result, #0
392         bne     retry
393     }
394     return originalValue;
395 }
396
397 // go back to the previous pragma state (probably Thumb mode)
398 #pragma pop
399 #endif
400
401 // common code
402
403 inline bool QBasicAtomicInt::testAndSetRelaxed(int expectedValue, int newValue)
404 {
405     return testAndSetOrdered(expectedValue, newValue);
406 }
407
408 inline bool QBasicAtomicInt::testAndSetAcquire(int expectedValue, int newValue)
409 {
410     return testAndSetOrdered(expectedValue, newValue);
411 }
412
413 inline bool QBasicAtomicInt::testAndSetRelease(int expectedValue, int newValue)
414 {
415     return testAndSetOrdered(expectedValue, newValue);
416 }
417
418 inline int QBasicAtomicInt::fetchAndStoreRelaxed(int newValue)
419 {
420     return fetchAndStoreOrdered(newValue);
421 }
422
423 inline int QBasicAtomicInt::fetchAndStoreAcquire(int newValue)
424 {
425     return fetchAndStoreOrdered(newValue);
426 }
427
428 inline int QBasicAtomicInt::fetchAndStoreRelease(int newValue)
429 {
430     return fetchAndStoreOrdered(newValue);
431 }
432
433 inline int QBasicAtomicInt::fetchAndAddRelaxed(int valueToAdd)
434 {
435     return fetchAndAddOrdered(valueToAdd);
436 }
437
438 inline int QBasicAtomicInt::fetchAndAddAcquire(int valueToAdd)
439 {
440     return fetchAndAddOrdered(valueToAdd);
441 }
442
443 inline int QBasicAtomicInt::fetchAndAddRelease(int valueToAdd)
444 {
445     return fetchAndAddOrdered(valueToAdd);
446 }
447
448 template <typename T>
449 Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::testAndSetRelaxed(T *expectedValue, T *newValue)
450 {
451     return testAndSetOrdered(expectedValue, newValue);
452 }
453
454 template <typename T>
455 Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::testAndSetAcquire(T *expectedValue, T *newValue)
456 {
457     return testAndSetOrdered(expectedValue, newValue);
458 }
459
460 template <typename T>
461 Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::testAndSetRelease(T *expectedValue, T *newValue)
462 {
463     return testAndSetOrdered(expectedValue, newValue);
464 }
465
466 template <typename T>
467 Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndStoreRelaxed(T *newValue)
468 {
469     return fetchAndStoreOrdered(newValue);
470 }
471
472 template <typename T>
473 Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndStoreAcquire(T *newValue)
474 {
475     return fetchAndStoreOrdered(newValue);
476 }
477
478 template <typename T>
479 Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndStoreRelease(T *newValue)
480 {
481     return fetchAndStoreOrdered(newValue);
482 }
483
484 template <typename T>
485 Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndAddRelaxed(qptrdiff valueToAdd)
486 {
487     return fetchAndAddOrdered(valueToAdd);
488 }
489
490 template <typename T>
491 Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndAddAcquire(qptrdiff valueToAdd)
492 {
493     return fetchAndAddOrdered(valueToAdd);
494 }
495
496 template <typename T>
497 Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndAddRelease(qptrdiff valueToAdd)
498 {
499     return fetchAndAddOrdered(valueToAdd);
500 }
501
502 QT_END_NAMESPACE
503
504 QT_END_HEADER
505
506 #endif // QATOMIC_ARMV6_H