xref: /titanic_54/usr/src/common/atomic/sparc/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	ALTENTRY(atomic_inc_ulong)
167*7c478bd9Sstevel@tonic-gate	ALTENTRY(atomic_inc_ulong_nv)
168*7c478bd9Sstevel@tonic-gate	ba	add_32
169*7c478bd9Sstevel@tonic-gate	  add	%g0, 1, %o1
170*7c478bd9Sstevel@tonic-gate	SET_SIZE(atomic_inc_ulong_nv)
171*7c478bd9Sstevel@tonic-gate	SET_SIZE(atomic_inc_ulong)
172*7c478bd9Sstevel@tonic-gate	SET_SIZE(atomic_inc_uint_nv)
173*7c478bd9Sstevel@tonic-gate	SET_SIZE(atomic_inc_uint)
174*7c478bd9Sstevel@tonic-gate	SET_SIZE(atomic_inc_32_nv)
175*7c478bd9Sstevel@tonic-gate	SET_SIZE(atomic_inc_32)
176*7c478bd9Sstevel@tonic-gate
177*7c478bd9Sstevel@tonic-gate	ENTRY(atomic_dec_32)
178*7c478bd9Sstevel@tonic-gate	ALTENTRY(atomic_dec_32_nv)
179*7c478bd9Sstevel@tonic-gate	ALTENTRY(atomic_dec_uint)
180*7c478bd9Sstevel@tonic-gate	ALTENTRY(atomic_dec_uint_nv)
181*7c478bd9Sstevel@tonic-gate	ALTENTRY(atomic_dec_ulong)
182*7c478bd9Sstevel@tonic-gate	ALTENTRY(atomic_dec_ulong_nv)
183*7c478bd9Sstevel@tonic-gate	ba	add_32
184*7c478bd9Sstevel@tonic-gate	  sub	%g0, 1, %o1
185*7c478bd9Sstevel@tonic-gate	SET_SIZE(atomic_dec_ulong_nv)
186*7c478bd9Sstevel@tonic-gate	SET_SIZE(atomic_dec_ulong)
187*7c478bd9Sstevel@tonic-gate	SET_SIZE(atomic_dec_uint_nv)
188*7c478bd9Sstevel@tonic-gate	SET_SIZE(atomic_dec_uint)
189*7c478bd9Sstevel@tonic-gate	SET_SIZE(atomic_dec_32_nv)
190*7c478bd9Sstevel@tonic-gate	SET_SIZE(atomic_dec_32)
191*7c478bd9Sstevel@tonic-gate
192*7c478bd9Sstevel@tonic-gate	ENTRY(atomic_add_32)
193*7c478bd9Sstevel@tonic-gate	ALTENTRY(atomic_add_32_nv)
194*7c478bd9Sstevel@tonic-gate	ALTENTRY(atomic_add_int)
195*7c478bd9Sstevel@tonic-gate	ALTENTRY(atomic_add_int_nv)
196*7c478bd9Sstevel@tonic-gate	ALTENTRY(atomic_add_ptr)
197*7c478bd9Sstevel@tonic-gate	ALTENTRY(atomic_add_ptr_nv)
198*7c478bd9Sstevel@tonic-gate	ALTENTRY(atomic_add_long)
199*7c478bd9Sstevel@tonic-gate	ALTENTRY(atomic_add_long_nv)
200*7c478bd9Sstevel@tonic-gateadd_32:
201*7c478bd9Sstevel@tonic-gate	ld	[%o0], %o2
202*7c478bd9Sstevel@tonic-gate1:
203*7c478bd9Sstevel@tonic-gate	add	%o2, %o1, %o3
204*7c478bd9Sstevel@tonic-gate	cas	[%o0], %o2, %o3
205*7c478bd9Sstevel@tonic-gate	cmp	%o2, %o3
206*7c478bd9Sstevel@tonic-gate	bne,a,pn %icc, 1b
207*7c478bd9Sstevel@tonic-gate	  mov	%o3, %o2
208*7c478bd9Sstevel@tonic-gate	retl
209*7c478bd9Sstevel@tonic-gate	add	%o2, %o1, %o0		! return new value
210*7c478bd9Sstevel@tonic-gate	SET_SIZE(atomic_add_long_nv)
211*7c478bd9Sstevel@tonic-gate	SET_SIZE(atomic_add_long)
212*7c478bd9Sstevel@tonic-gate	SET_SIZE(atomic_add_ptr_nv)
213*7c478bd9Sstevel@tonic-gate	SET_SIZE(atomic_add_ptr)
214*7c478bd9Sstevel@tonic-gate	SET_SIZE(atomic_add_int_nv)
215*7c478bd9Sstevel@tonic-gate	SET_SIZE(atomic_add_int)
216*7c478bd9Sstevel@tonic-gate	SET_SIZE(atomic_add_32_nv)
217*7c478bd9Sstevel@tonic-gate	SET_SIZE(atomic_add_32)
218*7c478bd9Sstevel@tonic-gate
219*7c478bd9Sstevel@tonic-gate	ENTRY(atomic_inc_64)
220*7c478bd9Sstevel@tonic-gate	ALTENTRY(atomic_inc_64_nv)
221*7c478bd9Sstevel@tonic-gate	ba	add_64
222*7c478bd9Sstevel@tonic-gate	  add	%g0, 1, %o1
223*7c478bd9Sstevel@tonic-gate	SET_SIZE(atomic_inc_64_nv)
224*7c478bd9Sstevel@tonic-gate	SET_SIZE(atomic_inc_64)
225*7c478bd9Sstevel@tonic-gate
226*7c478bd9Sstevel@tonic-gate	ENTRY(atomic_dec_64)
227*7c478bd9Sstevel@tonic-gate	ALTENTRY(atomic_dec_64_nv)
228*7c478bd9Sstevel@tonic-gate	ba	add_64
229*7c478bd9Sstevel@tonic-gate	  sub	%g0, 1, %o1
230*7c478bd9Sstevel@tonic-gate	SET_SIZE(atomic_dec_64_nv)
231*7c478bd9Sstevel@tonic-gate	SET_SIZE(atomic_dec_64)
232*7c478bd9Sstevel@tonic-gate
233*7c478bd9Sstevel@tonic-gate	ENTRY(atomic_add_64)
234*7c478bd9Sstevel@tonic-gate	ALTENTRY(atomic_add_64_nv)
235*7c478bd9Sstevel@tonic-gate	sllx	%o1, 32, %o1		! upper 32 in %o1, lower in %o2
236*7c478bd9Sstevel@tonic-gate	srl	%o2, 0, %o2
237*7c478bd9Sstevel@tonic-gate	add	%o1, %o2, %o1		! convert 2 32-bit args into 1 64-bit
238*7c478bd9Sstevel@tonic-gateadd_64:
239*7c478bd9Sstevel@tonic-gate	ldx	[%o0], %o2
240*7c478bd9Sstevel@tonic-gate1:
241*7c478bd9Sstevel@tonic-gate	add	%o2, %o1, %o3
242*7c478bd9Sstevel@tonic-gate	casx	[%o0], %o2, %o3
243*7c478bd9Sstevel@tonic-gate	cmp	%o2, %o3
244*7c478bd9Sstevel@tonic-gate	bne,a,pn %xcc, 1b
245*7c478bd9Sstevel@tonic-gate	  mov	%o3, %o2
246*7c478bd9Sstevel@tonic-gate	add	%o2, %o1, %o1		! return lower 32-bits in %o1
247*7c478bd9Sstevel@tonic-gate	retl
248*7c478bd9Sstevel@tonic-gate	srlx	%o1, 32, %o0		! return upper 32-bits in %o0
249*7c478bd9Sstevel@tonic-gate	SET_SIZE(atomic_add_64_nv)
250*7c478bd9Sstevel@tonic-gate	SET_SIZE(atomic_add_64)
251*7c478bd9Sstevel@tonic-gate
252*7c478bd9Sstevel@tonic-gate	ENTRY(atomic_or_8)
253*7c478bd9Sstevel@tonic-gate	ALTENTRY(atomic_or_8_nv)
254*7c478bd9Sstevel@tonic-gate	ALTENTRY(atomic_or_uchar)
255*7c478bd9Sstevel@tonic-gate	ALTENTRY(atomic_or_uchar_nv)
256*7c478bd9Sstevel@tonic-gate	and	%o0, 0x3, %o4		! %o4 = byte offset, left-to-right
257*7c478bd9Sstevel@tonic-gate	xor	%o4, 0x3, %g1		! %g1 = byte offset, right-to-left
258*7c478bd9Sstevel@tonic-gate	sll	%g1, 3, %g1		! %g1 = bit offset, right-to-left
259*7c478bd9Sstevel@tonic-gate	set	0xff, %o3		! %o3 = mask
260*7c478bd9Sstevel@tonic-gate	sll	%o3, %g1, %o3		! %o3 = shifted to bit offset
261*7c478bd9Sstevel@tonic-gate	sll	%o1, %g1, %o1		! %o1 = shifted to bit offset
262*7c478bd9Sstevel@tonic-gate	and	%o1, %o3, %o1		! %o1 = single byte value
263*7c478bd9Sstevel@tonic-gate	andn	%o0, 0x3, %o0		! %o0 = word address
264*7c478bd9Sstevel@tonic-gate	ld	[%o0], %o2		! read old value
265*7c478bd9Sstevel@tonic-gate1:
266*7c478bd9Sstevel@tonic-gate	or	%o2, %o1, %o5		! or in the new value
267*7c478bd9Sstevel@tonic-gate	cas	[%o0], %o2, %o5
268*7c478bd9Sstevel@tonic-gate	cmp	%o2, %o5
269*7c478bd9Sstevel@tonic-gate	bne,a,pn %icc, 1b
270*7c478bd9Sstevel@tonic-gate	  mov	%o5, %o2		! %o2 = old value
271*7c478bd9Sstevel@tonic-gate	or	%o2, %o1, %o5
272*7c478bd9Sstevel@tonic-gate	and	%o5, %o3, %o5
273*7c478bd9Sstevel@tonic-gate	retl
274*7c478bd9Sstevel@tonic-gate	srl	%o5, %g1, %o0		! %o0 = new value
275*7c478bd9Sstevel@tonic-gate	SET_SIZE(atomic_or_uchar_nv)
276*7c478bd9Sstevel@tonic-gate	SET_SIZE(atomic_or_uchar)
277*7c478bd9Sstevel@tonic-gate	SET_SIZE(atomic_or_8_nv)
278*7c478bd9Sstevel@tonic-gate	SET_SIZE(atomic_or_8)
279*7c478bd9Sstevel@tonic-gate
280*7c478bd9Sstevel@tonic-gate	ENTRY(atomic_or_16)
281*7c478bd9Sstevel@tonic-gate	ALTENTRY(atomic_or_16_nv)
282*7c478bd9Sstevel@tonic-gate	ALTENTRY(atomic_or_ushort)
283*7c478bd9Sstevel@tonic-gate	ALTENTRY(atomic_or_ushort_nv)
284*7c478bd9Sstevel@tonic-gate	and	%o0, 0x2, %o4		! %o4 = byte offset, left-to-right
285*7c478bd9Sstevel@tonic-gate	xor	%o4, 0x2, %g1		! %g1 = byte offset, right-to-left
286*7c478bd9Sstevel@tonic-gate	sll	%o4, 3, %o4		! %o4 = bit offset, left-to-right
287*7c478bd9Sstevel@tonic-gate	sll	%g1, 3, %g1		! %g1 = bit offset, right-to-left
288*7c478bd9Sstevel@tonic-gate	sethi	%hi(0xffff0000), %o3	! %o3 = mask
289*7c478bd9Sstevel@tonic-gate	srl	%o3, %o4, %o3		! %o3 = shifted to bit offset
290*7c478bd9Sstevel@tonic-gate	sll	%o1, %g1, %o1		! %o1 = shifted to bit offset
291*7c478bd9Sstevel@tonic-gate	and	%o1, %o3, %o1		! %o1 = single short value
292*7c478bd9Sstevel@tonic-gate	andn	%o0, 0x2, %o0		! %o0 = word address
293*7c478bd9Sstevel@tonic-gate	! if low-order bit is 1, we will properly get an alignment fault here
294*7c478bd9Sstevel@tonic-gate	ld	[%o0], %o2		! read old value
295*7c478bd9Sstevel@tonic-gate1:
296*7c478bd9Sstevel@tonic-gate	or	%o2, %o1, %o5		! or in the new value
297*7c478bd9Sstevel@tonic-gate	cas	[%o0], %o2, %o5
298*7c478bd9Sstevel@tonic-gate	cmp	%o2, %o5
299*7c478bd9Sstevel@tonic-gate	bne,a,pn %icc, 1b
300*7c478bd9Sstevel@tonic-gate	  mov	%o5, %o2		! %o2 = old value
301*7c478bd9Sstevel@tonic-gate	or	%o2, %o1, %o5		! or in the new value
302*7c478bd9Sstevel@tonic-gate	and	%o5, %o3, %o5
303*7c478bd9Sstevel@tonic-gate	retl
304*7c478bd9Sstevel@tonic-gate	srl	%o5, %g1, %o0		! %o0 = new value
305*7c478bd9Sstevel@tonic-gate	SET_SIZE(atomic_or_ushort_nv)
306*7c478bd9Sstevel@tonic-gate	SET_SIZE(atomic_or_ushort)
307*7c478bd9Sstevel@tonic-gate	SET_SIZE(atomic_or_16_nv)
308*7c478bd9Sstevel@tonic-gate	SET_SIZE(atomic_or_16)
309*7c478bd9Sstevel@tonic-gate
310*7c478bd9Sstevel@tonic-gate	ENTRY(atomic_or_32)
311*7c478bd9Sstevel@tonic-gate	ALTENTRY(atomic_or_32_nv)
312*7c478bd9Sstevel@tonic-gate	ALTENTRY(atomic_or_uint)
313*7c478bd9Sstevel@tonic-gate	ALTENTRY(atomic_or_uint_nv)
314*7c478bd9Sstevel@tonic-gate	ALTENTRY(atomic_or_ulong)
315*7c478bd9Sstevel@tonic-gate	ALTENTRY(atomic_or_ulong_nv)
316*7c478bd9Sstevel@tonic-gate	ld	[%o0], %o2
317*7c478bd9Sstevel@tonic-gate1:
318*7c478bd9Sstevel@tonic-gate	or	%o2, %o1, %o3
319*7c478bd9Sstevel@tonic-gate	cas	[%o0], %o2, %o3
320*7c478bd9Sstevel@tonic-gate	cmp	%o2, %o3
321*7c478bd9Sstevel@tonic-gate	bne,a,pn %icc, 1b
322*7c478bd9Sstevel@tonic-gate	  mov	%o3, %o2
323*7c478bd9Sstevel@tonic-gate	retl
324*7c478bd9Sstevel@tonic-gate	or	%o2, %o1, %o0		! return new value
325*7c478bd9Sstevel@tonic-gate	SET_SIZE(atomic_or_ulong_nv)
326*7c478bd9Sstevel@tonic-gate	SET_SIZE(atomic_or_ulong)
327*7c478bd9Sstevel@tonic-gate	SET_SIZE(atomic_or_uint_nv)
328*7c478bd9Sstevel@tonic-gate	SET_SIZE(atomic_or_uint)
329*7c478bd9Sstevel@tonic-gate	SET_SIZE(atomic_or_32_nv)
330*7c478bd9Sstevel@tonic-gate	SET_SIZE(atomic_or_32)
331*7c478bd9Sstevel@tonic-gate
332*7c478bd9Sstevel@tonic-gate	ENTRY(atomic_or_64)
333*7c478bd9Sstevel@tonic-gate	ALTENTRY(atomic_or_64_nv)
334*7c478bd9Sstevel@tonic-gate	sllx	%o1, 32, %o1		! upper 32 in %o1, lower in %o2
335*7c478bd9Sstevel@tonic-gate	srl	%o2, 0, %o2
336*7c478bd9Sstevel@tonic-gate	add	%o1, %o2, %o1		! convert 2 32-bit args into 1 64-bit
337*7c478bd9Sstevel@tonic-gate	ldx	[%o0], %o2
338*7c478bd9Sstevel@tonic-gate1:
339*7c478bd9Sstevel@tonic-gate	or	%o2, %o1, %o3
340*7c478bd9Sstevel@tonic-gate	casx	[%o0], %o2, %o3
341*7c478bd9Sstevel@tonic-gate	cmp	%o2, %o3
342*7c478bd9Sstevel@tonic-gate	bne,a,pn %xcc, 1b
343*7c478bd9Sstevel@tonic-gate	  mov	%o3, %o2
344*7c478bd9Sstevel@tonic-gate	or	%o2, %o1, %o1		! return lower 32-bits in %o1
345*7c478bd9Sstevel@tonic-gate	retl
346*7c478bd9Sstevel@tonic-gate	srlx	%o1, 32, %o0		! return upper 32-bits in %o0
347*7c478bd9Sstevel@tonic-gate	SET_SIZE(atomic_or_64_nv)
348*7c478bd9Sstevel@tonic-gate	SET_SIZE(atomic_or_64)
349*7c478bd9Sstevel@tonic-gate
350*7c478bd9Sstevel@tonic-gate	ENTRY(atomic_and_8)
351*7c478bd9Sstevel@tonic-gate	ALTENTRY(atomic_and_8_nv)
352*7c478bd9Sstevel@tonic-gate	ALTENTRY(atomic_and_uchar)
353*7c478bd9Sstevel@tonic-gate	ALTENTRY(atomic_and_uchar_nv)
354*7c478bd9Sstevel@tonic-gate	and	%o0, 0x3, %o4		! %o4 = byte offset, left-to-right
355*7c478bd9Sstevel@tonic-gate	xor	%o4, 0x3, %g1		! %g1 = byte offset, right-to-left
356*7c478bd9Sstevel@tonic-gate	sll	%g1, 3, %g1		! %g1 = bit offset, right-to-left
357*7c478bd9Sstevel@tonic-gate	set	0xff, %o3		! %o3 = mask
358*7c478bd9Sstevel@tonic-gate	sll	%o3, %g1, %o3		! %o3 = shifted to bit offset
359*7c478bd9Sstevel@tonic-gate	sll	%o1, %g1, %o1		! %o1 = shifted to bit offset
360*7c478bd9Sstevel@tonic-gate	orn	%o1, %o3, %o1		! all ones in other bytes
361*7c478bd9Sstevel@tonic-gate	andn	%o0, 0x3, %o0		! %o0 = word address
362*7c478bd9Sstevel@tonic-gate	ld	[%o0], %o2		! read old value
363*7c478bd9Sstevel@tonic-gate1:
364*7c478bd9Sstevel@tonic-gate	and	%o2, %o1, %o5		! and in the new value
365*7c478bd9Sstevel@tonic-gate	cas	[%o0], %o2, %o5
366*7c478bd9Sstevel@tonic-gate	cmp	%o2, %o5
367*7c478bd9Sstevel@tonic-gate	bne,a,pn %icc, 1b
368*7c478bd9Sstevel@tonic-gate	  mov	%o5, %o2		! %o2 = old value
369*7c478bd9Sstevel@tonic-gate	and	%o2, %o1, %o5
370*7c478bd9Sstevel@tonic-gate	and	%o5, %o3, %o5
371*7c478bd9Sstevel@tonic-gate	retl
372*7c478bd9Sstevel@tonic-gate	srl	%o5, %g1, %o0		! %o0 = new value
373*7c478bd9Sstevel@tonic-gate	SET_SIZE(atomic_and_uchar_nv)
374*7c478bd9Sstevel@tonic-gate	SET_SIZE(atomic_and_uchar)
375*7c478bd9Sstevel@tonic-gate	SET_SIZE(atomic_and_8_nv)
376*7c478bd9Sstevel@tonic-gate	SET_SIZE(atomic_and_8)
377*7c478bd9Sstevel@tonic-gate
378*7c478bd9Sstevel@tonic-gate	ENTRY(atomic_and_16)
379*7c478bd9Sstevel@tonic-gate	ALTENTRY(atomic_and_16_nv)
380*7c478bd9Sstevel@tonic-gate	ALTENTRY(atomic_and_ushort)
381*7c478bd9Sstevel@tonic-gate	ALTENTRY(atomic_and_ushort_nv)
382*7c478bd9Sstevel@tonic-gate	and	%o0, 0x2, %o4		! %o4 = byte offset, left-to-right
383*7c478bd9Sstevel@tonic-gate	xor	%o4, 0x2, %g1		! %g1 = byte offset, right-to-left
384*7c478bd9Sstevel@tonic-gate	sll	%o4, 3, %o4		! %o4 = bit offset, left-to-right
385*7c478bd9Sstevel@tonic-gate	sll	%g1, 3, %g1		! %g1 = bit offset, right-to-left
386*7c478bd9Sstevel@tonic-gate	sethi	%hi(0xffff0000), %o3	! %o3 = mask
387*7c478bd9Sstevel@tonic-gate	srl	%o3, %o4, %o3		! %o3 = shifted to bit offset
388*7c478bd9Sstevel@tonic-gate	sll	%o1, %g1, %o1		! %o1 = shifted to bit offset
389*7c478bd9Sstevel@tonic-gate	orn	%o1, %o3, %o1		! all ones in the other half
390*7c478bd9Sstevel@tonic-gate	andn	%o0, 0x2, %o0		! %o0 = word address
391*7c478bd9Sstevel@tonic-gate	! if low-order bit is 1, we will properly get an alignment fault here
392*7c478bd9Sstevel@tonic-gate	ld	[%o0], %o2		! read old value
393*7c478bd9Sstevel@tonic-gate1:
394*7c478bd9Sstevel@tonic-gate	and	%o2, %o1, %o5		! and in the new value
395*7c478bd9Sstevel@tonic-gate	cas	[%o0], %o2, %o5
396*7c478bd9Sstevel@tonic-gate	cmp	%o2, %o5
397*7c478bd9Sstevel@tonic-gate	bne,a,pn %icc, 1b
398*7c478bd9Sstevel@tonic-gate	  mov	%o5, %o2		! %o2 = old value
399*7c478bd9Sstevel@tonic-gate	and	%o2, %o1, %o5
400*7c478bd9Sstevel@tonic-gate	and	%o5, %o3, %o5
401*7c478bd9Sstevel@tonic-gate	retl
402*7c478bd9Sstevel@tonic-gate	srl	%o5, %g1, %o0		! %o0 = new value
403*7c478bd9Sstevel@tonic-gate	SET_SIZE(atomic_and_ushort_nv)
404*7c478bd9Sstevel@tonic-gate	SET_SIZE(atomic_and_ushort)
405*7c478bd9Sstevel@tonic-gate	SET_SIZE(atomic_and_16_nv)
406*7c478bd9Sstevel@tonic-gate	SET_SIZE(atomic_and_16)
407*7c478bd9Sstevel@tonic-gate
408*7c478bd9Sstevel@tonic-gate	ENTRY(atomic_and_32)
409*7c478bd9Sstevel@tonic-gate	ALTENTRY(atomic_and_32_nv)
410*7c478bd9Sstevel@tonic-gate	ALTENTRY(atomic_and_uint)
411*7c478bd9Sstevel@tonic-gate	ALTENTRY(atomic_and_uint_nv)
412*7c478bd9Sstevel@tonic-gate	ALTENTRY(atomic_and_ulong)
413*7c478bd9Sstevel@tonic-gate	ALTENTRY(atomic_and_ulong_nv)
414*7c478bd9Sstevel@tonic-gate	ld	[%o0], %o2
415*7c478bd9Sstevel@tonic-gate1:
416*7c478bd9Sstevel@tonic-gate	and	%o2, %o1, %o3
417*7c478bd9Sstevel@tonic-gate	cas	[%o0], %o2, %o3
418*7c478bd9Sstevel@tonic-gate	cmp	%o2, %o3
419*7c478bd9Sstevel@tonic-gate	bne,a,pn %icc, 1b
420*7c478bd9Sstevel@tonic-gate	  mov	%o3, %o2
421*7c478bd9Sstevel@tonic-gate	retl
422*7c478bd9Sstevel@tonic-gate	and	%o2, %o1, %o0		! return new value
423*7c478bd9Sstevel@tonic-gate	SET_SIZE(atomic_and_ulong_nv)
424*7c478bd9Sstevel@tonic-gate	SET_SIZE(atomic_and_ulong)
425*7c478bd9Sstevel@tonic-gate	SET_SIZE(atomic_and_uint_nv)
426*7c478bd9Sstevel@tonic-gate	SET_SIZE(atomic_and_uint)
427*7c478bd9Sstevel@tonic-gate	SET_SIZE(atomic_and_32_nv)
428*7c478bd9Sstevel@tonic-gate	SET_SIZE(atomic_and_32)
429*7c478bd9Sstevel@tonic-gate
430*7c478bd9Sstevel@tonic-gate	ENTRY(atomic_and_64)
431*7c478bd9Sstevel@tonic-gate	ALTENTRY(atomic_and_64_nv)
432*7c478bd9Sstevel@tonic-gate	sllx	%o1, 32, %o1		! upper 32 in %o1, lower in %o2
433*7c478bd9Sstevel@tonic-gate	srl	%o2, 0, %o2
434*7c478bd9Sstevel@tonic-gate	add	%o1, %o2, %o1		! convert 2 32-bit args into 1 64-bit
435*7c478bd9Sstevel@tonic-gate	ldx	[%o0], %o2
436*7c478bd9Sstevel@tonic-gate1:
437*7c478bd9Sstevel@tonic-gate	and	%o2, %o1, %o3
438*7c478bd9Sstevel@tonic-gate	casx	[%o0], %o2, %o3
439*7c478bd9Sstevel@tonic-gate	cmp	%o2, %o3
440*7c478bd9Sstevel@tonic-gate	bne,a,pn %xcc, 1b
441*7c478bd9Sstevel@tonic-gate	  mov	%o3, %o2
442*7c478bd9Sstevel@tonic-gate	and	%o2, %o1, %o1		! return lower 32-bits in %o1
443*7c478bd9Sstevel@tonic-gate	retl
444*7c478bd9Sstevel@tonic-gate	srlx	%o1, 32, %o0		! return upper 32-bits in %o0
445*7c478bd9Sstevel@tonic-gate	SET_SIZE(atomic_and_64_nv)
446*7c478bd9Sstevel@tonic-gate	SET_SIZE(atomic_and_64)
447*7c478bd9Sstevel@tonic-gate
448*7c478bd9Sstevel@tonic-gate	ENTRY(atomic_cas_8)
449*7c478bd9Sstevel@tonic-gate	ALTENTRY(atomic_cas_uchar)
450*7c478bd9Sstevel@tonic-gate	and	%o0, 0x3, %o4		! %o4 = byte offset, left-to-right
451*7c478bd9Sstevel@tonic-gate	xor	%o4, 0x3, %g1		! %g1 = byte offset, right-to-left
452*7c478bd9Sstevel@tonic-gate	sll	%g1, 3, %g1		! %g1 = bit offset, right-to-left
453*7c478bd9Sstevel@tonic-gate	set	0xff, %o3		! %o3 = mask
454*7c478bd9Sstevel@tonic-gate	sll	%o3, %g1, %o3		! %o3 = shifted to bit offset
455*7c478bd9Sstevel@tonic-gate	sll	%o1, %g1, %o1		! %o1 = shifted to bit offset
456*7c478bd9Sstevel@tonic-gate	and	%o1, %o3, %o1		! %o1 = single byte value
457*7c478bd9Sstevel@tonic-gate	sll	%o2, %g1, %o2		! %o2 = shifted to bit offset
458*7c478bd9Sstevel@tonic-gate	and	%o2, %o3, %o2		! %o2 = single byte value
459*7c478bd9Sstevel@tonic-gate	andn	%o0, 0x3, %o0		! %o0 = word address
460*7c478bd9Sstevel@tonic-gate	ld	[%o0], %o4		! read old value
461*7c478bd9Sstevel@tonic-gate1:
462*7c478bd9Sstevel@tonic-gate	andn	%o4, %o3, %o4		! clear target bits
463*7c478bd9Sstevel@tonic-gate	or	%o4, %o2, %o5		! insert the new value
464*7c478bd9Sstevel@tonic-gate	or	%o4, %o1, %o4		! insert the comparison value
465*7c478bd9Sstevel@tonic-gate	cas	[%o0], %o4, %o5
466*7c478bd9Sstevel@tonic-gate	cmp	%o4, %o5		! did we succeed?
467*7c478bd9Sstevel@tonic-gate	be,pt	%icc, 2f
468*7c478bd9Sstevel@tonic-gate	  and	%o5, %o3, %o4		! isolate the old value
469*7c478bd9Sstevel@tonic-gate	cmp	%o1, %o4		! should we have succeeded?
470*7c478bd9Sstevel@tonic-gate	be,a,pt	%icc, 1b		! yes, try again
471*7c478bd9Sstevel@tonic-gate	  mov	%o5, %o4		! %o4 = old value
472*7c478bd9Sstevel@tonic-gate2:
473*7c478bd9Sstevel@tonic-gate	retl
474*7c478bd9Sstevel@tonic-gate	srl	%o4, %g1, %o0		! %o0 = old value
475*7c478bd9Sstevel@tonic-gate	SET_SIZE(atomic_cas_uchar)
476*7c478bd9Sstevel@tonic-gate	SET_SIZE(atomic_cas_8)
477*7c478bd9Sstevel@tonic-gate
478*7c478bd9Sstevel@tonic-gate	ENTRY(atomic_cas_16)
479*7c478bd9Sstevel@tonic-gate	ALTENTRY(atomic_cas_ushort)
480*7c478bd9Sstevel@tonic-gate	and	%o0, 0x2, %o4		! %o4 = byte offset, left-to-right
481*7c478bd9Sstevel@tonic-gate	xor	%o4, 0x2, %g1		! %g1 = byte offset, right-to-left
482*7c478bd9Sstevel@tonic-gate	sll	%o4, 3, %o4		! %o4 = bit offset, left-to-right
483*7c478bd9Sstevel@tonic-gate	sll	%g1, 3, %g1		! %g1 = bit offset, right-to-left
484*7c478bd9Sstevel@tonic-gate	sethi	%hi(0xffff0000), %o3	! %o3 = mask
485*7c478bd9Sstevel@tonic-gate	srl	%o3, %o4, %o3		! %o3 = shifted to bit offset
486*7c478bd9Sstevel@tonic-gate	sll	%o1, %g1, %o1		! %o1 = shifted to bit offset
487*7c478bd9Sstevel@tonic-gate	and	%o1, %o3, %o1		! %o1 = single short value
488*7c478bd9Sstevel@tonic-gate	sll	%o2, %g1, %o2		! %o2 = shifted to bit offset
489*7c478bd9Sstevel@tonic-gate	and	%o2, %o3, %o2		! %o2 = single short value
490*7c478bd9Sstevel@tonic-gate	andn	%o0, 0x2, %o0		! %o0 = word address
491*7c478bd9Sstevel@tonic-gate	! if low-order bit is 1, we will properly get an alignment fault here
492*7c478bd9Sstevel@tonic-gate	ld	[%o0], %o4		! read old value
493*7c478bd9Sstevel@tonic-gate1:
494*7c478bd9Sstevel@tonic-gate	andn	%o4, %o3, %o4		! clear target bits
495*7c478bd9Sstevel@tonic-gate	or	%o4, %o2, %o5		! insert the new value
496*7c478bd9Sstevel@tonic-gate	or	%o4, %o1, %o4		! insert the comparison value
497*7c478bd9Sstevel@tonic-gate	cas	[%o0], %o4, %o5
498*7c478bd9Sstevel@tonic-gate	cmp	%o4, %o5		! did we succeed?
499*7c478bd9Sstevel@tonic-gate	be,pt	%icc, 2f
500*7c478bd9Sstevel@tonic-gate	  and	%o5, %o3, %o4		! isolate the old value
501*7c478bd9Sstevel@tonic-gate	cmp	%o1, %o4		! should we have succeeded?
502*7c478bd9Sstevel@tonic-gate	be,a,pt	%icc, 1b		! yes, try again
503*7c478bd9Sstevel@tonic-gate	  mov	%o5, %o4		! %o4 = old value
504*7c478bd9Sstevel@tonic-gate2:
505*7c478bd9Sstevel@tonic-gate	retl
506*7c478bd9Sstevel@tonic-gate	srl	%o4, %g1, %o0		! %o0 = old value
507*7c478bd9Sstevel@tonic-gate	SET_SIZE(atomic_cas_ushort)
508*7c478bd9Sstevel@tonic-gate	SET_SIZE(atomic_cas_16)
509*7c478bd9Sstevel@tonic-gate
510*7c478bd9Sstevel@tonic-gate	ENTRY(atomic_cas_32)
511*7c478bd9Sstevel@tonic-gate	ALTENTRY(atomic_cas_uint)
512*7c478bd9Sstevel@tonic-gate	ALTENTRY(atomic_cas_ptr)
513*7c478bd9Sstevel@tonic-gate	ALTENTRY(atomic_cas_ulong)
514*7c478bd9Sstevel@tonic-gate	cas	[%o0], %o1, %o2
515*7c478bd9Sstevel@tonic-gate	retl
516*7c478bd9Sstevel@tonic-gate	mov	%o2, %o0
517*7c478bd9Sstevel@tonic-gate	SET_SIZE(atomic_cas_ulong)
518*7c478bd9Sstevel@tonic-gate	SET_SIZE(atomic_cas_ptr)
519*7c478bd9Sstevel@tonic-gate	SET_SIZE(atomic_cas_uint)
520*7c478bd9Sstevel@tonic-gate	SET_SIZE(atomic_cas_32)
521*7c478bd9Sstevel@tonic-gate
522*7c478bd9Sstevel@tonic-gate	ENTRY(atomic_cas_64)
523*7c478bd9Sstevel@tonic-gate	sllx	%o1, 32, %o1		! cmp's upper 32 in %o1, lower in %o2
524*7c478bd9Sstevel@tonic-gate	srl	%o2, 0, %o2		! convert 2 32-bit args into 1 64-bit
525*7c478bd9Sstevel@tonic-gate	add	%o1, %o2, %o1
526*7c478bd9Sstevel@tonic-gate	sllx	%o3, 32, %o2		! newval upper 32 in %o3, lower in %o4
527*7c478bd9Sstevel@tonic-gate	srl	%o4, 0, %o4		! setup %o2 to have newval
528*7c478bd9Sstevel@tonic-gate	add	%o2, %o4, %o2
529*7c478bd9Sstevel@tonic-gate	casx	[%o0], %o1, %o2
530*7c478bd9Sstevel@tonic-gate	srl	%o2, 0, %o1		! return lower 32-bits in %o1
531*7c478bd9Sstevel@tonic-gate	retl
532*7c478bd9Sstevel@tonic-gate	srlx	%o2, 32, %o0		! return upper 32-bits in %o0
533*7c478bd9Sstevel@tonic-gate	SET_SIZE(atomic_cas_64)
534*7c478bd9Sstevel@tonic-gate
535*7c478bd9Sstevel@tonic-gate	ENTRY(atomic_swap_8)
536*7c478bd9Sstevel@tonic-gate	ALTENTRY(atomic_swap_uchar)
537*7c478bd9Sstevel@tonic-gate	and	%o0, 0x3, %o4		! %o4 = byte offset, left-to-right
538*7c478bd9Sstevel@tonic-gate	xor	%o4, 0x3, %g1		! %g1 = byte offset, right-to-left
539*7c478bd9Sstevel@tonic-gate	sll	%g1, 3, %g1		! %g1 = bit offset, right-to-left
540*7c478bd9Sstevel@tonic-gate	set	0xff, %o3		! %o3 = mask
541*7c478bd9Sstevel@tonic-gate	sll	%o3, %g1, %o3		! %o3 = shifted to bit offset
542*7c478bd9Sstevel@tonic-gate	sll	%o1, %g1, %o1		! %o1 = shifted to bit offset
543*7c478bd9Sstevel@tonic-gate	and	%o1, %o3, %o1		! %o1 = single byte value
544*7c478bd9Sstevel@tonic-gate	andn	%o0, 0x3, %o0		! %o0 = word address
545*7c478bd9Sstevel@tonic-gate	ld	[%o0], %o2		! read old value
546*7c478bd9Sstevel@tonic-gate1:
547*7c478bd9Sstevel@tonic-gate	andn	%o2, %o3, %o5		! clear target bits
548*7c478bd9Sstevel@tonic-gate	or	%o5, %o1, %o5		! insert the new value
549*7c478bd9Sstevel@tonic-gate	cas	[%o0], %o2, %o5
550*7c478bd9Sstevel@tonic-gate	cmp	%o2, %o5
551*7c478bd9Sstevel@tonic-gate	bne,a,pn %icc, 1b
552*7c478bd9Sstevel@tonic-gate	  mov	%o5, %o2		! %o2 = old value
553*7c478bd9Sstevel@tonic-gate	and	%o5, %o3, %o5
554*7c478bd9Sstevel@tonic-gate	retl
555*7c478bd9Sstevel@tonic-gate	srl	%o5, %g1, %o0		! %o0 = old value
556*7c478bd9Sstevel@tonic-gate	SET_SIZE(atomic_swap_uchar)
557*7c478bd9Sstevel@tonic-gate	SET_SIZE(atomic_swap_8)
558*7c478bd9Sstevel@tonic-gate
559*7c478bd9Sstevel@tonic-gate	ENTRY(atomic_swap_16)
560*7c478bd9Sstevel@tonic-gate	ALTENTRY(atomic_swap_ushort)
561*7c478bd9Sstevel@tonic-gate	and	%o0, 0x2, %o4		! %o4 = byte offset, left-to-right
562*7c478bd9Sstevel@tonic-gate	xor	%o4, 0x2, %g1		! %g1 = byte offset, right-to-left
563*7c478bd9Sstevel@tonic-gate	sll	%o4, 3, %o4		! %o4 = bit offset, left-to-right
564*7c478bd9Sstevel@tonic-gate	sll	%g1, 3, %g1		! %g1 = bit offset, right-to-left
565*7c478bd9Sstevel@tonic-gate	sethi	%hi(0xffff0000), %o3	! %o3 = mask
566*7c478bd9Sstevel@tonic-gate	srl	%o3, %o4, %o3		! %o3 = shifted to bit offset
567*7c478bd9Sstevel@tonic-gate	sll	%o1, %g1, %o1		! %o1 = shifted to bit offset
568*7c478bd9Sstevel@tonic-gate	and	%o1, %o3, %o1		! %o1 = single short value
569*7c478bd9Sstevel@tonic-gate	andn	%o0, 0x2, %o0		! %o0 = word address
570*7c478bd9Sstevel@tonic-gate	! if low-order bit is 1, we will properly get an alignment fault here
571*7c478bd9Sstevel@tonic-gate	ld	[%o0], %o2		! read old value
572*7c478bd9Sstevel@tonic-gate1:
573*7c478bd9Sstevel@tonic-gate	andn	%o2, %o3, %o5		! clear target bits
574*7c478bd9Sstevel@tonic-gate	or	%o5, %o1, %o5		! insert the new value
575*7c478bd9Sstevel@tonic-gate	cas	[%o0], %o2, %o5
576*7c478bd9Sstevel@tonic-gate	cmp	%o2, %o5
577*7c478bd9Sstevel@tonic-gate	bne,a,pn %icc, 1b
578*7c478bd9Sstevel@tonic-gate	  mov	%o5, %o2		! %o2 = old value
579*7c478bd9Sstevel@tonic-gate	and	%o5, %o3, %o5
580*7c478bd9Sstevel@tonic-gate	retl
581*7c478bd9Sstevel@tonic-gate	srl	%o5, %g1, %o0		! %o0 = old value
582*7c478bd9Sstevel@tonic-gate	SET_SIZE(atomic_swap_ushort)
583*7c478bd9Sstevel@tonic-gate	SET_SIZE(atomic_swap_16)
584*7c478bd9Sstevel@tonic-gate
585*7c478bd9Sstevel@tonic-gate	ENTRY(atomic_swap_32)
586*7c478bd9Sstevel@tonic-gate	ALTENTRY(atomic_swap_uint)
587*7c478bd9Sstevel@tonic-gate	ALTENTRY(atomic_swap_ptr)
588*7c478bd9Sstevel@tonic-gate	ALTENTRY(atomic_swap_ulong)
589*7c478bd9Sstevel@tonic-gate	ld	[%o0], %o2
590*7c478bd9Sstevel@tonic-gate1:
591*7c478bd9Sstevel@tonic-gate	mov	%o1, %o3
592*7c478bd9Sstevel@tonic-gate	cas	[%o0], %o2, %o3
593*7c478bd9Sstevel@tonic-gate	cmp	%o2, %o3
594*7c478bd9Sstevel@tonic-gate	bne,a,pn %icc, 1b
595*7c478bd9Sstevel@tonic-gate	  mov	%o3, %o2
596*7c478bd9Sstevel@tonic-gate	retl
597*7c478bd9Sstevel@tonic-gate	mov	%o3, %o0
598*7c478bd9Sstevel@tonic-gate	SET_SIZE(atomic_swap_ulong)
599*7c478bd9Sstevel@tonic-gate	SET_SIZE(atomic_swap_ptr)
600*7c478bd9Sstevel@tonic-gate	SET_SIZE(atomic_swap_uint)
601*7c478bd9Sstevel@tonic-gate	SET_SIZE(atomic_swap_32)
602*7c478bd9Sstevel@tonic-gate
603*7c478bd9Sstevel@tonic-gate	ENTRY(atomic_swap_64)
604*7c478bd9Sstevel@tonic-gate	sllx	%o1, 32, %o1		! upper 32 in %o1, lower in %o2
605*7c478bd9Sstevel@tonic-gate	srl	%o2, 0, %o2
606*7c478bd9Sstevel@tonic-gate	add	%o1, %o2, %o1		! convert 2 32-bit args into 1 64-bit
607*7c478bd9Sstevel@tonic-gate	ldx	[%o0], %o2
608*7c478bd9Sstevel@tonic-gate1:
609*7c478bd9Sstevel@tonic-gate	mov	%o1, %o3
610*7c478bd9Sstevel@tonic-gate	casx	[%o0], %o2, %o3
611*7c478bd9Sstevel@tonic-gate	cmp	%o2, %o3
612*7c478bd9Sstevel@tonic-gate	bne,a,pn %xcc, 1b
613*7c478bd9Sstevel@tonic-gate	  mov	%o3, %o2
614*7c478bd9Sstevel@tonic-gate	srl	%o3, 0, %o1		! return lower 32-bits in %o1
615*7c478bd9Sstevel@tonic-gate	retl
616*7c478bd9Sstevel@tonic-gate	srlx	%o3, 32, %o0		! return upper 32-bits in %o0
617*7c478bd9Sstevel@tonic-gate	SET_SIZE(atomic_swap_64)
618*7c478bd9Sstevel@tonic-gate
619*7c478bd9Sstevel@tonic-gate	ENTRY(atomic_set_long_excl)
620*7c478bd9Sstevel@tonic-gate	mov	1, %o3
621*7c478bd9Sstevel@tonic-gate	slln	%o3, %o1, %o3
622*7c478bd9Sstevel@tonic-gate	ldn	[%o0], %o2
623*7c478bd9Sstevel@tonic-gate1:
624*7c478bd9Sstevel@tonic-gate	andcc	%o2, %o3, %g0		! test if the bit is set
625*7c478bd9Sstevel@tonic-gate	bnz,a,pn %ncc, 2f		! if so, then fail out
626*7c478bd9Sstevel@tonic-gate	  mov	-1, %o0
627*7c478bd9Sstevel@tonic-gate	or	%o2, %o3, %o4		! set the bit, and try to commit it
628*7c478bd9Sstevel@tonic-gate	casn	[%o0], %o2, %o4
629*7c478bd9Sstevel@tonic-gate	cmp	%o2, %o4
630*7c478bd9Sstevel@tonic-gate	bne,a,pn %ncc, 1b		! failed to commit, try again
631*7c478bd9Sstevel@tonic-gate	  mov	%o4, %o2
632*7c478bd9Sstevel@tonic-gate	mov	%g0, %o0
633*7c478bd9Sstevel@tonic-gate2:
634*7c478bd9Sstevel@tonic-gate	retl
635*7c478bd9Sstevel@tonic-gate	nop
636*7c478bd9Sstevel@tonic-gate	SET_SIZE(atomic_set_long_excl)
637*7c478bd9Sstevel@tonic-gate
638*7c478bd9Sstevel@tonic-gate	ENTRY(atomic_clear_long_excl)
639*7c478bd9Sstevel@tonic-gate	mov	1, %o3
640*7c478bd9Sstevel@tonic-gate	slln	%o3, %o1, %o3
641*7c478bd9Sstevel@tonic-gate	ldn	[%o0], %o2
642*7c478bd9Sstevel@tonic-gate1:
643*7c478bd9Sstevel@tonic-gate	andncc	%o3, %o2, %g0		! test if the bit is clear
644*7c478bd9Sstevel@tonic-gate	bnz,a,pn %ncc, 2f		! if so, then fail out
645*7c478bd9Sstevel@tonic-gate	  mov	-1, %o0
646*7c478bd9Sstevel@tonic-gate	andn	%o2, %o3, %o4		! clear the bit, and try to commit it
647*7c478bd9Sstevel@tonic-gate	casn	[%o0], %o2, %o4
648*7c478bd9Sstevel@tonic-gate	cmp	%o2, %o4
649*7c478bd9Sstevel@tonic-gate	bne,a,pn %ncc, 1b		! failed to commit, try again
650*7c478bd9Sstevel@tonic-gate	  mov	%o4, %o2
651*7c478bd9Sstevel@tonic-gate	mov	%g0, %o0
652*7c478bd9Sstevel@tonic-gate2:
653*7c478bd9Sstevel@tonic-gate	retl
654*7c478bd9Sstevel@tonic-gate	nop
655*7c478bd9Sstevel@tonic-gate	SET_SIZE(atomic_clear_long_excl)
656*7c478bd9Sstevel@tonic-gate
657*7c478bd9Sstevel@tonic-gate#if !defined(_KERNEL)
658*7c478bd9Sstevel@tonic-gate
659*7c478bd9Sstevel@tonic-gate	/*
660*7c478bd9Sstevel@tonic-gate	 * Spitfires and Blackbirds have a problem with membars in the
661*7c478bd9Sstevel@tonic-gate	 * delay slot (SF_ERRATA_51).  For safety's sake, we assume
662*7c478bd9Sstevel@tonic-gate	 * that the whole world needs the workaround.
663*7c478bd9Sstevel@tonic-gate	 */
664*7c478bd9Sstevel@tonic-gate	ENTRY(membar_enter)
665*7c478bd9Sstevel@tonic-gate	membar	#StoreLoad|#StoreStore
666*7c478bd9Sstevel@tonic-gate	retl
667*7c478bd9Sstevel@tonic-gate	nop
668*7c478bd9Sstevel@tonic-gate	SET_SIZE(membar_enter)
669*7c478bd9Sstevel@tonic-gate
670*7c478bd9Sstevel@tonic-gate	ENTRY(membar_exit)
671*7c478bd9Sstevel@tonic-gate	membar	#LoadStore|#StoreStore
672*7c478bd9Sstevel@tonic-gate	retl
673*7c478bd9Sstevel@tonic-gate	nop
674*7c478bd9Sstevel@tonic-gate	SET_SIZE(membar_exit)
675*7c478bd9Sstevel@tonic-gate
676*7c478bd9Sstevel@tonic-gate	ENTRY(membar_producer)
677*7c478bd9Sstevel@tonic-gate	membar	#StoreStore
678*7c478bd9Sstevel@tonic-gate	retl
679*7c478bd9Sstevel@tonic-gate	nop
680*7c478bd9Sstevel@tonic-gate	SET_SIZE(membar_producer)
681*7c478bd9Sstevel@tonic-gate
682*7c478bd9Sstevel@tonic-gate	ENTRY(membar_consumer)
683*7c478bd9Sstevel@tonic-gate	membar	#LoadLoad
684*7c478bd9Sstevel@tonic-gate	retl
685*7c478bd9Sstevel@tonic-gate	nop
686*7c478bd9Sstevel@tonic-gate	SET_SIZE(membar_consumer)
687*7c478bd9Sstevel@tonic-gate
688*7c478bd9Sstevel@tonic-gate#endif	/* !_KERNEL */
689