qatomic_mips.h

Go to the documentation of this file.
00001 /****************************************************************************
00002 **
00003 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
00004 ** All rights reserved.
00005 ** Contact: Nokia Corporation (qt-info@nokia.com)
00006 **
00007 ** This file is part of the QtCore module of the Qt Toolkit.
00008 **
00009 ** $QT_BEGIN_LICENSE:LGPL$
00010 ** Commercial Usage
00011 ** Licensees holding valid Qt Commercial licenses may use this file in
00012 ** accordance with the Qt Commercial License Agreement provided with the
00013 ** Software or, alternatively, in accordance with the terms contained in
00014 ** a written agreement between you and Nokia.
00015 **
00016 ** GNU Lesser General Public License Usage
00017 ** Alternatively, this file may be used under the terms of the GNU Lesser
00018 ** General Public License version 2.1 as published by the Free Software
00019 ** Foundation and appearing in the file LICENSE.LGPL included in the
00020 ** packaging of this file.  Please review the following information to
00021 ** ensure the GNU Lesser General Public License version 2.1 requirements
00022 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
00023 **
00024 ** In addition, as a special exception, Nokia gives you certain additional
00025 ** rights.  These rights are described in the Nokia Qt LGPL Exception
00026 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this module.
00027 **
00028 ** GNU General Public License Usage
00029 ** Alternatively, this file may be used under the terms of the GNU
00030 ** General Public License version 3.0 as published by the Free Software
00031 ** Foundation and appearing in the file LICENSE.GPL included in the
00032 ** packaging of this file.  Please review the following information to
00033 ** ensure the GNU General Public License version 3.0 requirements will be
00034 ** met: http://www.gnu.org/copyleft/gpl.html.
00035 **
00036 ** If you have questions regarding the use of this file, please contact
00037 ** Nokia at qt-info@nokia.com.
00038 ** $QT_END_LICENSE$
00039 **
00040 ****************************************************************************/
00041 
00042 #ifndef QATOMIC_MIPS_H
00043 #define QATOMIC_MIPS_H
00044 
00045 QT_BEGIN_HEADER
00046 
00047 QT_BEGIN_NAMESPACE
00048 
00049 #define Q_ATOMIC_INT_REFERENCE_COUNTING_IS_ALWAYS_NATIVE
00050 
00051 inline bool QBasicAtomicInt::isReferenceCountingNative()
00052 { return true; }
00053 inline bool QBasicAtomicInt::isReferenceCountingWaitFree()
00054 { return false; }
00055 
00056 #define Q_ATOMIC_INT_TEST_AND_SET_IS_ALWAYS_NATIVE
00057 
00058 inline bool QBasicAtomicInt::isTestAndSetNative()
00059 { return true; }
00060 inline bool QBasicAtomicInt::isTestAndSetWaitFree()
00061 { return false; }
00062 
00063 #define Q_ATOMIC_INT_FETCH_AND_STORE_IS_ALWAYS_NATIVE
00064 
00065 inline bool QBasicAtomicInt::isFetchAndStoreNative()
00066 { return true; }
00067 inline bool QBasicAtomicInt::isFetchAndStoreWaitFree()
00068 { return false; }
00069 
00070 #define Q_ATOMIC_INT_FETCH_AND_ADD_IS_ALWAYS_NATIVE
00071 
00072 inline bool QBasicAtomicInt::isFetchAndAddNative()
00073 { return true; }
00074 inline bool QBasicAtomicInt::isFetchAndAddWaitFree()
00075 { return false; }
00076 
00077 #define Q_ATOMIC_POINTER_TEST_AND_SET_IS_ALWAYS_NATIVE
00078 
00079 template <typename T>
00080 Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::isTestAndSetNative()
00081 { return true; }
00082 template <typename T>
00083 Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::isTestAndSetWaitFree()
00084 { return false; }
00085 
00086 #define Q_ATOMIC_POINTER_FETCH_AND_STORE_IS_ALWAYS_NATIVE
00087 
00088 template <typename T>
00089 Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::isFetchAndStoreNative()
00090 { return true; }
00091 template <typename T>
00092 Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::isFetchAndStoreWaitFree()
00093 { return false; }
00094 
00095 #define Q_ATOMIC_POINTER_FETCH_AND_ADD_IS_ALWAYS_NATIVE
00096 
00097 template <typename T>
00098 Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::isFetchAndAddNative()
00099 { return true; }
00100 template <typename T>
00101 Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::isFetchAndAddWaitFree()
00102 { return false; }
00103 
00104 #if defined(Q_CC_GNU) && !defined(Q_OS_IRIX)
00105 
00106 #if _MIPS_SIM == _ABIO32
00107 #define SET_MIPS2 ".set mips2\n\t"
00108 #else
00109 #define SET_MIPS2
00110 #endif
00111 
00112 inline bool QBasicAtomicInt::ref()
00113 {
00114     register int originalValue;
00115     register int newValue;
00116     asm volatile(".set push\n"
00117                  SET_MIPS2
00118                  "0:\n"
00119                  "ll %[originalValue], %[_q_value]\n"
00120                  "addiu %[newValue], %[originalValue], %[one]\n"
00121                  "sc %[newValue], %[_q_value]\n"
00122                  "beqz %[newValue], 0b\n"
00123                  "nop\n"
00124                  ".set pop\n"
00125                  : [originalValue] "=&r" (originalValue),
00126                    [_q_value] "+m" (_q_value),
00127                    [newValue] "=&r" (newValue)
00128                  : [one] "i" (1)
00129                  : "cc", "memory");
00130     return originalValue != -1;
00131 }
00132 
00133 inline bool QBasicAtomicInt::deref()
00134 {
00135     register int originalValue;
00136     register int newValue;
00137     asm volatile(".set push\n"
00138                  SET_MIPS2
00139                  "0:\n"
00140                  "ll %[originalValue], %[_q_value]\n"
00141                  "addiu %[newValue], %[originalValue], %[minusOne]\n"
00142                  "sc %[newValue], %[_q_value]\n"
00143                  "beqz %[newValue], 0b\n"
00144                  "nop\n"
00145                  ".set pop\n"
00146                  : [originalValue] "=&r" (originalValue),
00147                    [_q_value] "+m" (_q_value),
00148                    [newValue] "=&r" (newValue)
00149                  : [minusOne] "i" (-1)
00150                  : "cc", "memory");
00151     return originalValue != 1;
00152 }
00153 
00154 inline bool QBasicAtomicInt::testAndSetRelaxed(int expectedValue, int newValue)
00155 {
00156     register int result;
00157     register int tempValue;
00158     asm volatile(".set push\n"
00159                  SET_MIPS2
00160                  "0:\n"
00161                  "ll %[result], %[_q_value]\n"
00162                  "xor %[result], %[result], %[expectedValue]\n"
00163                  "bnez %[result], 0f\n"
00164                  "nop\n"
00165                  "move %[tempValue], %[newValue]\n"
00166                  "sc %[tempValue], %[_q_value]\n"
00167                  "beqz %[tempValue], 0b\n"
00168                  "nop\n"
00169                  "0:\n"
00170                  ".set pop\n"
00171                  : [result] "=&r" (result),
00172                    [tempValue] "=&r" (tempValue),
00173                    [_q_value] "+m" (_q_value)
00174                  : [expectedValue] "r" (expectedValue),
00175                    [newValue] "r" (newValue)
00176                  : "cc", "memory");
00177     return result == 0;
00178 }
00179 
00180 inline bool QBasicAtomicInt::testAndSetAcquire(int expectedValue, int newValue)
00181 {
00182     register int result;
00183     register int tempValue;
00184     asm volatile(".set push\n"
00185                  SET_MIPS2
00186                  "0:\n"
00187                  "ll %[result], %[_q_value]\n"
00188                  "xor %[result], %[result], %[expectedValue]\n"
00189                  "bnez %[result], 0f\n"
00190                  "nop\n"
00191                  "move %[tempValue], %[newValue]\n"
00192                  "sc %[tempValue], %[_q_value]\n"
00193                  "beqz %[tempValue], 0b\n"
00194                  "nop\n"
00195                  "sync\n"
00196                  "0:\n"
00197                  ".set pop\n"
00198                  : [result] "=&r" (result),
00199                    [tempValue] "=&r" (tempValue),
00200                    [_q_value] "+m" (_q_value)
00201                  : [expectedValue] "r" (expectedValue),
00202                    [newValue] "r" (newValue)
00203                  : "cc", "memory");
00204     return result == 0;
00205 }
00206 
00207 inline bool QBasicAtomicInt::testAndSetRelease(int expectedValue, int newValue)
00208 {
00209     register int result;
00210     register int tempValue;
00211     asm volatile(".set push\n"
00212                  SET_MIPS2
00213                  "sync\n"
00214                  "0:\n"
00215                  "ll %[result], %[_q_value]\n"
00216                  "xor %[result], %[result], %[expectedValue]\n"
00217                  "bnez %[result], 0f\n"
00218                  "nop\n"
00219                  "move %[tempValue], %[newValue]\n"
00220                  "sc %[tempValue], %[_q_value]\n"
00221                  "beqz %[tempValue], 0b\n"
00222                  "nop\n"
00223                  "0:\n"
00224                  ".set pop\n"
00225                  : [result] "=&r" (result),
00226                    [tempValue] "=&r" (tempValue),
00227                    [_q_value] "+m" (_q_value)
00228                  : [expectedValue] "r" (expectedValue),
00229                    [newValue] "r" (newValue)
00230                  : "cc", "memory");
00231     return result == 0;
00232 }
00233 
00234 inline bool QBasicAtomicInt::testAndSetOrdered(int expectedValue, int newValue)
00235 {
00236     return testAndSetAcquire(expectedValue, newValue);
00237 }
00238 
00239 inline int QBasicAtomicInt::fetchAndStoreRelaxed(int newValue)
00240 {
00241     register int originalValue;
00242     register int tempValue;
00243     asm volatile(".set push\n"
00244                  SET_MIPS2
00245                  "0:\n"
00246                  "ll %[originalValue], %[_q_value]\n"
00247                  "move %[tempValue], %[newValue]\n"
00248                  "sc %[tempValue], %[_q_value]\n"
00249                  "beqz %[tempValue], 0b\n"
00250                  "nop\n"
00251                  ".set pop\n"
00252                  : [originalValue] "=&r" (originalValue),
00253                    [tempValue] "=&r" (tempValue),
00254                    [_q_value] "+m" (_q_value)
00255                  : [newValue] "r" (newValue)
00256                  : "cc", "memory");
00257     return originalValue;
00258 }
00259 
00260 inline int QBasicAtomicInt::fetchAndStoreAcquire(int newValue)
00261 {
00262     register int originalValue;
00263     register int tempValue;
00264     asm volatile(".set push\n"
00265                  SET_MIPS2
00266                  "0:\n"
00267                  "ll %[originalValue], %[_q_value]\n"
00268                  "move %[tempValue], %[newValue]\n"
00269                  "sc %[tempValue], %[_q_value]\n"
00270                  "beqz %[tempValue], 0b\n"
00271                  "nop\n"
00272                  "sync\n"
00273                  ".set pop\n"
00274                  : [originalValue] "=&r" (originalValue),
00275                    [tempValue] "=&r" (tempValue),
00276                    [_q_value] "+m" (_q_value)
00277                  : [newValue] "r" (newValue)
00278                  : "cc", "memory");
00279     return originalValue;
00280 }
00281 
00282 inline int QBasicAtomicInt::fetchAndStoreRelease(int newValue)
00283 {
00284     register int originalValue;
00285     register int tempValue;
00286     asm volatile(".set push\n"
00287                  SET_MIPS2
00288                  "sync\n"
00289                  "0:\n"
00290                  "ll %[originalValue], %[_q_value]\n"
00291                  "move %[tempValue], %[newValue]\n"
00292                  "sc %[tempValue], %[_q_value]\n"
00293                  "beqz %[tempValue], 0b\n"
00294                  "nop\n"
00295                  ".set pop\n"
00296                  : [originalValue] "=&r" (originalValue),
00297                    [tempValue] "=&r" (tempValue),
00298                    [_q_value] "+m" (_q_value)
00299                  : [newValue] "r" (newValue)
00300                  : "cc", "memory");
00301     return originalValue;
00302 }
00303 
00304 inline int QBasicAtomicInt::fetchAndStoreOrdered(int newValue)
00305 {
00306     return fetchAndStoreAcquire(newValue);
00307 }
00308 
00309 inline int QBasicAtomicInt::fetchAndAddRelaxed(int valueToAdd)
00310 {
00311     register int originalValue;
00312     register int newValue;
00313     asm volatile(".set push\n"
00314                  SET_MIPS2
00315                  "0:\n"
00316                  "ll %[originalValue], %[_q_value]\n"
00317                  "addu %[newValue], %[originalValue], %[valueToAdd]\n"
00318                  "sc %[newValue], %[_q_value]\n"
00319                  "beqz %[newValue], 0b\n"
00320                  "nop\n"
00321                  ".set pop\n"
00322                  : [originalValue] "=&r" (originalValue),
00323                    [_q_value] "+m" (_q_value),
00324                    [newValue] "=&r" (newValue)
00325                  : [valueToAdd] "r" (valueToAdd)
00326                  : "cc", "memory");
00327     return originalValue;
00328 }
00329 
00330 inline int QBasicAtomicInt::fetchAndAddAcquire(int valueToAdd)
00331 {
00332     register int originalValue;
00333     register int newValue;
00334     asm volatile(".set push\n"
00335                  SET_MIPS2
00336                  "0:\n"
00337                  "ll %[originalValue], %[_q_value]\n"
00338                  "addu %[newValue], %[originalValue], %[valueToAdd]\n"
00339                  "sc %[newValue], %[_q_value]\n"
00340                  "beqz %[newValue], 0b\n"
00341                  "nop\n"
00342                  "sync\n"
00343                  ".set pop\n"
00344                  : [originalValue] "=&r" (originalValue),
00345                    [_q_value] "+m" (_q_value),
00346                    [newValue] "=&r" (newValue)
00347                  : [valueToAdd] "r" (valueToAdd)
00348                  : "cc", "memory");
00349     return originalValue;
00350 }
00351 
00352 inline int QBasicAtomicInt::fetchAndAddRelease(int valueToAdd)
00353 {
00354     register int originalValue;
00355     register int newValue;
00356     asm volatile(".set push\n"
00357                  SET_MIPS2
00358                  "sync\n"
00359                  "0:\n"
00360                  "ll %[originalValue], %[_q_value]\n"
00361                  "addu %[newValue], %[originalValue], %[valueToAdd]\n"
00362                  "sc %[newValue], %[_q_value]\n"
00363                  "beqz %[newValue], 0b\n"
00364                  "nop\n"
00365                  ".set pop\n"
00366                  : [originalValue] "=&r" (originalValue),
00367                    [_q_value] "+m" (_q_value),
00368                    [newValue] "=&r" (newValue)
00369                  : [valueToAdd] "r" (valueToAdd)
00370                  : "cc", "memory");
00371     return originalValue;
00372 }
00373 
00374 inline int QBasicAtomicInt::fetchAndAddOrdered(int valueToAdd)
00375 {
00376     return fetchAndAddAcquire(valueToAdd);
00377 }
00378 
00379 #if defined(__LP64__)
00380 #  define LLP "lld"
00381 #  define SCP "scd"
00382 #else
00383 #  define LLP "ll"
00384 #  define SCP "sc"
00385 #endif
00386 
00387 template <typename T>
00388 Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::testAndSetRelaxed(T *expectedValue, T *newValue)
00389 {
00390     register T *result;
00391     register T *tempValue;
00392     asm volatile(".set push\n"
00393                  SET_MIPS2
00394                  "0:\n"
00395                  LLP" %[result], %[_q_value]\n"
00396                  "xor %[result], %[result], %[expectedValue]\n"
00397                  "bnez %[result], 0f\n"
00398                  "nop\n"
00399                  "move %[tempValue], %[newValue]\n"
00400                  SCP" %[tempValue], %[_q_value]\n"
00401                  "beqz %[tempValue], 0b\n"
00402                  "nop\n"
00403                  "0:\n"
00404                  ".set pop\n"
00405                  : [result] "=&r" (result),
00406                    [tempValue] "=&r" (tempValue),
00407                    [_q_value] "+m" (_q_value)
00408                  : [expectedValue] "r" (expectedValue),
00409                    [newValue] "r" (newValue)
00410                  : "cc", "memory");
00411     return result == 0;
00412 }
00413 
00414 template <typename T>
00415 Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::testAndSetAcquire(T *expectedValue, T *newValue)
00416 {
00417     register T *result;
00418     register T *tempValue;
00419     asm volatile(".set push\n"
00420                  SET_MIPS2
00421                  "0:\n"
00422                  LLP" %[result], %[_q_value]\n"
00423                  "xor %[result], %[result], %[expectedValue]\n"
00424                  "bnez %[result], 0f\n"
00425                  "nop\n"
00426                  "move %[tempValue], %[newValue]\n"
00427                  SCP" %[tempValue], %[_q_value]\n"
00428                  "beqz %[tempValue], 0b\n"
00429                  "nop\n"
00430                  "sync\n"
00431                  "0:\n"
00432                  ".set pop\n"
00433                  : [result] "=&r" (result),
00434                    [tempValue] "=&r" (tempValue),
00435                    [_q_value] "+m" (_q_value)
00436                  : [expectedValue] "r" (expectedValue),
00437                    [newValue] "r" (newValue)
00438                  : "cc", "memory");
00439     return result == 0;
00440 }
00441 
00442 template <typename T>
00443 Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::testAndSetRelease(T *expectedValue, T *newValue)
00444 {
00445     register T *result;
00446     register T *tempValue;
00447     asm volatile(".set push\n"
00448                  SET_MIPS2
00449                  "sync\n"
00450                  "0:\n"
00451                  LLP" %[result], %[_q_value]\n"
00452                  "xor %[result], %[result], %[expectedValue]\n"
00453                  "bnez %[result], 0f\n"
00454                  "nop\n"
00455                  "move %[tempValue], %[newValue]\n"
00456                  SCP" %[tempValue], %[_q_value]\n"
00457                  "beqz %[tempValue], 0b\n"
00458                  "nop\n"
00459                  "0:\n"
00460                  ".set pop\n"
00461                  : [result] "=&r" (result),
00462                    [tempValue] "=&r" (tempValue),
00463                    [_q_value] "+m" (_q_value)
00464                  : [expectedValue] "r" (expectedValue),
00465                    [newValue] "r" (newValue)
00466                  : "cc", "memory");
00467     return result == 0;
00468 }
00469 
00470 template <typename T>
00471 Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::testAndSetOrdered(T *expectedValue, T *newValue)
00472 {
00473     return testAndSetAcquire(expectedValue, newValue);
00474 }
00475 
00476 template <typename T>
00477 Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndStoreRelaxed(T *newValue)
00478 {
00479     register T *originalValue;
00480     register T *tempValue;
00481     asm volatile(".set push\n"
00482                  SET_MIPS2
00483                  "0:\n"
00484                  LLP" %[originalValue], %[_q_value]\n"
00485                  "move %[tempValue], %[newValue]\n"
00486                  SCP" %[tempValue], %[_q_value]\n"
00487                  "beqz %[tempValue], 0b\n"
00488                  "nop\n"
00489                  ".set pop\n"
00490                  : [originalValue] "=&r" (originalValue),
00491                    [tempValue] "=&r" (tempValue),
00492                    [_q_value] "+m" (_q_value)
00493                  : [newValue] "r" (newValue)
00494                  : "cc", "memory");
00495     return originalValue;
00496 }
00497 
00498 template <typename T>
00499 Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndStoreAcquire(T *newValue)
00500 {
00501     register T *originalValue;
00502     register T *tempValue;
00503     asm volatile(".set push\n"
00504                  SET_MIPS2
00505                  "0:\n"
00506                  LLP" %[originalValue], %[_q_value]\n"
00507                  "move %[tempValue], %[newValue]\n"
00508                  SCP" %[tempValue], %[_q_value]\n"
00509                  "beqz %[tempValue], 0b\n"
00510                  "nop\n"
00511                  "sync\n"
00512                  ".set pop\n"
00513                  : [originalValue] "=&r" (originalValue),
00514                    [tempValue] "=&r" (tempValue),
00515                    [_q_value] "+m" (_q_value)
00516                  : [newValue] "r" (newValue)
00517                  : "cc", "memory");
00518     return originalValue;
00519 }
00520 
00521 template <typename T>
00522 Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndStoreRelease(T *newValue)
00523 {
00524     register T *originalValue;
00525     register T *tempValue;
00526     asm volatile(".set push\n"
00527                  SET_MIPS2
00528                  "sync\n"
00529                  "0:\n"
00530                  LLP" %[originalValue], %[_q_value]\n"
00531                  "move %[tempValue], %[newValue]\n"
00532                  SCP" %[tempValue], %[_q_value]\n"
00533                  "beqz %[tempValue], 0b\n"
00534                  "nop\n"
00535                  ".set pop\n"
00536                  : [originalValue] "=&r" (originalValue),
00537                    [tempValue] "=&r" (tempValue),
00538                    [_q_value] "+m" (_q_value)
00539                  : [newValue] "r" (newValue)
00540                  : "cc", "memory");
00541     return originalValue;
00542 }
00543 
00544 template <typename T>
00545 Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndStoreOrdered(T *newValue)
00546 {
00547     return fetchAndStoreAcquire(newValue);
00548 }
00549 
00550 template <typename T>
00551 Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndAddRelaxed(qptrdiff valueToAdd)
00552 {
00553     register T *originalValue;
00554     register T *newValue;
00555     asm volatile(".set push\n"
00556                  SET_MIPS2
00557                  "0:\n"
00558                  LLP" %[originalValue], %[_q_value]\n"
00559                  "addu %[newValue], %[originalValue], %[valueToAdd]\n"
00560                  SCP" %[newValue], %[_q_value]\n"
00561                  "beqz %[newValue], 0b\n"
00562                  "nop\n"
00563                  ".set pop\n"
00564                  : [originalValue] "=&r" (originalValue),
00565                    [_q_value] "+m" (_q_value),
00566                    [newValue] "=&r" (newValue)
00567                  : [valueToAdd] "r" (valueToAdd * sizeof(T))
00568                  : "cc", "memory");
00569     return originalValue;
00570 }
00571 
00572 template <typename T>
00573 Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndAddAcquire(qptrdiff valueToAdd)
00574 {
00575     register T *originalValue;
00576     register T *newValue;
00577     asm volatile(".set push\n"
00578                  SET_MIPS2
00579                  "0:\n"
00580                  LLP" %[originalValue], %[_q_value]\n"
00581                  "addu %[newValue], %[originalValue], %[valueToAdd]\n"
00582                  SCP" %[newValue], %[_q_value]\n"
00583                  "beqz %[newValue], 0b\n"
00584                  "nop\n"
00585                  "sync\n"
00586                  ".set pop\n"
00587                  : [originalValue] "=&r" (originalValue),
00588                    [_q_value] "+m" (_q_value),
00589                    [newValue] "=&r" (newValue)
00590                  : [valueToAdd] "r" (valueToAdd * sizeof(T))
00591                  : "cc", "memory");
00592     return originalValue;
00593 }
00594 
00595 template <typename T>
00596 Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndAddRelease(qptrdiff valueToAdd)
00597 {
00598     register T *originalValue;
00599     register T *newValue;
00600     asm volatile(".set push\n"
00601                  SET_MIPS2
00602                  "sync\n"
00603                  "0:\n"
00604                  LLP" %[originalValue], %[_q_value]\n"
00605                  "addu %[newValue], %[originalValue], %[valueToAdd]\n"
00606                  SCP" %[newValue], %[_q_value]\n"
00607                  "beqz %[newValue], 0b\n"
00608                  "nop\n"
00609                  ".set pop\n"
00610                  : [originalValue] "=&r" (originalValue),
00611                    [_q_value] "+m" (_q_value),
00612                    [newValue] "=&r" (newValue)
00613                  : [valueToAdd] "r" (valueToAdd * sizeof(T))
00614                  : "cc", "memory");
00615     return originalValue;
00616 }
00617 
00618 template <typename T>
00619 Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndAddOrdered(qptrdiff valueToAdd)
00620 {
00621     return fetchAndAddAcquire(valueToAdd);
00622 }
00623 
00624 #else // !Q_CC_GNU
00625 
00626 extern "C" {
00627     Q_CORE_EXPORT int q_atomic_test_and_set_int(volatile int *ptr, int expected, int newval);
00628     Q_CORE_EXPORT int q_atomic_test_and_set_acquire_int(volatile int *ptr, int expected, int newval);
00629     Q_CORE_EXPORT int q_atomic_test_and_set_release_int(volatile int *ptr, int expected, int newval);
00630     Q_CORE_EXPORT int q_atomic_test_and_set_ptr(volatile void *ptr, void *expected, void *newval);
00631     Q_CORE_EXPORT int q_atomic_test_and_set_acquire_ptr(volatile void *ptr, void *expected, void *newval);
00632     Q_CORE_EXPORT int q_atomic_test_and_set_release_ptr(volatile void *ptr, void *expected, void *newval);
00633 } // extern "C"
00634 
00635 inline bool QBasicAtomicInt::ref()
00636 {
00637     register int expected;
00638     for (;;) {
00639         expected = _q_value;
00640         if (q_atomic_test_and_set_int(&_q_value, expected, expected + 1))
00641             break;
00642     }
00643     return expected != -1;
00644 }
00645 
00646 inline bool QBasicAtomicInt::deref()
00647 {
00648     register int expected;
00649     for (;;) {
00650         expected = _q_value;
00651         if (q_atomic_test_and_set_int(&_q_value, expected, expected - 1))
00652             break;
00653     }
00654     return expected != 1;
00655 }
00656 
00657 inline bool QBasicAtomicInt::testAndSetRelaxed(int expectedValue, int newValue)
00658 {
00659     return q_atomic_test_and_set_int(&_q_value, expectedValue, newValue) != 0;
00660 }
00661 
00662 inline bool QBasicAtomicInt::testAndSetAcquire(int expectedValue, int newValue)
00663 {
00664     return q_atomic_test_and_set_acquire_int(&_q_value, expectedValue, newValue) != 0;
00665 }
00666 
00667 inline bool QBasicAtomicInt::testAndSetRelease(int expectedValue, int newValue)
00668 {
00669     return q_atomic_test_and_set_release_int(&_q_value, expectedValue, newValue) != 0;
00670 }
00671 
00672 inline bool QBasicAtomicInt::testAndSetOrdered(int expectedValue, int newValue)
00673 {
00674     return q_atomic_test_and_set_acquire_int(&_q_value, expectedValue, newValue) != 0;
00675 }
00676 
00677 inline int QBasicAtomicInt::fetchAndStoreRelaxed(int newValue)
00678 {
00679     int returnValue;
00680     for (;;) {
00681         returnValue = _q_value;
00682         if (testAndSetRelaxed(returnValue, newValue))
00683             break;
00684     }
00685     return returnValue;
00686 }
00687 
00688 inline int QBasicAtomicInt::fetchAndStoreAcquire(int newValue)
00689 {
00690     int returnValue;
00691     for (;;) {
00692         returnValue = _q_value;
00693         if (testAndSetAcquire(returnValue, newValue))
00694             break;
00695     }
00696     return returnValue;
00697 }
00698 
00699 inline int QBasicAtomicInt::fetchAndStoreRelease(int newValue)
00700 {
00701     int returnValue;
00702     for (;;) {
00703         returnValue = _q_value;
00704         if (testAndSetRelease(returnValue, newValue))
00705             break;
00706     }
00707     return returnValue;
00708 }
00709 
00710 inline int QBasicAtomicInt::fetchAndStoreOrdered(int newValue)
00711 {
00712     int returnValue;
00713     for (;;) {
00714         returnValue = _q_value;
00715         if (testAndSetOrdered(returnValue, newValue))
00716             break;
00717     }
00718     return returnValue;
00719 }
00720 
00721 inline int QBasicAtomicInt::fetchAndAddRelaxed(int valueToAdd)
00722 {
00723     int returnValue;
00724     for (;;) {
00725         returnValue = _q_value;
00726         if (testAndSetRelaxed(returnValue, returnValue + valueToAdd))
00727             break;
00728     }
00729     return returnValue;
00730 }
00731 
00732 inline int QBasicAtomicInt::fetchAndAddAcquire(int valueToAdd)
00733 {
00734     int returnValue;
00735     for (;;) {
00736         returnValue = _q_value;
00737         if (testAndSetAcquire(returnValue, returnValue + valueToAdd))
00738             break;
00739     }
00740     return returnValue;
00741 }
00742 
00743 inline int QBasicAtomicInt::fetchAndAddRelease(int valueToAdd)
00744 {
00745     int returnValue;
00746     for (;;) {
00747         returnValue = _q_value;
00748         if (testAndSetRelease(returnValue, returnValue + valueToAdd))
00749             break;
00750     }
00751     return returnValue;
00752 }
00753 
00754 inline int QBasicAtomicInt::fetchAndAddOrdered(int valueToAdd)
00755 {
00756     int returnValue;
00757     for (;;) {
00758         returnValue = _q_value;
00759         if (testAndSetOrdered(returnValue, returnValue + valueToAdd))
00760             break;
00761     }
00762     return returnValue;
00763 }
00764 
00765 template <typename T>
00766 Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::testAndSetRelaxed(T *expectedValue, T *newValue)
00767 {
00768     return q_atomic_test_and_set_ptr(&_q_value, expectedValue, newValue) != 0;
00769 }
00770 
00771 template <typename T>
00772 Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::testAndSetAcquire(T *expectedValue, T *newValue)
00773 {
00774     return q_atomic_test_and_set_acquire_ptr(&_q_value, expectedValue, newValue) != 0;
00775 }
00776 
00777 template <typename T>
00778 Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::testAndSetRelease(T *expectedValue, T *newValue)
00779 {
00780     return q_atomic_test_and_set_release_ptr(&_q_value, expectedValue, newValue) != 0;
00781 }
00782 
00783 template <typename T>
00784 Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::testAndSetOrdered(T *expectedValue, T *newValue)
00785 {
00786     return q_atomic_test_and_set_acquire_ptr(&_q_value, expectedValue, newValue) != 0;
00787 }
00788 
00789 template <typename T>
00790 Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndStoreRelaxed(T *newValue)
00791 {
00792     T *returnValue;
00793     for (;;) {
00794         returnValue = (_q_value);
00795         if (testAndSetRelaxed(returnValue, newValue))
00796             break;
00797     }
00798     return returnValue;
00799 }
00800 
00801 template <typename T>
00802 Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndStoreAcquire(T *newValue)
00803 {
00804     T *returnValue;
00805     for (;;) {
00806         returnValue = (_q_value);
00807         if (testAndSetAcquire(returnValue, newValue))
00808             break;
00809     }
00810     return returnValue;
00811 }
00812 
00813 template <typename T>
00814 Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndStoreRelease(T *newValue)
00815 {
00816     T *returnValue;
00817     for (;;) {
00818         returnValue = (_q_value);
00819         if (testAndSetRelease(returnValue, newValue))
00820             break;
00821     }
00822     return returnValue;
00823 }
00824 
00825 template <typename T>
00826 Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndStoreOrdered(T *newValue)
00827 {
00828     T *returnValue;
00829     for (;;) {
00830         returnValue = (_q_value);
00831         if (testAndSetOrdered(returnValue, newValue))
00832             break;
00833     }
00834     return returnValue;
00835 }
00836 
00837 template <typename T>
00838 Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndAddRelaxed(qptrdiff valueToAdd)
00839 {
00840     T *returnValue;
00841     for (;;) {
00842         returnValue = (_q_value);
00843         if (testAndSetRelaxed(returnValue, returnValue + valueToAdd))
00844             break;
00845     }
00846     return returnValue;
00847 }
00848 
00849 template <typename T>
00850 Q_INLINE_TEMPLATE
00851 T *QBasicAtomicPointer<T>::fetchAndAddAcquire(qptrdiff valueToAdd)
00852 {
00853     T *returnValue;
00854     for (;;) {
00855         returnValue = (_q_value);
00856         if (testAndSetAcquire(returnValue, returnValue + valueToAdd))
00857             break;
00858     }
00859     return returnValue;
00860 }
00861 
00862 template <typename T>
00863 Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndAddRelease(qptrdiff valueToAdd)
00864 {
00865     T *returnValue;
00866     for (;;) {
00867         returnValue = (_q_value);
00868         if (testAndSetRelease(returnValue, returnValue + valueToAdd))
00869             break;
00870     }
00871     return returnValue;
00872 }
00873 
00874 template <typename T>
00875 Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndAddOrdered(qptrdiff valueToAdd)
00876 {
00877     T *returnValue;
00878     for (;;) {
00879         returnValue = (_q_value);
00880         if (testAndSetOrdered(returnValue, returnValue + valueToAdd))
00881             break;
00882     }
00883     return returnValue;
00884 }
00885 
00886 #endif // Q_CC_GNU
00887 
00888 QT_END_NAMESPACE
00889 
00890 QT_END_HEADER
00891 
00892 #endif // QATOMIC_MIPS_H