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_alpha.hpp
12 *
13 * This header contains implementation of the \c operations template.
14 */
15
16 #ifndef BOOST_ATOMIC_DETAIL_OPS_GCC_ALPHA_HPP_INCLUDED_
17 #define BOOST_ATOMIC_DETAIL_OPS_GCC_ALPHA_HPP_INCLUDED_
18
19 #include <boost/memory_order.hpp>
20 #include <boost/atomic/detail/config.hpp>
21 #include <boost/atomic/detail/storage_type.hpp>
22 #include <boost/atomic/detail/operations_fwd.hpp>
23 #include <boost/atomic/capabilities.hpp>
24
25 #ifdef BOOST_HAS_PRAGMA_ONCE
26 #pragma once
27 #endif
28
29 namespace boost {
30 namespace atomics {
31 namespace detail {
32
33 /*
34 Refer to http://h71000.www7.hp.com/doc/82final/5601/5601pro_004.html
35 (HP OpenVMS systems documentation) and the Alpha Architecture Reference Manual.
36 */
37
38 /*
39 NB: The most natural thing would be to write the increment/decrement
40 operators along the following lines:
41
42 __asm__ __volatile__
43 (
44 "1: ldl_l %0,%1 \n"
45 "addl %0,1,%0 \n"
46 "stl_c %0,%1 \n"
47 "beq %0,1b\n"
48 : "=&b" (tmp)
49 : "m" (value)
50 : "cc"
51 );
52
53 However according to the comments on the HP website and matching
54 comments in the Linux kernel sources this defies branch prediction,
55 as the cpu assumes that backward branches are always taken; so
56 instead copy the trick from the Linux kernel, introduce a forward
57 branch and back again.
58
59 I have, however, had a hard time measuring the difference between
60 the two versions in microbenchmarks -- I am leaving it in nevertheless
61 as it apparently does not hurt either.
62 */
63
64 struct gcc_alpha_operations_base
65 {
fence_beforeboost::atomics::detail::gcc_alpha_operations_base66 static BOOST_FORCEINLINE void fence_before(memory_order order) BOOST_NOEXCEPT
67 {
68 if ((order & memory_order_release) != 0)
69 __asm__ __volatile__ ("mb" ::: "memory");
70 }
71
fence_afterboost::atomics::detail::gcc_alpha_operations_base72 static BOOST_FORCEINLINE void fence_after(memory_order order) BOOST_NOEXCEPT
73 {
74 if ((order & (memory_order_consume | memory_order_acquire)) != 0)
75 __asm__ __volatile__ ("mb" ::: "memory");
76 }
77
fence_after_storeboost::atomics::detail::gcc_alpha_operations_base78 static BOOST_FORCEINLINE void fence_after_store(memory_order order) BOOST_NOEXCEPT
79 {
80 if (order == memory_order_seq_cst)
81 __asm__ __volatile__ ("mb" ::: "memory");
82 }
83 };
84
85
86 template< bool Signed >
87 struct operations< 4u, Signed > :
88 public gcc_alpha_operations_base
89 {
90 typedef typename make_storage_type< 4u, Signed >::type storage_type;
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 storage = v;
96 fence_after_store(order);
97 }
98
loadboost::atomics::detail::operations99 static BOOST_FORCEINLINE storage_type load(storage_type const volatile& storage, memory_order order) BOOST_NOEXCEPT
100 {
101 storage_type v = storage;
102 fence_after(order);
103 return v;
104 }
105
exchangeboost::atomics::detail::operations106 static BOOST_FORCEINLINE storage_type exchange(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
107 {
108 storage_type original, tmp;
109 fence_before(order);
110 __asm__ __volatile__
111 (
112 "1:\n"
113 "mov %3, %1\n"
114 "ldl_l %0, %2\n"
115 "stl_c %1, %2\n"
116 "beq %1, 2f\n"
117
118 ".subsection 2\n"
119 "2: br 1b\n"
120 ".previous\n"
121
122 : "=&r" (original), // %0
123 "=&r" (tmp) // %1
124 : "m" (storage), // %2
125 "r" (v) // %3
126 : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC
127 );
128 fence_after(order);
129 return original;
130 }
131
compare_exchange_weakboost::atomics::detail::operations132 static BOOST_FORCEINLINE bool compare_exchange_weak(
133 storage_type volatile& storage, storage_type& expected, storage_type desired, memory_order success_order, memory_order failure_order) BOOST_NOEXCEPT
134 {
135 fence_before(success_order);
136 int success;
137 storage_type current;
138 __asm__ __volatile__
139 (
140 "1:\n"
141 "ldl_l %2, %4\n" // current = *(&storage)
142 "cmpeq %2, %0, %3\n" // success = current == expected
143 "mov %2, %0\n" // expected = current
144 "beq %3, 2f\n" // if (success == 0) goto end
145 "stl_c %1, %4\n" // storage = desired; desired = store succeeded
146 "mov %1, %3\n" // success = desired
147 "2:\n"
148 : "+&r" (expected), // %0
149 "+&r" (desired), // %1
150 "=&r" (current), // %2
151 "=&r" (success) // %3
152 : "m" (storage) // %4
153 : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC
154 );
155 if (success)
156 fence_after(success_order);
157 else
158 fence_after(failure_order);
159 return !!success;
160 }
161
compare_exchange_strongboost::atomics::detail::operations162 static BOOST_FORCEINLINE bool compare_exchange_strong(
163 storage_type volatile& storage, storage_type& expected, storage_type desired, memory_order success_order, memory_order failure_order) BOOST_NOEXCEPT
164 {
165 int success;
166 storage_type current, tmp;
167 fence_before(success_order);
168 __asm__ __volatile__
169 (
170 "1:\n"
171 "mov %5, %1\n" // tmp = desired
172 "ldl_l %2, %4\n" // current = *(&storage)
173 "cmpeq %2, %0, %3\n" // success = current == expected
174 "mov %2, %0\n" // expected = current
175 "beq %3, 2f\n" // if (success == 0) goto end
176 "stl_c %1, %4\n" // storage = tmp; tmp = store succeeded
177 "beq %1, 3f\n" // if (tmp == 0) goto retry
178 "mov %1, %3\n" // success = tmp
179 "2:\n"
180
181 ".subsection 2\n"
182 "3: br 1b\n"
183 ".previous\n"
184
185 : "+&r" (expected), // %0
186 "=&r" (tmp), // %1
187 "=&r" (current), // %2
188 "=&r" (success) // %3
189 : "m" (storage), // %4
190 "r" (desired) // %5
191 : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC
192 );
193 if (success)
194 fence_after(success_order);
195 else
196 fence_after(failure_order);
197 return !!success;
198 }
199
fetch_addboost::atomics::detail::operations200 static BOOST_FORCEINLINE storage_type fetch_add(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
201 {
202 storage_type original, modified;
203 fence_before(order);
204 __asm__ __volatile__
205 (
206 "1:\n"
207 "ldl_l %0, %2\n"
208 "addl %0, %3, %1\n"
209 "stl_c %1, %2\n"
210 "beq %1, 2f\n"
211
212 ".subsection 2\n"
213 "2: br 1b\n"
214 ".previous\n"
215
216 : "=&r" (original), // %0
217 "=&r" (modified) // %1
218 : "m" (storage), // %2
219 "r" (v) // %3
220 : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC
221 );
222 fence_after(order);
223 return original;
224 }
225
fetch_subboost::atomics::detail::operations226 static BOOST_FORCEINLINE storage_type fetch_sub(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
227 {
228 storage_type original, modified;
229 fence_before(order);
230 __asm__ __volatile__
231 (
232 "1:\n"
233 "ldl_l %0, %2\n"
234 "subl %0, %3, %1\n"
235 "stl_c %1, %2\n"
236 "beq %1, 2f\n"
237
238 ".subsection 2\n"
239 "2: br 1b\n"
240 ".previous\n"
241
242 : "=&r" (original), // %0
243 "=&r" (modified) // %1
244 : "m" (storage), // %2
245 "r" (v) // %3
246 : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC
247 );
248 fence_after(order);
249 return original;
250 }
251
fetch_andboost::atomics::detail::operations252 static BOOST_FORCEINLINE storage_type fetch_and(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
253 {
254 storage_type original, modified;
255 fence_before(order);
256 __asm__ __volatile__
257 (
258 "1:\n"
259 "ldl_l %0, %2\n"
260 "and %0, %3, %1\n"
261 "stl_c %1, %2\n"
262 "beq %1, 2f\n"
263
264 ".subsection 2\n"
265 "2: br 1b\n"
266 ".previous\n"
267
268 : "=&r" (original), // %0
269 "=&r" (modified) // %1
270 : "m" (storage), // %2
271 "r" (v) // %3
272 : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC
273 );
274 fence_after(order);
275 return original;
276 }
277
fetch_orboost::atomics::detail::operations278 static BOOST_FORCEINLINE storage_type fetch_or(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
279 {
280 storage_type original, modified;
281 fence_before(order);
282 __asm__ __volatile__
283 (
284 "1:\n"
285 "ldl_l %0, %2\n"
286 "bis %0, %3, %1\n"
287 "stl_c %1, %2\n"
288 "beq %1, 2f\n"
289
290 ".subsection 2\n"
291 "2: br 1b\n"
292 ".previous\n"
293
294 : "=&r" (original), // %0
295 "=&r" (modified) // %1
296 : "m" (storage), // %2
297 "r" (v) // %3
298 : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC
299 );
300 fence_after(order);
301 return original;
302 }
303
fetch_xorboost::atomics::detail::operations304 static BOOST_FORCEINLINE storage_type fetch_xor(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
305 {
306 storage_type original, modified;
307 fence_before(order);
308 __asm__ __volatile__
309 (
310 "1:\n"
311 "ldl_l %0, %2\n"
312 "xor %0, %3, %1\n"
313 "stl_c %1, %2\n"
314 "beq %1, 2f\n"
315
316 ".subsection 2\n"
317 "2: br 1b\n"
318 ".previous\n"
319
320 : "=&r" (original), // %0
321 "=&r" (modified) // %1
322 : "m" (storage), // %2
323 "r" (v) // %3
324 : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC
325 );
326 fence_after(order);
327 return original;
328 }
329
test_and_setboost::atomics::detail::operations330 static BOOST_FORCEINLINE bool test_and_set(storage_type volatile& storage, memory_order order) BOOST_NOEXCEPT
331 {
332 return !!exchange(storage, (storage_type)1, order);
333 }
334
clearboost::atomics::detail::operations335 static BOOST_FORCEINLINE void clear(storage_type volatile& storage, memory_order order) BOOST_NOEXCEPT
336 {
337 store(storage, 0, order);
338 }
339
is_lock_freeboost::atomics::detail::operations340 static BOOST_FORCEINLINE bool is_lock_free(storage_type const volatile&) BOOST_NOEXCEPT
341 {
342 return true;
343 }
344 };
345
346
347 template< >
348 struct operations< 1u, false > :
349 public operations< 4u, false >
350 {
351 typedef operations< 4u, false > base_type;
352 typedef base_type::storage_type storage_type;
353
fetch_addboost::atomics::detail::operations354 static BOOST_FORCEINLINE storage_type fetch_add(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
355 {
356 storage_type original, modified;
357 fence_before(order);
358 __asm__ __volatile__
359 (
360 "1:\n"
361 "ldl_l %0, %2\n"
362 "addl %0, %3, %1\n"
363 "zapnot %1, #1, %1\n"
364 "stl_c %1, %2\n"
365 "beq %1, 2f\n"
366
367 ".subsection 2\n"
368 "2: br 1b\n"
369 ".previous\n"
370
371 : "=&r" (original), // %0
372 "=&r" (modified) // %1
373 : "m" (storage), // %2
374 "r" (v) // %3
375 : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC
376 );
377 fence_after(order);
378 return original;
379 }
380
fetch_subboost::atomics::detail::operations381 static BOOST_FORCEINLINE storage_type fetch_sub(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
382 {
383 storage_type original, modified;
384 fence_before(order);
385 __asm__ __volatile__
386 (
387 "1:\n"
388 "ldl_l %0, %2\n"
389 "subl %0, %3, %1\n"
390 "zapnot %1, #1, %1\n"
391 "stl_c %1, %2\n"
392 "beq %1, 2f\n"
393
394 ".subsection 2\n"
395 "2: br 1b\n"
396 ".previous\n"
397
398 : "=&r" (original), // %0
399 "=&r" (modified) // %1
400 : "m" (storage), // %2
401 "r" (v) // %3
402 : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC
403 );
404 fence_after(order);
405 return original;
406 }
407 };
408
409 template< >
410 struct operations< 1u, true > :
411 public operations< 4u, true >
412 {
413 typedef operations< 4u, true > base_type;
414 typedef base_type::storage_type storage_type;
415
fetch_addboost::atomics::detail::operations416 static BOOST_FORCEINLINE storage_type fetch_add(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
417 {
418 storage_type original, modified;
419 fence_before(order);
420 __asm__ __volatile__
421 (
422 "1:\n"
423 "ldl_l %0, %2\n"
424 "addl %0, %3, %1\n"
425 "sextb %1, %1\n"
426 "stl_c %1, %2\n"
427 "beq %1, 2f\n"
428
429 ".subsection 2\n"
430 "2: br 1b\n"
431 ".previous\n"
432
433 : "=&r" (original), // %0
434 "=&r" (modified) // %1
435 : "m" (storage), // %2
436 "r" (v) // %3
437 : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC
438 );
439 fence_after(order);
440 return original;
441 }
442
fetch_subboost::atomics::detail::operations443 static BOOST_FORCEINLINE storage_type fetch_sub(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
444 {
445 storage_type original, modified;
446 fence_before(order);
447 __asm__ __volatile__
448 (
449 "1:\n"
450 "ldl_l %0, %2\n"
451 "subl %0, %3, %1\n"
452 "sextb %1, %1\n"
453 "stl_c %1, %2\n"
454 "beq %1, 2f\n"
455
456 ".subsection 2\n"
457 "2: br 1b\n"
458 ".previous\n"
459
460 : "=&r" (original), // %0
461 "=&r" (modified) // %1
462 : "m" (storage), // %2
463 "r" (v) // %3
464 : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC
465 );
466 fence_after(order);
467 return original;
468 }
469 };
470
471
472 template< >
473 struct operations< 2u, false > :
474 public operations< 4u, false >
475 {
476 typedef operations< 4u, false > base_type;
477 typedef base_type::storage_type storage_type;
478
fetch_addboost::atomics::detail::operations479 static BOOST_FORCEINLINE storage_type fetch_add(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
480 {
481 storage_type original, modified;
482 fence_before(order);
483 __asm__ __volatile__
484 (
485 "1:\n"
486 "ldl_l %0, %2\n"
487 "addl %0, %3, %1\n"
488 "zapnot %1, #3, %1\n"
489 "stl_c %1, %2\n"
490 "beq %1, 2f\n"
491
492 ".subsection 2\n"
493 "2: br 1b\n"
494 ".previous\n"
495
496 : "=&r" (original), // %0
497 "=&r" (modified) // %1
498 : "m" (storage), // %2
499 "r" (v) // %3
500 : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC
501 );
502 fence_after(order);
503 return original;
504 }
505
fetch_subboost::atomics::detail::operations506 static BOOST_FORCEINLINE storage_type fetch_sub(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
507 {
508 storage_type original, modified;
509 fence_before(order);
510 __asm__ __volatile__
511 (
512 "1:\n"
513 "ldl_l %0, %2\n"
514 "subl %0, %3, %1\n"
515 "zapnot %1, #3, %1\n"
516 "stl_c %1, %2\n"
517 "beq %1, 2f\n"
518
519 ".subsection 2\n"
520 "2: br 1b\n"
521 ".previous\n"
522
523 : "=&r" (original), // %0
524 "=&r" (modified) // %1
525 : "m" (storage), // %2
526 "r" (v) // %3
527 : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC
528 );
529 fence_after(order);
530 return original;
531 }
532 };
533
534 template< >
535 struct operations< 2u, true > :
536 public operations< 4u, true >
537 {
538 typedef operations< 4u, true > base_type;
539 typedef base_type::storage_type storage_type;
540
fetch_addboost::atomics::detail::operations541 static BOOST_FORCEINLINE storage_type fetch_add(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
542 {
543 storage_type original, modified;
544 fence_before(order);
545 __asm__ __volatile__
546 (
547 "1:\n"
548 "ldl_l %0, %2\n"
549 "addl %0, %3, %1\n"
550 "sextw %1, %1\n"
551 "stl_c %1, %2\n"
552 "beq %1, 2f\n"
553
554 ".subsection 2\n"
555 "2: br 1b\n"
556 ".previous\n"
557
558 : "=&r" (original), // %0
559 "=&r" (modified) // %1
560 : "m" (storage), // %2
561 "r" (v) // %3
562 : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC
563 );
564 fence_after(order);
565 return original;
566 }
567
fetch_subboost::atomics::detail::operations568 static BOOST_FORCEINLINE storage_type fetch_sub(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
569 {
570 storage_type original, modified;
571 fence_before(order);
572 __asm__ __volatile__
573 (
574 "1:\n"
575 "ldl_l %0, %2\n"
576 "subl %0, %3, %1\n"
577 "sextw %1, %1\n"
578 "stl_c %1, %2\n"
579 "beq %1, 2f\n"
580
581 ".subsection 2\n"
582 "2: br 1b\n"
583 ".previous\n"
584
585 : "=&r" (original), // %0
586 "=&r" (modified) // %1
587 : "m" (storage), // %2
588 "r" (v) // %3
589 : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC
590 );
591 fence_after(order);
592 return original;
593 }
594 };
595
596
597 template< bool Signed >
598 struct operations< 8u, Signed > :
599 public gcc_alpha_operations_base
600 {
601 typedef typename make_storage_type< 8u, Signed >::type storage_type;
602
storeboost::atomics::detail::operations603 static BOOST_FORCEINLINE void store(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
604 {
605 fence_before(order);
606 storage = v;
607 fence_after_store(order);
608 }
609
loadboost::atomics::detail::operations610 static BOOST_FORCEINLINE storage_type load(storage_type const volatile& storage, memory_order order) BOOST_NOEXCEPT
611 {
612 storage_type v = storage;
613 fence_after(order);
614 return v;
615 }
616
exchangeboost::atomics::detail::operations617 static BOOST_FORCEINLINE storage_type exchange(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
618 {
619 storage_type original, tmp;
620 fence_before(order);
621 __asm__ __volatile__
622 (
623 "1:\n"
624 "mov %3, %1\n"
625 "ldq_l %0, %2\n"
626 "stq_c %1, %2\n"
627 "beq %1, 2f\n"
628
629 ".subsection 2\n"
630 "2: br 1b\n"
631 ".previous\n"
632
633 : "=&r" (original), // %0
634 "=&r" (tmp) // %1
635 : "m" (storage), // %2
636 "r" (v) // %3
637 : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC
638 );
639 fence_after(order);
640 return original;
641 }
642
compare_exchange_weakboost::atomics::detail::operations643 static BOOST_FORCEINLINE bool compare_exchange_weak(
644 storage_type volatile& storage, storage_type& expected, storage_type desired, memory_order success_order, memory_order failure_order) BOOST_NOEXCEPT
645 {
646 fence_before(success_order);
647 int success;
648 storage_type current;
649 __asm__ __volatile__
650 (
651 "1:\n"
652 "ldq_l %2, %4\n" // current = *(&storage)
653 "cmpeq %2, %0, %3\n" // success = current == expected
654 "mov %2, %0\n" // expected = current
655 "beq %3, 2f\n" // if (success == 0) goto end
656 "stq_c %1, %4\n" // storage = desired; desired = store succeeded
657 "mov %1, %3\n" // success = desired
658 "2:\n"
659 : "+&r" (expected), // %0
660 "+&r" (desired), // %1
661 "=&r" (current), // %2
662 "=&r" (success) // %3
663 : "m" (storage) // %4
664 : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC
665 );
666 if (success)
667 fence_after(success_order);
668 else
669 fence_after(failure_order);
670 return !!success;
671 }
672
compare_exchange_strongboost::atomics::detail::operations673 static BOOST_FORCEINLINE bool compare_exchange_strong(
674 storage_type volatile& storage, storage_type& expected, storage_type desired, memory_order success_order, memory_order failure_order) BOOST_NOEXCEPT
675 {
676 int success;
677 storage_type current, tmp;
678 fence_before(success_order);
679 __asm__ __volatile__
680 (
681 "1:\n"
682 "mov %5, %1\n" // tmp = desired
683 "ldq_l %2, %4\n" // current = *(&storage)
684 "cmpeq %2, %0, %3\n" // success = current == expected
685 "mov %2, %0\n" // expected = current
686 "beq %3, 2f\n" // if (success == 0) goto end
687 "stq_c %1, %4\n" // storage = tmp; tmp = store succeeded
688 "beq %1, 3f\n" // if (tmp == 0) goto retry
689 "mov %1, %3\n" // success = tmp
690 "2:\n"
691
692 ".subsection 2\n"
693 "3: br 1b\n"
694 ".previous\n"
695
696 : "+&r" (expected), // %0
697 "=&r" (tmp), // %1
698 "=&r" (current), // %2
699 "=&r" (success) // %3
700 : "m" (storage), // %4
701 "r" (desired) // %5
702 : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC
703 );
704 if (success)
705 fence_after(success_order);
706 else
707 fence_after(failure_order);
708 return !!success;
709 }
710
fetch_addboost::atomics::detail::operations711 static BOOST_FORCEINLINE storage_type fetch_add(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
712 {
713 storage_type original, modified;
714 fence_before(order);
715 __asm__ __volatile__
716 (
717 "1:\n"
718 "ldq_l %0, %2\n"
719 "addq %0, %3, %1\n"
720 "stq_c %1, %2\n"
721 "beq %1, 2f\n"
722
723 ".subsection 2\n"
724 "2: br 1b\n"
725 ".previous\n"
726
727 : "=&r" (original), // %0
728 "=&r" (modified) // %1
729 : "m" (storage), // %2
730 "r" (v) // %3
731 : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC
732 );
733 fence_after(order);
734 return original;
735 }
736
fetch_subboost::atomics::detail::operations737 static BOOST_FORCEINLINE storage_type fetch_sub(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
738 {
739 storage_type original, modified;
740 fence_before(order);
741 __asm__ __volatile__
742 (
743 "1:\n"
744 "ldq_l %0, %2\n"
745 "subq %0, %3, %1\n"
746 "stq_c %1, %2\n"
747 "beq %1, 2f\n"
748
749 ".subsection 2\n"
750 "2: br 1b\n"
751 ".previous\n"
752
753 : "=&r" (original), // %0
754 "=&r" (modified) // %1
755 : "m" (storage), // %2
756 "r" (v) // %3
757 : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC
758 );
759 fence_after(order);
760 return original;
761 }
762
fetch_andboost::atomics::detail::operations763 static BOOST_FORCEINLINE storage_type fetch_and(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
764 {
765 storage_type original, modified;
766 fence_before(order);
767 __asm__ __volatile__
768 (
769 "1:\n"
770 "ldq_l %0, %2\n"
771 "and %0, %3, %1\n"
772 "stq_c %1, %2\n"
773 "beq %1, 2f\n"
774
775 ".subsection 2\n"
776 "2: br 1b\n"
777 ".previous\n"
778
779 : "=&r" (original), // %0
780 "=&r" (modified) // %1
781 : "m" (storage), // %2
782 "r" (v) // %3
783 : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC
784 );
785 fence_after(order);
786 return original;
787 }
788
fetch_orboost::atomics::detail::operations789 static BOOST_FORCEINLINE storage_type fetch_or(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
790 {
791 storage_type original, modified;
792 fence_before(order);
793 __asm__ __volatile__
794 (
795 "1:\n"
796 "ldq_l %0, %2\n"
797 "bis %0, %3, %1\n"
798 "stq_c %1, %2\n"
799 "beq %1, 2f\n"
800
801 ".subsection 2\n"
802 "2: br 1b\n"
803 ".previous\n"
804
805 : "=&r" (original), // %0
806 "=&r" (modified) // %1
807 : "m" (storage), // %2
808 "r" (v) // %3
809 : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC
810 );
811 fence_after(order);
812 return original;
813 }
814
fetch_xorboost::atomics::detail::operations815 static BOOST_FORCEINLINE storage_type fetch_xor(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
816 {
817 storage_type original, modified;
818 fence_before(order);
819 __asm__ __volatile__
820 (
821 "1:\n"
822 "ldq_l %0, %2\n"
823 "xor %0, %3, %1\n"
824 "stq_c %1, %2\n"
825 "beq %1, 2f\n"
826
827 ".subsection 2\n"
828 "2: br 1b\n"
829 ".previous\n"
830
831 : "=&r" (original), // %0
832 "=&r" (modified) // %1
833 : "m" (storage), // %2
834 "r" (v) // %3
835 : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC
836 );
837 fence_after(order);
838 return original;
839 }
840
test_and_setboost::atomics::detail::operations841 static BOOST_FORCEINLINE bool test_and_set(storage_type volatile& storage, memory_order order) BOOST_NOEXCEPT
842 {
843 return !!exchange(storage, (storage_type)1, order);
844 }
845
clearboost::atomics::detail::operations846 static BOOST_FORCEINLINE void clear(storage_type volatile& storage, memory_order order) BOOST_NOEXCEPT
847 {
848 store(storage, 0, order);
849 }
850
is_lock_freeboost::atomics::detail::operations851 static BOOST_FORCEINLINE bool is_lock_free(storage_type const volatile&) BOOST_NOEXCEPT
852 {
853 return true;
854 }
855 };
856
857
thread_fence(memory_order order)858 BOOST_FORCEINLINE void thread_fence(memory_order order) BOOST_NOEXCEPT
859 {
860 if (order != memory_order_relaxed)
861 __asm__ __volatile__ ("mb" ::: "memory");
862 }
863
signal_fence(memory_order order)864 BOOST_FORCEINLINE void signal_fence(memory_order order) BOOST_NOEXCEPT
865 {
866 if (order != memory_order_relaxed)
867 __asm__ __volatile__ ("" ::: "memory");
868 }
869
870 } // namespace detail
871 } // namespace atomics
872 } // namespace boost
873
874 #endif // BOOST_ATOMIC_DETAIL_OPS_GCC_ALPHA_HPP_INCLUDED_
875