]> git.proxmox.com Git - ceph.git/blame - ceph/src/boost/boost/atomic/detail/ops_gcc_ppc.hpp
update sources to ceph Nautilus 14.2.1
[ceph.git] / ceph / src / boost / boost / atomic / detail / ops_gcc_ppc.hpp
CommitLineData
7c673cae
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 *
6 * Copyright (c) 2009 Helge Bahmann
7 * Copyright (c) 2013 Tim Blechmann
8 * Copyright (c) 2014 Andrey Semashev
9 */
10/*!
11 * \file atomic/detail/ops_gcc_ppc.hpp
12 *
13 * This header contains implementation of the \c operations template.
14 */
15
16#ifndef BOOST_ATOMIC_DETAIL_OPS_GCC_PPC_HPP_INCLUDED_
17#define BOOST_ATOMIC_DETAIL_OPS_GCC_PPC_HPP_INCLUDED_
18
b32b8144 19#include <cstddef>
7c673cae
FG
20#include <boost/memory_order.hpp>
21#include <boost/atomic/detail/config.hpp>
22#include <boost/atomic/detail/storage_type.hpp>
23#include <boost/atomic/detail/operations_fwd.hpp>
b32b8144 24#include <boost/atomic/detail/ops_gcc_ppc_common.hpp>
7c673cae
FG
25#include <boost/atomic/capabilities.hpp>
26
27#ifdef BOOST_HAS_PRAGMA_ONCE
28#pragma once
29#endif
30
31namespace boost {
32namespace atomics {
33namespace detail {
34
35// The implementation below uses information from this document:
36// http://www.rdrop.com/users/paulmck/scalability/paper/N2745r.2010.02.19a.html
37
38/*
39 Refer to: Motorola: "Programming Environments Manual for 32-Bit
40 Implementations of the PowerPC Architecture", Appendix E:
41 "Synchronization Programming Examples" for an explanation of what is
42 going on here (can be found on the web at various places by the
43 name "MPCFPE32B.pdf", Google is your friend...)
44
45 Most of the atomic operations map to instructions in a relatively
46 straight-forward fashion, but "load"s may at first glance appear
47 a bit strange as they map to:
48
49 lwz %rX, addr
50 cmpw %rX, %rX
51 bne- 1f
52 1:
53
54 That is, the CPU is forced to perform a branch that "formally" depends
55 on the value retrieved from memory. This scheme has an overhead of
56 about 1-2 clock cycles per load, but it allows to map "acquire" to
57 the "isync" instruction instead of "sync" uniformly and for all type
58 of atomic operations. Since "isync" has a cost of about 15 clock
59 cycles, while "sync" hast a cost of about 50 clock cycles, the small
60 penalty to atomic loads more than compensates for this.
61
b32b8144
FG
62 Byte- and halfword-sized atomic values are implemented in two ways.
63 When 8 and 16-bit instructions are available (in Power8 and later),
64 they are used. Otherwise operations are realized by encoding the
7c673cae
FG
65 value to be represented into a word, performing sign/zero extension
66 as appropriate. This means that after add/sub operations the value
67 needs fixing up to accurately preserve the wrap-around semantic of
68 the smaller type. (Nothing special needs to be done for the bit-wise
69 and the "exchange type" operators as the compiler already sees to
70 it that values carried in registers are extended appropriately and
71 everything falls into place naturally).
72
73 The register constraint "b" instructs gcc to use any register
74 except r0; this is sometimes required because the encoding for
75 r0 is used to signify "constant zero" in a number of instructions,
76 making r0 unusable in this place. For simplicity this constraint
77 is used everywhere since I am to lazy to look this up on a
78 per-instruction basis, and ppc has enough registers for this not
79 to pose a problem.
80*/
81
7c673cae
FG
82template< bool Signed >
83struct operations< 4u, Signed > :
84 public gcc_ppc_operations_base
85{
11fdf7f2
TL
86 typedef typename make_storage_type< 4u >::type storage_type;
87 typedef typename make_storage_type< 4u >::aligned aligned_storage_type;
7c673cae 88
b32b8144
FG
89 static BOOST_CONSTEXPR_OR_CONST std::size_t storage_size = 4u;
90 static BOOST_CONSTEXPR_OR_CONST bool is_signed = Signed;
91
7c673cae
FG
92 static BOOST_FORCEINLINE void store(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
93 {
94 fence_before(order);
95 __asm__ __volatile__
96 (
97 "stw %1, %0\n\t"
98 : "+m" (storage)
99 : "r" (v)
100 );
101 }
102
103 static BOOST_FORCEINLINE storage_type load(storage_type const volatile& storage, memory_order order) BOOST_NOEXCEPT
104 {
105 storage_type v;
106 if (order == memory_order_seq_cst)
107 __asm__ __volatile__ ("sync" ::: "memory");
11fdf7f2 108 if ((static_cast< unsigned int >(order) & (static_cast< unsigned int >(memory_order_consume) | static_cast< unsigned int >(memory_order_acquire))) != 0u)
7c673cae
FG
109 {
110 __asm__ __volatile__
111 (
112 "lwz %0, %1\n\t"
113 "cmpw %0, %0\n\t"
114 "bne- 1f\n\t"
115 "1:\n\t"
116 "isync\n\t"
117 : "=&r" (v)
118 : "m" (storage)
119 : "cr0", "memory"
120 );
121 }
122 else
123 {
124 __asm__ __volatile__
125 (
126 "lwz %0, %1\n\t"
127 : "=&r" (v)
128 : "m" (storage)
129 );
130 }
131 return v;
132 }
133
134 static BOOST_FORCEINLINE storage_type exchange(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
135 {
136 storage_type original;
137 fence_before(order);
138 __asm__ __volatile__
139 (
140 "1:\n\t"
141 "lwarx %0,%y1\n\t"
142 "stwcx. %2,%y1\n\t"
143 "bne- 1b\n\t"
144 : "=&b" (original), "+Z" (storage)
145 : "b" (v)
146 : "cr0"
147 );
148 fence_after(order);
149 return original;
150 }
151
152 static BOOST_FORCEINLINE bool compare_exchange_weak(
153 storage_type volatile& storage, storage_type& expected, storage_type desired, memory_order success_order, memory_order failure_order) BOOST_NOEXCEPT
154 {
155 int success;
156 fence_before(success_order);
157 __asm__ __volatile__
158 (
159 "li %1, 0\n\t"
160 "lwarx %0,%y2\n\t"
161 "cmpw %0, %3\n\t"
162 "bne- 1f\n\t"
163 "stwcx. %4,%y2\n\t"
164 "bne- 1f\n\t"
165 "li %1, 1\n\t"
166 "1:\n\t"
167 : "=&b" (expected), "=&b" (success), "+Z" (storage)
168 : "b" (expected), "b" (desired)
169 : "cr0"
170 );
171 if (success)
172 fence_after(success_order);
173 else
174 fence_after(failure_order);
175 return !!success;
176 }
177
178 static BOOST_FORCEINLINE bool compare_exchange_strong(
179 storage_type volatile& storage, storage_type& expected, storage_type desired, memory_order success_order, memory_order failure_order) BOOST_NOEXCEPT
180 {
181 int success;
182 fence_before(success_order);
183 __asm__ __volatile__
184 (
185 "li %1, 0\n\t"
186 "0: lwarx %0,%y2\n\t"
187 "cmpw %0, %3\n\t"
188 "bne- 1f\n\t"
189 "stwcx. %4,%y2\n\t"
190 "bne- 0b\n\t"
191 "li %1, 1\n\t"
192 "1:\n\t"
193 : "=&b" (expected), "=&b" (success), "+Z" (storage)
194 : "b" (expected), "b" (desired)
195 : "cr0"
196 );
197 if (success)
198 fence_after(success_order);
199 else
200 fence_after(failure_order);
201 return !!success;
202 }
203
204 static BOOST_FORCEINLINE storage_type fetch_add(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
205 {
11fdf7f2 206 storage_type original, result;
7c673cae
FG
207 fence_before(order);
208 __asm__ __volatile__
209 (
210 "1:\n\t"
211 "lwarx %0,%y2\n\t"
212 "add %1,%0,%3\n\t"
213 "stwcx. %1,%y2\n\t"
214 "bne- 1b\n\t"
11fdf7f2 215 : "=&b" (original), "=&b" (result), "+Z" (storage)
7c673cae
FG
216 : "b" (v)
217 : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC
218 );
219 fence_after(order);
220 return original;
221 }
222
223 static BOOST_FORCEINLINE storage_type fetch_sub(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
224 {
11fdf7f2 225 storage_type original, result;
7c673cae
FG
226 fence_before(order);
227 __asm__ __volatile__
228 (
229 "1:\n\t"
230 "lwarx %0,%y2\n\t"
231 "sub %1,%0,%3\n\t"
232 "stwcx. %1,%y2\n\t"
233 "bne- 1b\n\t"
11fdf7f2 234 : "=&b" (original), "=&b" (result), "+Z" (storage)
7c673cae
FG
235 : "b" (v)
236 : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC
237 );
238 fence_after(order);
239 return original;
240 }
241
242 static BOOST_FORCEINLINE storage_type fetch_and(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
243 {
11fdf7f2 244 storage_type original, result;
7c673cae
FG
245 fence_before(order);
246 __asm__ __volatile__
247 (
248 "1:\n\t"
249 "lwarx %0,%y2\n\t"
250 "and %1,%0,%3\n\t"
251 "stwcx. %1,%y2\n\t"
252 "bne- 1b\n\t"
11fdf7f2 253 : "=&b" (original), "=&b" (result), "+Z" (storage)
7c673cae
FG
254 : "b" (v)
255 : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC
256 );
257 fence_after(order);
258 return original;
259 }
260
261 static BOOST_FORCEINLINE storage_type fetch_or(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
262 {
11fdf7f2 263 storage_type original, result;
7c673cae
FG
264 fence_before(order);
265 __asm__ __volatile__
266 (
267 "1:\n\t"
268 "lwarx %0,%y2\n\t"
269 "or %1,%0,%3\n\t"
270 "stwcx. %1,%y2\n\t"
271 "bne- 1b\n\t"
11fdf7f2 272 : "=&b" (original), "=&b" (result), "+Z" (storage)
7c673cae
FG
273 : "b" (v)
274 : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC
275 );
276 fence_after(order);
277 return original;
278 }
279
280 static BOOST_FORCEINLINE storage_type fetch_xor(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
281 {
11fdf7f2 282 storage_type original, result;
7c673cae
FG
283 fence_before(order);
284 __asm__ __volatile__
285 (
286 "1:\n\t"
287 "lwarx %0,%y2\n\t"
288 "xor %1,%0,%3\n\t"
289 "stwcx. %1,%y2\n\t"
290 "bne- 1b\n\t"
11fdf7f2 291 : "=&b" (original), "=&b" (result), "+Z" (storage)
7c673cae
FG
292 : "b" (v)
293 : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC
294 );
295 fence_after(order);
296 return original;
297 }
298
299 static BOOST_FORCEINLINE bool test_and_set(storage_type volatile& storage, memory_order order) BOOST_NOEXCEPT
300 {
301 return !!exchange(storage, (storage_type)1, order);
302 }
303
304 static BOOST_FORCEINLINE void clear(storage_type volatile& storage, memory_order order) BOOST_NOEXCEPT
305 {
306 store(storage, 0, order);
307 }
b32b8144
FG
308};
309
310#if defined(BOOST_ATOMIC_DETAIL_PPC_HAS_LBARX_STBCX)
311
312template< bool Signed >
313struct operations< 1u, Signed > :
314 public gcc_ppc_operations_base
315{
11fdf7f2
TL
316 typedef typename make_storage_type< 1u >::type storage_type;
317 typedef typename make_storage_type< 1u >::aligned aligned_storage_type;
b32b8144
FG
318
319 static BOOST_CONSTEXPR_OR_CONST std::size_t storage_size = 1u;
320 static BOOST_CONSTEXPR_OR_CONST bool is_signed = Signed;
321
322 static BOOST_FORCEINLINE void store(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
323 {
324 fence_before(order);
325 __asm__ __volatile__
326 (
327 "stb %1, %0\n\t"
328 : "+m" (storage)
329 : "r" (v)
330 );
331 }
332
333 static BOOST_FORCEINLINE storage_type load(storage_type const volatile& storage, memory_order order) BOOST_NOEXCEPT
334 {
335 storage_type v;
336 if (order == memory_order_seq_cst)
337 __asm__ __volatile__ ("sync" ::: "memory");
11fdf7f2 338 if ((static_cast< unsigned int >(order) & (static_cast< unsigned int >(memory_order_consume) | static_cast< unsigned int >(memory_order_acquire))) != 0u)
b32b8144
FG
339 {
340 __asm__ __volatile__
341 (
342 "lbz %0, %1\n\t"
343 "cmpw %0, %0\n\t"
344 "bne- 1f\n\t"
345 "1:\n\t"
346 "isync\n\t"
347 : "=&r" (v)
348 : "m" (storage)
349 : "cr0", "memory"
350 );
351 }
352 else
353 {
354 __asm__ __volatile__
355 (
356 "lbz %0, %1\n\t"
357 : "=&r" (v)
358 : "m" (storage)
359 );
360 }
361 return v;
362 }
363
364 static BOOST_FORCEINLINE storage_type exchange(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
365 {
366 storage_type original;
367 fence_before(order);
368 __asm__ __volatile__
369 (
370 "1:\n\t"
371 "lbarx %0,%y1\n\t"
372 "stbcx. %2,%y1\n\t"
373 "bne- 1b\n\t"
374 : "=&b" (original), "+Z" (storage)
375 : "b" (v)
376 : "cr0"
377 );
378 fence_after(order);
379 return original;
380 }
381
382 static BOOST_FORCEINLINE bool compare_exchange_weak(
383 storage_type volatile& storage, storage_type& expected, storage_type desired, memory_order success_order, memory_order failure_order) BOOST_NOEXCEPT
384 {
385 int success;
386 fence_before(success_order);
387 __asm__ __volatile__
388 (
389 "li %1, 0\n\t"
390 "lbarx %0,%y2\n\t"
391 "cmpw %0, %3\n\t"
392 "bne- 1f\n\t"
393 "stbcx. %4,%y2\n\t"
394 "bne- 1f\n\t"
395 "li %1, 1\n\t"
396 "1:\n\t"
397 : "=&b" (expected), "=&b" (success), "+Z" (storage)
11fdf7f2 398 : "b" (expected), "b" (desired)
b32b8144
FG
399 : "cr0"
400 );
401 if (success)
402 fence_after(success_order);
403 else
404 fence_after(failure_order);
405 return !!success;
406 }
407
408 static BOOST_FORCEINLINE bool compare_exchange_strong(
409 storage_type volatile& storage, storage_type& expected, storage_type desired, memory_order success_order, memory_order failure_order) BOOST_NOEXCEPT
410 {
411 int success;
412 fence_before(success_order);
413 __asm__ __volatile__
414 (
415 "li %1, 0\n\t"
416 "0: lbarx %0,%y2\n\t"
417 "cmpw %0, %3\n\t"
418 "bne- 1f\n\t"
419 "stbcx. %4,%y2\n\t"
420 "bne- 0b\n\t"
421 "li %1, 1\n\t"
422 "1:\n\t"
423 : "=&b" (expected), "=&b" (success), "+Z" (storage)
11fdf7f2 424 : "b" (expected), "b" (desired)
b32b8144
FG
425 : "cr0"
426 );
427 if (success)
428 fence_after(success_order);
429 else
430 fence_after(failure_order);
431 return !!success;
432 }
433
434 static BOOST_FORCEINLINE storage_type fetch_add(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
435 {
11fdf7f2 436 storage_type original, result;
b32b8144
FG
437 fence_before(order);
438 __asm__ __volatile__
439 (
440 "1:\n\t"
441 "lbarx %0,%y2\n\t"
442 "add %1,%0,%3\n\t"
443 "stbcx. %1,%y2\n\t"
444 "bne- 1b\n\t"
11fdf7f2 445 : "=&b" (original), "=&b" (result), "+Z" (storage)
b32b8144
FG
446 : "b" (v)
447 : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC
448 );
449 fence_after(order);
450 return original;
451 }
452
453 static BOOST_FORCEINLINE storage_type fetch_sub(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
454 {
11fdf7f2 455 storage_type original, result;
b32b8144
FG
456 fence_before(order);
457 __asm__ __volatile__
458 (
459 "1:\n\t"
460 "lbarx %0,%y2\n\t"
461 "sub %1,%0,%3\n\t"
462 "stbcx. %1,%y2\n\t"
463 "bne- 1b\n\t"
11fdf7f2 464 : "=&b" (original), "=&b" (result), "+Z" (storage)
b32b8144
FG
465 : "b" (v)
466 : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC
467 );
468 fence_after(order);
469 return original;
470 }
471
472 static BOOST_FORCEINLINE storage_type fetch_and(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
473 {
11fdf7f2 474 storage_type original, result;
b32b8144
FG
475 fence_before(order);
476 __asm__ __volatile__
477 (
478 "1:\n\t"
479 "lbarx %0,%y2\n\t"
480 "and %1,%0,%3\n\t"
481 "stbcx. %1,%y2\n\t"
482 "bne- 1b\n\t"
11fdf7f2 483 : "=&b" (original), "=&b" (result), "+Z" (storage)
b32b8144
FG
484 : "b" (v)
485 : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC
486 );
487 fence_after(order);
488 return original;
489 }
490
491 static BOOST_FORCEINLINE storage_type fetch_or(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
492 {
11fdf7f2 493 storage_type original, result;
b32b8144
FG
494 fence_before(order);
495 __asm__ __volatile__
496 (
497 "1:\n\t"
498 "lbarx %0,%y2\n\t"
499 "or %1,%0,%3\n\t"
500 "stbcx. %1,%y2\n\t"
501 "bne- 1b\n\t"
11fdf7f2 502 : "=&b" (original), "=&b" (result), "+Z" (storage)
b32b8144
FG
503 : "b" (v)
504 : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC
505 );
506 fence_after(order);
507 return original;
508 }
509
510 static BOOST_FORCEINLINE storage_type fetch_xor(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
511 {
11fdf7f2 512 storage_type original, result;
b32b8144
FG
513 fence_before(order);
514 __asm__ __volatile__
515 (
516 "1:\n\t"
517 "lbarx %0,%y2\n\t"
518 "xor %1,%0,%3\n\t"
519 "stbcx. %1,%y2\n\t"
520 "bne- 1b\n\t"
11fdf7f2 521 : "=&b" (original), "=&b" (result), "+Z" (storage)
b32b8144
FG
522 : "b" (v)
523 : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC
524 );
525 fence_after(order);
526 return original;
527 }
528
529 static BOOST_FORCEINLINE bool test_and_set(storage_type volatile& storage, memory_order order) BOOST_NOEXCEPT
530 {
531 return !!exchange(storage, (storage_type)1, order);
532 }
7c673cae 533
b32b8144 534 static BOOST_FORCEINLINE void clear(storage_type volatile& storage, memory_order order) BOOST_NOEXCEPT
7c673cae 535 {
b32b8144 536 store(storage, 0, order);
7c673cae
FG
537 }
538};
539
b32b8144 540#else // defined(BOOST_ATOMIC_DETAIL_PPC_HAS_LBARX_STBCX)
7c673cae
FG
541
542template< >
543struct operations< 1u, false > :
544 public operations< 4u, false >
545{
546 typedef operations< 4u, false > base_type;
547 typedef base_type::storage_type storage_type;
548
549 static BOOST_FORCEINLINE storage_type fetch_add(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
550 {
11fdf7f2 551 storage_type original, result;
7c673cae
FG
552 fence_before(order);
553 __asm__ __volatile__
554 (
555 "1:\n\t"
556 "lwarx %0,%y2\n\t"
557 "add %1,%0,%3\n\t"
558 "rlwinm %1, %1, 0, 0xff\n\t"
559 "stwcx. %1,%y2\n\t"
560 "bne- 1b\n\t"
11fdf7f2 561 : "=&b" (original), "=&b" (result), "+Z" (storage)
7c673cae
FG
562 : "b" (v)
563 : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC
564 );
565 fence_after(order);
566 return original;
567 }
568
569 static BOOST_FORCEINLINE storage_type fetch_sub(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
570 {
11fdf7f2 571 storage_type original, result;
7c673cae
FG
572 fence_before(order);
573 __asm__ __volatile__
574 (
575 "1:\n\t"
576 "lwarx %0,%y2\n\t"
577 "sub %1,%0,%3\n\t"
578 "rlwinm %1, %1, 0, 0xff\n\t"
579 "stwcx. %1,%y2\n\t"
580 "bne- 1b\n\t"
11fdf7f2 581 : "=&b" (original), "=&b" (result), "+Z" (storage)
7c673cae
FG
582 : "b" (v)
583 : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC
584 );
585 fence_after(order);
586 return original;
587 }
588};
589
590template< >
591struct operations< 1u, true > :
592 public operations< 4u, true >
593{
594 typedef operations< 4u, true > base_type;
595 typedef base_type::storage_type storage_type;
596
597 static BOOST_FORCEINLINE storage_type fetch_add(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
598 {
11fdf7f2 599 storage_type original, result;
7c673cae
FG
600 fence_before(order);
601 __asm__ __volatile__
602 (
603 "1:\n\t"
604 "lwarx %0,%y2\n\t"
605 "add %1,%0,%3\n\t"
606 "extsb %1, %1\n\t"
607 "stwcx. %1,%y2\n\t"
608 "bne- 1b\n\t"
11fdf7f2 609 : "=&b" (original), "=&b" (result), "+Z" (storage)
7c673cae
FG
610 : "b" (v)
611 : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC
612 );
613 fence_after(order);
614 return original;
615 }
616
617 static BOOST_FORCEINLINE storage_type fetch_sub(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
618 {
11fdf7f2 619 storage_type original, result;
7c673cae
FG
620 fence_before(order);
621 __asm__ __volatile__
622 (
623 "1:\n\t"
624 "lwarx %0,%y2\n\t"
625 "sub %1,%0,%3\n\t"
626 "extsb %1, %1\n\t"
627 "stwcx. %1,%y2\n\t"
628 "bne- 1b\n\t"
11fdf7f2 629 : "=&b" (original), "=&b" (result), "+Z" (storage)
7c673cae
FG
630 : "b" (v)
631 : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC
632 );
633 fence_after(order);
634 return original;
635 }
636};
637
b32b8144
FG
638#endif // defined(BOOST_ATOMIC_DETAIL_PPC_HAS_LBARX_STBCX)
639
640#if defined(BOOST_ATOMIC_DETAIL_PPC_HAS_LHARX_STHCX)
641
642template< bool Signed >
643struct operations< 2u, Signed > :
644 public gcc_ppc_operations_base
645{
11fdf7f2
TL
646 typedef typename make_storage_type< 2u >::type storage_type;
647 typedef typename make_storage_type< 2u >::aligned aligned_storage_type;
b32b8144
FG
648
649 static BOOST_CONSTEXPR_OR_CONST std::size_t storage_size = 2u;
650 static BOOST_CONSTEXPR_OR_CONST bool is_signed = Signed;
651
652 static BOOST_FORCEINLINE void store(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
653 {
654 fence_before(order);
655 __asm__ __volatile__
656 (
657 "sth %1, %0\n\t"
658 : "+m" (storage)
659 : "r" (v)
660 );
661 }
662
663 static BOOST_FORCEINLINE storage_type load(storage_type const volatile& storage, memory_order order) BOOST_NOEXCEPT
664 {
665 storage_type v;
666 if (order == memory_order_seq_cst)
667 __asm__ __volatile__ ("sync" ::: "memory");
11fdf7f2 668 if ((static_cast< unsigned int >(order) & (static_cast< unsigned int >(memory_order_consume) | static_cast< unsigned int >(memory_order_acquire))) != 0u)
b32b8144
FG
669 {
670 __asm__ __volatile__
671 (
672 "lhz %0, %1\n\t"
673 "cmpw %0, %0\n\t"
674 "bne- 1f\n\t"
675 "1:\n\t"
676 "isync\n\t"
677 : "=&r" (v)
678 : "m" (storage)
679 : "cr0", "memory"
680 );
681 }
682 else
683 {
684 __asm__ __volatile__
685 (
686 "lhz %0, %1\n\t"
687 : "=&r" (v)
688 : "m" (storage)
689 );
690 }
691 return v;
692 }
693
694 static BOOST_FORCEINLINE storage_type exchange(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
695 {
696 storage_type original;
697 fence_before(order);
698 __asm__ __volatile__
699 (
700 "1:\n\t"
701 "lharx %0,%y1\n\t"
702 "sthcx. %2,%y1\n\t"
703 "bne- 1b\n\t"
704 : "=&b" (original), "+Z" (storage)
705 : "b" (v)
706 : "cr0"
707 );
708 fence_after(order);
709 return original;
710 }
711
712 static BOOST_FORCEINLINE bool compare_exchange_weak(
713 storage_type volatile& storage, storage_type& expected, storage_type desired, memory_order success_order, memory_order failure_order) BOOST_NOEXCEPT
714 {
715 int success;
716 fence_before(success_order);
717 __asm__ __volatile__
718 (
719 "li %1, 0\n\t"
720 "lharx %0,%y2\n\t"
721 "cmpw %0, %3\n\t"
722 "bne- 1f\n\t"
723 "sthcx. %4,%y2\n\t"
724 "bne- 1f\n\t"
725 "li %1, 1\n\t"
726 "1:\n\t"
727 : "=&b" (expected), "=&b" (success), "+Z" (storage)
11fdf7f2 728 : "b" (expected), "b" (desired)
b32b8144
FG
729 : "cr0"
730 );
731 if (success)
732 fence_after(success_order);
733 else
734 fence_after(failure_order);
735 return !!success;
736 }
737
738 static BOOST_FORCEINLINE bool compare_exchange_strong(
739 storage_type volatile& storage, storage_type& expected, storage_type desired, memory_order success_order, memory_order failure_order) BOOST_NOEXCEPT
740 {
741 int success;
742 fence_before(success_order);
743 __asm__ __volatile__
744 (
745 "li %1, 0\n\t"
746 "0: lharx %0,%y2\n\t"
747 "cmpw %0, %3\n\t"
748 "bne- 1f\n\t"
749 "sthcx. %4,%y2\n\t"
750 "bne- 0b\n\t"
751 "li %1, 1\n\t"
752 "1:\n\t"
753 : "=&b" (expected), "=&b" (success), "+Z" (storage)
11fdf7f2 754 : "b" (expected), "b" (desired)
b32b8144
FG
755 : "cr0"
756 );
757 if (success)
758 fence_after(success_order);
759 else
760 fence_after(failure_order);
761 return !!success;
762 }
763
764 static BOOST_FORCEINLINE storage_type fetch_add(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
765 {
11fdf7f2 766 storage_type original, result;
b32b8144
FG
767 fence_before(order);
768 __asm__ __volatile__
769 (
770 "1:\n\t"
771 "lharx %0,%y2\n\t"
772 "add %1,%0,%3\n\t"
773 "sthcx. %1,%y2\n\t"
774 "bne- 1b\n\t"
11fdf7f2 775 : "=&b" (original), "=&b" (result), "+Z" (storage)
b32b8144
FG
776 : "b" (v)
777 : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC
778 );
779 fence_after(order);
780 return original;
781 }
782
783 static BOOST_FORCEINLINE storage_type fetch_sub(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
784 {
11fdf7f2 785 storage_type original, result;
b32b8144
FG
786 fence_before(order);
787 __asm__ __volatile__
788 (
789 "1:\n\t"
790 "lharx %0,%y2\n\t"
791 "sub %1,%0,%3\n\t"
792 "sthcx. %1,%y2\n\t"
793 "bne- 1b\n\t"
11fdf7f2 794 : "=&b" (original), "=&b" (result), "+Z" (storage)
b32b8144
FG
795 : "b" (v)
796 : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC
797 );
798 fence_after(order);
799 return original;
800 }
801
802 static BOOST_FORCEINLINE storage_type fetch_and(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
803 {
11fdf7f2 804 storage_type original, result;
b32b8144
FG
805 fence_before(order);
806 __asm__ __volatile__
807 (
808 "1:\n\t"
809 "lharx %0,%y2\n\t"
810 "and %1,%0,%3\n\t"
811 "sthcx. %1,%y2\n\t"
812 "bne- 1b\n\t"
11fdf7f2 813 : "=&b" (original), "=&b" (result), "+Z" (storage)
b32b8144
FG
814 : "b" (v)
815 : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC
816 );
817 fence_after(order);
818 return original;
819 }
820
821 static BOOST_FORCEINLINE storage_type fetch_or(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
822 {
11fdf7f2 823 storage_type original, result;
b32b8144
FG
824 fence_before(order);
825 __asm__ __volatile__
826 (
827 "1:\n\t"
828 "lharx %0,%y2\n\t"
829 "or %1,%0,%3\n\t"
830 "sthcx. %1,%y2\n\t"
831 "bne- 1b\n\t"
11fdf7f2 832 : "=&b" (original), "=&b" (result), "+Z" (storage)
b32b8144
FG
833 : "b" (v)
834 : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC
835 );
836 fence_after(order);
837 return original;
838 }
839
840 static BOOST_FORCEINLINE storage_type fetch_xor(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
841 {
11fdf7f2 842 storage_type original, result;
b32b8144
FG
843 fence_before(order);
844 __asm__ __volatile__
845 (
846 "1:\n\t"
847 "lharx %0,%y2\n\t"
848 "xor %1,%0,%3\n\t"
849 "sthcx. %1,%y2\n\t"
850 "bne- 1b\n\t"
11fdf7f2 851 : "=&b" (original), "=&b" (result), "+Z" (storage)
b32b8144
FG
852 : "b" (v)
853 : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC
854 );
855 fence_after(order);
856 return original;
857 }
858
859 static BOOST_FORCEINLINE bool test_and_set(storage_type volatile& storage, memory_order order) BOOST_NOEXCEPT
860 {
861 return !!exchange(storage, (storage_type)1, order);
862 }
863
864 static BOOST_FORCEINLINE void clear(storage_type volatile& storage, memory_order order) BOOST_NOEXCEPT
865 {
866 store(storage, 0, order);
867 }
868};
869
870#else // defined(BOOST_ATOMIC_DETAIL_PPC_HAS_LHARX_STHCX)
7c673cae
FG
871
872template< >
873struct operations< 2u, false > :
874 public operations< 4u, false >
875{
876 typedef operations< 4u, false > base_type;
877 typedef base_type::storage_type storage_type;
878
879 static BOOST_FORCEINLINE storage_type fetch_add(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
880 {
11fdf7f2 881 storage_type original, result;
7c673cae
FG
882 fence_before(order);
883 __asm__ __volatile__
884 (
885 "1:\n\t"
886 "lwarx %0,%y2\n\t"
887 "add %1,%0,%3\n\t"
888 "rlwinm %1, %1, 0, 0xffff\n\t"
889 "stwcx. %1,%y2\n\t"
890 "bne- 1b\n\t"
11fdf7f2 891 : "=&b" (original), "=&b" (result), "+Z" (storage)
7c673cae
FG
892 : "b" (v)
893 : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC
894 );
895 fence_after(order);
896 return original;
897 }
898
899 static BOOST_FORCEINLINE storage_type fetch_sub(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
900 {
11fdf7f2 901 storage_type original, result;
7c673cae
FG
902 fence_before(order);
903 __asm__ __volatile__
904 (
905 "1:\n\t"
906 "lwarx %0,%y2\n\t"
907 "sub %1,%0,%3\n\t"
908 "rlwinm %1, %1, 0, 0xffff\n\t"
909 "stwcx. %1,%y2\n\t"
910 "bne- 1b\n\t"
11fdf7f2 911 : "=&b" (original), "=&b" (result), "+Z" (storage)
7c673cae
FG
912 : "b" (v)
913 : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC
914 );
915 fence_after(order);
916 return original;
917 }
918};
919
920template< >
921struct operations< 2u, true > :
922 public operations< 4u, true >
923{
924 typedef operations< 4u, true > base_type;
925 typedef base_type::storage_type storage_type;
926
927 static BOOST_FORCEINLINE storage_type fetch_add(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
928 {
11fdf7f2 929 storage_type original, result;
7c673cae
FG
930 fence_before(order);
931 __asm__ __volatile__
932 (
933 "1:\n\t"
934 "lwarx %0,%y2\n\t"
935 "add %1,%0,%3\n\t"
936 "extsh %1, %1\n\t"
937 "stwcx. %1,%y2\n\t"
938 "bne- 1b\n\t"
11fdf7f2 939 : "=&b" (original), "=&b" (result), "+Z" (storage)
7c673cae
FG
940 : "b" (v)
941 : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC
942 );
943 fence_after(order);
944 return original;
945 }
946
947 static BOOST_FORCEINLINE storage_type fetch_sub(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
948 {
11fdf7f2 949 storage_type original, result;
7c673cae
FG
950 fence_before(order);
951 __asm__ __volatile__
952 (
953 "1:\n\t"
954 "lwarx %0,%y2\n\t"
955 "sub %1,%0,%3\n\t"
956 "extsh %1, %1\n\t"
957 "stwcx. %1,%y2\n\t"
958 "bne- 1b\n\t"
11fdf7f2 959 : "=&b" (original), "=&b" (result), "+Z" (storage)
7c673cae
FG
960 : "b" (v)
961 : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC
962 );
963 fence_after(order);
964 return original;
965 }
966};
967
b32b8144 968#endif // defined(BOOST_ATOMIC_DETAIL_PPC_HAS_LHARX_STHCX)
7c673cae 969
b32b8144 970#if defined(BOOST_ATOMIC_DETAIL_PPC_HAS_LDARX_STDCX)
7c673cae
FG
971
972template< bool Signed >
973struct operations< 8u, Signed > :
974 public gcc_ppc_operations_base
975{
11fdf7f2
TL
976 typedef typename make_storage_type< 8u >::type storage_type;
977 typedef typename make_storage_type< 8u >::aligned aligned_storage_type;
7c673cae 978
b32b8144
FG
979 static BOOST_CONSTEXPR_OR_CONST std::size_t storage_size = 8u;
980 static BOOST_CONSTEXPR_OR_CONST bool is_signed = Signed;
981
7c673cae
FG
982 static BOOST_FORCEINLINE void store(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
983 {
984 fence_before(order);
985 __asm__ __volatile__
986 (
987 "std %1, %0\n\t"
988 : "+m" (storage)
989 : "r" (v)
990 );
991 }
992
993 static BOOST_FORCEINLINE storage_type load(storage_type const volatile& storage, memory_order order) BOOST_NOEXCEPT
994 {
995 storage_type v;
996 if (order == memory_order_seq_cst)
997 __asm__ __volatile__ ("sync" ::: "memory");
11fdf7f2 998 if ((static_cast< unsigned int >(order) & (static_cast< unsigned int >(memory_order_consume) | static_cast< unsigned int >(memory_order_acquire))) != 0u)
7c673cae
FG
999 {
1000 __asm__ __volatile__
1001 (
1002 "ld %0, %1\n\t"
1003 "cmpd %0, %0\n\t"
1004 "bne- 1f\n\t"
1005 "1:\n\t"
1006 "isync\n\t"
1007 : "=&b" (v)
1008 : "m" (storage)
1009 : "cr0", "memory"
1010 );
1011 }
1012 else
1013 {
1014 __asm__ __volatile__
1015 (
1016 "ld %0, %1\n\t"
1017 : "=&b" (v)
1018 : "m" (storage)
1019 );
1020 }
1021 return v;
1022 }
1023
1024 static BOOST_FORCEINLINE storage_type exchange(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
1025 {
1026 storage_type original;
1027 fence_before(order);
1028 __asm__ __volatile__
1029 (
1030 "1:\n\t"
1031 "ldarx %0,%y1\n\t"
1032 "stdcx. %2,%y1\n\t"
1033 "bne- 1b\n\t"
1034 : "=&b" (original), "+Z" (storage)
1035 : "b" (v)
1036 : "cr0"
1037 );
1038 fence_after(order);
1039 return original;
1040 }
1041
1042 static BOOST_FORCEINLINE bool compare_exchange_weak(
1043 storage_type volatile& storage, storage_type& expected, storage_type desired, memory_order success_order, memory_order failure_order) BOOST_NOEXCEPT
1044 {
1045 int success;
1046 fence_before(success_order);
1047 __asm__ __volatile__
1048 (
1049 "li %1, 0\n\t"
1050 "ldarx %0,%y2\n\t"
1051 "cmpd %0, %3\n\t"
1052 "bne- 1f\n\t"
1053 "stdcx. %4,%y2\n\t"
1054 "bne- 1f\n\t"
1055 "li %1, 1\n\t"
1056 "1:"
1057 : "=&b" (expected), "=&b" (success), "+Z" (storage)
1058 : "b" (expected), "b" (desired)
1059 : "cr0"
1060 );
1061 if (success)
1062 fence_after(success_order);
1063 else
1064 fence_after(failure_order);
1065 return !!success;
1066 }
1067
1068 static BOOST_FORCEINLINE bool compare_exchange_strong(
1069 storage_type volatile& storage, storage_type& expected, storage_type desired, memory_order success_order, memory_order failure_order) BOOST_NOEXCEPT
1070 {
1071 int success;
1072 fence_before(success_order);
1073 __asm__ __volatile__
1074 (
1075 "li %1, 0\n\t"
1076 "0: ldarx %0,%y2\n\t"
1077 "cmpd %0, %3\n\t"
1078 "bne- 1f\n\t"
1079 "stdcx. %4,%y2\n\t"
1080 "bne- 0b\n\t"
1081 "li %1, 1\n\t"
1082 "1:\n\t"
1083 : "=&b" (expected), "=&b" (success), "+Z" (storage)
1084 : "b" (expected), "b" (desired)
1085 : "cr0"
1086 );
1087 if (success)
1088 fence_after(success_order);
1089 else
1090 fence_after(failure_order);
1091 return !!success;
1092 }
1093
1094 static BOOST_FORCEINLINE storage_type fetch_add(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
1095 {
11fdf7f2 1096 storage_type original, result;
7c673cae
FG
1097 fence_before(order);
1098 __asm__ __volatile__
1099 (
1100 "1:\n\t"
1101 "ldarx %0,%y2\n\t"
1102 "add %1,%0,%3\n\t"
1103 "stdcx. %1,%y2\n\t"
1104 "bne- 1b\n\t"
11fdf7f2 1105 : "=&b" (original), "=&b" (result), "+Z" (storage)
7c673cae
FG
1106 : "b" (v)
1107 : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC
1108 );
1109 fence_after(order);
1110 return original;
1111 }
1112
1113 static BOOST_FORCEINLINE storage_type fetch_sub(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
1114 {
11fdf7f2 1115 storage_type original, result;
7c673cae
FG
1116 fence_before(order);
1117 __asm__ __volatile__
1118 (
1119 "1:\n\t"
1120 "ldarx %0,%y2\n\t"
1121 "sub %1,%0,%3\n\t"
1122 "stdcx. %1,%y2\n\t"
1123 "bne- 1b\n\t"
11fdf7f2 1124 : "=&b" (original), "=&b" (result), "+Z" (storage)
7c673cae
FG
1125 : "b" (v)
1126 : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC
1127 );
1128 fence_after(order);
1129 return original;
1130 }
1131
1132 static BOOST_FORCEINLINE storage_type fetch_and(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
1133 {
11fdf7f2 1134 storage_type original, result;
7c673cae
FG
1135 fence_before(order);
1136 __asm__ __volatile__
1137 (
1138 "1:\n\t"
1139 "ldarx %0,%y2\n\t"
1140 "and %1,%0,%3\n\t"
1141 "stdcx. %1,%y2\n\t"
1142 "bne- 1b\n\t"
11fdf7f2 1143 : "=&b" (original), "=&b" (result), "+Z" (storage)
7c673cae
FG
1144 : "b" (v)
1145 : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC
1146 );
1147 fence_after(order);
1148 return original;
1149 }
1150
1151 static BOOST_FORCEINLINE storage_type fetch_or(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
1152 {
11fdf7f2 1153 storage_type original, result;
7c673cae
FG
1154 fence_before(order);
1155 __asm__ __volatile__
1156 (
1157 "1:\n\t"
1158 "ldarx %0,%y2\n\t"
1159 "or %1,%0,%3\n\t"
1160 "stdcx. %1,%y2\n\t"
1161 "bne- 1b\n\t"
11fdf7f2 1162 : "=&b" (original), "=&b" (result), "+Z" (storage)
7c673cae
FG
1163 : "b" (v)
1164 : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC
1165 );
1166 fence_after(order);
1167 return original;
1168 }
1169
1170 static BOOST_FORCEINLINE storage_type fetch_xor(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
1171 {
11fdf7f2 1172 storage_type original, result;
7c673cae
FG
1173 fence_before(order);
1174 __asm__ __volatile__
1175 (
1176 "1:\n\t"
1177 "ldarx %0,%y2\n\t"
1178 "xor %1,%0,%3\n\t"
1179 "stdcx. %1,%y2\n\t"
1180 "bne- 1b\n\t"
11fdf7f2 1181 : "=&b" (original), "=&b" (result), "+Z" (storage)
7c673cae
FG
1182 : "b" (v)
1183 : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC
1184 );
1185 fence_after(order);
1186 return original;
1187 }
1188
1189 static BOOST_FORCEINLINE bool test_and_set(storage_type volatile& storage, memory_order order) BOOST_NOEXCEPT
1190 {
1191 return !!exchange(storage, (storage_type)1, order);
1192 }
1193
1194 static BOOST_FORCEINLINE void clear(storage_type volatile& storage, memory_order order) BOOST_NOEXCEPT
1195 {
1196 store(storage, 0, order);
1197 }
7c673cae
FG
1198};
1199
b32b8144 1200#endif // defined(BOOST_ATOMIC_DETAIL_PPC_HAS_LDARX_STDCX)
7c673cae
FG
1201
1202
1203BOOST_FORCEINLINE void thread_fence(memory_order order) BOOST_NOEXCEPT
1204{
11fdf7f2 1205 if (order != memory_order_relaxed)
7c673cae 1206 {
7c673cae 1207#if defined(__powerpc64__) || defined(__PPC64__)
11fdf7f2
TL
1208 if (order != memory_order_seq_cst)
1209 __asm__ __volatile__ ("lwsync" ::: "memory");
1210 else
1211 __asm__ __volatile__ ("sync" ::: "memory");
1212#else
7c673cae 1213 __asm__ __volatile__ ("sync" ::: "memory");
11fdf7f2 1214#endif
7c673cae
FG
1215 }
1216}
1217
1218BOOST_FORCEINLINE void signal_fence(memory_order order) BOOST_NOEXCEPT
1219{
1220 if (order != memory_order_relaxed)
1221#if defined(__ibmxl__) || defined(__IBMCPP__)
1222 __fence();
1223#else
1224 __asm__ __volatile__ ("" ::: "memory");
1225#endif
1226}
1227
1228} // namespace detail
1229} // namespace atomics
1230} // namespace boost
1231
1232#endif // BOOST_ATOMIC_DETAIL_OPS_GCC_PPC_HPP_INCLUDED_