136 D result; 137 138 pre_membar(order); 139 140 __asm__ __volatile__ ( 141 "1: ldarx %0, 0, %2 \n" 142 " add %0, %0, %1 \n" 143 " stdcx. %0, 0, %2 \n" 144 " bne- 1b \n" 145 : /*%0*/"=&r" (result) 146 : /*%1*/"r" (add_value), /*%2*/"r" (dest) 147 : "cc", "memory" ); 148 149 post_membar(order); 150 151 return result; 152 } 153 154 template<> 155 template<typename T> 156 inline T Atomic::PlatformXchg<4>::operator()(T exchange_value, 157 T volatile* dest, 158 atomic_memory_order order) const { 159 // Note that xchg doesn't necessarily do an acquire 160 // (see synchronizer.cpp). 161 162 T old_value; 163 const uint64_t zero = 0; 164 165 pre_membar(order); 166 167 __asm__ __volatile__ ( 168 /* atomic loop */ 169 "1: \n" 170 " lwarx %[old_value], %[dest], %[zero] \n" 171 " stwcx. %[exchange_value], %[dest], %[zero] \n" 172 " bne- 1b \n" 173 /* exit */ 174 "2: \n" 175 /* out */ 176 : [old_value] "=&r" (old_value), 177 "=m" (*dest) 178 /* in */ 179 : [dest] "b" (dest), 180 [zero] "r" (zero), 181 [exchange_value] "r" (exchange_value), 182 "m" (*dest) 183 /* clobber */ 184 : "cc", 185 "memory" 186 ); 187 188 post_membar(order); 189 190 return old_value; 191 } 192 193 template<> 194 template<typename T> 195 inline T Atomic::PlatformXchg<8>::operator()(T exchange_value, 196 T volatile* dest, 197 atomic_memory_order order) const { 198 STATIC_ASSERT(8 == sizeof(T)); 199 // Note that xchg doesn't necessarily do an acquire 200 // (see synchronizer.cpp). 201 202 T old_value; 203 const uint64_t zero = 0; 204 205 pre_membar(order); 206 207 __asm__ __volatile__ ( 208 /* atomic loop */ 209 "1: \n" 210 " ldarx %[old_value], %[dest], %[zero] \n" 211 " stdcx. %[exchange_value], %[dest], %[zero] \n" 212 " bne- 1b \n" 213 /* exit */ 214 "2: \n" 215 /* out */ 216 : [old_value] "=&r" (old_value), | 136 D result; 137 138 pre_membar(order); 139 140 __asm__ __volatile__ ( 141 "1: ldarx %0, 0, %2 \n" 142 " add %0, %0, %1 \n" 143 " stdcx. %0, 0, %2 \n" 144 " bne- 1b \n" 145 : /*%0*/"=&r" (result) 146 : /*%1*/"r" (add_value), /*%2*/"r" (dest) 147 : "cc", "memory" ); 148 149 post_membar(order); 150 151 return result; 152 } 153 154 template<> 155 template<typename T> 156 inline T Atomic::PlatformXchg<4>::operator()(T volatile* dest, 157 T exchange_value, 158 atomic_memory_order order) const { 159 // Note that xchg doesn't necessarily do an acquire 160 // (see synchronizer.cpp). 161 162 T old_value; 163 const uint64_t zero = 0; 164 165 pre_membar(order); 166 167 __asm__ __volatile__ ( 168 /* atomic loop */ 169 "1: \n" 170 " lwarx %[old_value], %[dest], %[zero] \n" 171 " stwcx. %[exchange_value], %[dest], %[zero] \n" 172 " bne- 1b \n" 173 /* exit */ 174 "2: \n" 175 /* out */ 176 : [old_value] "=&r" (old_value), 177 "=m" (*dest) 178 /* in */ 179 : [dest] "b" (dest), 180 [zero] "r" (zero), 181 [exchange_value] "r" (exchange_value), 182 "m" (*dest) 183 /* clobber */ 184 : "cc", 185 "memory" 186 ); 187 188 post_membar(order); 189 190 return old_value; 191 } 192 193 template<> 194 template<typename T> 195 inline T Atomic::PlatformXchg<8>::operator()(T volatile* dest, 196 T exchange_value, 197 atomic_memory_order order) const { 198 STATIC_ASSERT(8 == sizeof(T)); 199 // Note that xchg doesn't necessarily do an acquire 200 // (see synchronizer.cpp). 201 202 T old_value; 203 const uint64_t zero = 0; 204 205 pre_membar(order); 206 207 __asm__ __volatile__ ( 208 /* atomic loop */ 209 "1: \n" 210 " ldarx %[old_value], %[dest], %[zero] \n" 211 " stdcx. %[exchange_value], %[dest], %[zero] \n" 212 " bne- 1b \n" 213 /* exit */ 214 "2: \n" 215 /* out */ 216 : [old_value] "=&r" (old_value), |