xref: /titanic_52/usr/src/common/atomic/sparcv9/atomic.s (revision 7c478bd95313f5f23a4c958a745db2134aa03244)
1*7c478bd9Sstevel@tonic-gate/*
2*7c478bd9Sstevel@tonic-gate * CDDL HEADER START
3*7c478bd9Sstevel@tonic-gate *
4*7c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the
5*7c478bd9Sstevel@tonic-gate * Common Development and Distribution License, Version 1.0 only
6*7c478bd9Sstevel@tonic-gate * (the "License").  You may not use this file except in compliance
7*7c478bd9Sstevel@tonic-gate * with the License.
8*7c478bd9Sstevel@tonic-gate *
9*7c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10*7c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing.
11*7c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions
12*7c478bd9Sstevel@tonic-gate * and limitations under the License.
13*7c478bd9Sstevel@tonic-gate *
14*7c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each
15*7c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16*7c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the
17*7c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying
18*7c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner]
19*7c478bd9Sstevel@tonic-gate *
20*7c478bd9Sstevel@tonic-gate * CDDL HEADER END
21*7c478bd9Sstevel@tonic-gate */
22*7c478bd9Sstevel@tonic-gate/*
23*7c478bd9Sstevel@tonic-gate * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
24*7c478bd9Sstevel@tonic-gate * Use is subject to license terms.
25*7c478bd9Sstevel@tonic-gate */
26*7c478bd9Sstevel@tonic-gate
27*7c478bd9Sstevel@tonic-gate	.ident	"%Z%%M%	%I%	%E% SMI"
28*7c478bd9Sstevel@tonic-gate
29*7c478bd9Sstevel@tonic-gate	.file	"%M%"
30*7c478bd9Sstevel@tonic-gate
31*7c478bd9Sstevel@tonic-gate#include <sys/asm_linkage.h>
32*7c478bd9Sstevel@tonic-gate
33*7c478bd9Sstevel@tonic-gate#if defined(_KERNEL)
34*7c478bd9Sstevel@tonic-gate	/*
35*7c478bd9Sstevel@tonic-gate	 * Legacy kernel interfaces; they will go away (eventually).
36*7c478bd9Sstevel@tonic-gate	 */
37*7c478bd9Sstevel@tonic-gate	ANSI_PRAGMA_WEAK2(cas8,atomic_cas_8,function)
38*7c478bd9Sstevel@tonic-gate	ANSI_PRAGMA_WEAK2(cas32,atomic_cas_32,function)
39*7c478bd9Sstevel@tonic-gate	ANSI_PRAGMA_WEAK2(cas64,atomic_cas_64,function)
40*7c478bd9Sstevel@tonic-gate	ANSI_PRAGMA_WEAK2(caslong,atomic_cas_ulong,function)
41*7c478bd9Sstevel@tonic-gate	ANSI_PRAGMA_WEAK2(casptr,atomic_cas_ptr,function)
42*7c478bd9Sstevel@tonic-gate	ANSI_PRAGMA_WEAK2(atomic_and_long,atomic_and_ulong,function)
43*7c478bd9Sstevel@tonic-gate	ANSI_PRAGMA_WEAK2(atomic_or_long,atomic_or_ulong,function)
44*7c478bd9Sstevel@tonic-gate	ANSI_PRAGMA_WEAK2(swapl,atomic_swap_32,function)
45*7c478bd9Sstevel@tonic-gate#else
46*7c478bd9Sstevel@tonic-gate	/*
47*7c478bd9Sstevel@tonic-gate	 * Include the definitions for the libc weak aliases.
48*7c478bd9Sstevel@tonic-gate	 */
49*7c478bd9Sstevel@tonic-gate#include "../atomic_asm_weak.h"
50*7c478bd9Sstevel@tonic-gate#endif
51*7c478bd9Sstevel@tonic-gate
52*7c478bd9Sstevel@tonic-gate	ENTRY(atomic_inc_8)
53*7c478bd9Sstevel@tonic-gate	ALTENTRY(atomic_inc_8_nv)
54*7c478bd9Sstevel@tonic-gate	ALTENTRY(atomic_inc_uchar)
55*7c478bd9Sstevel@tonic-gate	ALTENTRY(atomic_inc_uchar_nv)
56*7c478bd9Sstevel@tonic-gate	ba	add_8
57*7c478bd9Sstevel@tonic-gate	  add	%g0, 1, %o1
58*7c478bd9Sstevel@tonic-gate	SET_SIZE(atomic_inc_uchar_nv)
59*7c478bd9Sstevel@tonic-gate	SET_SIZE(atomic_inc_uchar)
60*7c478bd9Sstevel@tonic-gate	SET_SIZE(atomic_inc_8_nv)
61*7c478bd9Sstevel@tonic-gate	SET_SIZE(atomic_inc_8)
62*7c478bd9Sstevel@tonic-gate
63*7c478bd9Sstevel@tonic-gate	ENTRY(atomic_dec_8)
64*7c478bd9Sstevel@tonic-gate	ALTENTRY(atomic_dec_8_nv)
65*7c478bd9Sstevel@tonic-gate	ALTENTRY(atomic_dec_uchar)
66*7c478bd9Sstevel@tonic-gate	ALTENTRY(atomic_dec_uchar_nv)
67*7c478bd9Sstevel@tonic-gate	ba	add_8
68*7c478bd9Sstevel@tonic-gate	  sub	%g0, 1, %o1
69*7c478bd9Sstevel@tonic-gate	SET_SIZE(atomic_dec_uchar_nv)
70*7c478bd9Sstevel@tonic-gate	SET_SIZE(atomic_dec_uchar)
71*7c478bd9Sstevel@tonic-gate	SET_SIZE(atomic_dec_8_nv)
72*7c478bd9Sstevel@tonic-gate	SET_SIZE(atomic_dec_8)
73*7c478bd9Sstevel@tonic-gate
74*7c478bd9Sstevel@tonic-gate	ENTRY(atomic_add_8)
75*7c478bd9Sstevel@tonic-gate	ALTENTRY(atomic_add_8_nv)
76*7c478bd9Sstevel@tonic-gate	ALTENTRY(atomic_add_char)
77*7c478bd9Sstevel@tonic-gate	ALTENTRY(atomic_add_char_nv)
78*7c478bd9Sstevel@tonic-gateadd_8:
79*7c478bd9Sstevel@tonic-gate	and	%o0, 0x3, %o4		! %o4 = byte offset, left-to-right
80*7c478bd9Sstevel@tonic-gate	xor	%o4, 0x3, %g1		! %g1 = byte offset, right-to-left
81*7c478bd9Sstevel@tonic-gate	sll	%g1, 3, %g1		! %g1 = bit offset, right-to-left
82*7c478bd9Sstevel@tonic-gate	set	0xff, %o3		! %o3 = mask
83*7c478bd9Sstevel@tonic-gate	sll	%o3, %g1, %o3		! %o3 = shifted to bit offset
84*7c478bd9Sstevel@tonic-gate	sll	%o1, %g1, %o1		! %o1 = shifted to bit offset
85*7c478bd9Sstevel@tonic-gate	and	%o1, %o3, %o1		! %o1 = single byte value
86*7c478bd9Sstevel@tonic-gate	andn	%o0, 0x3, %o0		! %o0 = word address
87*7c478bd9Sstevel@tonic-gate	ld	[%o0], %o2		! read old value
88*7c478bd9Sstevel@tonic-gate1:
89*7c478bd9Sstevel@tonic-gate	add	%o2, %o1, %o5		! add value to the old value
90*7c478bd9Sstevel@tonic-gate	and	%o5, %o3, %o5		! clear other bits
91*7c478bd9Sstevel@tonic-gate	andn	%o2, %o3, %o4		! clear target bits
92*7c478bd9Sstevel@tonic-gate	or	%o4, %o5, %o5		! insert the new value
93*7c478bd9Sstevel@tonic-gate	cas	[%o0], %o2, %o5
94*7c478bd9Sstevel@tonic-gate	cmp	%o2, %o5
95*7c478bd9Sstevel@tonic-gate	bne,a,pn %icc, 1b
96*7c478bd9Sstevel@tonic-gate	  mov	%o5, %o2		! %o2 = old value
97*7c478bd9Sstevel@tonic-gate	add	%o2, %o1, %o5
98*7c478bd9Sstevel@tonic-gate	and	%o5, %o3, %o5
99*7c478bd9Sstevel@tonic-gate	retl
100*7c478bd9Sstevel@tonic-gate	srl	%o5, %g1, %o0		! %o0 = new value
101*7c478bd9Sstevel@tonic-gate	SET_SIZE(atomic_add_char_nv)
102*7c478bd9Sstevel@tonic-gate	SET_SIZE(atomic_add_char)
103*7c478bd9Sstevel@tonic-gate	SET_SIZE(atomic_add_8_nv)
104*7c478bd9Sstevel@tonic-gate	SET_SIZE(atomic_add_8)
105*7c478bd9Sstevel@tonic-gate
106*7c478bd9Sstevel@tonic-gate	ENTRY(atomic_inc_16)
107*7c478bd9Sstevel@tonic-gate	ALTENTRY(atomic_inc_16_nv)
108*7c478bd9Sstevel@tonic-gate	ALTENTRY(atomic_inc_ushort)
109*7c478bd9Sstevel@tonic-gate	ALTENTRY(atomic_inc_ushort_nv)
110*7c478bd9Sstevel@tonic-gate	ba	add_16
111*7c478bd9Sstevel@tonic-gate	  add	%g0, 1, %o1
112*7c478bd9Sstevel@tonic-gate	SET_SIZE(atomic_inc_ushort_nv)
113*7c478bd9Sstevel@tonic-gate	SET_SIZE(atomic_inc_ushort)
114*7c478bd9Sstevel@tonic-gate	SET_SIZE(atomic_inc_16_nv)
115*7c478bd9Sstevel@tonic-gate	SET_SIZE(atomic_inc_16)
116*7c478bd9Sstevel@tonic-gate
117*7c478bd9Sstevel@tonic-gate	ENTRY(atomic_dec_16)
118*7c478bd9Sstevel@tonic-gate	ALTENTRY(atomic_dec_16_nv)
119*7c478bd9Sstevel@tonic-gate	ALTENTRY(atomic_dec_ushort)
120*7c478bd9Sstevel@tonic-gate	ALTENTRY(atomic_dec_ushort_nv)
121*7c478bd9Sstevel@tonic-gate	ba	add_16
122*7c478bd9Sstevel@tonic-gate	  sub	%g0, 1, %o1
123*7c478bd9Sstevel@tonic-gate	SET_SIZE(atomic_dec_ushort_nv)
124*7c478bd9Sstevel@tonic-gate	SET_SIZE(atomic_dec_ushort)
125*7c478bd9Sstevel@tonic-gate	SET_SIZE(atomic_dec_16_nv)
126*7c478bd9Sstevel@tonic-gate	SET_SIZE(atomic_dec_16)
127*7c478bd9Sstevel@tonic-gate
128*7c478bd9Sstevel@tonic-gate	ENTRY(atomic_add_16)
129*7c478bd9Sstevel@tonic-gate	ALTENTRY(atomic_add_16_nv)
130*7c478bd9Sstevel@tonic-gate	ALTENTRY(atomic_add_short)
131*7c478bd9Sstevel@tonic-gate	ALTENTRY(atomic_add_short_nv)
132*7c478bd9Sstevel@tonic-gateadd_16:
133*7c478bd9Sstevel@tonic-gate	and	%o0, 0x2, %o4		! %o4 = byte offset, left-to-right
134*7c478bd9Sstevel@tonic-gate	xor	%o4, 0x2, %g1		! %g1 = byte offset, right-to-left
135*7c478bd9Sstevel@tonic-gate	sll	%o4, 3, %o4		! %o4 = bit offset, left-to-right
136*7c478bd9Sstevel@tonic-gate	sll	%g1, 3, %g1		! %g1 = bit offset, right-to-left
137*7c478bd9Sstevel@tonic-gate	sethi	%hi(0xffff0000), %o3	! %o3 = mask
138*7c478bd9Sstevel@tonic-gate	srl	%o3, %o4, %o3		! %o3 = shifted to bit offset
139*7c478bd9Sstevel@tonic-gate	sll	%o1, %g1, %o1		! %o1 = shifted to bit offset
140*7c478bd9Sstevel@tonic-gate	and	%o1, %o3, %o1		! %o1 = single short value
141*7c478bd9Sstevel@tonic-gate	andn	%o0, 0x2, %o0		! %o0 = word address
142*7c478bd9Sstevel@tonic-gate	! if low-order bit is 1, we will properly get an alignment fault here
143*7c478bd9Sstevel@tonic-gate	ld	[%o0], %o2		! read old value
144*7c478bd9Sstevel@tonic-gate1:
145*7c478bd9Sstevel@tonic-gate	add	%o1, %o2, %o5		! add value to the old value
146*7c478bd9Sstevel@tonic-gate	and	%o5, %o3, %o5		! clear other bits
147*7c478bd9Sstevel@tonic-gate	andn	%o2, %o3, %o4		! clear target bits
148*7c478bd9Sstevel@tonic-gate	or	%o4, %o5, %o5		! insert the new value
149*7c478bd9Sstevel@tonic-gate	cas	[%o0], %o2, %o5
150*7c478bd9Sstevel@tonic-gate	cmp	%o2, %o5
151*7c478bd9Sstevel@tonic-gate	bne,a,pn %icc, 1b
152*7c478bd9Sstevel@tonic-gate	  mov	%o5, %o2		! %o2 = old value
153*7c478bd9Sstevel@tonic-gate	add	%o1, %o2, %o5
154*7c478bd9Sstevel@tonic-gate	and	%o5, %o3, %o5
155*7c478bd9Sstevel@tonic-gate	retl
156*7c478bd9Sstevel@tonic-gate	srl	%o5, %g1, %o0		! %o0 = new value
157*7c478bd9Sstevel@tonic-gate	SET_SIZE(atomic_add_short_nv)
158*7c478bd9Sstevel@tonic-gate	SET_SIZE(atomic_add_short)
159*7c478bd9Sstevel@tonic-gate	SET_SIZE(atomic_add_16_nv)
160*7c478bd9Sstevel@tonic-gate	SET_SIZE(atomic_add_16)
161*7c478bd9Sstevel@tonic-gate
162*7c478bd9Sstevel@tonic-gate	ENTRY(atomic_inc_32)
163*7c478bd9Sstevel@tonic-gate	ALTENTRY(atomic_inc_32_nv)
164*7c478bd9Sstevel@tonic-gate	ALTENTRY(atomic_inc_uint)
165*7c478bd9Sstevel@tonic-gate	ALTENTRY(atomic_inc_uint_nv)
166*7c478bd9Sstevel@tonic-gate	ba	add_32
167*7c478bd9Sstevel@tonic-gate	  add	%g0, 1, %o1
168*7c478bd9Sstevel@tonic-gate	SET_SIZE(atomic_inc_uint_nv)
169*7c478bd9Sstevel@tonic-gate	SET_SIZE(atomic_inc_uint)
170*7c478bd9Sstevel@tonic-gate	SET_SIZE(atomic_inc_32_nv)
171*7c478bd9Sstevel@tonic-gate	SET_SIZE(atomic_inc_32)
172*7c478bd9Sstevel@tonic-gate
173*7c478bd9Sstevel@tonic-gate	ENTRY(atomic_dec_32)
174*7c478bd9Sstevel@tonic-gate	ALTENTRY(atomic_dec_32_nv)
175*7c478bd9Sstevel@tonic-gate	ALTENTRY(atomic_dec_uint)
176*7c478bd9Sstevel@tonic-gate	ALTENTRY(atomic_dec_uint_nv)
177*7c478bd9Sstevel@tonic-gate	ba	add_32
178*7c478bd9Sstevel@tonic-gate	  sub	%g0, 1, %o1
179*7c478bd9Sstevel@tonic-gate	SET_SIZE(atomic_dec_uint_nv)
180*7c478bd9Sstevel@tonic-gate	SET_SIZE(atomic_dec_uint)
181*7c478bd9Sstevel@tonic-gate	SET_SIZE(atomic_dec_32_nv)
182*7c478bd9Sstevel@tonic-gate	SET_SIZE(atomic_dec_32)
183*7c478bd9Sstevel@tonic-gate
184*7c478bd9Sstevel@tonic-gate	ENTRY(atomic_add_32)
185*7c478bd9Sstevel@tonic-gate	ALTENTRY(atomic_add_32_nv)
186*7c478bd9Sstevel@tonic-gate	ALTENTRY(atomic_add_int)
187*7c478bd9Sstevel@tonic-gate	ALTENTRY(atomic_add_int_nv)
188*7c478bd9Sstevel@tonic-gateadd_32:
189*7c478bd9Sstevel@tonic-gate	ld	[%o0], %o2
190*7c478bd9Sstevel@tonic-gate1:
191*7c478bd9Sstevel@tonic-gate	add	%o2, %o1, %o3
192*7c478bd9Sstevel@tonic-gate	cas	[%o0], %o2, %o3
193*7c478bd9Sstevel@tonic-gate	cmp	%o2, %o3
194*7c478bd9Sstevel@tonic-gate	bne,a,pn %icc, 1b
195*7c478bd9Sstevel@tonic-gate	  mov	%o3, %o2
196*7c478bd9Sstevel@tonic-gate	retl
197*7c478bd9Sstevel@tonic-gate	add	%o2, %o1, %o0		! return new value
198*7c478bd9Sstevel@tonic-gate	SET_SIZE(atomic_add_int_nv)
199*7c478bd9Sstevel@tonic-gate	SET_SIZE(atomic_add_int)
200*7c478bd9Sstevel@tonic-gate	SET_SIZE(atomic_add_32_nv)
201*7c478bd9Sstevel@tonic-gate	SET_SIZE(atomic_add_32)
202*7c478bd9Sstevel@tonic-gate
203*7c478bd9Sstevel@tonic-gate	ENTRY(atomic_inc_64)
204*7c478bd9Sstevel@tonic-gate	ALTENTRY(atomic_inc_64_nv)
205*7c478bd9Sstevel@tonic-gate	ALTENTRY(atomic_inc_ulong)
206*7c478bd9Sstevel@tonic-gate	ALTENTRY(atomic_inc_ulong_nv)
207*7c478bd9Sstevel@tonic-gate	ba	add_64
208*7c478bd9Sstevel@tonic-gate	  add	%g0, 1, %o1
209*7c478bd9Sstevel@tonic-gate	SET_SIZE(atomic_inc_ulong_nv)
210*7c478bd9Sstevel@tonic-gate	SET_SIZE(atomic_inc_ulong)
211*7c478bd9Sstevel@tonic-gate	SET_SIZE(atomic_inc_64_nv)
212*7c478bd9Sstevel@tonic-gate	SET_SIZE(atomic_inc_64)
213*7c478bd9Sstevel@tonic-gate
214*7c478bd9Sstevel@tonic-gate	ENTRY(atomic_dec_64)
215*7c478bd9Sstevel@tonic-gate	ALTENTRY(atomic_dec_64_nv)
216*7c478bd9Sstevel@tonic-gate	ALTENTRY(atomic_dec_ulong)
217*7c478bd9Sstevel@tonic-gate	ALTENTRY(atomic_dec_ulong_nv)
218*7c478bd9Sstevel@tonic-gate	ba	add_64
219*7c478bd9Sstevel@tonic-gate	  sub	%g0, 1, %o1
220*7c478bd9Sstevel@tonic-gate	SET_SIZE(atomic_dec_ulong_nv)
221*7c478bd9Sstevel@tonic-gate	SET_SIZE(atomic_dec_ulong)
222*7c478bd9Sstevel@tonic-gate	SET_SIZE(atomic_dec_64_nv)
223*7c478bd9Sstevel@tonic-gate	SET_SIZE(atomic_dec_64)
224*7c478bd9Sstevel@tonic-gate
225*7c478bd9Sstevel@tonic-gate	ENTRY(atomic_add_64)
226*7c478bd9Sstevel@tonic-gate	ALTENTRY(atomic_add_64_nv)
227*7c478bd9Sstevel@tonic-gate	ALTENTRY(atomic_add_ptr)
228*7c478bd9Sstevel@tonic-gate	ALTENTRY(atomic_add_ptr_nv)
229*7c478bd9Sstevel@tonic-gate	ALTENTRY(atomic_add_long)
230*7c478bd9Sstevel@tonic-gate	ALTENTRY(atomic_add_long_nv)
231*7c478bd9Sstevel@tonic-gateadd_64:
232*7c478bd9Sstevel@tonic-gate	ldx	[%o0], %o2
233*7c478bd9Sstevel@tonic-gate1:
234*7c478bd9Sstevel@tonic-gate	add	%o2, %o1, %o3
235*7c478bd9Sstevel@tonic-gate	casx	[%o0], %o2, %o3
236*7c478bd9Sstevel@tonic-gate	cmp	%o2, %o3
237*7c478bd9Sstevel@tonic-gate	bne,a,pn %xcc, 1b
238*7c478bd9Sstevel@tonic-gate	  mov	%o3, %o2
239*7c478bd9Sstevel@tonic-gate	retl
240*7c478bd9Sstevel@tonic-gate	add	%o2, %o1, %o0		! return new value
241*7c478bd9Sstevel@tonic-gate	SET_SIZE(atomic_add_long_nv)
242*7c478bd9Sstevel@tonic-gate	SET_SIZE(atomic_add_long)
243*7c478bd9Sstevel@tonic-gate	SET_SIZE(atomic_add_ptr_nv)
244*7c478bd9Sstevel@tonic-gate	SET_SIZE(atomic_add_ptr)
245*7c478bd9Sstevel@tonic-gate	SET_SIZE(atomic_add_64_nv)
246*7c478bd9Sstevel@tonic-gate	SET_SIZE(atomic_add_64)
247*7c478bd9Sstevel@tonic-gate
248*7c478bd9Sstevel@tonic-gate	ENTRY(atomic_or_8)
249*7c478bd9Sstevel@tonic-gate	ALTENTRY(atomic_or_8_nv)
250*7c478bd9Sstevel@tonic-gate	ALTENTRY(atomic_or_uchar)
251*7c478bd9Sstevel@tonic-gate	ALTENTRY(atomic_or_uchar_nv)
252*7c478bd9Sstevel@tonic-gate	and	%o0, 0x3, %o4		! %o4 = byte offset, left-to-right
253*7c478bd9Sstevel@tonic-gate	xor	%o4, 0x3, %g1		! %g1 = byte offset, right-to-left
254*7c478bd9Sstevel@tonic-gate	sll	%g1, 3, %g1		! %g1 = bit offset, right-to-left
255*7c478bd9Sstevel@tonic-gate	set	0xff, %o3		! %o3 = mask
256*7c478bd9Sstevel@tonic-gate	sll	%o3, %g1, %o3		! %o3 = shifted to bit offset
257*7c478bd9Sstevel@tonic-gate	sll	%o1, %g1, %o1		! %o1 = shifted to bit offset
258*7c478bd9Sstevel@tonic-gate	and	%o1, %o3, %o1		! %o1 = single byte value
259*7c478bd9Sstevel@tonic-gate	andn	%o0, 0x3, %o0		! %o0 = word address
260*7c478bd9Sstevel@tonic-gate	ld	[%o0], %o2		! read old value
261*7c478bd9Sstevel@tonic-gate1:
262*7c478bd9Sstevel@tonic-gate	or	%o2, %o1, %o5		! or in the new value
263*7c478bd9Sstevel@tonic-gate	cas	[%o0], %o2, %o5
264*7c478bd9Sstevel@tonic-gate	cmp	%o2, %o5
265*7c478bd9Sstevel@tonic-gate	bne,a,pn %icc, 1b
266*7c478bd9Sstevel@tonic-gate	  mov	%o5, %o2		! %o2 = old value
267*7c478bd9Sstevel@tonic-gate	or	%o2, %o1, %o5
268*7c478bd9Sstevel@tonic-gate	and	%o5, %o3, %o5
269*7c478bd9Sstevel@tonic-gate	retl
270*7c478bd9Sstevel@tonic-gate	srl	%o5, %g1, %o0		! %o0 = new value
271*7c478bd9Sstevel@tonic-gate	SET_SIZE(atomic_or_uchar_nv)
272*7c478bd9Sstevel@tonic-gate	SET_SIZE(atomic_or_uchar)
273*7c478bd9Sstevel@tonic-gate	SET_SIZE(atomic_or_8_nv)
274*7c478bd9Sstevel@tonic-gate	SET_SIZE(atomic_or_8)
275*7c478bd9Sstevel@tonic-gate
276*7c478bd9Sstevel@tonic-gate	ENTRY(atomic_or_16)
277*7c478bd9Sstevel@tonic-gate	ALTENTRY(atomic_or_16_nv)
278*7c478bd9Sstevel@tonic-gate	ALTENTRY(atomic_or_ushort)
279*7c478bd9Sstevel@tonic-gate	ALTENTRY(atomic_or_ushort_nv)
280*7c478bd9Sstevel@tonic-gate	and	%o0, 0x2, %o4		! %o4 = byte offset, left-to-right
281*7c478bd9Sstevel@tonic-gate	xor	%o4, 0x2, %g1		! %g1 = byte offset, right-to-left
282*7c478bd9Sstevel@tonic-gate	sll	%o4, 3, %o4		! %o4 = bit offset, left-to-right
283*7c478bd9Sstevel@tonic-gate	sll	%g1, 3, %g1		! %g1 = bit offset, right-to-left
284*7c478bd9Sstevel@tonic-gate	sethi	%hi(0xffff0000), %o3	! %o3 = mask
285*7c478bd9Sstevel@tonic-gate	srl	%o3, %o4, %o3		! %o3 = shifted to bit offset
286*7c478bd9Sstevel@tonic-gate	sll	%o1, %g1, %o1		! %o1 = shifted to bit offset
287*7c478bd9Sstevel@tonic-gate	and	%o1, %o3, %o1		! %o1 = single short value
288*7c478bd9Sstevel@tonic-gate	andn	%o0, 0x2, %o0		! %o0 = word address
289*7c478bd9Sstevel@tonic-gate	! if low-order bit is 1, we will properly get an alignment fault here
290*7c478bd9Sstevel@tonic-gate	ld	[%o0], %o2		! read old value
291*7c478bd9Sstevel@tonic-gate1:
292*7c478bd9Sstevel@tonic-gate	or	%o2, %o1, %o5		! or in the new value
293*7c478bd9Sstevel@tonic-gate	cas	[%o0], %o2, %o5
294*7c478bd9Sstevel@tonic-gate	cmp	%o2, %o5
295*7c478bd9Sstevel@tonic-gate	bne,a,pn %icc, 1b
296*7c478bd9Sstevel@tonic-gate	  mov	%o5, %o2		! %o2 = old value
297*7c478bd9Sstevel@tonic-gate	or	%o2, %o1, %o5		! or in the new value
298*7c478bd9Sstevel@tonic-gate	and	%o5, %o3, %o5
299*7c478bd9Sstevel@tonic-gate	retl
300*7c478bd9Sstevel@tonic-gate	srl	%o5, %g1, %o0		! %o0 = new value
301*7c478bd9Sstevel@tonic-gate	SET_SIZE(atomic_or_ushort_nv)
302*7c478bd9Sstevel@tonic-gate	SET_SIZE(atomic_or_ushort)
303*7c478bd9Sstevel@tonic-gate	SET_SIZE(atomic_or_16_nv)
304*7c478bd9Sstevel@tonic-gate	SET_SIZE(atomic_or_16)
305*7c478bd9Sstevel@tonic-gate
306*7c478bd9Sstevel@tonic-gate	ENTRY(atomic_or_32)
307*7c478bd9Sstevel@tonic-gate	ALTENTRY(atomic_or_32_nv)
308*7c478bd9Sstevel@tonic-gate	ALTENTRY(atomic_or_uint)
309*7c478bd9Sstevel@tonic-gate	ALTENTRY(atomic_or_uint_nv)
310*7c478bd9Sstevel@tonic-gate	ld	[%o0], %o2
311*7c478bd9Sstevel@tonic-gate1:
312*7c478bd9Sstevel@tonic-gate	or	%o2, %o1, %o3
313*7c478bd9Sstevel@tonic-gate	cas	[%o0], %o2, %o3
314*7c478bd9Sstevel@tonic-gate	cmp	%o2, %o3
315*7c478bd9Sstevel@tonic-gate	bne,a,pn %icc, 1b
316*7c478bd9Sstevel@tonic-gate	  mov	%o3, %o2
317*7c478bd9Sstevel@tonic-gate	retl
318*7c478bd9Sstevel@tonic-gate	or	%o2, %o1, %o0		! return new value
319*7c478bd9Sstevel@tonic-gate	SET_SIZE(atomic_or_uint_nv)
320*7c478bd9Sstevel@tonic-gate	SET_SIZE(atomic_or_uint)
321*7c478bd9Sstevel@tonic-gate	SET_SIZE(atomic_or_32_nv)
322*7c478bd9Sstevel@tonic-gate	SET_SIZE(atomic_or_32)
323*7c478bd9Sstevel@tonic-gate
324*7c478bd9Sstevel@tonic-gate	ENTRY(atomic_or_64)
325*7c478bd9Sstevel@tonic-gate	ALTENTRY(atomic_or_64_nv)
326*7c478bd9Sstevel@tonic-gate	ALTENTRY(atomic_or_ulong)
327*7c478bd9Sstevel@tonic-gate	ALTENTRY(atomic_or_ulong_nv)
328*7c478bd9Sstevel@tonic-gate	ldx	[%o0], %o2
329*7c478bd9Sstevel@tonic-gate1:
330*7c478bd9Sstevel@tonic-gate	or	%o2, %o1, %o3
331*7c478bd9Sstevel@tonic-gate	casx	[%o0], %o2, %o3
332*7c478bd9Sstevel@tonic-gate	cmp	%o2, %o3
333*7c478bd9Sstevel@tonic-gate	bne,a,pn %xcc, 1b
334*7c478bd9Sstevel@tonic-gate	  mov	%o3, %o2
335*7c478bd9Sstevel@tonic-gate	retl
336*7c478bd9Sstevel@tonic-gate	or	%o2, %o1, %o0		! return new value
337*7c478bd9Sstevel@tonic-gate	SET_SIZE(atomic_or_ulong_nv)
338*7c478bd9Sstevel@tonic-gate	SET_SIZE(atomic_or_ulong)
339*7c478bd9Sstevel@tonic-gate	SET_SIZE(atomic_or_64_nv)
340*7c478bd9Sstevel@tonic-gate	SET_SIZE(atomic_or_64)
341*7c478bd9Sstevel@tonic-gate
342*7c478bd9Sstevel@tonic-gate	ENTRY(atomic_and_8)
343*7c478bd9Sstevel@tonic-gate	ALTENTRY(atomic_and_8_nv)
344*7c478bd9Sstevel@tonic-gate	ALTENTRY(atomic_and_uchar)
345*7c478bd9Sstevel@tonic-gate	ALTENTRY(atomic_and_uchar_nv)
346*7c478bd9Sstevel@tonic-gate	and	%o0, 0x3, %o4		! %o4 = byte offset, left-to-right
347*7c478bd9Sstevel@tonic-gate	xor	%o4, 0x3, %g1		! %g1 = byte offset, right-to-left
348*7c478bd9Sstevel@tonic-gate	sll	%g1, 3, %g1		! %g1 = bit offset, right-to-left
349*7c478bd9Sstevel@tonic-gate	set	0xff, %o3		! %o3 = mask
350*7c478bd9Sstevel@tonic-gate	sll	%o3, %g1, %o3		! %o3 = shifted to bit offset
351*7c478bd9Sstevel@tonic-gate	sll	%o1, %g1, %o1		! %o1 = shifted to bit offset
352*7c478bd9Sstevel@tonic-gate	orn	%o1, %o3, %o1		! all ones in other bytes
353*7c478bd9Sstevel@tonic-gate	andn	%o0, 0x3, %o0		! %o0 = word address
354*7c478bd9Sstevel@tonic-gate	ld	[%o0], %o2		! read old value
355*7c478bd9Sstevel@tonic-gate1:
356*7c478bd9Sstevel@tonic-gate	and	%o2, %o1, %o5		! and in the new value
357*7c478bd9Sstevel@tonic-gate	cas	[%o0], %o2, %o5
358*7c478bd9Sstevel@tonic-gate	cmp	%o2, %o5
359*7c478bd9Sstevel@tonic-gate	bne,a,pn %icc, 1b
360*7c478bd9Sstevel@tonic-gate	  mov	%o5, %o2		! %o2 = old value
361*7c478bd9Sstevel@tonic-gate	and	%o2, %o1, %o5
362*7c478bd9Sstevel@tonic-gate	and	%o5, %o3, %o5
363*7c478bd9Sstevel@tonic-gate	retl
364*7c478bd9Sstevel@tonic-gate	srl	%o5, %g1, %o0		! %o0 = new value
365*7c478bd9Sstevel@tonic-gate	SET_SIZE(atomic_and_uchar_nv)
366*7c478bd9Sstevel@tonic-gate	SET_SIZE(atomic_and_uchar)
367*7c478bd9Sstevel@tonic-gate	SET_SIZE(atomic_and_8_nv)
368*7c478bd9Sstevel@tonic-gate	SET_SIZE(atomic_and_8)
369*7c478bd9Sstevel@tonic-gate
370*7c478bd9Sstevel@tonic-gate	ENTRY(atomic_and_16)
371*7c478bd9Sstevel@tonic-gate	ALTENTRY(atomic_and_16_nv)
372*7c478bd9Sstevel@tonic-gate	ALTENTRY(atomic_and_ushort)
373*7c478bd9Sstevel@tonic-gate	ALTENTRY(atomic_and_ushort_nv)
374*7c478bd9Sstevel@tonic-gate	and	%o0, 0x2, %o4		! %o4 = byte offset, left-to-right
375*7c478bd9Sstevel@tonic-gate	xor	%o4, 0x2, %g1		! %g1 = byte offset, right-to-left
376*7c478bd9Sstevel@tonic-gate	sll	%o4, 3, %o4		! %o4 = bit offset, left-to-right
377*7c478bd9Sstevel@tonic-gate	sll	%g1, 3, %g1		! %g1 = bit offset, right-to-left
378*7c478bd9Sstevel@tonic-gate	sethi	%hi(0xffff0000), %o3	! %o3 = mask
379*7c478bd9Sstevel@tonic-gate	srl	%o3, %o4, %o3		! %o3 = shifted to bit offset
380*7c478bd9Sstevel@tonic-gate	sll	%o1, %g1, %o1		! %o1 = shifted to bit offset
381*7c478bd9Sstevel@tonic-gate	orn	%o1, %o3, %o1		! all ones in the other half
382*7c478bd9Sstevel@tonic-gate	andn	%o0, 0x2, %o0		! %o0 = word address
383*7c478bd9Sstevel@tonic-gate	! if low-order bit is 1, we will properly get an alignment fault here
384*7c478bd9Sstevel@tonic-gate	ld	[%o0], %o2		! read old value
385*7c478bd9Sstevel@tonic-gate1:
386*7c478bd9Sstevel@tonic-gate	and	%o2, %o1, %o5		! and in the new value
387*7c478bd9Sstevel@tonic-gate	cas	[%o0], %o2, %o5
388*7c478bd9Sstevel@tonic-gate	cmp	%o2, %o5
389*7c478bd9Sstevel@tonic-gate	bne,a,pn %icc, 1b
390*7c478bd9Sstevel@tonic-gate	  mov	%o5, %o2		! %o2 = old value
391*7c478bd9Sstevel@tonic-gate	and	%o2, %o1, %o5
392*7c478bd9Sstevel@tonic-gate	and	%o5, %o3, %o5
393*7c478bd9Sstevel@tonic-gate	retl
394*7c478bd9Sstevel@tonic-gate	srl	%o5, %g1, %o0		! %o0 = new value
395*7c478bd9Sstevel@tonic-gate	SET_SIZE(atomic_and_ushort_nv)
396*7c478bd9Sstevel@tonic-gate	SET_SIZE(atomic_and_ushort)
397*7c478bd9Sstevel@tonic-gate	SET_SIZE(atomic_and_16_nv)
398*7c478bd9Sstevel@tonic-gate	SET_SIZE(atomic_and_16)
399*7c478bd9Sstevel@tonic-gate
400*7c478bd9Sstevel@tonic-gate	ENTRY(atomic_and_32)
401*7c478bd9Sstevel@tonic-gate	ALTENTRY(atomic_and_32_nv)
402*7c478bd9Sstevel@tonic-gate	ALTENTRY(atomic_and_uint)
403*7c478bd9Sstevel@tonic-gate	ALTENTRY(atomic_and_uint_nv)
404*7c478bd9Sstevel@tonic-gate	ld	[%o0], %o2
405*7c478bd9Sstevel@tonic-gate1:
406*7c478bd9Sstevel@tonic-gate	and	%o2, %o1, %o3
407*7c478bd9Sstevel@tonic-gate	cas	[%o0], %o2, %o3
408*7c478bd9Sstevel@tonic-gate	cmp	%o2, %o3
409*7c478bd9Sstevel@tonic-gate	bne,a,pn %icc, 1b
410*7c478bd9Sstevel@tonic-gate	  mov	%o3, %o2
411*7c478bd9Sstevel@tonic-gate	retl
412*7c478bd9Sstevel@tonic-gate	and	%o2, %o1, %o0		! return new value
413*7c478bd9Sstevel@tonic-gate	SET_SIZE(atomic_and_uint_nv)
414*7c478bd9Sstevel@tonic-gate	SET_SIZE(atomic_and_uint)
415*7c478bd9Sstevel@tonic-gate	SET_SIZE(atomic_and_32_nv)
416*7c478bd9Sstevel@tonic-gate	SET_SIZE(atomic_and_32)
417*7c478bd9Sstevel@tonic-gate
418*7c478bd9Sstevel@tonic-gate	ENTRY(atomic_and_64)
419*7c478bd9Sstevel@tonic-gate	ALTENTRY(atomic_and_64_nv)
420*7c478bd9Sstevel@tonic-gate	ALTENTRY(atomic_and_ulong)
421*7c478bd9Sstevel@tonic-gate	ALTENTRY(atomic_and_ulong_nv)
422*7c478bd9Sstevel@tonic-gate	ldx	[%o0], %o2
423*7c478bd9Sstevel@tonic-gate1:
424*7c478bd9Sstevel@tonic-gate	and	%o2, %o1, %o3
425*7c478bd9Sstevel@tonic-gate	casx	[%o0], %o2, %o3
426*7c478bd9Sstevel@tonic-gate	cmp	%o2, %o3
427*7c478bd9Sstevel@tonic-gate	bne,a,pn %xcc, 1b
428*7c478bd9Sstevel@tonic-gate	  mov	%o3, %o2
429*7c478bd9Sstevel@tonic-gate	retl
430*7c478bd9Sstevel@tonic-gate	and	%o2, %o1, %o0		! return new value
431*7c478bd9Sstevel@tonic-gate	SET_SIZE(atomic_and_ulong_nv)
432*7c478bd9Sstevel@tonic-gate	SET_SIZE(atomic_and_ulong)
433*7c478bd9Sstevel@tonic-gate	SET_SIZE(atomic_and_64_nv)
434*7c478bd9Sstevel@tonic-gate	SET_SIZE(atomic_and_64)
435*7c478bd9Sstevel@tonic-gate
436*7c478bd9Sstevel@tonic-gate	ENTRY(atomic_cas_8)
437*7c478bd9Sstevel@tonic-gate	ALTENTRY(atomic_cas_uchar)
438*7c478bd9Sstevel@tonic-gate	and	%o0, 0x3, %o4		! %o4 = byte offset, left-to-right
439*7c478bd9Sstevel@tonic-gate	xor	%o4, 0x3, %g1		! %g1 = byte offset, right-to-left
440*7c478bd9Sstevel@tonic-gate	sll	%g1, 3, %g1		! %g1 = bit offset, right-to-left
441*7c478bd9Sstevel@tonic-gate	set	0xff, %o3		! %o3 = mask
442*7c478bd9Sstevel@tonic-gate	sll	%o3, %g1, %o3		! %o3 = shifted to bit offset
443*7c478bd9Sstevel@tonic-gate	sll	%o1, %g1, %o1		! %o1 = shifted to bit offset
444*7c478bd9Sstevel@tonic-gate	and	%o1, %o3, %o1		! %o1 = single byte value
445*7c478bd9Sstevel@tonic-gate	sll	%o2, %g1, %o2		! %o2 = shifted to bit offset
446*7c478bd9Sstevel@tonic-gate	and	%o2, %o3, %o2		! %o2 = single byte value
447*7c478bd9Sstevel@tonic-gate	andn	%o0, 0x3, %o0		! %o0 = word address
448*7c478bd9Sstevel@tonic-gate	ld	[%o0], %o4		! read old value
449*7c478bd9Sstevel@tonic-gate1:
450*7c478bd9Sstevel@tonic-gate	andn	%o4, %o3, %o4		! clear target bits
451*7c478bd9Sstevel@tonic-gate	or	%o4, %o2, %o5		! insert the new value
452*7c478bd9Sstevel@tonic-gate	or	%o4, %o1, %o4		! insert the comparison value
453*7c478bd9Sstevel@tonic-gate	cas	[%o0], %o4, %o5
454*7c478bd9Sstevel@tonic-gate	cmp	%o4, %o5		! did we succeed?
455*7c478bd9Sstevel@tonic-gate	be,pt	%icc, 2f
456*7c478bd9Sstevel@tonic-gate	  and	%o5, %o3, %o4		! isolate the old value
457*7c478bd9Sstevel@tonic-gate	cmp	%o1, %o4		! should we have succeeded?
458*7c478bd9Sstevel@tonic-gate	be,a,pt	%icc, 1b		! yes, try again
459*7c478bd9Sstevel@tonic-gate	  mov	%o5, %o4		! %o4 = old value
460*7c478bd9Sstevel@tonic-gate2:
461*7c478bd9Sstevel@tonic-gate	retl
462*7c478bd9Sstevel@tonic-gate	srl	%o4, %g1, %o0		! %o0 = old value
463*7c478bd9Sstevel@tonic-gate	SET_SIZE(atomic_cas_uchar)
464*7c478bd9Sstevel@tonic-gate	SET_SIZE(atomic_cas_8)
465*7c478bd9Sstevel@tonic-gate
466*7c478bd9Sstevel@tonic-gate	ENTRY(atomic_cas_16)
467*7c478bd9Sstevel@tonic-gate	ALTENTRY(atomic_cas_ushort)
468*7c478bd9Sstevel@tonic-gate	and	%o0, 0x2, %o4		! %o4 = byte offset, left-to-right
469*7c478bd9Sstevel@tonic-gate	xor	%o4, 0x2, %g1		! %g1 = byte offset, right-to-left
470*7c478bd9Sstevel@tonic-gate	sll	%o4, 3, %o4		! %o4 = bit offset, left-to-right
471*7c478bd9Sstevel@tonic-gate	sll	%g1, 3, %g1		! %g1 = bit offset, right-to-left
472*7c478bd9Sstevel@tonic-gate	sethi	%hi(0xffff0000), %o3	! %o3 = mask
473*7c478bd9Sstevel@tonic-gate	srl	%o3, %o4, %o3		! %o3 = shifted to bit offset
474*7c478bd9Sstevel@tonic-gate	sll	%o1, %g1, %o1		! %o1 = shifted to bit offset
475*7c478bd9Sstevel@tonic-gate	and	%o1, %o3, %o1		! %o1 = single short value
476*7c478bd9Sstevel@tonic-gate	sll	%o2, %g1, %o2		! %o2 = shifted to bit offset
477*7c478bd9Sstevel@tonic-gate	and	%o2, %o3, %o2		! %o2 = single short value
478*7c478bd9Sstevel@tonic-gate	andn	%o0, 0x2, %o0		! %o0 = word address
479*7c478bd9Sstevel@tonic-gate	! if low-order bit is 1, we will properly get an alignment fault here
480*7c478bd9Sstevel@tonic-gate	ld	[%o0], %o4		! read old value
481*7c478bd9Sstevel@tonic-gate1:
482*7c478bd9Sstevel@tonic-gate	andn	%o4, %o3, %o4		! clear target bits
483*7c478bd9Sstevel@tonic-gate	or	%o4, %o2, %o5		! insert the new value
484*7c478bd9Sstevel@tonic-gate	or	%o4, %o1, %o4		! insert the comparison value
485*7c478bd9Sstevel@tonic-gate	cas	[%o0], %o4, %o5
486*7c478bd9Sstevel@tonic-gate	cmp	%o4, %o5		! did we succeed?
487*7c478bd9Sstevel@tonic-gate	be,pt	%icc, 2f
488*7c478bd9Sstevel@tonic-gate	  and	%o5, %o3, %o4		! isolate the old value
489*7c478bd9Sstevel@tonic-gate	cmp	%o1, %o4		! should we have succeeded?
490*7c478bd9Sstevel@tonic-gate	be,a,pt	%icc, 1b		! yes, try again
491*7c478bd9Sstevel@tonic-gate	  mov	%o5, %o4		! %o4 = old value
492*7c478bd9Sstevel@tonic-gate2:
493*7c478bd9Sstevel@tonic-gate	retl
494*7c478bd9Sstevel@tonic-gate	srl	%o4, %g1, %o0		! %o0 = old value
495*7c478bd9Sstevel@tonic-gate	SET_SIZE(atomic_cas_ushort)
496*7c478bd9Sstevel@tonic-gate	SET_SIZE(atomic_cas_16)
497*7c478bd9Sstevel@tonic-gate
498*7c478bd9Sstevel@tonic-gate	ENTRY(atomic_cas_32)
499*7c478bd9Sstevel@tonic-gate	ALTENTRY(atomic_cas_uint)
500*7c478bd9Sstevel@tonic-gate	cas	[%o0], %o1, %o2
501*7c478bd9Sstevel@tonic-gate	retl
502*7c478bd9Sstevel@tonic-gate	mov	%o2, %o0
503*7c478bd9Sstevel@tonic-gate	SET_SIZE(atomic_cas_uint)
504*7c478bd9Sstevel@tonic-gate	SET_SIZE(atomic_cas_32)
505*7c478bd9Sstevel@tonic-gate
506*7c478bd9Sstevel@tonic-gate	ENTRY(atomic_cas_64)
507*7c478bd9Sstevel@tonic-gate	ALTENTRY(atomic_cas_ptr)
508*7c478bd9Sstevel@tonic-gate	ALTENTRY(atomic_cas_ulong)
509*7c478bd9Sstevel@tonic-gate	casx	[%o0], %o1, %o2
510*7c478bd9Sstevel@tonic-gate	retl
511*7c478bd9Sstevel@tonic-gate	mov	%o2, %o0
512*7c478bd9Sstevel@tonic-gate	SET_SIZE(atomic_cas_ulong)
513*7c478bd9Sstevel@tonic-gate	SET_SIZE(atomic_cas_ptr)
514*7c478bd9Sstevel@tonic-gate	SET_SIZE(atomic_cas_64)
515*7c478bd9Sstevel@tonic-gate
516*7c478bd9Sstevel@tonic-gate	ENTRY(atomic_swap_8)
517*7c478bd9Sstevel@tonic-gate	ALTENTRY(atomic_swap_uchar)
518*7c478bd9Sstevel@tonic-gate	and	%o0, 0x3, %o4		! %o4 = byte offset, left-to-right
519*7c478bd9Sstevel@tonic-gate	xor	%o4, 0x3, %g1		! %g1 = byte offset, right-to-left
520*7c478bd9Sstevel@tonic-gate	sll	%g1, 3, %g1		! %g1 = bit offset, right-to-left
521*7c478bd9Sstevel@tonic-gate	set	0xff, %o3		! %o3 = mask
522*7c478bd9Sstevel@tonic-gate	sll	%o3, %g1, %o3		! %o3 = shifted to bit offset
523*7c478bd9Sstevel@tonic-gate	sll	%o1, %g1, %o1		! %o1 = shifted to bit offset
524*7c478bd9Sstevel@tonic-gate	and	%o1, %o3, %o1		! %o1 = single byte value
525*7c478bd9Sstevel@tonic-gate	andn	%o0, 0x3, %o0		! %o0 = word address
526*7c478bd9Sstevel@tonic-gate	ld	[%o0], %o2		! read old value
527*7c478bd9Sstevel@tonic-gate1:
528*7c478bd9Sstevel@tonic-gate	andn	%o2, %o3, %o5		! clear target bits
529*7c478bd9Sstevel@tonic-gate	or	%o5, %o1, %o5		! insert the new value
530*7c478bd9Sstevel@tonic-gate	cas	[%o0], %o2, %o5
531*7c478bd9Sstevel@tonic-gate	cmp	%o2, %o5
532*7c478bd9Sstevel@tonic-gate	bne,a,pn %icc, 1b
533*7c478bd9Sstevel@tonic-gate	  mov	%o5, %o2		! %o2 = old value
534*7c478bd9Sstevel@tonic-gate	and	%o5, %o3, %o5
535*7c478bd9Sstevel@tonic-gate	retl
536*7c478bd9Sstevel@tonic-gate	srl	%o5, %g1, %o0		! %o0 = old value
537*7c478bd9Sstevel@tonic-gate	SET_SIZE(atomic_swap_uchar)
538*7c478bd9Sstevel@tonic-gate	SET_SIZE(atomic_swap_8)
539*7c478bd9Sstevel@tonic-gate
540*7c478bd9Sstevel@tonic-gate	ENTRY(atomic_swap_16)
541*7c478bd9Sstevel@tonic-gate	ALTENTRY(atomic_swap_ushort)
542*7c478bd9Sstevel@tonic-gate	and	%o0, 0x2, %o4		! %o4 = byte offset, left-to-right
543*7c478bd9Sstevel@tonic-gate	xor	%o4, 0x2, %g1		! %g1 = byte offset, right-to-left
544*7c478bd9Sstevel@tonic-gate	sll	%o4, 3, %o4		! %o4 = bit offset, left-to-right
545*7c478bd9Sstevel@tonic-gate	sll	%g1, 3, %g1		! %g1 = bit offset, right-to-left
546*7c478bd9Sstevel@tonic-gate	sethi	%hi(0xffff0000), %o3	! %o3 = mask
547*7c478bd9Sstevel@tonic-gate	srl	%o3, %o4, %o3		! %o3 = shifted to bit offset
548*7c478bd9Sstevel@tonic-gate	sll	%o1, %g1, %o1		! %o1 = shifted to bit offset
549*7c478bd9Sstevel@tonic-gate	and	%o1, %o3, %o1		! %o1 = single short value
550*7c478bd9Sstevel@tonic-gate	andn	%o0, 0x2, %o0		! %o0 = word address
551*7c478bd9Sstevel@tonic-gate	! if low-order bit is 1, we will properly get an alignment fault here
552*7c478bd9Sstevel@tonic-gate	ld	[%o0], %o2		! read old value
553*7c478bd9Sstevel@tonic-gate1:
554*7c478bd9Sstevel@tonic-gate	andn	%o2, %o3, %o5		! clear target bits
555*7c478bd9Sstevel@tonic-gate	or	%o5, %o1, %o5		! insert the new value
556*7c478bd9Sstevel@tonic-gate	cas	[%o0], %o2, %o5
557*7c478bd9Sstevel@tonic-gate	cmp	%o2, %o5
558*7c478bd9Sstevel@tonic-gate	bne,a,pn %icc, 1b
559*7c478bd9Sstevel@tonic-gate	  mov	%o5, %o2		! %o2 = old value
560*7c478bd9Sstevel@tonic-gate	and	%o5, %o3, %o5
561*7c478bd9Sstevel@tonic-gate	retl
562*7c478bd9Sstevel@tonic-gate	srl	%o5, %g1, %o0		! %o0 = old value
563*7c478bd9Sstevel@tonic-gate	SET_SIZE(atomic_swap_ushort)
564*7c478bd9Sstevel@tonic-gate	SET_SIZE(atomic_swap_16)
565*7c478bd9Sstevel@tonic-gate
566*7c478bd9Sstevel@tonic-gate	ENTRY(atomic_swap_32)
567*7c478bd9Sstevel@tonic-gate	ALTENTRY(atomic_swap_uint)
568*7c478bd9Sstevel@tonic-gate	ld	[%o0], %o2
569*7c478bd9Sstevel@tonic-gate1:
570*7c478bd9Sstevel@tonic-gate	mov	%o1, %o3
571*7c478bd9Sstevel@tonic-gate	cas	[%o0], %o2, %o3
572*7c478bd9Sstevel@tonic-gate	cmp	%o2, %o3
573*7c478bd9Sstevel@tonic-gate	bne,a,pn %icc, 1b
574*7c478bd9Sstevel@tonic-gate	  mov	%o3, %o2
575*7c478bd9Sstevel@tonic-gate	retl
576*7c478bd9Sstevel@tonic-gate	mov	%o3, %o0
577*7c478bd9Sstevel@tonic-gate	SET_SIZE(atomic_swap_uint)
578*7c478bd9Sstevel@tonic-gate	SET_SIZE(atomic_swap_32)
579*7c478bd9Sstevel@tonic-gate
580*7c478bd9Sstevel@tonic-gate	ENTRY(atomic_swap_64)
581*7c478bd9Sstevel@tonic-gate	ALTENTRY(atomic_swap_ptr)
582*7c478bd9Sstevel@tonic-gate	ALTENTRY(atomic_swap_ulong)
583*7c478bd9Sstevel@tonic-gate	ldx	[%o0], %o2
584*7c478bd9Sstevel@tonic-gate1:
585*7c478bd9Sstevel@tonic-gate	mov	%o1, %o3
586*7c478bd9Sstevel@tonic-gate	casx	[%o0], %o2, %o3
587*7c478bd9Sstevel@tonic-gate	cmp	%o2, %o3
588*7c478bd9Sstevel@tonic-gate	bne,a,pn %xcc, 1b
589*7c478bd9Sstevel@tonic-gate	  mov	%o3, %o2
590*7c478bd9Sstevel@tonic-gate	retl
591*7c478bd9Sstevel@tonic-gate	mov	%o3, %o0
592*7c478bd9Sstevel@tonic-gate	SET_SIZE(atomic_swap_ulong)
593*7c478bd9Sstevel@tonic-gate	SET_SIZE(atomic_swap_ptr)
594*7c478bd9Sstevel@tonic-gate	SET_SIZE(atomic_swap_64)
595*7c478bd9Sstevel@tonic-gate
596*7c478bd9Sstevel@tonic-gate	ENTRY(atomic_set_long_excl)
597*7c478bd9Sstevel@tonic-gate	mov	1, %o3
598*7c478bd9Sstevel@tonic-gate	slln	%o3, %o1, %o3
599*7c478bd9Sstevel@tonic-gate	ldn	[%o0], %o2
600*7c478bd9Sstevel@tonic-gate1:
601*7c478bd9Sstevel@tonic-gate	andcc	%o2, %o3, %g0		! test if the bit is set
602*7c478bd9Sstevel@tonic-gate	bnz,a,pn %ncc, 2f		! if so, then fail out
603*7c478bd9Sstevel@tonic-gate	  mov	-1, %o0
604*7c478bd9Sstevel@tonic-gate	or	%o2, %o3, %o4		! set the bit, and try to commit it
605*7c478bd9Sstevel@tonic-gate	casn	[%o0], %o2, %o4
606*7c478bd9Sstevel@tonic-gate	cmp	%o2, %o4
607*7c478bd9Sstevel@tonic-gate	bne,a,pn %ncc, 1b		! failed to commit, try again
608*7c478bd9Sstevel@tonic-gate	  mov	%o4, %o2
609*7c478bd9Sstevel@tonic-gate	mov	%g0, %o0
610*7c478bd9Sstevel@tonic-gate2:
611*7c478bd9Sstevel@tonic-gate	retl
612*7c478bd9Sstevel@tonic-gate	nop
613*7c478bd9Sstevel@tonic-gate	SET_SIZE(atomic_set_long_excl)
614*7c478bd9Sstevel@tonic-gate
615*7c478bd9Sstevel@tonic-gate	ENTRY(atomic_clear_long_excl)
616*7c478bd9Sstevel@tonic-gate	mov	1, %o3
617*7c478bd9Sstevel@tonic-gate	slln	%o3, %o1, %o3
618*7c478bd9Sstevel@tonic-gate	ldn	[%o0], %o2
619*7c478bd9Sstevel@tonic-gate1:
620*7c478bd9Sstevel@tonic-gate	andncc	%o3, %o2, %g0		! test if the bit is clear
621*7c478bd9Sstevel@tonic-gate	bnz,a,pn %ncc, 2f		! if so, then fail out
622*7c478bd9Sstevel@tonic-gate	  mov	-1, %o0
623*7c478bd9Sstevel@tonic-gate	andn	%o2, %o3, %o4		! clear the bit, and try to commit it
624*7c478bd9Sstevel@tonic-gate	casn	[%o0], %o2, %o4
625*7c478bd9Sstevel@tonic-gate	cmp	%o2, %o4
626*7c478bd9Sstevel@tonic-gate	bne,a,pn %ncc, 1b		! failed to commit, try again
627*7c478bd9Sstevel@tonic-gate	  mov	%o4, %o2
628*7c478bd9Sstevel@tonic-gate	mov	%g0, %o0
629*7c478bd9Sstevel@tonic-gate2:
630*7c478bd9Sstevel@tonic-gate	retl
631*7c478bd9Sstevel@tonic-gate	nop
632*7c478bd9Sstevel@tonic-gate	SET_SIZE(atomic_clear_long_excl)
633*7c478bd9Sstevel@tonic-gate
634*7c478bd9Sstevel@tonic-gate#if !defined(_KERNEL)
635*7c478bd9Sstevel@tonic-gate
636*7c478bd9Sstevel@tonic-gate	/*
637*7c478bd9Sstevel@tonic-gate	 * Spitfires and Blackbirds have a problem with membars in the
638*7c478bd9Sstevel@tonic-gate	 * delay slot (SF_ERRATA_51).  For safety's sake, we assume
639*7c478bd9Sstevel@tonic-gate	 * that the whole world needs the workaround.
640*7c478bd9Sstevel@tonic-gate	 */
641*7c478bd9Sstevel@tonic-gate	ENTRY(membar_enter)
642*7c478bd9Sstevel@tonic-gate	membar	#StoreLoad|#StoreStore
643*7c478bd9Sstevel@tonic-gate	retl
644*7c478bd9Sstevel@tonic-gate	nop
645*7c478bd9Sstevel@tonic-gate	SET_SIZE(membar_enter)
646*7c478bd9Sstevel@tonic-gate
647*7c478bd9Sstevel@tonic-gate	ENTRY(membar_exit)
648*7c478bd9Sstevel@tonic-gate	membar	#LoadStore|#StoreStore
649*7c478bd9Sstevel@tonic-gate	retl
650*7c478bd9Sstevel@tonic-gate	nop
651*7c478bd9Sstevel@tonic-gate	SET_SIZE(membar_exit)
652*7c478bd9Sstevel@tonic-gate
653*7c478bd9Sstevel@tonic-gate	ENTRY(membar_producer)
654*7c478bd9Sstevel@tonic-gate	membar	#StoreStore
655*7c478bd9Sstevel@tonic-gate	retl
656*7c478bd9Sstevel@tonic-gate	nop
657*7c478bd9Sstevel@tonic-gate	SET_SIZE(membar_producer)
658*7c478bd9Sstevel@tonic-gate
659*7c478bd9Sstevel@tonic-gate	ENTRY(membar_consumer)
660*7c478bd9Sstevel@tonic-gate	membar	#LoadLoad
661*7c478bd9Sstevel@tonic-gate	retl
662*7c478bd9Sstevel@tonic-gate	nop
663*7c478bd9Sstevel@tonic-gate	SET_SIZE(membar_consumer)
664*7c478bd9Sstevel@tonic-gate
665*7c478bd9Sstevel@tonic-gate#endif	/* !_KERNEL */
666