change underlying type of clock_t to be uniform and match ABI
[musl] / arch / mips / atomic.h
1 #ifndef _INTERNAL_ATOMIC_H
2 #define _INTERNAL_ATOMIC_H
3
4 #include <stdint.h>
5
6 static inline int a_ctz_l(unsigned long x)
7 {
8         static const char debruijn32[32] = {
9                 0, 1, 23, 2, 29, 24, 19, 3, 30, 27, 25, 11, 20, 8, 4, 13,
10                 31, 22, 28, 18, 26, 10, 7, 12, 21, 17, 9, 6, 16, 5, 15, 14
11         };
12         return debruijn32[(x&-x)*0x076be629 >> 27];
13 }
14
15 static inline int a_ctz_64(uint64_t x)
16 {
17         uint32_t y = x;
18         if (!y) {
19                 y = x>>32;
20                 return 32 + a_ctz_l(y);
21         }
22         return a_ctz_l(y);
23 }
24
25 static inline int a_cas(volatile int *p, int t, int s)
26 {
27         int dummy;
28         __asm__ __volatile__(
29                 ".set push\n"
30                 ".set mips2\n"
31                 ".set noreorder\n"
32                 "1:     ll %0, 0(%2)\n"
33                 "       bne %0, %3, 1f\n"
34                 "       addu %1, %4, $0\n"
35                 "       sc %1, 0(%2)\n"
36                 "       beq %1, $0, 1b\n"
37                 "       nop\n"
38                 "1:     \n"
39                 ".set pop\n"
40                 : "=&r"(t), "=&r"(dummy) : "r"(p), "r"(t), "r"(s) : "memory" );
41         return t;
42 }
43
44 static inline void *a_cas_p(volatile void *p, void *t, void *s)
45 {
46         return (void *)a_cas(p, (int)t, (int)s);
47 }
48
49 static inline long a_cas_l(volatile void *p, long t, long s)
50 {
51         return a_cas(p, t, s);
52 }
53
54
55 static inline int a_swap(volatile int *x, int v)
56 {
57         int old, dummy;
58         __asm__ __volatile__(
59                 ".set push\n"
60                 ".set mips2\n"
61                 ".set noreorder\n"
62                 "1:     ll %0, 0(%2)\n"
63                 "       addu %1, %3, $0\n"
64                 "       sc %1, 0(%2)\n"
65                 "       beq %1, $0, 1b\n"
66                 "       nop\n"
67                 "1:     \n"
68                 ".set pop\n"
69                 : "=&r"(old), "=&r"(dummy) : "r"(x), "r"(v) : "memory" );
70         return old;
71 }
72
73 static inline int a_fetch_add(volatile int *x, int v)
74 {
75         int old, dummy;
76         __asm__ __volatile__(
77                 ".set push\n"
78                 ".set mips2\n"
79                 ".set noreorder\n"
80                 "1:     ll %0, 0(%2)\n"
81                 "       addu %1, %0, %3\n"
82                 "       sc %1, 0(%2)\n"
83                 "       beq %1, $0, 1b\n"
84                 "       nop\n"
85                 "1:     \n"
86                 ".set pop\n"
87                 : "=&r"(old), "=&r"(dummy) : "r"(x), "r"(v) : "memory" );
88         return old;
89 }
90
91 static inline void a_inc(volatile int *x)
92 {
93         int dummy;
94         __asm__ __volatile__(
95                 ".set push\n"
96                 ".set mips2\n"
97                 ".set noreorder\n"
98                 "1:     ll %0, 0(%1)\n"
99                 "       addu %0, %0, 1\n"
100                 "       sc %0, 0(%1)\n"
101                 "       beq %0, $0, 1b\n"
102                 "       nop\n"
103                 "1:     \n"
104                 ".set pop\n"
105                 : "=&r"(dummy) : "r"(x) : "memory" );
106 }
107
108 static inline void a_dec(volatile int *x)
109 {
110         int dummy;
111         __asm__ __volatile__(
112                 ".set push\n"
113                 ".set mips2\n"
114                 ".set noreorder\n"
115                 "1:     ll %0, 0(%1)\n"
116                 "       subu %0, %0, 1\n"
117                 "       sc %0, 0(%1)\n"
118                 "       beq %0, $0, 1b\n"
119                 "       nop\n"
120                 "1:     \n"
121                 ".set pop\n"
122                 : "=&r"(dummy) : "r"(x) : "memory" );
123 }
124
125 static inline void a_store(volatile int *p, int x)
126 {
127         int dummy;
128         __asm__ __volatile__(
129                 ".set push\n"
130                 ".set mips2\n"
131                 ".set noreorder\n"
132                 "1:     ll %0, 0(%1)\n"
133                 "       addu %0, %2, $0\n"
134                 "       sc %0, 0(%1)\n"
135                 "       beq %0, $0, 1b\n"
136                 "       nop\n"
137                 "1:     \n"
138                 ".set pop\n"
139                 : "=&r"(dummy) : "r"(p), "r"(x) : "memory" );
140 }
141
142 static inline void a_spin()
143 {
144 }
145
146 static inline void a_crash()
147 {
148         *(volatile char *)0=0;
149 }
150
151 static inline void a_and(volatile int *p, int v)
152 {
153         int dummy;
154         __asm__ __volatile__(
155                 ".set push\n"
156                 ".set mips2\n"
157                 ".set noreorder\n"
158                 "1:     ll %0, 0(%1)\n"
159                 "       and %0, %0, %2\n"
160                 "       sc %0, 0(%1)\n"
161                 "       beq %0, $0, 1b\n"
162                 "       nop\n"
163                 "1:     \n"
164                 ".set pop\n"
165                 : "=&r"(dummy) : "r"(p), "r"(v) : "memory" );
166 }
167
168 static inline void a_or(volatile int *p, int v)
169 {
170         int dummy;
171         __asm__ __volatile__(
172                 ".set push\n"
173                 ".set mips2\n"
174                 ".set noreorder\n"
175                 "1:     ll %0, 0(%1)\n"
176                 "       or %0, %0, %2\n"
177                 "       sc %0, 0(%1)\n"
178                 "       beq %0, $0, 1b\n"
179                 "       nop\n"
180                 "1:     \n"
181                 ".set pop\n"
182                 : "=&r"(dummy) : "r"(p), "r"(v) : "memory" );
183 }
184
185 static inline void a_and_64(volatile uint64_t *p, uint64_t v)
186 {
187         union { uint64_t v; uint32_t r[2]; } u = { v };
188         a_and((int *)p, u.r[0]);
189         a_and((int *)p+1, u.r[1]);
190 }
191
192 static inline void a_or_64(volatile uint64_t *p, uint64_t v)
193 {
194         union { uint64_t v; uint32_t r[2]; } u = { v };
195         a_or((int *)p, u.r[0]);
196         a_or((int *)p+1, u.r[1]);
197 }
198
199 #endif