1# ast atomic scalar operations feature tests
2
3if	aso note{ gcc 4.1+ 64 bit memory atomic operations model }end link{
4		#include "FEATURE/common"
5		int main()
6		{
7			uint64_t i = 0;
8			return __sync_fetch_and_add(&i,7);
9		}
10	}end && {
11		#define _aso_cas8(p,o,n)	__sync_val_compare_and_swap(p,o,n)
12		#define _aso_inc8(p)		__sync_fetch_and_add(p,1)
13		#define _aso_dec8(p)		__sync_fetch_and_sub(p,1)
14		#define _aso_cas16(p,o,n)	__sync_val_compare_and_swap(p,o,n)
15		#define _aso_inc16(p)		__sync_fetch_and_add(p,1)
16		#define _aso_dec16(p)		__sync_fetch_and_sub(p,1)
17		#define _aso_cas32(p,o,n)	__sync_val_compare_and_swap(p,o,n)
18		#define _aso_inc32(p)		__sync_fetch_and_add(p,1)
19		#define _aso_dec32(p)		__sync_fetch_and_sub(p,1)
20		#define _aso_cas64(p,o,n)	__sync_val_compare_and_swap(p,o,n)
21		#define _aso_inc64(p)		__sync_fetch_and_add(p,1)
22		#define _aso_dec64(p)		__sync_fetch_and_sub(p,1)
23		#if _ast_sizeof_pointer == 8
24		#define _aso_casptr(p,o,n)	((void*)__sync_val_compare_and_swap(p,(uint64_t)o,(uint64_t)n))
25		#else
26		#define _aso_casptr(p,o,n)	((void*)__sync_val_compare_and_swap(p,(uint32_t)o,(uint32_t)n))
27		#endif
28	}
29elif	aso note{ gcc 4.1+ 32 bit memory atomic operations model }end link{
30		#include "FEATURE/common"
31		int main()
32		{
33			uint32_t i = 0;
34			return __sync_fetch_and_add(&i,7);
35		}
36	}end && {
37		#define _aso_cas8(p,o,n)	__sync_val_compare_and_swap(p,o,n)
38		#define _aso_inc8(p)		__sync_fetch_and_add(p,1)
39		#define _aso_dec8(p)		__sync_fetch_and_sub(p,1)
40		#define _aso_cas16(p,o,n)	__sync_val_compare_and_swap(p,o,n)
41		#define _aso_inc16(p)		__sync_fetch_and_add(p,1)
42		#define _aso_dec16(p)		__sync_fetch_and_sub(p,1)
43		#define _aso_cas32(p,o,n)	__sync_val_compare_and_swap(p,o,n)
44		#define _aso_inc32(p)		__sync_fetch_and_add(p,1)
45		#define _aso_dec32(p)		__sync_fetch_and_sub(p,1)
46		#define _aso_casptr(p,o,n)	((void*)__sync_val_compare_and_swap(p,(uint32_t)o,(uint32_t)n))
47	}
48elif	aso note{ <atomic.h> atomic_cas_64 }end link{
49		#include "FEATURE/common"
50		#include <atomic.h>
51		int main()
52		{
53			uint64_t i = 0;
54			uint32_t j = 1;
55			return atomic_cas_64(&i, 0, 1) != 0 || atomic_add_32_nv(&j, 1) != 1;
56		}
57	}end && {
58		#include <atomic.h>
59		#define _aso_cas8(p,o,n)	atomic_cas_8(p,o,n)
60		#define _aso_inc8(p)		(atomic_add_8_nv(p,1)-1)
61		#define _aso_dec8(p)		(atomic_add_8_nv(p,-1)+1)
62		#define _aso_cas16(p,o,n)	atomic_cas_16(p,o,n)
63		#define _aso_inc16(p)		(atomic_add_16_nv(p,1)-1)
64		#define _aso_dec16(p)		(atomic_add_16_nv(p,-1)+1)
65		#define _aso_cas32(p,o,n)	atomic_cas_32(p,o,n)
66		#define _aso_inc32(p)		(atomic_add_32_nv(p,1)-1)
67		#define _aso_dec32(p)		(atomic_add_32_nv(p,-1)+1)
68		#define _aso_cas64(p,o,n)	atomic_cas_64(p,o,n)
69		#define _aso_inc64(p)		(atomic_add_64_nv(p,1)-1)
70		#define _aso_dec64(p)		(atomic_add_64_nv(p,-1)+1)
71		#if _ast_sizeof_pointer == 8
72		#define _aso_casptr(p,o,n)	((void*)atomic_cas_64((uint64_t*)p,(uint64_t)o,(uint64_t)n))
73		#else
74		#define _aso_casptr(p,o,n)	((void*)atomic_cas_32((uint32_t*)p,(uint32_t)o,(uint32_t)n))
75		#endif
76	}
77elif	aso note{ <atomic.h> atomic_cas_32 }end link{
78		#include "FEATURE/common"
79		#include <atomic.h>
80		int main()
81		{
82			uint32_t i = 0;
83			return atomic_cas_32(&i, 0, 1) != 0 || (atomic_add_32_nv(&i, 1) - 1) != 1;
84		}
85	}end && {
86		#include <atomic.h>
87		#define _aso_cas8(p,o,n)	atomic_cas_8(p,o,n)
88		#define _aso_inc8(p)		(atomic_add_8_nv(p,1)-1)
89		#define _aso_dec8(p)		(atomic_add_8_nv(p,-1)+1)
90		#define _aso_cas16(p,o,n)	atomic_cas_16(p,o,n)
91		#define _aso_inc16(p)		(atomic_add_16_nv(p,1)-1)
92		#define _aso_dec16(p)		(atomic_add_16_nv(p,-1)+1)
93		#define _aso_cas32(p,o,n)	atomic_cas_32(p,o,n)
94		#define _aso_inc32(p)		(atomic_add_32_nv(p,1)-1)
95		#define _aso_dec32(p)		(atomic_add_32_nv(p,-1)+1)
96		#define _aso_casptr(p,o,n)	((void*)atomic_cas_32((uint32_t*)p,(uint32_t)o,(uint32_t)n))
97	}
98elif	aso -latomic note{ <atomic.h> atomic_cas_64 with -latomic }end link{
99		#include "FEATURE/common"
100		#include <atomic.h>
101		int main()
102		{
103			uint64_t i = 0;
104			uint32_t j = 1;
105			return atomic_cas_64(&i, 0, 1) != 0 || (atomic_add_32_nv(&j, 1) - 1) != 1;
106		}
107	}end && {
108		#include <atomic.h>
109		#define _REQ_atomic
110		#define _aso_cas8(p,o,n)	atomic_cas_8(p,o,n)
111		#define _aso_inc8(p)		(atomic_add_8_nv(p,1)-1)
112		#define _aso_dec8(p)		(atomic_add_8_nv(p,-1)+1)
113		#define _aso_cas16(p,o,n)	atomic_cas_16(p,o,n)
114		#define _aso_inc16(p)		(atomic_add_16_nv(p,1)-1)
115		#define _aso_dec16(p)		(atomic_add_16_nv(p,-1)+1)
116		#define _aso_cas32(p,o,n)	atomic_cas_32(p,o,n)
117		#define _aso_inc32(p)		(atomic_add_32_nv(p,1)-1)
118		#define _aso_dec32(p)		(atomic_add_32_nv(p,-1)+1)
119		#define _aso_cas64(p,o,n)	atomic_cas_64(p,o,n)
120		#define _aso_inc64(p)		(atomic_add_64_nv(p,1)-1)
121		#define _aso_dec64(p)		(atomic_add_64_nv(p,-1)+1)
122		#if _ast_sizeof_pointer == 8
123		#define _aso_casptr(p,o,n)	((void*)atomic_cas_64((uint64_t*)p,(uint64_t)o,(uint64_t)n))
124		#else
125		#define _aso_casptr(p,o,n)	((void*)atomic_cas_32((uint32_t*)p,(uint32_t)o,(uint32_t)n))
126		#endif
127	}
128elif	aso note{ <atomic.h> atomic_cas_32 with -latomic }end link{
129		#include "FEATURE/common"
130		#include <atomic.h>
131		int main()
132		{
133			uint32_t i = 0;
134			return atomic_cas_32(&i, 0, 1) != 0 || (atomic_add_32_nv(&i, 1) - 1) != 1;
135		}
136	}end && {
137		#include <atomic.h>
138		#define _REQ_atomic
139		#define _aso_cas8(p,o,n)	atomic_cas_8(p,o,n)
140		#define _aso_inc8(p)		(atomic_add_8_nv(p,1)-1)
141		#define _aso_dec8(p)		(atomic_add_8_nv(p,-1)+1)
142		#define _aso_cas16(p,o,n)	atomic_cas_16(p,o,n)
143		#define _aso_inc16(p)		(atomic_add_16_nv(p,1)-1)
144		#define _aso_dec16(p)		(atomic_add_16_nv(p,-1)+1)
145		#define _aso_cas32(p,o,n)	atomic_cas_32(p,o,n)
146		#define _aso_inc32(p)		(atomic_add_32_nv(p,1)-1)
147		#define _aso_dec32(p)		(atomic_add_32_nv(p,-1)+1)
148		#define _aso_casptr(p,o,n)	((void*)atomic_cas_32((uint32_t*)p,(uint32_t)o,(uint32_t)n))
149	}
150elif	aso note{ <atomic.h> cas64 }end link{
151		#include "FEATURE/common"
152		#include <atomic.h>
153		int main()
154		{
155			uint64_t i = 0;
156			uint32_t j = 1;
157			return cas64(&i, 0, 1) != 0 || (atomic_add_32_nv(&j, 1) - 1) != 1;
158		}
159	}end && {
160		#include <atomic.h>
161		#define _aso_cas8(p,o,n)	cas8(p,o,n)
162		#define _aso_inc8(p)		(atomic_add_8_nv(p,1)-1)
163		#define _aso_dec8(p)		(atomic_add_8_nv(p,-1)+1)
164		#define _aso_cas16(p,o,n)	cas16(p,o,n)
165		#define _aso_inc16(p)		(atomic_add_16_nv(p,1)-1)
166		#define _aso_dec16(p)		(atomic_add_16_nv(p,-1)+1)
167		#define _aso_cas32(p,o,n)	cas32(p,o,n)
168		#define _aso_inc32(p)		(atomic_add_32_nv(p,1)-1)
169		#define _aso_dec32(p)		(atomic_add_32_nv(p,-1)+1)
170		#define _aso_cas64(p,o,n)	cas64(p,o,n)
171		#define _aso_inc64(p)		(atomic_add_64_nv(p,1)-1)
172		#define _aso_dec64(p)		(atomic_add_64_nv(p,-1)+1)
173		#if _ast_sizeof_pointer == 8
174		#define _aso_casptr(p,o,n)	((void*)cas64((uint64_t*)p,(uint64_t)o,(uint64_t)n))
175		#else
176		#define _aso_casptr(p,o,n)	((void*)cas32((uint32_t*)p,(uint32_t)o,(uint32_t)n))
177		#endif
178	}
179elif	aso note{ <atomic.h> just cas64 }end link{
180		#include "FEATURE/common"
181		#include <atomic.h>
182		int main()
183		{
184			uint64_t i = 0;
185			uint32_t j = 1;
186			uint16_t k = 1;
187			uint8_t l = 1;
188			return cas64(&i, 0, 1) != 0 || cas32(&j, 0, 1) != 0 || cas16(&k, 0, 1) != 0 || cas8(&l, 0, 1) != 0;
189		}
190	}end && {
191		#include <atomic.h>
192		#define _aso_cas8(p,o,n)	cas8(p,o,n)
193		#define _aso_cas16(p,o,n)	cas16(p,o,n)
194		#define _aso_cas32(p,o,n)	cas32(p,o,n)
195		#define _aso_cas64(p,o,n)	cas64(p,o,n)
196		#if _ast_sizeof_pointer == 8
197		#define _aso_casptr(p,o,n)	((void*)cas64((uint64_t*)p,(uint64_t)o,(uint64_t)n))
198		#else
199		#define _aso_casptr(p,o,n)	((void*)cas32((uint32_t*)p,(uint32_t)o,(uint32_t)n))
200		#endif
201	}
202elif	aso note{ <atomic.h> cas32 }end link{
203		#include "FEATURE/common"
204		#include <atomic.h>
205		int main()
206		{
207			uint32_t i = 0;
208			return cas32(&i, 0, 1) != 0 || (atomic_add_32_nv(&i, 1) - 1) != 1;
209		}
210	}end && {
211		#include <atomic.h>
212		#define _aso_cas8(p,o,n)	cas8(p,o,n)
213		#define _aso_inc8(p)		(atomic_add_8_nv(p,1)-1)
214		#define _aso_dec8(p)		(atomic_add_8_nv(p,-1)+1)
215		#define _aso_cas16(p,o,n)	cas16(p,o,n)
216		#define _aso_inc16(p)		(atomic_add_16_nv(p,1)-1)
217		#define _aso_dec16(p)		(atomic_add_16_nv(p,-1)+1)
218		#define _aso_cas32(p,o,n)	cas32(p,o,n)
219		#define _aso_inc32(p)		(atomic_add_32_nv(p,1)-1)
220		#define _aso_dec32(p)		(atomic_add_32_nv(p,-1)+1)
221		#define _aso_casptr(p,o,n)	((void*)cas32((uint32_t*)p,(uint32_t)o,(uint32_t)n))
222	}
223elif	aso note{ <atomic.h> just cas32 }end link{
224		#include "FEATURE/common"
225		#include <atomic.h>
226		int main()
227		{
228			uint32_t j = 1;
229			uint16_t k = 1;
230			uint8_t l = 1;
231			return cas32(&j, 0, 1) != 0 || cas16(&k, 0, 1) != 0 || cas8(&l, 0, 1) != 0;
232		}
233	}end && {
234		#include <atomic.h>
235		#define _aso_cas8(p,o,n)	cas8(p,o,n)
236		#define _aso_cas16(p,o,n)	cas16(p,o,n)
237		#define _aso_cas32(p,o,n)	cas32(p,o,n)
238		#define _aso_casptr(p,o,n)	((void*)cas32((uint32_t*)p,(uint32_t)o,(uint32_t)n))
239	}
240elif	aso note{ winix Interlocked }end link{
241		#include <windows.h>
242		int main()
243		{
244			LONG		i = 0;
245			LONGLONG	j = 0;
246			return InterlockedCompareExchange(&i, 1, 0) != 0 ||
247			       InterlockedIncrement(&i) != 1 ||
248			       InterlockedDecrement(&i) != 2;
249		}
250	}end && {
251		#include <ast_windows.h>
252		#define _aso_cas32(p,o,n)	InterlockedCompareExchange((LONG volatile*)p,n,o)
253		#define _aso_inc32(p)		(InterlockedIncrement((LONG volatile*)p)-1)
254		#define _aso_dec32(p)		(InterlockedDecrement((LONG volatile*)p)+1)
255		#if _X64
256		#define _aso_cas64(p,o,n)	InterlockedCompareExchange64((LONGLONG volatile*)p,n,o)
257		#define _aso_inc64(p)		(InterlockedIncrement64((LONGLONG volatile*)p)-1)
258		#define _aso_dec64(p)		(InterlockedDecrement64((LONGLONG volatile*)p)+1)
259		#define _aso_casptr(p,o,n)	((void*)InterlockedCompareExchange64((LONGLONG volatile*)p,(LONGLONG)n,(LONGLONG)o))
260		#else
261		#if _BLD_posix
262		#include "dl.h"
263		typedef struct LL_s
264		{
265			LONG		a;
266			LONG		b;
267		} LL_t;
268		typedef union
269		{
270			LONGLONG	i;
271			LL_t		ll;
272		} LL_u;
273
274		#define _aso_cas64(p,o,n)	_aso_InterlockedCompareExchange64((LONGLONG volatile*)p,n,o)
275		static LONGLONG _aso_InterlockedCompareExchange64_init(LONGLONG volatile*, LONGLONG, LONGLONG);
276		typedef LONGLONG (*_aso_InterlockedCompareExchange64_f)(LONGLONG volatile*, LONGLONG, LONGLONG);
277		static _aso_InterlockedCompareExchange64_f _aso_InterlockedCompareExchange64 = _aso_InterlockedCompareExchange64_init;
278		static LONGLONG _aso_InterlockedCompareExchange64_32(LONGLONG volatile* p, LONGLONG o, LONGLONG n)
279		{
280			LL_t*		lp = (LL_t*)p;
281			LL_t*		op = (LL_t*)&o;
282			LL_t*		np = (LL_t*)&n;
283			LONGLONG	r;
284
285			r = *p;
286			if (_aso_cas32(&lp->a, op->a, np->a) == op->a)
287			{
288				if (_aso_cas32(&lp->b, op->b, np->b) == op->b)
289					return o;
290				_aso_cas32(&lp->a, np->a, op->a);
291			}
292			return r;
293		}
294		static LONGLONG _aso_InterlockedCompareExchange64_init(LONGLONG volatile* p, LONGLONG o, LONGLONG n)
295		{
296			if (!(_aso_InterlockedCompareExchange64 = (_aso_InterlockedCompareExchange64_f)getsymbol(MODULE_kernel, "InterlockedCompareExchange64")))
297				_aso_InterlockedCompareExchange64 = _aso_InterlockedCompareExchange64_32;
298			return _aso_InterlockedCompareExchange64(p, o, n);
299		}
300
301		#define _aso_inc64(p)		(_aso_InterlockedIncrement64((LONGLONG volatile*)p)-1)
302		typedef LONGLONG (*_aso_InterlockedIncrement64_f)(LONGLONG volatile*);
303		static LONGLONG _aso_InterlockedIncrement64_init(LONGLONG volatile*);
304		static _aso_InterlockedIncrement64_f _aso_InterlockedIncrement64 = _aso_InterlockedIncrement64_init;
305		static LONGLONG _aso_InterlockedIncrement64_32(LONGLONG volatile* p)
306		{
307			LONGLONG	o;
308
309			do
310			{
311				o = *p;
312			} while (_aso_InterlockedCompareExchange64_32(p, o, o + 1) != o);
313			return o;
314		}
315		static LONGLONG _aso_InterlockedIncrement64_init(LONGLONG volatile* p)
316		{
317			if (!(_aso_InterlockedIncrement64 = (_aso_InterlockedIncrement64_f)getsymbol(MODULE_kernel, "InterlockedIncrement64")))
318				_aso_InterlockedIncrement64 = _aso_InterlockedIncrement64_32;
319			return _aso_InterlockedIncrement64(p);
320		}
321
322		#define _aso_dec64(p)		(_aso_InterlockedDecrement64((LONGLONG volatile*)p)+1)
323		typedef LONGLONG (*_aso_InterlockedDecrement64_f)(LONGLONG volatile*);
324		static LONGLONG _aso_InterlockedDecrement64_init(LONGLONG volatile*);
325		static _aso_InterlockedDecrement64_f _aso_InterlockedDecrement64 = _aso_InterlockedDecrement64_init;
326		static LONGLONG _aso_InterlockedDecrement64_32(LONGLONG volatile* p)
327		{
328			LONGLONG	o;
329
330			do
331			{
332				o = *p;
333			} while (_aso_InterlockedCompareExchange64_32(p, o, o - 1) != o);
334			return o;
335		}
336		static LONGLONG _aso_InterlockedDecrement64_init(LONGLONG volatile* p)
337		{
338			if (!(_aso_InterlockedDecrement64 = (_aso_InterlockedDecrement64_f)getsymbol(MODULE_kernel, "InterlockedDecrement64")))
339				_aso_InterlockedDecrement64 = _aso_InterlockedDecrement64_32;
340			return _aso_InterlockedDecrement64(p);
341		}
342		#endif
343		#define _aso_casptr(p,o,n)	((void*)InterlockedCompareExchange((LONG volatile*)p,(LONG)n,(LONG)o))
344		#endif
345	}
346elif	aso note{ aix fetch and add }end link{
347		#include <sys/atomic_op.h>
348		int main()
349		{
350			int i = 0;
351			return fetch_and_add((atomic_p)&i,1);
352		}
353	}end && {
354		#include <sys/atomic_op.h>
355		#define _aso_incint(p)		fetch_and_add((atomic_p)p,1)
356		#define _aso_decint(p)		fetch_and_add((atomic_p)p,-1)
357		#define _aso_casint(p,o,n)	(compare_and_swap((atomic_p)p,(int*)&o,(int)n) ? o : *p)
358		#if _ast_sizeof_pointer == 8
359		#define _aso_casptr(p,o,n)	(compare_and_swaplp((atomic_l)p,(long*)&o,(long)n) ? o : *(void**)p)
360		#else
361		#define _aso_casptr(p,o,n)	(compare_and_swap((atomic_p)p,(int*)&o,(int)n) ? o : *(void**)p)
362		#endif
363	}
364elif	aso note{ mips compare and swap }end link{
365		int main()
366		{
367			int i = 1;
368			return __compare_and_swap(&i, 0, 1) != 1;
369		}
370	}end && {
371		#define _aso_cas32(p,o,n)	(__compare_and_swap(p,o,n) ? o : *p)
372		#define _aso_casptr(p,o,n)	(__compare_and_swap((long*)p,(long)o,(long)n) ? o : *(void**)p)
373	}
374elif	aso note{ i386|i386-64 asm compare and swap }end link{
375		#include "FEATURE/common"
376
377		static uint32_t
378		cas32(uint32_t volatile* p, uint32_t o, uint32_t n)
379		{
380			uint32_t	r;
381
382			__asm__ __volatile__ (
383				"lock ; cmpxchg %3,%4"
384				: "=a"(r), "=m"(*p)
385				: "0"(o), "q"(n), "m"(*p)
386				: "memory", "cc"
387				);
388			return r;
389		}
390
391		#if _ast_sizeof_pointer == 8
392
393		static uint64_t
394		cas64(uint64_t volatile* p, uint64_t o, uint64_t n)
395		{
396			uint64_t	r;
397
398			__asm__ __volatile__ (
399				"lock ; cmpxchg %3,%4"
400				: "=a"(r), "=m"(*p)
401				: "0"(o), "q"(n), "m"(*p)
402				: "memory", "cc"
403				);
404			return r;
405		}
406
407		#else
408
409		#define cas64(p,o,n)	(*(p))
410
411		#endif
412
413		int main()
414		{
415			uint32_t	i = 0;
416			uint64_t	j = 0;
417			return cas32(&i, 0, 1) || cas64(&j, 0, 1);
418		}
419	}end && {
420		static uint32_t
421		cas32(uint32_t volatile* p, uint32_t o, uint32_t n)
422		{
423			uint32_t	r;
424
425			__asm__ __volatile__ (
426				"lock ; cmpxchg %3,%4"
427				: "=a"(r), "=m"(*p)
428				: "0"(o), "q"(n), "m"(*p)
429				: "memory", "cc"
430				);
431			return r;
432		}
433
434		#if _ast_sizeof_pointer == 8
435
436		static uint64_t
437		cas64(uint64_t volatile* p, uint64_t o, uint64_t n)
438		{
439			uint64_t	r;
440
441			__asm__ __volatile__ (
442				"lock ; cmpxchg %3,%4"
443				: "=a"(r), "=m"(*p)
444				: "0"(o), "q"(n), "m"(*p)
445				: "memory", "cc"
446				);
447			return r;
448		}
449
450		#endif
451
452		#define _aso_cas32(p,o,n)	cas32(p,o,n)
453		#if _ast_sizeof_pointer == 8
454		#define _aso_cas64(p,o,n)	cas64(p,o,n)
455		#define _aso_casptr(p,o,n)	((void*)cas64((uint64_t*)p,(uint64_t)o,(uint64_t)n))
456		#else
457		#define _aso_casptr(p,o,n)	((void*)cas32((uint32_t*)p,(uint32_t)o,(uint32_t)n))
458		#endif
459	}
460elif	aso note{ ia64 asm compare and swap }end link{
461		#include "FEATURE/common"
462
463		static uint32_t
464		cas32(uint32_t volatile* p, uint32_t o, uint32_t n)
465		{
466			uint32_t	r;
467
468			__asm__ __volatile__ (
469				"zxt4 %3=%3 ;; mov ar.ccv=%3 ;; cmpxchg4.acq %0=%1,%2,ar.ccv"
470			        : "=r"(r), "+S"(*p)
471				: "r"(n), "r"(o) : "memory"
472				);
473			return r;
474		}
475
476		static uint64_t
477		cas64(uint64_t volatile* p, uint64_t o, uint64_t n)
478		{
479			uint64_t	r;
480
481			__asm__ __volatile__ (
482				"mov ar.ccv=%3 ;; cmpxchg8.acq %0=%1,%2,ar.ccv"
483			        : "=r"(r), "+S"(*p)
484				: "r"(n), "r"(o) : "memory"
485				);
486			return r;
487		}
488
489		int main()
490		{
491			uint32_t	i = 0;
492			uint64_t	j = 0;
493			return cas32(&i, 0, 1) || cas64(&j, 0, 1);
494		}
495	}end && {
496		static uint32_t
497		cas32(uint32_t volatile* p, uint32_t o, uint32_t n)
498		{
499			uint32_t	r;
500
501			__asm__ __volatile__ (
502				"zxt4 %3=%3 ;; mov ar.ccv=%3 ;; cmpxchg4.acq %0=%1,%2,ar.ccv"
503			        : "=r"(r), "+S"(*p)
504				: "r"(n), "r"(o) : "memory"
505				);
506			return r;
507		}
508
509		static uint64_t
510		cas64(uint64_t volatile* p, uint64_t o, uint64_t n)
511		{
512			uint64_t	r;
513
514			__asm__ __volatile__ (
515				"mov ar.ccv=%3 ;; cmpxchg8.acq %0=%1,%2,ar.ccv"
516			        : "=r"(r), "+S"(*p)
517				: "r"(n), "r"(o) : "memory"
518				);
519			return r;
520		}
521
522		#define _aso_cas32(p,o,n)	cas32(p,o,n)
523		#define _aso_cas64(p,o,n)	cas64(p,o,n)
524		#if _ast_sizeof_pointer == 8
525		#define _aso_casptr(p,o,n)	((void*)cas64((uint64_t*)p,(uint64_t)o,(uint64_t)n))
526		#else
527		#define _aso_casptr(p,o,n)	((void*)cas32((uint32_t*)p,(uint32_t)o,(uint32_t)n))
528		#endif
529	}
530elif	aso note{ ppc asm compare and swap }end link{
531		#include "FEATURE/common"
532
533		static uint32_t
534		cas32(uint32_t volatile* p, uint32_t o, uint32_t n)
535		{
536			int	r;
537
538			__asm__ __volatile__ (
539				"0:	lwarx %0,0,%1 ;"
540				"	xor. %0,%3,%0;"
541				"	bne 1f;"
542				"	stwcx. %2,0,%1;"
543				"	bne- 0b;"
544				"1:"
545				: "=&r"(r)
546				: "r"(p), "r"(n), "r"(o)
547				: "cr0", "memory"
548				);
549			__asm__ __volatile__ ("isync" : : : "memory");
550			return r ? *p : o;
551		}
552
553		static uint64_t
554		cas64(uint64_t volatile* p, uint64_t o, uint64_t n)
555		{
556			long	r;
557
558			__asm__ __volatile__ (
559				"0:	ldarx %0,0,%1 ;"
560				"	xor. %0,%3,%0;"
561				"	bne 1f;"
562				"	stdcx. %2,0,%1;"
563				"	bne- 0b;"
564				"1:"
565				: "=&r"(r)
566				: "r"(p), "r"(n), "r"(o)
567				: "cr0", "memory"
568				);
569			__asm__ __volatile__ ("isync" : : : "memory");
570			return r ? *p : o;
571		}
572
573		int main()
574		{
575			uint32_t	i = 0;
576			uint64_t	j = 0;
577			return cas32(&i, 0, 1) || cas64(&j, 0, 1);
578		}
579	}end && {
580		static uint32_t
581		cas32(uint32_t volatile* p, uint32_t o, uint32_t n)
582		{
583			int	r;
584
585			__asm__ __volatile__ (
586				"0:	lwarx %0,0,%1 ;"
587				"	xor. %0,%3,%0;"
588				"	bne 1f;"
589				"	stwcx. %2,0,%1;"
590				"	bne- 0b;"
591				"1:"
592				: "=&r"(r)
593				: "r"(p), "r"(n), "r"(o)
594				: "cr0", "memory"
595				);
596			__asm__ __volatile__ ("isync" : : : "memory");
597			return r ? *p : o;
598		}
599
600		static uint64_t
601		cas64(uint64_t volatile* p, uint64_t o, uint64_t n)
602		{
603			long	r;
604
605			__asm__ __volatile__ (
606				"0:	ldarx %0,0,%1 ;"
607				"	xor. %0,%3,%0;"
608				"	bne 1f;"
609				"	stdcx. %2,0,%1;"
610				"	bne- 0b;"
611				"1:"
612				: "=&r"(r)
613				: "r"(p), "r"(n), "r"(o)
614				: "cr0", "memory"
615				);
616			__asm__ __volatile__ ("isync" : : : "memory");
617			return r ? *p : o;
618		}
619
620		#define _aso_cas32(p,o,n)	cas32(p,o,n)
621		#define _aso_cas64(p,o,n)	cas64(p,o,n)
622		#if _ast_sizeof_pointer == 8
623		#define _aso_casptr(p,o,n)	((void*)cas64((uint64_t*)p,(uint64_t)o,(uint64_t)n))
624		#else
625		#define _aso_casptr(p,o,n)	((void*)cas32((uint32_t*)p,(uint32_t)o,(uint32_t)n))
626		#endif
627	}
628endif
629