aarch64.h 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199
  1. /*
  2. * Copyright (c) 1991-1994 by Xerox Corporation. All rights reserved.
  3. * Copyright (c) 1996-1999 by Silicon Graphics. All rights reserved.
  4. * Copyright (c) 1999-2003 by Hewlett-Packard Company. All rights reserved.
  5. *
  6. *
  7. * THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED
  8. * OR IMPLIED. ANY USE IS AT YOUR OWN RISK.
  9. *
  10. * Permission is hereby granted to use or copy this program
  11. * for any purpose, provided the above notices are retained on all copies.
  12. * Permission to modify the code and to distribute modified code is granted,
  13. * provided the above notices are retained, and a notice that the code was
  14. * modified is included with the above copyright notice.
  15. *
  16. */
  17. #include "../test_and_set_t_is_ao_t.h"
  18. #include "../standard_ao_double_t.h"
  19. #ifndef AO_UNIPROCESSOR
  20. AO_INLINE void
  21. AO_nop_write(void)
  22. {
  23. __asm__ __volatile__("dmb st" : : : "memory");
  24. }
  25. # define AO_HAVE_nop_write
  26. #endif
  27. /* TODO: Adjust version check on fixing double-wide AO support in GCC. */
  28. #if __GNUC__ >= 4
  29. AO_INLINE AO_double_t
  30. AO_double_load(const volatile AO_double_t *addr)
  31. {
  32. AO_double_t result;
  33. int status;
  34. /* Note that STXP cannot be discarded because LD[A]XP is not */
  35. /* single-copy atomic (unlike LDREXD for 32-bit ARM). */
  36. do {
  37. __asm__ __volatile__("//AO_double_load\n"
  38. " ldxp %0, %1, %3\n"
  39. " stxp %w2, %0, %1, %3"
  40. : "=&r" (result.AO_val1), "=&r" (result.AO_val2), "=&r" (status)
  41. : "Q" (*addr));
  42. } while (AO_EXPECT_FALSE(status));
  43. return result;
  44. }
  45. # define AO_HAVE_double_load
  46. AO_INLINE AO_double_t
  47. AO_double_load_acquire(const volatile AO_double_t *addr)
  48. {
  49. AO_double_t result;
  50. int status;
  51. do {
  52. __asm__ __volatile__("//AO_double_load_acquire\n"
  53. " ldaxp %0, %1, %3\n"
  54. " stxp %w2, %0, %1, %3"
  55. : "=&r" (result.AO_val1), "=&r" (result.AO_val2), "=&r" (status)
  56. : "Q" (*addr));
  57. } while (AO_EXPECT_FALSE(status));
  58. return result;
  59. }
  60. # define AO_HAVE_double_load_acquire
  61. AO_INLINE void
  62. AO_double_store(volatile AO_double_t *addr, AO_double_t value)
  63. {
  64. AO_double_t old_val;
  65. int status;
  66. do {
  67. __asm__ __volatile__("//AO_double_store\n"
  68. " ldxp %0, %1, %3\n"
  69. " stxp %w2, %4, %5, %3"
  70. : "=&r" (old_val.AO_val1), "=&r" (old_val.AO_val2), "=&r" (status),
  71. "=Q" (*addr)
  72. : "r" (value.AO_val1), "r" (value.AO_val2));
  73. /* Compared to the arm.h implementation, the 'cc' (flags) are not */
  74. /* clobbered because A64 has no concept of conditional execution. */
  75. } while (AO_EXPECT_FALSE(status));
  76. }
  77. # define AO_HAVE_double_store
  78. AO_INLINE void
  79. AO_double_store_release(volatile AO_double_t *addr, AO_double_t value)
  80. {
  81. AO_double_t old_val;
  82. int status;
  83. do {
  84. __asm__ __volatile__("//AO_double_store_release\n"
  85. " ldxp %0, %1, %3\n"
  86. " stlxp %w2, %4, %5, %3"
  87. : "=&r" (old_val.AO_val1), "=&r" (old_val.AO_val2), "=&r" (status),
  88. "=Q" (*addr)
  89. : "r" (value.AO_val1), "r" (value.AO_val2));
  90. } while (AO_EXPECT_FALSE(status));
  91. }
  92. # define AO_HAVE_double_store_release
  93. AO_INLINE int
  94. AO_double_compare_and_swap(volatile AO_double_t *addr,
  95. AO_double_t old_val, AO_double_t new_val)
  96. {
  97. AO_double_t tmp;
  98. int result = 1;
  99. do {
  100. __asm__ __volatile__("//AO_double_compare_and_swap\n"
  101. " ldxp %0, %1, %2\n"
  102. : "=&r" (tmp.AO_val1), "=&r" (tmp.AO_val2)
  103. : "Q" (*addr));
  104. if (tmp.AO_val1 != old_val.AO_val1 || tmp.AO_val2 != old_val.AO_val2)
  105. break;
  106. __asm__ __volatile__(
  107. " stxp %w0, %2, %3, %1\n"
  108. : "=&r" (result), "=Q" (*addr)
  109. : "r" (new_val.AO_val1), "r" (new_val.AO_val2));
  110. } while (AO_EXPECT_FALSE(result));
  111. return !result;
  112. }
  113. # define AO_HAVE_double_compare_and_swap
  114. AO_INLINE int
  115. AO_double_compare_and_swap_acquire(volatile AO_double_t *addr,
  116. AO_double_t old_val, AO_double_t new_val)
  117. {
  118. AO_double_t tmp;
  119. int result = 1;
  120. do {
  121. __asm__ __volatile__("//AO_double_compare_and_swap_acquire\n"
  122. " ldaxp %0, %1, %2\n"
  123. : "=&r" (tmp.AO_val1), "=&r" (tmp.AO_val2)
  124. : "Q" (*addr));
  125. if (tmp.AO_val1 != old_val.AO_val1 || tmp.AO_val2 != old_val.AO_val2)
  126. break;
  127. __asm__ __volatile__(
  128. " stxp %w0, %2, %3, %1\n"
  129. : "=&r" (result), "=Q" (*addr)
  130. : "r" (new_val.AO_val1), "r" (new_val.AO_val2));
  131. } while (AO_EXPECT_FALSE(result));
  132. return !result;
  133. }
  134. # define AO_HAVE_double_compare_and_swap_acquire
  135. AO_INLINE int
  136. AO_double_compare_and_swap_release(volatile AO_double_t *addr,
  137. AO_double_t old_val, AO_double_t new_val)
  138. {
  139. AO_double_t tmp;
  140. int result = 1;
  141. do {
  142. __asm__ __volatile__("//AO_double_compare_and_swap_release\n"
  143. " ldxp %0, %1, %2\n"
  144. : "=&r" (tmp.AO_val1), "=&r" (tmp.AO_val2)
  145. : "Q" (*addr));
  146. if (tmp.AO_val1 != old_val.AO_val1 || tmp.AO_val2 != old_val.AO_val2)
  147. break;
  148. __asm__ __volatile__(
  149. " stlxp %w0, %2, %3, %1\n"
  150. : "=&r" (result), "=Q" (*addr)
  151. : "r" (new_val.AO_val1), "r" (new_val.AO_val2));
  152. } while (AO_EXPECT_FALSE(result));
  153. return !result;
  154. }
  155. # define AO_HAVE_double_compare_and_swap_release
  156. AO_INLINE int
  157. AO_double_compare_and_swap_full(volatile AO_double_t *addr,
  158. AO_double_t old_val, AO_double_t new_val)
  159. {
  160. AO_double_t tmp;
  161. int result = 1;
  162. do {
  163. __asm__ __volatile__("//AO_double_compare_and_swap_full\n"
  164. " ldaxp %0, %1, %2\n"
  165. : "=&r" (tmp.AO_val1), "=&r" (tmp.AO_val2)
  166. : "Q" (*addr));
  167. if (tmp.AO_val1 != old_val.AO_val1 || tmp.AO_val2 != old_val.AO_val2)
  168. break;
  169. __asm__ __volatile__(
  170. " stlxp %w0, %2, %3, %1\n"
  171. : "=&r" (result), "=Q" (*addr)
  172. : "r" (new_val.AO_val1), "r" (new_val.AO_val2));
  173. } while (AO_EXPECT_FALSE(result));
  174. return !result;
  175. }
  176. # define AO_HAVE_double_compare_and_swap_full
  177. #endif /* __GNUC__ >= 4 */
  178. #include "generic.h"