00001 #ifndef BOOST_ATOMIC_DETAIL_ATOMIC_GCC_PPC_HPP
00002 #define BOOST_ATOMIC_DETAIL_ATOMIC_GCC_PPC_HPP
00003 
00004 
00005 
00006 
00007 
00008 
00009 
00010 #include "base.hpp"
00011 #include "builder.hpp"
00012 
00013 
00014 
00015 
00016 
00017 
00018 
00019 
00020 
00021 namespace boost_atomic {
00022 namespace detail {
00023 namespace atomic {
00024 
00025 static inline void fence_before(memory_order2 order)
00026 {
00027         switch(order) {
00028                 case memory_order2_release:
00029                 case memory_order2_acq_rel:
00030 #if defined(__powerpc64__)
00031                         __asm__ __volatile__ ("lwsync" ::: "memory");
00032                         break;
00033 #endif
00034                 case memory_order2_seq_cst:
00035                         __asm__ __volatile__ ("sync" ::: "memory");
00036                 default:;
00037         }
00038 }
00039 
00040 
00041 
00042 
00043 
00044 
00045 
00046 
00047 
00048 
00049 
00050 
00051 
00052 
00053 
00054 
00055 
00056 
00057 
00058 
00059 
00060 
00061 
00062 static inline void fence_after(memory_order2 order)
00063 {
00064         switch(order) {
00065                 case memory_order2_acquire:
00066                 case memory_order2_acq_rel:
00067                 case memory_order2_seq_cst:
00068                         __asm__ __volatile__ ("isync");
00069                 case memory_order2_consume:
00070                         __asm__ __volatile__ ("" ::: "memory");
00071                 default:;
00072         }
00073 }
00074 
00075 template<>
00076 inline void platform_atomic_thread_fence(memory_order2 order)
00077 {
00078         switch(order) {
00079                 case memory_order2_acquire:
00080                         __asm__ __volatile__ ("isync" ::: "memory");
00081                         break;
00082                 case memory_order2_release:
00083                 case memory_order2_acq_rel:
00084 #if defined(__powerpc64__)
00085                         __asm__ __volatile__ ("lwsync" ::: "memory");
00086                         break;
00087 #endif
00088                 case memory_order2_seq_cst:
00089                         __asm__ __volatile__ ("sync" ::: "memory");
00090                 default:;
00091         }
00092 }
00093 
00094 
00095 
00096 
00097 
00098 
00099 
00100 
00101 template<typename T>
00102 class atomic_ppc_32 {
00103 public:
00104         typedef T integral_type;
00105         explicit atomic_ppc_32(T v) : i(v) {}
00106         atomic_ppc_32() {}
00107         T load(memory_order2 order=memory_order2_seq_cst) const volatile
00108         {
00109                 T v=*reinterpret_cast<volatile const T *>(&i);
00110                 __asm__ __volatile__ (
00111                         "cmpw %0, %0\n"
00112                         "bne- 1f\n"
00113                         "1f:\n"
00114                         : "+b"(v));
00115                 fence_after(order);
00116                 return v;
00117         }
00118         void store(T v, memory_order2 order=memory_order2_seq_cst) volatile
00119         {
00120                 fence_before(order);
00121                 *reinterpret_cast<volatile T *>(&i)=v;
00122         }
00123         bool compare_exchange_weak(
00124                 T &expected,
00125                 T desired,
00126                 memory_order2 success_order,
00127                 memory_order2 failure_order) volatile
00128         {
00129                 fence_before(success_order);
00130                 int success;
00131                 __asm__ __volatile__(
00132                         "lwarx %0,0,%2\n"
00133                         "cmpw %0, %3\n"
00134                         "bne- 2f\n"
00135                         "stwcx. %4,0,%2\n"
00136                         "bne- 2f\n"
00137                         "addi %1,0,1\n"
00138                         "1:"
00139                         
00140                         ".subsection 2\n"
00141                         "2: addi %1,0,0\n"
00142                         "b 1b\n"
00143                         ".previous\n"
00144                                 : "=&b" (expected), "=&b" (success)
00145                                 : "b" (&i), "b" (expected), "b" ((int)desired)
00146                         );
00147                 if (success) fence_after(success_order);
00148                 else fence_after(failure_order);
00149                 return success;
00150         }
00151         
00152         bool is_lock_free(void) const volatile {return true;}
00153 protected:
00154         inline T fetch_add_var(T c, memory_order2 order) volatile
00155         {
00156                 fence_before(order);
00157                 T original, tmp;
00158                 __asm__ __volatile__(
00159                         "1: lwarx %0,0,%2\n"
00160                         "add %1,%0,%3\n"
00161                         "stwcx. %1,0,%2\n"
00162                         "bne- 1b\n"
00163                         : "=&b" (original), "=&b" (tmp)
00164                         : "b" (&i), "b" (c)
00165                         : "cc");
00166                 fence_after(order);
00167                 return original;
00168         }
00169         inline T fetch_inc(memory_order2 order) volatile
00170         {
00171                 fence_before(order);
00172                 T original, tmp;
00173                 __asm__ __volatile__(
00174                         "1: lwarx %0,0,%2\n"
00175                         "addi %1,%0,1\n"
00176                         "stwcx. %1,0,%2\n"
00177                         "bne- 1b\n"
00178                         : "=&b" (original), "=&b" (tmp)
00179                         : "b" (&i)
00180                         : "cc");
00181                 fence_after(order);
00182                 return original;
00183         }
00184         inline T fetch_dec(memory_order2 order) volatile
00185         {
00186                 fence_before(order);
00187                 T original, tmp;
00188                 __asm__ __volatile__(
00189                         "1: lwarx %0,0,%2\n"
00190                         "addi %1,%0,-1\n"
00191                         "stwcx. %1,0,%2\n"
00192                         "bne- 1b\n"
00193                         : "=&b" (original), "=&b" (tmp)
00194                         : "b" (&i)
00195                         : "cc");
00196                 fence_after(order);
00197                 return original;
00198         }
00199 private:
00200         T i;
00201 };
00202 
00203 #if defined(__powerpc64__)
00204 
00205 #warning Untested code -- please inform me if it works
00206 
00207 template<typename T>
00208 class atomic_ppc_64 {
00209 public:
00210         typedef T integral_type;
00211         explicit atomic_ppc_64(T v) : i(v) {}
00212         atomic_ppc_64() {}
00213         T load(memory_order2 order=memory_order2_seq_cst) const volatile
00214         {
00215                 T v=*reinterpret_cast<volatile const T *>(&i);
00216                 __asm__ __volatile__ (
00217                         "cmpw %0, %0\n"
00218                         "bne- 1f\n"
00219                         "1f:\n"
00220                         : "+b"(v));
00221                 fence_after(order);
00222                 return v;
00223         }
00224         void store(T v, memory_order2 order=memory_order2_seq_cst) volatile
00225         {
00226                 fence_before(order);
00227                 *reinterpret_cast<volatile T *>(&i)=v;
00228         }
00229         bool compare_exchange_weak(
00230                 T &expected,
00231                 T desired,
00232                 memory_order2 success_order,
00233                 memory_order2 failure_order) volatile
00234         {
00235                 fence_before(success_order);
00236                 int success;
00237                 __asm__ __volatile__(
00238                         "ldarx %0,0,%2\n"
00239                         "cmpw %0, %3\n"
00240                         "bne- 2f\n"
00241                         "stdcx. %4,0,%2\n"
00242                         "bne- 2f\n"
00243                         "addi %1,0,1\n"
00244                         "1:"
00245                         
00246                         ".subsection 2\n"
00247                         "2: addi %1,0,0\n"
00248                         "b 1b\n"
00249                         ".previous\n"
00250                                 : "=&b" (expected), "=&b" (success)
00251                                 : "b" (&i), "b" (expected), "b" ((int)desired)
00252                         );
00253                 if (success) fence_after(success_order);
00254                 else fence_after(failure_order);
00255                 fence_after(order);
00256                 return success;
00257         }
00258         
00259         bool is_lock_free(void) const volatile {return true;}
00260 protected:
00261         inline T fetch_add_var(T c, memory_order2 order) volatile
00262         {
00263                 fence_before(order);
00264                 T original, tmp;
00265                 __asm__ __volatile__(
00266                         "1: ldarx %0,0,%2\n"
00267                         "add %1,%0,%3\n"
00268                         "stdcx. %1,0,%2\n"
00269                         "bne- 1b\n"
00270                         : "=&b" (original), "=&b" (tmp)
00271                         : "b" (&i), "b" (c)
00272                         : "cc");
00273                 fence_after(order);
00274                 return original;
00275         }
00276         inline T fetch_inc(memory_order2 order) volatile
00277         {
00278                 fence_before(order);
00279                 T original, tmp;
00280                 __asm__ __volatile__(
00281                         "1: ldarx %0,0,%2\n"
00282                         "addi %1,%0,1\n"
00283                         "stdcx. %1,0,%2\n"
00284                         "bne- 1b\n"
00285                         : "=&b" (original), "=&b" (tmp)
00286                         : "b" (&i)
00287                         : "cc");
00288                 fence_after(order);
00289                 return original;
00290         }
00291         inline T fetch_dec(memory_order2 order) volatile
00292         {
00293                 fence_before(order);
00294                 T original, tmp;
00295                 __asm__ __volatile__(
00296                         "1: ldarx %0,0,%2\n"
00297                         "addi %1,%0,-1\n"
00298                         "stdcx. %1,0,%2\n"
00299                         "bne- 1b\n"
00300                         : "=&b" (original), "=&b" (tmp)
00301                         : "b" (&i)
00302                         : "cc");
00303                 fence_after(order);
00304                 return original;
00305         }
00306 private:
00307         T i;
00308 };
00309 #endif
00310 
00311 template<typename T>
00312 class platform_atomic_integral<T, 4> : public build_atomic_from_typical<build_exchange<atomic_ppc_32<T> > > {
00313 public:
00314         typedef build_atomic_from_typical<build_exchange<atomic_ppc_32<T> > > super;
00315         explicit platform_atomic_integral(T v) : super(v) {}
00316         platform_atomic_integral(void) {}
00317 };
00318 
00319 template<typename T>
00320 class platform_atomic_integral<T, 1>: public build_atomic_from_larger_type<atomic_ppc_32<uint32_t>, T> {
00321 public:
00322         typedef build_atomic_from_larger_type<atomic_ppc_32<uint32_t>, T> super;
00323         
00324         explicit platform_atomic_integral(T v) : super(v) {}
00325         platform_atomic_integral(void) {}
00326 };
00327 
00328 template<typename T>
00329 class platform_atomic_integral<T, 2>: public build_atomic_from_larger_type<atomic_ppc_32<uint32_t>, T> {
00330 public:
00331         typedef build_atomic_from_larger_type<atomic_ppc_32<uint32_t>, T> super;
00332         
00333         explicit platform_atomic_integral(T v) : super(v) {}
00334         platform_atomic_integral(void) {}
00335 };
00336 
00337 #if defined(__powerpc64__)
00338 template<typename T>
00339 class platform_atomic_integral<T, 8> : public build_atomic_from_typical<build_exchange<atomic_ppc_64<T> > > {
00340 public:
00341         typedef build_atomic_from_typical<build_exchange<atomic_ppc_64<T> > > super;
00342         explicit platform_atomic_integral(T v) : super(v) {}
00343         platform_atomic_integral(void) {}
00344 };
00345 #endif
00346 
00347 }
00348 }
00349 }
00350 
00351 #endif