gcc-ppc.hpp
Go to the documentation of this file.
00001 #ifndef BOOST_DETAIL_ATOMIC_GCC_PPC_HPP
00002 #define BOOST_DETAIL_ATOMIC_GCC_PPC_HPP
00003 
00004 //  Copyright (c) 2009 Helge Bahmann
00005 //
00006 //  Distributed under the Boost Software License, Version 1.0.
00007 //  See accompanying file LICENSE_1_0.txt or copy at
00008 //  http://www.boost.org/LICENSE_1_0.txt)
00009 
00010 #include <boost/atomic/detail/base.hpp>
00011 
00012 /*
00013         Refer to: Motorola: "Programming Environments Manual for 32-Bit
00014         Implementations of the PowerPC Architecture", Appendix E:
00015         "Synchronization Programming Examples" for an explanation of what is
00016         going on here (can be found on the web at various places by the
00017         name "MPCFPE32B.pdf", Google is your friend...)
00018         
00019         Most of the atomic operations map to instructions in a relatively
00020         straight-forward fashion, but "load"s may at first glance appear
00021         a bit strange as they map to:
00022                 
00023                         lwz %rX, addr
00024                         cmpw %rX, %rX
00025                         bne- 1f
00026                 1:
00027         
00028         That is, the CPU is forced to perform a branch that "formally" depends
00029         on the value retrieved from memory. This scheme has an overhead of
00030         about 1-2 clock cycles per load, but it allows to map "acquire" to
00031         the "isync" instruction instead of "sync" uniformly and for all type
00032         of atomic operations. Since "isync" has a cost of about 15 clock
00033         cycles, while "sync" hast a cost of about 50 clock cycles, the small
00034         penalty to atomic loads more than compensates for this.
00035         
00036         Byte- and halfword-sized atomic values are realized by encoding the
00037         value to be represented into a word, performing sign/zero extension
00038         as appropriate. This means that after add/sub operations the value
00039         needs fixing up to accurately preserve the wrap-around semantic of
00040         the smaller type. (Nothing special needs to be done for the bit-wise
00041         and the "exchange type" operators as the compiler already sees to
00042         it that values carried in registers are extended appropriately and
00043         everything falls into place naturally).
00044         
00045         The register constrant "b"  instructs gcc to use any register
00046         except r0; this is sometimes required because the encoding for
00047         r0 is used to signify "constant zero" in a number of instructions,
00048         making r0 unusable in this place. For simplicity this constraint
00049         is used everywhere since I am to lazy to look this up on a
00050         per-instruction basis, and ppc has enough registers for this not
00051         to pose a problem.
00052 */
00053 
00054 #define BOOST_ATOMIC_CHAR_LOCK_FREE 2
00055 #define BOOST_ATOMIC_CHAR16_T_LOCK_FREE 2
00056 #define BOOST_ATOMIC_CHAR32_T_LOCK_FREE 2
00057 #define BOOST_ATOMIC_WCHAR_T_LOCK_FREE 2
00058 #define BOOST_ATOMIC_SHORT_LOCK_FREE 2
00059 #define BOOST_ATOMIC_INT_LOCK_FREE 2
00060 #define BOOST_ATOMIC_LONG_LOCK_FREE 2
00061 #define BOOST_ATOMIC_ADDRESS_LOCK_FREE 2
00062 #if defined(__powerpc64__)
00063 #define BOOST_ATOMIC_LLONG_LOCK_FREE 2
00064 #else
00065 #define BOOST_ATOMIC_LLONG_LOCK_FREE 0
00066 #endif
00067 #define BOOST_ATOMIC_BOOL_LOCK_FREE 2
00068 
00069 /* Would like to move the slow-path of failed compare_exchange
00070 (that clears the "success" bit) out-of-line. gcc can in
00071 principle do that using ".subsection"/".previous", but Apple's
00072 binutils seemingly does not understand that. Therefore wrap
00073 the "clear" of the flag in a macro and let it remain
00074 in-line for Apple
00075 */
00076 
00077 #if !defined(__APPLE__)
00078 
00079 #define BOOST_ATOMIC_ASM_SLOWPATH_CLEAR \
00080         "1:\n" \
00081         ".subsection 2\n" \
00082         "2: addi %1,0,0\n" \
00083         "b 1b\n" \
00084         ".previous\n" \
00085 
00086 #else
00087 
00088 #define BOOST_ATOMIC_ASM_SLOWPATH_CLEAR \
00089         "b 1f\n" \
00090         "2: addi %1,0,0\n" \
00091         "1:\n" \
00092 
00093 #endif
00094 
00095 namespace boost {
00096 namespace detail {
00097 namespace atomic {
00098 
00099 static inline void
00100 ppc_fence_before(memory_order order)
00101 {
00102         switch(order) {
00103                 case memory_order_release:
00104                 case memory_order_acq_rel:
00105 #if defined(__powerpc64__)
00106                         __asm__ __volatile__ ("lwsync" ::: "memory");
00107                         break;
00108 #endif
00109                 case memory_order_seq_cst:
00110                         __asm__ __volatile__ ("sync" ::: "memory");
00111                 default:;
00112         }
00113 }
00114 
00115 static inline void
00116 ppc_fence_after(memory_order order)
00117 {
00118         switch(order) {
00119                 case memory_order_acquire:
00120                 case memory_order_acq_rel:
00121                 case memory_order_seq_cst:
00122                         __asm__ __volatile__ ("isync");
00123                 case memory_order_consume:
00124                         __asm__ __volatile__ ("" ::: "memory");
00125                 default:;
00126         }
00127 }
00128 
00129 static inline void
00130 ppc_fence_after_store(memory_order order)
00131 {
00132         switch(order) {
00133                 case memory_order_seq_cst:
00134                         __asm__ __volatile__ ("sync");
00135                 default:;
00136         }
00137 }
00138 
00139 /* integral types */
00140 
00141 template<typename T>
00142 class base_atomic<T, int, 1, true> {
00143         typedef base_atomic this_type;
00144         typedef T value_type;
00145         typedef int32_t storage_type;
00146         typedef T difference_type;
00147 public:
00148         explicit base_atomic(value_type v) : v_(v) {}
00149         base_atomic(void) {}
00150         
00151         void
00152         store(value_type v, memory_order order = memory_order_seq_cst) volatile
00153         {
00154                 ppc_fence_before(order);
00155                 __asm__ (
00156                         "stw %1, %0\n"
00157                         : "+m"(v_)
00158                         : "r" (v)
00159                 );
00160                 ppc_fence_after_store(order);
00161         }
00162         
00163         value_type
00164         load(memory_order order = memory_order_seq_cst) const volatile
00165         {
00166                 value_type v;
00167                 __asm__ __volatile__ (
00168                         "lwz %0, %1\n"
00169                         "cmpw %0, %0\n"
00170                         "bne- 1f\n"
00171                         "1:\n"
00172                         : "=&r" (v)
00173                         : "m" (v_)
00174                 );
00175                 ppc_fence_after(order);
00176                 return v;
00177         }
00178         
00179         value_type
00180         exchange(value_type v, memory_order order = memory_order_seq_cst) volatile
00181         {
00182                 value_type original;
00183                 ppc_fence_before(order);
00184                 __asm__ (
00185                         "1:\n"
00186                         "lwarx %0,%y1\n"
00187                         "stwcx. %2,%y1\n"
00188                         "bne- 1b\n"
00189                         : "=&b" (original), "+Z"(v_)
00190                         : "b" (v)
00191                         : "cr0"
00192                 );
00193                 ppc_fence_after(order);
00194                 return original;
00195         }
00196         
00197         bool
00198         compare_exchange_weak(
00199                 value_type & expected,
00200                 value_type desired,
00201                 memory_order success_order,
00202                 memory_order failure_order) volatile
00203         {
00204                 int success;
00205                 ppc_fence_before(success_order);
00206                 __asm__(
00207                         "lwarx %0,%y2\n"
00208                         "cmpw %0, %3\n"
00209                         "bne- 2f\n"
00210                         "stwcx. %4,%y2\n"
00211                         "bne- 2f\n"
00212                         "addi %1,0,1\n"
00213                         "1:"
00214                         BOOST_ATOMIC_ASM_SLOWPATH_CLEAR
00215                         : "=&b" (expected), "=&b" (success), "+Z"(v_)
00216                         : "b" (expected), "b" (desired)
00217                         : "cr0"
00218                 );
00219                 if (success)
00220                         ppc_fence_after(success_order);
00221                 else
00222                         ppc_fence_after(failure_order);
00223                 return success;
00224         }
00225         
00226         bool
00227         compare_exchange_strong(
00228                 value_type & expected,
00229                 value_type desired,
00230                 memory_order success_order,
00231                 memory_order failure_order) volatile
00232         {
00233                 int success;
00234                 ppc_fence_before(success_order);
00235                 __asm__(
00236                         "0: lwarx %0,%y2\n"
00237                         "cmpw %0, %3\n"
00238                         "bne- 2f\n"
00239                         "stwcx. %4,%y2\n"
00240                         "bne- 0b\n"
00241                         "addi %1,0,1\n"
00242                         "1:"
00243                         
00244                         BOOST_ATOMIC_ASM_SLOWPATH_CLEAR
00245                         : "=&b" (expected), "=&b" (success), "+Z"(v_)
00246                         : "b" (expected), "b" (desired)
00247                         : "cr0"
00248                 );
00249                 if (success)
00250                         ppc_fence_after(success_order);
00251                 else
00252                         ppc_fence_after(failure_order);
00253                 return success;
00254         }
00255         
00256         value_type
00257         fetch_add(value_type v, memory_order order = memory_order_seq_cst) volatile
00258         {
00259                 value_type original, tmp;
00260                 ppc_fence_before(order);
00261                 __asm__ (
00262                         "1:\n"
00263                         "lwarx %0,%y2\n"
00264                         "add %1,%0,%3\n"
00265                         "extsb %1, %1\n"
00266                         "stwcx. %1,%y2\n"
00267                         "bne- 1b\n"
00268                         : "=&b" (original), "=&b" (tmp), "+Z"(v_)
00269                         : "b" (v)
00270                         : "cc");
00271                 ppc_fence_after(order);
00272                 return original;
00273         }
00274         
00275         value_type
00276         fetch_sub(value_type v, memory_order order = memory_order_seq_cst) volatile
00277         {
00278                 value_type original, tmp;
00279                 ppc_fence_before(order);
00280                 __asm__ (
00281                         "1:\n"
00282                         "lwarx %0,%y2\n"
00283                         "sub %1,%0,%3\n"
00284                         "extsb %1, %1\n"
00285                         "stwcx. %1,%y2\n"
00286                         "bne- 1b\n"
00287                         : "=&b" (original), "=&b" (tmp), "+Z"(v_)
00288                         : "b" (v)
00289                         : "cc");
00290                 ppc_fence_after(order);
00291                 return original;
00292         }
00293         
00294         value_type
00295         fetch_and(value_type v, memory_order order = memory_order_seq_cst) volatile
00296         {
00297                 value_type original, tmp;
00298                 ppc_fence_before(order);
00299                 __asm__ (
00300                         "1:\n"
00301                         "lwarx %0,%y2\n"
00302                         "and %1,%0,%3\n"
00303                         "stwcx. %1,%y2\n"
00304                         "bne- 1b\n"
00305                         : "=&b" (original), "=&b" (tmp), "+Z"(v_)
00306                         : "b" (v)
00307                         : "cc");
00308                 ppc_fence_after(order);
00309                 return original;
00310         }
00311         
00312         value_type
00313         fetch_or(value_type v, memory_order order = memory_order_seq_cst) volatile
00314         {
00315                 value_type original, tmp;
00316                 ppc_fence_before(order);
00317                 __asm__ (
00318                         "1:\n"
00319                         "lwarx %0,%y2\n"
00320                         "or %1,%0,%3\n"
00321                         "stwcx. %1,%y2\n"
00322                         "bne- 1b\n"
00323                         : "=&b" (original), "=&b" (tmp), "+Z"(v_)
00324                         : "b" (v)
00325                         : "cc");
00326                 ppc_fence_after(order);
00327                 return original;
00328         }
00329         
00330         value_type
00331         fetch_xor(value_type v, memory_order order = memory_order_seq_cst) volatile
00332         {
00333                 value_type original, tmp;
00334                 ppc_fence_before(order);
00335                 __asm__ (
00336                         "1:\n"
00337                         "lwarx %0,%y2\n"
00338                         "xor %1,%0,%3\n"
00339                         "stwcx. %1,%y2\n"
00340                         "bne- 1b\n"
00341                         : "=&b" (original), "=&b" (tmp), "+Z"(v_)
00342                         : "b" (v)
00343                         : "cc");
00344                 ppc_fence_after(order);
00345                 return original;
00346         }
00347         
00348         bool
00349         is_lock_free(void) const volatile
00350         {
00351                 return true;
00352         }
00353         
00354         BOOST_ATOMIC_DECLARE_INTEGRAL_OPERATORS
00355 private:
00356         base_atomic(const base_atomic &) /* = delete */ ;
00357         void operator=(const base_atomic &) /* = delete */ ;
00358         storage_type v_;
00359 };
00360 
00361 template<typename T>
00362 class base_atomic<T, int, 1, false> {
00363         typedef base_atomic this_type;
00364         typedef T value_type;
00365         typedef uint32_t storage_type;
00366         typedef T difference_type;
00367 public:
00368         explicit base_atomic(value_type v) : v_(v) {}
00369         base_atomic(void) {}
00370         
00371         void
00372         store(value_type v, memory_order order = memory_order_seq_cst) volatile
00373         {
00374                 ppc_fence_before(order);
00375                 __asm__ (
00376                         "stw %1, %0\n"
00377                         : "+m"(v_)
00378                         : "r" (v)
00379                 );
00380                 ppc_fence_after_store(order);
00381         }
00382         
00383         value_type
00384         load(memory_order order = memory_order_seq_cst) const volatile
00385         {
00386                 value_type v;
00387                 __asm__ __volatile__ (
00388                         "lwz %0, %1\n"
00389                         "cmpw %0, %0\n"
00390                         "bne- 1f\n"
00391                         "1:\n"
00392                         : "=&r" (v)
00393                         : "m" (v_)
00394                 );
00395                 ppc_fence_after(order);
00396                 return v;
00397         }
00398         
00399         value_type
00400         exchange(value_type v, memory_order order = memory_order_seq_cst) volatile
00401         {
00402                 value_type original;
00403                 ppc_fence_before(order);
00404                 __asm__ (
00405                         "1:\n"
00406                         "lwarx %0,%y1\n"
00407                         "stwcx. %2,%y1\n"
00408                         "bne- 1b\n"
00409                         : "=&b" (original), "+Z"(v_)
00410                         : "b" (v)
00411                         : "cr0"
00412                 );
00413                 ppc_fence_after(order);
00414                 return original;
00415         }
00416         
00417         bool
00418         compare_exchange_weak(
00419                 value_type & expected,
00420                 value_type desired,
00421                 memory_order success_order,
00422                 memory_order failure_order) volatile
00423         {
00424                 int success;
00425                 ppc_fence_before(success_order);
00426                 __asm__(
00427                         "lwarx %0,%y2\n"
00428                         "cmpw %0, %3\n"
00429                         "bne- 2f\n"
00430                         "stwcx. %4,%y2\n"
00431                         "bne- 2f\n"
00432                         "addi %1,0,1\n"
00433                         "1:"
00434                         
00435                         BOOST_ATOMIC_ASM_SLOWPATH_CLEAR
00436                         : "=&b" (expected), "=&b" (success), "+Z"(v_)
00437                         : "b" (expected), "b" (desired)
00438                         : "cr0"
00439                 );
00440                 if (success)
00441                         ppc_fence_after(success_order);
00442                 else
00443                         ppc_fence_after(failure_order);
00444                 return success;
00445         }
00446         
00447         bool
00448         compare_exchange_strong(
00449                 value_type & expected,
00450                 value_type desired,
00451                 memory_order success_order,
00452                 memory_order failure_order) volatile
00453         {
00454                 int success;
00455                 ppc_fence_before(success_order);
00456                 __asm__(
00457                         "0: lwarx %0,%y2\n"
00458                         "cmpw %0, %3\n"
00459                         "bne- 2f\n"
00460                         "stwcx. %4,%y2\n"
00461                         "bne- 0b\n"
00462                         "addi %1,0,1\n"
00463                         "1:"
00464                         
00465                         BOOST_ATOMIC_ASM_SLOWPATH_CLEAR
00466                         : "=&b" (expected), "=&b" (success), "+Z"(v_)
00467                         : "b" (expected), "b" (desired)
00468                         : "cr0"
00469                 );
00470                 if (success)
00471                         ppc_fence_after(success_order);
00472                 else
00473                         ppc_fence_after(failure_order);
00474                 return success;
00475         }
00476         
00477         value_type
00478         fetch_add(value_type v, memory_order order = memory_order_seq_cst) volatile
00479         {
00480                 value_type original, tmp;
00481                 ppc_fence_before(order);
00482                 __asm__ (
00483                         "1:\n"
00484                         "lwarx %0,%y2\n"
00485                         "add %1,%0,%3\n"
00486                         "rlwinm %1, %1, 0, 0xff\n"
00487                         "stwcx. %1,%y2\n"
00488                         "bne- 1b\n"
00489                         : "=&b" (original), "=&b" (tmp), "+Z"(v_)
00490                         : "b" (v)
00491                         : "cc");
00492                 ppc_fence_after(order);
00493                 return original;
00494         }
00495         
00496         value_type
00497         fetch_sub(value_type v, memory_order order = memory_order_seq_cst) volatile
00498         {
00499                 value_type original, tmp;
00500                 ppc_fence_before(order);
00501                 __asm__ (
00502                         "1:\n"
00503                         "lwarx %0,%y2\n"
00504                         "sub %1,%0,%3\n"
00505                         "rlwinm %1, %1, 0, 0xff\n"
00506                         "stwcx. %1,%y2\n"
00507                         "bne- 1b\n"
00508                         : "=&b" (original), "=&b" (tmp), "+Z"(v_)
00509                         : "b" (v)
00510                         : "cc");
00511                 ppc_fence_after(order);
00512                 return original;
00513         }
00514         
00515         value_type
00516         fetch_and(value_type v, memory_order order = memory_order_seq_cst) volatile
00517         {
00518                 value_type original, tmp;
00519                 ppc_fence_before(order);
00520                 __asm__ (
00521                         "1:\n"
00522                         "lwarx %0,%y2\n"
00523                         "and %1,%0,%3\n"
00524                         "stwcx. %1,%y2\n"
00525                         "bne- 1b\n"
00526                         : "=&b" (original), "=&b" (tmp), "+Z"(v_)
00527                         : "b" (v)
00528                         : "cc");
00529                 ppc_fence_after(order);
00530                 return original;
00531         }
00532         
00533         value_type
00534         fetch_or(value_type v, memory_order order = memory_order_seq_cst) volatile
00535         {
00536                 value_type original, tmp;
00537                 ppc_fence_before(order);
00538                 __asm__ (
00539                         "1:\n"
00540                         "lwarx %0,%y2\n"
00541                         "or %1,%0,%3\n"
00542                         "stwcx. %1,%y2\n"
00543                         "bne- 1b\n"
00544                         : "=&b" (original), "=&b" (tmp), "+Z"(v_)
00545                         : "b" (v)
00546                         : "cc");
00547                 ppc_fence_after(order);
00548                 return original;
00549         }
00550         
00551         value_type
00552         fetch_xor(value_type v, memory_order order = memory_order_seq_cst) volatile
00553         {
00554                 value_type original, tmp;
00555                 ppc_fence_before(order);
00556                 __asm__ (
00557                         "1:\n"
00558                         "lwarx %0,%y2\n"
00559                         "xor %1,%0,%3\n"
00560                         "stwcx. %1,%y2\n"
00561                         "bne- 1b\n"
00562                         : "=&b" (original), "=&b" (tmp), "+Z"(v_)
00563                         : "b" (v)
00564                         : "cc");
00565                 ppc_fence_after(order);
00566                 return original;
00567         }
00568         
00569         bool
00570         is_lock_free(void) const volatile
00571         {
00572                 return true;
00573         }
00574         
00575         BOOST_ATOMIC_DECLARE_INTEGRAL_OPERATORS
00576 private:
00577         base_atomic(const base_atomic &) /* = delete */ ;
00578         void operator=(const base_atomic &) /* = delete */ ;
00579         storage_type v_;
00580 };
00581 
00582 template<typename T>
00583 class base_atomic<T, int, 2, true> {
00584         typedef base_atomic this_type;
00585         typedef T value_type;
00586         typedef int32_t storage_type;
00587         typedef T difference_type;
00588 public:
00589         explicit base_atomic(value_type v) : v_(v) {}
00590         base_atomic(void) {}
00591         
00592         void
00593         store(value_type v, memory_order order = memory_order_seq_cst) volatile
00594         {
00595                 ppc_fence_before(order);
00596                 __asm__ (
00597                         "stw %1, %0\n"
00598                         : "+m"(v_)
00599                         : "r" (v)
00600                 );
00601                 ppc_fence_after_store(order);
00602         }
00603         
00604         value_type
00605         load(memory_order order = memory_order_seq_cst) const volatile
00606         {
00607                 value_type v;
00608                 __asm__ __volatile__ (
00609                         "lwz %0, %1\n"
00610                         "cmpw %0, %0\n"
00611                         "bne- 1f\n"
00612                         "1:\n"
00613                         : "=&r" (v)
00614                         : "m" (v_)
00615                 );
00616                 ppc_fence_after(order);
00617                 return v;
00618         }
00619         
00620         value_type
00621         exchange(value_type v, memory_order order = memory_order_seq_cst) volatile
00622         {
00623                 value_type original;
00624                 ppc_fence_before(order);
00625                 __asm__ (
00626                         "1:\n"
00627                         "lwarx %0,%y1\n"
00628                         "stwcx. %2,%y1\n"
00629                         "bne- 1b\n"
00630                         : "=&b" (original), "+Z"(v_)
00631                         : "b" (v)
00632                         : "cr0"
00633                 );
00634                 ppc_fence_after(order);
00635                 return original;
00636         }
00637         
00638         bool
00639         compare_exchange_weak(
00640                 value_type & expected,
00641                 value_type desired,
00642                 memory_order success_order,
00643                 memory_order failure_order) volatile
00644         {
00645                 int success;
00646                 ppc_fence_before(success_order);
00647                 __asm__(
00648                         "lwarx %0,%y2\n"
00649                         "cmpw %0, %3\n"
00650                         "bne- 2f\n"
00651                         "stwcx. %4,%y2\n"
00652                         "bne- 2f\n"
00653                         "addi %1,0,1\n"
00654                         "1:"
00655                         
00656                         BOOST_ATOMIC_ASM_SLOWPATH_CLEAR
00657                         : "=&b" (expected), "=&b" (success), "+Z"(v_)
00658                         : "b" (expected), "b" (desired)
00659                         : "cr0"
00660                 );
00661                 if (success)
00662                         ppc_fence_after(success_order);
00663                 else
00664                         ppc_fence_after(failure_order);
00665                 return success;
00666         }
00667         
00668         bool
00669         compare_exchange_strong(
00670                 value_type & expected,
00671                 value_type desired,
00672                 memory_order success_order,
00673                 memory_order failure_order) volatile
00674         {
00675                 int success;
00676                 ppc_fence_before(success_order);
00677                 __asm__(
00678                         "0: lwarx %0,%y2\n"
00679                         "cmpw %0, %3\n"
00680                         "bne- 2f\n"
00681                         "stwcx. %4,%y2\n"
00682                         "bne- 0b\n"
00683                         "addi %1,0,1\n"
00684                         "1:"
00685                         
00686                         BOOST_ATOMIC_ASM_SLOWPATH_CLEAR
00687                         : "=&b" (expected), "=&b" (success), "+Z"(v_)
00688                         : "b" (expected), "b" (desired)
00689                         : "cr0"
00690                 );
00691                 if (success)
00692                         ppc_fence_after(success_order);
00693                 else
00694                         ppc_fence_after(failure_order);
00695                 return success;
00696         }
00697         
00698         value_type
00699         fetch_add(value_type v, memory_order order = memory_order_seq_cst) volatile
00700         {
00701                 value_type original, tmp;
00702                 ppc_fence_before(order);
00703                 __asm__ (
00704                         "1:\n"
00705                         "lwarx %0,%y2\n"
00706                         "add %1,%0,%3\n"
00707                         "extsh %1, %1\n"
00708                         "stwcx. %1,%y2\n"
00709                         "bne- 1b\n"
00710                         : "=&b" (original), "=&b" (tmp), "+Z"(v_)
00711                         : "b" (v)
00712                         : "cc");
00713                 ppc_fence_after(order);
00714                 return original;
00715         }
00716         
00717         value_type
00718         fetch_sub(value_type v, memory_order order = memory_order_seq_cst) volatile
00719         {
00720                 value_type original, tmp;
00721                 ppc_fence_before(order);
00722                 __asm__ (
00723                         "1:\n"
00724                         "lwarx %0,%y2\n"
00725                         "sub %1,%0,%3\n"
00726                         "extsh %1, %1\n"
00727                         "stwcx. %1,%y2\n"
00728                         "bne- 1b\n"
00729                         : "=&b" (original), "=&b" (tmp), "+Z"(v_)
00730                         : "b" (v)
00731                         : "cc");
00732                 ppc_fence_after(order);
00733                 return original;
00734         }
00735         
00736         value_type
00737         fetch_and(value_type v, memory_order order = memory_order_seq_cst) volatile
00738         {
00739                 value_type original, tmp;
00740                 ppc_fence_before(order);
00741                 __asm__ (
00742                         "1:\n"
00743                         "lwarx %0,%y2\n"
00744                         "and %1,%0,%3\n"
00745                         "stwcx. %1,%y2\n"
00746                         "bne- 1b\n"
00747                         : "=&b" (original), "=&b" (tmp), "+Z"(v_)
00748                         : "b" (v)
00749                         : "cc");
00750                 ppc_fence_after(order);
00751                 return original;
00752         }
00753         
00754         value_type
00755         fetch_or(value_type v, memory_order order = memory_order_seq_cst) volatile
00756         {
00757                 value_type original, tmp;
00758                 ppc_fence_before(order);
00759                 __asm__ (
00760                         "1:\n"
00761                         "lwarx %0,%y2\n"
00762                         "or %1,%0,%3\n"
00763                         "stwcx. %1,%y2\n"
00764                         "bne- 1b\n"
00765                         : "=&b" (original), "=&b" (tmp), "+Z"(v_)
00766                         : "b" (v)
00767                         : "cc");
00768                 ppc_fence_after(order);
00769                 return original;
00770         }
00771         
00772         value_type
00773         fetch_xor(value_type v, memory_order order = memory_order_seq_cst) volatile
00774         {
00775                 value_type original, tmp;
00776                 ppc_fence_before(order);
00777                 __asm__ (
00778                         "1:\n"
00779                         "lwarx %0,%y2\n"
00780                         "xor %1,%0,%3\n"
00781                         "stwcx. %1,%y2\n"
00782                         "bne- 1b\n"
00783                         : "=&b" (original), "=&b" (tmp), "+Z"(v_)
00784                         : "b" (v)
00785                         : "cc");
00786                 ppc_fence_after(order);
00787                 return original;
00788         }
00789         
00790         bool
00791         is_lock_free(void) const volatile
00792         {
00793                 return true;
00794         }
00795         
00796         BOOST_ATOMIC_DECLARE_INTEGRAL_OPERATORS
00797 private:
00798         base_atomic(const base_atomic &) /* = delete */ ;
00799         void operator=(const base_atomic &) /* = delete */ ;
00800         storage_type v_;
00801 };
00802 
00803 template<typename T>
00804 class base_atomic<T, int, 2, false> {
00805         typedef base_atomic this_type;
00806         typedef T value_type;
00807         typedef uint32_t storage_type;
00808         typedef T difference_type;
00809 public:
00810         explicit base_atomic(value_type v) : v_(v) {}
00811         base_atomic(void) {}
00812         
00813         void
00814         store(value_type v, memory_order order = memory_order_seq_cst) volatile
00815         {
00816                 ppc_fence_before(order);
00817                 __asm__ (
00818                         "stw %1, %0\n"
00819                         : "+m"(v_)
00820                         : "r" (v)
00821                 );
00822                 ppc_fence_after_store(order);
00823         }
00824         
00825         value_type
00826         load(memory_order order = memory_order_seq_cst) const volatile
00827         {
00828                 value_type v;
00829                 __asm__ __volatile__ (
00830                         "lwz %0, %1\n"
00831                         "cmpw %0, %0\n"
00832                         "bne- 1f\n"
00833                         "1:\n"
00834                         : "=&r" (v)
00835                         : "m" (v_)
00836                 );
00837                 ppc_fence_after(order);
00838                 return v;
00839         }
00840         
00841         value_type
00842         exchange(value_type v, memory_order order = memory_order_seq_cst) volatile
00843         {
00844                 value_type original;
00845                 ppc_fence_before(order);
00846                 __asm__ (
00847                         "1:\n"
00848                         "lwarx %0,%y1\n"
00849                         "stwcx. %2,%y1\n"
00850                         "bne- 1b\n"
00851                         : "=&b" (original), "+Z"(v_)
00852                         : "b" (v)
00853                         : "cr0"
00854                 );
00855                 ppc_fence_after(order);
00856                 return original;
00857         }
00858         
00859         bool
00860         compare_exchange_weak(
00861                 value_type & expected,
00862                 value_type desired,
00863                 memory_order success_order,
00864                 memory_order failure_order) volatile
00865         {
00866                 int success;
00867                 ppc_fence_before(success_order);
00868                 __asm__(
00869                         "lwarx %0,%y2\n"
00870                         "cmpw %0, %3\n"
00871                         "bne- 2f\n"
00872                         "stwcx. %4,%y2\n"
00873                         "bne- 2f\n"
00874                         "addi %1,0,1\n"
00875                         "1:"
00876                         
00877                         BOOST_ATOMIC_ASM_SLOWPATH_CLEAR
00878                         : "=&b" (expected), "=&b" (success), "+Z"(v_)
00879                         : "b" (expected), "b" (desired)
00880                         : "cr0"
00881                 );
00882                 if (success)
00883                         ppc_fence_after(success_order);
00884                 else
00885                         ppc_fence_after(failure_order);
00886                 return success;
00887         }
00888         
00889         bool
00890         compare_exchange_strong(
00891                 value_type & expected,
00892                 value_type desired,
00893                 memory_order success_order,
00894                 memory_order failure_order) volatile
00895         {
00896                 int success;
00897                 ppc_fence_before(success_order);
00898                 __asm__(
00899                         "0: lwarx %0,%y2\n"
00900                         "cmpw %0, %3\n"
00901                         "bne- 2f\n"
00902                         "stwcx. %4,%y2\n"
00903                         "bne- 0b\n"
00904                         "addi %1,0,1\n"
00905                         "1:"
00906                         
00907                         BOOST_ATOMIC_ASM_SLOWPATH_CLEAR
00908                         : "=&b" (expected), "=&b" (success), "+Z"(v_)
00909                         : "b" (expected), "b" (desired)
00910                         : "cr0"
00911                 );
00912                 if (success)
00913                         ppc_fence_after(success_order);
00914                 else
00915                         ppc_fence_after(failure_order);
00916                 return success;
00917         }
00918         
00919         value_type
00920         fetch_add(value_type v, memory_order order = memory_order_seq_cst) volatile
00921         {
00922                 value_type original, tmp;
00923                 ppc_fence_before(order);
00924                 __asm__ (
00925                         "1:\n"
00926                         "lwarx %0,%y2\n"
00927                         "add %1,%0,%3\n"
00928                         "rlwinm %1, %1, 0, 0xffff\n"
00929                         "stwcx. %1,%y2\n"
00930                         "bne- 1b\n"
00931                         : "=&b" (original), "=&b" (tmp), "+Z"(v_)
00932                         : "b" (v)
00933                         : "cc");
00934                 ppc_fence_after(order);
00935                 return original;
00936         }
00937         
00938         value_type
00939         fetch_sub(value_type v, memory_order order = memory_order_seq_cst) volatile
00940         {
00941                 value_type original, tmp;
00942                 ppc_fence_before(order);
00943                 __asm__ (
00944                         "1:\n"
00945                         "lwarx %0,%y2\n"
00946                         "sub %1,%0,%3\n"
00947                         "rlwinm %1, %1, 0, 0xffff\n"
00948                         "stwcx. %1,%y2\n"
00949                         "bne- 1b\n"
00950                         : "=&b" (original), "=&b" (tmp), "+Z"(v_)
00951                         : "b" (v)
00952                         : "cc");
00953                 ppc_fence_after(order);
00954                 return original;
00955         }
00956         
00957         value_type
00958         fetch_and(value_type v, memory_order order = memory_order_seq_cst) volatile
00959         {
00960                 value_type original, tmp;
00961                 ppc_fence_before(order);
00962                 __asm__ (
00963                         "1:\n"
00964                         "lwarx %0,%y2\n"
00965                         "and %1,%0,%3\n"
00966                         "stwcx. %1,%y2\n"
00967                         "bne- 1b\n"
00968                         : "=&b" (original), "=&b" (tmp), "+Z"(v_)
00969                         : "b" (v)
00970                         : "cc");
00971                 ppc_fence_after(order);
00972                 return original;
00973         }
00974         
00975         value_type
00976         fetch_or(value_type v, memory_order order = memory_order_seq_cst) volatile
00977         {
00978                 value_type original, tmp;
00979                 ppc_fence_before(order);
00980                 __asm__ (
00981                         "1:\n"
00982                         "lwarx %0,%y2\n"
00983                         "or %1,%0,%3\n"
00984                         "stwcx. %1,%y2\n"
00985                         "bne- 1b\n"
00986                         : "=&b" (original), "=&b" (tmp), "+Z"(v_)
00987                         : "b" (v)
00988                         : "cc");
00989                 ppc_fence_after(order);
00990                 return original;
00991         }
00992         
00993         value_type
00994         fetch_xor(value_type v, memory_order order = memory_order_seq_cst) volatile
00995         {
00996                 value_type original, tmp;
00997                 ppc_fence_before(order);
00998                 __asm__ (
00999                         "1:\n"
01000                         "lwarx %0,%y2\n"
01001                         "xor %1,%0,%3\n"
01002                         "stwcx. %1,%y2\n"
01003                         "bne- 1b\n"
01004                         : "=&b" (original), "=&b" (tmp), "+Z"(v_)
01005                         : "b" (v)
01006                         : "cc");
01007                 ppc_fence_after(order);
01008                 return original;
01009         }
01010         
01011         bool
01012         is_lock_free(void) const volatile
01013         {
01014                 return true;
01015         }
01016         
01017         BOOST_ATOMIC_DECLARE_INTEGRAL_OPERATORS
01018 private:
01019         base_atomic(const base_atomic &) /* = delete */ ;
01020         void operator=(const base_atomic &) /* = delete */ ;
01021         storage_type v_;
01022 };
01023 
01024 template<typename T, bool Sign>
01025 class base_atomic<T, int, 4, Sign> {
01026         typedef base_atomic this_type;
01027         typedef T value_type;
01028         typedef T difference_type;
01029 public:
01030         explicit base_atomic(value_type v) : v_(v) {}
01031         base_atomic(void) {}
01032         
01033         void
01034         store(value_type v, memory_order order = memory_order_seq_cst) volatile
01035         {
01036                 ppc_fence_before(order);
01037                 const_cast<volatile value_type &>(v_) = v;
01038                 ppc_fence_after_store(order);
01039         }
01040         
01041         value_type
01042         load(memory_order order = memory_order_seq_cst) const volatile
01043         {
01044                 value_type v = const_cast<const volatile value_type &>(v_);
01045                 __asm__ __volatile__ (
01046                         "cmpw %0, %0\n"
01047                         "bne- 1f\n"
01048                         "1:\n"
01049                         : "+b"(v)
01050                         :
01051                         : "cr0"
01052                 );
01053                 ppc_fence_after(order);
01054                 return v;
01055         }
01056         
01057         value_type
01058         exchange(value_type v, memory_order order = memory_order_seq_cst) volatile
01059         {
01060                 value_type original;
01061                 ppc_fence_before(order);
01062                 __asm__ (
01063                         "1:\n"
01064                         "lwarx %0,%y1\n"
01065                         "stwcx. %2,%y1\n"
01066                         "bne- 1b\n"
01067                         : "=&b" (original), "+Z"(v_)
01068                         : "b" (v)
01069                         : "cr0"
01070                 );
01071                 ppc_fence_after(order);
01072                 return original;
01073         }
01074         
01075         bool
01076         compare_exchange_weak(
01077                 value_type & expected,
01078                 value_type desired,
01079                 memory_order success_order,
01080                 memory_order failure_order) volatile
01081         {
01082                 int success;
01083                 ppc_fence_before(success_order);
01084                 __asm__(
01085                         "lwarx %0,%y2\n"
01086                         "cmpw %0, %3\n"
01087                         "bne- 2f\n"
01088                         "stwcx. %4,%y2\n"
01089                         "bne- 2f\n"
01090                         "addi %1,0,1\n"
01091                         "1:"
01092                         
01093                         BOOST_ATOMIC_ASM_SLOWPATH_CLEAR
01094                         : "=&b" (expected), "=&b" (success), "+Z"(v_)
01095                         : "b" (expected), "b" (desired)
01096                         : "cr0"
01097                 );
01098                 if (success)
01099                         ppc_fence_after(success_order);
01100                 else
01101                         ppc_fence_after(failure_order);
01102                 return success;
01103         }
01104         
01105         bool
01106         compare_exchange_strong(
01107                 value_type & expected,
01108                 value_type desired,
01109                 memory_order success_order,
01110                 memory_order failure_order) volatile
01111         {
01112                 int success;
01113                 ppc_fence_before(success_order);
01114                 __asm__(
01115                         "0: lwarx %0,%y2\n"
01116                         "cmpw %0, %3\n"
01117                         "bne- 2f\n"
01118                         "stwcx. %4,%y2\n"
01119                         "bne- 0b\n"
01120                         "addi %1,0,1\n"
01121                         "1:"
01122                         
01123                         BOOST_ATOMIC_ASM_SLOWPATH_CLEAR
01124                         : "=&b" (expected), "=&b" (success), "+Z"(v_)
01125                         : "b" (expected), "b" (desired)
01126                         : "cr0"
01127                 );
01128                 if (success)
01129                         ppc_fence_after(success_order);
01130                 else
01131                         ppc_fence_after(failure_order);
01132                 return success;
01133         }
01134         
01135         value_type
01136         fetch_add(value_type v, memory_order order = memory_order_seq_cst) volatile
01137         {
01138                 value_type original, tmp;
01139                 ppc_fence_before(order);
01140                 __asm__ (
01141                         "1:\n"
01142                         "lwarx %0,%y2\n"
01143                         "add %1,%0,%3\n"
01144                         "stwcx. %1,%y2\n"
01145                         "bne- 1b\n"
01146                         : "=&b" (original), "=&b" (tmp), "+Z"(v_)
01147                         : "b" (v)
01148                         : "cc");
01149                 ppc_fence_after(order);
01150                 return original;
01151         }
01152         
01153         value_type
01154         fetch_sub(value_type v, memory_order order = memory_order_seq_cst) volatile
01155         {
01156                 value_type original, tmp;
01157                 ppc_fence_before(order);
01158                 __asm__ (
01159                         "1:\n"
01160                         "lwarx %0,%y2\n"
01161                         "sub %1,%0,%3\n"
01162                         "stwcx. %1,%y2\n"
01163                         "bne- 1b\n"
01164                         : "=&b" (original), "=&b" (tmp), "+Z"(v_)
01165                         : "b" (v)
01166                         : "cc");
01167                 ppc_fence_after(order);
01168                 return original;
01169         }
01170         
01171         value_type
01172         fetch_and(value_type v, memory_order order = memory_order_seq_cst) volatile
01173         {
01174                 value_type original, tmp;
01175                 ppc_fence_before(order);
01176                 __asm__ (
01177                         "1:\n"
01178                         "lwarx %0,%y2\n"
01179                         "and %1,%0,%3\n"
01180                         "stwcx. %1,%y2\n"
01181                         "bne- 1b\n"
01182                         : "=&b" (original), "=&b" (tmp), "+Z"(v_)
01183                         : "b" (v)
01184                         : "cc");
01185                 ppc_fence_after(order);
01186                 return original;
01187         }
01188         
01189         value_type
01190         fetch_or(value_type v, memory_order order = memory_order_seq_cst) volatile
01191         {
01192                 value_type original, tmp;
01193                 ppc_fence_before(order);
01194                 __asm__ (
01195                         "1:\n"
01196                         "lwarx %0,%y2\n"
01197                         "or %1,%0,%3\n"
01198                         "stwcx. %1,%y2\n"
01199                         "bne- 1b\n"
01200                         : "=&b" (original), "=&b" (tmp), "+Z"(v_)
01201                         : "b" (v)
01202                         : "cc");
01203                 ppc_fence_after(order);
01204                 return original;
01205         }
01206         
01207         value_type
01208         fetch_xor(value_type v, memory_order order = memory_order_seq_cst) volatile
01209         {
01210                 value_type original, tmp;
01211                 ppc_fence_before(order);
01212                 __asm__ (
01213                         "1:\n"
01214                         "lwarx %0,%y2\n"
01215                         "xor %1,%0,%3\n"
01216                         "stwcx. %1,%y2\n"
01217                         "bne- 1b\n"
01218                         : "=&b" (original), "=&b" (tmp), "+Z"(v_)
01219                         : "b" (v)
01220                         : "cc");
01221                 ppc_fence_after(order);
01222                 return original;
01223         }
01224         
01225         bool
01226         is_lock_free(void) const volatile
01227         {
01228                 return true;
01229         }
01230         
01231         BOOST_ATOMIC_DECLARE_INTEGRAL_OPERATORS
01232 private:
01233         base_atomic(const base_atomic &) /* = delete */ ;
01234         void operator=(const base_atomic &) /* = delete */ ;
01235         value_type v_;
01236 };
01237 
01238 #if defined(__powerpc64__)
01239 
01240 template<typename T, bool Sign>
01241 class base_atomic<T, int, 8, Sign> {
01242         typedef base_atomic this_type;
01243         typedef T value_type;
01244         typedef T difference_type;
01245 public:
01246         explicit base_atomic(value_type v) : v_(v) {}
01247         base_atomic(void) {}
01248         
01249         void
01250         store(value_type v, memory_order order = memory_order_seq_cst) volatile
01251         {
01252                 ppc_fence_before(order);
01253                 const_cast<volatile value_type &>(v_) = v;
01254                 ppc_fence_after_store(order);
01255         }
01256         
01257         value_type
01258         load(memory_order order = memory_order_seq_cst) const volatile
01259         {
01260                 value_type v = const_cast<const volatile value_type &>(v_);
01261                 __asm__ __volatile__ (
01262                         "cmpd %0, %0\n"
01263                         "bne- 1f\n"
01264                         "1:\n"
01265                         : "+b"(v)
01266                         :
01267                         : "cr0"
01268                 );
01269                 ppc_fence_after(order);
01270                 return v;
01271         }
01272         
01273         value_type
01274         exchange(value_type v, memory_order order = memory_order_seq_cst) volatile
01275         {
01276                 value_type original;
01277                 ppc_fence_before(order);
01278                 __asm__ (
01279                         "1:\n"
01280                         "ldarx %0,%y1\n"
01281                         "stdcx. %2,%y1\n"
01282                         "bne- 1b\n"
01283                         : "=&b" (original), "+Z"(v_)
01284                         : "b" (v)
01285                         : "cr0"
01286                 );
01287                 ppc_fence_after(order);
01288                 return original;
01289         }
01290         
01291         bool
01292         compare_exchange_weak(
01293                 value_type & expected,
01294                 value_type desired,
01295                 memory_order success_order,
01296                 memory_order failure_order) volatile
01297         {
01298                 int success;
01299                 ppc_fence_before(success_order);
01300                 __asm__(
01301                         "ldarx %0,%y2\n"
01302                         "cmpd %0, %3\n"
01303                         "bne- 2f\n"
01304                         "stdcx. %4,%y2\n"
01305                         "bne- 2f\n"
01306                         "addi %1,0,1\n"
01307                         "1:"
01308                         
01309                         BOOST_ATOMIC_ASM_SLOWPATH_CLEAR
01310                         : "=&b" (expected), "=&b" (success), "+Z"(v_)
01311                         : "b" (expected), "b" (desired)
01312                         : "cr0"
01313                 );
01314                 if (success)
01315                         ppc_fence_after(success_order);
01316                 else
01317                         ppc_fence_after(failure_order);
01318                 return success;
01319         }
01320         
01321         bool
01322         compare_exchange_strong(
01323                 value_type & expected,
01324                 value_type desired,
01325                 memory_order success_order,
01326                 memory_order failure_order) volatile
01327         {
01328                 int success;
01329                 ppc_fence_before(success_order);
01330                 __asm__(
01331                         "0: ldarx %0,%y2\n"
01332                         "cmpd %0, %3\n"
01333                         "bne- 2f\n"
01334                         "stdcx. %4,%y2\n"
01335                         "bne- 0b\n"
01336                         "addi %1,0,1\n"
01337                         "1:"
01338                         
01339                         BOOST_ATOMIC_ASM_SLOWPATH_CLEAR
01340                         : "=&b" (expected), "=&b" (success), "+Z"(v_)
01341                         : "b" (expected), "b" (desired)
01342                         : "cr0"
01343                 );
01344                 if (success)
01345                         ppc_fence_after(success_order);
01346                 else
01347                         ppc_fence_after(failure_order);
01348                 return success;
01349         }
01350         
01351         value_type
01352         fetch_add(value_type v, memory_order order = memory_order_seq_cst) volatile
01353         {
01354                 value_type original, tmp;
01355                 ppc_fence_before(order);
01356                 __asm__ (
01357                         "1:\n"
01358                         "ldarx %0,%y2\n"
01359                         "add %1,%0,%3\n"
01360                         "stdcx. %1,%y2\n"
01361                         "bne- 1b\n"
01362                         : "=&b" (original), "=&b" (tmp), "+Z"(v_)
01363                         : "b" (v)
01364                         : "cc");
01365                 ppc_fence_after(order);
01366                 return original;
01367         }
01368         
01369         value_type
01370         fetch_sub(value_type v, memory_order order = memory_order_seq_cst) volatile
01371         {
01372                 value_type original, tmp;
01373                 ppc_fence_before(order);
01374                 __asm__ (
01375                         "1:\n"
01376                         "ldarx %0,%y2\n"
01377                         "sub %1,%0,%3\n"
01378                         "stdcx. %1,%y2\n"
01379                         "bne- 1b\n"
01380                         : "=&b" (original), "=&b" (tmp), "+Z"(v_)
01381                         : "b" (v)
01382                         : "cc");
01383                 ppc_fence_after(order);
01384                 return original;
01385         }
01386         
01387         value_type
01388         fetch_and(value_type v, memory_order order = memory_order_seq_cst) volatile
01389         {
01390                 value_type original, tmp;
01391                 ppc_fence_before(order);
01392                 __asm__ (
01393                         "1:\n"
01394                         "ldarx %0,%y2\n"
01395                         "and %1,%0,%3\n"
01396                         "stdcx. %1,%y2\n"
01397                         "bne- 1b\n"
01398                         : "=&b" (original), "=&b" (tmp), "+Z"(v_)
01399                         : "b" (v)
01400                         : "cc");
01401                 ppc_fence_after(order);
01402                 return original;
01403         }
01404         
01405         value_type
01406         fetch_or(value_type v, memory_order order = memory_order_seq_cst) volatile
01407         {
01408                 value_type original, tmp;
01409                 ppc_fence_before(order);
01410                 __asm__ (
01411                         "1:\n"
01412                         "ldarx %0,%y2\n"
01413                         "or %1,%0,%3\n"
01414                         "stdcx. %1,%y2\n"
01415                         "bne- 1b\n"
01416                         : "=&b" (original), "=&b" (tmp), "+Z"(v_)
01417                         : "b" (v)
01418                         : "cc");
01419                 ppc_fence_after(order);
01420                 return original;
01421         }
01422         
01423         value_type
01424         fetch_xor(value_type v, memory_order order = memory_order_seq_cst) volatile
01425         {
01426                 value_type original, tmp;
01427                 ppc_fence_before(order);
01428                 __asm__ (
01429                         "1:\n"
01430                         "ldarx %0,%y2\n"
01431                         "xor %1,%0,%3\n"
01432                         "stdcx. %1,%y2\n"
01433                         "bne- 1b\n"
01434                         : "=&b" (original), "=&b" (tmp), "+Z"(v_)
01435                         : "b" (v)
01436                         : "cc");
01437                 ppc_fence_after(order);
01438                 return original;
01439         }
01440         
01441         bool
01442         is_lock_free(void) const volatile
01443         {
01444                 return true;
01445         }
01446         
01447         BOOST_ATOMIC_DECLARE_INTEGRAL_OPERATORS
01448 private:
01449         base_atomic(const base_atomic &) /* = delete */ ;
01450         void operator=(const base_atomic &) /* = delete */ ;
01451         value_type v_;
01452 };
01453 
01454 #endif
01455 
01456 /* pointer types */
01457 
01458 #if !defined(__powerpc64__)
01459 
01460 template<bool Sign>
01461 class base_atomic<void *, void *, 4, Sign> {
01462         typedef base_atomic this_type;
01463         typedef void * value_type;
01464 public:
01465         explicit base_atomic(value_type v) : v_(v) {}
01466         base_atomic(void) {}
01467         
01468         void
01469         store(value_type v, memory_order order = memory_order_seq_cst) volatile
01470         {
01471                 ppc_fence_before(order);
01472                 __asm__ (
01473                         "stw %1, %0\n"
01474                         : "+m" (v_)
01475                         : "r" (v)
01476                 );
01477                 ppc_fence_after_store(order);
01478         }
01479         
01480         value_type
01481         load(memory_order order = memory_order_seq_cst) const volatile
01482         {
01483                 value_type v;
01484                 __asm__ (
01485                         "lwz %0, %1\n"
01486                         "cmpw %0, %0\n"
01487                         "bne- 1f\n"
01488                         "1:\n"
01489                         : "=r"(v)
01490                         : "m"(v_)
01491                         : "cr0"
01492                 );
01493                 ppc_fence_after(order);
01494                 return v;
01495         }
01496         
01497         value_type
01498         exchange(value_type v, memory_order order = memory_order_seq_cst) volatile
01499         {
01500                 value_type original;
01501                 ppc_fence_before(order);
01502                 __asm__ (
01503                         "1:\n"
01504                         "lwarx %0,%y1\n"
01505                         "stwcx. %2,%y1\n"
01506                         "bne- 1b\n"
01507                         : "=&b" (original), "+Z"(v_)
01508                         : "b" (v)
01509                         : "cr0"
01510                 );
01511                 ppc_fence_after(order);
01512                 return original;
01513         }
01514         
01515         bool
01516         compare_exchange_weak(
01517                 value_type & expected,
01518                 value_type desired,
01519                 memory_order success_order,
01520                 memory_order failure_order) volatile
01521         {
01522                 int success;
01523                 ppc_fence_before(success_order);
01524                 __asm__(
01525                         "lwarx %0,%y2\n"
01526                         "cmpw %0, %3\n"
01527                         "bne- 2f\n"
01528                         "stwcx. %4,%y2\n"
01529                         "bne- 2f\n"
01530                         "addi %1,0,1\n"
01531                         "1:"
01532                         
01533                         BOOST_ATOMIC_ASM_SLOWPATH_CLEAR
01534                         : "=&b" (expected), "=&b" (success), "+Z"(v_)
01535                         : "b" (expected), "b" (desired)
01536                         : "cr0"
01537                 );
01538                 if (success)
01539                         ppc_fence_after(success_order);
01540                 else
01541                         ppc_fence_after(failure_order);
01542                 return success;
01543         }
01544         
01545         bool
01546         compare_exchange_strong(
01547                 value_type & expected,
01548                 value_type desired,
01549                 memory_order success_order,
01550                 memory_order failure_order) volatile
01551         {
01552                 int success;
01553                 ppc_fence_before(success_order);
01554                 __asm__(
01555                         "0: lwarx %0,%y2\n"
01556                         "cmpw %0, %3\n"
01557                         "bne- 2f\n"
01558                         "stwcx. %4,%y2\n"
01559                         "bne- 0b\n"
01560                         "addi %1,0,1\n"
01561                         "1:"
01562                         
01563                         BOOST_ATOMIC_ASM_SLOWPATH_CLEAR
01564                         : "=&b" (expected), "=&b" (success), "+Z"(v_)
01565                         : "b" (expected), "b" (desired)
01566                         : "cr0"
01567                 );
01568                 if (success)
01569                         ppc_fence_after(success_order);
01570                 else
01571                         ppc_fence_after(failure_order);
01572                 return success;
01573         }
01574         
01575         bool
01576         is_lock_free(void) const volatile
01577         {
01578                 return true;
01579         }
01580         
01581         BOOST_ATOMIC_DECLARE_BASE_OPERATORS
01582 private:
01583         base_atomic(const base_atomic &) /* = delete */ ;
01584         void operator=(const base_atomic &) /* = delete */ ;
01585         value_type v_;
01586 };
01587 
01588 template<typename T, bool Sign>
01589 class base_atomic<T *, void *, 4, Sign> {
01590         typedef base_atomic this_type;
01591         typedef T * value_type;
01592         typedef ptrdiff_t difference_type;
01593 public:
01594         explicit base_atomic(value_type v) : v_(v) {}
01595         base_atomic(void) {}
01596         
01597         void
01598         store(value_type v, memory_order order = memory_order_seq_cst) volatile
01599         {
01600                 ppc_fence_before(order);
01601                 __asm__ (
01602                         "stw %1, %0\n"
01603                         : "+m" (v_)
01604                         : "r" (v)
01605                 );
01606                 ppc_fence_after_store(order);
01607         }
01608         
01609         value_type
01610         load(memory_order order = memory_order_seq_cst) const volatile
01611         {
01612                 value_type v;
01613                 __asm__ (
01614                         "lwz %0, %1\n"
01615                         "cmpw %0, %0\n"
01616                         "bne- 1f\n"
01617                         "1:\n"
01618                         : "=r"(v)
01619                         : "m"(v_)
01620                         : "cr0"
01621                 );
01622                 ppc_fence_after(order);
01623                 return v;
01624         }
01625         
01626         value_type
01627         exchange(value_type v, memory_order order = memory_order_seq_cst) volatile
01628         {
01629                 value_type original;
01630                 ppc_fence_before(order);
01631                 __asm__ (
01632                         "1:\n"
01633                         "lwarx %0,%y1\n"
01634                         "stwcx. %2,%y1\n"
01635                         "bne- 1b\n"
01636                         : "=&b" (original), "+Z"(v_)
01637                         : "b" (v)
01638                         : "cr0"
01639                 );
01640                 ppc_fence_after(order);
01641                 return original;
01642         }
01643         
01644         bool
01645         compare_exchange_weak(
01646                 value_type & expected,
01647                 value_type desired,
01648                 memory_order success_order,
01649                 memory_order failure_order) volatile
01650         {
01651                 int success;
01652                 ppc_fence_before(success_order);
01653                 __asm__(
01654                         "lwarx %0,%y2\n"
01655                         "cmpw %0, %3\n"
01656                         "bne- 2f\n"
01657                         "stwcx. %4,%y2\n"
01658                         "bne- 2f\n"
01659                         "addi %1,0,1\n"
01660                         "1:"
01661                         
01662                         BOOST_ATOMIC_ASM_SLOWPATH_CLEAR
01663                         : "=&b" (expected), "=&b" (success), "+Z"(v_)
01664                         : "b" (expected), "b" (desired)
01665                         : "cr0"
01666                 );
01667                 if (success)
01668                         ppc_fence_after(success_order);
01669                 else
01670                         ppc_fence_after(failure_order);
01671                 return success;
01672         }
01673         
01674         bool
01675         compare_exchange_strong(
01676                 value_type & expected,
01677                 value_type desired,
01678                 memory_order success_order,
01679                 memory_order failure_order) volatile
01680         {
01681                 int success;
01682                 ppc_fence_before(success_order);
01683                 __asm__(
01684                         "0: lwarx %0,%y2\n"
01685                         "cmpw %0, %3\n"
01686                         "bne- 2f\n"
01687                         "stwcx. %4,%y2\n"
01688                         "bne- 0b\n"
01689                         "addi %1,0,1\n"
01690                         "1:"
01691                         
01692                         BOOST_ATOMIC_ASM_SLOWPATH_CLEAR
01693                         : "=&b" (expected), "=&b" (success), "+Z"(v_)
01694                         : "b" (expected), "b" (desired)
01695                         : "cr0"
01696                 );
01697                 if (success)
01698                         ppc_fence_after(success_order);
01699                 else
01700                         ppc_fence_after(failure_order);
01701                 return success;
01702         }
01703         
01704         value_type
01705         fetch_add(difference_type v, memory_order order = memory_order_seq_cst) volatile
01706         {
01707                 v = v * sizeof(*v_);
01708                 value_type original, tmp;
01709                 ppc_fence_before(order);
01710                 __asm__ (
01711                         "1:\n"
01712                         "lwarx %0,%y2\n"
01713                         "add %1,%0,%3\n"
01714                         "stwcx. %1,%y2\n"
01715                         "bne- 1b\n"
01716                         : "=&b" (original), "=&b" (tmp), "+Z"(v_)
01717                         : "b" (v)
01718                         : "cc");
01719                 ppc_fence_after(order);
01720                 return original;
01721         }
01722         
01723         value_type
01724         fetch_sub(difference_type v, memory_order order = memory_order_seq_cst) volatile
01725         {
01726                 v = v * sizeof(*v_);
01727                 value_type original, tmp;
01728                 ppc_fence_before(order);
01729                 __asm__ (
01730                         "1:\n"
01731                         "lwarx %0,%y2\n"
01732                         "sub %1,%0,%3\n"
01733                         "stwcx. %1,%y2\n"
01734                         "bne- 1b\n"
01735                         : "=&b" (original), "=&b" (tmp), "+Z"(v_)
01736                         : "b" (v)
01737                         : "cc");
01738                 ppc_fence_after(order);
01739                 return original;
01740         }
01741         
01742         bool
01743         is_lock_free(void) const volatile
01744         {
01745                 return true;
01746         }
01747         
01748         BOOST_ATOMIC_DECLARE_POINTER_OPERATORS
01749 private:
01750         base_atomic(const base_atomic &) /* = delete */ ;
01751         void operator=(const base_atomic &) /* = delete */ ;
01752         value_type v_;
01753 };
01754 
01755 #else
01756 
01757 template<bool Sign>
01758 class base_atomic<void *, void *, 8, Sign> {
01759         typedef base_atomic this_type;
01760         typedef void * value_type;
01761 public:
01762         explicit base_atomic(value_type v) : v_(v) {}
01763         base_atomic(void) {}
01764         
01765         void
01766         store(value_type v, memory_order order = memory_order_seq_cst) volatile
01767         {
01768                 ppc_fence_before(order);
01769                 __asm__ (
01770                         "std %1, %0\n"
01771                         : "+m" (v_)
01772                         : "r" (v)
01773                 );
01774                 ppc_fence_after_store(order);
01775         }
01776         
01777         value_type
01778         load(memory_order order = memory_order_seq_cst) const volatile
01779         {
01780                 value_type v;
01781                 __asm__ (
01782                         "ld %0, %1\n"
01783                         "cmpd %0, %0\n"
01784                         "bne- 1f\n"
01785                         "1:\n"
01786                         : "=r"(v)
01787                         : "m"(v_)
01788                         : "cr0"
01789                 );
01790                 ppc_fence_after(order);
01791                 return v;
01792         }
01793         
01794         value_type
01795         exchange(value_type v, memory_order order = memory_order_seq_cst) volatile
01796         {
01797                 value_type original;
01798                 ppc_fence_before(order);
01799                 __asm__ (
01800                         "1:\n"
01801                         "ldarx %0,%y1\n"
01802                         "stdcx. %2,%y1\n"
01803                         "bne- 1b\n"
01804                         : "=&b" (original), "+Z"(v_)
01805                         : "b" (v)
01806                         : "cr0"
01807                 );
01808                 ppc_fence_after(order);
01809                 return original;
01810         }
01811         
01812         bool
01813         compare_exchange_weak(
01814                 value_type & expected,
01815                 value_type desired,
01816                 memory_order success_order,
01817                 memory_order failure_order) volatile
01818         {
01819                 int success;
01820                 ppc_fence_before(success_order);
01821                 __asm__(
01822                         "ldarx %0,%y2\n"
01823                         "cmpd %0, %3\n"
01824                         "bne- 2f\n"
01825                         "stdcx. %4,%y2\n"
01826                         "bne- 2f\n"
01827                         "addi %1,0,1\n"
01828                         "1:"
01829                         
01830                         BOOST_ATOMIC_ASM_SLOWPATH_CLEAR
01831                         : "=&b" (expected), "=&b" (success), "+Z"(v_)
01832                         : "b" (expected), "b" (desired)
01833                         : "cr0"
01834                 );
01835                 if (success)
01836                         ppc_fence_after(success_order);
01837                 else
01838                         ppc_fence_after(failure_order);
01839                 return success;
01840         }
01841         
01842         bool
01843         compare_exchange_strong(
01844                 value_type & expected,
01845                 value_type desired,
01846                 memory_order success_order,
01847                 memory_order failure_order) volatile
01848         {
01849                 int success;
01850                 ppc_fence_before(success_order);
01851                 __asm__(
01852                         "0: ldarx %0,%y2\n"
01853                         "cmpd %0, %3\n"
01854                         "bne- 2f\n"
01855                         "stdcx. %4,%y2\n"
01856                         "bne- 0b\n"
01857                         "addi %1,0,1\n"
01858                         "1:"
01859                         
01860                         BOOST_ATOMIC_ASM_SLOWPATH_CLEAR
01861                         : "=&b" (expected), "=&b" (success), "+Z"(v_)
01862                         : "b" (expected), "b" (desired)
01863                         : "cr0"
01864                 );
01865                 if (success)
01866                         ppc_fence_after(success_order);
01867                 else
01868                         ppc_fence_after(failure_order);
01869                 return success;
01870         }
01871         
01872         bool
01873         is_lock_free(void) const volatile
01874         {
01875                 return true;
01876         }
01877         
01878         BOOST_ATOMIC_DECLARE_BASE_OPERATORS
01879 private:
01880         base_atomic(const base_atomic &) /* = delete */ ;
01881         void operator=(const base_atomic &) /* = delete */ ;
01882         value_type v_;
01883 };
01884 
01885 template<typename T, bool Sign>
01886 class base_atomic<T *, void *, 8, Sign> {
01887         typedef base_atomic this_type;
01888         typedef T * value_type;
01889         typedef ptrdiff_t difference_type;
01890 public:
01891         explicit base_atomic(value_type v) : v_(v) {}
01892         base_atomic(void) {}
01893         
01894         void
01895         store(value_type v, memory_order order = memory_order_seq_cst) volatile
01896         {
01897                 ppc_fence_before(order);
01898                 __asm__ (
01899                         "std %1, %0\n"
01900                         : "+m" (v_)
01901                         : "r" (v)
01902                 );
01903                 ppc_fence_after_store(order);
01904         }
01905         
01906         value_type
01907         load(memory_order order = memory_order_seq_cst) const volatile
01908         {
01909                 value_type v;
01910                 __asm__ (
01911                         "ld %0, %1\n"
01912                         "cmpd %0, %0\n"
01913                         "bne- 1f\n"
01914                         "1:\n"
01915                         : "=r"(v)
01916                         : "m"(v_)
01917                         : "cr0"
01918                 );
01919                 ppc_fence_after(order);
01920                 return v;
01921         }
01922         
01923         value_type
01924         exchange(value_type v, memory_order order = memory_order_seq_cst) volatile
01925         {
01926                 value_type original;
01927                 ppc_fence_before(order);
01928                 __asm__ (
01929                         "1:\n"
01930                         "ldarx %0,%y1\n"
01931                         "stdcx. %2,%y1\n"
01932                         "bne- 1b\n"
01933                         : "=&b" (original), "+Z"(v_)
01934                         : "b" (v)
01935                         : "cr0"
01936                 );
01937                 ppc_fence_after(order);
01938                 return original;
01939         }
01940         
01941         bool
01942         compare_exchange_weak(
01943                 value_type & expected,
01944                 value_type desired,
01945                 memory_order success_order,
01946                 memory_order failure_order) volatile
01947         {
01948                 int success;
01949                 ppc_fence_before(success_order);
01950                 __asm__(
01951                         "ldarx %0,%y2\n"
01952                         "cmpd %0, %3\n"
01953                         "bne- 2f\n"
01954                         "stdcx. %4,%y2\n"
01955                         "bne- 2f\n"
01956                         "addi %1,0,1\n"
01957                         "1:"
01958                         
01959                         BOOST_ATOMIC_ASM_SLOWPATH_CLEAR
01960                         : "=&b" (expected), "=&b" (success), "+Z"(v_)
01961                         : "b" (expected), "b" (desired)
01962                         : "cr0"
01963                 );
01964                 if (success)
01965                         ppc_fence_after(success_order);
01966                 else
01967                         ppc_fence_after(failure_order);
01968                 return success;
01969         }
01970         
01971         bool
01972         compare_exchange_strong(
01973                 value_type & expected,
01974                 value_type desired,
01975                 memory_order success_order,
01976                 memory_order failure_order) volatile
01977         {
01978                 int success;
01979                 ppc_fence_before(success_order);
01980                 __asm__(
01981                         "0: ldarx %0,%y2\n"
01982                         "cmpd %0, %3\n"
01983                         "bne- 2f\n"
01984                         "stdcx. %4,%y2\n"
01985                         "bne- 0b\n"
01986                         "addi %1,0,1\n"
01987                         "1:"
01988                         
01989                         BOOST_ATOMIC_ASM_SLOWPATH_CLEAR
01990                         : "=&b" (expected), "=&b" (success), "+Z"(v_)
01991                         : "b" (expected), "b" (desired)
01992                         : "cr0"
01993                 );
01994                 if (success)
01995                         ppc_fence_after(success_order);
01996                 else
01997                         ppc_fence_after(failure_order);
01998                 return success;
01999         }
02000         
02001         value_type
02002         fetch_add(difference_type v, memory_order order = memory_order_seq_cst) volatile
02003         {
02004                 v = v * sizeof(*v_);
02005                 value_type original, tmp;
02006                 ppc_fence_before(order);
02007                 __asm__ (
02008                         "1:\n"
02009                         "ldarx %0,%y2\n"
02010                         "add %1,%0,%3\n"
02011                         "stdcx. %1,%y2\n"
02012                         "bne- 1b\n"
02013                         : "=&b" (original), "=&b" (tmp), "+Z"(v_)
02014                         : "b" (v)
02015                         : "cc");
02016                 ppc_fence_after(order);
02017                 return original;
02018         }
02019         
02020         value_type
02021         fetch_sub(difference_type v, memory_order order = memory_order_seq_cst) volatile
02022         {
02023                 v = v * sizeof(*v_);
02024                 value_type original, tmp;
02025                 ppc_fence_before(order);
02026                 __asm__ (
02027                         "1:\n"
02028                         "ldarx %0,%y2\n"
02029                         "sub %1,%0,%3\n"
02030                         "stdcx. %1,%y2\n"
02031                         "bne- 1b\n"
02032                         : "=&b" (original), "=&b" (tmp), "+Z"(v_)
02033                         : "b" (v)
02034                         : "cc");
02035                 ppc_fence_after(order);
02036                 return original;
02037         }
02038         
02039         bool
02040         is_lock_free(void) const volatile
02041         {
02042                 return true;
02043         }
02044         
02045         BOOST_ATOMIC_DECLARE_POINTER_OPERATORS
02046 private:
02047         base_atomic(const base_atomic &) /* = delete */ ;
02048         void operator=(const base_atomic &) /* = delete */ ;
02049         value_type v_;
02050 };
02051 
02052 #endif
02053 
02054 /* generic */
02055 
02056 template<typename T, bool Sign>
02057 class base_atomic<T, void, 1, Sign> {
02058         typedef base_atomic this_type;
02059         typedef T value_type;
02060         typedef uint32_t storage_type;
02061 public:
02062         explicit base_atomic(value_type v) : v_(0)
02063         {
02064                 memcpy(&v_, &v, sizeof(value_type));
02065         }
02066         base_atomic(void) : v_(0) {}
02067         
02068         void
02069         store(value_type v, memory_order order = memory_order_seq_cst) volatile
02070         {
02071                 storage_type tmp = 0;
02072                 memcpy(&tmp, &v, sizeof(value_type));
02073                 ppc_fence_before(order);
02074                 __asm__ (
02075                         "stw %1, %0\n"
02076                         : "+m" (v_)
02077                         : "r" (tmp)
02078                 );
02079                 ppc_fence_after_store(order);
02080         }
02081         
02082         value_type
02083         load(memory_order order = memory_order_seq_cst) const volatile
02084         {
02085                 storage_type tmp;
02086                 __asm__ __volatile__ (
02087                         "lwz %0, %1\n"
02088                         "cmpw %0, %0\n"
02089                         "bne- 1f\n"
02090                         "1:\n"
02091                         : "=r"(tmp)
02092                         : "m"(v_)
02093                         : "cr0"
02094                 );
02095                 ppc_fence_after(order);
02096                 
02097                 value_type v;
02098                 memcpy(&v, &tmp, sizeof(value_type));
02099                 return v;
02100         }
02101         
02102         value_type
02103         exchange(value_type v, memory_order order = memory_order_seq_cst) volatile
02104         {
02105                 storage_type tmp = 0, original;
02106                 memcpy(&tmp, &v, sizeof(value_type));
02107                 ppc_fence_before(order);
02108                 __asm__ (
02109                         "1:\n"
02110                         "lwarx %0,%y1\n"
02111                         "stwcx. %2,%y1\n"
02112                         "bne- 1b\n"
02113                         : "=&b" (original), "+Z"(v_)
02114                         : "b" (tmp)
02115                         : "cr0"
02116                 );
02117                 ppc_fence_after(order);
02118                 memcpy(&v, &original, sizeof(value_type));
02119                 return v;
02120         }
02121         
02122         bool
02123         compare_exchange_weak(
02124                 value_type & expected,
02125                 value_type desired,
02126                 memory_order success_order,
02127                 memory_order failure_order) volatile
02128         {
02129                 storage_type expected_s = 0, desired_s = 0;
02130                 memcpy(&expected_s, &expected, sizeof(value_type));
02131                 memcpy(&desired_s, &desired, sizeof(value_type));
02132                 
02133                 int success;
02134                 ppc_fence_before(success_order);
02135                 __asm__(
02136                         "lwarx %0,%y2\n"
02137                         "cmpw %0, %3\n"
02138                         "bne- 2f\n"
02139                         "stwcx. %4,%y2\n"
02140                         "bne- 2f\n"
02141                         "addi %1,0,1\n"
02142                         "1:"
02143                         
02144                         BOOST_ATOMIC_ASM_SLOWPATH_CLEAR
02145                         : "=&b" (expected_s), "=&b" (success), "+Z"(v_)
02146                         : "b" (expected_s), "b" (desired_s)
02147                         : "cr0"
02148                 );
02149                 if (success)
02150                         ppc_fence_after(success_order);
02151                 else
02152                         ppc_fence_after(failure_order);
02153                 memcpy(&expected, &expected_s, sizeof(value_type));
02154                 return success;
02155         }
02156         
02157         bool
02158         compare_exchange_strong(
02159                 value_type & expected,
02160                 value_type desired,
02161                 memory_order success_order,
02162                 memory_order failure_order) volatile
02163         {
02164                 storage_type expected_s = 0, desired_s = 0;
02165                 memcpy(&expected_s, &expected, sizeof(value_type));
02166                 memcpy(&desired_s, &desired, sizeof(value_type));
02167                 
02168                 int success;
02169                 ppc_fence_before(success_order);
02170                 __asm__(
02171                         "0: lwarx %0,%y2\n"
02172                         "cmpw %0, %3\n"
02173                         "bne- 2f\n"
02174                         "stwcx. %4,%y2\n"
02175                         "bne- 0b\n"
02176                         "addi %1,0,1\n"
02177                         "1:"
02178                         
02179                         BOOST_ATOMIC_ASM_SLOWPATH_CLEAR
02180                         : "=&b" (expected_s), "=&b" (success), "+Z"(v_)
02181                         : "b" (expected_s), "b" (desired_s)
02182                         : "cr0"
02183                 );
02184                 if (success)
02185                         ppc_fence_after(success_order);
02186                 else
02187                         ppc_fence_after(failure_order);
02188                 memcpy(&expected, &expected_s, sizeof(value_type));
02189                 return success;
02190         }
02191         
02192         bool
02193         is_lock_free(void) const volatile
02194         {
02195                 return true;
02196         }
02197         
02198         BOOST_ATOMIC_DECLARE_BASE_OPERATORS
02199 private:
02200         base_atomic(const base_atomic &) /* = delete */ ;
02201         void operator=(const base_atomic &) /* = delete */ ;
02202         storage_type v_;
02203 };
02204 
02205 template<typename T, bool Sign>
02206 class base_atomic<T, void, 2, Sign> {
02207         typedef base_atomic this_type;
02208         typedef T value_type;
02209         typedef uint32_t storage_type;
02210 public:
02211         explicit base_atomic(value_type v) : v_(0)
02212         {
02213                 memcpy(&v_, &v, sizeof(value_type));
02214         }
02215         base_atomic(void) : v_(0) {}
02216         
02217         void
02218         store(value_type v, memory_order order = memory_order_seq_cst) volatile
02219         {
02220                 storage_type tmp = 0;
02221                 memcpy(&tmp, &v, sizeof(value_type));
02222                 ppc_fence_before(order);
02223                 __asm__ (
02224                         "stw %1, %0\n"
02225                         : "+m" (v_)
02226                         : "r" (tmp)
02227                 );
02228                 ppc_fence_after_store(order);
02229         }
02230         
02231         value_type
02232         load(memory_order order = memory_order_seq_cst) const volatile
02233         {
02234                 storage_type tmp;
02235                 __asm__ __volatile__ (
02236                         "lwz %0, %1\n"
02237                         "cmpw %0, %0\n"
02238                         "bne- 1f\n"
02239                         "1:\n"
02240                         : "=r"(tmp)
02241                         : "m"(v_)
02242                         : "cr0"
02243                 );
02244                 ppc_fence_after(order);
02245                 
02246                 value_type v;
02247                 memcpy(&v, &tmp, sizeof(value_type));
02248                 return v;
02249         }
02250         
02251         value_type
02252         exchange(value_type v, memory_order order = memory_order_seq_cst) volatile
02253         {
02254                 storage_type tmp = 0, original;
02255                 memcpy(&tmp, &v, sizeof(value_type));
02256                 ppc_fence_before(order);
02257                 __asm__ (
02258                         "1:\n"
02259                         "lwarx %0,%y1\n"
02260                         "stwcx. %2,%y1\n"
02261                         "bne- 1b\n"
02262                         : "=&b" (original), "+Z"(v_)
02263                         : "b" (tmp)
02264                         : "cr0"
02265                 );
02266                 ppc_fence_after(order);
02267                 memcpy(&v, &original, sizeof(value_type));
02268                 return v;
02269         }
02270         
02271         bool
02272         compare_exchange_weak(
02273                 value_type & expected,
02274                 value_type desired,
02275                 memory_order success_order,
02276                 memory_order failure_order) volatile
02277         {
02278                 storage_type expected_s = 0, desired_s = 0;
02279                 memcpy(&expected_s, &expected, sizeof(value_type));
02280                 memcpy(&desired_s, &desired, sizeof(value_type));
02281                 
02282                 int success;
02283                 ppc_fence_before(success_order);
02284                 __asm__(
02285                         "lwarx %0,%y2\n"
02286                         "cmpw %0, %3\n"
02287                         "bne- 2f\n"
02288                         "stwcx. %4,%y2\n"
02289                         "bne- 2f\n"
02290                         "addi %1,0,1\n"
02291                         "1:"
02292                         
02293                         BOOST_ATOMIC_ASM_SLOWPATH_CLEAR
02294                         : "=&b" (expected_s), "=&b" (success), "+Z"(v_)
02295                         : "b" (expected_s), "b" (desired_s)
02296                         : "cr0"
02297                 );
02298                 if (success)
02299                         ppc_fence_after(success_order);
02300                 else
02301                         ppc_fence_after(failure_order);
02302                 memcpy(&expected, &expected_s, sizeof(value_type));
02303                 return success;
02304         }
02305         
02306         bool
02307         compare_exchange_strong(
02308                 value_type & expected,
02309                 value_type desired,
02310                 memory_order success_order,
02311                 memory_order failure_order) volatile
02312         {
02313                 storage_type expected_s = 0, desired_s = 0;
02314                 memcpy(&expected_s, &expected, sizeof(value_type));
02315                 memcpy(&desired_s, &desired, sizeof(value_type));
02316                 
02317                 int success;
02318                 ppc_fence_before(success_order);
02319                 __asm__(
02320                         "0: lwarx %0,%y2\n"
02321                         "cmpw %0, %3\n"
02322                         "bne- 2f\n"
02323                         "stwcx. %4,%y2\n"
02324                         "bne- 0b\n"
02325                         "addi %1,0,1\n"
02326                         "1:"
02327                         
02328                         BOOST_ATOMIC_ASM_SLOWPATH_CLEAR
02329                         : "=&b" (expected_s), "=&b" (success), "+Z"(v_)
02330                         : "b" (expected_s), "b" (desired_s)
02331                         : "cr0"
02332                 );
02333                 if (success)
02334                         ppc_fence_after(success_order);
02335                 else
02336                         ppc_fence_after(failure_order);
02337                 memcpy(&expected, &expected_s, sizeof(value_type));
02338                 return success;
02339         }
02340         
02341         bool
02342         is_lock_free(void) const volatile
02343         {
02344                 return true;
02345         }
02346         
02347         BOOST_ATOMIC_DECLARE_BASE_OPERATORS
02348 private:
02349         base_atomic(const base_atomic &) /* = delete */ ;
02350         void operator=(const base_atomic &) /* = delete */ ;
02351         storage_type v_;
02352 };
02353 
02354 template<typename T, bool Sign>
02355 class base_atomic<T, void, 4, Sign> {
02356         typedef base_atomic this_type;
02357         typedef T value_type;
02358         typedef uint32_t storage_type;
02359 public:
02360         explicit base_atomic(value_type v) : v_(0)
02361         {
02362                 memcpy(&v_, &v, sizeof(value_type));
02363         }
02364         base_atomic(void) : v_(0) {}
02365         
02366         void
02367         store(value_type v, memory_order order = memory_order_seq_cst) volatile
02368         {
02369                 storage_type tmp = 0;
02370                 memcpy(&tmp, &v, sizeof(value_type));
02371                 ppc_fence_before(order);
02372                 __asm__ (
02373                         "stw %1, %0\n"
02374                         : "+m" (v_)
02375                         : "r" (tmp)
02376                 );
02377                 ppc_fence_after_store(order);
02378         }
02379         
02380         value_type
02381         load(memory_order order = memory_order_seq_cst) const volatile
02382         {
02383                 storage_type tmp;
02384                 __asm__ __volatile__ (
02385                         "lwz %0, %1\n"
02386                         "cmpw %0, %0\n"
02387                         "bne- 1f\n"
02388                         "1:\n"
02389                         : "=r"(tmp)
02390                         : "m"(v_)
02391                         : "cr0"
02392                 );
02393                 ppc_fence_after(order);
02394                 
02395                 value_type v;
02396                 memcpy(&v, &tmp, sizeof(value_type));
02397                 return v;
02398         }
02399         
02400         value_type
02401         exchange(value_type v, memory_order order = memory_order_seq_cst) volatile
02402         {
02403                 storage_type tmp = 0, original;
02404                 memcpy(&tmp, &v, sizeof(value_type));
02405                 ppc_fence_before(order);
02406                 __asm__ (
02407                         "1:\n"
02408                         "lwarx %0,%y1\n"
02409                         "stwcx. %2,%y1\n"
02410                         "bne- 1b\n"
02411                         : "=&b" (original), "+Z"(v_)
02412                         : "b" (tmp)
02413                         : "cr0"
02414                 );
02415                 ppc_fence_after(order);
02416                 memcpy(&v, &original, sizeof(value_type));
02417                 return v;
02418         }
02419         
02420         bool
02421         compare_exchange_weak(
02422                 value_type & expected,
02423                 value_type desired,
02424                 memory_order success_order,
02425                 memory_order failure_order) volatile
02426         {
02427                 storage_type expected_s = 0, desired_s = 0;
02428                 memcpy(&expected_s, &expected, sizeof(value_type));
02429                 memcpy(&desired_s, &desired, sizeof(value_type));
02430                 
02431                 int success;
02432                 ppc_fence_before(success_order);
02433                 __asm__(
02434                         "lwarx %0,%y2\n"
02435                         "cmpw %0, %3\n"
02436                         "bne- 2f\n"
02437                         "stwcx. %4,%y2\n"
02438                         "bne- 2f\n"
02439                         "addi %1,0,1\n"
02440                         "1:"
02441                         
02442                         BOOST_ATOMIC_ASM_SLOWPATH_CLEAR
02443                         : "=&b" (expected_s), "=&b" (success), "+Z"(v_)
02444                         : "b" (expected_s), "b" (desired_s)
02445                         : "cr0"
02446                 );
02447                 if (success)
02448                         ppc_fence_after(success_order);
02449                 else
02450                         ppc_fence_after(failure_order);
02451                 memcpy(&expected, &expected_s, sizeof(value_type));
02452                 return success;
02453         }
02454         
02455         bool
02456         compare_exchange_strong(
02457                 value_type & expected,
02458                 value_type desired,
02459                 memory_order success_order,
02460                 memory_order failure_order) volatile
02461         {
02462                 storage_type expected_s = 0, desired_s = 0;
02463                 memcpy(&expected_s, &expected, sizeof(value_type));
02464                 memcpy(&desired_s, &desired, sizeof(value_type));
02465                 
02466                 int success;
02467                 ppc_fence_before(success_order);
02468                 __asm__(
02469                         "0: lwarx %0,%y2\n"
02470                         "cmpw %0, %3\n"
02471                         "bne- 2f\n"
02472                         "stwcx. %4,%y2\n"
02473                         "bne- 0b\n"
02474                         "addi %1,0,1\n"
02475                         "1:"
02476                         
02477                         BOOST_ATOMIC_ASM_SLOWPATH_CLEAR
02478                         : "=&b" (expected_s), "=&b" (success), "+Z"(v_)
02479                         : "b" (expected_s), "b" (desired_s)
02480                         : "cr0"
02481                 );
02482                 if (success)
02483                         ppc_fence_after(success_order);
02484                 else
02485                         ppc_fence_after(failure_order);
02486                 memcpy(&expected, &expected_s, sizeof(value_type));
02487                 return success;
02488         }
02489         
02490         bool
02491         is_lock_free(void) const volatile
02492         {
02493                 return true;
02494         }
02495         
02496         BOOST_ATOMIC_DECLARE_BASE_OPERATORS
02497 private:
02498         base_atomic(const base_atomic &) /* = delete */ ;
02499         void operator=(const base_atomic &) /* = delete */ ;
02500         storage_type v_;
02501 };
02502 
02503 #if defined(__powerpc64__)
02504 
02505 template<typename T, bool Sign>
02506 class base_atomic<T, void, 8, Sign> {
02507         typedef base_atomic this_type;
02508         typedef T value_type;
02509         typedef uint64_t storage_type;
02510 public:
02511         explicit base_atomic(value_type v)
02512         {
02513                 memcpy(&v_, &v, sizeof(value_type));
02514         }
02515         base_atomic(void) {}
02516         
02517         void
02518         store(value_type v, memory_order order = memory_order_seq_cst) volatile
02519         {
02520                 storage_type tmp;
02521                 memcpy(&tmp, &v, sizeof(value_type));
02522                 ppc_fence_before(order);
02523                 __asm__ (
02524                         "std %1, %0\n"
02525                         : "+m" (v_)
02526                         : "r" (tmp)
02527                 );
02528                 ppc_fence_after_store(order);
02529         }
02530         
02531         value_type
02532         load(memory_order order = memory_order_seq_cst) const volatile
02533         {
02534                 storage_type tmp;
02535                 __asm__ __volatile__ (
02536                         "ld %0, %1\n"
02537                         "cmpd %0, %0\n"
02538                         "bne- 1f\n"
02539                         "1:\n"
02540                         : "=r"(tmp)
02541                         : "m"(v_)
02542                         : "cr0"
02543                 );
02544                 ppc_fence_after(order);
02545                 
02546                 value_type v;
02547                 memcpy(&v, &tmp, sizeof(value_type));
02548                 return v;
02549         }
02550         
02551         value_type
02552         exchange(value_type v, memory_order order = memory_order_seq_cst) volatile
02553         {
02554                 storage_type tmp = 0, original;
02555                 memcpy(&tmp, &v, sizeof(value_type));
02556                 ppc_fence_before(order);
02557                 __asm__ (
02558                         "1:\n"
02559                         "ldarx %0,%y1\n"
02560                         "stdcx. %2,%y1\n"
02561                         "bne- 1b\n"
02562                         : "=&b" (original), "+Z"(v_)
02563                         : "b" (tmp)
02564                         : "cr0"
02565                 );
02566                 ppc_fence_after(order);
02567                 memcpy(&v, &original, sizeof(value_type));
02568                 return v;
02569         }
02570         
02571         bool
02572         compare_exchange_weak(
02573                 value_type & expected,
02574                 value_type desired,
02575                 memory_order success_order,
02576                 memory_order failure_order) volatile
02577         {
02578                 storage_type expected_s, desired_s;
02579                 memcpy(&expected_s, &expected, sizeof(value_type));
02580                 memcpy(&desired_s, &desired, sizeof(value_type));
02581                 
02582                 int success;
02583                 ppc_fence_before(success_order);
02584                 __asm__(
02585                         "ldarx %0,%y2\n"
02586                         "cmpd %0, %3\n"
02587                         "bne- 2f\n"
02588                         "stdcx. %4,%y2\n"
02589                         "bne- 2f\n"
02590                         "addi %1,0,1\n"
02591                         "1:"
02592                         
02593                         BOOST_ATOMIC_ASM_SLOWPATH_CLEAR
02594                         : "=&b" (expected_s), "=&b" (success), "+Z"(v_)
02595                         : "b" (expected_s), "b" (desired_s)
02596                         : "cr0"
02597                 );
02598                 if (success)
02599                         ppc_fence_after(success_order);
02600                 else
02601                         ppc_fence_after(failure_order);
02602                 memcpy(&expected, &expected_s, sizeof(value_type));
02603                 return success;
02604         }
02605         
02606         bool
02607         compare_exchange_strong(
02608                 value_type & expected,
02609                 value_type desired,
02610                 memory_order success_order,
02611                 memory_order failure_order) volatile
02612         {
02613                 storage_type expected_s, desired_s;
02614                 memcpy(&expected_s, &expected, sizeof(value_type));
02615                 memcpy(&desired_s, &desired, sizeof(value_type));
02616                 
02617                 int success;
02618                 ppc_fence_before(success_order);
02619                 __asm__(
02620                         "0: ldarx %0,%y2\n"
02621                         "cmpd %0, %3\n"
02622                         "bne- 2f\n"
02623                         "stdcx. %4,%y2\n"
02624                         "bne- 0b\n"
02625                         "addi %1,0,1\n"
02626                         "1:"
02627                         
02628                         BOOST_ATOMIC_ASM_SLOWPATH_CLEAR
02629                         : "=&b" (expected_s), "=&b" (success), "+Z"(v_)
02630                         : "b" (expected_s), "b" (desired_s)
02631                         : "cr0"
02632                 );
02633                 if (success)
02634                         ppc_fence_after(success_order);
02635                 else
02636                         ppc_fence_after(failure_order);
02637                 memcpy(&expected, &expected_s, sizeof(value_type));
02638                 return success;
02639         }
02640         
02641         bool
02642         is_lock_free(void) const volatile
02643         {
02644                 return true;
02645         }
02646         
02647         BOOST_ATOMIC_DECLARE_BASE_OPERATORS
02648 private:
02649         base_atomic(const base_atomic &) /* = delete */ ;
02650         void operator=(const base_atomic &) /* = delete */ ;
02651         storage_type v_;
02652 };
02653 #endif
02654 
02655 }
02656 }
02657 
02658 #define BOOST_ATOMIC_THREAD_FENCE 2
02659 inline void
02660 atomic_thread_fence(memory_order order)
02661 {
02662         switch(order) {
02663                 case memory_order_acquire:
02664                         __asm__ __volatile__ ("isync" ::: "memory");
02665                         break;
02666                 case memory_order_release:
02667 #if defined(__powerpc64__)
02668                         __asm__ __volatile__ ("lwsync" ::: "memory");
02669                         break;
02670 #endif
02671                 case memory_order_acq_rel:
02672                 case memory_order_seq_cst:
02673                         __asm__ __volatile__ ("sync" ::: "memory");
02674                 default:;
02675         }
02676 }
02677 
02678 #define BOOST_ATOMIC_SIGNAL_FENCE 2
02679 inline void
02680 atomic_signal_fence(memory_order order)
02681 {
02682         switch(order) {
02683                 case memory_order_acquire:
02684                 case memory_order_release:
02685                 case memory_order_acq_rel:
02686                 case memory_order_seq_cst:
02687                         __asm__ __volatile__ ("" ::: "memory");
02688                         break;
02689                 default:;
02690         }
02691 }
02692 
02693 }
02694 
02695 #endif


rosatomic
Author(s): Josh Faust
autogenerated on Mon Oct 6 2014 06:54:49