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) 2017 - 2018 Andrey Semashev 7 */ 8 /*! 9 * \file atomic/detail/extra_ops_gcc_arm.hpp 10 * 11 * This header contains implementation of the extra atomic operations for ARM. 12 */ 13 14 #ifndef BOOST_ATOMIC_DETAIL_EXTRA_OPS_GCC_ARM_HPP_INCLUDED_ 15 #define BOOST_ATOMIC_DETAIL_EXTRA_OPS_GCC_ARM_HPP_INCLUDED_ 16 17 #include <cstddef> 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_type.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> 27 28 #ifdef BOOST_HAS_PRAGMA_ONCE 29 #pragma once 30 #endif 31 32 namespace boost { 33 namespace atomics { 34 namespace detail { 35 36 template< typename Base > 37 struct gcc_arm_extra_operations_common : 38 public Base 39 { 40 typedef Base base_type; 41 typedef typename base_type::storage_type storage_type; 42 opaque_negateboost::atomics::detail::gcc_arm_extra_operations_common43 static BOOST_FORCEINLINE void opaque_negate(storage_type volatile& storage, memory_order order) BOOST_NOEXCEPT 44 { 45 base_type::fetch_negate(storage, order); 46 } 47 opaque_complementboost::atomics::detail::gcc_arm_extra_operations_common48 static BOOST_FORCEINLINE void opaque_complement(storage_type volatile& storage, memory_order order) BOOST_NOEXCEPT 49 { 50 base_type::fetch_complement(storage, order); 51 } 52 negate_and_testboost::atomics::detail::gcc_arm_extra_operations_common53 static BOOST_FORCEINLINE bool negate_and_test(storage_type volatile& storage, memory_order order) BOOST_NOEXCEPT 54 { 55 return !!base_type::negate(storage, order); 56 } 57 add_and_testboost::atomics::detail::gcc_arm_extra_operations_common58 static BOOST_FORCEINLINE bool add_and_test(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT 59 { 60 return !!base_type::add(storage, v, order); 61 } 62 sub_and_testboost::atomics::detail::gcc_arm_extra_operations_common63 static BOOST_FORCEINLINE bool sub_and_test(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT 64 { 65 return !!base_type::sub(storage, v, order); 66 } 67 and_and_testboost::atomics::detail::gcc_arm_extra_operations_common68 static BOOST_FORCEINLINE bool and_and_test(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT 69 { 70 return !!base_type::bitwise_and(storage, v, order); 71 } 72 or_and_testboost::atomics::detail::gcc_arm_extra_operations_common73 static BOOST_FORCEINLINE bool or_and_test(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT 74 { 75 return !!base_type::bitwise_or(storage, v, order); 76 } 77 xor_and_testboost::atomics::detail::gcc_arm_extra_operations_common78 static BOOST_FORCEINLINE bool xor_and_test(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT 79 { 80 return !!base_type::bitwise_xor(storage, v, order); 81 } 82 complement_and_testboost::atomics::detail::gcc_arm_extra_operations_common83 static BOOST_FORCEINLINE bool complement_and_test(storage_type volatile& storage, memory_order order) BOOST_NOEXCEPT 84 { 85 return !!base_type::bitwise_complement(storage, order); 86 } 87 }; 88 89 template< typename Base, std::size_t Size, bool Signed > 90 struct gcc_arm_extra_operations; 91 92 #if defined(BOOST_ATOMIC_DETAIL_ARM_HAS_LDREXB_STREXB) 93 94 template< typename Base, bool Signed > 95 struct gcc_arm_extra_operations< Base, 1u, Signed > : 96 public generic_extra_operations< Base, 1u, Signed > 97 { 98 typedef generic_extra_operations< Base, 1u, Signed > base_type; 99 typedef typename base_type::storage_type storage_type; 100 typedef typename make_storage_type< 4u >::type extended_storage_type; 101 fetch_negateboost::atomics::detail::gcc_arm_extra_operations102 static BOOST_FORCEINLINE storage_type fetch_negate(storage_type volatile& storage, memory_order order) BOOST_NOEXCEPT 103 { 104 gcc_arm_operations_base::fence_before(order); 105 uint32_t tmp; 106 extended_storage_type original, result; 107 __asm__ __volatile__ 108 ( 109 BOOST_ATOMIC_DETAIL_ARM_ASM_START(%[tmp]) 110 "1:\n" 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 121 : 122 : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC 123 ); 124 gcc_arm_operations_base::fence_after(order); 125 return static_cast< storage_type >(original); 126 } 127 negateboost::atomics::detail::gcc_arm_extra_operations128 static BOOST_FORCEINLINE storage_type negate(storage_type volatile& storage, memory_order order) BOOST_NOEXCEPT 129 { 130 gcc_arm_operations_base::fence_before(order); 131 uint32_t tmp; 132 extended_storage_type original, result; 133 __asm__ __volatile__ 134 ( 135 BOOST_ATOMIC_DETAIL_ARM_ASM_START(%[tmp]) 136 "1:\n" 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 147 : 148 : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC 149 ); 150 gcc_arm_operations_base::fence_after(order); 151 return static_cast< storage_type >(result); 152 } 153 addboost::atomics::detail::gcc_arm_extra_operations154 static BOOST_FORCEINLINE storage_type add(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT 155 { 156 gcc_arm_operations_base::fence_before(order); 157 uint32_t tmp; 158 extended_storage_type original, result; 159 __asm__ __volatile__ 160 ( 161 BOOST_ATOMIC_DETAIL_ARM_ASM_START(%[tmp]) 162 "1:\n" 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 175 ); 176 gcc_arm_operations_base::fence_after(order); 177 return static_cast< storage_type >(result); 178 } 179 subboost::atomics::detail::gcc_arm_extra_operations180 static BOOST_FORCEINLINE storage_type sub(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT 181 { 182 gcc_arm_operations_base::fence_before(order); 183 uint32_t tmp; 184 extended_storage_type original, result; 185 __asm__ __volatile__ 186 ( 187 BOOST_ATOMIC_DETAIL_ARM_ASM_START(%[tmp]) 188 "1:\n" 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 201 ); 202 gcc_arm_operations_base::fence_after(order); 203 return static_cast< storage_type >(result); 204 } 205 bitwise_andboost::atomics::detail::gcc_arm_extra_operations206 static BOOST_FORCEINLINE storage_type bitwise_and(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT 207 { 208 gcc_arm_operations_base::fence_before(order); 209 uint32_t tmp; 210 extended_storage_type original, result; 211 __asm__ __volatile__ 212 ( 213 BOOST_ATOMIC_DETAIL_ARM_ASM_START(%[tmp]) 214 "1:\n" 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 227 ); 228 gcc_arm_operations_base::fence_after(order); 229 return static_cast< storage_type >(result); 230 } 231 bitwise_orboost::atomics::detail::gcc_arm_extra_operations232 static BOOST_FORCEINLINE storage_type bitwise_or(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT 233 { 234 gcc_arm_operations_base::fence_before(order); 235 uint32_t tmp; 236 extended_storage_type original, result; 237 __asm__ __volatile__ 238 ( 239 BOOST_ATOMIC_DETAIL_ARM_ASM_START(%[tmp]) 240 "1:\n" 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 253 ); 254 gcc_arm_operations_base::fence_after(order); 255 return static_cast< storage_type >(result); 256 } 257 bitwise_xorboost::atomics::detail::gcc_arm_extra_operations258 static BOOST_FORCEINLINE storage_type bitwise_xor(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT 259 { 260 gcc_arm_operations_base::fence_before(order); 261 uint32_t tmp; 262 extended_storage_type original, result; 263 __asm__ __volatile__ 264 ( 265 BOOST_ATOMIC_DETAIL_ARM_ASM_START(%[tmp]) 266 "1:\n" 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 279 ); 280 gcc_arm_operations_base::fence_after(order); 281 return static_cast< storage_type >(result); 282 } 283 fetch_complementboost::atomics::detail::gcc_arm_extra_operations284 static BOOST_FORCEINLINE storage_type fetch_complement(storage_type volatile& storage, memory_order order) BOOST_NOEXCEPT 285 { 286 gcc_arm_operations_base::fence_before(order); 287 uint32_t tmp; 288 extended_storage_type original, result; 289 __asm__ __volatile__ 290 ( 291 BOOST_ATOMIC_DETAIL_ARM_ASM_START(%[tmp]) 292 "1:\n" 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 303 : 304 : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC 305 ); 306 gcc_arm_operations_base::fence_after(order); 307 return static_cast< storage_type >(original); 308 } 309 bitwise_complementboost::atomics::detail::gcc_arm_extra_operations310 static BOOST_FORCEINLINE storage_type bitwise_complement(storage_type volatile& storage, memory_order order) BOOST_NOEXCEPT 311 { 312 gcc_arm_operations_base::fence_before(order); 313 uint32_t tmp; 314 extended_storage_type original, result; 315 __asm__ __volatile__ 316 ( 317 BOOST_ATOMIC_DETAIL_ARM_ASM_START(%[tmp]) 318 "1:\n" 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 329 : 330 : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC 331 ); 332 gcc_arm_operations_base::fence_after(order); 333 return static_cast< storage_type >(result); 334 } 335 }; 336 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 > > 340 { 341 }; 342 343 #endif // defined(BOOST_ATOMIC_DETAIL_ARM_HAS_LDREXB_STREXB) 344 345 #if defined(BOOST_ATOMIC_DETAIL_ARM_HAS_LDREXH_STREXH) 346 347 template< typename Base, bool Signed > 348 struct gcc_arm_extra_operations< Base, 2u, Signed > : 349 public generic_extra_operations< Base, 2u, Signed > 350 { 351 typedef generic_extra_operations< Base, 2u, Signed > base_type; 352 typedef typename base_type::storage_type storage_type; 353 typedef typename make_storage_type< 4u >::type extended_storage_type; 354 fetch_negateboost::atomics::detail::gcc_arm_extra_operations355 static BOOST_FORCEINLINE storage_type fetch_negate(storage_type volatile& storage, memory_order order) BOOST_NOEXCEPT 356 { 357 gcc_arm_operations_base::fence_before(order); 358 uint32_t tmp; 359 extended_storage_type original, result; 360 __asm__ __volatile__ 361 ( 362 BOOST_ATOMIC_DETAIL_ARM_ASM_START(%[tmp]) 363 "1:\n" 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 374 : 375 : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC 376 ); 377 gcc_arm_operations_base::fence_after(order); 378 return static_cast< storage_type >(original); 379 } 380 negateboost::atomics::detail::gcc_arm_extra_operations381 static BOOST_FORCEINLINE storage_type negate(storage_type volatile& storage, memory_order order) BOOST_NOEXCEPT 382 { 383 gcc_arm_operations_base::fence_before(order); 384 uint32_t tmp; 385 extended_storage_type original, result; 386 __asm__ __volatile__ 387 ( 388 BOOST_ATOMIC_DETAIL_ARM_ASM_START(%[tmp]) 389 "1:\n" 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 400 : 401 : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC 402 ); 403 gcc_arm_operations_base::fence_after(order); 404 return static_cast< storage_type >(result); 405 } 406 addboost::atomics::detail::gcc_arm_extra_operations407 static BOOST_FORCEINLINE storage_type add(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT 408 { 409 gcc_arm_operations_base::fence_before(order); 410 uint32_t tmp; 411 extended_storage_type original, result; 412 __asm__ __volatile__ 413 ( 414 BOOST_ATOMIC_DETAIL_ARM_ASM_START(%[tmp]) 415 "1:\n" 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 428 ); 429 gcc_arm_operations_base::fence_after(order); 430 return static_cast< storage_type >(result); 431 } 432 subboost::atomics::detail::gcc_arm_extra_operations433 static BOOST_FORCEINLINE storage_type sub(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT 434 { 435 gcc_arm_operations_base::fence_before(order); 436 uint32_t tmp; 437 extended_storage_type original, result; 438 __asm__ __volatile__ 439 ( 440 BOOST_ATOMIC_DETAIL_ARM_ASM_START(%[tmp]) 441 "1:\n" 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 454 ); 455 gcc_arm_operations_base::fence_after(order); 456 return static_cast< storage_type >(result); 457 } 458 bitwise_andboost::atomics::detail::gcc_arm_extra_operations459 static BOOST_FORCEINLINE storage_type bitwise_and(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT 460 { 461 gcc_arm_operations_base::fence_before(order); 462 uint32_t tmp; 463 extended_storage_type original, result; 464 __asm__ __volatile__ 465 ( 466 BOOST_ATOMIC_DETAIL_ARM_ASM_START(%[tmp]) 467 "1:\n" 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 480 ); 481 gcc_arm_operations_base::fence_after(order); 482 return static_cast< storage_type >(result); 483 } 484 bitwise_orboost::atomics::detail::gcc_arm_extra_operations485 static BOOST_FORCEINLINE storage_type bitwise_or(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT 486 { 487 gcc_arm_operations_base::fence_before(order); 488 uint32_t tmp; 489 extended_storage_type original, result; 490 __asm__ __volatile__ 491 ( 492 BOOST_ATOMIC_DETAIL_ARM_ASM_START(%[tmp]) 493 "1:\n" 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 506 ); 507 gcc_arm_operations_base::fence_after(order); 508 return static_cast< storage_type >(result); 509 } 510 bitwise_xorboost::atomics::detail::gcc_arm_extra_operations511 static BOOST_FORCEINLINE storage_type bitwise_xor(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT 512 { 513 gcc_arm_operations_base::fence_before(order); 514 uint32_t tmp; 515 extended_storage_type original, result; 516 __asm__ __volatile__ 517 ( 518 BOOST_ATOMIC_DETAIL_ARM_ASM_START(%[tmp]) 519 "1:\n" 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 532 ); 533 gcc_arm_operations_base::fence_after(order); 534 return static_cast< storage_type >(result); 535 } 536 fetch_complementboost::atomics::detail::gcc_arm_extra_operations537 static BOOST_FORCEINLINE storage_type fetch_complement(storage_type volatile& storage, memory_order order) BOOST_NOEXCEPT 538 { 539 gcc_arm_operations_base::fence_before(order); 540 uint32_t tmp; 541 extended_storage_type original, result; 542 __asm__ __volatile__ 543 ( 544 BOOST_ATOMIC_DETAIL_ARM_ASM_START(%[tmp]) 545 "1:\n" 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 556 : 557 : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC 558 ); 559 gcc_arm_operations_base::fence_after(order); 560 return static_cast< storage_type >(original); 561 } 562 bitwise_complementboost::atomics::detail::gcc_arm_extra_operations563 static BOOST_FORCEINLINE storage_type bitwise_complement(storage_type volatile& storage, memory_order order) BOOST_NOEXCEPT 564 { 565 gcc_arm_operations_base::fence_before(order); 566 uint32_t tmp; 567 extended_storage_type original, result; 568 __asm__ __volatile__ 569 ( 570 BOOST_ATOMIC_DETAIL_ARM_ASM_START(%[tmp]) 571 "1:\n" 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 582 : 583 : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC 584 ); 585 gcc_arm_operations_base::fence_after(order); 586 return static_cast< storage_type >(result); 587 } 588 }; 589 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 > > 593 { 594 }; 595 596 #endif // defined(BOOST_ATOMIC_DETAIL_ARM_HAS_LDREXH_STREXH) 597 598 template< typename Base, bool Signed > 599 struct gcc_arm_extra_operations< Base, 4u, Signed > : 600 public generic_extra_operations< Base, 4u, Signed > 601 { 602 typedef generic_extra_operations< Base, 4u, Signed > base_type; 603 typedef typename base_type::storage_type storage_type; 604 fetch_negateboost::atomics::detail::gcc_arm_extra_operations605 static BOOST_FORCEINLINE storage_type fetch_negate(storage_type volatile& storage, memory_order order) BOOST_NOEXCEPT 606 { 607 gcc_arm_operations_base::fence_before(order); 608 uint32_t tmp; 609 storage_type original, result; 610 __asm__ __volatile__ 611 ( 612 BOOST_ATOMIC_DETAIL_ARM_ASM_START(%[tmp]) 613 "1:\n" 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 624 : 625 : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC 626 ); 627 gcc_arm_operations_base::fence_after(order); 628 return original; 629 } 630 negateboost::atomics::detail::gcc_arm_extra_operations631 static BOOST_FORCEINLINE storage_type negate(storage_type volatile& storage, memory_order order) BOOST_NOEXCEPT 632 { 633 gcc_arm_operations_base::fence_before(order); 634 uint32_t tmp; 635 storage_type original, result; 636 __asm__ __volatile__ 637 ( 638 BOOST_ATOMIC_DETAIL_ARM_ASM_START(%[tmp]) 639 "1:\n" 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 650 : 651 : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC 652 ); 653 gcc_arm_operations_base::fence_after(order); 654 return result; 655 } 656 addboost::atomics::detail::gcc_arm_extra_operations657 static BOOST_FORCEINLINE storage_type add(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT 658 { 659 gcc_arm_operations_base::fence_before(order); 660 uint32_t tmp; 661 storage_type original, result; 662 __asm__ __volatile__ 663 ( 664 BOOST_ATOMIC_DETAIL_ARM_ASM_START(%[tmp]) 665 "1:\n" 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 678 ); 679 gcc_arm_operations_base::fence_after(order); 680 return result; 681 } 682 subboost::atomics::detail::gcc_arm_extra_operations683 static BOOST_FORCEINLINE storage_type sub(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT 684 { 685 gcc_arm_operations_base::fence_before(order); 686 uint32_t tmp; 687 storage_type original, result; 688 __asm__ __volatile__ 689 ( 690 BOOST_ATOMIC_DETAIL_ARM_ASM_START(%[tmp]) 691 "1:\n" 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 704 ); 705 gcc_arm_operations_base::fence_after(order); 706 return result; 707 } 708 bitwise_andboost::atomics::detail::gcc_arm_extra_operations709 static BOOST_FORCEINLINE storage_type bitwise_and(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT 710 { 711 gcc_arm_operations_base::fence_before(order); 712 uint32_t tmp; 713 storage_type original, result; 714 __asm__ __volatile__ 715 ( 716 BOOST_ATOMIC_DETAIL_ARM_ASM_START(%[tmp]) 717 "1:\n" 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 730 ); 731 gcc_arm_operations_base::fence_after(order); 732 return result; 733 } 734 bitwise_orboost::atomics::detail::gcc_arm_extra_operations735 static BOOST_FORCEINLINE storage_type bitwise_or(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT 736 { 737 gcc_arm_operations_base::fence_before(order); 738 uint32_t tmp; 739 storage_type original, result; 740 __asm__ __volatile__ 741 ( 742 BOOST_ATOMIC_DETAIL_ARM_ASM_START(%[tmp]) 743 "1:\n" 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 756 ); 757 gcc_arm_operations_base::fence_after(order); 758 return result; 759 } 760 bitwise_xorboost::atomics::detail::gcc_arm_extra_operations761 static BOOST_FORCEINLINE storage_type bitwise_xor(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT 762 { 763 gcc_arm_operations_base::fence_before(order); 764 uint32_t tmp; 765 storage_type original, result; 766 __asm__ __volatile__ 767 ( 768 BOOST_ATOMIC_DETAIL_ARM_ASM_START(%[tmp]) 769 "1:\n" 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 782 ); 783 gcc_arm_operations_base::fence_after(order); 784 return result; 785 } 786 fetch_complementboost::atomics::detail::gcc_arm_extra_operations787 static BOOST_FORCEINLINE storage_type fetch_complement(storage_type volatile& storage, memory_order order) BOOST_NOEXCEPT 788 { 789 gcc_arm_operations_base::fence_before(order); 790 uint32_t tmp; 791 storage_type original, result; 792 __asm__ __volatile__ 793 ( 794 BOOST_ATOMIC_DETAIL_ARM_ASM_START(%[tmp]) 795 "1:\n" 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 806 : 807 : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC 808 ); 809 gcc_arm_operations_base::fence_after(order); 810 return original; 811 } 812 bitwise_complementboost::atomics::detail::gcc_arm_extra_operations813 static BOOST_FORCEINLINE storage_type bitwise_complement(storage_type volatile& storage, memory_order order) BOOST_NOEXCEPT 814 { 815 gcc_arm_operations_base::fence_before(order); 816 uint32_t tmp; 817 storage_type original, result; 818 __asm__ __volatile__ 819 ( 820 BOOST_ATOMIC_DETAIL_ARM_ASM_START(%[tmp]) 821 "1:\n" 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 832 : 833 : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC 834 ); 835 gcc_arm_operations_base::fence_after(order); 836 return result; 837 } 838 }; 839 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 > > 843 { 844 }; 845 846 #if defined(BOOST_ATOMIC_DETAIL_ARM_HAS_LDREXD_STREXD) 847 848 template< typename Base, bool Signed > 849 struct gcc_arm_extra_operations< Base, 8u, Signed > : 850 public generic_extra_operations< Base, 8u, Signed > 851 { 852 typedef generic_extra_operations< Base, 8u, Signed > base_type; 853 typedef typename base_type::storage_type storage_type; 854 fetch_negateboost::atomics::detail::gcc_arm_extra_operations855 static BOOST_FORCEINLINE storage_type fetch_negate(storage_type volatile& storage, memory_order order) BOOST_NOEXCEPT 856 { 857 gcc_arm_operations_base::fence_before(order); 858 storage_type original, result; 859 uint32_t tmp; 860 __asm__ __volatile__ 861 ( 862 BOOST_ATOMIC_DETAIL_ARM_ASM_START(%0) 863 "1:\n" 864 "ldrexd %1, %H1, [%3]\n" // original = *(&storage) 865 "mvn %2, %1\n" // result = NOT original 866 "mvn %H2, %H1\n" 867 "adds %2, %2, #1\n" // result = result + 1 868 "adc %H2, %H2, #0\n" 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 875 "=&r" (result) // %2 876 : "r" (&storage) // %3 877 : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC_COMMA "memory" 878 ); 879 gcc_arm_operations_base::fence_after(order); 880 return original; 881 } 882 negateboost::atomics::detail::gcc_arm_extra_operations883 static BOOST_FORCEINLINE storage_type negate(storage_type volatile& storage, memory_order order) BOOST_NOEXCEPT 884 { 885 gcc_arm_operations_base::fence_before(order); 886 storage_type original, result; 887 uint32_t tmp; 888 __asm__ __volatile__ 889 ( 890 BOOST_ATOMIC_DETAIL_ARM_ASM_START(%0) 891 "1:\n" 892 "ldrexd %1, %H1, [%3]\n" // original = *(&storage) 893 "mvn %2, %1\n" // result = NOT original 894 "mvn %H2, %H1\n" 895 "adds %2, %2, #1\n" // result = result + 1 896 "adc %H2, %H2, #0\n" 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 903 "=&r" (result) // %2 904 : "r" (&storage) // %3 905 : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC_COMMA "memory" 906 ); 907 gcc_arm_operations_base::fence_after(order); 908 return result; 909 } 910 addboost::atomics::detail::gcc_arm_extra_operations911 static BOOST_FORCEINLINE storage_type add(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT 912 { 913 gcc_arm_operations_base::fence_before(order); 914 storage_type original, result; 915 uint32_t tmp; 916 __asm__ __volatile__ 917 ( 918 BOOST_ATOMIC_DETAIL_ARM_ASM_START(%0) 919 "1:\n" 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 929 "=&r" (result) // %2 930 : "r" (&storage), // %3 931 "r" (v) // %4 932 : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC_COMMA "memory" 933 ); 934 gcc_arm_operations_base::fence_after(order); 935 return result; 936 } 937 subboost::atomics::detail::gcc_arm_extra_operations938 static BOOST_FORCEINLINE storage_type sub(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT 939 { 940 gcc_arm_operations_base::fence_before(order); 941 storage_type original, result; 942 uint32_t tmp; 943 __asm__ __volatile__ 944 ( 945 BOOST_ATOMIC_DETAIL_ARM_ASM_START(%0) 946 "1:\n" 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 956 "=&r" (result) // %2 957 : "r" (&storage), // %3 958 "r" (v) // %4 959 : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC_COMMA "memory" 960 ); 961 gcc_arm_operations_base::fence_after(order); 962 return result; 963 } 964 bitwise_andboost::atomics::detail::gcc_arm_extra_operations965 static BOOST_FORCEINLINE storage_type bitwise_and(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT 966 { 967 gcc_arm_operations_base::fence_before(order); 968 storage_type original, result; 969 uint32_t tmp; 970 __asm__ __volatile__ 971 ( 972 BOOST_ATOMIC_DETAIL_ARM_ASM_START(%0) 973 "1:\n" 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 983 "=&r" (result) // %2 984 : "r" (&storage), // %3 985 "r" (v) // %4 986 : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC_COMMA "memory" 987 ); 988 gcc_arm_operations_base::fence_after(order); 989 return result; 990 } 991 bitwise_orboost::atomics::detail::gcc_arm_extra_operations992 static BOOST_FORCEINLINE storage_type bitwise_or(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT 993 { 994 gcc_arm_operations_base::fence_before(order); 995 storage_type original, result; 996 uint32_t tmp; 997 __asm__ __volatile__ 998 ( 999 BOOST_ATOMIC_DETAIL_ARM_ASM_START(%0) 1000 "1:\n" 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 1012 "r" (v) // %4 1013 : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC_COMMA "memory" 1014 ); 1015 gcc_arm_operations_base::fence_after(order); 1016 return result; 1017 } 1018 bitwise_xorboost::atomics::detail::gcc_arm_extra_operations1019 static BOOST_FORCEINLINE storage_type bitwise_xor(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT 1020 { 1021 gcc_arm_operations_base::fence_before(order); 1022 storage_type original, result; 1023 uint32_t tmp; 1024 __asm__ __volatile__ 1025 ( 1026 BOOST_ATOMIC_DETAIL_ARM_ASM_START(%0) 1027 "1:\n" 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 1039 "r" (v) // %4 1040 : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC_COMMA "memory" 1041 ); 1042 gcc_arm_operations_base::fence_after(order); 1043 return result; 1044 } 1045 fetch_complementboost::atomics::detail::gcc_arm_extra_operations1046 static BOOST_FORCEINLINE storage_type fetch_complement(storage_type volatile& storage, memory_order order) BOOST_NOEXCEPT 1047 { 1048 gcc_arm_operations_base::fence_before(order); 1049 storage_type original, result; 1050 uint32_t tmp; 1051 __asm__ __volatile__ 1052 ( 1053 BOOST_ATOMIC_DETAIL_ARM_ASM_START(%0) 1054 "1:\n" 1055 "ldrexd %1, %H1, [%3]\n" // original = *(&storage) 1056 "mvn %2, %1\n" // result = NOT original 1057 "mvn %H2, %H1\n" 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" 1067 ); 1068 gcc_arm_operations_base::fence_after(order); 1069 return original; 1070 } 1071 bitwise_complementboost::atomics::detail::gcc_arm_extra_operations1072 static BOOST_FORCEINLINE storage_type bitwise_complement(storage_type volatile& storage, memory_order order) BOOST_NOEXCEPT 1073 { 1074 gcc_arm_operations_base::fence_before(order); 1075 storage_type original, result; 1076 uint32_t tmp; 1077 __asm__ __volatile__ 1078 ( 1079 BOOST_ATOMIC_DETAIL_ARM_ASM_START(%0) 1080 "1:\n" 1081 "ldrexd %1, %H1, [%3]\n" // original = *(&storage) 1082 "mvn %2, %1\n" // result = NOT original 1083 "mvn %H2, %H1\n" 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" 1093 ); 1094 gcc_arm_operations_base::fence_after(order); 1095 return result; 1096 } 1097 }; 1098 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 > > 1102 { 1103 }; 1104 1105 #endif // defined(BOOST_ATOMIC_DETAIL_ARM_HAS_LDREXD_STREXD) 1106 1107 } // namespace detail 1108 } // namespace atomics 1109 } // namespace boost 1110 1111 #endif // BOOST_ATOMIC_DETAIL_EXTRA_OPS_GCC_ARM_HPP_INCLUDED_ 1112