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)
6 * Copyright (c) 2017 - 2018 Andrey Semashev
9 * \file atomic/detail/extra_ops_gcc_arm.hpp
11 * This header contains implementation of the extra atomic operations for ARM.
14 #ifndef BOOST_ATOMIC_DETAIL_EXTRA_OPS_GCC_ARM_HPP_INCLUDED_
15 #define BOOST_ATOMIC_DETAIL_EXTRA_OPS_GCC_ARM_HPP_INCLUDED_
18 #include <boost/cstdint.hpp>
19 #include <boost/memory_order.hpp>
20 #include <boost/atomic/detail/config.hpp>
21 #include <boost/atomic/detail/platform.hpp>
22 #include <boost/atomic/detail/storage_traits.hpp>
23 #include <boost/atomic/detail/extra_operations_fwd.hpp>
24 #include <boost/atomic/detail/extra_ops_generic.hpp>
25 #include <boost/atomic/detail/ops_gcc_arm_common.hpp>
26 #include <boost/atomic/capabilities.hpp>
28 #ifdef BOOST_HAS_PRAGMA_ONCE
36 template< typename Base >
37 struct gcc_arm_extra_operations_common :
40 typedef Base base_type;
41 typedef typename base_type::storage_type storage_type;
43 static BOOST_FORCEINLINE void opaque_negate(storage_type volatile& storage, memory_order order) BOOST_NOEXCEPT
45 base_type::fetch_negate(storage, order);
48 static BOOST_FORCEINLINE void opaque_complement(storage_type volatile& storage, memory_order order) BOOST_NOEXCEPT
50 base_type::fetch_complement(storage, order);
53 static BOOST_FORCEINLINE bool negate_and_test(storage_type volatile& storage, memory_order order) BOOST_NOEXCEPT
55 return !!base_type::negate(storage, order);
58 static BOOST_FORCEINLINE bool add_and_test(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
60 return !!base_type::add(storage, v, order);
63 static BOOST_FORCEINLINE bool sub_and_test(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
65 return !!base_type::sub(storage, v, order);
68 static BOOST_FORCEINLINE bool and_and_test(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
70 return !!base_type::bitwise_and(storage, v, order);
73 static BOOST_FORCEINLINE bool or_and_test(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
75 return !!base_type::bitwise_or(storage, v, order);
78 static BOOST_FORCEINLINE bool xor_and_test(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
80 return !!base_type::bitwise_xor(storage, v, order);
83 static BOOST_FORCEINLINE bool complement_and_test(storage_type volatile& storage, memory_order order) BOOST_NOEXCEPT
85 return !!base_type::bitwise_complement(storage, order);
89 template< typename Base, std::size_t Size, bool Signed >
90 struct gcc_arm_extra_operations;
92 #if defined(BOOST_ATOMIC_DETAIL_ARM_HAS_LDREXB_STREXB)
94 template< typename Base, bool Signed >
95 struct gcc_arm_extra_operations< Base, 1u, Signed > :
96 public generic_extra_operations< Base, 1u, Signed >
98 typedef generic_extra_operations< Base, 1u, Signed > base_type;
99 typedef typename base_type::storage_type storage_type;
100 typedef typename storage_traits< 4u >::type extended_storage_type;
102 static BOOST_FORCEINLINE storage_type fetch_negate(storage_type volatile& storage, memory_order order) BOOST_NOEXCEPT
104 gcc_arm_operations_base::fence_before(order);
106 extended_storage_type original, result;
109 BOOST_ATOMIC_DETAIL_ARM_ASM_START(%[tmp])
111 "ldrexb %[original], %[storage]\n" // original = zero_extend(*(&storage))
112 "rsb %[result], %[original], #0\n" // result = 0 - original
113 "strexb %[tmp], %[result], %[storage]\n" // *(&storage) = result, tmp = store failed
114 "teq %[tmp], #0\n" // flags = tmp==0
115 "bne 1b\n" // if (!flags.equal) goto retry
116 BOOST_ATOMIC_DETAIL_ARM_ASM_END(%[tmp])
117 : [original] "=&r" (original), // %0
118 [result] "=&r" (result), // %1
119 [tmp] "=&l" (tmp), // %2
120 [storage] "+Q" (storage) // %3
122 : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC
124 gcc_arm_operations_base::fence_after(order);
125 return static_cast< storage_type >(original);
128 static BOOST_FORCEINLINE storage_type negate(storage_type volatile& storage, memory_order order) BOOST_NOEXCEPT
130 gcc_arm_operations_base::fence_before(order);
132 extended_storage_type original, result;
135 BOOST_ATOMIC_DETAIL_ARM_ASM_START(%[tmp])
137 "ldrexb %[original], %[storage]\n" // original = zero_extend(*(&storage))
138 "rsb %[result], %[original], #0\n" // result = 0 - original
139 "strexb %[tmp], %[result], %[storage]\n" // *(&storage) = result, tmp = store failed
140 "teq %[tmp], #0\n" // flags = tmp==0
141 "bne 1b\n" // if (!flags.equal) goto retry
142 BOOST_ATOMIC_DETAIL_ARM_ASM_END(%[tmp])
143 : [original] "=&r" (original), // %0
144 [result] "=&r" (result), // %1
145 [tmp] "=&l" (tmp), // %2
146 [storage] "+Q" (storage) // %3
148 : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC
150 gcc_arm_operations_base::fence_after(order);
151 return static_cast< storage_type >(result);
154 static BOOST_FORCEINLINE storage_type add(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
156 gcc_arm_operations_base::fence_before(order);
158 extended_storage_type original, result;
161 BOOST_ATOMIC_DETAIL_ARM_ASM_START(%[tmp])
163 "ldrexb %[original], %[storage]\n" // original = zero_extend(*(&storage))
164 "add %[result], %[original], %[value]\n" // result = original + value
165 "strexb %[tmp], %[result], %[storage]\n" // *(&storage) = result, tmp = store failed
166 "teq %[tmp], #0\n" // flags = tmp==0
167 "bne 1b\n" // if (!flags.equal) goto retry
168 BOOST_ATOMIC_DETAIL_ARM_ASM_END(%[tmp])
169 : [original] "=&r" (original), // %0
170 [result] "=&r" (result), // %1
171 [tmp] "=&l" (tmp), // %2
172 [storage] "+Q" (storage) // %3
173 : [value] "Ir" (v) // %4
174 : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC
176 gcc_arm_operations_base::fence_after(order);
177 return static_cast< storage_type >(result);
180 static BOOST_FORCEINLINE storage_type sub(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
182 gcc_arm_operations_base::fence_before(order);
184 extended_storage_type original, result;
187 BOOST_ATOMIC_DETAIL_ARM_ASM_START(%[tmp])
189 "ldrexb %[original], %[storage]\n" // original = zero_extend(*(&storage))
190 "sub %[result], %[original], %[value]\n" // result = original - value
191 "strexb %[tmp], %[result], %[storage]\n" // *(&storage) = result, tmp = store failed
192 "teq %[tmp], #0\n" // flags = tmp==0
193 "bne 1b\n" // if (!flags.equal) goto retry
194 BOOST_ATOMIC_DETAIL_ARM_ASM_END(%[tmp])
195 : [original] "=&r" (original), // %0
196 [result] "=&r" (result), // %1
197 [tmp] "=&l" (tmp), // %2
198 [storage] "+Q" (storage) // %3
199 : [value] "Ir" (v) // %4
200 : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC
202 gcc_arm_operations_base::fence_after(order);
203 return static_cast< storage_type >(result);
206 static BOOST_FORCEINLINE storage_type bitwise_and(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
208 gcc_arm_operations_base::fence_before(order);
210 extended_storage_type original, result;
213 BOOST_ATOMIC_DETAIL_ARM_ASM_START(%[tmp])
215 "ldrexb %[original], %[storage]\n" // original = zero_extend(*(&storage))
216 "and %[result], %[original], %[value]\n" // result = original & value
217 "strexb %[tmp], %[result], %[storage]\n" // *(&storage) = result, tmp = store failed
218 "teq %[tmp], #0\n" // flags = tmp==0
219 "bne 1b\n" // if (!flags.equal) goto retry
220 BOOST_ATOMIC_DETAIL_ARM_ASM_END(%[tmp])
221 : [original] "=&r" (original), // %0
222 [result] "=&r" (result), // %1
223 [tmp] "=&l" (tmp), // %2
224 [storage] "+Q" (storage) // %3
225 : [value] "Ir" (v) // %4
226 : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC
228 gcc_arm_operations_base::fence_after(order);
229 return static_cast< storage_type >(result);
232 static BOOST_FORCEINLINE storage_type bitwise_or(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
234 gcc_arm_operations_base::fence_before(order);
236 extended_storage_type original, result;
239 BOOST_ATOMIC_DETAIL_ARM_ASM_START(%[tmp])
241 "ldrexb %[original], %[storage]\n" // original = zero_extend(*(&storage))
242 "orr %[result], %[original], %[value]\n" // result = original | value
243 "strexb %[tmp], %[result], %[storage]\n" // *(&storage) = result, tmp = store failed
244 "teq %[tmp], #0\n" // flags = tmp==0
245 "bne 1b\n" // if (!flags.equal) goto retry
246 BOOST_ATOMIC_DETAIL_ARM_ASM_END(%[tmp])
247 : [original] "=&r" (original), // %0
248 [result] "=&r" (result), // %1
249 [tmp] "=&l" (tmp), // %2
250 [storage] "+Q" (storage) // %3
251 : [value] "Ir" (v) // %4
252 : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC
254 gcc_arm_operations_base::fence_after(order);
255 return static_cast< storage_type >(result);
258 static BOOST_FORCEINLINE storage_type bitwise_xor(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
260 gcc_arm_operations_base::fence_before(order);
262 extended_storage_type original, result;
265 BOOST_ATOMIC_DETAIL_ARM_ASM_START(%[tmp])
267 "ldrexb %[original], %[storage]\n" // original = zero_extend(*(&storage))
268 "eor %[result], %[original], %[value]\n" // result = original ^ value
269 "strexb %[tmp], %[result], %[storage]\n" // *(&storage) = result, tmp = store failed
270 "teq %[tmp], #0\n" // flags = tmp==0
271 "bne 1b\n" // if (!flags.equal) goto retry
272 BOOST_ATOMIC_DETAIL_ARM_ASM_END(%[tmp])
273 : [original] "=&r" (original), // %0
274 [result] "=&r" (result), // %1
275 [tmp] "=&l" (tmp), // %2
276 [storage] "+Q" (storage) // %3
277 : [value] "Ir" (v) // %4
278 : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC
280 gcc_arm_operations_base::fence_after(order);
281 return static_cast< storage_type >(result);
284 static BOOST_FORCEINLINE storage_type fetch_complement(storage_type volatile& storage, memory_order order) BOOST_NOEXCEPT
286 gcc_arm_operations_base::fence_before(order);
288 extended_storage_type original, result;
291 BOOST_ATOMIC_DETAIL_ARM_ASM_START(%[tmp])
293 "ldrexb %[original], %[storage]\n" // original = zero_extend(*(&storage))
294 "mvn %[result], %[original]\n" // result = NOT original
295 "strexb %[tmp], %[result], %[storage]\n" // *(&storage) = result, tmp = store failed
296 "teq %[tmp], #0\n" // flags = tmp==0
297 "bne 1b\n" // if (!flags.equal) goto retry
298 BOOST_ATOMIC_DETAIL_ARM_ASM_END(%[tmp])
299 : [original] "=&r" (original), // %0
300 [result] "=&r" (result), // %1
301 [tmp] "=&l" (tmp), // %2
302 [storage] "+Q" (storage) // %3
304 : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC
306 gcc_arm_operations_base::fence_after(order);
307 return static_cast< storage_type >(original);
310 static BOOST_FORCEINLINE storage_type bitwise_complement(storage_type volatile& storage, memory_order order) BOOST_NOEXCEPT
312 gcc_arm_operations_base::fence_before(order);
314 extended_storage_type original, result;
317 BOOST_ATOMIC_DETAIL_ARM_ASM_START(%[tmp])
319 "ldrexb %[original], %[storage]\n" // original = zero_extend(*(&storage))
320 "mvn %[result], %[original]\n" // result = NOT original
321 "strexb %[tmp], %[result], %[storage]\n" // *(&storage) = result, tmp = store failed
322 "teq %[tmp], #0\n" // flags = tmp==0
323 "bne 1b\n" // if (!flags.equal) goto retry
324 BOOST_ATOMIC_DETAIL_ARM_ASM_END(%[tmp])
325 : [original] "=&r" (original), // %0
326 [result] "=&r" (result), // %1
327 [tmp] "=&l" (tmp), // %2
328 [storage] "+Q" (storage) // %3
330 : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC
332 gcc_arm_operations_base::fence_after(order);
333 return static_cast< storage_type >(result);
337 template< typename Base, bool Signed >
338 struct extra_operations< Base, 1u, Signed, true > :
339 public gcc_arm_extra_operations_common< gcc_arm_extra_operations< Base, 1u, Signed > >
343 #endif // defined(BOOST_ATOMIC_DETAIL_ARM_HAS_LDREXB_STREXB)
345 #if defined(BOOST_ATOMIC_DETAIL_ARM_HAS_LDREXH_STREXH)
347 template< typename Base, bool Signed >
348 struct gcc_arm_extra_operations< Base, 2u, Signed > :
349 public generic_extra_operations< Base, 2u, Signed >
351 typedef generic_extra_operations< Base, 2u, Signed > base_type;
352 typedef typename base_type::storage_type storage_type;
353 typedef typename storage_traits< 4u >::type extended_storage_type;
355 static BOOST_FORCEINLINE storage_type fetch_negate(storage_type volatile& storage, memory_order order) BOOST_NOEXCEPT
357 gcc_arm_operations_base::fence_before(order);
359 extended_storage_type original, result;
362 BOOST_ATOMIC_DETAIL_ARM_ASM_START(%[tmp])
364 "ldrexh %[original], %[storage]\n" // original = zero_extend(*(&storage))
365 "rsb %[result], %[original], #0\n" // result = 0 - original
366 "strexh %[tmp], %[result], %[storage]\n" // *(&storage) = result, tmp = store failed
367 "teq %[tmp], #0\n" // flags = tmp==0
368 "bne 1b\n" // if (!flags.equal) goto retry
369 BOOST_ATOMIC_DETAIL_ARM_ASM_END(%[tmp])
370 : [original] "=&r" (original), // %0
371 [result] "=&r" (result), // %1
372 [tmp] "=&l" (tmp), // %2
373 [storage] "+Q" (storage) // %3
375 : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC
377 gcc_arm_operations_base::fence_after(order);
378 return static_cast< storage_type >(original);
381 static BOOST_FORCEINLINE storage_type negate(storage_type volatile& storage, memory_order order) BOOST_NOEXCEPT
383 gcc_arm_operations_base::fence_before(order);
385 extended_storage_type original, result;
388 BOOST_ATOMIC_DETAIL_ARM_ASM_START(%[tmp])
390 "ldrexh %[original], %[storage]\n" // original = zero_extend(*(&storage))
391 "rsb %[result], %[original], #0\n" // result = 0 - original
392 "strexh %[tmp], %[result], %[storage]\n" // *(&storage) = result, tmp = store failed
393 "teq %[tmp], #0\n" // flags = tmp==0
394 "bne 1b\n" // if (!flags.equal) goto retry
395 BOOST_ATOMIC_DETAIL_ARM_ASM_END(%[tmp])
396 : [original] "=&r" (original), // %0
397 [result] "=&r" (result), // %1
398 [tmp] "=&l" (tmp), // %2
399 [storage] "+Q" (storage) // %3
401 : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC
403 gcc_arm_operations_base::fence_after(order);
404 return static_cast< storage_type >(result);
407 static BOOST_FORCEINLINE storage_type add(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
409 gcc_arm_operations_base::fence_before(order);
411 extended_storage_type original, result;
414 BOOST_ATOMIC_DETAIL_ARM_ASM_START(%[tmp])
416 "ldrexh %[original], %[storage]\n" // original = zero_extend(*(&storage))
417 "add %[result], %[original], %[value]\n" // result = original + value
418 "strexh %[tmp], %[result], %[storage]\n" // *(&storage) = result, tmp = store failed
419 "teq %[tmp], #0\n" // flags = tmp==0
420 "bne 1b\n" // if (!flags.equal) goto retry
421 BOOST_ATOMIC_DETAIL_ARM_ASM_END(%[tmp])
422 : [original] "=&r" (original), // %0
423 [result] "=&r" (result), // %1
424 [tmp] "=&l" (tmp), // %2
425 [storage] "+Q" (storage) // %3
426 : [value] "Ir" (v) // %4
427 : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC
429 gcc_arm_operations_base::fence_after(order);
430 return static_cast< storage_type >(result);
433 static BOOST_FORCEINLINE storage_type sub(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
435 gcc_arm_operations_base::fence_before(order);
437 extended_storage_type original, result;
440 BOOST_ATOMIC_DETAIL_ARM_ASM_START(%[tmp])
442 "ldrexh %[original], %[storage]\n" // original = zero_extend(*(&storage))
443 "sub %[result], %[original], %[value]\n" // result = original - value
444 "strexh %[tmp], %[result], %[storage]\n" // *(&storage) = result, tmp = store failed
445 "teq %[tmp], #0\n" // flags = tmp==0
446 "bne 1b\n" // if (!flags.equal) goto retry
447 BOOST_ATOMIC_DETAIL_ARM_ASM_END(%[tmp])
448 : [original] "=&r" (original), // %0
449 [result] "=&r" (result), // %1
450 [tmp] "=&l" (tmp), // %2
451 [storage] "+Q" (storage) // %3
452 : [value] "Ir" (v) // %4
453 : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC
455 gcc_arm_operations_base::fence_after(order);
456 return static_cast< storage_type >(result);
459 static BOOST_FORCEINLINE storage_type bitwise_and(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
461 gcc_arm_operations_base::fence_before(order);
463 extended_storage_type original, result;
466 BOOST_ATOMIC_DETAIL_ARM_ASM_START(%[tmp])
468 "ldrexh %[original], %[storage]\n" // original = zero_extend(*(&storage))
469 "and %[result], %[original], %[value]\n" // result = original & value
470 "strexh %[tmp], %[result], %[storage]\n" // *(&storage) = result, tmp = store failed
471 "teq %[tmp], #0\n" // flags = tmp==0
472 "bne 1b\n" // if (!flags.equal) goto retry
473 BOOST_ATOMIC_DETAIL_ARM_ASM_END(%[tmp])
474 : [original] "=&r" (original), // %0
475 [result] "=&r" (result), // %1
476 [tmp] "=&l" (tmp), // %2
477 [storage] "+Q" (storage) // %3
478 : [value] "Ir" (v) // %4
479 : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC
481 gcc_arm_operations_base::fence_after(order);
482 return static_cast< storage_type >(result);
485 static BOOST_FORCEINLINE storage_type bitwise_or(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
487 gcc_arm_operations_base::fence_before(order);
489 extended_storage_type original, result;
492 BOOST_ATOMIC_DETAIL_ARM_ASM_START(%[tmp])
494 "ldrexh %[original], %[storage]\n" // original = zero_extend(*(&storage))
495 "orr %[result], %[original], %[value]\n" // result = original | value
496 "strexh %[tmp], %[result], %[storage]\n" // *(&storage) = result, tmp = store failed
497 "teq %[tmp], #0\n" // flags = tmp==0
498 "bne 1b\n" // if (!flags.equal) goto retry
499 BOOST_ATOMIC_DETAIL_ARM_ASM_END(%[tmp])
500 : [original] "=&r" (original), // %0
501 [result] "=&r" (result), // %1
502 [tmp] "=&l" (tmp), // %2
503 [storage] "+Q" (storage) // %3
504 : [value] "Ir" (v) // %4
505 : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC
507 gcc_arm_operations_base::fence_after(order);
508 return static_cast< storage_type >(result);
511 static BOOST_FORCEINLINE storage_type bitwise_xor(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
513 gcc_arm_operations_base::fence_before(order);
515 extended_storage_type original, result;
518 BOOST_ATOMIC_DETAIL_ARM_ASM_START(%[tmp])
520 "ldrexh %[original], %[storage]\n" // original = zero_extend(*(&storage))
521 "eor %[result], %[original], %[value]\n" // result = original ^ value
522 "strexh %[tmp], %[result], %[storage]\n" // *(&storage) = result, tmp = store failed
523 "teq %[tmp], #0\n" // flags = tmp==0
524 "bne 1b\n" // if (!flags.equal) goto retry
525 BOOST_ATOMIC_DETAIL_ARM_ASM_END(%[tmp])
526 : [original] "=&r" (original), // %0
527 [result] "=&r" (result), // %1
528 [tmp] "=&l" (tmp), // %2
529 [storage] "+Q" (storage) // %3
530 : [value] "Ir" (v) // %4
531 : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC
533 gcc_arm_operations_base::fence_after(order);
534 return static_cast< storage_type >(result);
537 static BOOST_FORCEINLINE storage_type fetch_complement(storage_type volatile& storage, memory_order order) BOOST_NOEXCEPT
539 gcc_arm_operations_base::fence_before(order);
541 extended_storage_type original, result;
544 BOOST_ATOMIC_DETAIL_ARM_ASM_START(%[tmp])
546 "ldrexh %[original], %[storage]\n" // original = zero_extend(*(&storage))
547 "mvn %[result], %[original]\n" // result = NOT original
548 "strexh %[tmp], %[result], %[storage]\n" // *(&storage) = result, tmp = store failed
549 "teq %[tmp], #0\n" // flags = tmp==0
550 "bne 1b\n" // if (!flags.equal) goto retry
551 BOOST_ATOMIC_DETAIL_ARM_ASM_END(%[tmp])
552 : [original] "=&r" (original), // %0
553 [result] "=&r" (result), // %1
554 [tmp] "=&l" (tmp), // %2
555 [storage] "+Q" (storage) // %3
557 : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC
559 gcc_arm_operations_base::fence_after(order);
560 return static_cast< storage_type >(original);
563 static BOOST_FORCEINLINE storage_type bitwise_complement(storage_type volatile& storage, memory_order order) BOOST_NOEXCEPT
565 gcc_arm_operations_base::fence_before(order);
567 extended_storage_type original, result;
570 BOOST_ATOMIC_DETAIL_ARM_ASM_START(%[tmp])
572 "ldrexh %[original], %[storage]\n" // original = zero_extend(*(&storage))
573 "mvn %[result], %[original]\n" // result = NOT original
574 "strexh %[tmp], %[result], %[storage]\n" // *(&storage) = result, tmp = store failed
575 "teq %[tmp], #0\n" // flags = tmp==0
576 "bne 1b\n" // if (!flags.equal) goto retry
577 BOOST_ATOMIC_DETAIL_ARM_ASM_END(%[tmp])
578 : [original] "=&r" (original), // %0
579 [result] "=&r" (result), // %1
580 [tmp] "=&l" (tmp), // %2
581 [storage] "+Q" (storage) // %3
583 : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC
585 gcc_arm_operations_base::fence_after(order);
586 return static_cast< storage_type >(result);
590 template< typename Base, bool Signed >
591 struct extra_operations< Base, 2u, Signed, true > :
592 public gcc_arm_extra_operations_common< gcc_arm_extra_operations< Base, 2u, Signed > >
596 #endif // defined(BOOST_ATOMIC_DETAIL_ARM_HAS_LDREXH_STREXH)
598 template< typename Base, bool Signed >
599 struct gcc_arm_extra_operations< Base, 4u, Signed > :
600 public generic_extra_operations< Base, 4u, Signed >
602 typedef generic_extra_operations< Base, 4u, Signed > base_type;
603 typedef typename base_type::storage_type storage_type;
605 static BOOST_FORCEINLINE storage_type fetch_negate(storage_type volatile& storage, memory_order order) BOOST_NOEXCEPT
607 gcc_arm_operations_base::fence_before(order);
609 storage_type original, result;
612 BOOST_ATOMIC_DETAIL_ARM_ASM_START(%[tmp])
614 "ldrex %[original], %[storage]\n" // original = *(&storage)
615 "rsb %[result], %[original], #0\n" // result = 0 - original
616 "strex %[tmp], %[result], %[storage]\n" // *(&storage) = result, tmp = store failed
617 "teq %[tmp], #0\n" // flags = tmp==0
618 "bne 1b\n" // if (!flags.equal) goto retry
619 BOOST_ATOMIC_DETAIL_ARM_ASM_END(%[tmp])
620 : [original] "=&r" (original), // %0
621 [result] "=&r" (result), // %1
622 [tmp] "=&l" (tmp), // %2
623 [storage] "+Q" (storage) // %3
625 : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC
627 gcc_arm_operations_base::fence_after(order);
631 static BOOST_FORCEINLINE storage_type negate(storage_type volatile& storage, memory_order order) BOOST_NOEXCEPT
633 gcc_arm_operations_base::fence_before(order);
635 storage_type original, result;
638 BOOST_ATOMIC_DETAIL_ARM_ASM_START(%[tmp])
640 "ldrex %[original], %[storage]\n" // original = *(&storage)
641 "rsb %[result], %[original], #0\n" // result = 0 - original
642 "strex %[tmp], %[result], %[storage]\n" // *(&storage) = result, tmp = store failed
643 "teq %[tmp], #0\n" // flags = tmp==0
644 "bne 1b\n" // if (!flags.equal) goto retry
645 BOOST_ATOMIC_DETAIL_ARM_ASM_END(%[tmp])
646 : [original] "=&r" (original), // %0
647 [result] "=&r" (result), // %1
648 [tmp] "=&l" (tmp), // %2
649 [storage] "+Q" (storage) // %3
651 : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC
653 gcc_arm_operations_base::fence_after(order);
657 static BOOST_FORCEINLINE storage_type add(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
659 gcc_arm_operations_base::fence_before(order);
661 storage_type original, result;
664 BOOST_ATOMIC_DETAIL_ARM_ASM_START(%[tmp])
666 "ldrex %[original], %[storage]\n" // original = *(&storage)
667 "add %[result], %[original], %[value]\n" // result = original + value
668 "strex %[tmp], %[result], %[storage]\n" // *(&storage) = result, tmp = store failed
669 "teq %[tmp], #0\n" // flags = tmp==0
670 "bne 1b\n" // if (!flags.equal) goto retry
671 BOOST_ATOMIC_DETAIL_ARM_ASM_END(%[tmp])
672 : [original] "=&r" (original), // %0
673 [result] "=&r" (result), // %1
674 [tmp] "=&l" (tmp), // %2
675 [storage] "+Q" (storage) // %3
676 : [value] "Ir" (v) // %4
677 : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC
679 gcc_arm_operations_base::fence_after(order);
683 static BOOST_FORCEINLINE storage_type sub(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
685 gcc_arm_operations_base::fence_before(order);
687 storage_type original, result;
690 BOOST_ATOMIC_DETAIL_ARM_ASM_START(%[tmp])
692 "ldrex %[original], %[storage]\n" // original = *(&storage)
693 "sub %[result], %[original], %[value]\n" // result = original - value
694 "strex %[tmp], %[result], %[storage]\n" // *(&storage) = result, tmp = store failed
695 "teq %[tmp], #0\n" // flags = tmp==0
696 "bne 1b\n" // if (!flags.equal) goto retry
697 BOOST_ATOMIC_DETAIL_ARM_ASM_END(%[tmp])
698 : [original] "=&r" (original), // %0
699 [result] "=&r" (result), // %1
700 [tmp] "=&l" (tmp), // %2
701 [storage] "+Q" (storage) // %3
702 : [value] "Ir" (v) // %4
703 : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC
705 gcc_arm_operations_base::fence_after(order);
709 static BOOST_FORCEINLINE storage_type bitwise_and(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
711 gcc_arm_operations_base::fence_before(order);
713 storage_type original, result;
716 BOOST_ATOMIC_DETAIL_ARM_ASM_START(%[tmp])
718 "ldrex %[original], %[storage]\n" // original = *(&storage)
719 "and %[result], %[original], %[value]\n" // result = original & value
720 "strex %[tmp], %[result], %[storage]\n" // *(&storage) = result, tmp = store failed
721 "teq %[tmp], #0\n" // flags = tmp==0
722 "bne 1b\n" // if (!flags.equal) goto retry
723 BOOST_ATOMIC_DETAIL_ARM_ASM_END(%[tmp])
724 : [original] "=&r" (original), // %0
725 [result] "=&r" (result), // %1
726 [tmp] "=&l" (tmp), // %2
727 [storage] "+Q" (storage) // %3
728 : [value] "Ir" (v) // %4
729 : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC
731 gcc_arm_operations_base::fence_after(order);
735 static BOOST_FORCEINLINE storage_type bitwise_or(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
737 gcc_arm_operations_base::fence_before(order);
739 storage_type original, result;
742 BOOST_ATOMIC_DETAIL_ARM_ASM_START(%[tmp])
744 "ldrex %[original], %[storage]\n" // original = *(&storage)
745 "orr %[result], %[original], %[value]\n" // result = original | value
746 "strex %[tmp], %[result], %[storage]\n" // *(&storage) = result, tmp = store failed
747 "teq %[tmp], #0\n" // flags = tmp==0
748 "bne 1b\n" // if (!flags.equal) goto retry
749 BOOST_ATOMIC_DETAIL_ARM_ASM_END(%[tmp])
750 : [original] "=&r" (original), // %0
751 [result] "=&r" (result), // %1
752 [tmp] "=&l" (tmp), // %2
753 [storage] "+Q" (storage) // %3
754 : [value] "Ir" (v) // %4
755 : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC
757 gcc_arm_operations_base::fence_after(order);
761 static BOOST_FORCEINLINE storage_type bitwise_xor(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
763 gcc_arm_operations_base::fence_before(order);
765 storage_type original, result;
768 BOOST_ATOMIC_DETAIL_ARM_ASM_START(%[tmp])
770 "ldrex %[original], %[storage]\n" // original = *(&storage)
771 "eor %[result], %[original], %[value]\n" // result = original ^ value
772 "strex %[tmp], %[result], %[storage]\n" // *(&storage) = result, tmp = store failed
773 "teq %[tmp], #0\n" // flags = tmp==0
774 "bne 1b\n" // if (!flags.equal) goto retry
775 BOOST_ATOMIC_DETAIL_ARM_ASM_END(%[tmp])
776 : [original] "=&r" (original), // %0
777 [result] "=&r" (result), // %1
778 [tmp] "=&l" (tmp), // %2
779 [storage] "+Q" (storage) // %3
780 : [value] "Ir" (v) // %4
781 : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC
783 gcc_arm_operations_base::fence_after(order);
787 static BOOST_FORCEINLINE storage_type fetch_complement(storage_type volatile& storage, memory_order order) BOOST_NOEXCEPT
789 gcc_arm_operations_base::fence_before(order);
791 storage_type original, result;
794 BOOST_ATOMIC_DETAIL_ARM_ASM_START(%[tmp])
796 "ldrex %[original], %[storage]\n" // original = *(&storage)
797 "mvn %[result], %[original]\n" // result = NOT original
798 "strex %[tmp], %[result], %[storage]\n" // *(&storage) = result, tmp = store failed
799 "teq %[tmp], #0\n" // flags = tmp==0
800 "bne 1b\n" // if (!flags.equal) goto retry
801 BOOST_ATOMIC_DETAIL_ARM_ASM_END(%[tmp])
802 : [original] "=&r" (original), // %0
803 [result] "=&r" (result), // %1
804 [tmp] "=&l" (tmp), // %2
805 [storage] "+Q" (storage) // %3
807 : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC
809 gcc_arm_operations_base::fence_after(order);
813 static BOOST_FORCEINLINE storage_type bitwise_complement(storage_type volatile& storage, memory_order order) BOOST_NOEXCEPT
815 gcc_arm_operations_base::fence_before(order);
817 storage_type original, result;
820 BOOST_ATOMIC_DETAIL_ARM_ASM_START(%[tmp])
822 "ldrex %[original], %[storage]\n" // original = *(&storage)
823 "mvn %[result], %[original]\n" // result = NOT original
824 "strex %[tmp], %[result], %[storage]\n" // *(&storage) = result, tmp = store failed
825 "teq %[tmp], #0\n" // flags = tmp==0
826 "bne 1b\n" // if (!flags.equal) goto retry
827 BOOST_ATOMIC_DETAIL_ARM_ASM_END(%[tmp])
828 : [original] "=&r" (original), // %0
829 [result] "=&r" (result), // %1
830 [tmp] "=&l" (tmp), // %2
831 [storage] "+Q" (storage) // %3
833 : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC
835 gcc_arm_operations_base::fence_after(order);
840 template< typename Base, bool Signed >
841 struct extra_operations< Base, 4u, Signed, true > :
842 public gcc_arm_extra_operations_common< gcc_arm_extra_operations< Base, 4u, Signed > >
846 #if defined(BOOST_ATOMIC_DETAIL_ARM_HAS_LDREXD_STREXD)
848 template< typename Base, bool Signed >
849 struct gcc_arm_extra_operations< Base, 8u, Signed > :
850 public generic_extra_operations< Base, 8u, Signed >
852 typedef generic_extra_operations< Base, 8u, Signed > base_type;
853 typedef typename base_type::storage_type storage_type;
855 static BOOST_FORCEINLINE storage_type fetch_negate(storage_type volatile& storage, memory_order order) BOOST_NOEXCEPT
857 gcc_arm_operations_base::fence_before(order);
858 storage_type original, result;
862 BOOST_ATOMIC_DETAIL_ARM_ASM_START(%0)
864 "ldrexd %1, %H1, [%3]\n" // original = *(&storage)
865 "mvn %2, %1\n" // result = NOT original
867 "adds %2, %2, #1\n" // result = result + 1
869 "strexd %0, %2, %H2, [%3]\n" // *(&storage) = result, tmp = store failed
870 "teq %0, #0\n" // flags = tmp==0
871 "bne 1b\n" // if (!flags.equal) goto retry
872 BOOST_ATOMIC_DETAIL_ARM_ASM_END(%0)
873 : BOOST_ATOMIC_DETAIL_ARM_ASM_TMPREG_CONSTRAINT(tmp), // %0
874 "=&r" (original), // %1
876 : "r" (&storage) // %3
877 : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC_COMMA "memory"
879 gcc_arm_operations_base::fence_after(order);
883 static BOOST_FORCEINLINE storage_type negate(storage_type volatile& storage, memory_order order) BOOST_NOEXCEPT
885 gcc_arm_operations_base::fence_before(order);
886 storage_type original, result;
890 BOOST_ATOMIC_DETAIL_ARM_ASM_START(%0)
892 "ldrexd %1, %H1, [%3]\n" // original = *(&storage)
893 "mvn %2, %1\n" // result = NOT original
895 "adds %2, %2, #1\n" // result = result + 1
897 "strexd %0, %2, %H2, [%3]\n" // *(&storage) = result, tmp = store failed
898 "teq %0, #0\n" // flags = tmp==0
899 "bne 1b\n" // if (!flags.equal) goto retry
900 BOOST_ATOMIC_DETAIL_ARM_ASM_END(%0)
901 : BOOST_ATOMIC_DETAIL_ARM_ASM_TMPREG_CONSTRAINT(tmp), // %0
902 "=&r" (original), // %1
904 : "r" (&storage) // %3
905 : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC_COMMA "memory"
907 gcc_arm_operations_base::fence_after(order);
911 static BOOST_FORCEINLINE storage_type add(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
913 gcc_arm_operations_base::fence_before(order);
914 storage_type original, result;
918 BOOST_ATOMIC_DETAIL_ARM_ASM_START(%0)
920 "ldrexd %1, %H1, [%3]\n" // original = *(&storage)
921 "adds %2, %1, %4\n" // result = original + value
922 "adc %H2, %H1, %H4\n"
923 "strexd %0, %2, %H2, [%3]\n" // *(&storage) = result, tmp = store failed
924 "teq %0, #0\n" // flags = tmp==0
925 "bne 1b\n" // if (!flags.equal) goto retry
926 BOOST_ATOMIC_DETAIL_ARM_ASM_END(%0)
927 : BOOST_ATOMIC_DETAIL_ARM_ASM_TMPREG_CONSTRAINT(tmp), // %0
928 "=&r" (original), // %1
930 : "r" (&storage), // %3
932 : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC_COMMA "memory"
934 gcc_arm_operations_base::fence_after(order);
938 static BOOST_FORCEINLINE storage_type sub(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
940 gcc_arm_operations_base::fence_before(order);
941 storage_type original, result;
945 BOOST_ATOMIC_DETAIL_ARM_ASM_START(%0)
947 "ldrexd %1, %H1, [%3]\n" // original = *(&storage)
948 "subs %2, %1, %4\n" // result = original - value
949 "sbc %H2, %H1, %H4\n"
950 "strexd %0, %2, %H2, [%3]\n" // *(&storage) = result, tmp = store failed
951 "teq %0, #0\n" // flags = tmp==0
952 "bne 1b\n" // if (!flags.equal) goto retry
953 BOOST_ATOMIC_DETAIL_ARM_ASM_END(%0)
954 : BOOST_ATOMIC_DETAIL_ARM_ASM_TMPREG_CONSTRAINT(tmp), // %0
955 "=&r" (original), // %1
957 : "r" (&storage), // %3
959 : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC_COMMA "memory"
961 gcc_arm_operations_base::fence_after(order);
965 static BOOST_FORCEINLINE storage_type bitwise_and(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
967 gcc_arm_operations_base::fence_before(order);
968 storage_type original, result;
972 BOOST_ATOMIC_DETAIL_ARM_ASM_START(%0)
974 "ldrexd %1, %H1, [%3]\n" // original = *(&storage)
975 "and %2, %1, %4\n" // result = original & value
976 "and %H2, %H1, %H4\n"
977 "strexd %0, %2, %H2, [%3]\n" // *(&storage) = result, tmp = store failed
978 "teq %0, #0\n" // flags = tmp==0
979 "bne 1b\n" // if (!flags.equal) goto retry
980 BOOST_ATOMIC_DETAIL_ARM_ASM_END(%0)
981 : BOOST_ATOMIC_DETAIL_ARM_ASM_TMPREG_CONSTRAINT(tmp), // %0
982 "=&r" (original), // %1
984 : "r" (&storage), // %3
986 : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC_COMMA "memory"
988 gcc_arm_operations_base::fence_after(order);
992 static BOOST_FORCEINLINE storage_type bitwise_or(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
994 gcc_arm_operations_base::fence_before(order);
995 storage_type original, result;
999 BOOST_ATOMIC_DETAIL_ARM_ASM_START(%0)
1001 "ldrexd %1, %H1, [%3]\n" // original = *(&storage)
1002 "orr %2, %1, %4\n" // result = original | value
1003 "orr %H2, %H1, %H4\n"
1004 "strexd %0, %2, %H2, [%3]\n" // *(&storage) = result, tmp = store failed
1005 "teq %0, #0\n" // flags = tmp==0
1006 "bne 1b\n" // if (!flags.equal) goto retry
1007 BOOST_ATOMIC_DETAIL_ARM_ASM_END(%0)
1008 : BOOST_ATOMIC_DETAIL_ARM_ASM_TMPREG_CONSTRAINT(tmp), // %0
1009 "=&r" (original), // %1
1010 "=&r" (result) // %2
1011 : "r" (&storage), // %3
1013 : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC_COMMA "memory"
1015 gcc_arm_operations_base::fence_after(order);
1019 static BOOST_FORCEINLINE storage_type bitwise_xor(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
1021 gcc_arm_operations_base::fence_before(order);
1022 storage_type original, result;
1024 __asm__ __volatile__
1026 BOOST_ATOMIC_DETAIL_ARM_ASM_START(%0)
1028 "ldrexd %1, %H1, [%3]\n" // original = *(&storage)
1029 "eor %2, %1, %4\n" // result = original ^ value
1030 "eor %H2, %H1, %H4\n"
1031 "strexd %0, %2, %H2, [%3]\n" // *(&storage) = result, tmp = store failed
1032 "teq %0, #0\n" // flags = tmp==0
1033 "bne 1b\n" // if (!flags.equal) goto retry
1034 BOOST_ATOMIC_DETAIL_ARM_ASM_END(%0)
1035 : BOOST_ATOMIC_DETAIL_ARM_ASM_TMPREG_CONSTRAINT(tmp), // %0
1036 "=&r" (original), // %1
1037 "=&r" (result) // %2
1038 : "r" (&storage), // %3
1040 : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC_COMMA "memory"
1042 gcc_arm_operations_base::fence_after(order);
1046 static BOOST_FORCEINLINE storage_type fetch_complement(storage_type volatile& storage, memory_order order) BOOST_NOEXCEPT
1048 gcc_arm_operations_base::fence_before(order);
1049 storage_type original, result;
1051 __asm__ __volatile__
1053 BOOST_ATOMIC_DETAIL_ARM_ASM_START(%0)
1055 "ldrexd %1, %H1, [%3]\n" // original = *(&storage)
1056 "mvn %2, %1\n" // result = NOT original
1058 "strexd %0, %2, %H2, [%3]\n" // *(&storage) = result, tmp = store failed
1059 "teq %0, #0\n" // flags = tmp==0
1060 "bne 1b\n" // if (!flags.equal) goto retry
1061 BOOST_ATOMIC_DETAIL_ARM_ASM_END(%0)
1062 : BOOST_ATOMIC_DETAIL_ARM_ASM_TMPREG_CONSTRAINT(tmp), // %0
1063 "=&r" (original), // %1
1064 "=&r" (result) // %2
1065 : "r" (&storage) // %3
1066 : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC_COMMA "memory"
1068 gcc_arm_operations_base::fence_after(order);
1072 static BOOST_FORCEINLINE storage_type bitwise_complement(storage_type volatile& storage, memory_order order) BOOST_NOEXCEPT
1074 gcc_arm_operations_base::fence_before(order);
1075 storage_type original, result;
1077 __asm__ __volatile__
1079 BOOST_ATOMIC_DETAIL_ARM_ASM_START(%0)
1081 "ldrexd %1, %H1, [%3]\n" // original = *(&storage)
1082 "mvn %2, %1\n" // result = NOT original
1084 "strexd %0, %2, %H2, [%3]\n" // *(&storage) = result, tmp = store failed
1085 "teq %0, #0\n" // flags = tmp==0
1086 "bne 1b\n" // if (!flags.equal) goto retry
1087 BOOST_ATOMIC_DETAIL_ARM_ASM_END(%0)
1088 : BOOST_ATOMIC_DETAIL_ARM_ASM_TMPREG_CONSTRAINT(tmp), // %0
1089 "=&r" (original), // %1
1090 "=&r" (result) // %2
1091 : "r" (&storage) // %3
1092 : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC_COMMA "memory"
1094 gcc_arm_operations_base::fence_after(order);
1099 template< typename Base, bool Signed >
1100 struct extra_operations< Base, 8u, Signed, true > :
1101 public gcc_arm_extra_operations_common< gcc_arm_extra_operations< Base, 8u, Signed > >
1105 #endif // defined(BOOST_ATOMIC_DETAIL_ARM_HAS_LDREXD_STREXD)
1107 } // namespace detail
1108 } // namespace atomics
1109 } // namespace boost
1111 #endif // BOOST_ATOMIC_DETAIL_EXTRA_OPS_GCC_ARM_HPP_INCLUDED_