• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
19 #include <cstddef>
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>
24 #include <boost/atomic/detail/ops_gcc_ppc_common.hpp>
25 #include <boost/atomic/capabilities.hpp>
26 
27 #ifdef BOOST_HAS_PRAGMA_ONCE
28 #pragma once
29 #endif
30 
31 namespace boost {
32 namespace atomics {
33 namespace 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 
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
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 
82 template< bool Signed >
83 struct operations< 4u, Signed > :
84     public gcc_ppc_operations_base
85 {
86     typedef typename make_storage_type< 4u >::type storage_type;
87     typedef typename make_storage_type< 4u >::aligned aligned_storage_type;
88 
89     static BOOST_CONSTEXPR_OR_CONST std::size_t storage_size = 4u;
90     static BOOST_CONSTEXPR_OR_CONST bool is_signed = Signed;
91 
storeboost::atomics::detail::operations92     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 
loadboost::atomics::detail::operations103     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");
108         if ((static_cast< unsigned int >(order) & (static_cast< unsigned int >(memory_order_consume) | static_cast< unsigned int >(memory_order_acquire))) != 0u)
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 
exchangeboost::atomics::detail::operations134     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 
compare_exchange_weakboost::atomics::detail::operations152     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 
compare_exchange_strongboost::atomics::detail::operations178     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 
fetch_addboost::atomics::detail::operations204     static BOOST_FORCEINLINE storage_type fetch_add(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
205     {
206         storage_type original, result;
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"
215             : "=&b" (original), "=&b" (result), "+Z" (storage)
216             : "b" (v)
217             : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC
218         );
219         fence_after(order);
220         return original;
221     }
222 
fetch_subboost::atomics::detail::operations223     static BOOST_FORCEINLINE storage_type fetch_sub(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
224     {
225         storage_type original, result;
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"
234             : "=&b" (original), "=&b" (result), "+Z" (storage)
235             : "b" (v)
236             : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC
237         );
238         fence_after(order);
239         return original;
240     }
241 
fetch_andboost::atomics::detail::operations242     static BOOST_FORCEINLINE storage_type fetch_and(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
243     {
244         storage_type original, result;
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"
253             : "=&b" (original), "=&b" (result), "+Z" (storage)
254             : "b" (v)
255             : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC
256         );
257         fence_after(order);
258         return original;
259     }
260 
fetch_orboost::atomics::detail::operations261     static BOOST_FORCEINLINE storage_type fetch_or(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
262     {
263         storage_type original, result;
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"
272             : "=&b" (original), "=&b" (result), "+Z" (storage)
273             : "b" (v)
274             : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC
275         );
276         fence_after(order);
277         return original;
278     }
279 
fetch_xorboost::atomics::detail::operations280     static BOOST_FORCEINLINE storage_type fetch_xor(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
281     {
282         storage_type original, result;
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"
291             : "=&b" (original), "=&b" (result), "+Z" (storage)
292             : "b" (v)
293             : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC
294         );
295         fence_after(order);
296         return original;
297     }
298 
test_and_setboost::atomics::detail::operations299     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 
clearboost::atomics::detail::operations304     static BOOST_FORCEINLINE void clear(storage_type volatile& storage, memory_order order) BOOST_NOEXCEPT
305     {
306         store(storage, 0, order);
307     }
308 };
309 
310 #if defined(BOOST_ATOMIC_DETAIL_PPC_HAS_LBARX_STBCX)
311 
312 template< bool Signed >
313 struct operations< 1u, Signed > :
314     public gcc_ppc_operations_base
315 {
316     typedef typename make_storage_type< 1u >::type storage_type;
317     typedef typename make_storage_type< 1u >::aligned aligned_storage_type;
318 
319     static BOOST_CONSTEXPR_OR_CONST std::size_t storage_size = 1u;
320     static BOOST_CONSTEXPR_OR_CONST bool is_signed = Signed;
321 
storeboost::atomics::detail::operations322     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 
loadboost::atomics::detail::operations333     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");
338         if ((static_cast< unsigned int >(order) & (static_cast< unsigned int >(memory_order_consume) | static_cast< unsigned int >(memory_order_acquire))) != 0u)
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 
exchangeboost::atomics::detail::operations364     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 
compare_exchange_weakboost::atomics::detail::operations382     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)
398             : "b" (expected), "b" (desired)
399             : "cr0"
400         );
401         if (success)
402             fence_after(success_order);
403         else
404             fence_after(failure_order);
405         return !!success;
406     }
407 
compare_exchange_strongboost::atomics::detail::operations408     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)
424             : "b" (expected), "b" (desired)
425             : "cr0"
426         );
427         if (success)
428             fence_after(success_order);
429         else
430             fence_after(failure_order);
431         return !!success;
432     }
433 
fetch_addboost::atomics::detail::operations434     static BOOST_FORCEINLINE storage_type fetch_add(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
435     {
436         storage_type original, result;
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"
445             : "=&b" (original), "=&b" (result), "+Z" (storage)
446             : "b" (v)
447             : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC
448         );
449         fence_after(order);
450         return original;
451     }
452 
fetch_subboost::atomics::detail::operations453     static BOOST_FORCEINLINE storage_type fetch_sub(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
454     {
455         storage_type original, result;
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"
464             : "=&b" (original), "=&b" (result), "+Z" (storage)
465             : "b" (v)
466             : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC
467         );
468         fence_after(order);
469         return original;
470     }
471 
fetch_andboost::atomics::detail::operations472     static BOOST_FORCEINLINE storage_type fetch_and(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
473     {
474         storage_type original, result;
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"
483             : "=&b" (original), "=&b" (result), "+Z" (storage)
484             : "b" (v)
485             : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC
486         );
487         fence_after(order);
488         return original;
489     }
490 
fetch_orboost::atomics::detail::operations491     static BOOST_FORCEINLINE storage_type fetch_or(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
492     {
493         storage_type original, result;
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"
502             : "=&b" (original), "=&b" (result), "+Z" (storage)
503             : "b" (v)
504             : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC
505         );
506         fence_after(order);
507         return original;
508     }
509 
fetch_xorboost::atomics::detail::operations510     static BOOST_FORCEINLINE storage_type fetch_xor(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
511     {
512         storage_type original, result;
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"
521             : "=&b" (original), "=&b" (result), "+Z" (storage)
522             : "b" (v)
523             : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC
524         );
525         fence_after(order);
526         return original;
527     }
528 
test_and_setboost::atomics::detail::operations529     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     }
533 
clearboost::atomics::detail::operations534     static BOOST_FORCEINLINE void clear(storage_type volatile& storage, memory_order order) BOOST_NOEXCEPT
535     {
536         store(storage, 0, order);
537     }
538 };
539 
540 #else // defined(BOOST_ATOMIC_DETAIL_PPC_HAS_LBARX_STBCX)
541 
542 template< >
543 struct 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 
fetch_addboost::atomics::detail::operations549     static BOOST_FORCEINLINE storage_type fetch_add(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
550     {
551         storage_type original, result;
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"
561             : "=&b" (original), "=&b" (result), "+Z" (storage)
562             : "b" (v)
563             : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC
564         );
565         fence_after(order);
566         return original;
567     }
568 
fetch_subboost::atomics::detail::operations569     static BOOST_FORCEINLINE storage_type fetch_sub(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
570     {
571         storage_type original, result;
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"
581             : "=&b" (original), "=&b" (result), "+Z" (storage)
582             : "b" (v)
583             : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC
584         );
585         fence_after(order);
586         return original;
587     }
588 };
589 
590 template< >
591 struct 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 
fetch_addboost::atomics::detail::operations597     static BOOST_FORCEINLINE storage_type fetch_add(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
598     {
599         storage_type original, result;
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"
609             : "=&b" (original), "=&b" (result), "+Z" (storage)
610             : "b" (v)
611             : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC
612         );
613         fence_after(order);
614         return original;
615     }
616 
fetch_subboost::atomics::detail::operations617     static BOOST_FORCEINLINE storage_type fetch_sub(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
618     {
619         storage_type original, result;
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"
629             : "=&b" (original), "=&b" (result), "+Z" (storage)
630             : "b" (v)
631             : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC
632         );
633         fence_after(order);
634         return original;
635     }
636 };
637 
638 #endif // defined(BOOST_ATOMIC_DETAIL_PPC_HAS_LBARX_STBCX)
639 
640 #if defined(BOOST_ATOMIC_DETAIL_PPC_HAS_LHARX_STHCX)
641 
642 template< bool Signed >
643 struct operations< 2u, Signed > :
644     public gcc_ppc_operations_base
645 {
646     typedef typename make_storage_type< 2u >::type storage_type;
647     typedef typename make_storage_type< 2u >::aligned aligned_storage_type;
648 
649     static BOOST_CONSTEXPR_OR_CONST std::size_t storage_size = 2u;
650     static BOOST_CONSTEXPR_OR_CONST bool is_signed = Signed;
651 
storeboost::atomics::detail::operations652     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 
loadboost::atomics::detail::operations663     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");
668         if ((static_cast< unsigned int >(order) & (static_cast< unsigned int >(memory_order_consume) | static_cast< unsigned int >(memory_order_acquire))) != 0u)
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 
exchangeboost::atomics::detail::operations694     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 
compare_exchange_weakboost::atomics::detail::operations712     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)
728             : "b" (expected), "b" (desired)
729             : "cr0"
730         );
731         if (success)
732             fence_after(success_order);
733         else
734             fence_after(failure_order);
735         return !!success;
736     }
737 
compare_exchange_strongboost::atomics::detail::operations738     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)
754             : "b" (expected), "b" (desired)
755             : "cr0"
756         );
757         if (success)
758             fence_after(success_order);
759         else
760             fence_after(failure_order);
761         return !!success;
762     }
763 
fetch_addboost::atomics::detail::operations764     static BOOST_FORCEINLINE storage_type fetch_add(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
765     {
766         storage_type original, result;
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"
775             : "=&b" (original), "=&b" (result), "+Z" (storage)
776             : "b" (v)
777             : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC
778         );
779         fence_after(order);
780         return original;
781     }
782 
fetch_subboost::atomics::detail::operations783     static BOOST_FORCEINLINE storage_type fetch_sub(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
784     {
785         storage_type original, result;
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"
794             : "=&b" (original), "=&b" (result), "+Z" (storage)
795             : "b" (v)
796             : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC
797         );
798         fence_after(order);
799         return original;
800     }
801 
fetch_andboost::atomics::detail::operations802     static BOOST_FORCEINLINE storage_type fetch_and(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
803     {
804         storage_type original, result;
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"
813             : "=&b" (original), "=&b" (result), "+Z" (storage)
814             : "b" (v)
815             : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC
816         );
817         fence_after(order);
818         return original;
819     }
820 
fetch_orboost::atomics::detail::operations821     static BOOST_FORCEINLINE storage_type fetch_or(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
822     {
823         storage_type original, result;
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"
832             : "=&b" (original), "=&b" (result), "+Z" (storage)
833             : "b" (v)
834             : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC
835         );
836         fence_after(order);
837         return original;
838     }
839 
fetch_xorboost::atomics::detail::operations840     static BOOST_FORCEINLINE storage_type fetch_xor(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
841     {
842         storage_type original, result;
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"
851             : "=&b" (original), "=&b" (result), "+Z" (storage)
852             : "b" (v)
853             : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC
854         );
855         fence_after(order);
856         return original;
857     }
858 
test_and_setboost::atomics::detail::operations859     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 
clearboost::atomics::detail::operations864     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)
871 
872 template< >
873 struct 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 
fetch_addboost::atomics::detail::operations879     static BOOST_FORCEINLINE storage_type fetch_add(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
880     {
881         storage_type original, result;
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"
891             : "=&b" (original), "=&b" (result), "+Z" (storage)
892             : "b" (v)
893             : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC
894         );
895         fence_after(order);
896         return original;
897     }
898 
fetch_subboost::atomics::detail::operations899     static BOOST_FORCEINLINE storage_type fetch_sub(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
900     {
901         storage_type original, result;
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"
911             : "=&b" (original), "=&b" (result), "+Z" (storage)
912             : "b" (v)
913             : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC
914         );
915         fence_after(order);
916         return original;
917     }
918 };
919 
920 template< >
921 struct 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 
fetch_addboost::atomics::detail::operations927     static BOOST_FORCEINLINE storage_type fetch_add(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
928     {
929         storage_type original, result;
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"
939             : "=&b" (original), "=&b" (result), "+Z" (storage)
940             : "b" (v)
941             : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC
942         );
943         fence_after(order);
944         return original;
945     }
946 
fetch_subboost::atomics::detail::operations947     static BOOST_FORCEINLINE storage_type fetch_sub(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
948     {
949         storage_type original, result;
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"
959             : "=&b" (original), "=&b" (result), "+Z" (storage)
960             : "b" (v)
961             : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC
962         );
963         fence_after(order);
964         return original;
965     }
966 };
967 
968 #endif // defined(BOOST_ATOMIC_DETAIL_PPC_HAS_LHARX_STHCX)
969 
970 #if defined(BOOST_ATOMIC_DETAIL_PPC_HAS_LDARX_STDCX)
971 
972 template< bool Signed >
973 struct operations< 8u, Signed > :
974     public gcc_ppc_operations_base
975 {
976     typedef typename make_storage_type< 8u >::type storage_type;
977     typedef typename make_storage_type< 8u >::aligned aligned_storage_type;
978 
979     static BOOST_CONSTEXPR_OR_CONST std::size_t storage_size = 8u;
980     static BOOST_CONSTEXPR_OR_CONST bool is_signed = Signed;
981 
storeboost::atomics::detail::operations982     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 
loadboost::atomics::detail::operations993     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");
998         if ((static_cast< unsigned int >(order) & (static_cast< unsigned int >(memory_order_consume) | static_cast< unsigned int >(memory_order_acquire))) != 0u)
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 
exchangeboost::atomics::detail::operations1024     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 
compare_exchange_weakboost::atomics::detail::operations1042     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 
compare_exchange_strongboost::atomics::detail::operations1068     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 
fetch_addboost::atomics::detail::operations1094     static BOOST_FORCEINLINE storage_type fetch_add(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
1095     {
1096         storage_type original, result;
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"
1105             : "=&b" (original), "=&b" (result), "+Z" (storage)
1106             : "b" (v)
1107             : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC
1108         );
1109         fence_after(order);
1110         return original;
1111     }
1112 
fetch_subboost::atomics::detail::operations1113     static BOOST_FORCEINLINE storage_type fetch_sub(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
1114     {
1115         storage_type original, result;
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"
1124             : "=&b" (original), "=&b" (result), "+Z" (storage)
1125             : "b" (v)
1126             : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC
1127         );
1128         fence_after(order);
1129         return original;
1130     }
1131 
fetch_andboost::atomics::detail::operations1132     static BOOST_FORCEINLINE storage_type fetch_and(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
1133     {
1134         storage_type original, result;
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"
1143             : "=&b" (original), "=&b" (result), "+Z" (storage)
1144             : "b" (v)
1145             : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC
1146         );
1147         fence_after(order);
1148         return original;
1149     }
1150 
fetch_orboost::atomics::detail::operations1151     static BOOST_FORCEINLINE storage_type fetch_or(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
1152     {
1153         storage_type original, result;
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"
1162             : "=&b" (original), "=&b" (result), "+Z" (storage)
1163             : "b" (v)
1164             : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC
1165         );
1166         fence_after(order);
1167         return original;
1168     }
1169 
fetch_xorboost::atomics::detail::operations1170     static BOOST_FORCEINLINE storage_type fetch_xor(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
1171     {
1172         storage_type original, result;
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"
1181             : "=&b" (original), "=&b" (result), "+Z" (storage)
1182             : "b" (v)
1183             : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC
1184         );
1185         fence_after(order);
1186         return original;
1187     }
1188 
test_and_setboost::atomics::detail::operations1189     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 
clearboost::atomics::detail::operations1194     static BOOST_FORCEINLINE void clear(storage_type volatile& storage, memory_order order) BOOST_NOEXCEPT
1195     {
1196         store(storage, 0, order);
1197     }
1198 };
1199 
1200 #endif // defined(BOOST_ATOMIC_DETAIL_PPC_HAS_LDARX_STDCX)
1201 
1202 
thread_fence(memory_order order)1203 BOOST_FORCEINLINE void thread_fence(memory_order order) BOOST_NOEXCEPT
1204 {
1205     if (order != memory_order_relaxed)
1206     {
1207 #if defined(__powerpc64__) || defined(__PPC64__)
1208         if (order != memory_order_seq_cst)
1209             __asm__ __volatile__ ("lwsync" ::: "memory");
1210         else
1211             __asm__ __volatile__ ("sync" ::: "memory");
1212 #else
1213         __asm__ __volatile__ ("sync" ::: "memory");
1214 #endif
1215     }
1216 }
1217 
signal_fence(memory_order order)1218 BOOST_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_
1233