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