atomic_arch.h 2.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107
  1. #include "libc.h"
  2. #if __ARM_ARCH_4__ || __ARM_ARCH_4T__ || __ARM_ARCH == 4
  3. #define BLX "mov lr,pc\n\tbx"
  4. #else
  5. #define BLX "blx"
  6. #endif
  7. extern hidden uintptr_t __a_cas_ptr, __a_barrier_ptr;
  8. #if ((__ARM_ARCH_6__ || __ARM_ARCH_6K__ || __ARM_ARCH_6KZ__ || __ARM_ARCH_6ZK__) && !__thumb__) \
  9. || __ARM_ARCH_6T2__ || __ARM_ARCH_7A__ || __ARM_ARCH_7R__ || __ARM_ARCH >= 7
  10. #define a_ll a_ll
  11. static inline int a_ll(volatile int *p)
  12. {
  13. int v;
  14. __asm__ __volatile__ ("ldrex %0, %1" : "=r"(v) : "Q"(*p));
  15. return v;
  16. }
  17. #define a_sc a_sc
  18. static inline int a_sc(volatile int *p, int v)
  19. {
  20. int r;
  21. __asm__ __volatile__ ("strex %0,%2,%1" : "=&r"(r), "=Q"(*p) : "r"(v) : "memory");
  22. return !r;
  23. }
  24. #if __ARM_ARCH_7A__ || __ARM_ARCH_7R__ || __ARM_ARCH >= 7
  25. #define a_barrier a_barrier
  26. static inline void a_barrier()
  27. {
  28. __asm__ __volatile__ ("dmb ish" : : : "memory");
  29. }
  30. #endif
  31. #define a_pre_llsc a_barrier
  32. #define a_post_llsc a_barrier
  33. #else
  34. #define a_cas a_cas
  35. static inline int a_cas(volatile int *p, int t, int s)
  36. {
  37. for (;;) {
  38. register int r0 __asm__("r0") = t;
  39. register int r1 __asm__("r1") = s;
  40. register volatile int *r2 __asm__("r2") = p;
  41. register uintptr_t r3 __asm__("r3") = __a_cas_ptr;
  42. int old;
  43. __asm__ __volatile__ (
  44. BLX " r3"
  45. : "+r"(r0), "+r"(r3) : "r"(r1), "r"(r2)
  46. : "memory", "lr", "ip", "cc" );
  47. if (!r0) return t;
  48. if ((old=*p)!=t) return old;
  49. }
  50. }
  51. #endif
  52. #ifndef a_barrier
  53. #define a_barrier a_barrier
  54. static inline void a_barrier()
  55. {
  56. register uintptr_t ip __asm__("ip") = __a_barrier_ptr;
  57. __asm__ __volatile__( BLX " ip" : "+r"(ip) : : "memory", "cc", "lr" );
  58. }
  59. #endif
  60. #define a_crash a_crash
  61. static inline void a_crash()
  62. {
  63. __asm__ __volatile__(
  64. #ifndef __thumb__
  65. ".word 0xe7f000f0"
  66. #else
  67. ".short 0xdeff"
  68. #endif
  69. : : : "memory");
  70. }
  71. #if __ARM_ARCH >= 5 && (!__thumb__ || __thumb2__)
  72. #define a_clz_32 a_clz_32
  73. static inline int a_clz_32(uint32_t x)
  74. {
  75. __asm__ ("clz %0, %1" : "=r"(x) : "r"(x));
  76. return x;
  77. }
  78. #if __ARM_ARCH_6T2__ || __ARM_ARCH_7A__ || __ARM_ARCH_7R__ || __ARM_ARCH >= 7
  79. #define a_ctz_32 a_ctz_32
  80. static inline int a_ctz_32(uint32_t x)
  81. {
  82. uint32_t xr;
  83. __asm__ ("rbit %0, %1" : "=r"(xr) : "r"(x));
  84. return a_clz_32(xr);
  85. }
  86. #endif
  87. #endif