File indexing completed on 2025-01-30 09:33:52
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016 #ifndef BOOST_ATOMIC_DETAIL_CORE_ARCH_OPS_GCC_ARM_HPP_INCLUDED_
0017 #define BOOST_ATOMIC_DETAIL_CORE_ARCH_OPS_GCC_ARM_HPP_INCLUDED_
0018
0019 #include <cstddef>
0020 #include <boost/cstdint.hpp>
0021 #include <boost/memory_order.hpp>
0022 #include <boost/atomic/detail/config.hpp>
0023 #include <boost/atomic/detail/storage_traits.hpp>
0024 #include <boost/atomic/detail/integral_conversions.hpp>
0025 #include <boost/atomic/detail/core_arch_operations_fwd.hpp>
0026 #include <boost/atomic/detail/ops_gcc_arm_common.hpp>
0027 #include <boost/atomic/detail/gcc_arm_asm_common.hpp>
0028 #include <boost/atomic/detail/capabilities.hpp>
0029 #include <boost/atomic/detail/header.hpp>
0030
0031 #ifdef BOOST_HAS_PRAGMA_ONCE
0032 #pragma once
0033 #endif
0034
0035 namespace boost {
0036 namespace atomics {
0037 namespace detail {
0038
0039
0040
0041
0042
0043
0044
0045
0046
0047
0048
0049
0050
0051
0052
0053
0054
0055
0056
0057
0058
0059 template< bool Signed, bool Interprocess >
0060 struct core_arch_operations< 4u, Signed, Interprocess > :
0061 public core_arch_operations_gcc_arm_base
0062 {
0063 typedef typename storage_traits< 4u >::type storage_type;
0064
0065 static BOOST_CONSTEXPR_OR_CONST std::size_t storage_size = 4u;
0066 static BOOST_CONSTEXPR_OR_CONST std::size_t storage_alignment = 4u;
0067 static BOOST_CONSTEXPR_OR_CONST bool is_signed = Signed;
0068 static BOOST_CONSTEXPR_OR_CONST bool is_interprocess = Interprocess;
0069
0070 static BOOST_FORCEINLINE void store(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
0071 {
0072 fence_before(order);
0073 storage = v;
0074 fence_after_store(order);
0075 }
0076
0077 static BOOST_FORCEINLINE storage_type load(storage_type const volatile& storage, memory_order order) BOOST_NOEXCEPT
0078 {
0079 storage_type v = storage;
0080 fence_after(order);
0081 return v;
0082 }
0083
0084 static BOOST_FORCEINLINE storage_type exchange(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
0085 {
0086 fence_before(order);
0087 storage_type original;
0088 uint32_t tmp;
0089 __asm__ __volatile__
0090 (
0091 BOOST_ATOMIC_DETAIL_ARM_ASM_START(%[tmp])
0092 "1:\n\t"
0093 "ldrex %[original], %[storage]\n\t"
0094 "strex %[tmp], %[value], %[storage]\n\t"
0095 "teq %[tmp], #0\n\t"
0096 "bne 1b\n\t"
0097 BOOST_ATOMIC_DETAIL_ARM_ASM_END(%[tmp])
0098 : [tmp] "=&l" (tmp), [original] "=&r" (original), [storage] "+Q" (storage)
0099 : [value] "r" (v)
0100 : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC
0101 );
0102 fence_after(order);
0103 return original;
0104 }
0105
0106 static BOOST_FORCEINLINE bool compare_exchange_weak(
0107 storage_type volatile& storage, storage_type& expected, storage_type desired, memory_order success_order, memory_order failure_order) BOOST_NOEXCEPT
0108 {
0109 fence_before(success_order);
0110 bool success = false;
0111 #if !defined(BOOST_ATOMIC_DETAIL_ARM_ASM_TMPREG_UNUSED)
0112 uint32_t tmp;
0113 #endif
0114 storage_type original;
0115 __asm__ __volatile__
0116 (
0117 BOOST_ATOMIC_DETAIL_ARM_ASM_START(%[tmp])
0118 "ldrex %[original], %[storage]\n\t"
0119 "cmp %[original], %[expected]\n\t"
0120 "itt eq\n\t"
0121 "strexeq %[success], %[desired], %[storage]\n\t"
0122 "eoreq %[success], %[success], #1\n\t"
0123 BOOST_ATOMIC_DETAIL_ARM_ASM_END(%[tmp])
0124 : [original] "=&r" (original),
0125 [success] "+r" (success),
0126 #if !defined(BOOST_ATOMIC_DETAIL_ARM_ASM_TMPREG_UNUSED)
0127 [tmp] "=&l" (tmp),
0128 #endif
0129 [storage] "+Q" (storage)
0130 : [expected] "Ir" (expected),
0131 [desired] "r" (desired)
0132 : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC
0133 );
0134 if (success)
0135 fence_after(success_order);
0136 else
0137 fence_after(failure_order);
0138 expected = original;
0139 return success;
0140 }
0141
0142 static BOOST_FORCEINLINE bool compare_exchange_strong(
0143 storage_type volatile& storage, storage_type& expected, storage_type desired, memory_order success_order, memory_order failure_order) BOOST_NOEXCEPT
0144 {
0145 fence_before(success_order);
0146 bool success = false;
0147 #if !defined(BOOST_ATOMIC_DETAIL_ARM_ASM_TMPREG_UNUSED)
0148 uint32_t tmp;
0149 #endif
0150 storage_type original;
0151 __asm__ __volatile__
0152 (
0153 BOOST_ATOMIC_DETAIL_ARM_ASM_START(%[tmp])
0154 "1:\n\t"
0155 "ldrex %[original], %[storage]\n\t"
0156 "cmp %[original], %[expected]\n\t"
0157 "bne 2f\n\t"
0158 "strex %[success], %[desired], %[storage]\n\t"
0159 "eors %[success], %[success], #1\n\t"
0160 "beq 1b\n\t"
0161 "2:\n\t"
0162 BOOST_ATOMIC_DETAIL_ARM_ASM_END(%[tmp])
0163 : [original] "=&r" (original),
0164 [success] "+r" (success),
0165 #if !defined(BOOST_ATOMIC_DETAIL_ARM_ASM_TMPREG_UNUSED)
0166 [tmp] "=&l" (tmp),
0167 #endif
0168 [storage] "+Q" (storage)
0169 : [expected] "Ir" (expected),
0170 [desired] "r" (desired)
0171 : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC
0172 );
0173 if (success)
0174 fence_after(success_order);
0175 else
0176 fence_after(failure_order);
0177 expected = original;
0178 return success;
0179 }
0180
0181 static BOOST_FORCEINLINE storage_type fetch_add(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
0182 {
0183 fence_before(order);
0184 uint32_t tmp;
0185 storage_type original, result;
0186 __asm__ __volatile__
0187 (
0188 BOOST_ATOMIC_DETAIL_ARM_ASM_START(%[tmp])
0189 "1:\n\t"
0190 "ldrex %[original], %[storage]\n\t"
0191 "add %[result], %[original], %[value]\n\t"
0192 "strex %[tmp], %[result], %[storage]\n\t"
0193 "teq %[tmp], #0\n\t"
0194 "bne 1b\n\t"
0195 BOOST_ATOMIC_DETAIL_ARM_ASM_END(%[tmp])
0196 : [original] "=&r" (original),
0197 [result] "=&r" (result),
0198 [tmp] "=&l" (tmp),
0199 [storage] "+Q" (storage)
0200 : [value] "Ir" (v)
0201 : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC
0202 );
0203 fence_after(order);
0204 return original;
0205 }
0206
0207 static BOOST_FORCEINLINE storage_type fetch_sub(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
0208 {
0209 fence_before(order);
0210 uint32_t tmp;
0211 storage_type original, result;
0212 __asm__ __volatile__
0213 (
0214 BOOST_ATOMIC_DETAIL_ARM_ASM_START(%[tmp])
0215 "1:\n\t"
0216 "ldrex %[original], %[storage]\n\t"
0217 "sub %[result], %[original], %[value]\n\t"
0218 "strex %[tmp], %[result], %[storage]\n\t"
0219 "teq %[tmp], #0\n\t"
0220 "bne 1b\n\t"
0221 BOOST_ATOMIC_DETAIL_ARM_ASM_END(%[tmp])
0222 : [original] "=&r" (original),
0223 [result] "=&r" (result),
0224 [tmp] "=&l" (tmp),
0225 [storage] "+Q" (storage)
0226 : [value] "Ir" (v)
0227 : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC
0228 );
0229 fence_after(order);
0230 return original;
0231 }
0232
0233 static BOOST_FORCEINLINE storage_type fetch_and(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
0234 {
0235 fence_before(order);
0236 uint32_t tmp;
0237 storage_type original, result;
0238 __asm__ __volatile__
0239 (
0240 BOOST_ATOMIC_DETAIL_ARM_ASM_START(%[tmp])
0241 "1:\n\t"
0242 "ldrex %[original], %[storage]\n\t"
0243 "and %[result], %[original], %[value]\n\t"
0244 "strex %[tmp], %[result], %[storage]\n\t"
0245 "teq %[tmp], #0\n\t"
0246 "bne 1b\n\t"
0247 BOOST_ATOMIC_DETAIL_ARM_ASM_END(%[tmp])
0248 : [original] "=&r" (original),
0249 [result] "=&r" (result),
0250 [tmp] "=&l" (tmp),
0251 [storage] "+Q" (storage)
0252 : [value] "Ir" (v)
0253 : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC
0254 );
0255 fence_after(order);
0256 return original;
0257 }
0258
0259 static BOOST_FORCEINLINE storage_type fetch_or(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
0260 {
0261 fence_before(order);
0262 uint32_t tmp;
0263 storage_type original, result;
0264 __asm__ __volatile__
0265 (
0266 BOOST_ATOMIC_DETAIL_ARM_ASM_START(%[tmp])
0267 "1:\n\t"
0268 "ldrex %[original], %[storage]\n\t"
0269 "orr %[result], %[original], %[value]\n\t"
0270 "strex %[tmp], %[result], %[storage]\n\t"
0271 "teq %[tmp], #0\n\t"
0272 "bne 1b\n\t"
0273 BOOST_ATOMIC_DETAIL_ARM_ASM_END(%[tmp])
0274 : [original] "=&r" (original),
0275 [result] "=&r" (result),
0276 [tmp] "=&l" (tmp),
0277 [storage] "+Q" (storage)
0278 : [value] "Ir" (v)
0279 : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC
0280 );
0281 fence_after(order);
0282 return original;
0283 }
0284
0285 static BOOST_FORCEINLINE storage_type fetch_xor(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
0286 {
0287 fence_before(order);
0288 uint32_t tmp;
0289 storage_type original, result;
0290 __asm__ __volatile__
0291 (
0292 BOOST_ATOMIC_DETAIL_ARM_ASM_START(%[tmp])
0293 "1:\n\t"
0294 "ldrex %[original], %[storage]\n\t"
0295 "eor %[result], %[original], %[value]\n\t"
0296 "strex %[tmp], %[result], %[storage]\n\t"
0297 "teq %[tmp], #0\n\t"
0298 "bne 1b\n\t"
0299 BOOST_ATOMIC_DETAIL_ARM_ASM_END(%[tmp])
0300 : [original] "=&r" (original),
0301 [result] "=&r" (result),
0302 [tmp] "=&l" (tmp),
0303 [storage] "+Q" (storage)
0304 : [value] "Ir" (v)
0305 : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC
0306 );
0307 fence_after(order);
0308 return original;
0309 }
0310
0311 static BOOST_FORCEINLINE bool test_and_set(storage_type volatile& storage, memory_order order) BOOST_NOEXCEPT
0312 {
0313 return !!exchange(storage, (storage_type)1, order);
0314 }
0315
0316 static BOOST_FORCEINLINE void clear(storage_type volatile& storage, memory_order order) BOOST_NOEXCEPT
0317 {
0318 store(storage, (storage_type)0, order);
0319 }
0320 };
0321
0322 #if defined(BOOST_ATOMIC_DETAIL_ARM_HAS_LDREXB_STREXB)
0323
0324 template< bool Signed, bool Interprocess >
0325 struct core_arch_operations< 1u, Signed, Interprocess > :
0326 public core_arch_operations_gcc_arm_base
0327 {
0328 typedef typename storage_traits< 1u >::type storage_type;
0329 typedef typename storage_traits< 4u >::type extended_storage_type;
0330
0331 static BOOST_CONSTEXPR_OR_CONST std::size_t storage_size = 1u;
0332 static BOOST_CONSTEXPR_OR_CONST std::size_t storage_alignment = 1u;
0333 static BOOST_CONSTEXPR_OR_CONST bool is_signed = Signed;
0334 static BOOST_CONSTEXPR_OR_CONST bool is_interprocess = Interprocess;
0335
0336 static BOOST_FORCEINLINE void store(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
0337 {
0338 fence_before(order);
0339 storage = v;
0340 fence_after_store(order);
0341 }
0342
0343 static BOOST_FORCEINLINE storage_type load(storage_type const volatile& storage, memory_order order) BOOST_NOEXCEPT
0344 {
0345 storage_type v = storage;
0346 fence_after(order);
0347 return v;
0348 }
0349
0350 static BOOST_FORCEINLINE storage_type exchange(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
0351 {
0352 fence_before(order);
0353 extended_storage_type original;
0354 uint32_t tmp;
0355 __asm__ __volatile__
0356 (
0357 BOOST_ATOMIC_DETAIL_ARM_ASM_START(%[tmp])
0358 "1:\n\t"
0359 "ldrexb %[original], %[storage]\n\t"
0360 "strexb %[tmp], %[value], %[storage]\n\t"
0361 "teq %[tmp], #0\n\t"
0362 "bne 1b\n\t"
0363 BOOST_ATOMIC_DETAIL_ARM_ASM_END(%[tmp])
0364 : [tmp] "=&l" (tmp), [original] "=&r" (original), [storage] "+Q" (storage)
0365 : [value] "r" (v)
0366 : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC
0367 );
0368 fence_after(order);
0369 return static_cast< storage_type >(original);
0370 }
0371
0372 static BOOST_FORCEINLINE bool compare_exchange_weak(
0373 storage_type volatile& storage, storage_type& expected, storage_type desired, memory_order success_order, memory_order failure_order) BOOST_NOEXCEPT
0374 {
0375 fence_before(success_order);
0376 bool success = false;
0377 #if !defined(BOOST_ATOMIC_DETAIL_ARM_ASM_TMPREG_UNUSED)
0378 uint32_t tmp;
0379 #endif
0380 extended_storage_type original;
0381 __asm__ __volatile__
0382 (
0383 BOOST_ATOMIC_DETAIL_ARM_ASM_START(%[tmp])
0384 "ldrexb %[original], %[storage]\n\t"
0385 "cmp %[original], %[expected]\n\t"
0386 "itt eq\n\t"
0387 "strexbeq %[success], %[desired], %[storage]\n\t"
0388 "eoreq %[success], %[success], #1\n\t"
0389 BOOST_ATOMIC_DETAIL_ARM_ASM_END(%[tmp])
0390 : [original] "=&r" (original),
0391 [success] "+r" (success),
0392 #if !defined(BOOST_ATOMIC_DETAIL_ARM_ASM_TMPREG_UNUSED)
0393 [tmp] "=&l" (tmp),
0394 #endif
0395 [storage] "+Q" (storage)
0396 : [expected] "Ir" (atomics::detail::zero_extend< extended_storage_type >(expected)),
0397 [desired] "r" (desired)
0398 : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC
0399 );
0400 if (success)
0401 fence_after(success_order);
0402 else
0403 fence_after(failure_order);
0404 expected = static_cast< storage_type >(original);
0405 return success;
0406 }
0407
0408 static BOOST_FORCEINLINE bool compare_exchange_strong(
0409 storage_type volatile& storage, storage_type& expected, storage_type desired, memory_order success_order, memory_order failure_order) BOOST_NOEXCEPT
0410 {
0411 fence_before(success_order);
0412 bool success = false;
0413 #if !defined(BOOST_ATOMIC_DETAIL_ARM_ASM_TMPREG_UNUSED)
0414 uint32_t tmp;
0415 #endif
0416 extended_storage_type original;
0417 __asm__ __volatile__
0418 (
0419 BOOST_ATOMIC_DETAIL_ARM_ASM_START(%[tmp])
0420 "1:\n\t"
0421 "ldrexb %[original], %[storage]\n\t"
0422 "cmp %[original], %[expected]\n\t"
0423 "bne 2f\n\t"
0424 "strexb %[success], %[desired], %[storage]\n\t"
0425 "eors %[success], %[success], #1\n\t"
0426 "beq 1b\n\t"
0427 "2:\n\t"
0428 BOOST_ATOMIC_DETAIL_ARM_ASM_END(%[tmp])
0429 : [original] "=&r" (original),
0430 [success] "+r" (success),
0431 #if !defined(BOOST_ATOMIC_DETAIL_ARM_ASM_TMPREG_UNUSED)
0432 [tmp] "=&l" (tmp),
0433 #endif
0434 [storage] "+Q" (storage)
0435 : [expected] "Ir" (atomics::detail::zero_extend< extended_storage_type >(expected)),
0436 [desired] "r" (desired)
0437 : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC
0438 );
0439 if (success)
0440 fence_after(success_order);
0441 else
0442 fence_after(failure_order);
0443 expected = static_cast< storage_type >(original);
0444 return success;
0445 }
0446
0447 static BOOST_FORCEINLINE storage_type fetch_add(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
0448 {
0449 fence_before(order);
0450 uint32_t tmp;
0451 extended_storage_type original, result;
0452 __asm__ __volatile__
0453 (
0454 BOOST_ATOMIC_DETAIL_ARM_ASM_START(%[tmp])
0455 "1:\n\t"
0456 "ldrexb %[original], %[storage]\n\t"
0457 "add %[result], %[original], %[value]\n\t"
0458 "strexb %[tmp], %[result], %[storage]\n\t"
0459 "teq %[tmp], #0\n\t"
0460 "bne 1b\n\t"
0461 BOOST_ATOMIC_DETAIL_ARM_ASM_END(%[tmp])
0462 : [original] "=&r" (original),
0463 [result] "=&r" (result),
0464 [tmp] "=&l" (tmp),
0465 [storage] "+Q" (storage)
0466 : [value] "Ir" (v)
0467 : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC
0468 );
0469 fence_after(order);
0470 return static_cast< storage_type >(original);
0471 }
0472
0473 static BOOST_FORCEINLINE storage_type fetch_sub(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
0474 {
0475 fence_before(order);
0476 uint32_t tmp;
0477 extended_storage_type original, result;
0478 __asm__ __volatile__
0479 (
0480 BOOST_ATOMIC_DETAIL_ARM_ASM_START(%[tmp])
0481 "1:\n\t"
0482 "ldrexb %[original], %[storage]\n\t"
0483 "sub %[result], %[original], %[value]\n\t"
0484 "strexb %[tmp], %[result], %[storage]\n\t"
0485 "teq %[tmp], #0\n\t"
0486 "bne 1b\n\t"
0487 BOOST_ATOMIC_DETAIL_ARM_ASM_END(%[tmp])
0488 : [original] "=&r" (original),
0489 [result] "=&r" (result),
0490 [tmp] "=&l" (tmp),
0491 [storage] "+Q" (storage)
0492 : [value] "Ir" (v)
0493 : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC
0494 );
0495 fence_after(order);
0496 return static_cast< storage_type >(original);
0497 }
0498
0499 static BOOST_FORCEINLINE storage_type fetch_and(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
0500 {
0501 fence_before(order);
0502 uint32_t tmp;
0503 extended_storage_type original, result;
0504 __asm__ __volatile__
0505 (
0506 BOOST_ATOMIC_DETAIL_ARM_ASM_START(%[tmp])
0507 "1:\n\t"
0508 "ldrexb %[original], %[storage]\n\t"
0509 "and %[result], %[original], %[value]\n\t"
0510 "strexb %[tmp], %[result], %[storage]\n\t"
0511 "teq %[tmp], #0\n\t"
0512 "bne 1b\n\t"
0513 BOOST_ATOMIC_DETAIL_ARM_ASM_END(%[tmp])
0514 : [original] "=&r" (original),
0515 [result] "=&r" (result),
0516 [tmp] "=&l" (tmp),
0517 [storage] "+Q" (storage)
0518 : [value] "Ir" (v)
0519 : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC
0520 );
0521 fence_after(order);
0522 return static_cast< storage_type >(original);
0523 }
0524
0525 static BOOST_FORCEINLINE storage_type fetch_or(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
0526 {
0527 fence_before(order);
0528 uint32_t tmp;
0529 extended_storage_type original, result;
0530 __asm__ __volatile__
0531 (
0532 BOOST_ATOMIC_DETAIL_ARM_ASM_START(%[tmp])
0533 "1:\n\t"
0534 "ldrexb %[original], %[storage]\n\t"
0535 "orr %[result], %[original], %[value]\n\t"
0536 "strexb %[tmp], %[result], %[storage]\n\t"
0537 "teq %[tmp], #0\n\t"
0538 "bne 1b\n\t"
0539 BOOST_ATOMIC_DETAIL_ARM_ASM_END(%[tmp])
0540 : [original] "=&r" (original),
0541 [result] "=&r" (result),
0542 [tmp] "=&l" (tmp),
0543 [storage] "+Q" (storage)
0544 : [value] "Ir" (v)
0545 : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC
0546 );
0547 fence_after(order);
0548 return static_cast< storage_type >(original);
0549 }
0550
0551 static BOOST_FORCEINLINE storage_type fetch_xor(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
0552 {
0553 fence_before(order);
0554 uint32_t tmp;
0555 extended_storage_type original, result;
0556 __asm__ __volatile__
0557 (
0558 BOOST_ATOMIC_DETAIL_ARM_ASM_START(%[tmp])
0559 "1:\n\t"
0560 "ldrexb %[original], %[storage]\n\t"
0561 "eor %[result], %[original], %[value]\n\t"
0562 "strexb %[tmp], %[result], %[storage]\n\t"
0563 "teq %[tmp], #0\n\t"
0564 "bne 1b\n\t"
0565 BOOST_ATOMIC_DETAIL_ARM_ASM_END(%[tmp])
0566 : [original] "=&r" (original),
0567 [result] "=&r" (result),
0568 [tmp] "=&l" (tmp),
0569 [storage] "+Q" (storage)
0570 : [value] "Ir" (v)
0571 : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC
0572 );
0573 fence_after(order);
0574 return static_cast< storage_type >(original);
0575 }
0576
0577 static BOOST_FORCEINLINE bool test_and_set(storage_type volatile& storage, memory_order order) BOOST_NOEXCEPT
0578 {
0579 return !!exchange(storage, (storage_type)1, order);
0580 }
0581
0582 static BOOST_FORCEINLINE void clear(storage_type volatile& storage, memory_order order) BOOST_NOEXCEPT
0583 {
0584 store(storage, (storage_type)0, order);
0585 }
0586 };
0587
0588 #else
0589
0590 template< bool Interprocess >
0591 struct core_arch_operations< 1u, false, Interprocess > :
0592 public core_arch_operations< 4u, false, Interprocess >
0593 {
0594 typedef core_arch_operations< 4u, false, Interprocess > base_type;
0595 typedef typename base_type::storage_type storage_type;
0596
0597 static BOOST_FORCEINLINE storage_type fetch_add(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
0598 {
0599 base_type::fence_before(order);
0600 uint32_t tmp;
0601 storage_type original, result;
0602 __asm__ __volatile__
0603 (
0604 BOOST_ATOMIC_DETAIL_ARM_ASM_START(%[tmp])
0605 "1:\n\t"
0606 "ldrex %[original], %[storage]\n\t"
0607 "add %[result], %[original], %[value]\n\t"
0608 "uxtb %[result], %[result]\n\t"
0609 "strex %[tmp], %[result], %[storage]\n\t"
0610 "teq %[tmp], #0\n\t"
0611 "bne 1b\n\t"
0612 BOOST_ATOMIC_DETAIL_ARM_ASM_END(%[tmp])
0613 : [original] "=&r" (original),
0614 [result] "=&r" (result),
0615 [tmp] "=&l" (tmp),
0616 [storage] "+Q" (storage)
0617 : [value] "Ir" (v)
0618 : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC
0619 );
0620 base_type::fence_after(order);
0621 return original;
0622 }
0623
0624 static BOOST_FORCEINLINE storage_type fetch_sub(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
0625 {
0626 base_type::fence_before(order);
0627 uint32_t tmp;
0628 storage_type original, result;
0629 __asm__ __volatile__
0630 (
0631 BOOST_ATOMIC_DETAIL_ARM_ASM_START(%[tmp])
0632 "1:\n\t"
0633 "ldrex %[original], %[storage]\n\t"
0634 "sub %[result], %[original], %[value]\n\t"
0635 "uxtb %[result], %[result]\n\t"
0636 "strex %[tmp], %[result], %[storage]\n\t"
0637 "teq %[tmp], #0\n\t"
0638 "bne 1b\n\t"
0639 BOOST_ATOMIC_DETAIL_ARM_ASM_END(%[tmp])
0640 : [original] "=&r" (original),
0641 [result] "=&r" (result),
0642 [tmp] "=&l" (tmp),
0643 [storage] "+Q" (storage)
0644 : [value] "Ir" (v)
0645 : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC
0646 );
0647 base_type::fence_after(order);
0648 return original;
0649 }
0650 };
0651
0652 template< bool Interprocess >
0653 struct core_arch_operations< 1u, true, Interprocess > :
0654 public core_arch_operations< 4u, true, Interprocess >
0655 {
0656 typedef core_arch_operations< 4u, true, Interprocess > base_type;
0657 typedef typename base_type::storage_type storage_type;
0658
0659 static BOOST_FORCEINLINE storage_type fetch_add(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
0660 {
0661 base_type::fence_before(order);
0662 uint32_t tmp;
0663 storage_type original, result;
0664 __asm__ __volatile__
0665 (
0666 BOOST_ATOMIC_DETAIL_ARM_ASM_START(%[tmp])
0667 "1:\n\t"
0668 "ldrex %[original], %[storage]\n\t"
0669 "add %[result], %[original], %[value]\n\t"
0670 "sxtb %[result], %[result]\n\t"
0671 "strex %[tmp], %[result], %[storage]\n\t"
0672 "teq %[tmp], #0\n\t"
0673 "bne 1b\n\t"
0674 BOOST_ATOMIC_DETAIL_ARM_ASM_END(%[tmp])
0675 : [original] "=&r" (original),
0676 [result] "=&r" (result),
0677 [tmp] "=&l" (tmp),
0678 [storage] "+Q" (storage)
0679 : [value] "Ir" (v)
0680 : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC
0681 );
0682 base_type::fence_after(order);
0683 return original;
0684 }
0685
0686 static BOOST_FORCEINLINE storage_type fetch_sub(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
0687 {
0688 base_type::fence_before(order);
0689 uint32_t tmp;
0690 storage_type original, result;
0691 __asm__ __volatile__
0692 (
0693 BOOST_ATOMIC_DETAIL_ARM_ASM_START(%[tmp])
0694 "1:\n\t"
0695 "ldrex %[original], %[storage]\n\t"
0696 "sub %[result], %[original], %[value]\n\t"
0697 "sxtb %[result], %[result]\n\t"
0698 "strex %[tmp], %[result], %[storage]\n\t"
0699 "teq %[tmp], #0\n\t"
0700 "bne 1b\n\t"
0701 BOOST_ATOMIC_DETAIL_ARM_ASM_END(%[tmp])
0702 : [original] "=&r" (original),
0703 [result] "=&r" (result),
0704 [tmp] "=&l" (tmp),
0705 [storage] "+Q" (storage)
0706 : [value] "Ir" (v)
0707 : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC
0708 );
0709 base_type::fence_after(order);
0710 return original;
0711 }
0712 };
0713
0714 #endif
0715
0716 #if defined(BOOST_ATOMIC_DETAIL_ARM_HAS_LDREXH_STREXH)
0717
0718 template< bool Signed, bool Interprocess >
0719 struct core_arch_operations< 2u, Signed, Interprocess > :
0720 public core_arch_operations_gcc_arm_base
0721 {
0722 typedef typename storage_traits< 2u >::type storage_type;
0723 typedef typename storage_traits< 4u >::type extended_storage_type;
0724
0725 static BOOST_CONSTEXPR_OR_CONST std::size_t storage_size = 2u;
0726 static BOOST_CONSTEXPR_OR_CONST std::size_t storage_alignment = 2u;
0727 static BOOST_CONSTEXPR_OR_CONST bool is_signed = Signed;
0728 static BOOST_CONSTEXPR_OR_CONST bool is_interprocess = Interprocess;
0729
0730 static BOOST_FORCEINLINE void store(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
0731 {
0732 fence_before(order);
0733 storage = v;
0734 fence_after_store(order);
0735 }
0736
0737 static BOOST_FORCEINLINE storage_type load(storage_type const volatile& storage, memory_order order) BOOST_NOEXCEPT
0738 {
0739 storage_type v = storage;
0740 fence_after(order);
0741 return v;
0742 }
0743
0744 static BOOST_FORCEINLINE storage_type exchange(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
0745 {
0746 fence_before(order);
0747 extended_storage_type original;
0748 uint32_t tmp;
0749 __asm__ __volatile__
0750 (
0751 BOOST_ATOMIC_DETAIL_ARM_ASM_START(%[tmp])
0752 "1:\n\t"
0753 "ldrexh %[original], %[storage]\n\t"
0754 "strexh %[tmp], %[value], %[storage]\n\t"
0755 "teq %[tmp], #0\n\t"
0756 "bne 1b\n\t"
0757 BOOST_ATOMIC_DETAIL_ARM_ASM_END(%[tmp])
0758 : [tmp] "=&l" (tmp), [original] "=&r" (original), [storage] "+Q" (storage)
0759 : [value] "r" (v)
0760 : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC
0761 );
0762 fence_after(order);
0763 return static_cast< storage_type >(original);
0764 }
0765
0766 static BOOST_FORCEINLINE bool compare_exchange_weak(
0767 storage_type volatile& storage, storage_type& expected, storage_type desired, memory_order success_order, memory_order failure_order) BOOST_NOEXCEPT
0768 {
0769 fence_before(success_order);
0770 bool success = false;
0771 #if !defined(BOOST_ATOMIC_DETAIL_ARM_ASM_TMPREG_UNUSED)
0772 uint32_t tmp;
0773 #endif
0774 extended_storage_type original;
0775 __asm__ __volatile__
0776 (
0777 BOOST_ATOMIC_DETAIL_ARM_ASM_START(%[tmp])
0778 "ldrexh %[original], %[storage]\n\t"
0779 "cmp %[original], %[expected]\n\t"
0780 "itt eq\n\t"
0781 "strexheq %[success], %[desired], %[storage]\n\t"
0782 "eoreq %[success], %[success], #1\n\t"
0783 BOOST_ATOMIC_DETAIL_ARM_ASM_END(%[tmp])
0784 : [original] "=&r" (original),
0785 [success] "+r" (success),
0786 #if !defined(BOOST_ATOMIC_DETAIL_ARM_ASM_TMPREG_UNUSED)
0787 [tmp] "=&l" (tmp),
0788 #endif
0789 [storage] "+Q" (storage)
0790 : [expected] "Ir" (atomics::detail::zero_extend< extended_storage_type >(expected)),
0791 [desired] "r" (desired)
0792 : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC
0793 );
0794 if (success)
0795 fence_after(success_order);
0796 else
0797 fence_after(failure_order);
0798 expected = static_cast< storage_type >(original);
0799 return success;
0800 }
0801
0802 static BOOST_FORCEINLINE bool compare_exchange_strong(
0803 storage_type volatile& storage, storage_type& expected, storage_type desired, memory_order success_order, memory_order failure_order) BOOST_NOEXCEPT
0804 {
0805 fence_before(success_order);
0806 bool success = false;
0807 #if !defined(BOOST_ATOMIC_DETAIL_ARM_ASM_TMPREG_UNUSED)
0808 uint32_t tmp;
0809 #endif
0810 extended_storage_type original;
0811 __asm__ __volatile__
0812 (
0813 BOOST_ATOMIC_DETAIL_ARM_ASM_START(%[tmp])
0814 "1:\n\t"
0815 "ldrexh %[original], %[storage]\n\t"
0816 "cmp %[original], %[expected]\n\t"
0817 "bne 2f\n\t"
0818 "strexh %[success], %[desired], %[storage]\n\t"
0819 "eors %[success], %[success], #1\n\t"
0820 "beq 1b\n\t"
0821 "2:\n\t"
0822 BOOST_ATOMIC_DETAIL_ARM_ASM_END(%[tmp])
0823 : [original] "=&r" (original),
0824 [success] "+r" (success),
0825 #if !defined(BOOST_ATOMIC_DETAIL_ARM_ASM_TMPREG_UNUSED)
0826 [tmp] "=&l" (tmp),
0827 #endif
0828 [storage] "+Q" (storage)
0829 : [expected] "Ir" (atomics::detail::zero_extend< extended_storage_type >(expected)),
0830 [desired] "r" (desired)
0831 : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC
0832 );
0833 if (success)
0834 fence_after(success_order);
0835 else
0836 fence_after(failure_order);
0837 expected = static_cast< storage_type >(original);
0838 return success;
0839 }
0840
0841 static BOOST_FORCEINLINE storage_type fetch_add(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
0842 {
0843 fence_before(order);
0844 uint32_t tmp;
0845 extended_storage_type original, result;
0846 __asm__ __volatile__
0847 (
0848 BOOST_ATOMIC_DETAIL_ARM_ASM_START(%[tmp])
0849 "1:\n\t"
0850 "ldrexh %[original], %[storage]\n\t"
0851 "add %[result], %[original], %[value]\n\t"
0852 "strexh %[tmp], %[result], %[storage]\n\t"
0853 "teq %[tmp], #0\n\t"
0854 "bne 1b\n\t"
0855 BOOST_ATOMIC_DETAIL_ARM_ASM_END(%[tmp])
0856 : [original] "=&r" (original),
0857 [result] "=&r" (result),
0858 [tmp] "=&l" (tmp),
0859 [storage] "+Q" (storage)
0860 : [value] "Ir" (v)
0861 : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC
0862 );
0863 fence_after(order);
0864 return static_cast< storage_type >(original);
0865 }
0866
0867 static BOOST_FORCEINLINE storage_type fetch_sub(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
0868 {
0869 fence_before(order);
0870 uint32_t tmp;
0871 extended_storage_type original, result;
0872 __asm__ __volatile__
0873 (
0874 BOOST_ATOMIC_DETAIL_ARM_ASM_START(%[tmp])
0875 "1:\n\t"
0876 "ldrexh %[original], %[storage]\n\t"
0877 "sub %[result], %[original], %[value]\n\t"
0878 "strexh %[tmp], %[result], %[storage]\n\t"
0879 "teq %[tmp], #0\n\t"
0880 "bne 1b\n\t"
0881 BOOST_ATOMIC_DETAIL_ARM_ASM_END(%[tmp])
0882 : [original] "=&r" (original),
0883 [result] "=&r" (result),
0884 [tmp] "=&l" (tmp),
0885 [storage] "+Q" (storage)
0886 : [value] "Ir" (v)
0887 : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC
0888 );
0889 fence_after(order);
0890 return static_cast< storage_type >(original);
0891 }
0892
0893 static BOOST_FORCEINLINE storage_type fetch_and(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
0894 {
0895 fence_before(order);
0896 uint32_t tmp;
0897 extended_storage_type original, result;
0898 __asm__ __volatile__
0899 (
0900 BOOST_ATOMIC_DETAIL_ARM_ASM_START(%[tmp])
0901 "1:\n\t"
0902 "ldrexh %[original], %[storage]\n\t"
0903 "and %[result], %[original], %[value]\n\t"
0904 "strexh %[tmp], %[result], %[storage]\n\t"
0905 "teq %[tmp], #0\n\t"
0906 "bne 1b\n\t"
0907 BOOST_ATOMIC_DETAIL_ARM_ASM_END(%[tmp])
0908 : [original] "=&r" (original),
0909 [result] "=&r" (result),
0910 [tmp] "=&l" (tmp),
0911 [storage] "+Q" (storage)
0912 : [value] "Ir" (v)
0913 : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC
0914 );
0915 fence_after(order);
0916 return static_cast< storage_type >(original);
0917 }
0918
0919 static BOOST_FORCEINLINE storage_type fetch_or(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
0920 {
0921 fence_before(order);
0922 uint32_t tmp;
0923 extended_storage_type original, result;
0924 __asm__ __volatile__
0925 (
0926 BOOST_ATOMIC_DETAIL_ARM_ASM_START(%[tmp])
0927 "1:\n\t"
0928 "ldrexh %[original], %[storage]\n\t"
0929 "orr %[result], %[original], %[value]\n\t"
0930 "strexh %[tmp], %[result], %[storage]\n\t"
0931 "teq %[tmp], #0\n\t"
0932 "bne 1b\n\t"
0933 BOOST_ATOMIC_DETAIL_ARM_ASM_END(%[tmp])
0934 : [original] "=&r" (original),
0935 [result] "=&r" (result),
0936 [tmp] "=&l" (tmp),
0937 [storage] "+Q" (storage)
0938 : [value] "Ir" (v)
0939 : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC
0940 );
0941 fence_after(order);
0942 return static_cast< storage_type >(original);
0943 }
0944
0945 static BOOST_FORCEINLINE storage_type fetch_xor(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
0946 {
0947 fence_before(order);
0948 uint32_t tmp;
0949 extended_storage_type original, result;
0950 __asm__ __volatile__
0951 (
0952 BOOST_ATOMIC_DETAIL_ARM_ASM_START(%[tmp])
0953 "1:\n\t"
0954 "ldrexh %[original], %[storage]\n\t"
0955 "eor %[result], %[original], %[value]\n\t"
0956 "strexh %[tmp], %[result], %[storage]\n\t"
0957 "teq %[tmp], #0\n\t"
0958 "bne 1b\n\t"
0959 BOOST_ATOMIC_DETAIL_ARM_ASM_END(%[tmp])
0960 : [original] "=&r" (original),
0961 [result] "=&r" (result),
0962 [tmp] "=&l" (tmp),
0963 [storage] "+Q" (storage)
0964 : [value] "Ir" (v)
0965 : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC
0966 );
0967 fence_after(order);
0968 return static_cast< storage_type >(original);
0969 }
0970
0971 static BOOST_FORCEINLINE bool test_and_set(storage_type volatile& storage, memory_order order) BOOST_NOEXCEPT
0972 {
0973 return !!exchange(storage, (storage_type)1, order);
0974 }
0975
0976 static BOOST_FORCEINLINE void clear(storage_type volatile& storage, memory_order order) BOOST_NOEXCEPT
0977 {
0978 store(storage, (storage_type)0, order);
0979 }
0980 };
0981
0982 #else
0983
0984 template< bool Interprocess >
0985 struct core_arch_operations< 2u, false, Interprocess > :
0986 public core_arch_operations< 4u, false, Interprocess >
0987 {
0988 typedef core_arch_operations< 4u, false, Interprocess > base_type;
0989 typedef typename base_type::storage_type storage_type;
0990
0991 static BOOST_FORCEINLINE storage_type fetch_add(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
0992 {
0993 base_type::fence_before(order);
0994 uint32_t tmp;
0995 storage_type original, result;
0996 __asm__ __volatile__
0997 (
0998 BOOST_ATOMIC_DETAIL_ARM_ASM_START(%[tmp])
0999 "1:\n\t"
1000 "ldrex %[original], %[storage]\n\t"
1001 "add %[result], %[original], %[value]\n\t"
1002 "uxth %[result], %[result]\n\t"
1003 "strex %[tmp], %[result], %[storage]\n\t"
1004 "teq %[tmp], #0\n\t"
1005 "bne 1b\n\t"
1006 BOOST_ATOMIC_DETAIL_ARM_ASM_END(%[tmp])
1007 : [original] "=&r" (original),
1008 [result] "=&r" (result),
1009 [tmp] "=&l" (tmp),
1010 [storage] "+Q" (storage)
1011 : [value] "Ir" (v)
1012 : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC
1013 );
1014 base_type::fence_after(order);
1015 return original;
1016 }
1017
1018 static BOOST_FORCEINLINE storage_type fetch_sub(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
1019 {
1020 base_type::fence_before(order);
1021 uint32_t tmp;
1022 storage_type original, result;
1023 __asm__ __volatile__
1024 (
1025 BOOST_ATOMIC_DETAIL_ARM_ASM_START(%[tmp])
1026 "1:\n\t"
1027 "ldrex %[original], %[storage]\n\t"
1028 "sub %[result], %[original], %[value]\n\t"
1029 "uxth %[result], %[result]\n\t"
1030 "strex %[tmp], %[result], %[storage]\n\t"
1031 "teq %[tmp], #0\n\t"
1032 "bne 1b\n\t"
1033 BOOST_ATOMIC_DETAIL_ARM_ASM_END(%[tmp])
1034 : [original] "=&r" (original),
1035 [result] "=&r" (result),
1036 [tmp] "=&l" (tmp),
1037 [storage] "+Q" (storage)
1038 : [value] "Ir" (v)
1039 : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC
1040 );
1041 base_type::fence_after(order);
1042 return original;
1043 }
1044 };
1045
1046 template< bool Interprocess >
1047 struct core_arch_operations< 2u, true, Interprocess > :
1048 public core_arch_operations< 4u, true, Interprocess >
1049 {
1050 typedef core_arch_operations< 4u, true, Interprocess > base_type;
1051 typedef typename base_type::storage_type storage_type;
1052
1053 static BOOST_FORCEINLINE storage_type fetch_add(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
1054 {
1055 base_type::fence_before(order);
1056 uint32_t tmp;
1057 storage_type original, result;
1058 __asm__ __volatile__
1059 (
1060 BOOST_ATOMIC_DETAIL_ARM_ASM_START(%[tmp])
1061 "1:\n\t"
1062 "ldrex %[original], %[storage]\n\t"
1063 "add %[result], %[original], %[value]\n\t"
1064 "sxth %[result], %[result]\n\t"
1065 "strex %[tmp], %[result], %[storage]\n\t"
1066 "teq %[tmp], #0\n\t"
1067 "bne 1b\n\t"
1068 BOOST_ATOMIC_DETAIL_ARM_ASM_END(%[tmp])
1069 : [original] "=&r" (original),
1070 [result] "=&r" (result),
1071 [tmp] "=&l" (tmp),
1072 [storage] "+Q" (storage)
1073 : [value] "Ir" (v)
1074 : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC
1075 );
1076 base_type::fence_after(order);
1077 return original;
1078 }
1079
1080 static BOOST_FORCEINLINE storage_type fetch_sub(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
1081 {
1082 base_type::fence_before(order);
1083 uint32_t tmp;
1084 storage_type original, result;
1085 __asm__ __volatile__
1086 (
1087 BOOST_ATOMIC_DETAIL_ARM_ASM_START(%[tmp])
1088 "1:\n\t"
1089 "ldrex %[original], %[storage]\n\t"
1090 "sub %[result], %[original], %[value]\n\t"
1091 "sxth %[result], %[result]\n\t"
1092 "strex %[tmp], %[result], %[storage]\n\t"
1093 "teq %[tmp], #0\n\t"
1094 "bne 1b\n\t"
1095 BOOST_ATOMIC_DETAIL_ARM_ASM_END(%[tmp])
1096 : [original] "=&r" (original),
1097 [result] "=&r" (result),
1098 [tmp] "=&l" (tmp),
1099 [storage] "+Q" (storage)
1100 : [value] "Ir" (v)
1101 : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC
1102 );
1103 base_type::fence_after(order);
1104 return original;
1105 }
1106 };
1107
1108 #endif
1109
1110 #if defined(BOOST_ATOMIC_DETAIL_ARM_HAS_LDREXD_STREXD)
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123 template< bool Signed, bool Interprocess >
1124 struct core_arch_operations< 8u, Signed, Interprocess > :
1125 public core_arch_operations_gcc_arm_base
1126 {
1127 typedef typename storage_traits< 8u >::type storage_type;
1128
1129 static BOOST_CONSTEXPR_OR_CONST std::size_t storage_size = 8u;
1130 static BOOST_CONSTEXPR_OR_CONST std::size_t storage_alignment = 8u;
1131 static BOOST_CONSTEXPR_OR_CONST bool is_signed = Signed;
1132 static BOOST_CONSTEXPR_OR_CONST bool is_interprocess = Interprocess;
1133
1134 static BOOST_FORCEINLINE void store(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
1135 {
1136 exchange(storage, v, order);
1137 }
1138
1139 static BOOST_FORCEINLINE storage_type load(storage_type const volatile& storage, memory_order order) BOOST_NOEXCEPT
1140 {
1141
1142
1143 storage_type original;
1144 #if defined(BOOST_ATOMIC_DETAIL_ARM_ASM_TMPREG_UNUSED)
1145 __asm__ __volatile__
1146 (
1147 "ldrexd %0, %H0, %1\n\t"
1148 : "=&r" (original)
1149 : "Q" (storage)
1150 );
1151 #else
1152 uint32_t tmp;
1153 __asm__ __volatile__
1154 (
1155 BOOST_ATOMIC_DETAIL_ARM_ASM_START(%0)
1156 "ldrexd %1, %H1, %2\n\t"
1157 BOOST_ATOMIC_DETAIL_ARM_ASM_END(%0)
1158 : BOOST_ATOMIC_DETAIL_ARM_ASM_TMPREG_CONSTRAINT(tmp),
1159 "=&r" (original)
1160 : "Q" (storage)
1161 );
1162 #endif
1163 fence_after(order);
1164 return original;
1165 }
1166
1167 static BOOST_FORCEINLINE storage_type exchange(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
1168 {
1169 fence_before(order);
1170 storage_type original;
1171 uint32_t tmp;
1172 __asm__ __volatile__
1173 (
1174 BOOST_ATOMIC_DETAIL_ARM_ASM_START(%0)
1175 "1:\n\t"
1176 "ldrexd %1, %H1, %2\n\t"
1177 "strexd %0, %3, %H3, %2\n\t"
1178 "teq %0, #0\n\t"
1179 "bne 1b\n\t"
1180 BOOST_ATOMIC_DETAIL_ARM_ASM_END(%0)
1181 : BOOST_ATOMIC_DETAIL_ARM_ASM_TMPREG_CONSTRAINT(tmp),
1182 "=&r" (original),
1183 "+Q" (storage)
1184 : "r" (v)
1185 : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC
1186 );
1187 fence_after(order);
1188 return original;
1189 }
1190
1191 static BOOST_FORCEINLINE bool compare_exchange_weak(
1192 storage_type volatile& storage, storage_type& expected, storage_type desired, memory_order success_order, memory_order failure_order) BOOST_NOEXCEPT
1193 {
1194 fence_before(success_order);
1195 storage_type original;
1196 bool success = false;
1197 uint32_t tmp;
1198 __asm__ __volatile__
1199 (
1200 BOOST_ATOMIC_DETAIL_ARM_ASM_START(%0)
1201 "ldrexd %1, %H1, %3\n\t"
1202 "cmp %1, %4\n\t"
1203 "it eq\n\t"
1204 "cmpeq %H1, %H4\n\t"
1205 "bne 1f\n\t"
1206 "strexd %2, %5, %H5, %3\n\t"
1207 "eor %2, %2, #1\n\t"
1208 "1:\n\t"
1209 BOOST_ATOMIC_DETAIL_ARM_ASM_END(%0)
1210 : BOOST_ATOMIC_DETAIL_ARM_ASM_TMPREG_CONSTRAINT(tmp),
1211 "=&r" (original),
1212 "+r" (success),
1213 "+Q" (storage)
1214 : "r" (expected),
1215 "r" (desired)
1216 : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC
1217 );
1218 if (success)
1219 fence_after(success_order);
1220 else
1221 fence_after(failure_order);
1222 expected = original;
1223 return success;
1224 }
1225
1226 static BOOST_FORCEINLINE bool compare_exchange_strong(
1227 storage_type volatile& storage, storage_type& expected, storage_type desired, memory_order success_order, memory_order failure_order) BOOST_NOEXCEPT
1228 {
1229 fence_before(success_order);
1230 storage_type original;
1231 bool success = false;
1232 uint32_t tmp;
1233 __asm__ __volatile__
1234 (
1235 BOOST_ATOMIC_DETAIL_ARM_ASM_START(%0)
1236 "1:\n\t"
1237 "ldrexd %1, %H1, %3\n\t"
1238 "cmp %1, %4\n\t"
1239 "it eq\n\t"
1240 "cmpeq %H1, %H4\n\t"
1241 "bne 2f\n\t"
1242 "strexd %2, %5, %H5, %3\n\t"
1243 "eors %2, %2, #1\n\t"
1244 "beq 1b\n\t"
1245 "2:\n\t"
1246 BOOST_ATOMIC_DETAIL_ARM_ASM_END(%0)
1247 : BOOST_ATOMIC_DETAIL_ARM_ASM_TMPREG_CONSTRAINT(tmp),
1248 "=&r" (original),
1249 "+r" (success),
1250 "+Q" (storage)
1251 : "r" (expected),
1252 "r" (desired)
1253 : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC
1254 );
1255 if (success)
1256 fence_after(success_order);
1257 else
1258 fence_after(failure_order);
1259 expected = original;
1260 return success;
1261 }
1262
1263 static BOOST_FORCEINLINE storage_type fetch_add(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
1264 {
1265 fence_before(order);
1266 storage_type original, result;
1267 uint32_t tmp;
1268 __asm__ __volatile__
1269 (
1270 BOOST_ATOMIC_DETAIL_ARM_ASM_START(%0)
1271 "1:\n\t"
1272 "ldrexd %1, %H1, %3\n\t"
1273 "adds " BOOST_ATOMIC_DETAIL_ARM_ASM_ARG_LO(2) ", " BOOST_ATOMIC_DETAIL_ARM_ASM_ARG_LO(1) ", " BOOST_ATOMIC_DETAIL_ARM_ASM_ARG_LO(4) "\n\t"
1274 "adc " BOOST_ATOMIC_DETAIL_ARM_ASM_ARG_HI(2) ", " BOOST_ATOMIC_DETAIL_ARM_ASM_ARG_HI(1) ", " BOOST_ATOMIC_DETAIL_ARM_ASM_ARG_HI(4) "\n\t"
1275 "strexd %0, %2, %H2, %3\n\t"
1276 "teq %0, #0\n\t"
1277 "bne 1b\n\t"
1278 BOOST_ATOMIC_DETAIL_ARM_ASM_END(%0)
1279 : BOOST_ATOMIC_DETAIL_ARM_ASM_TMPREG_CONSTRAINT(tmp),
1280 "=&r" (original),
1281 "=&r" (result),
1282 "+Q" (storage)
1283 : "r" (v)
1284 : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC
1285 );
1286 fence_after(order);
1287 return original;
1288 }
1289
1290 static BOOST_FORCEINLINE storage_type fetch_sub(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
1291 {
1292 fence_before(order);
1293 storage_type original, result;
1294 uint32_t tmp;
1295 __asm__ __volatile__
1296 (
1297 BOOST_ATOMIC_DETAIL_ARM_ASM_START(%0)
1298 "1:\n\t"
1299 "ldrexd %1, %H1, %3\n\t"
1300 "subs " BOOST_ATOMIC_DETAIL_ARM_ASM_ARG_LO(2) ", " BOOST_ATOMIC_DETAIL_ARM_ASM_ARG_LO(1) ", " BOOST_ATOMIC_DETAIL_ARM_ASM_ARG_LO(4) "\n\t"
1301 "sbc " BOOST_ATOMIC_DETAIL_ARM_ASM_ARG_HI(2) ", " BOOST_ATOMIC_DETAIL_ARM_ASM_ARG_HI(1) ", " BOOST_ATOMIC_DETAIL_ARM_ASM_ARG_HI(4) "\n\t"
1302 "strexd %0, %2, %H2, %3\n\t"
1303 "teq %0, #0\n\t"
1304 "bne 1b\n\t"
1305 BOOST_ATOMIC_DETAIL_ARM_ASM_END(%0)
1306 : BOOST_ATOMIC_DETAIL_ARM_ASM_TMPREG_CONSTRAINT(tmp),
1307 "=&r" (original),
1308 "=&r" (result),
1309 "+Q" (storage)
1310 : "r" (v)
1311 : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC
1312 );
1313 fence_after(order);
1314 return original;
1315 }
1316
1317 static BOOST_FORCEINLINE storage_type fetch_and(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
1318 {
1319 fence_before(order);
1320 storage_type original, result;
1321 uint32_t tmp;
1322 __asm__ __volatile__
1323 (
1324 BOOST_ATOMIC_DETAIL_ARM_ASM_START(%0)
1325 "1:\n\t"
1326 "ldrexd %1, %H1, %3\n\t"
1327 "and %2, %1, %4\n\t"
1328 "and %H2, %H1, %H4\n\t"
1329 "strexd %0, %2, %H2, %3\n\t"
1330 "teq %0, #0\n\t"
1331 "bne 1b\n\t"
1332 BOOST_ATOMIC_DETAIL_ARM_ASM_END(%0)
1333 : BOOST_ATOMIC_DETAIL_ARM_ASM_TMPREG_CONSTRAINT(tmp),
1334 "=&r" (original),
1335 "=&r" (result),
1336 "+Q" (storage)
1337 : "r" (v)
1338 : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC
1339 );
1340 fence_after(order);
1341 return original;
1342 }
1343
1344 static BOOST_FORCEINLINE storage_type fetch_or(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
1345 {
1346 fence_before(order);
1347 storage_type original, result;
1348 uint32_t tmp;
1349 __asm__ __volatile__
1350 (
1351 BOOST_ATOMIC_DETAIL_ARM_ASM_START(%0)
1352 "1:\n\t"
1353 "ldrexd %1, %H1, %3\n\t"
1354 "orr %2, %1, %4\n\t"
1355 "orr %H2, %H1, %H4\n\t"
1356 "strexd %0, %2, %H2, %3\n\t"
1357 "teq %0, #0\n\t"
1358 "bne 1b\n\t"
1359 BOOST_ATOMIC_DETAIL_ARM_ASM_END(%0)
1360 : BOOST_ATOMIC_DETAIL_ARM_ASM_TMPREG_CONSTRAINT(tmp),
1361 "=&r" (original),
1362 "=&r" (result),
1363 "+Q" (storage)
1364 : "r" (v)
1365 : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC
1366 );
1367 fence_after(order);
1368 return original;
1369 }
1370
1371 static BOOST_FORCEINLINE storage_type fetch_xor(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
1372 {
1373 fence_before(order);
1374 storage_type original, result;
1375 uint32_t tmp;
1376 __asm__ __volatile__
1377 (
1378 BOOST_ATOMIC_DETAIL_ARM_ASM_START(%0)
1379 "1:\n\t"
1380 "ldrexd %1, %H1, %3\n\t"
1381 "eor %2, %1, %4\n\t"
1382 "eor %H2, %H1, %H4\n\t"
1383 "strexd %0, %2, %H2, %3\n\t"
1384 "teq %0, #0\n\t"
1385 "bne 1b\n\t"
1386 BOOST_ATOMIC_DETAIL_ARM_ASM_END(%0)
1387 : BOOST_ATOMIC_DETAIL_ARM_ASM_TMPREG_CONSTRAINT(tmp),
1388 "=&r" (original),
1389 "=&r" (result),
1390 "+Q" (storage)
1391 : "r" (v)
1392 : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC
1393 );
1394 fence_after(order);
1395 return original;
1396 }
1397
1398 static BOOST_FORCEINLINE bool test_and_set(storage_type volatile& storage, memory_order order) BOOST_NOEXCEPT
1399 {
1400 return !!exchange(storage, (storage_type)1, order);
1401 }
1402
1403 static BOOST_FORCEINLINE void clear(storage_type volatile& storage, memory_order order) BOOST_NOEXCEPT
1404 {
1405 store(storage, (storage_type)0, order);
1406 }
1407 };
1408
1409 #endif
1410
1411 }
1412 }
1413 }
1414
1415 #include <boost/atomic/detail/footer.hpp>
1416
1417 #endif