ObjFW
atomic_powerpc.h
1 /*
2  * Copyright (c) 2008-2021 Jonathan Schleifer <js@nil.im>
3  *
4  * All rights reserved.
5  *
6  * This file is part of ObjFW. It may be distributed under the terms of the
7  * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
8  * the packaging of this file.
9  *
10  * Alternatively, it may be distributed under the terms of the GNU General
11  * Public License, either version 2 or 3, which can be found in the file
12  * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this
13  * file.
14  */
15 
16 static OF_INLINE int
17 of_atomic_int_add(volatile int *_Nonnull p, int i)
18 {
19  __asm__ __volatile__ (
20  "0:\n\t"
21  "lwarx %0, 0, %2\n\t"
22  "add %0, %0, %1\n\t"
23  "stwcx. %0, 0, %2\n\t"
24  "bne- 0b"
25  : "=&r"(i)
26  : "r"(i), "r"(p)
27  : "cc", "memory"
28  );
29 
30  return i;
31 }
32 
33 static OF_INLINE int32_t
34 of_atomic_int32_add(volatile int32_t *_Nonnull p, int32_t i)
35 {
36  __asm__ __volatile__ (
37  "0:\n\t"
38  "lwarx %0, 0, %2\n\t"
39  "add %0, %0, %1\n\t"
40  "stwcx. %0, 0, %2\n\t"
41  "bne- 0b"
42  : "=&r"(i)
43  : "r"(i), "r"(p)
44  : "cc", "memory"
45  );
46 
47  return i;
48 }
49 
50 static OF_INLINE void *_Nullable
51 of_atomic_ptr_add(void *volatile _Nullable *_Nonnull p, intptr_t i)
52 {
53  __asm__ __volatile__ (
54  "0:\n\t"
55  "lwarx %0, 0, %2\n\t"
56  "add %0, %0, %1\n\t"
57  "stwcx. %0, 0, %2\n\t"
58  "bne- 0b"
59  : "=&r"(i)
60  : "r"(i), "r"(p)
61  : "cc", "memory"
62  );
63 
64  return (void *)i;
65 }
66 
67 static OF_INLINE int
68 of_atomic_int_sub(volatile int *_Nonnull p, int i)
69 {
70  __asm__ __volatile__ (
71  "0:\n\t"
72  "lwarx %0, 0, %2\n\t"
73  "sub %0, %0, %1\n\t"
74  "stwcx. %0, 0, %2\n\t"
75  "bne- 0b"
76  : "=&r"(i)
77  : "r"(i), "r"(p)
78  : "cc", "memory"
79  );
80 
81  return i;
82 }
83 
84 static OF_INLINE int32_t
85 of_atomic_int32_sub(volatile int32_t *_Nonnull p, int32_t i)
86 {
87  __asm__ __volatile__ (
88  "0:\n\t"
89  "lwarx %0, 0, %2\n\t"
90  "sub %0, %0, %1\n\t"
91  "stwcx. %0, 0, %2\n\t"
92  "bne- 0b"
93  : "=&r"(i)
94  : "r"(i), "r"(p)
95  : "cc", "memory"
96  );
97 
98  return i;
99 }
100 
101 static OF_INLINE void *_Nullable
102 of_atomic_ptr_sub(void *volatile _Nullable *_Nonnull p, intptr_t i)
103 {
104  __asm__ __volatile__ (
105  "0:\n\t"
106  "lwarx %0, 0, %2\n\t"
107  "sub %0, %0, %1\n\t"
108  "stwcx. %0, 0, %2\n\t"
109  "bne- 0b"
110  : "=&r"(i)
111  : "r"(i), "r"(p)
112  : "cc", "memory"
113  );
114 
115  return (void *)i;
116 }
117 
118 static OF_INLINE int
119 of_atomic_int_inc(volatile int *_Nonnull p)
120 {
121  int i;
122 
123  __asm__ __volatile__ (
124  "0:\n\t"
125  "lwarx %0, 0, %1\n\t"
126  "addi %0, %0, 1\n\t"
127  "stwcx. %0, 0, %1\n\t"
128  "bne- 0b"
129  : "=&r"(i)
130  : "r"(p)
131  : "cc", "memory"
132  );
133 
134  return i;
135 }
136 
137 static OF_INLINE int32_t
138 of_atomic_int32_inc(volatile int32_t *_Nonnull p)
139 {
140  int32_t i;
141 
142  __asm__ __volatile__ (
143  "0:\n\t"
144  "lwarx %0, 0, %1\n\t"
145  "addi %0, %0, 1\n\t"
146  "stwcx. %0, 0, %1\n\t"
147  "bne- 0b"
148  : "=&r"(i)
149  : "r"(p)
150  : "cc", "memory"
151  );
152 
153  return i;
154 }
155 
156 static OF_INLINE int
157 of_atomic_int_dec(volatile int *_Nonnull p)
158 {
159  int i;
160 
161  __asm__ __volatile__ (
162  "0:\n\t"
163  "lwarx %0, 0, %1\n\t"
164  "subi %0, %0, 1\n\t"
165  "stwcx. %0, 0, %1\n\t"
166  "bne- 0b"
167  : "=&r"(i)
168  : "r"(p)
169  : "cc", "memory"
170  );
171 
172  return i;
173 }
174 
175 static OF_INLINE int32_t
176 of_atomic_int32_dec(volatile int32_t *_Nonnull p)
177 {
178  int32_t i;
179 
180  __asm__ __volatile__ (
181  "0:\n\t"
182  "lwarx %0, 0, %1\n\t"
183  "subi %0, %0, 1\n\t"
184  "stwcx. %0, 0, %1\n\t"
185  "bne- 0b"
186  : "=&r"(i)
187  : "r"(p)
188  : "cc", "memory"
189  );
190 
191  return i;
192 }
193 
194 static OF_INLINE unsigned int
195 of_atomic_int_or(volatile unsigned int *_Nonnull p, unsigned int i)
196 {
197  __asm__ __volatile__ (
198  "0:\n\t"
199  "lwarx %0, 0, %2\n\t"
200  "or %0, %0, %1\n\t"
201  "stwcx. %0, 0, %2\n\t"
202  "bne- 0b"
203  : "=&r"(i)
204  : "r"(i), "r"(p)
205  : "cc", "memory"
206  );
207 
208  return i;
209 }
210 
211 static OF_INLINE uint32_t
212 of_atomic_int32_or(volatile uint32_t *_Nonnull p, uint32_t i)
213 {
214  __asm__ __volatile__ (
215  "0:\n\t"
216  "lwarx %0, 0, %2\n\t"
217  "or %0, %0, %1\n\t"
218  "stwcx. %0, 0, %2\n\t"
219  "bne- 0b"
220  : "=&r"(i)
221  : "r"(i), "r"(p)
222  : "cc", "memory"
223  );
224 
225  return i;
226 }
227 
228 static OF_INLINE unsigned int
229 of_atomic_int_and(volatile unsigned int *_Nonnull p, unsigned int i)
230 {
231  __asm__ __volatile__ (
232  "0:\n\t"
233  "lwarx %0, 0, %2\n\t"
234  "and %0, %0, %1\n\t"
235  "stwcx. %0, 0, %2\n\t"
236  "bne- 0b"
237  : "=&r"(i)
238  : "r"(i), "r"(p)
239  : "cc", "memory"
240  );
241 
242  return i;
243 }
244 
245 static OF_INLINE uint32_t
246 of_atomic_int32_and(volatile uint32_t *_Nonnull p, uint32_t i)
247 {
248  __asm__ __volatile__ (
249  "0:\n\t"
250  "lwarx %0, 0, %2\n\t"
251  "and %0, %0, %1\n\t"
252  "stwcx. %0, 0, %2\n\t"
253  "bne- 0b"
254  : "=&r"(i)
255  : "r"(i), "r"(p)
256  : "cc", "memory"
257  );
258 
259  return i;
260 }
261 
262 static OF_INLINE unsigned int
263 of_atomic_int_xor(volatile unsigned int *_Nonnull p, unsigned int i)
264 {
265  __asm__ __volatile__ (
266  "0:\n\t"
267  "lwarx %0, 0, %2\n\t"
268  "xor %0, %0, %1\n\t"
269  "stwcx. %0, 0, %2\n\t"
270  "bne- 0b"
271  : "=&r"(i)
272  : "r"(i), "r"(p)
273  : "cc", "memory"
274  );
275 
276  return i;
277 }
278 
279 static OF_INLINE uint32_t
280 of_atomic_int32_xor(volatile uint32_t *_Nonnull p, uint32_t i)
281 {
282  __asm__ __volatile__ (
283  "0:\n\t"
284  "lwarx %0, 0, %2\n\t"
285  "xor %0, %0, %1\n\t"
286  "stwcx. %0, 0, %2\n\t"
287  "bne- 0b"
288  : "=&r"(i)
289  : "r"(i), "r"(p)
290  : "cc", "memory"
291  );
292 
293  return i;
294 }
295 
296 static OF_INLINE bool
297 of_atomic_int_cmpswap(volatile int *_Nonnull p, int o, int n)
298 {
299  int r;
300 
301  __asm__ __volatile__ (
302  "0:\n\t"
303  "lwarx %0, 0, %3\n\t"
304  "cmpw %0, %1\n\t"
305  "bne 1f\n\t"
306  "stwcx. %2, 0, %3\n\t"
307  "bne- 0b\n\t"
308  "li %0, 1\n\t"
309  "b 2f\n\t"
310  "1:\n\t"
311  "stwcx. %0, 0, %3\n\t"
312  "li %0, 0\n\t"
313  "2:"
314  : "=&r"(r)
315  : "r"(o), "r"(n), "r"(p)
316  : "cc", "memory"
317  );
318 
319  return r;
320 }
321 
322 static OF_INLINE bool
323 of_atomic_int32_cmpswap(volatile int32_t *_Nonnull p, int32_t o, int32_t n)
324 {
325  int r;
326 
327  __asm__ __volatile__ (
328  "0:\n\t"
329  "lwarx %0, 0, %3\n\t"
330  "cmpw %0, %1\n\t"
331  "bne 1f\n\t"
332  "stwcx. %2, 0, %3\n\t"
333  "bne- 0b\n\t"
334  "li %0, 1\n\t"
335  "b 2f\n\t"
336  "1:\n\t"
337  "stwcx. %0, 0, %3\n\t"
338  "li %0, 0\n\t"
339  "2:"
340  : "=&r"(r)
341  : "r"(o), "r"(n), "r"(p)
342  : "cc", "memory"
343  );
344 
345  return r;
346 }
347 
348 static OF_INLINE bool
349 of_atomic_ptr_cmpswap(void *volatile _Nullable *_Nonnull p,
350  void *_Nullable o, void *_Nullable n)
351 {
352  int r;
353 
354  __asm__ __volatile__ (
355  "0:\n\t"
356  "lwarx %0, 0, %3\n\t"
357  "cmpw %0, %1\n\t"
358  "bne 1f\n\t"
359  "stwcx. %2, 0, %3\n\t"
360  "bne- 0b\n\t"
361  "li %0, 1\n\t"
362  "b 2f\n\t"
363  "1:\n\t"
364  "stwcx. %0, 0, %3\n\t"
365  "li %0, 0\n\t"
366  "2:"
367  : "=&r"(r)
368  : "r"(o), "r"(n), "r"(p)
369  : "cc", "memory"
370  );
371 
372  return r;
373 }
374 
375 static OF_INLINE void
376 of_memory_barrier(void)
377 {
378  __asm__ __volatile__ (
379  ".long 0x7C2004AC /* lwsync */" ::: "memory"
380  );
381 }
382 
383 static OF_INLINE void
384 of_memory_barrier_acquire(void)
385 {
386  __asm__ __volatile__ (
387  ".long 0x7C2004AC /* lwsync */" ::: "memory"
388  );
389 }
390 
391 static OF_INLINE void
392 of_memory_barrier_release(void)
393 {
394  __asm__ __volatile__ (
395  ".long 0x7C2004AC /* lwsync */" ::: "memory"
396  );
397 }