]>
Commit | Line | Data |
---|---|---|
b32b8144 FG |
1 | /* |
2 | * Distributed under the Boost Software License, Version 1.0. | |
3 | * (See accompanying file LICENSE_1_0.txt or copy at | |
4 | * http://www.boost.org/LICENSE_1_0.txt) | |
5 | * | |
11fdf7f2 | 6 | * Copyright (c) 2017 - 2018 Andrey Semashev |
b32b8144 FG |
7 | */ |
8 | /*! | |
9 | * \file atomic/detail/extra_ops_gcc_ppc.hpp | |
10 | * | |
11 | * This header contains implementation of the extra atomic operations for PowerPC. | |
12 | */ | |
13 | ||
14 | #ifndef BOOST_ATOMIC_DETAIL_EXTRA_OPS_GCC_PPC_HPP_INCLUDED_ | |
15 | #define BOOST_ATOMIC_DETAIL_EXTRA_OPS_GCC_PPC_HPP_INCLUDED_ | |
16 | ||
17 | #include <cstddef> | |
18 | #include <boost/memory_order.hpp> | |
19 | #include <boost/atomic/detail/config.hpp> | |
20 | #include <boost/atomic/detail/storage_type.hpp> | |
21 | #include <boost/atomic/detail/extra_operations_fwd.hpp> | |
22 | #include <boost/atomic/detail/extra_ops_generic.hpp> | |
23 | #include <boost/atomic/detail/ops_gcc_ppc_common.hpp> | |
24 | #include <boost/atomic/capabilities.hpp> | |
25 | ||
26 | #ifdef BOOST_HAS_PRAGMA_ONCE | |
27 | #pragma once | |
28 | #endif | |
29 | ||
30 | namespace boost { | |
31 | namespace atomics { | |
32 | namespace detail { | |
33 | ||
11fdf7f2 TL |
34 | template< typename Base > |
35 | struct gcc_ppc_extra_operations_common : | |
36 | public Base | |
37 | { | |
38 | typedef Base base_type; | |
39 | typedef typename base_type::storage_type storage_type; | |
40 | ||
41 | static BOOST_FORCEINLINE void opaque_negate(storage_type volatile& storage, memory_order order) BOOST_NOEXCEPT | |
42 | { | |
43 | base_type::fetch_negate(storage, order); | |
44 | } | |
45 | ||
46 | static BOOST_FORCEINLINE void opaque_complement(storage_type volatile& storage, memory_order order) BOOST_NOEXCEPT | |
47 | { | |
48 | base_type::fetch_complement(storage, order); | |
49 | } | |
50 | ||
51 | static BOOST_FORCEINLINE bool negate_and_test(storage_type volatile& storage, memory_order order) BOOST_NOEXCEPT | |
52 | { | |
53 | return !!base_type::negate(storage, order); | |
54 | } | |
55 | ||
56 | static BOOST_FORCEINLINE bool add_and_test(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT | |
57 | { | |
58 | return !!base_type::add(storage, v, order); | |
59 | } | |
60 | ||
61 | static BOOST_FORCEINLINE bool sub_and_test(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT | |
62 | { | |
63 | return !!base_type::sub(storage, v, order); | |
64 | } | |
65 | ||
66 | static BOOST_FORCEINLINE bool and_and_test(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT | |
67 | { | |
68 | return !!base_type::bitwise_and(storage, v, order); | |
69 | } | |
70 | ||
71 | static BOOST_FORCEINLINE bool or_and_test(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT | |
72 | { | |
73 | return !!base_type::bitwise_or(storage, v, order); | |
74 | } | |
75 | ||
76 | static BOOST_FORCEINLINE bool xor_and_test(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT | |
77 | { | |
78 | return !!base_type::bitwise_xor(storage, v, order); | |
79 | } | |
80 | ||
81 | static BOOST_FORCEINLINE bool complement_and_test(storage_type volatile& storage, memory_order order) BOOST_NOEXCEPT | |
82 | { | |
83 | return !!base_type::bitwise_complement(storage, order); | |
84 | } | |
85 | }; | |
86 | ||
87 | template< typename Base, std::size_t Size, bool Signed > | |
88 | struct gcc_ppc_extra_operations; | |
89 | ||
b32b8144 FG |
90 | #if defined(BOOST_ATOMIC_DETAIL_PPC_HAS_LBARX_STBCX) |
91 | ||
92 | template< typename Base, bool Signed > | |
11fdf7f2 | 93 | struct gcc_ppc_extra_operations< Base, 1u, Signed > : |
b32b8144 FG |
94 | public generic_extra_operations< Base, 1u, Signed > |
95 | { | |
96 | typedef generic_extra_operations< Base, 1u, Signed > base_type; | |
97 | typedef typename base_type::storage_type storage_type; | |
98 | ||
99 | static BOOST_FORCEINLINE storage_type fetch_negate(storage_type volatile& storage, memory_order order) BOOST_NOEXCEPT | |
100 | { | |
101 | gcc_ppc_operations_base::fence_before(order); | |
11fdf7f2 | 102 | storage_type original, result; |
b32b8144 FG |
103 | __asm__ __volatile__ |
104 | ( | |
105 | "1:\n\t" | |
106 | "lbarx %0,%y2\n\t" | |
107 | "neg %1,%0\n\t" | |
108 | "stbcx. %1,%y2\n\t" | |
109 | "bne- 1b\n\t" | |
11fdf7f2 | 110 | : "=&b" (original), "=&b" (result), "+Z" (storage) |
b32b8144 FG |
111 | : |
112 | : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC | |
113 | ); | |
114 | gcc_ppc_operations_base::fence_after(order); | |
115 | return original; | |
116 | } | |
117 | ||
11fdf7f2 TL |
118 | static BOOST_FORCEINLINE storage_type negate(storage_type volatile& storage, memory_order order) BOOST_NOEXCEPT |
119 | { | |
120 | gcc_ppc_operations_base::fence_before(order); | |
121 | storage_type original, result; | |
122 | __asm__ __volatile__ | |
123 | ( | |
124 | "1:\n\t" | |
125 | "lbarx %0,%y2\n\t" | |
126 | "neg %1,%0\n\t" | |
127 | "stbcx. %1,%y2\n\t" | |
128 | "bne- 1b\n\t" | |
129 | : "=&b" (original), "=&b" (result), "+Z" (storage) | |
130 | : | |
131 | : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC | |
132 | ); | |
133 | gcc_ppc_operations_base::fence_after(order); | |
134 | return result; | |
135 | } | |
136 | ||
137 | static BOOST_FORCEINLINE storage_type add(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT | |
138 | { | |
139 | storage_type original, result; | |
140 | gcc_ppc_operations_base::fence_before(order); | |
141 | __asm__ __volatile__ | |
142 | ( | |
143 | "1:\n\t" | |
144 | "lbarx %0,%y2\n\t" | |
145 | "add %1,%0,%3\n\t" | |
146 | "stbcx. %1,%y2\n\t" | |
147 | "bne- 1b\n\t" | |
148 | : "=&b" (original), "=&b" (result), "+Z" (storage) | |
149 | : "b" (v) | |
150 | : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC | |
151 | ); | |
152 | gcc_ppc_operations_base::fence_after(order); | |
153 | return result; | |
154 | } | |
155 | ||
156 | static BOOST_FORCEINLINE storage_type sub(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT | |
157 | { | |
158 | storage_type original, result; | |
159 | gcc_ppc_operations_base::fence_before(order); | |
160 | __asm__ __volatile__ | |
161 | ( | |
162 | "1:\n\t" | |
163 | "lbarx %0,%y2\n\t" | |
164 | "sub %1,%0,%3\n\t" | |
165 | "stbcx. %1,%y2\n\t" | |
166 | "bne- 1b\n\t" | |
167 | : "=&b" (original), "=&b" (result), "+Z" (storage) | |
168 | : "b" (v) | |
169 | : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC | |
170 | ); | |
171 | gcc_ppc_operations_base::fence_after(order); | |
172 | return result; | |
173 | } | |
174 | ||
175 | static BOOST_FORCEINLINE storage_type bitwise_and(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT | |
176 | { | |
177 | storage_type original, result; | |
178 | gcc_ppc_operations_base::fence_before(order); | |
179 | __asm__ __volatile__ | |
180 | ( | |
181 | "1:\n\t" | |
182 | "lbarx %0,%y2\n\t" | |
183 | "and %1,%0,%3\n\t" | |
184 | "stbcx. %1,%y2\n\t" | |
185 | "bne- 1b\n\t" | |
186 | : "=&b" (original), "=&b" (result), "+Z" (storage) | |
187 | : "b" (v) | |
188 | : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC | |
189 | ); | |
190 | gcc_ppc_operations_base::fence_after(order); | |
191 | return result; | |
192 | } | |
193 | ||
194 | static BOOST_FORCEINLINE storage_type bitwise_or(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT | |
195 | { | |
196 | storage_type original, result; | |
197 | gcc_ppc_operations_base::fence_before(order); | |
198 | __asm__ __volatile__ | |
199 | ( | |
200 | "1:\n\t" | |
201 | "lbarx %0,%y2\n\t" | |
202 | "or %1,%0,%3\n\t" | |
203 | "stbcx. %1,%y2\n\t" | |
204 | "bne- 1b\n\t" | |
205 | : "=&b" (original), "=&b" (result), "+Z" (storage) | |
206 | : "b" (v) | |
207 | : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC | |
208 | ); | |
209 | gcc_ppc_operations_base::fence_after(order); | |
210 | return result; | |
211 | } | |
212 | ||
213 | static BOOST_FORCEINLINE storage_type bitwise_xor(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT | |
214 | { | |
215 | storage_type original, result; | |
216 | gcc_ppc_operations_base::fence_before(order); | |
217 | __asm__ __volatile__ | |
218 | ( | |
219 | "1:\n\t" | |
220 | "lbarx %0,%y2\n\t" | |
221 | "xor %1,%0,%3\n\t" | |
222 | "stbcx. %1,%y2\n\t" | |
223 | "bne- 1b\n\t" | |
224 | : "=&b" (original), "=&b" (result), "+Z" (storage) | |
225 | : "b" (v) | |
226 | : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC | |
227 | ); | |
228 | gcc_ppc_operations_base::fence_after(order); | |
229 | return result; | |
230 | } | |
231 | ||
b32b8144 FG |
232 | static BOOST_FORCEINLINE storage_type fetch_complement(storage_type volatile& storage, memory_order order) BOOST_NOEXCEPT |
233 | { | |
234 | gcc_ppc_operations_base::fence_before(order); | |
11fdf7f2 | 235 | storage_type original, result; |
b32b8144 FG |
236 | __asm__ __volatile__ |
237 | ( | |
238 | "1:\n\t" | |
239 | "lbarx %0,%y2\n\t" | |
240 | "nor %1,%0,%0\n\t" | |
241 | "stbcx. %1,%y2\n\t" | |
242 | "bne- 1b\n\t" | |
11fdf7f2 | 243 | : "=&b" (original), "=&b" (result), "+Z" (storage) |
b32b8144 FG |
244 | : |
245 | : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC | |
246 | ); | |
247 | gcc_ppc_operations_base::fence_after(order); | |
248 | return original; | |
249 | } | |
250 | ||
11fdf7f2 | 251 | static BOOST_FORCEINLINE storage_type bitwise_complement(storage_type volatile& storage, memory_order order) BOOST_NOEXCEPT |
b32b8144 | 252 | { |
11fdf7f2 TL |
253 | gcc_ppc_operations_base::fence_before(order); |
254 | storage_type original, result; | |
255 | __asm__ __volatile__ | |
256 | ( | |
257 | "1:\n\t" | |
258 | "lbarx %0,%y2\n\t" | |
259 | "nor %1,%0,%0\n\t" | |
260 | "stbcx. %1,%y2\n\t" | |
261 | "bne- 1b\n\t" | |
262 | : "=&b" (original), "=&b" (result), "+Z" (storage) | |
263 | : | |
264 | : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC | |
265 | ); | |
266 | gcc_ppc_operations_base::fence_after(order); | |
267 | return result; | |
b32b8144 | 268 | } |
11fdf7f2 | 269 | }; |
b32b8144 | 270 | |
11fdf7f2 TL |
271 | template< typename Base, bool Signed > |
272 | struct extra_operations< Base, 1u, Signed, true > : | |
273 | public gcc_ppc_extra_operations_common< gcc_ppc_extra_operations< Base, 1u, Signed > > | |
274 | { | |
b32b8144 FG |
275 | }; |
276 | ||
277 | #endif // defined(BOOST_ATOMIC_DETAIL_PPC_HAS_LBARX_STBCX) | |
278 | ||
279 | #if defined(BOOST_ATOMIC_DETAIL_PPC_HAS_LHARX_STHCX) | |
280 | ||
281 | template< typename Base, bool Signed > | |
11fdf7f2 | 282 | struct gcc_ppc_extra_operations< Base, 2u, Signed > : |
b32b8144 FG |
283 | public generic_extra_operations< Base, 2u, Signed > |
284 | { | |
285 | typedef generic_extra_operations< Base, 2u, Signed > base_type; | |
286 | typedef typename base_type::storage_type storage_type; | |
287 | ||
288 | static BOOST_FORCEINLINE storage_type fetch_negate(storage_type volatile& storage, memory_order order) BOOST_NOEXCEPT | |
289 | { | |
290 | gcc_ppc_operations_base::fence_before(order); | |
11fdf7f2 | 291 | storage_type original, result; |
b32b8144 FG |
292 | __asm__ __volatile__ |
293 | ( | |
294 | "1:\n\t" | |
295 | "lharx %0,%y2\n\t" | |
296 | "neg %1,%0\n\t" | |
297 | "sthcx. %1,%y2\n\t" | |
298 | "bne- 1b\n\t" | |
11fdf7f2 | 299 | : "=&b" (original), "=&b" (result), "+Z" (storage) |
b32b8144 FG |
300 | : |
301 | : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC | |
302 | ); | |
303 | gcc_ppc_operations_base::fence_after(order); | |
304 | return original; | |
305 | } | |
306 | ||
11fdf7f2 | 307 | static BOOST_FORCEINLINE storage_type negate(storage_type volatile& storage, memory_order order) BOOST_NOEXCEPT |
b32b8144 FG |
308 | { |
309 | gcc_ppc_operations_base::fence_before(order); | |
11fdf7f2 | 310 | storage_type original, result; |
b32b8144 FG |
311 | __asm__ __volatile__ |
312 | ( | |
313 | "1:\n\t" | |
314 | "lharx %0,%y2\n\t" | |
11fdf7f2 | 315 | "neg %1,%0\n\t" |
b32b8144 FG |
316 | "sthcx. %1,%y2\n\t" |
317 | "bne- 1b\n\t" | |
11fdf7f2 | 318 | : "=&b" (original), "=&b" (result), "+Z" (storage) |
b32b8144 FG |
319 | : |
320 | : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC | |
321 | ); | |
322 | gcc_ppc_operations_base::fence_after(order); | |
11fdf7f2 | 323 | return result; |
b32b8144 FG |
324 | } |
325 | ||
11fdf7f2 | 326 | static BOOST_FORCEINLINE storage_type add(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT |
b32b8144 | 327 | { |
11fdf7f2 TL |
328 | storage_type original, result; |
329 | gcc_ppc_operations_base::fence_before(order); | |
330 | __asm__ __volatile__ | |
331 | ( | |
332 | "1:\n\t" | |
333 | "lharx %0,%y2\n\t" | |
334 | "add %1,%0,%3\n\t" | |
335 | "sthcx. %1,%y2\n\t" | |
336 | "bne- 1b\n\t" | |
337 | : "=&b" (original), "=&b" (result), "+Z" (storage) | |
338 | : "b" (v) | |
339 | : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC | |
340 | ); | |
341 | gcc_ppc_operations_base::fence_after(order); | |
342 | return result; | |
b32b8144 FG |
343 | } |
344 | ||
11fdf7f2 TL |
345 | static BOOST_FORCEINLINE storage_type sub(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT |
346 | { | |
347 | storage_type original, result; | |
348 | gcc_ppc_operations_base::fence_before(order); | |
349 | __asm__ __volatile__ | |
350 | ( | |
351 | "1:\n\t" | |
352 | "lharx %0,%y2\n\t" | |
353 | "sub %1,%0,%3\n\t" | |
354 | "sthcx. %1,%y2\n\t" | |
355 | "bne- 1b\n\t" | |
356 | : "=&b" (original), "=&b" (result), "+Z" (storage) | |
357 | : "b" (v) | |
358 | : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC | |
359 | ); | |
360 | gcc_ppc_operations_base::fence_after(order); | |
361 | return result; | |
362 | } | |
363 | ||
364 | static BOOST_FORCEINLINE storage_type bitwise_and(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT | |
365 | { | |
366 | storage_type original, result; | |
367 | gcc_ppc_operations_base::fence_before(order); | |
368 | __asm__ __volatile__ | |
369 | ( | |
370 | "1:\n\t" | |
371 | "lharx %0,%y2\n\t" | |
372 | "and %1,%0,%3\n\t" | |
373 | "sthcx. %1,%y2\n\t" | |
374 | "bne- 1b\n\t" | |
375 | : "=&b" (original), "=&b" (result), "+Z" (storage) | |
376 | : "b" (v) | |
377 | : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC | |
378 | ); | |
379 | gcc_ppc_operations_base::fence_after(order); | |
380 | return result; | |
381 | } | |
382 | ||
383 | static BOOST_FORCEINLINE storage_type bitwise_or(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT | |
384 | { | |
385 | storage_type original, result; | |
386 | gcc_ppc_operations_base::fence_before(order); | |
387 | __asm__ __volatile__ | |
388 | ( | |
389 | "1:\n\t" | |
390 | "lharx %0,%y2\n\t" | |
391 | "or %1,%0,%3\n\t" | |
392 | "sthcx. %1,%y2\n\t" | |
393 | "bne- 1b\n\t" | |
394 | : "=&b" (original), "=&b" (result), "+Z" (storage) | |
395 | : "b" (v) | |
396 | : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC | |
397 | ); | |
398 | gcc_ppc_operations_base::fence_after(order); | |
399 | return result; | |
400 | } | |
401 | ||
402 | static BOOST_FORCEINLINE storage_type bitwise_xor(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT | |
403 | { | |
404 | storage_type original, result; | |
405 | gcc_ppc_operations_base::fence_before(order); | |
406 | __asm__ __volatile__ | |
407 | ( | |
408 | "1:\n\t" | |
409 | "lharx %0,%y2\n\t" | |
410 | "xor %1,%0,%3\n\t" | |
411 | "sthcx. %1,%y2\n\t" | |
412 | "bne- 1b\n\t" | |
413 | : "=&b" (original), "=&b" (result), "+Z" (storage) | |
414 | : "b" (v) | |
415 | : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC | |
416 | ); | |
417 | gcc_ppc_operations_base::fence_after(order); | |
418 | return result; | |
419 | } | |
420 | ||
421 | static BOOST_FORCEINLINE storage_type fetch_complement(storage_type volatile& storage, memory_order order) BOOST_NOEXCEPT | |
422 | { | |
423 | gcc_ppc_operations_base::fence_before(order); | |
424 | storage_type original, result; | |
425 | __asm__ __volatile__ | |
426 | ( | |
427 | "1:\n\t" | |
428 | "lharx %0,%y2\n\t" | |
429 | "nor %1,%0,%0\n\t" | |
430 | "sthcx. %1,%y2\n\t" | |
431 | "bne- 1b\n\t" | |
432 | : "=&b" (original), "=&b" (result), "+Z" (storage) | |
433 | : | |
434 | : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC | |
435 | ); | |
436 | gcc_ppc_operations_base::fence_after(order); | |
437 | return original; | |
438 | } | |
439 | ||
440 | static BOOST_FORCEINLINE storage_type bitwise_complement(storage_type volatile& storage, memory_order order) BOOST_NOEXCEPT | |
b32b8144 | 441 | { |
11fdf7f2 TL |
442 | gcc_ppc_operations_base::fence_before(order); |
443 | storage_type original, result; | |
444 | __asm__ __volatile__ | |
445 | ( | |
446 | "1:\n\t" | |
447 | "lharx %0,%y2\n\t" | |
448 | "nor %1,%0,%0\n\t" | |
449 | "sthcx. %1,%y2\n\t" | |
450 | "bne- 1b\n\t" | |
451 | : "=&b" (original), "=&b" (result), "+Z" (storage) | |
452 | : | |
453 | : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC | |
454 | ); | |
455 | gcc_ppc_operations_base::fence_after(order); | |
456 | return result; | |
b32b8144 FG |
457 | } |
458 | }; | |
459 | ||
460 | #endif // defined(BOOST_ATOMIC_DETAIL_PPC_HAS_LHARX_STHCX) | |
461 | ||
462 | template< typename Base, bool Signed > | |
11fdf7f2 | 463 | struct gcc_ppc_extra_operations< Base, 4u, Signed > : |
b32b8144 FG |
464 | public generic_extra_operations< Base, 4u, Signed > |
465 | { | |
466 | typedef generic_extra_operations< Base, 4u, Signed > base_type; | |
467 | typedef typename base_type::storage_type storage_type; | |
468 | ||
469 | static BOOST_FORCEINLINE storage_type fetch_negate(storage_type volatile& storage, memory_order order) BOOST_NOEXCEPT | |
470 | { | |
471 | gcc_ppc_operations_base::fence_before(order); | |
11fdf7f2 | 472 | storage_type original, result; |
b32b8144 FG |
473 | __asm__ __volatile__ |
474 | ( | |
475 | "1:\n\t" | |
476 | "lwarx %0,%y2\n\t" | |
477 | "neg %1,%0\n\t" | |
478 | "stwcx. %1,%y2\n\t" | |
479 | "bne- 1b\n\t" | |
11fdf7f2 | 480 | : "=&b" (original), "=&b" (result), "+Z" (storage) |
b32b8144 FG |
481 | : |
482 | : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC | |
483 | ); | |
484 | gcc_ppc_operations_base::fence_after(order); | |
485 | return original; | |
486 | } | |
487 | ||
11fdf7f2 TL |
488 | static BOOST_FORCEINLINE storage_type negate(storage_type volatile& storage, memory_order order) BOOST_NOEXCEPT |
489 | { | |
490 | gcc_ppc_operations_base::fence_before(order); | |
491 | storage_type original, result; | |
492 | __asm__ __volatile__ | |
493 | ( | |
494 | "1:\n\t" | |
495 | "lwarx %0,%y2\n\t" | |
496 | "neg %1,%0\n\t" | |
497 | "stwcx. %1,%y2\n\t" | |
498 | "bne- 1b\n\t" | |
499 | : "=&b" (original), "=&b" (result), "+Z" (storage) | |
500 | : | |
501 | : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC | |
502 | ); | |
503 | gcc_ppc_operations_base::fence_after(order); | |
504 | return result; | |
505 | } | |
506 | ||
507 | static BOOST_FORCEINLINE storage_type add(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT | |
508 | { | |
509 | storage_type original, result; | |
510 | gcc_ppc_operations_base::fence_before(order); | |
511 | __asm__ __volatile__ | |
512 | ( | |
513 | "1:\n\t" | |
514 | "lwarx %0,%y2\n\t" | |
515 | "add %1,%0,%3\n\t" | |
516 | "stwcx. %1,%y2\n\t" | |
517 | "bne- 1b\n\t" | |
518 | : "=&b" (original), "=&b" (result), "+Z" (storage) | |
519 | : "b" (v) | |
520 | : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC | |
521 | ); | |
522 | gcc_ppc_operations_base::fence_after(order); | |
523 | return result; | |
524 | } | |
525 | ||
526 | static BOOST_FORCEINLINE storage_type sub(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT | |
527 | { | |
528 | storage_type original, result; | |
529 | gcc_ppc_operations_base::fence_before(order); | |
530 | __asm__ __volatile__ | |
531 | ( | |
532 | "1:\n\t" | |
533 | "lwarx %0,%y2\n\t" | |
534 | "sub %1,%0,%3\n\t" | |
535 | "stwcx. %1,%y2\n\t" | |
536 | "bne- 1b\n\t" | |
537 | : "=&b" (original), "=&b" (result), "+Z" (storage) | |
538 | : "b" (v) | |
539 | : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC | |
540 | ); | |
541 | gcc_ppc_operations_base::fence_after(order); | |
542 | return result; | |
543 | } | |
544 | ||
545 | static BOOST_FORCEINLINE storage_type bitwise_and(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT | |
546 | { | |
547 | storage_type original, result; | |
548 | gcc_ppc_operations_base::fence_before(order); | |
549 | __asm__ __volatile__ | |
550 | ( | |
551 | "1:\n\t" | |
552 | "lwarx %0,%y2\n\t" | |
553 | "and %1,%0,%3\n\t" | |
554 | "stwcx. %1,%y2\n\t" | |
555 | "bne- 1b\n\t" | |
556 | : "=&b" (original), "=&b" (result), "+Z" (storage) | |
557 | : "b" (v) | |
558 | : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC | |
559 | ); | |
560 | gcc_ppc_operations_base::fence_after(order); | |
561 | return result; | |
562 | } | |
563 | ||
564 | static BOOST_FORCEINLINE storage_type bitwise_or(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT | |
565 | { | |
566 | storage_type original, result; | |
567 | gcc_ppc_operations_base::fence_before(order); | |
568 | __asm__ __volatile__ | |
569 | ( | |
570 | "1:\n\t" | |
571 | "lwarx %0,%y2\n\t" | |
572 | "or %1,%0,%3\n\t" | |
573 | "stwcx. %1,%y2\n\t" | |
574 | "bne- 1b\n\t" | |
575 | : "=&b" (original), "=&b" (result), "+Z" (storage) | |
576 | : "b" (v) | |
577 | : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC | |
578 | ); | |
579 | gcc_ppc_operations_base::fence_after(order); | |
580 | return result; | |
581 | } | |
582 | ||
583 | static BOOST_FORCEINLINE storage_type bitwise_xor(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT | |
584 | { | |
585 | storage_type original, result; | |
586 | gcc_ppc_operations_base::fence_before(order); | |
587 | __asm__ __volatile__ | |
588 | ( | |
589 | "1:\n\t" | |
590 | "lwarx %0,%y2\n\t" | |
591 | "xor %1,%0,%3\n\t" | |
592 | "stwcx. %1,%y2\n\t" | |
593 | "bne- 1b\n\t" | |
594 | : "=&b" (original), "=&b" (result), "+Z" (storage) | |
595 | : "b" (v) | |
596 | : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC | |
597 | ); | |
598 | gcc_ppc_operations_base::fence_after(order); | |
599 | return result; | |
600 | } | |
601 | ||
b32b8144 FG |
602 | static BOOST_FORCEINLINE storage_type fetch_complement(storage_type volatile& storage, memory_order order) BOOST_NOEXCEPT |
603 | { | |
604 | gcc_ppc_operations_base::fence_before(order); | |
11fdf7f2 | 605 | storage_type original, result; |
b32b8144 FG |
606 | __asm__ __volatile__ |
607 | ( | |
608 | "1:\n\t" | |
609 | "lwarx %0,%y2\n\t" | |
610 | "nor %1,%0,%0\n\t" | |
611 | "stwcx. %1,%y2\n\t" | |
612 | "bne- 1b\n\t" | |
11fdf7f2 | 613 | : "=&b" (original), "=&b" (result), "+Z" (storage) |
b32b8144 FG |
614 | : |
615 | : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC | |
616 | ); | |
617 | gcc_ppc_operations_base::fence_after(order); | |
618 | return original; | |
619 | } | |
620 | ||
11fdf7f2 | 621 | static BOOST_FORCEINLINE storage_type bitwise_complement(storage_type volatile& storage, memory_order order) BOOST_NOEXCEPT |
b32b8144 | 622 | { |
11fdf7f2 TL |
623 | gcc_ppc_operations_base::fence_before(order); |
624 | storage_type original, result; | |
625 | __asm__ __volatile__ | |
626 | ( | |
627 | "1:\n\t" | |
628 | "lwarx %0,%y2\n\t" | |
629 | "nor %1,%0,%0\n\t" | |
630 | "stwcx. %1,%y2\n\t" | |
631 | "bne- 1b\n\t" | |
632 | : "=&b" (original), "=&b" (result), "+Z" (storage) | |
633 | : | |
634 | : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC | |
635 | ); | |
636 | gcc_ppc_operations_base::fence_after(order); | |
637 | return result; | |
b32b8144 | 638 | } |
11fdf7f2 | 639 | }; |
b32b8144 | 640 | |
11fdf7f2 TL |
641 | template< typename Base, bool Signed > |
642 | struct extra_operations< Base, 4u, Signed, true > : | |
643 | public gcc_ppc_extra_operations_common< gcc_ppc_extra_operations< Base, 4u, Signed > > | |
644 | { | |
b32b8144 FG |
645 | }; |
646 | ||
647 | #if defined(BOOST_ATOMIC_DETAIL_PPC_HAS_LDARX_STDCX) | |
648 | ||
649 | template< typename Base, bool Signed > | |
11fdf7f2 | 650 | struct gcc_ppc_extra_operations< Base, 8u, Signed > : |
b32b8144 FG |
651 | public generic_extra_operations< Base, 8u, Signed > |
652 | { | |
653 | typedef generic_extra_operations< Base, 8u, Signed > base_type; | |
654 | typedef typename base_type::storage_type storage_type; | |
655 | ||
656 | static BOOST_FORCEINLINE storage_type fetch_negate(storage_type volatile& storage, memory_order order) BOOST_NOEXCEPT | |
657 | { | |
658 | gcc_ppc_operations_base::fence_before(order); | |
11fdf7f2 | 659 | storage_type original, result; |
b32b8144 FG |
660 | __asm__ __volatile__ |
661 | ( | |
662 | "1:\n\t" | |
663 | "ldarx %0,%y2\n\t" | |
664 | "neg %1,%0\n\t" | |
665 | "stdcx. %1,%y2\n\t" | |
666 | "bne- 1b\n\t" | |
11fdf7f2 | 667 | : "=&b" (original), "=&b" (result), "+Z" (storage) |
b32b8144 FG |
668 | : |
669 | : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC | |
670 | ); | |
671 | gcc_ppc_operations_base::fence_after(order); | |
672 | return original; | |
673 | } | |
674 | ||
11fdf7f2 TL |
675 | static BOOST_FORCEINLINE storage_type negate(storage_type volatile& storage, memory_order order) BOOST_NOEXCEPT |
676 | { | |
677 | gcc_ppc_operations_base::fence_before(order); | |
678 | storage_type original, result; | |
679 | __asm__ __volatile__ | |
680 | ( | |
681 | "1:\n\t" | |
682 | "ldarx %0,%y2\n\t" | |
683 | "neg %1,%0\n\t" | |
684 | "stdcx. %1,%y2\n\t" | |
685 | "bne- 1b\n\t" | |
686 | : "=&b" (original), "=&b" (result), "+Z" (storage) | |
687 | : | |
688 | : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC | |
689 | ); | |
690 | gcc_ppc_operations_base::fence_after(order); | |
691 | return result; | |
692 | } | |
693 | ||
694 | static BOOST_FORCEINLINE storage_type add(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT | |
695 | { | |
696 | storage_type original, result; | |
697 | gcc_ppc_operations_base::fence_before(order); | |
698 | __asm__ __volatile__ | |
699 | ( | |
700 | "1:\n\t" | |
701 | "ldarx %0,%y2\n\t" | |
702 | "add %1,%0,%3\n\t" | |
703 | "stdcx. %1,%y2\n\t" | |
704 | "bne- 1b\n\t" | |
705 | : "=&b" (original), "=&b" (result), "+Z" (storage) | |
706 | : "b" (v) | |
707 | : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC | |
708 | ); | |
709 | gcc_ppc_operations_base::fence_after(order); | |
710 | return result; | |
711 | } | |
712 | ||
713 | static BOOST_FORCEINLINE storage_type sub(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT | |
714 | { | |
715 | storage_type original, result; | |
716 | gcc_ppc_operations_base::fence_before(order); | |
717 | __asm__ __volatile__ | |
718 | ( | |
719 | "1:\n\t" | |
720 | "ldarx %0,%y2\n\t" | |
721 | "sub %1,%0,%3\n\t" | |
722 | "stdcx. %1,%y2\n\t" | |
723 | "bne- 1b\n\t" | |
724 | : "=&b" (original), "=&b" (result), "+Z" (storage) | |
725 | : "b" (v) | |
726 | : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC | |
727 | ); | |
728 | gcc_ppc_operations_base::fence_after(order); | |
729 | return result; | |
730 | } | |
731 | ||
732 | static BOOST_FORCEINLINE storage_type bitwise_and(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT | |
733 | { | |
734 | storage_type original, result; | |
735 | gcc_ppc_operations_base::fence_before(order); | |
736 | __asm__ __volatile__ | |
737 | ( | |
738 | "1:\n\t" | |
739 | "ldarx %0,%y2\n\t" | |
740 | "and %1,%0,%3\n\t" | |
741 | "stdcx. %1,%y2\n\t" | |
742 | "bne- 1b\n\t" | |
743 | : "=&b" (original), "=&b" (result), "+Z" (storage) | |
744 | : "b" (v) | |
745 | : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC | |
746 | ); | |
747 | gcc_ppc_operations_base::fence_after(order); | |
748 | return result; | |
749 | } | |
750 | ||
751 | static BOOST_FORCEINLINE storage_type bitwise_or(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT | |
752 | { | |
753 | storage_type original, result; | |
754 | gcc_ppc_operations_base::fence_before(order); | |
755 | __asm__ __volatile__ | |
756 | ( | |
757 | "1:\n\t" | |
758 | "ldarx %0,%y2\n\t" | |
759 | "or %1,%0,%3\n\t" | |
760 | "stdcx. %1,%y2\n\t" | |
761 | "bne- 1b\n\t" | |
762 | : "=&b" (original), "=&b" (result), "+Z" (storage) | |
763 | : "b" (v) | |
764 | : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC | |
765 | ); | |
766 | gcc_ppc_operations_base::fence_after(order); | |
767 | return result; | |
768 | } | |
769 | ||
770 | static BOOST_FORCEINLINE storage_type bitwise_xor(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT | |
771 | { | |
772 | storage_type original, result; | |
773 | gcc_ppc_operations_base::fence_before(order); | |
774 | __asm__ __volatile__ | |
775 | ( | |
776 | "1:\n\t" | |
777 | "ldarx %0,%y2\n\t" | |
778 | "xor %1,%0,%3\n\t" | |
779 | "stdcx. %1,%y2\n\t" | |
780 | "bne- 1b\n\t" | |
781 | : "=&b" (original), "=&b" (result), "+Z" (storage) | |
782 | : "b" (v) | |
783 | : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC | |
784 | ); | |
785 | gcc_ppc_operations_base::fence_after(order); | |
786 | return result; | |
787 | } | |
788 | ||
b32b8144 FG |
789 | static BOOST_FORCEINLINE storage_type fetch_complement(storage_type volatile& storage, memory_order order) BOOST_NOEXCEPT |
790 | { | |
791 | gcc_ppc_operations_base::fence_before(order); | |
11fdf7f2 | 792 | storage_type original, result; |
b32b8144 FG |
793 | __asm__ __volatile__ |
794 | ( | |
795 | "1:\n\t" | |
796 | "ldarx %0,%y2\n\t" | |
797 | "nor %1,%0,%0\n\t" | |
798 | "stdcx. %1,%y2\n\t" | |
799 | "bne- 1b\n\t" | |
11fdf7f2 | 800 | : "=&b" (original), "=&b" (result), "+Z" (storage) |
b32b8144 FG |
801 | : |
802 | : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC | |
803 | ); | |
804 | gcc_ppc_operations_base::fence_after(order); | |
805 | return original; | |
806 | } | |
807 | ||
11fdf7f2 | 808 | static BOOST_FORCEINLINE storage_type bitwise_complement(storage_type volatile& storage, memory_order order) BOOST_NOEXCEPT |
b32b8144 | 809 | { |
11fdf7f2 TL |
810 | gcc_ppc_operations_base::fence_before(order); |
811 | storage_type original, result; | |
812 | __asm__ __volatile__ | |
813 | ( | |
814 | "1:\n\t" | |
815 | "ldarx %0,%y2\n\t" | |
816 | "nor %1,%0,%0\n\t" | |
817 | "stdcx. %1,%y2\n\t" | |
818 | "bne- 1b\n\t" | |
819 | : "=&b" (original), "=&b" (result), "+Z" (storage) | |
820 | : | |
821 | : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC | |
822 | ); | |
823 | gcc_ppc_operations_base::fence_after(order); | |
824 | return result; | |
b32b8144 | 825 | } |
11fdf7f2 | 826 | }; |
b32b8144 | 827 | |
11fdf7f2 TL |
828 | template< typename Base, bool Signed > |
829 | struct extra_operations< Base, 8u, Signed, true > : | |
830 | public gcc_ppc_extra_operations_common< gcc_ppc_extra_operations< Base, 8u, Signed > > | |
831 | { | |
b32b8144 FG |
832 | }; |
833 | ||
834 | #endif // defined(BOOST_ATOMIC_DETAIL_PPC_HAS_LDARX_STDCX) | |
835 | ||
836 | } // namespace detail | |
837 | } // namespace atomics | |
838 | } // namespace boost | |
839 | ||
840 | #endif // BOOST_ATOMIC_DETAIL_EXTRA_OPS_GCC_ARM_PPC_INCLUDED_ |