opensolaris_atomic.S revision 168675
1168482Spjd/*
2168482Spjd * CDDL HEADER START
3168482Spjd *
4168482Spjd * The contents of this file are subject to the terms of the
5168482Spjd * Common Development and Distribution License, Version 1.0 only
6168482Spjd * (the "License").  You may not use this file except in compliance
7168482Spjd * with the License.
8168482Spjd *
9168482Spjd * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10168482Spjd * or http://www.opensolaris.org/os/licensing.
11168482Spjd * See the License for the specific language governing permissions
12168482Spjd * and limitations under the License.
13168482Spjd *
14168482Spjd * When distributing Covered Code, include this CDDL HEADER in each
15168482Spjd * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16168482Spjd * If applicable, add the following below this CDDL HEADER, with the
17168482Spjd * fields enclosed by brackets "[]" replaced with your own identifying
18168482Spjd * information: Portions Copyright [yyyy] [name of copyright owner]
19168482Spjd *
20168482Spjd * CDDL HEADER END
21168482Spjd */
22168482Spjd/*
23168482Spjd * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
24168482Spjd * Use is subject to license terms.
25168482Spjd */
26168482Spjd
27168482Spjd	.ident	"%Z%%M%	%I%	%E% SMI"
28168482Spjd
29168482Spjd	.file	"%M%"
30168482Spjd
31168482Spjd#define	_ASM
32168482Spjd#include <sys/asm_linkage.h>
33168482Spjd
34168482Spjd#if defined(_KERNEL)
35168482Spjd	/*
36168482Spjd	 * Legacy kernel interfaces; they will go away (eventually).
37168482Spjd	 */
38168482Spjd	ANSI_PRAGMA_WEAK2(cas8,atomic_cas_8,function)
39168482Spjd	ANSI_PRAGMA_WEAK2(cas32,atomic_cas_32,function)
40168482Spjd	ANSI_PRAGMA_WEAK2(cas64,atomic_cas_64,function)
41168482Spjd	ANSI_PRAGMA_WEAK2(caslong,atomic_cas_ulong,function)
42168482Spjd	ANSI_PRAGMA_WEAK2(casptr,atomic_cas_ptr,function)
43168482Spjd	ANSI_PRAGMA_WEAK2(atomic_and_long,atomic_and_ulong,function)
44168482Spjd	ANSI_PRAGMA_WEAK2(atomic_or_long,atomic_or_ulong,function)
45168482Spjd#endif
46168482Spjd
47168482Spjd	ENTRY(atomic_inc_8)
48168482Spjd	ALTENTRY(atomic_inc_uchar)
49168482Spjd	movl	4(%esp), %eax
50168482Spjd	lock
51168482Spjd	incb	(%eax)
52168482Spjd	ret
53168482Spjd	SET_SIZE(atomic_inc_uchar)
54168482Spjd	SET_SIZE(atomic_inc_8)
55168482Spjd
56168482Spjd	ENTRY(atomic_inc_16)
57168482Spjd	ALTENTRY(atomic_inc_ushort)
58168482Spjd	movl	4(%esp), %eax
59168482Spjd	lock
60168482Spjd	incw	(%eax)
61168482Spjd	ret
62168482Spjd	SET_SIZE(atomic_inc_ushort)
63168482Spjd	SET_SIZE(atomic_inc_16)
64168482Spjd
65168482Spjd	ENTRY(atomic_inc_32)
66168482Spjd	ALTENTRY(atomic_inc_uint)
67168482Spjd	ALTENTRY(atomic_inc_ulong)
68168482Spjd	movl	4(%esp), %eax
69168482Spjd	lock
70168482Spjd	incl	(%eax)
71168482Spjd	ret
72168482Spjd	SET_SIZE(atomic_inc_ulong)
73168482Spjd	SET_SIZE(atomic_inc_uint)
74168482Spjd	SET_SIZE(atomic_inc_32)
75168482Spjd
76168482Spjd	ENTRY(atomic_inc_8_nv)
77168482Spjd	ALTENTRY(atomic_inc_uchar_nv)
78168675Spjd	movl	4(%esp), %edx	// %edx = target address
79168675Spjd	movb	(%edx), %al	// %al = old value
80168482Spjd1:
81168675Spjd	leal	1(%eax), %ecx	// %cl = new value
82168482Spjd	lock
83168675Spjd	cmpxchgb %cl, (%edx)	// try to stick it in
84168482Spjd	jne	1b
85168675Spjd	movzbl	%cl, %eax	// return new value
86168482Spjd	ret
87168482Spjd	SET_SIZE(atomic_inc_uchar_nv)
88168482Spjd	SET_SIZE(atomic_inc_8_nv)
89168482Spjd
90168482Spjd	ENTRY(atomic_inc_16_nv)
91168482Spjd	ALTENTRY(atomic_inc_ushort_nv)
92168675Spjd	movl	4(%esp), %edx	// %edx = target address
93168675Spjd	movw	(%edx), %ax	// %ax = old value
94168482Spjd1:
95168675Spjd	leal	1(%eax), %ecx	// %cx = new value
96168482Spjd	lock
97168675Spjd	cmpxchgw %cx, (%edx)	// try to stick it in
98168482Spjd	jne	1b
99168675Spjd	movzwl	%cx, %eax	// return new value
100168482Spjd	ret
101168482Spjd	SET_SIZE(atomic_inc_ushort_nv)
102168482Spjd	SET_SIZE(atomic_inc_16_nv)
103168482Spjd
104168482Spjd	ENTRY(atomic_inc_32_nv)
105168482Spjd	ALTENTRY(atomic_inc_uint_nv)
106168482Spjd	ALTENTRY(atomic_inc_ulong_nv)
107168675Spjd	movl	4(%esp), %edx	// %edx = target address
108168675Spjd	movl	(%edx), %eax	// %eax = old value
109168482Spjd1:
110168675Spjd	leal	1(%eax), %ecx	// %ecx = new value
111168482Spjd	lock
112168675Spjd	cmpxchgl %ecx, (%edx)	// try to stick it in
113168482Spjd	jne	1b
114168675Spjd	movl	%ecx, %eax	// return new value
115168482Spjd	ret
116168482Spjd	SET_SIZE(atomic_inc_ulong_nv)
117168482Spjd	SET_SIZE(atomic_inc_uint_nv)
118168482Spjd	SET_SIZE(atomic_inc_32_nv)
119168482Spjd
120168482Spjd	ENTRY(atomic_inc_64)
121168482Spjd	ALTENTRY(atomic_inc_64_nv)
122168482Spjd	pushl	%edi
123168482Spjd	pushl	%ebx
124168675Spjd	movl	12(%esp), %edi	// %edi = target address
125168482Spjd	movl	(%edi), %eax
126168675Spjd	movl	4(%edi), %edx	// %edx:%eax = old value
127168482Spjd1:
128168482Spjd	xorl	%ebx, %ebx
129168482Spjd	xorl	%ecx, %ecx
130168675Spjd	incl	%ebx		// %ecx:%ebx = 1
131168482Spjd	addl	%eax, %ebx
132168675Spjd	adcl	%edx, %ecx	// add in the carry from inc
133168482Spjd	lock
134168675Spjd	cmpxchg8b (%edi)	// try to stick it in
135168482Spjd	jne	1b
136168482Spjd	movl	%ebx, %eax
137168675Spjd	movl	%ecx, %edx	// return new value
138168482Spjd	popl	%ebx
139168482Spjd	popl	%edi
140168482Spjd	ret
141168482Spjd	SET_SIZE(atomic_inc_64_nv)
142168482Spjd	SET_SIZE(atomic_inc_64)
143168482Spjd
144168482Spjd	ENTRY(atomic_dec_8)
145168482Spjd	ALTENTRY(atomic_dec_uchar)
146168482Spjd	movl	4(%esp), %eax
147168482Spjd	lock
148168482Spjd	decb	(%eax)
149168482Spjd	ret
150168482Spjd	SET_SIZE(atomic_dec_uchar)
151168482Spjd	SET_SIZE(atomic_dec_8)
152168482Spjd
153168482Spjd	ENTRY(atomic_dec_16)
154168482Spjd	ALTENTRY(atomic_dec_ushort)
155168482Spjd	movl	4(%esp), %eax
156168482Spjd	lock
157168482Spjd	decw	(%eax)
158168482Spjd	ret
159168482Spjd	SET_SIZE(atomic_dec_ushort)
160168482Spjd	SET_SIZE(atomic_dec_16)
161168482Spjd
162168482Spjd	ENTRY(atomic_dec_32)
163168482Spjd	ALTENTRY(atomic_dec_uint)
164168482Spjd	ALTENTRY(atomic_dec_ulong)
165168482Spjd	movl	4(%esp), %eax
166168482Spjd	lock
167168482Spjd	decl	(%eax)
168168482Spjd	ret
169168482Spjd	SET_SIZE(atomic_dec_ulong)
170168482Spjd	SET_SIZE(atomic_dec_uint)
171168482Spjd	SET_SIZE(atomic_dec_32)
172168482Spjd
173168482Spjd	ENTRY(atomic_dec_8_nv)
174168482Spjd	ALTENTRY(atomic_dec_uchar_nv)
175168675Spjd	movl	4(%esp), %edx	// %edx = target address
176168675Spjd	movb	(%edx), %al	// %al = old value
177168482Spjd1:
178168675Spjd	leal	-1(%eax), %ecx	// %cl = new value
179168482Spjd	lock
180168675Spjd	cmpxchgb %cl, (%edx)	// try to stick it in
181168482Spjd	jne	1b
182168675Spjd	movzbl	%cl, %eax	// return new value
183168482Spjd	ret
184168482Spjd	SET_SIZE(atomic_dec_uchar_nv)
185168482Spjd	SET_SIZE(atomic_dec_8_nv)
186168482Spjd
187168482Spjd	ENTRY(atomic_dec_16_nv)
188168482Spjd	ALTENTRY(atomic_dec_ushort_nv)
189168675Spjd	movl	4(%esp), %edx	// %edx = target address
190168675Spjd	movw	(%edx), %ax	// %ax = old value
191168482Spjd1:
192168675Spjd	leal	-1(%eax), %ecx	// %cx = new value
193168482Spjd	lock
194168675Spjd	cmpxchgw %cx, (%edx)	// try to stick it in
195168482Spjd	jne	1b
196168675Spjd	movzwl	%cx, %eax	// return new value
197168482Spjd	ret
198168482Spjd	SET_SIZE(atomic_dec_ushort_nv)
199168482Spjd	SET_SIZE(atomic_dec_16_nv)
200168482Spjd
201168482Spjd	ENTRY(atomic_dec_32_nv)
202168482Spjd	ALTENTRY(atomic_dec_uint_nv)
203168482Spjd	ALTENTRY(atomic_dec_ulong_nv)
204168675Spjd	movl	4(%esp), %edx	// %edx = target address
205168675Spjd	movl	(%edx), %eax	// %eax = old value
206168482Spjd1:
207168675Spjd	leal	-1(%eax), %ecx	// %ecx = new value
208168482Spjd	lock
209168675Spjd	cmpxchgl %ecx, (%edx)	// try to stick it in
210168482Spjd	jne	1b
211168675Spjd	movl	%ecx, %eax	// return new value
212168482Spjd	ret
213168482Spjd	SET_SIZE(atomic_dec_ulong_nv)
214168482Spjd	SET_SIZE(atomic_dec_uint_nv)
215168482Spjd	SET_SIZE(atomic_dec_32_nv)
216168482Spjd
217168482Spjd	ENTRY(atomic_dec_64)
218168482Spjd	ALTENTRY(atomic_dec_64_nv)
219168482Spjd	pushl	%edi
220168482Spjd	pushl	%ebx
221168675Spjd	movl	12(%esp), %edi	// %edi = target address
222168482Spjd	movl	(%edi), %eax
223168675Spjd	movl	4(%edi), %edx	// %edx:%eax = old value
224168482Spjd1:
225168482Spjd	xorl	%ebx, %ebx
226168482Spjd	xorl	%ecx, %ecx
227168482Spjd	not	%ecx
228168675Spjd	not	%ebx		// %ecx:%ebx = -1
229168482Spjd	addl	%eax, %ebx
230168675Spjd	adcl	%edx, %ecx	// add in the carry from inc
231168482Spjd	lock
232168675Spjd	cmpxchg8b (%edi)	// try to stick it in
233168482Spjd	jne	1b
234168482Spjd	movl	%ebx, %eax
235168675Spjd	movl	%ecx, %edx	// return new value
236168482Spjd	popl	%ebx
237168482Spjd	popl	%edi
238168482Spjd	ret
239168482Spjd	SET_SIZE(atomic_dec_64_nv)
240168482Spjd	SET_SIZE(atomic_dec_64)
241168482Spjd
242168482Spjd	ENTRY(atomic_or_8)
243168482Spjd	ALTENTRY(atomic_or_uchar)
244168482Spjd	movl	4(%esp), %eax
245168482Spjd	movb	8(%esp), %cl
246168482Spjd	lock
247168482Spjd	orb	%cl, (%eax)
248168482Spjd	ret
249168482Spjd	SET_SIZE(atomic_or_uchar)
250168482Spjd	SET_SIZE(atomic_or_8)
251168482Spjd
252168482Spjd	ENTRY(atomic_or_16)
253168482Spjd	ALTENTRY(atomic_or_ushort)
254168482Spjd	movl	4(%esp), %eax
255168482Spjd	movw	8(%esp), %cx
256168482Spjd	lock
257168482Spjd	orw	%cx, (%eax)
258168482Spjd	ret
259168482Spjd	SET_SIZE(atomic_or_ushort)
260168482Spjd	SET_SIZE(atomic_or_16)
261168482Spjd
262168482Spjd	ENTRY(atomic_or_32)
263168482Spjd	ALTENTRY(atomic_or_uint)
264168482Spjd	ALTENTRY(atomic_or_ulong)
265168482Spjd	movl	4(%esp), %eax
266168482Spjd	movl	8(%esp), %ecx
267168482Spjd	lock
268168482Spjd	orl	%ecx, (%eax)
269168482Spjd	ret
270168482Spjd	SET_SIZE(atomic_or_ulong)
271168482Spjd	SET_SIZE(atomic_or_uint)
272168482Spjd	SET_SIZE(atomic_or_32)
273168482Spjd
274168482Spjd	ENTRY(atomic_and_8)
275168482Spjd	ALTENTRY(atomic_and_uchar)
276168482Spjd	movl	4(%esp), %eax
277168482Spjd	movb	8(%esp), %cl
278168482Spjd	lock
279168482Spjd	andb	%cl, (%eax)
280168482Spjd	ret
281168482Spjd	SET_SIZE(atomic_and_uchar)
282168482Spjd	SET_SIZE(atomic_and_8)
283168482Spjd
284168482Spjd	ENTRY(atomic_and_16)
285168482Spjd	ALTENTRY(atomic_and_ushort)
286168482Spjd	movl	4(%esp), %eax
287168482Spjd	movw	8(%esp), %cx
288168482Spjd	lock
289168482Spjd	andw	%cx, (%eax)
290168482Spjd	ret
291168482Spjd	SET_SIZE(atomic_and_ushort)
292168482Spjd	SET_SIZE(atomic_and_16)
293168482Spjd
294168482Spjd	ENTRY(atomic_and_32)
295168482Spjd	ALTENTRY(atomic_and_uint)
296168482Spjd	ALTENTRY(atomic_and_ulong)
297168482Spjd	movl	4(%esp), %eax
298168482Spjd	movl	8(%esp), %ecx
299168482Spjd	lock
300168482Spjd	andl	%ecx, (%eax)
301168482Spjd	ret
302168482Spjd	SET_SIZE(atomic_and_ulong)
303168482Spjd	SET_SIZE(atomic_and_uint)
304168482Spjd	SET_SIZE(atomic_and_32)
305168482Spjd
306168482Spjd	ENTRY(atomic_add_8_nv)
307168482Spjd	ALTENTRY(atomic_add_char_nv)
308168675Spjd	movl	4(%esp), %edx	// %edx = target address
309168675Spjd	movb	(%edx), %al	// %al = old value
310168482Spjd1:
311168675Spjd	movl	8(%esp), %ecx	// %ecx = delta
312168675Spjd	addb	%al, %cl	// %cl = new value
313168482Spjd	lock
314168675Spjd	cmpxchgb %cl, (%edx)	// try to stick it in
315168482Spjd	jne	1b
316168675Spjd	movzbl	%cl, %eax	// return new value
317168482Spjd	ret
318168482Spjd	SET_SIZE(atomic_add_char_nv)
319168482Spjd	SET_SIZE(atomic_add_8_nv)
320168482Spjd
321168482Spjd	ENTRY(atomic_add_16_nv)
322168482Spjd	ALTENTRY(atomic_add_short_nv)
323168675Spjd	movl	4(%esp), %edx	// %edx = target address
324168675Spjd	movw	(%edx), %ax	// %ax = old value
325168482Spjd1:
326168675Spjd	movl	8(%esp), %ecx	// %ecx = delta
327168675Spjd	addw	%ax, %cx	// %cx = new value
328168482Spjd	lock
329168675Spjd	cmpxchgw %cx, (%edx)	// try to stick it in
330168482Spjd	jne	1b
331168675Spjd	movzwl	%cx, %eax	// return new value
332168482Spjd	ret
333168482Spjd	SET_SIZE(atomic_add_short_nv)
334168482Spjd	SET_SIZE(atomic_add_16_nv)
335168482Spjd
336168482Spjd	ENTRY(atomic_add_32_nv)
337168482Spjd	ALTENTRY(atomic_add_int_nv)
338168482Spjd	ALTENTRY(atomic_add_ptr_nv)
339168482Spjd	ALTENTRY(atomic_add_long_nv)
340168675Spjd	movl	4(%esp), %edx	// %edx = target address
341168675Spjd	movl	(%edx), %eax	// %eax = old value
342168482Spjd1:
343168675Spjd	movl	8(%esp), %ecx	// %ecx = delta
344168675Spjd	addl	%eax, %ecx	// %ecx = new value
345168482Spjd	lock
346168675Spjd	cmpxchgl %ecx, (%edx)	// try to stick it in
347168482Spjd	jne	1b
348168675Spjd	movl	%ecx, %eax	// return new value
349168482Spjd	ret
350168482Spjd	SET_SIZE(atomic_add_long_nv)
351168482Spjd	SET_SIZE(atomic_add_ptr_nv)
352168482Spjd	SET_SIZE(atomic_add_int_nv)
353168482Spjd	SET_SIZE(atomic_add_32_nv)
354168482Spjd
355168482Spjd	ENTRY(atomic_add_64)
356168482Spjd	ALTENTRY(atomic_add_64_nv)
357168482Spjd	pushl	%edi
358168482Spjd	pushl	%ebx
359168675Spjd	movl	12(%esp), %edi	// %edi = target address
360168482Spjd	movl	(%edi), %eax
361168675Spjd	movl	4(%edi), %edx	// %edx:%eax = old value
362168482Spjd1:
363168482Spjd	movl	16(%esp), %ebx
364168675Spjd	movl	20(%esp), %ecx	// %ecx:%ebx = delta
365168482Spjd	addl	%eax, %ebx
366168675Spjd	adcl	%edx, %ecx	// %ecx:%ebx = new value
367168482Spjd	lock
368168675Spjd	cmpxchg8b (%edi)	// try to stick it in
369168482Spjd	jne	1b
370168482Spjd	movl	%ebx, %eax
371168675Spjd	movl	%ecx, %edx	// return new value
372168482Spjd	popl	%ebx
373168482Spjd	popl	%edi
374168482Spjd	ret
375168482Spjd	SET_SIZE(atomic_add_64_nv)
376168482Spjd	SET_SIZE(atomic_add_64)
377168482Spjd
378168482Spjd	ENTRY(atomic_or_8_nv)
379168482Spjd	ALTENTRY(atomic_or_uchar_nv)
380168675Spjd	movl	4(%esp), %edx	// %edx = target address
381168675Spjd	movb	(%edx), %al	// %al = old value
382168482Spjd1:
383168675Spjd	movl	8(%esp), %ecx	// %ecx = delta
384168675Spjd	orb	%al, %cl	// %cl = new value
385168482Spjd	lock
386168675Spjd	cmpxchgb %cl, (%edx)	// try to stick it in
387168482Spjd	jne	1b
388168675Spjd	movzbl	%cl, %eax	// return new value
389168482Spjd	ret
390168482Spjd	SET_SIZE(atomic_or_uchar_nv)
391168482Spjd	SET_SIZE(atomic_or_8_nv)
392168482Spjd
393168482Spjd	ENTRY(atomic_or_16_nv)
394168482Spjd	ALTENTRY(atomic_or_ushort_nv)
395168675Spjd	movl	4(%esp), %edx	// %edx = target address
396168675Spjd	movw	(%edx), %ax	// %ax = old value
397168482Spjd1:
398168675Spjd	movl	8(%esp), %ecx	// %ecx = delta
399168675Spjd	orw	%ax, %cx	// %cx = new value
400168482Spjd	lock
401168675Spjd	cmpxchgw %cx, (%edx)	// try to stick it in
402168482Spjd	jne	1b
403168675Spjd	movzwl	%cx, %eax	// return new value
404168482Spjd	ret
405168482Spjd	SET_SIZE(atomic_or_ushort_nv)
406168482Spjd	SET_SIZE(atomic_or_16_nv)
407168482Spjd
408168482Spjd	ENTRY(atomic_or_32_nv)
409168482Spjd	ALTENTRY(atomic_or_uint_nv)
410168482Spjd	ALTENTRY(atomic_or_ulong_nv)
411168675Spjd	movl	4(%esp), %edx	// %edx = target address
412168675Spjd	movl	(%edx), %eax	// %eax = old value
413168482Spjd1:
414168675Spjd	movl	8(%esp), %ecx	// %ecx = delta
415168675Spjd	orl	%eax, %ecx	// %ecx = new value
416168482Spjd	lock
417168675Spjd	cmpxchgl %ecx, (%edx)	// try to stick it in
418168482Spjd	jne	1b
419168675Spjd	movl	%ecx, %eax	// return new value
420168482Spjd	ret
421168482Spjd	SET_SIZE(atomic_or_ulong_nv)
422168482Spjd	SET_SIZE(atomic_or_uint_nv)
423168482Spjd	SET_SIZE(atomic_or_32_nv)
424168482Spjd
425168482Spjd	ENTRY(atomic_or_64)
426168482Spjd	ALTENTRY(atomic_or_64_nv)
427168482Spjd	pushl	%edi
428168482Spjd	pushl	%ebx
429168675Spjd	movl	12(%esp), %edi	// %edi = target address
430168482Spjd	movl	(%edi), %eax
431168675Spjd	movl	4(%edi), %edx	// %edx:%eax = old value
432168482Spjd1:
433168482Spjd	movl	16(%esp), %ebx
434168675Spjd	movl	20(%esp), %ecx	// %ecx:%ebx = delta
435168482Spjd	orl	%eax, %ebx
436168675Spjd	orl	%edx, %ecx	// %ecx:%ebx = new value
437168482Spjd	lock
438168675Spjd	cmpxchg8b (%edi)	// try to stick it in
439168482Spjd	jne	1b
440168482Spjd	movl	%ebx, %eax
441168675Spjd	movl	%ecx, %edx	// return new value
442168482Spjd	popl	%ebx
443168482Spjd	popl	%edi
444168482Spjd	ret
445168482Spjd	SET_SIZE(atomic_or_64_nv)
446168482Spjd	SET_SIZE(atomic_or_64)
447168482Spjd
448168482Spjd	ENTRY(atomic_and_8_nv)
449168482Spjd	ALTENTRY(atomic_and_uchar_nv)
450168675Spjd	movl	4(%esp), %edx	// %edx = target address
451168675Spjd	movb	(%edx), %al	// %al = old value
452168482Spjd1:
453168675Spjd	movl	8(%esp), %ecx	// %ecx = delta
454168675Spjd	andb	%al, %cl	// %cl = new value
455168482Spjd	lock
456168675Spjd	cmpxchgb %cl, (%edx)	// try to stick it in
457168482Spjd	jne	1b
458168675Spjd	movzbl	%cl, %eax	// return new value
459168482Spjd	ret
460168482Spjd	SET_SIZE(atomic_and_uchar_nv)
461168482Spjd	SET_SIZE(atomic_and_8_nv)
462168482Spjd
463168482Spjd	ENTRY(atomic_and_16_nv)
464168482Spjd	ALTENTRY(atomic_and_ushort_nv)
465168675Spjd	movl	4(%esp), %edx	// %edx = target address
466168675Spjd	movw	(%edx), %ax	// %ax = old value
467168482Spjd1:
468168675Spjd	movl	8(%esp), %ecx	// %ecx = delta
469168675Spjd	andw	%ax, %cx	// %cx = new value
470168482Spjd	lock
471168675Spjd	cmpxchgw %cx, (%edx)	// try to stick it in
472168482Spjd	jne	1b
473168675Spjd	movzwl	%cx, %eax	// return new value
474168482Spjd	ret
475168482Spjd	SET_SIZE(atomic_and_ushort_nv)
476168482Spjd	SET_SIZE(atomic_and_16_nv)
477168482Spjd
478168482Spjd	ENTRY(atomic_and_32_nv)
479168482Spjd	ALTENTRY(atomic_and_uint_nv)
480168482Spjd	ALTENTRY(atomic_and_ulong_nv)
481168675Spjd	movl	4(%esp), %edx	// %edx = target address
482168675Spjd	movl	(%edx), %eax	// %eax = old value
483168482Spjd1:
484168675Spjd	movl	8(%esp), %ecx	// %ecx = delta
485168675Spjd	andl	%eax, %ecx	// %ecx = new value
486168482Spjd	lock
487168675Spjd	cmpxchgl %ecx, (%edx)	// try to stick it in
488168482Spjd	jne	1b
489168675Spjd	movl	%ecx, %eax	// return new value
490168482Spjd	ret
491168482Spjd	SET_SIZE(atomic_and_ulong_nv)
492168482Spjd	SET_SIZE(atomic_and_uint_nv)
493168482Spjd	SET_SIZE(atomic_and_32_nv)
494168482Spjd
495168482Spjd	ENTRY(atomic_and_64)
496168482Spjd	ALTENTRY(atomic_and_64_nv)
497168482Spjd	pushl	%edi
498168482Spjd	pushl	%ebx
499168675Spjd	movl	12(%esp), %edi	// %edi = target address
500168482Spjd	movl	(%edi), %eax
501168675Spjd	movl	4(%edi), %edx	// %edx:%eax = old value
502168482Spjd1:
503168482Spjd	movl	16(%esp), %ebx
504168675Spjd	movl	20(%esp), %ecx	// %ecx:%ebx = delta
505168482Spjd	andl	%eax, %ebx
506168675Spjd	andl	%edx, %ecx	// %ecx:%ebx = new value
507168482Spjd	lock
508168675Spjd	cmpxchg8b (%edi)	// try to stick it in
509168482Spjd	jne	1b
510168482Spjd	movl	%ebx, %eax
511168675Spjd	movl	%ecx, %edx	// return new value
512168482Spjd	popl	%ebx
513168482Spjd	popl	%edi
514168482Spjd	ret
515168482Spjd	SET_SIZE(atomic_and_64_nv)
516168482Spjd	SET_SIZE(atomic_and_64)
517168482Spjd
518168482Spjd	ENTRY(atomic_cas_8)
519168482Spjd	ALTENTRY(atomic_cas_uchar)
520168482Spjd	movl	4(%esp), %edx
521168482Spjd	movzbl	8(%esp), %eax
522168482Spjd	movb	12(%esp), %cl
523168482Spjd	lock
524168482Spjd	cmpxchgb %cl, (%edx)
525168482Spjd	ret
526168482Spjd	SET_SIZE(atomic_cas_uchar)
527168482Spjd	SET_SIZE(atomic_cas_8)
528168482Spjd
529168482Spjd	ENTRY(atomic_cas_16)
530168482Spjd	ALTENTRY(atomic_cas_ushort)
531168482Spjd	movl	4(%esp), %edx
532168482Spjd	movzwl	8(%esp), %eax
533168482Spjd	movw	12(%esp), %cx
534168482Spjd	lock
535168482Spjd	cmpxchgw %cx, (%edx)
536168482Spjd	ret
537168482Spjd	SET_SIZE(atomic_cas_ushort)
538168482Spjd	SET_SIZE(atomic_cas_16)
539168482Spjd
540168482Spjd	ENTRY(atomic_cas_32)
541168482Spjd	ALTENTRY(atomic_cas_uint)
542168482Spjd	ALTENTRY(atomic_cas_ulong)
543168482Spjd	ALTENTRY(atomic_cas_ptr)
544168482Spjd	movl	4(%esp), %edx
545168482Spjd	movl	8(%esp), %eax
546168482Spjd	movl	12(%esp), %ecx
547168482Spjd	lock
548168482Spjd	cmpxchgl %ecx, (%edx)
549168482Spjd	ret
550168482Spjd	SET_SIZE(atomic_cas_ptr)
551168482Spjd	SET_SIZE(atomic_cas_ulong)
552168482Spjd	SET_SIZE(atomic_cas_uint)
553168482Spjd	SET_SIZE(atomic_cas_32)
554168482Spjd
555168482Spjd	ENTRY(atomic_cas_64)
556168482Spjd	pushl	%ebx
557168482Spjd	pushl	%esi
558168482Spjd	movl	12(%esp), %esi
559168482Spjd	movl	16(%esp), %eax
560168482Spjd	movl	20(%esp), %edx
561168482Spjd	movl	24(%esp), %ebx
562168482Spjd	movl	28(%esp), %ecx
563168482Spjd	lock
564168482Spjd	cmpxchg8b (%esi)
565168482Spjd	popl	%esi
566168482Spjd	popl	%ebx
567168482Spjd	ret
568168482Spjd	SET_SIZE(atomic_cas_64)
569168482Spjd
570168482Spjd	ENTRY(atomic_swap_8)
571168482Spjd	ALTENTRY(atomic_swap_uchar)
572168482Spjd	movl	4(%esp), %edx
573168482Spjd	movzbl	8(%esp), %eax
574168482Spjd	lock
575168482Spjd	xchgb	%al, (%edx)
576168482Spjd	ret
577168482Spjd	SET_SIZE(atomic_swap_uchar)
578168482Spjd	SET_SIZE(atomic_swap_8)
579168482Spjd
580168482Spjd	ENTRY(atomic_swap_16)
581168482Spjd	ALTENTRY(atomic_swap_ushort)
582168482Spjd	movl	4(%esp), %edx
583168482Spjd	movzwl	8(%esp), %eax
584168482Spjd	lock
585168482Spjd	xchgw	%ax, (%edx)
586168482Spjd	ret
587168482Spjd	SET_SIZE(atomic_swap_ushort)
588168482Spjd	SET_SIZE(atomic_swap_16)
589168482Spjd
590168482Spjd	ENTRY(atomic_swap_32)
591168482Spjd	ALTENTRY(atomic_swap_uint)
592168482Spjd	ALTENTRY(atomic_swap_ptr)
593168482Spjd	ALTENTRY(atomic_swap_ulong)
594168482Spjd	movl	4(%esp), %edx
595168482Spjd	movl	8(%esp), %eax
596168482Spjd	lock
597168482Spjd	xchgl	%eax, (%edx)
598168482Spjd	ret
599168482Spjd	SET_SIZE(atomic_swap_ulong)
600168482Spjd	SET_SIZE(atomic_swap_ptr)
601168482Spjd	SET_SIZE(atomic_swap_uint)
602168482Spjd	SET_SIZE(atomic_swap_32)
603168482Spjd
604168482Spjd	ENTRY(atomic_swap_64)
605168482Spjd	pushl	%esi
606168482Spjd	pushl	%ebx
607168482Spjd	movl	12(%esp), %esi
608168482Spjd	movl	16(%esp), %ebx
609168482Spjd	movl	20(%esp), %ecx
610168482Spjd	movl	(%esi), %eax
611168675Spjd	movl	4(%esi), %edx	// %edx:%eax = old value
612168482Spjd1:
613168482Spjd	lock
614168482Spjd	cmpxchg8b (%esi)
615168482Spjd	jne	1b
616168482Spjd	popl	%ebx
617168482Spjd	popl	%esi
618168482Spjd	ret
619168482Spjd	SET_SIZE(atomic_swap_64)
620168482Spjd
621168482Spjd	ENTRY(atomic_set_long_excl)
622168675Spjd	movl	4(%esp), %edx	// %edx = target address
623168675Spjd	movl	8(%esp), %ecx	// %ecx = bit id
624168482Spjd	xorl	%eax, %eax
625168482Spjd	lock
626168482Spjd	btsl	%ecx, (%edx)
627168482Spjd	jnc	1f
628168675Spjd	decl	%eax		// return -1
629168482Spjd1:
630168482Spjd	ret
631168482Spjd	SET_SIZE(atomic_set_long_excl)
632168482Spjd
633168482Spjd	ENTRY(atomic_clear_long_excl)
634168675Spjd	movl	4(%esp), %edx	// %edx = target address
635168675Spjd	movl	8(%esp), %ecx	// %ecx = bit id
636168482Spjd	xorl	%eax, %eax
637168482Spjd	lock
638168482Spjd	btrl	%ecx, (%edx)
639168482Spjd	jc	1f
640168675Spjd	decl	%eax		// return -1
641168482Spjd1:
642168482Spjd	ret
643168482Spjd	SET_SIZE(atomic_clear_long_excl)
644168482Spjd
645168482Spjd	ENTRY(membar_enter)
646168482Spjd	ALTENTRY(membar_exit)
647168482Spjd	ALTENTRY(membar_producer)
648168482Spjd	ALTENTRY(membar_consumer)
649168482Spjd	lock
650168482Spjd	xorl	$0, (%esp)
651168482Spjd	ret
652168482Spjd	SET_SIZE(membar_consumer)
653168482Spjd	SET_SIZE(membar_producer)
654168482Spjd	SET_SIZE(membar_exit)
655168482Spjd	SET_SIZE(membar_enter)
656