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)
|