120 121 __asm__ __volatile__ ( 122 strasm_lwsync 123 "1: ldarx %0, 0, %2 \n" 124 " add %0, %0, %1 \n" 125 " stdcx. %0, 0, %2 \n" 126 " bne- 1b \n" 127 strasm_isync 128 : /*%0*/"=&r" (result) 129 : /*%1*/"r" (add_value), /*%2*/"r" (dest) 130 : "cc", "memory" ); 131 132 return result; 133 } 134 135 template<> 136 template<typename T> 137 inline T Atomic::PlatformXchg<4>::operator()(T exchange_value, 138 T volatile* dest) const { 139 STATIC_ASSERT(4 == sizeof(T)); 140 // Note that xchg_ptr doesn't necessarily do an acquire 141 // (see synchronizer.cpp). 142 143 T old_value; 144 const uint64_t zero = 0; 145 146 __asm__ __volatile__ ( 147 /* lwsync */ 148 strasm_lwsync 149 /* atomic loop */ 150 "1: \n" 151 " lwarx %[old_value], %[dest], %[zero] \n" 152 " stwcx. %[exchange_value], %[dest], %[zero] \n" 153 " bne- 1b \n" 154 /* isync */ 155 strasm_sync 156 /* exit */ 157 "2: \n" 158 /* out */ 159 : [old_value] "=&r" (old_value), 160 "=m" (*dest) 161 /* in */ 162 : [dest] "b" (dest), 163 [zero] "r" (zero), 164 [exchange_value] "r" (exchange_value), 165 "m" (*dest) 166 /* clobber */ 167 : "cc", 168 "memory" 169 ); 170 171 return old_value; 172 } 173 174 template<> 175 template<typename T> 176 inline T Atomic::PlatformXchg<8>::operator()(T exchange_value, 177 T volatile* dest) const { 178 STATIC_ASSERT(8 == sizeof(T)); 179 // Note that xchg_ptr doesn't necessarily do an acquire 180 // (see synchronizer.cpp). 181 182 T old_value; 183 const uint64_t zero = 0; 184 185 __asm__ __volatile__ ( 186 /* lwsync */ 187 strasm_lwsync 188 /* atomic loop */ 189 "1: \n" 190 " ldarx %[old_value], %[dest], %[zero] \n" 191 " stdcx. %[exchange_value], %[dest], %[zero] \n" 192 " bne- 1b \n" 193 /* isync */ 194 strasm_sync 195 /* exit */ 196 "2: \n" 197 /* out */ 198 : [old_value] "=&r" (old_value), 199 "=m" (*dest) | 120 121 __asm__ __volatile__ ( 122 strasm_lwsync 123 "1: ldarx %0, 0, %2 \n" 124 " add %0, %0, %1 \n" 125 " stdcx. %0, 0, %2 \n" 126 " bne- 1b \n" 127 strasm_isync 128 : /*%0*/"=&r" (result) 129 : /*%1*/"r" (add_value), /*%2*/"r" (dest) 130 : "cc", "memory" ); 131 132 return result; 133 } 134 135 template<> 136 template<typename T> 137 inline T Atomic::PlatformXchg<4>::operator()(T exchange_value, 138 T volatile* dest) const { 139 STATIC_ASSERT(4 == sizeof(T)); 140 // Note that xchg doesn't necessarily do an acquire 141 // (see synchronizer.cpp). 142 143 T old_value; 144 const uint64_t zero = 0; 145 146 __asm__ __volatile__ ( 147 /* lwsync */ 148 strasm_lwsync 149 /* atomic loop */ 150 "1: \n" 151 " lwarx %[old_value], %[dest], %[zero] \n" 152 " stwcx. %[exchange_value], %[dest], %[zero] \n" 153 " bne- 1b \n" 154 /* isync */ 155 strasm_sync 156 /* exit */ 157 "2: \n" 158 /* out */ 159 : [old_value] "=&r" (old_value), 160 "=m" (*dest) 161 /* in */ 162 : [dest] "b" (dest), 163 [zero] "r" (zero), 164 [exchange_value] "r" (exchange_value), 165 "m" (*dest) 166 /* clobber */ 167 : "cc", 168 "memory" 169 ); 170 171 return old_value; 172 } 173 174 template<> 175 template<typename T> 176 inline T Atomic::PlatformXchg<8>::operator()(T exchange_value, 177 T volatile* dest) const { 178 STATIC_ASSERT(8 == sizeof(T)); 179 // Note that xchg doesn't necessarily do an acquire 180 // (see synchronizer.cpp). 181 182 T old_value; 183 const uint64_t zero = 0; 184 185 __asm__ __volatile__ ( 186 /* lwsync */ 187 strasm_lwsync 188 /* atomic loop */ 189 "1: \n" 190 " ldarx %[old_value], %[dest], %[zero] \n" 191 " stdcx. %[exchange_value], %[dest], %[zero] \n" 192 " bne- 1b \n" 193 /* isync */ 194 strasm_sync 195 /* exit */ 196 "2: \n" 197 /* out */ 198 : [old_value] "=&r" (old_value), 199 "=m" (*dest) |