extra_ops_gcc_ppc.hpp 34 KB

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