ops_gcc_alpha.hpp 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876
  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) 2009 Helge Bahmann
  7. * Copyright (c) 2013 Tim Blechmann
  8. * Copyright (c) 2014 Andrey Semashev
  9. */
  10. /*!
  11. * \file atomic/detail/ops_gcc_alpha.hpp
  12. *
  13. * This header contains implementation of the \c operations template.
  14. */
  15. #ifndef BOOST_ATOMIC_DETAIL_OPS_GCC_ALPHA_HPP_INCLUDED_
  16. #define BOOST_ATOMIC_DETAIL_OPS_GCC_ALPHA_HPP_INCLUDED_
  17. #include <cstddef>
  18. #include <boost/memory_order.hpp>
  19. #include <boost/atomic/detail/config.hpp>
  20. #include <boost/atomic/detail/storage_type.hpp>
  21. #include <boost/atomic/detail/operations_fwd.hpp>
  22. #include <boost/atomic/capabilities.hpp>
  23. #ifdef BOOST_HAS_PRAGMA_ONCE
  24. #pragma once
  25. #endif
  26. namespace boost {
  27. namespace atomics {
  28. namespace detail {
  29. /*
  30. Refer to http://h71000.www7.hp.com/doc/82final/5601/5601pro_004.html
  31. (HP OpenVMS systems documentation) and the Alpha Architecture Reference Manual.
  32. */
  33. /*
  34. NB: The most natural thing would be to write the increment/decrement
  35. operators along the following lines:
  36. __asm__ __volatile__
  37. (
  38. "1: ldl_l %0,%1 \n"
  39. "addl %0,1,%0 \n"
  40. "stl_c %0,%1 \n"
  41. "beq %0,1b\n"
  42. : "=&b" (tmp)
  43. : "m" (value)
  44. : "cc"
  45. );
  46. However according to the comments on the HP website and matching
  47. comments in the Linux kernel sources this defies branch prediction,
  48. as the cpu assumes that backward branches are always taken; so
  49. instead copy the trick from the Linux kernel, introduce a forward
  50. branch and back again.
  51. I have, however, had a hard time measuring the difference between
  52. the two versions in microbenchmarks -- I am leaving it in nevertheless
  53. as it apparently does not hurt either.
  54. */
  55. struct gcc_alpha_operations_base
  56. {
  57. static BOOST_CONSTEXPR_OR_CONST bool full_cas_based = false;
  58. static BOOST_CONSTEXPR_OR_CONST bool is_always_lock_free = true;
  59. static BOOST_FORCEINLINE void fence_before(memory_order order) BOOST_NOEXCEPT
  60. {
  61. if ((static_cast< unsigned int >(order) & static_cast< unsigned int >(memory_order_release)) != 0u)
  62. __asm__ __volatile__ ("mb" ::: "memory");
  63. }
  64. static BOOST_FORCEINLINE void fence_after(memory_order order) BOOST_NOEXCEPT
  65. {
  66. if ((static_cast< unsigned int >(order) & (static_cast< unsigned int >(memory_order_consume) | static_cast< unsigned int >(memory_order_acquire))) != 0u)
  67. __asm__ __volatile__ ("mb" ::: "memory");
  68. }
  69. static BOOST_FORCEINLINE void fence_after_store(memory_order order) BOOST_NOEXCEPT
  70. {
  71. if (order == memory_order_seq_cst)
  72. __asm__ __volatile__ ("mb" ::: "memory");
  73. }
  74. };
  75. template< bool Signed >
  76. struct operations< 4u, Signed > :
  77. public gcc_alpha_operations_base
  78. {
  79. typedef typename make_storage_type< 4u >::type storage_type;
  80. typedef typename make_storage_type< 4u >::aligned aligned_storage_type;
  81. static BOOST_CONSTEXPR_OR_CONST std::size_t storage_size = 4u;
  82. static BOOST_CONSTEXPR_OR_CONST bool is_signed = Signed;
  83. static BOOST_FORCEINLINE void store(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
  84. {
  85. fence_before(order);
  86. storage = v;
  87. fence_after_store(order);
  88. }
  89. static BOOST_FORCEINLINE storage_type load(storage_type const volatile& storage, memory_order order) BOOST_NOEXCEPT
  90. {
  91. storage_type v = storage;
  92. fence_after(order);
  93. return v;
  94. }
  95. static BOOST_FORCEINLINE storage_type exchange(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
  96. {
  97. storage_type original, tmp;
  98. fence_before(order);
  99. __asm__ __volatile__
  100. (
  101. "1:\n"
  102. "mov %3, %1\n"
  103. "ldl_l %0, %2\n"
  104. "stl_c %1, %2\n"
  105. "beq %1, 2f\n"
  106. ".subsection 2\n"
  107. "2: br 1b\n"
  108. ".previous\n"
  109. : "=&r" (original), // %0
  110. "=&r" (tmp) // %1
  111. : "m" (storage), // %2
  112. "r" (v) // %3
  113. : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC
  114. );
  115. fence_after(order);
  116. return original;
  117. }
  118. static BOOST_FORCEINLINE bool compare_exchange_weak(
  119. storage_type volatile& storage, storage_type& expected, storage_type desired, memory_order success_order, memory_order failure_order) BOOST_NOEXCEPT
  120. {
  121. fence_before(success_order);
  122. int success;
  123. storage_type current;
  124. __asm__ __volatile__
  125. (
  126. "1:\n"
  127. "ldl_l %2, %4\n" // current = *(&storage)
  128. "cmpeq %2, %0, %3\n" // success = current == expected
  129. "mov %2, %0\n" // expected = current
  130. "beq %3, 2f\n" // if (success == 0) goto end
  131. "stl_c %1, %4\n" // storage = desired; desired = store succeeded
  132. "mov %1, %3\n" // success = desired
  133. "2:\n"
  134. : "+&r" (expected), // %0
  135. "+&r" (desired), // %1
  136. "=&r" (current), // %2
  137. "=&r" (success) // %3
  138. : "m" (storage) // %4
  139. : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC
  140. );
  141. if (success)
  142. fence_after(success_order);
  143. else
  144. fence_after(failure_order);
  145. return !!success;
  146. }
  147. static BOOST_FORCEINLINE bool compare_exchange_strong(
  148. storage_type volatile& storage, storage_type& expected, storage_type desired, memory_order success_order, memory_order failure_order) BOOST_NOEXCEPT
  149. {
  150. int success;
  151. storage_type current, tmp;
  152. fence_before(success_order);
  153. __asm__ __volatile__
  154. (
  155. "1:\n"
  156. "mov %5, %1\n" // tmp = desired
  157. "ldl_l %2, %4\n" // current = *(&storage)
  158. "cmpeq %2, %0, %3\n" // success = current == expected
  159. "mov %2, %0\n" // expected = current
  160. "beq %3, 2f\n" // if (success == 0) goto end
  161. "stl_c %1, %4\n" // storage = tmp; tmp = store succeeded
  162. "beq %1, 3f\n" // if (tmp == 0) goto retry
  163. "mov %1, %3\n" // success = tmp
  164. "2:\n"
  165. ".subsection 2\n"
  166. "3: br 1b\n"
  167. ".previous\n"
  168. : "+&r" (expected), // %0
  169. "=&r" (tmp), // %1
  170. "=&r" (current), // %2
  171. "=&r" (success) // %3
  172. : "m" (storage), // %4
  173. "r" (desired) // %5
  174. : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC
  175. );
  176. if (success)
  177. fence_after(success_order);
  178. else
  179. fence_after(failure_order);
  180. return !!success;
  181. }
  182. static BOOST_FORCEINLINE storage_type fetch_add(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
  183. {
  184. storage_type original, modified;
  185. fence_before(order);
  186. __asm__ __volatile__
  187. (
  188. "1:\n"
  189. "ldl_l %0, %2\n"
  190. "addl %0, %3, %1\n"
  191. "stl_c %1, %2\n"
  192. "beq %1, 2f\n"
  193. ".subsection 2\n"
  194. "2: br 1b\n"
  195. ".previous\n"
  196. : "=&r" (original), // %0
  197. "=&r" (modified) // %1
  198. : "m" (storage), // %2
  199. "r" (v) // %3
  200. : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC
  201. );
  202. fence_after(order);
  203. return original;
  204. }
  205. static BOOST_FORCEINLINE storage_type fetch_sub(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
  206. {
  207. storage_type original, modified;
  208. fence_before(order);
  209. __asm__ __volatile__
  210. (
  211. "1:\n"
  212. "ldl_l %0, %2\n"
  213. "subl %0, %3, %1\n"
  214. "stl_c %1, %2\n"
  215. "beq %1, 2f\n"
  216. ".subsection 2\n"
  217. "2: br 1b\n"
  218. ".previous\n"
  219. : "=&r" (original), // %0
  220. "=&r" (modified) // %1
  221. : "m" (storage), // %2
  222. "r" (v) // %3
  223. : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC
  224. );
  225. fence_after(order);
  226. return original;
  227. }
  228. static BOOST_FORCEINLINE storage_type fetch_and(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
  229. {
  230. storage_type original, modified;
  231. fence_before(order);
  232. __asm__ __volatile__
  233. (
  234. "1:\n"
  235. "ldl_l %0, %2\n"
  236. "and %0, %3, %1\n"
  237. "stl_c %1, %2\n"
  238. "beq %1, 2f\n"
  239. ".subsection 2\n"
  240. "2: br 1b\n"
  241. ".previous\n"
  242. : "=&r" (original), // %0
  243. "=&r" (modified) // %1
  244. : "m" (storage), // %2
  245. "r" (v) // %3
  246. : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC
  247. );
  248. fence_after(order);
  249. return original;
  250. }
  251. static BOOST_FORCEINLINE storage_type fetch_or(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
  252. {
  253. storage_type original, modified;
  254. fence_before(order);
  255. __asm__ __volatile__
  256. (
  257. "1:\n"
  258. "ldl_l %0, %2\n"
  259. "bis %0, %3, %1\n"
  260. "stl_c %1, %2\n"
  261. "beq %1, 2f\n"
  262. ".subsection 2\n"
  263. "2: br 1b\n"
  264. ".previous\n"
  265. : "=&r" (original), // %0
  266. "=&r" (modified) // %1
  267. : "m" (storage), // %2
  268. "r" (v) // %3
  269. : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC
  270. );
  271. fence_after(order);
  272. return original;
  273. }
  274. static BOOST_FORCEINLINE storage_type fetch_xor(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
  275. {
  276. storage_type original, modified;
  277. fence_before(order);
  278. __asm__ __volatile__
  279. (
  280. "1:\n"
  281. "ldl_l %0, %2\n"
  282. "xor %0, %3, %1\n"
  283. "stl_c %1, %2\n"
  284. "beq %1, 2f\n"
  285. ".subsection 2\n"
  286. "2: br 1b\n"
  287. ".previous\n"
  288. : "=&r" (original), // %0
  289. "=&r" (modified) // %1
  290. : "m" (storage), // %2
  291. "r" (v) // %3
  292. : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC
  293. );
  294. fence_after(order);
  295. return original;
  296. }
  297. static BOOST_FORCEINLINE bool test_and_set(storage_type volatile& storage, memory_order order) BOOST_NOEXCEPT
  298. {
  299. return !!exchange(storage, (storage_type)1, order);
  300. }
  301. static BOOST_FORCEINLINE void clear(storage_type volatile& storage, memory_order order) BOOST_NOEXCEPT
  302. {
  303. store(storage, 0, order);
  304. }
  305. };
  306. template< >
  307. struct operations< 1u, false > :
  308. public operations< 4u, false >
  309. {
  310. typedef operations< 4u, false > base_type;
  311. typedef base_type::storage_type storage_type;
  312. static BOOST_FORCEINLINE storage_type fetch_add(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
  313. {
  314. storage_type original, modified;
  315. fence_before(order);
  316. __asm__ __volatile__
  317. (
  318. "1:\n"
  319. "ldl_l %0, %2\n"
  320. "addl %0, %3, %1\n"
  321. "zapnot %1, #1, %1\n"
  322. "stl_c %1, %2\n"
  323. "beq %1, 2f\n"
  324. ".subsection 2\n"
  325. "2: br 1b\n"
  326. ".previous\n"
  327. : "=&r" (original), // %0
  328. "=&r" (modified) // %1
  329. : "m" (storage), // %2
  330. "r" (v) // %3
  331. : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC
  332. );
  333. fence_after(order);
  334. return original;
  335. }
  336. static BOOST_FORCEINLINE storage_type fetch_sub(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
  337. {
  338. storage_type original, modified;
  339. fence_before(order);
  340. __asm__ __volatile__
  341. (
  342. "1:\n"
  343. "ldl_l %0, %2\n"
  344. "subl %0, %3, %1\n"
  345. "zapnot %1, #1, %1\n"
  346. "stl_c %1, %2\n"
  347. "beq %1, 2f\n"
  348. ".subsection 2\n"
  349. "2: br 1b\n"
  350. ".previous\n"
  351. : "=&r" (original), // %0
  352. "=&r" (modified) // %1
  353. : "m" (storage), // %2
  354. "r" (v) // %3
  355. : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC
  356. );
  357. fence_after(order);
  358. return original;
  359. }
  360. };
  361. template< >
  362. struct operations< 1u, true > :
  363. public operations< 4u, true >
  364. {
  365. typedef operations< 4u, true > base_type;
  366. typedef base_type::storage_type storage_type;
  367. static BOOST_FORCEINLINE storage_type fetch_add(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
  368. {
  369. storage_type original, modified;
  370. fence_before(order);
  371. __asm__ __volatile__
  372. (
  373. "1:\n"
  374. "ldl_l %0, %2\n"
  375. "addl %0, %3, %1\n"
  376. "sextb %1, %1\n"
  377. "stl_c %1, %2\n"
  378. "beq %1, 2f\n"
  379. ".subsection 2\n"
  380. "2: br 1b\n"
  381. ".previous\n"
  382. : "=&r" (original), // %0
  383. "=&r" (modified) // %1
  384. : "m" (storage), // %2
  385. "r" (v) // %3
  386. : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC
  387. );
  388. fence_after(order);
  389. return original;
  390. }
  391. static BOOST_FORCEINLINE storage_type fetch_sub(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
  392. {
  393. storage_type original, modified;
  394. fence_before(order);
  395. __asm__ __volatile__
  396. (
  397. "1:\n"
  398. "ldl_l %0, %2\n"
  399. "subl %0, %3, %1\n"
  400. "sextb %1, %1\n"
  401. "stl_c %1, %2\n"
  402. "beq %1, 2f\n"
  403. ".subsection 2\n"
  404. "2: br 1b\n"
  405. ".previous\n"
  406. : "=&r" (original), // %0
  407. "=&r" (modified) // %1
  408. : "m" (storage), // %2
  409. "r" (v) // %3
  410. : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC
  411. );
  412. fence_after(order);
  413. return original;
  414. }
  415. };
  416. template< >
  417. struct operations< 2u, false > :
  418. public operations< 4u, false >
  419. {
  420. typedef operations< 4u, false > base_type;
  421. typedef base_type::storage_type storage_type;
  422. static BOOST_FORCEINLINE storage_type fetch_add(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
  423. {
  424. storage_type original, modified;
  425. fence_before(order);
  426. __asm__ __volatile__
  427. (
  428. "1:\n"
  429. "ldl_l %0, %2\n"
  430. "addl %0, %3, %1\n"
  431. "zapnot %1, #3, %1\n"
  432. "stl_c %1, %2\n"
  433. "beq %1, 2f\n"
  434. ".subsection 2\n"
  435. "2: br 1b\n"
  436. ".previous\n"
  437. : "=&r" (original), // %0
  438. "=&r" (modified) // %1
  439. : "m" (storage), // %2
  440. "r" (v) // %3
  441. : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC
  442. );
  443. fence_after(order);
  444. return original;
  445. }
  446. static BOOST_FORCEINLINE storage_type fetch_sub(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
  447. {
  448. storage_type original, modified;
  449. fence_before(order);
  450. __asm__ __volatile__
  451. (
  452. "1:\n"
  453. "ldl_l %0, %2\n"
  454. "subl %0, %3, %1\n"
  455. "zapnot %1, #3, %1\n"
  456. "stl_c %1, %2\n"
  457. "beq %1, 2f\n"
  458. ".subsection 2\n"
  459. "2: br 1b\n"
  460. ".previous\n"
  461. : "=&r" (original), // %0
  462. "=&r" (modified) // %1
  463. : "m" (storage), // %2
  464. "r" (v) // %3
  465. : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC
  466. );
  467. fence_after(order);
  468. return original;
  469. }
  470. };
  471. template< >
  472. struct operations< 2u, true > :
  473. public operations< 4u, true >
  474. {
  475. typedef operations< 4u, true > base_type;
  476. typedef base_type::storage_type storage_type;
  477. static BOOST_FORCEINLINE storage_type fetch_add(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
  478. {
  479. storage_type original, modified;
  480. fence_before(order);
  481. __asm__ __volatile__
  482. (
  483. "1:\n"
  484. "ldl_l %0, %2\n"
  485. "addl %0, %3, %1\n"
  486. "sextw %1, %1\n"
  487. "stl_c %1, %2\n"
  488. "beq %1, 2f\n"
  489. ".subsection 2\n"
  490. "2: br 1b\n"
  491. ".previous\n"
  492. : "=&r" (original), // %0
  493. "=&r" (modified) // %1
  494. : "m" (storage), // %2
  495. "r" (v) // %3
  496. : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC
  497. );
  498. fence_after(order);
  499. return original;
  500. }
  501. static BOOST_FORCEINLINE storage_type fetch_sub(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
  502. {
  503. storage_type original, modified;
  504. fence_before(order);
  505. __asm__ __volatile__
  506. (
  507. "1:\n"
  508. "ldl_l %0, %2\n"
  509. "subl %0, %3, %1\n"
  510. "sextw %1, %1\n"
  511. "stl_c %1, %2\n"
  512. "beq %1, 2f\n"
  513. ".subsection 2\n"
  514. "2: br 1b\n"
  515. ".previous\n"
  516. : "=&r" (original), // %0
  517. "=&r" (modified) // %1
  518. : "m" (storage), // %2
  519. "r" (v) // %3
  520. : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC
  521. );
  522. fence_after(order);
  523. return original;
  524. }
  525. };
  526. template< bool Signed >
  527. struct operations< 8u, Signed > :
  528. public gcc_alpha_operations_base
  529. {
  530. typedef typename make_storage_type< 8u >::type storage_type;
  531. typedef typename make_storage_type< 8u >::aligned aligned_storage_type;
  532. static BOOST_CONSTEXPR_OR_CONST std::size_t storage_size = 8u;
  533. static BOOST_CONSTEXPR_OR_CONST bool is_signed = Signed;
  534. static BOOST_FORCEINLINE void store(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
  535. {
  536. fence_before(order);
  537. storage = v;
  538. fence_after_store(order);
  539. }
  540. static BOOST_FORCEINLINE storage_type load(storage_type const volatile& storage, memory_order order) BOOST_NOEXCEPT
  541. {
  542. storage_type v = storage;
  543. fence_after(order);
  544. return v;
  545. }
  546. static BOOST_FORCEINLINE storage_type exchange(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
  547. {
  548. storage_type original, tmp;
  549. fence_before(order);
  550. __asm__ __volatile__
  551. (
  552. "1:\n"
  553. "mov %3, %1\n"
  554. "ldq_l %0, %2\n"
  555. "stq_c %1, %2\n"
  556. "beq %1, 2f\n"
  557. ".subsection 2\n"
  558. "2: br 1b\n"
  559. ".previous\n"
  560. : "=&r" (original), // %0
  561. "=&r" (tmp) // %1
  562. : "m" (storage), // %2
  563. "r" (v) // %3
  564. : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC
  565. );
  566. fence_after(order);
  567. return original;
  568. }
  569. static BOOST_FORCEINLINE bool compare_exchange_weak(
  570. storage_type volatile& storage, storage_type& expected, storage_type desired, memory_order success_order, memory_order failure_order) BOOST_NOEXCEPT
  571. {
  572. fence_before(success_order);
  573. int success;
  574. storage_type current;
  575. __asm__ __volatile__
  576. (
  577. "1:\n"
  578. "ldq_l %2, %4\n" // current = *(&storage)
  579. "cmpeq %2, %0, %3\n" // success = current == expected
  580. "mov %2, %0\n" // expected = current
  581. "beq %3, 2f\n" // if (success == 0) goto end
  582. "stq_c %1, %4\n" // storage = desired; desired = store succeeded
  583. "mov %1, %3\n" // success = desired
  584. "2:\n"
  585. : "+&r" (expected), // %0
  586. "+&r" (desired), // %1
  587. "=&r" (current), // %2
  588. "=&r" (success) // %3
  589. : "m" (storage) // %4
  590. : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC
  591. );
  592. if (success)
  593. fence_after(success_order);
  594. else
  595. fence_after(failure_order);
  596. return !!success;
  597. }
  598. static BOOST_FORCEINLINE bool compare_exchange_strong(
  599. storage_type volatile& storage, storage_type& expected, storage_type desired, memory_order success_order, memory_order failure_order) BOOST_NOEXCEPT
  600. {
  601. int success;
  602. storage_type current, tmp;
  603. fence_before(success_order);
  604. __asm__ __volatile__
  605. (
  606. "1:\n"
  607. "mov %5, %1\n" // tmp = desired
  608. "ldq_l %2, %4\n" // current = *(&storage)
  609. "cmpeq %2, %0, %3\n" // success = current == expected
  610. "mov %2, %0\n" // expected = current
  611. "beq %3, 2f\n" // if (success == 0) goto end
  612. "stq_c %1, %4\n" // storage = tmp; tmp = store succeeded
  613. "beq %1, 3f\n" // if (tmp == 0) goto retry
  614. "mov %1, %3\n" // success = tmp
  615. "2:\n"
  616. ".subsection 2\n"
  617. "3: br 1b\n"
  618. ".previous\n"
  619. : "+&r" (expected), // %0
  620. "=&r" (tmp), // %1
  621. "=&r" (current), // %2
  622. "=&r" (success) // %3
  623. : "m" (storage), // %4
  624. "r" (desired) // %5
  625. : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC
  626. );
  627. if (success)
  628. fence_after(success_order);
  629. else
  630. fence_after(failure_order);
  631. return !!success;
  632. }
  633. static BOOST_FORCEINLINE storage_type fetch_add(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
  634. {
  635. storage_type original, modified;
  636. fence_before(order);
  637. __asm__ __volatile__
  638. (
  639. "1:\n"
  640. "ldq_l %0, %2\n"
  641. "addq %0, %3, %1\n"
  642. "stq_c %1, %2\n"
  643. "beq %1, 2f\n"
  644. ".subsection 2\n"
  645. "2: br 1b\n"
  646. ".previous\n"
  647. : "=&r" (original), // %0
  648. "=&r" (modified) // %1
  649. : "m" (storage), // %2
  650. "r" (v) // %3
  651. : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC
  652. );
  653. fence_after(order);
  654. return original;
  655. }
  656. static BOOST_FORCEINLINE storage_type fetch_sub(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
  657. {
  658. storage_type original, modified;
  659. fence_before(order);
  660. __asm__ __volatile__
  661. (
  662. "1:\n"
  663. "ldq_l %0, %2\n"
  664. "subq %0, %3, %1\n"
  665. "stq_c %1, %2\n"
  666. "beq %1, 2f\n"
  667. ".subsection 2\n"
  668. "2: br 1b\n"
  669. ".previous\n"
  670. : "=&r" (original), // %0
  671. "=&r" (modified) // %1
  672. : "m" (storage), // %2
  673. "r" (v) // %3
  674. : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC
  675. );
  676. fence_after(order);
  677. return original;
  678. }
  679. static BOOST_FORCEINLINE storage_type fetch_and(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
  680. {
  681. storage_type original, modified;
  682. fence_before(order);
  683. __asm__ __volatile__
  684. (
  685. "1:\n"
  686. "ldq_l %0, %2\n"
  687. "and %0, %3, %1\n"
  688. "stq_c %1, %2\n"
  689. "beq %1, 2f\n"
  690. ".subsection 2\n"
  691. "2: br 1b\n"
  692. ".previous\n"
  693. : "=&r" (original), // %0
  694. "=&r" (modified) // %1
  695. : "m" (storage), // %2
  696. "r" (v) // %3
  697. : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC
  698. );
  699. fence_after(order);
  700. return original;
  701. }
  702. static BOOST_FORCEINLINE storage_type fetch_or(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
  703. {
  704. storage_type original, modified;
  705. fence_before(order);
  706. __asm__ __volatile__
  707. (
  708. "1:\n"
  709. "ldq_l %0, %2\n"
  710. "bis %0, %3, %1\n"
  711. "stq_c %1, %2\n"
  712. "beq %1, 2f\n"
  713. ".subsection 2\n"
  714. "2: br 1b\n"
  715. ".previous\n"
  716. : "=&r" (original), // %0
  717. "=&r" (modified) // %1
  718. : "m" (storage), // %2
  719. "r" (v) // %3
  720. : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC
  721. );
  722. fence_after(order);
  723. return original;
  724. }
  725. static BOOST_FORCEINLINE storage_type fetch_xor(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
  726. {
  727. storage_type original, modified;
  728. fence_before(order);
  729. __asm__ __volatile__
  730. (
  731. "1:\n"
  732. "ldq_l %0, %2\n"
  733. "xor %0, %3, %1\n"
  734. "stq_c %1, %2\n"
  735. "beq %1, 2f\n"
  736. ".subsection 2\n"
  737. "2: br 1b\n"
  738. ".previous\n"
  739. : "=&r" (original), // %0
  740. "=&r" (modified) // %1
  741. : "m" (storage), // %2
  742. "r" (v) // %3
  743. : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC
  744. );
  745. fence_after(order);
  746. return original;
  747. }
  748. static BOOST_FORCEINLINE bool test_and_set(storage_type volatile& storage, memory_order order) BOOST_NOEXCEPT
  749. {
  750. return !!exchange(storage, (storage_type)1, order);
  751. }
  752. static BOOST_FORCEINLINE void clear(storage_type volatile& storage, memory_order order) BOOST_NOEXCEPT
  753. {
  754. store(storage, 0, order);
  755. }
  756. };
  757. BOOST_FORCEINLINE void thread_fence(memory_order order) BOOST_NOEXCEPT
  758. {
  759. if (order != memory_order_relaxed)
  760. __asm__ __volatile__ ("mb" ::: "memory");
  761. }
  762. BOOST_FORCEINLINE void signal_fence(memory_order order) BOOST_NOEXCEPT
  763. {
  764. if (order != memory_order_relaxed)
  765. __asm__ __volatile__ ("" ::: "memory");
  766. }
  767. } // namespace detail
  768. } // namespace atomics
  769. } // namespace boost
  770. #endif // BOOST_ATOMIC_DETAIL_OPS_GCC_ALPHA_HPP_INCLUDED_