5ab20a55e5f45077c1e9366b604c24c92eb96fdc
[musl] / arch / arm / atomic_arch.h
1 #if __ARM_ARCH_7A__ || __ARM_ARCH_7R__ ||  __ARM_ARCH >= 7
2
3 #define a_barrier a_barrier
4 static inline void a_barrier()
5 {
6         __asm__ __volatile__("dmb ish");
7 }
8
9 #define a_cas a_cas
10 static inline int a_cas(volatile int *p, int t, int s)
11 {
12         int old;
13         __asm__ __volatile__(
14                 "       dmb ish\n"
15                 "1:     ldrex %0,%3\n"
16                 "       cmp %0,%1\n"
17                 "       bne 1f\n"
18                 "       strex %0,%2,%3\n"
19                 "       cmp %0, #0\n"
20                 "       bne 1b\n"
21                 "       mov %0, %1\n"
22                 "1:     dmb ish\n"
23                 : "=&r"(old)
24                 : "r"(t), "r"(s), "Q"(*p)
25                 : "memory", "cc" );
26         return old;
27 }
28
29 #define a_swap a_swap
30 static inline int a_swap(volatile int *x, int v)
31 {
32         int old, tmp;
33         __asm__ __volatile__(
34                 "       dmb ish\n"
35                 "1:     ldrex %0,%3\n"
36                 "       strex %1,%2,%3\n"
37                 "       cmp %1, #0\n"
38                 "       bne 1b\n"
39                 "       dmb ish\n"
40                 : "=&r"(old), "=&r"(tmp)
41                 : "r"(v), "Q"(*x)
42                 : "memory", "cc" );
43         return old;
44 }
45
46 #define a_fetch_add a_fetch_add
47 static inline int a_fetch_add(volatile int *x, int v)
48 {
49         int old, tmp;
50         __asm__ __volatile__(
51                 "       dmb ish\n"
52                 "1:     ldrex %0,%3\n"
53                 "       add %0,%0,%2\n"
54                 "       strex %1,%0,%3\n"
55                 "       cmp %1, #0\n"
56                 "       bne 1b\n"
57                 "       dmb ish\n"
58                 : "=&r"(old), "=&r"(tmp)
59                 : "r"(v), "Q"(*x)
60                 : "memory", "cc" );
61         return old-v;
62 }
63
64 #define a_inc a_inc
65 static inline void a_inc(volatile int *x)
66 {
67         int tmp, tmp2;
68         __asm__ __volatile__(
69                 "       dmb ish\n"
70                 "1:     ldrex %0,%2\n"
71                 "       add %0,%0,#1\n"
72                 "       strex %1,%0,%2\n"
73                 "       cmp %1, #0\n"
74                 "       bne 1b\n"
75                 "       dmb ish\n"
76                 : "=&r"(tmp), "=&r"(tmp2)
77                 : "Q"(*x)
78                 : "memory", "cc" );
79 }
80
81 #define a_dec a_dec
82 static inline void a_dec(volatile int *x)
83 {
84         int tmp, tmp2;
85         __asm__ __volatile__(
86                 "       dmb ish\n"
87                 "1:     ldrex %0,%2\n"
88                 "       sub %0,%0,#1\n"
89                 "       strex %1,%0,%2\n"
90                 "       cmp %1, #0\n"
91                 "       bne 1b\n"
92                 "       dmb ish\n"
93                 : "=&r"(tmp), "=&r"(tmp2)
94                 : "Q"(*x)
95                 : "memory", "cc" );
96 }
97
98 #define a_and a_and
99 static inline void a_and(volatile int *x, int v)
100 {
101         int tmp, tmp2;
102         __asm__ __volatile__(
103                 "       dmb ish\n"
104                 "1:     ldrex %0,%3\n"
105                 "       and %0,%0,%2\n"
106                 "       strex %1,%0,%3\n"
107                 "       cmp %1, #0\n"
108                 "       bne 1b\n"
109                 "       dmb ish\n"
110                 : "=&r"(tmp), "=&r"(tmp2)
111                 : "r"(v), "Q"(*x)
112                 : "memory", "cc" );
113 }
114
115 #define a_or a_or
116 static inline void a_or(volatile int *x, int v)
117 {
118         int tmp, tmp2;
119         __asm__ __volatile__(
120                 "       dmb ish\n"
121                 "1:     ldrex %0,%3\n"
122                 "       orr %0,%0,%2\n"
123                 "       strex %1,%0,%3\n"
124                 "       cmp %1, #0\n"
125                 "       bne 1b\n"
126                 "       dmb ish\n"
127                 : "=&r"(tmp), "=&r"(tmp2)
128                 : "r"(v), "Q"(*x)
129                 : "memory", "cc" );
130 }
131
132 #define a_store a_store
133 static inline void a_store(volatile int *p, int x)
134 {
135         __asm__ __volatile__(
136                 "       dmb ish\n"
137                 "       str %1,%0\n"
138                 "       dmb ish\n"
139                 : "=m"(*p)
140                 : "r"(x)
141                 : "memory", "cc" );
142 }
143
144 #else
145
146 int __a_cas(int, int, volatile int *) __attribute__((__visibility__("hidden")));
147 #define __k_cas __a_cas
148
149 #define a_barrier a_barrier
150 static inline void a_barrier()
151 {
152         __asm__ __volatile__("bl __a_barrier"
153                 : : : "memory", "cc", "ip", "lr" );
154 }
155
156 #define a_cas a_cas
157 static inline int a_cas(volatile int *p, int t, int s)
158 {
159         int old;
160         for (;;) {
161                 if (!__k_cas(t, s, p))
162                         return t;
163                 if ((old=*p) != t)
164                         return old;
165         }
166 }
167
168 #endif