extra_ops_gcc_aarch32.hpp 40 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133
  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_