extra_ops_gcc_aarch32.hpp 40 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132
  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) 2020-2025 Andrey Semashev
  7. */
  8. /*!
  9. * \file atomic/detail/extra_ops_gcc_aarch32.hpp
  10. *
  11. * This header contains implementation of the extra atomic operations for AArch32.
  12. */
  13. #ifndef BOOST_ATOMIC_DETAIL_EXTRA_OPS_GCC_AARCH32_HPP_INCLUDED_
  14. #define BOOST_ATOMIC_DETAIL_EXTRA_OPS_GCC_AARCH32_HPP_INCLUDED_
  15. #include <cstddef>
  16. #include <cstdint>
  17. #include <boost/memory_order.hpp>
  18. #include <boost/atomic/detail/config.hpp>
  19. #include <boost/atomic/detail/platform.hpp>
  20. #include <boost/atomic/detail/storage_traits.hpp>
  21. #include <boost/atomic/detail/extra_operations_fwd.hpp>
  22. #include <boost/atomic/detail/extra_ops_generic.hpp>
  23. #include <boost/atomic/detail/ops_gcc_aarch32_common.hpp>
  24. #include <boost/atomic/detail/capabilities.hpp>
  25. #include <boost/atomic/detail/header.hpp>
  26. #ifdef BOOST_HAS_PRAGMA_ONCE
  27. #pragma once
  28. #endif
  29. namespace boost {
  30. namespace atomics {
  31. namespace detail {
  32. template< typename Base >
  33. struct extra_operations_gcc_aarch32_common :
  34. public Base
  35. {
  36. using base_type = Base;
  37. using storage_type = typename base_type::storage_type;
  38. // Note: For opaque operations prefer operations returning the resulting values instead of the original values
  39. // as these operations require less registers.
  40. static BOOST_FORCEINLINE void opaque_negate(storage_type volatile& storage, memory_order order) noexcept
  41. {
  42. base_type::negate(storage, order);
  43. }
  44. static BOOST_FORCEINLINE void opaque_complement(storage_type volatile& storage, memory_order order) noexcept
  45. {
  46. base_type::bitwise_complement(storage, order);
  47. }
  48. static BOOST_FORCEINLINE void opaque_add(storage_type volatile& storage, storage_type v, memory_order order) noexcept
  49. {
  50. base_type::add(storage, v, order);
  51. }
  52. static BOOST_FORCEINLINE void opaque_sub(storage_type volatile& storage, storage_type v, memory_order order) noexcept
  53. {
  54. base_type::sub(storage, v, order);
  55. }
  56. static BOOST_FORCEINLINE void opaque_and(storage_type volatile& storage, storage_type v, memory_order order) noexcept
  57. {
  58. base_type::bitwise_and(storage, v, order);
  59. }
  60. static BOOST_FORCEINLINE void opaque_or(storage_type volatile& storage, storage_type v, memory_order order) noexcept
  61. {
  62. base_type::bitwise_or(storage, v, order);
  63. }
  64. static BOOST_FORCEINLINE void opaque_xor(storage_type volatile& storage, storage_type v, memory_order order) noexcept
  65. {
  66. base_type::bitwise_xor(storage, v, order);
  67. }
  68. static BOOST_FORCEINLINE bool negate_and_test(storage_type volatile& storage, memory_order order) noexcept
  69. {
  70. return !!base_type::negate(storage, order);
  71. }
  72. static BOOST_FORCEINLINE bool add_and_test(storage_type volatile& storage, storage_type v, memory_order order) noexcept
  73. {
  74. return !!base_type::add(storage, v, order);
  75. }
  76. static BOOST_FORCEINLINE bool sub_and_test(storage_type volatile& storage, storage_type v, memory_order order) noexcept
  77. {
  78. return !!base_type::sub(storage, v, order);
  79. }
  80. static BOOST_FORCEINLINE bool and_and_test(storage_type volatile& storage, storage_type v, memory_order order) noexcept
  81. {
  82. return !!base_type::bitwise_and(storage, v, order);
  83. }
  84. static BOOST_FORCEINLINE bool or_and_test(storage_type volatile& storage, storage_type v, memory_order order) noexcept
  85. {
  86. return !!base_type::bitwise_or(storage, v, order);
  87. }
  88. static BOOST_FORCEINLINE bool xor_and_test(storage_type volatile& storage, storage_type v, memory_order order) noexcept
  89. {
  90. return !!base_type::bitwise_xor(storage, v, order);
  91. }
  92. static BOOST_FORCEINLINE bool complement_and_test(storage_type volatile& storage, memory_order order) noexcept
  93. {
  94. return !!base_type::bitwise_complement(storage, order);
  95. }
  96. };
  97. template< typename Base, std::size_t Size, bool Signed >
  98. struct extra_operations_gcc_aarch32;
  99. template< typename Base, bool Signed >
  100. struct extra_operations_gcc_aarch32< Base, 1u, Signed > :
  101. public extra_operations_generic< Base, 1u, Signed >
  102. {
  103. using base_type = extra_operations_generic< Base, 1u, Signed >;
  104. using storage_type = typename base_type::storage_type;
  105. static BOOST_FORCEINLINE storage_type fetch_negate(storage_type volatile& storage, memory_order order) noexcept
  106. {
  107. BOOST_ATOMIC_DETAIL_TSAN_RELEASE(&storage, order);
  108. storage_type original, result;
  109. std::uint32_t tmp;
  110. #define BOOST_ATOMIC_DETAIL_AARCH32_MO_INSN(ld_mo, st_mo)\
  111. __asm__ __volatile__\
  112. (\
  113. "1:\n\t"\
  114. "ld" ld_mo "exb %[original], %[storage]\n\t"\
  115. "rsb %[result], %[original], #0\n\t"\
  116. "st" st_mo "exb %[tmp], %[result], %[storage]\n\t"\
  117. "teq %[tmp], #0\n\t"\
  118. "bne 1b\n\t"\
  119. : [original] "=&r" (original), [result] "=&r" (result), [tmp] "=&r" (tmp), [storage] "+Q" (storage)\
  120. : \
  121. : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC_COMMA "memory"\
  122. );
  123. BOOST_ATOMIC_DETAIL_AARCH32_MO_SWITCH(order)
  124. #undef BOOST_ATOMIC_DETAIL_AARCH32_MO_INSN
  125. BOOST_ATOMIC_DETAIL_TSAN_ACQUIRE(&storage, order);
  126. return original;
  127. }
  128. static BOOST_FORCEINLINE storage_type negate(storage_type volatile& storage, memory_order order) noexcept
  129. {
  130. BOOST_ATOMIC_DETAIL_TSAN_RELEASE(&storage, order);
  131. storage_type result;
  132. std::uint32_t tmp;
  133. #define BOOST_ATOMIC_DETAIL_AARCH32_MO_INSN(ld_mo, st_mo)\
  134. __asm__ __volatile__\
  135. (\
  136. "1:\n\t"\
  137. "ld" ld_mo "exb %[result], %[storage]\n\t"\
  138. "rsb %[result], #0\n\t"\
  139. "st" st_mo "exb %[tmp], %[result], %[storage]\n\t"\
  140. "teq %[tmp], #0\n\t"\
  141. "bne 1b\n\t"\
  142. : [result] "=&r" (result), [tmp] "=&r" (tmp), [storage] "+Q" (storage)\
  143. : \
  144. : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC_COMMA "memory"\
  145. );
  146. BOOST_ATOMIC_DETAIL_AARCH32_MO_SWITCH(order)
  147. #undef BOOST_ATOMIC_DETAIL_AARCH32_MO_INSN
  148. BOOST_ATOMIC_DETAIL_TSAN_ACQUIRE(&storage, order);
  149. return result;
  150. }
  151. static BOOST_FORCEINLINE storage_type add(storage_type volatile& storage, storage_type v, memory_order order) noexcept
  152. {
  153. BOOST_ATOMIC_DETAIL_TSAN_RELEASE(&storage, order);
  154. storage_type result;
  155. std::uint32_t tmp;
  156. #define BOOST_ATOMIC_DETAIL_AARCH32_MO_INSN(ld_mo, st_mo)\
  157. __asm__ __volatile__\
  158. (\
  159. "1:\n\t"\
  160. "ld" ld_mo "exb %[result], %[storage]\n\t"\
  161. "add %[result], %[value]\n\t"\
  162. "st" st_mo "exb %[tmp], %[result], %[storage]\n\t"\
  163. "teq %[tmp], #0\n\t"\
  164. "bne 1b\n\t"\
  165. : [result] "=&r" (result), [tmp] "=&r" (tmp), [storage] "+Q" (storage)\
  166. : [value] "Ir" (v)\
  167. : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC_COMMA "memory"\
  168. );
  169. BOOST_ATOMIC_DETAIL_AARCH32_MO_SWITCH(order)
  170. #undef BOOST_ATOMIC_DETAIL_AARCH32_MO_INSN
  171. BOOST_ATOMIC_DETAIL_TSAN_ACQUIRE(&storage, order);
  172. return result;
  173. }
  174. static BOOST_FORCEINLINE storage_type sub(storage_type volatile& storage, storage_type v, memory_order order) noexcept
  175. {
  176. BOOST_ATOMIC_DETAIL_TSAN_RELEASE(&storage, order);
  177. storage_type result;
  178. std::uint32_t tmp;
  179. #define BOOST_ATOMIC_DETAIL_AARCH32_MO_INSN(ld_mo, st_mo)\
  180. __asm__ __volatile__\
  181. (\
  182. "1:\n\t"\
  183. "ld" ld_mo "exb %[result], %[storage]\n\t"\
  184. "sub %[result], %[value]\n\t"\
  185. "st" st_mo "exb %[tmp], %[result], %[storage]\n\t"\
  186. "teq %[tmp], #0\n\t"\
  187. "bne 1b\n\t"\
  188. : [result] "=&r" (result), [tmp] "=&r" (tmp), [storage] "+Q" (storage)\
  189. : [value] "Ir" (v)\
  190. : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC_COMMA "memory"\
  191. );
  192. BOOST_ATOMIC_DETAIL_AARCH32_MO_SWITCH(order)
  193. #undef BOOST_ATOMIC_DETAIL_AARCH32_MO_INSN
  194. BOOST_ATOMIC_DETAIL_TSAN_ACQUIRE(&storage, order);
  195. return result;
  196. }
  197. static BOOST_FORCEINLINE storage_type bitwise_and(storage_type volatile& storage, storage_type v, memory_order order) noexcept
  198. {
  199. BOOST_ATOMIC_DETAIL_TSAN_RELEASE(&storage, order);
  200. storage_type result;
  201. std::uint32_t tmp;
  202. #define BOOST_ATOMIC_DETAIL_AARCH32_MO_INSN(ld_mo, st_mo)\
  203. __asm__ __volatile__\
  204. (\
  205. "1:\n\t"\
  206. "ld" ld_mo "exb %[result], %[storage]\n\t"\
  207. "and %[result], %[value]\n\t"\
  208. "st" st_mo "exb %[tmp], %[result], %[storage]\n\t"\
  209. "teq %[tmp], #0\n\t"\
  210. "bne 1b\n\t"\
  211. : [result] "=&r" (result), [tmp] "=&r" (tmp), [storage] "+Q" (storage)\
  212. : [value] "Ir" (v)\
  213. : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC_COMMA "memory"\
  214. );
  215. BOOST_ATOMIC_DETAIL_AARCH32_MO_SWITCH(order)
  216. #undef BOOST_ATOMIC_DETAIL_AARCH32_MO_INSN
  217. BOOST_ATOMIC_DETAIL_TSAN_ACQUIRE(&storage, order);
  218. return result;
  219. }
  220. static BOOST_FORCEINLINE storage_type bitwise_or(storage_type volatile& storage, storage_type v, memory_order order) noexcept
  221. {
  222. BOOST_ATOMIC_DETAIL_TSAN_RELEASE(&storage, order);
  223. storage_type result;
  224. std::uint32_t tmp;
  225. #define BOOST_ATOMIC_DETAIL_AARCH32_MO_INSN(ld_mo, st_mo)\
  226. __asm__ __volatile__\
  227. (\
  228. "1:\n\t"\
  229. "ld" ld_mo "exb %[result], %[storage]\n\t"\
  230. "orr %[result], %[value]\n\t"\
  231. "st" st_mo "exb %[tmp], %[result], %[storage]\n\t"\
  232. "teq %[tmp], #0\n\t"\
  233. "bne 1b\n\t"\
  234. : [result] "=&r" (result), [tmp] "=&r" (tmp), [storage] "+Q" (storage)\
  235. : [value] "Ir" (v)\
  236. : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC_COMMA "memory"\
  237. );
  238. BOOST_ATOMIC_DETAIL_AARCH32_MO_SWITCH(order)
  239. #undef BOOST_ATOMIC_DETAIL_AARCH32_MO_INSN
  240. BOOST_ATOMIC_DETAIL_TSAN_ACQUIRE(&storage, order);
  241. return result;
  242. }
  243. static BOOST_FORCEINLINE storage_type bitwise_xor(storage_type volatile& storage, storage_type v, memory_order order) noexcept
  244. {
  245. BOOST_ATOMIC_DETAIL_TSAN_RELEASE(&storage, order);
  246. storage_type result;
  247. std::uint32_t tmp;
  248. #define BOOST_ATOMIC_DETAIL_AARCH32_MO_INSN(ld_mo, st_mo)\
  249. __asm__ __volatile__\
  250. (\
  251. "1:\n\t"\
  252. "ld" ld_mo "exb %[result], %[storage]\n\t"\
  253. "eor %[result], %[value]\n\t"\
  254. "st" st_mo "exb %[tmp], %[result], %[storage]\n\t"\
  255. "teq %[tmp], #0\n\t"\
  256. "bne 1b\n\t"\
  257. : [result] "=&r" (result), [tmp] "=&r" (tmp), [storage] "+Q" (storage)\
  258. : [value] "Ir" (v)\
  259. : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC_COMMA "memory"\
  260. );
  261. BOOST_ATOMIC_DETAIL_AARCH32_MO_SWITCH(order)
  262. #undef BOOST_ATOMIC_DETAIL_AARCH32_MO_INSN
  263. BOOST_ATOMIC_DETAIL_TSAN_ACQUIRE(&storage, order);
  264. return result;
  265. }
  266. static BOOST_FORCEINLINE storage_type fetch_complement(storage_type volatile& storage, memory_order order) noexcept
  267. {
  268. BOOST_ATOMIC_DETAIL_TSAN_RELEASE(&storage, order);
  269. storage_type original, result;
  270. std::uint32_t tmp;
  271. #define BOOST_ATOMIC_DETAIL_AARCH32_MO_INSN(ld_mo, st_mo)\
  272. __asm__ __volatile__\
  273. (\
  274. "1:\n\t"\
  275. "ld" ld_mo "exb %[original], %[storage]\n\t"\
  276. "mvn %[result], %[original]\n\t"\
  277. "st" st_mo "exb %[tmp], %[result], %[storage]\n\t"\
  278. "teq %[tmp], #0\n\t"\
  279. "bne 1b\n\t"\
  280. : [original] "=&r" (original), [result] "=&r" (result), [tmp] "=&r" (tmp), [storage] "+Q" (storage)\
  281. : \
  282. : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC_COMMA "memory"\
  283. );
  284. BOOST_ATOMIC_DETAIL_AARCH32_MO_SWITCH(order)
  285. #undef BOOST_ATOMIC_DETAIL_AARCH32_MO_INSN
  286. BOOST_ATOMIC_DETAIL_TSAN_ACQUIRE(&storage, order);
  287. return original;
  288. }
  289. static BOOST_FORCEINLINE storage_type bitwise_complement(storage_type volatile& storage, memory_order order) noexcept
  290. {
  291. BOOST_ATOMIC_DETAIL_TSAN_RELEASE(&storage, order);
  292. storage_type result;
  293. std::uint32_t tmp;
  294. #define BOOST_ATOMIC_DETAIL_AARCH32_MO_INSN(ld_mo, st_mo)\
  295. __asm__ __volatile__\
  296. (\
  297. "1:\n\t"\
  298. "ld" ld_mo "exb %[result], %[storage]\n\t"\
  299. "mvn %[result], %[result]\n\t"\
  300. "st" st_mo "exb %[tmp], %[result], %[storage]\n\t"\
  301. "teq %[tmp], #0\n\t"\
  302. "bne 1b\n\t"\
  303. : [result] "=&r" (result), [tmp] "=&r" (tmp), [storage] "+Q" (storage)\
  304. : \
  305. : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC_COMMA "memory"\
  306. );
  307. BOOST_ATOMIC_DETAIL_AARCH32_MO_SWITCH(order)
  308. #undef BOOST_ATOMIC_DETAIL_AARCH32_MO_INSN
  309. BOOST_ATOMIC_DETAIL_TSAN_ACQUIRE(&storage, order);
  310. return result;
  311. }
  312. };
  313. template< typename Base, bool Signed >
  314. struct extra_operations< Base, 1u, Signed, true > :
  315. public extra_operations_gcc_aarch32_common< extra_operations_gcc_aarch32< Base, 1u, Signed > >
  316. {
  317. };
  318. template< typename Base, bool Signed >
  319. struct extra_operations_gcc_aarch32< Base, 2u, Signed > :
  320. public extra_operations_generic< Base, 2u, Signed >
  321. {
  322. using base_type = extra_operations_generic< Base, 2u, Signed >;
  323. using storage_type = typename base_type::storage_type;
  324. static BOOST_FORCEINLINE storage_type fetch_negate(storage_type volatile& storage, memory_order order) noexcept
  325. {
  326. BOOST_ATOMIC_DETAIL_TSAN_RELEASE(&storage, order);
  327. storage_type original, result;
  328. std::uint32_t tmp;
  329. #define BOOST_ATOMIC_DETAIL_AARCH32_MO_INSN(ld_mo, st_mo)\
  330. __asm__ __volatile__\
  331. (\
  332. "1:\n\t"\
  333. "ld" ld_mo "exh %[original], %[storage]\n\t"\
  334. "rsb %[result], %[original], #0\n\t"\
  335. "st" st_mo "exh %[tmp], %[result], %[storage]\n\t"\
  336. "teq %[tmp], #0\n\t"\
  337. "bne 1b\n\t"\
  338. : [original] "=&r" (original), [result] "=&r" (result), [tmp] "=&r" (tmp), [storage] "+Q" (storage)\
  339. : \
  340. : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC_COMMA "memory"\
  341. );
  342. BOOST_ATOMIC_DETAIL_AARCH32_MO_SWITCH(order)
  343. #undef BOOST_ATOMIC_DETAIL_AARCH32_MO_INSN
  344. BOOST_ATOMIC_DETAIL_TSAN_ACQUIRE(&storage, order);
  345. return original;
  346. }
  347. static BOOST_FORCEINLINE storage_type negate(storage_type volatile& storage, memory_order order) noexcept
  348. {
  349. BOOST_ATOMIC_DETAIL_TSAN_RELEASE(&storage, order);
  350. storage_type result;
  351. std::uint32_t tmp;
  352. #define BOOST_ATOMIC_DETAIL_AARCH32_MO_INSN(ld_mo, st_mo)\
  353. __asm__ __volatile__\
  354. (\
  355. "1:\n\t"\
  356. "ld" ld_mo "exh %[result], %[storage]\n\t"\
  357. "rsb %[result], #0\n\t"\
  358. "st" st_mo "exh %[tmp], %[result], %[storage]\n\t"\
  359. "teq %[tmp], #0\n\t"\
  360. "bne 1b\n\t"\
  361. : [result] "=&r" (result), [tmp] "=&r" (tmp), [storage] "+Q" (storage)\
  362. : \
  363. : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC_COMMA "memory"\
  364. );
  365. BOOST_ATOMIC_DETAIL_AARCH32_MO_SWITCH(order)
  366. #undef BOOST_ATOMIC_DETAIL_AARCH32_MO_INSN
  367. BOOST_ATOMIC_DETAIL_TSAN_ACQUIRE(&storage, order);
  368. return result;
  369. }
  370. static BOOST_FORCEINLINE storage_type add(storage_type volatile& storage, storage_type v, memory_order order) noexcept
  371. {
  372. BOOST_ATOMIC_DETAIL_TSAN_RELEASE(&storage, order);
  373. storage_type result;
  374. std::uint32_t tmp;
  375. #define BOOST_ATOMIC_DETAIL_AARCH32_MO_INSN(ld_mo, st_mo)\
  376. __asm__ __volatile__\
  377. (\
  378. "1:\n\t"\
  379. "ld" ld_mo "exh %[result], %[storage]\n\t"\
  380. "add %[result], %[value]\n\t"\
  381. "st" st_mo "exh %[tmp], %[result], %[storage]\n\t"\
  382. "teq %[tmp], #0\n\t"\
  383. "bne 1b\n\t"\
  384. : [result] "=&r" (result), [tmp] "=&r" (tmp), [storage] "+Q" (storage)\
  385. : [value] "Ir" (v)\
  386. : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC_COMMA "memory"\
  387. );
  388. BOOST_ATOMIC_DETAIL_AARCH32_MO_SWITCH(order)
  389. #undef BOOST_ATOMIC_DETAIL_AARCH32_MO_INSN
  390. BOOST_ATOMIC_DETAIL_TSAN_ACQUIRE(&storage, order);
  391. return result;
  392. }
  393. static BOOST_FORCEINLINE storage_type sub(storage_type volatile& storage, storage_type v, memory_order order) noexcept
  394. {
  395. BOOST_ATOMIC_DETAIL_TSAN_RELEASE(&storage, order);
  396. storage_type result;
  397. std::uint32_t tmp;
  398. #define BOOST_ATOMIC_DETAIL_AARCH32_MO_INSN(ld_mo, st_mo)\
  399. __asm__ __volatile__\
  400. (\
  401. "1:\n\t"\
  402. "ld" ld_mo "exh %[result], %[storage]\n\t"\
  403. "sub %[result], %[value]\n\t"\
  404. "st" st_mo "exh %[tmp], %[result], %[storage]\n\t"\
  405. "teq %[tmp], #0\n\t"\
  406. "bne 1b\n\t"\
  407. : [result] "=&r" (result), [tmp] "=&r" (tmp), [storage] "+Q" (storage)\
  408. : [value] "Ir" (v)\
  409. : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC_COMMA "memory"\
  410. );
  411. BOOST_ATOMIC_DETAIL_AARCH32_MO_SWITCH(order)
  412. #undef BOOST_ATOMIC_DETAIL_AARCH32_MO_INSN
  413. BOOST_ATOMIC_DETAIL_TSAN_ACQUIRE(&storage, order);
  414. return result;
  415. }
  416. static BOOST_FORCEINLINE storage_type bitwise_and(storage_type volatile& storage, storage_type v, memory_order order) noexcept
  417. {
  418. BOOST_ATOMIC_DETAIL_TSAN_RELEASE(&storage, order);
  419. storage_type result;
  420. std::uint32_t tmp;
  421. #define BOOST_ATOMIC_DETAIL_AARCH32_MO_INSN(ld_mo, st_mo)\
  422. __asm__ __volatile__\
  423. (\
  424. "1:\n\t"\
  425. "ld" ld_mo "exh %[result], %[storage]\n\t"\
  426. "and %[result], %[value]\n\t"\
  427. "st" st_mo "exh %[tmp], %[result], %[storage]\n\t"\
  428. "teq %[tmp], #0\n\t"\
  429. "bne 1b\n\t"\
  430. : [result] "=&r" (result), [tmp] "=&r" (tmp), [storage] "+Q" (storage)\
  431. : [value] "Ir" (v)\
  432. : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC_COMMA "memory"\
  433. );
  434. BOOST_ATOMIC_DETAIL_AARCH32_MO_SWITCH(order)
  435. #undef BOOST_ATOMIC_DETAIL_AARCH32_MO_INSN
  436. BOOST_ATOMIC_DETAIL_TSAN_ACQUIRE(&storage, order);
  437. return result;
  438. }
  439. static BOOST_FORCEINLINE storage_type bitwise_or(storage_type volatile& storage, storage_type v, memory_order order) noexcept
  440. {
  441. BOOST_ATOMIC_DETAIL_TSAN_RELEASE(&storage, order);
  442. storage_type result;
  443. std::uint32_t tmp;
  444. #define BOOST_ATOMIC_DETAIL_AARCH32_MO_INSN(ld_mo, st_mo)\
  445. __asm__ __volatile__\
  446. (\
  447. "1:\n\t"\
  448. "ld" ld_mo "exh %[result], %[storage]\n\t"\
  449. "orr %[result], %[value]\n\t"\
  450. "st" st_mo "exh %[tmp], %[result], %[storage]\n\t"\
  451. "teq %[tmp], #0\n\t"\
  452. "bne 1b\n\t"\
  453. : [result] "=&r" (result), [tmp] "=&r" (tmp), [storage] "+Q" (storage)\
  454. : [value] "Ir" (v)\
  455. : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC_COMMA "memory"\
  456. );
  457. BOOST_ATOMIC_DETAIL_AARCH32_MO_SWITCH(order)
  458. #undef BOOST_ATOMIC_DETAIL_AARCH32_MO_INSN
  459. BOOST_ATOMIC_DETAIL_TSAN_ACQUIRE(&storage, order);
  460. return result;
  461. }
  462. static BOOST_FORCEINLINE storage_type bitwise_xor(storage_type volatile& storage, storage_type v, memory_order order) noexcept
  463. {
  464. BOOST_ATOMIC_DETAIL_TSAN_RELEASE(&storage, order);
  465. storage_type result;
  466. std::uint32_t tmp;
  467. #define BOOST_ATOMIC_DETAIL_AARCH32_MO_INSN(ld_mo, st_mo)\
  468. __asm__ __volatile__\
  469. (\
  470. "1:\n\t"\
  471. "ld" ld_mo "exh %[result], %[storage]\n\t"\
  472. "eor %[result], %[value]\n\t"\
  473. "st" st_mo "exh %[tmp], %[result], %[storage]\n\t"\
  474. "teq %[tmp], #0\n\t"\
  475. "bne 1b\n\t"\
  476. : [result] "=&r" (result), [tmp] "=&r" (tmp), [storage] "+Q" (storage)\
  477. : [value] "Ir" (v)\
  478. : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC_COMMA "memory"\
  479. );
  480. BOOST_ATOMIC_DETAIL_AARCH32_MO_SWITCH(order)
  481. #undef BOOST_ATOMIC_DETAIL_AARCH32_MO_INSN
  482. BOOST_ATOMIC_DETAIL_TSAN_ACQUIRE(&storage, order);
  483. return result;
  484. }
  485. static BOOST_FORCEINLINE storage_type fetch_complement(storage_type volatile& storage, memory_order order) noexcept
  486. {
  487. BOOST_ATOMIC_DETAIL_TSAN_RELEASE(&storage, order);
  488. storage_type original, result;
  489. std::uint32_t tmp;
  490. #define BOOST_ATOMIC_DETAIL_AARCH32_MO_INSN(ld_mo, st_mo)\
  491. __asm__ __volatile__\
  492. (\
  493. "1:\n\t"\
  494. "ld" ld_mo "exh %[original], %[storage]\n\t"\
  495. "mvn %[result], %[original]\n\t"\
  496. "st" st_mo "exh %[tmp], %[result], %[storage]\n\t"\
  497. "teq %[tmp], #0\n\t"\
  498. "bne 1b\n\t"\
  499. : [original] "=&r" (original), [result] "=&r" (result), [tmp] "=&r" (tmp), [storage] "+Q" (storage)\
  500. : \
  501. : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC_COMMA "memory"\
  502. );
  503. BOOST_ATOMIC_DETAIL_AARCH32_MO_SWITCH(order)
  504. #undef BOOST_ATOMIC_DETAIL_AARCH32_MO_INSN
  505. BOOST_ATOMIC_DETAIL_TSAN_ACQUIRE(&storage, order);
  506. return original;
  507. }
  508. static BOOST_FORCEINLINE storage_type bitwise_complement(storage_type volatile& storage, memory_order order) noexcept
  509. {
  510. BOOST_ATOMIC_DETAIL_TSAN_RELEASE(&storage, order);
  511. storage_type result;
  512. std::uint32_t tmp;
  513. #define BOOST_ATOMIC_DETAIL_AARCH32_MO_INSN(ld_mo, st_mo)\
  514. __asm__ __volatile__\
  515. (\
  516. "1:\n\t"\
  517. "ld" ld_mo "exh %[result], %[storage]\n\t"\
  518. "mvn %[result], %[result]\n\t"\
  519. "st" st_mo "exh %[tmp], %[result], %[storage]\n\t"\
  520. "teq %[tmp], #0\n\t"\
  521. "bne 1b\n\t"\
  522. : [result] "=&r" (result), [tmp] "=&r" (tmp), [storage] "+Q" (storage)\
  523. : \
  524. : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC_COMMA "memory"\
  525. );
  526. BOOST_ATOMIC_DETAIL_AARCH32_MO_SWITCH(order)
  527. #undef BOOST_ATOMIC_DETAIL_AARCH32_MO_INSN
  528. BOOST_ATOMIC_DETAIL_TSAN_ACQUIRE(&storage, order);
  529. return result;
  530. }
  531. };
  532. template< typename Base, bool Signed >
  533. struct extra_operations< Base, 2u, Signed, true > :
  534. public extra_operations_gcc_aarch32_common< extra_operations_gcc_aarch32< Base, 2u, Signed > >
  535. {
  536. };
  537. template< typename Base, bool Signed >
  538. struct extra_operations_gcc_aarch32< Base, 4u, Signed > :
  539. public extra_operations_generic< Base, 4u, Signed >
  540. {
  541. using base_type = extra_operations_generic< Base, 4u, Signed >;
  542. using storage_type = typename base_type::storage_type;
  543. static BOOST_FORCEINLINE storage_type fetch_negate(storage_type volatile& storage, memory_order order) noexcept
  544. {
  545. BOOST_ATOMIC_DETAIL_TSAN_RELEASE(&storage, order);
  546. storage_type original, result;
  547. std::uint32_t tmp;
  548. #define BOOST_ATOMIC_DETAIL_AARCH32_MO_INSN(ld_mo, st_mo)\
  549. __asm__ __volatile__\
  550. (\
  551. "1:\n\t"\
  552. "ld" ld_mo "ex %[original], %[storage]\n\t"\
  553. "rsb %[result], %[original], #0\n\t"\
  554. "st" st_mo "ex %[tmp], %[result], %[storage]\n\t"\
  555. "teq %[tmp], #0\n\t"\
  556. "bne 1b\n\t"\
  557. : [original] "=&r" (original), [result] "=&r" (result), [tmp] "=&r" (tmp), [storage] "+Q" (storage)\
  558. : \
  559. : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC_COMMA "memory"\
  560. );
  561. BOOST_ATOMIC_DETAIL_AARCH32_MO_SWITCH(order)
  562. #undef BOOST_ATOMIC_DETAIL_AARCH32_MO_INSN
  563. BOOST_ATOMIC_DETAIL_TSAN_ACQUIRE(&storage, order);
  564. return original;
  565. }
  566. static BOOST_FORCEINLINE storage_type negate(storage_type volatile& storage, memory_order order) noexcept
  567. {
  568. BOOST_ATOMIC_DETAIL_TSAN_RELEASE(&storage, order);
  569. storage_type result;
  570. std::uint32_t tmp;
  571. #define BOOST_ATOMIC_DETAIL_AARCH32_MO_INSN(ld_mo, st_mo)\
  572. __asm__ __volatile__\
  573. (\
  574. "1:\n\t"\
  575. "ld" ld_mo "ex %[result], %[storage]\n\t"\
  576. "rsb %[result], #0\n\t"\
  577. "st" st_mo "ex %[tmp], %[result], %[storage]\n\t"\
  578. "teq %[tmp], #0\n\t"\
  579. "bne 1b\n\t"\
  580. : [result] "=&r" (result), [tmp] "=&r" (tmp), [storage] "+Q" (storage)\
  581. : \
  582. : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC_COMMA "memory"\
  583. );
  584. BOOST_ATOMIC_DETAIL_AARCH32_MO_SWITCH(order)
  585. #undef BOOST_ATOMIC_DETAIL_AARCH32_MO_INSN
  586. BOOST_ATOMIC_DETAIL_TSAN_ACQUIRE(&storage, order);
  587. return result;
  588. }
  589. static BOOST_FORCEINLINE storage_type add(storage_type volatile& storage, storage_type v, memory_order order) noexcept
  590. {
  591. BOOST_ATOMIC_DETAIL_TSAN_RELEASE(&storage, order);
  592. storage_type result;
  593. std::uint32_t tmp;
  594. #define BOOST_ATOMIC_DETAIL_AARCH32_MO_INSN(ld_mo, st_mo)\
  595. __asm__ __volatile__\
  596. (\
  597. "1:\n\t"\
  598. "ld" ld_mo "ex %[result], %[storage]\n\t"\
  599. "add %[result], %[value]\n\t"\
  600. "st" st_mo "ex %[tmp], %[result], %[storage]\n\t"\
  601. "teq %[tmp], #0\n\t"\
  602. "bne 1b\n\t"\
  603. : [result] "=&r" (result), [tmp] "=&r" (tmp), [storage] "+Q" (storage)\
  604. : [value] "Ir" (v)\
  605. : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC_COMMA "memory"\
  606. );
  607. BOOST_ATOMIC_DETAIL_AARCH32_MO_SWITCH(order)
  608. #undef BOOST_ATOMIC_DETAIL_AARCH32_MO_INSN
  609. BOOST_ATOMIC_DETAIL_TSAN_ACQUIRE(&storage, order);
  610. return result;
  611. }
  612. static BOOST_FORCEINLINE storage_type sub(storage_type volatile& storage, storage_type v, memory_order order) noexcept
  613. {
  614. BOOST_ATOMIC_DETAIL_TSAN_RELEASE(&storage, order);
  615. storage_type result;
  616. std::uint32_t tmp;
  617. #define BOOST_ATOMIC_DETAIL_AARCH32_MO_INSN(ld_mo, st_mo)\
  618. __asm__ __volatile__\
  619. (\
  620. "1:\n\t"\
  621. "ld" ld_mo "ex %[result], %[storage]\n\t"\
  622. "sub %[result], %[value]\n\t"\
  623. "st" st_mo "ex %[tmp], %[result], %[storage]\n\t"\
  624. "teq %[tmp], #0\n\t"\
  625. "bne 1b\n\t"\
  626. : [result] "=&r" (result), [tmp] "=&r" (tmp), [storage] "+Q" (storage)\
  627. : [value] "Ir" (v)\
  628. : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC_COMMA "memory"\
  629. );
  630. BOOST_ATOMIC_DETAIL_AARCH32_MO_SWITCH(order)
  631. #undef BOOST_ATOMIC_DETAIL_AARCH32_MO_INSN
  632. BOOST_ATOMIC_DETAIL_TSAN_ACQUIRE(&storage, order);
  633. return result;
  634. }
  635. static BOOST_FORCEINLINE storage_type bitwise_and(storage_type volatile& storage, storage_type v, memory_order order) noexcept
  636. {
  637. BOOST_ATOMIC_DETAIL_TSAN_RELEASE(&storage, order);
  638. storage_type result;
  639. std::uint32_t tmp;
  640. #define BOOST_ATOMIC_DETAIL_AARCH32_MO_INSN(ld_mo, st_mo)\
  641. __asm__ __volatile__\
  642. (\
  643. "1:\n\t"\
  644. "ld" ld_mo "ex %[result], %[storage]\n\t"\
  645. "and %[result], %[value]\n\t"\
  646. "st" st_mo "ex %[tmp], %[result], %[storage]\n\t"\
  647. "teq %[tmp], #0\n\t"\
  648. "bne 1b\n\t"\
  649. : [result] "=&r" (result), [tmp] "=&r" (tmp), [storage] "+Q" (storage)\
  650. : [value] "Ir" (v)\
  651. : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC_COMMA "memory"\
  652. );
  653. BOOST_ATOMIC_DETAIL_AARCH32_MO_SWITCH(order)
  654. #undef BOOST_ATOMIC_DETAIL_AARCH32_MO_INSN
  655. BOOST_ATOMIC_DETAIL_TSAN_ACQUIRE(&storage, order);
  656. return result;
  657. }
  658. static BOOST_FORCEINLINE storage_type bitwise_or(storage_type volatile& storage, storage_type v, memory_order order) noexcept
  659. {
  660. BOOST_ATOMIC_DETAIL_TSAN_RELEASE(&storage, order);
  661. storage_type result;
  662. std::uint32_t tmp;
  663. #define BOOST_ATOMIC_DETAIL_AARCH32_MO_INSN(ld_mo, st_mo)\
  664. __asm__ __volatile__\
  665. (\
  666. "1:\n\t"\
  667. "ld" ld_mo "ex %[result], %[storage]\n\t"\
  668. "orr %[result], %[value]\n\t"\
  669. "st" st_mo "ex %[tmp], %[result], %[storage]\n\t"\
  670. "teq %[tmp], #0\n\t"\
  671. "bne 1b\n\t"\
  672. : [result] "=&r" (result), [tmp] "=&r" (tmp), [storage] "+Q" (storage)\
  673. : [value] "Ir" (v)\
  674. : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC_COMMA "memory"\
  675. );
  676. BOOST_ATOMIC_DETAIL_AARCH32_MO_SWITCH(order)
  677. #undef BOOST_ATOMIC_DETAIL_AARCH32_MO_INSN
  678. BOOST_ATOMIC_DETAIL_TSAN_ACQUIRE(&storage, order);
  679. return result;
  680. }
  681. static BOOST_FORCEINLINE storage_type bitwise_xor(storage_type volatile& storage, storage_type v, memory_order order) noexcept
  682. {
  683. BOOST_ATOMIC_DETAIL_TSAN_RELEASE(&storage, order);
  684. storage_type result;
  685. std::uint32_t tmp;
  686. #define BOOST_ATOMIC_DETAIL_AARCH32_MO_INSN(ld_mo, st_mo)\
  687. __asm__ __volatile__\
  688. (\
  689. "1:\n\t"\
  690. "ld" ld_mo "ex %[result], %[storage]\n\t"\
  691. "eor %[result], %[value]\n\t"\
  692. "st" st_mo "ex %[tmp], %[result], %[storage]\n\t"\
  693. "teq %[tmp], #0\n\t"\
  694. "bne 1b\n\t"\
  695. : [result] "=&r" (result), [tmp] "=&r" (tmp), [storage] "+Q" (storage)\
  696. : [value] "Ir" (v)\
  697. : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC_COMMA "memory"\
  698. );
  699. BOOST_ATOMIC_DETAIL_AARCH32_MO_SWITCH(order)
  700. #undef BOOST_ATOMIC_DETAIL_AARCH32_MO_INSN
  701. BOOST_ATOMIC_DETAIL_TSAN_ACQUIRE(&storage, order);
  702. return result;
  703. }
  704. static BOOST_FORCEINLINE storage_type fetch_complement(storage_type volatile& storage, memory_order order) noexcept
  705. {
  706. BOOST_ATOMIC_DETAIL_TSAN_RELEASE(&storage, order);
  707. storage_type original, result;
  708. std::uint32_t tmp;
  709. #define BOOST_ATOMIC_DETAIL_AARCH32_MO_INSN(ld_mo, st_mo)\
  710. __asm__ __volatile__\
  711. (\
  712. "1:\n\t"\
  713. "ld" ld_mo "ex %[original], %[storage]\n\t"\
  714. "mvn %[result], %[original]\n\t"\
  715. "st" st_mo "ex %[tmp], %[result], %[storage]\n\t"\
  716. "teq %[tmp], #0\n\t"\
  717. "bne 1b\n\t"\
  718. : [original] "=&r" (original), [result] "=&r" (result), [tmp] "=&r" (tmp), [storage] "+Q" (storage)\
  719. : \
  720. : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC_COMMA "memory"\
  721. );
  722. BOOST_ATOMIC_DETAIL_AARCH32_MO_SWITCH(order)
  723. #undef BOOST_ATOMIC_DETAIL_AARCH32_MO_INSN
  724. BOOST_ATOMIC_DETAIL_TSAN_ACQUIRE(&storage, order);
  725. return original;
  726. }
  727. static BOOST_FORCEINLINE storage_type bitwise_complement(storage_type volatile& storage, memory_order order) noexcept
  728. {
  729. BOOST_ATOMIC_DETAIL_TSAN_RELEASE(&storage, order);
  730. storage_type result;
  731. std::uint32_t tmp;
  732. #define BOOST_ATOMIC_DETAIL_AARCH32_MO_INSN(ld_mo, st_mo)\
  733. __asm__ __volatile__\
  734. (\
  735. "1:\n\t"\
  736. "ld" ld_mo "ex %[result], %[storage]\n\t"\
  737. "mvn %[result], %[result]\n\t"\
  738. "st" st_mo "ex %[tmp], %[result], %[storage]\n\t"\
  739. "teq %[tmp], #0\n\t"\
  740. "bne 1b\n\t"\
  741. : [result] "=&r" (result), [tmp] "=&r" (tmp), [storage] "+Q" (storage)\
  742. : \
  743. : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC_COMMA "memory"\
  744. );
  745. BOOST_ATOMIC_DETAIL_AARCH32_MO_SWITCH(order)
  746. #undef BOOST_ATOMIC_DETAIL_AARCH32_MO_INSN
  747. BOOST_ATOMIC_DETAIL_TSAN_ACQUIRE(&storage, order);
  748. return result;
  749. }
  750. };
  751. template< typename Base, bool Signed >
  752. struct extra_operations< Base, 4u, Signed, true > :
  753. public extra_operations_gcc_aarch32_common< extra_operations_gcc_aarch32< Base, 4u, Signed > >
  754. {
  755. };
  756. template< typename Base, bool Signed >
  757. struct extra_operations_gcc_aarch32< Base, 8u, Signed > :
  758. public extra_operations_generic< Base, 8u, Signed >
  759. {
  760. using base_type = extra_operations_generic< Base, 8u, Signed >;
  761. using storage_type = typename base_type::storage_type;
  762. static BOOST_FORCEINLINE storage_type fetch_negate(storage_type volatile& storage, memory_order order) noexcept
  763. {
  764. BOOST_ATOMIC_DETAIL_TSAN_RELEASE(&storage, order);
  765. storage_type original, result;
  766. std::uint32_t tmp;
  767. #define BOOST_ATOMIC_DETAIL_AARCH32_MO_INSN(ld_mo, st_mo)\
  768. __asm__ __volatile__\
  769. (\
  770. "1:\n\t"\
  771. "ld" ld_mo "exd %0, %H0, %2\n\t"\
  772. "mvn %3, %0\n\t"\
  773. "mvn %H3, %H0\n\t"\
  774. "adds " BOOST_ATOMIC_DETAIL_AARCH32_ASM_ARG_LO(3) ", #1\n\t"\
  775. "adc " BOOST_ATOMIC_DETAIL_AARCH32_ASM_ARG_HI(3) ", #0\n\t"\
  776. "st" st_mo "exd %1, %3, %H3, %2\n\t"\
  777. "teq %1, #0\n\t"\
  778. "bne 1b\n\t"\
  779. : "=&r" (original), "=&r" (tmp), "+Q" (storage), "=&r" (result)\
  780. : \
  781. : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC_COMMA "memory"\
  782. );
  783. BOOST_ATOMIC_DETAIL_AARCH32_MO_SWITCH(order)
  784. #undef BOOST_ATOMIC_DETAIL_AARCH32_MO_INSN
  785. BOOST_ATOMIC_DETAIL_TSAN_ACQUIRE(&storage, order);
  786. return original;
  787. }
  788. static BOOST_FORCEINLINE storage_type negate(storage_type volatile& storage, memory_order order) noexcept
  789. {
  790. BOOST_ATOMIC_DETAIL_TSAN_RELEASE(&storage, order);
  791. storage_type result;
  792. std::uint32_t tmp;
  793. #define BOOST_ATOMIC_DETAIL_AARCH32_MO_INSN(ld_mo, st_mo)\
  794. __asm__ __volatile__\
  795. (\
  796. "1:\n\t"\
  797. "ld" ld_mo "exd %0, %H0, %2\n\t"\
  798. "mvn %0, %0\n\t"\
  799. "mvn %H0, %H0\n\t"\
  800. "adds " BOOST_ATOMIC_DETAIL_AARCH32_ASM_ARG_LO(0) ", #1\n\t"\
  801. "adc " BOOST_ATOMIC_DETAIL_AARCH32_ASM_ARG_HI(0) ", #0\n\t"\
  802. "st" st_mo "exd %1, %0, %H0, %2\n\t"\
  803. "teq %1, #0\n\t"\
  804. "bne 1b\n\t"\
  805. : "=&r" (result), "=&r" (tmp), "+Q" (storage)\
  806. : \
  807. : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC_COMMA "memory"\
  808. );
  809. BOOST_ATOMIC_DETAIL_AARCH32_MO_SWITCH(order)
  810. #undef BOOST_ATOMIC_DETAIL_AARCH32_MO_INSN
  811. BOOST_ATOMIC_DETAIL_TSAN_ACQUIRE(&storage, order);
  812. return result;
  813. }
  814. static BOOST_FORCEINLINE storage_type add(storage_type volatile& storage, storage_type v, memory_order order) noexcept
  815. {
  816. BOOST_ATOMIC_DETAIL_TSAN_RELEASE(&storage, order);
  817. storage_type result;
  818. std::uint32_t tmp;
  819. #define BOOST_ATOMIC_DETAIL_AARCH32_MO_INSN(ld_mo, st_mo)\
  820. __asm__ __volatile__\
  821. (\
  822. "1:\n\t"\
  823. "ld" ld_mo "exd %0, %H0, %2\n\t"\
  824. "adds " BOOST_ATOMIC_DETAIL_AARCH32_ASM_ARG_LO(0) ", " BOOST_ATOMIC_DETAIL_AARCH32_ASM_ARG_LO(3) "\n\t"\
  825. "adc " BOOST_ATOMIC_DETAIL_AARCH32_ASM_ARG_HI(0) ", " BOOST_ATOMIC_DETAIL_AARCH32_ASM_ARG_HI(3) "\n\t"\
  826. "st" st_mo "exd %1, %0, %H0, %2\n\t"\
  827. "teq %1, #0\n\t"\
  828. "bne 1b\n\t"\
  829. : "=&r" (result), "=&r" (tmp), "+Q" (storage)\
  830. : "r" (v)\
  831. : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC_COMMA "memory"\
  832. );
  833. BOOST_ATOMIC_DETAIL_AARCH32_MO_SWITCH(order)
  834. #undef BOOST_ATOMIC_DETAIL_AARCH32_MO_INSN
  835. BOOST_ATOMIC_DETAIL_TSAN_ACQUIRE(&storage, order);
  836. return result;
  837. }
  838. static BOOST_FORCEINLINE storage_type sub(storage_type volatile& storage, storage_type v, memory_order order) noexcept
  839. {
  840. BOOST_ATOMIC_DETAIL_TSAN_RELEASE(&storage, order);
  841. storage_type result;
  842. std::uint32_t tmp;
  843. #define BOOST_ATOMIC_DETAIL_AARCH32_MO_INSN(ld_mo, st_mo)\
  844. __asm__ __volatile__\
  845. (\
  846. "1:\n\t"\
  847. "ld" ld_mo "exd %0, %H0, %2\n\t"\
  848. "subs " BOOST_ATOMIC_DETAIL_AARCH32_ASM_ARG_LO(0) ", " BOOST_ATOMIC_DETAIL_AARCH32_ASM_ARG_LO(3) "\n\t"\
  849. "sbc " BOOST_ATOMIC_DETAIL_AARCH32_ASM_ARG_HI(0) ", " BOOST_ATOMIC_DETAIL_AARCH32_ASM_ARG_HI(3) "\n\t"\
  850. "st" st_mo "exd %1, %0, %H0, %2\n\t"\
  851. "teq %1, #0\n\t"\
  852. "bne 1b\n\t"\
  853. : "=&r" (result), "=&r" (tmp), "+Q" (storage)\
  854. : "r" (v)\
  855. : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC_COMMA "memory"\
  856. );
  857. BOOST_ATOMIC_DETAIL_AARCH32_MO_SWITCH(order)
  858. #undef BOOST_ATOMIC_DETAIL_AARCH32_MO_INSN
  859. BOOST_ATOMIC_DETAIL_TSAN_ACQUIRE(&storage, order);
  860. return result;
  861. }
  862. static BOOST_FORCEINLINE storage_type bitwise_and(storage_type volatile& storage, storage_type v, memory_order order) noexcept
  863. {
  864. BOOST_ATOMIC_DETAIL_TSAN_RELEASE(&storage, order);
  865. storage_type result;
  866. std::uint32_t tmp;
  867. #define BOOST_ATOMIC_DETAIL_AARCH32_MO_INSN(ld_mo, st_mo)\
  868. __asm__ __volatile__\
  869. (\
  870. "1:\n\t"\
  871. "ld" ld_mo "exd %0, %H0, %2\n\t"\
  872. "and %0, %3\n\t"\
  873. "and %H0, %H3\n\t"\
  874. "st" st_mo "exd %1, %0, %H0, %2\n\t"\
  875. "teq %1, #0\n\t"\
  876. "bne 1b\n\t"\
  877. : "=&r" (result), "=&r" (tmp), "+Q" (storage)\
  878. : "r" (v)\
  879. : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC_COMMA "memory"\
  880. );
  881. BOOST_ATOMIC_DETAIL_AARCH32_MO_SWITCH(order)
  882. #undef BOOST_ATOMIC_DETAIL_AARCH32_MO_INSN
  883. BOOST_ATOMIC_DETAIL_TSAN_ACQUIRE(&storage, order);
  884. return result;
  885. }
  886. static BOOST_FORCEINLINE storage_type bitwise_or(storage_type volatile& storage, storage_type v, memory_order order) noexcept
  887. {
  888. BOOST_ATOMIC_DETAIL_TSAN_RELEASE(&storage, order);
  889. storage_type result;
  890. std::uint32_t tmp;
  891. #define BOOST_ATOMIC_DETAIL_AARCH32_MO_INSN(ld_mo, st_mo)\
  892. __asm__ __volatile__\
  893. (\
  894. "1:\n\t"\
  895. "ld" ld_mo "exd %0, %H0, %2\n\t"\
  896. "orr %0, %3\n\t"\
  897. "orr %H0, %H3\n\t"\
  898. "st" st_mo "exd %1, %0, %H0, %2\n\t"\
  899. "teq %1, #0\n\t"\
  900. "bne 1b\n\t"\
  901. : "=&r" (result), "=&r" (tmp), "+Q" (storage)\
  902. : "r" (v)\
  903. : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC_COMMA "memory"\
  904. );
  905. BOOST_ATOMIC_DETAIL_AARCH32_MO_SWITCH(order)
  906. #undef BOOST_ATOMIC_DETAIL_AARCH32_MO_INSN
  907. BOOST_ATOMIC_DETAIL_TSAN_ACQUIRE(&storage, order);
  908. return result;
  909. }
  910. static BOOST_FORCEINLINE storage_type bitwise_xor(storage_type volatile& storage, storage_type v, memory_order order) noexcept
  911. {
  912. BOOST_ATOMIC_DETAIL_TSAN_RELEASE(&storage, order);
  913. storage_type result;
  914. std::uint32_t tmp;
  915. #define BOOST_ATOMIC_DETAIL_AARCH32_MO_INSN(ld_mo, st_mo)\
  916. __asm__ __volatile__\
  917. (\
  918. "1:\n\t"\
  919. "ld" ld_mo "exd %0, %H0, %2\n\t"\
  920. "eor %0, %3\n\t"\
  921. "eor %H0, %H3\n\t"\
  922. "st" st_mo "exd %1, %0, %H0, %2\n\t"\
  923. "teq %1, #0\n\t"\
  924. "bne 1b\n\t"\
  925. : "=&r" (result), "=&r" (tmp), "+Q" (storage)\
  926. : "r" (v)\
  927. : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC_COMMA "memory"\
  928. );
  929. BOOST_ATOMIC_DETAIL_AARCH32_MO_SWITCH(order)
  930. #undef BOOST_ATOMIC_DETAIL_AARCH32_MO_INSN
  931. BOOST_ATOMIC_DETAIL_TSAN_ACQUIRE(&storage, order);
  932. return result;
  933. }
  934. static BOOST_FORCEINLINE storage_type fetch_complement(storage_type volatile& storage, memory_order order) noexcept
  935. {
  936. BOOST_ATOMIC_DETAIL_TSAN_RELEASE(&storage, order);
  937. storage_type original, result;
  938. std::uint32_t tmp;
  939. #define BOOST_ATOMIC_DETAIL_AARCH32_MO_INSN(ld_mo, st_mo)\
  940. __asm__ __volatile__\
  941. (\
  942. "1:\n\t"\
  943. "ld" ld_mo "exd %0, %H0, %2\n\t"\
  944. "mvn %3, %0\n\t"\
  945. "mvn %H3, %H0\n\t"\
  946. "st" st_mo "exd %1, %3, %H3, %2\n\t"\
  947. "teq %1, #0\n\t"\
  948. "bne 1b\n\t"\
  949. : "=&r" (original), "=&r" (tmp), "+Q" (storage), "=&r" (result)\
  950. : \
  951. : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC_COMMA "memory"\
  952. );
  953. BOOST_ATOMIC_DETAIL_AARCH32_MO_SWITCH(order)
  954. #undef BOOST_ATOMIC_DETAIL_AARCH32_MO_INSN
  955. BOOST_ATOMIC_DETAIL_TSAN_ACQUIRE(&storage, order);
  956. return original;
  957. }
  958. static BOOST_FORCEINLINE storage_type bitwise_complement(storage_type volatile& storage, memory_order order) noexcept
  959. {
  960. BOOST_ATOMIC_DETAIL_TSAN_RELEASE(&storage, order);
  961. storage_type result;
  962. std::uint32_t tmp;
  963. #define BOOST_ATOMIC_DETAIL_AARCH32_MO_INSN(ld_mo, st_mo)\
  964. __asm__ __volatile__\
  965. (\
  966. "1:\n\t"\
  967. "ld" ld_mo "exd %0, %H0, %2\n\t"\
  968. "mvn %0, %0\n\t"\
  969. "mvn %H0, %H0\n\t"\
  970. "st" st_mo "exd %1, %0, %H0, %2\n\t"\
  971. "teq %1, #0\n\t"\
  972. "bne 1b\n\t"\
  973. : "=&r" (result), "=&r" (tmp), "+Q" (storage)\
  974. : \
  975. : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC_COMMA "memory"\
  976. );
  977. BOOST_ATOMIC_DETAIL_AARCH32_MO_SWITCH(order)
  978. #undef BOOST_ATOMIC_DETAIL_AARCH32_MO_INSN
  979. BOOST_ATOMIC_DETAIL_TSAN_ACQUIRE(&storage, order);
  980. return result;
  981. }
  982. };
  983. template< typename Base, bool Signed >
  984. struct extra_operations< Base, 8u, Signed, true > :
  985. public extra_operations_gcc_aarch32_common< extra_operations_gcc_aarch32< Base, 8u, Signed > >
  986. {
  987. };
  988. } // namespace detail
  989. } // namespace atomics
  990. } // namespace boost
  991. #include <boost/atomic/detail/footer.hpp>
  992. #endif // BOOST_ATOMIC_DETAIL_EXTRA_OPS_GCC_AARCH32_HPP_INCLUDED_