1/*
2 * CDDL HEADER START
3 *
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21
22/*
23 * Copyright 2010 Sun Microsystems, Inc.  All rights reserved.
24 * Use is subject to license terms.
25 */
26
27	.file	"atomic.s"
28
29#define	_ASM
30#include <sys/asm_linkage.h>
31
32	/*
33	 * NOTE: If atomic_dec_64 and atomic_dec_64_nv are ever
34	 * separated, it is important to edit the libc i386 platform
35	 * specific mapfile and remove the NODYNSORT attribute
36	 * from atomic_dec_64_nv.
37	 */
38	ENTRY(atomic_dec_64)
39	ALTENTRY(atomic_dec_64_nv)
40	pushl	%edi
41	pushl	%ebx
42	movl	12(%esp), %edi	// %edi = target address
43	movl	(%edi), %eax
44	movl	4(%edi), %edx	// %edx:%eax = old value
451:
46	xorl	%ebx, %ebx
47	xorl	%ecx, %ecx
48	not	%ecx
49	not	%ebx		// %ecx:%ebx = -1
50	addl	%eax, %ebx
51	adcl	%edx, %ecx	// add in the carry from inc
52	lock
53	cmpxchg8b (%edi)	// try to stick it in
54	jne	1b
55	movl	%ebx, %eax
56	movl	%ecx, %edx	// return new value
57	popl	%ebx
58	popl	%edi
59	ret
60	SET_SIZE(atomic_dec_64_nv)
61	SET_SIZE(atomic_dec_64)
62
63	/*
64	 * NOTE: If atomic_add_64 and atomic_add_64_nv are ever
65	 * separated, it is important to edit the libc i386 platform
66	 * specific mapfile and remove the NODYNSORT attribute
67	 * from atomic_add_64_nv.
68	 */
69	ENTRY(atomic_add_64)
70	ALTENTRY(atomic_add_64_nv)
71	pushl	%edi
72	pushl	%ebx
73	movl	12(%esp), %edi	// %edi = target address
74	movl	(%edi), %eax
75	movl	4(%edi), %edx	// %edx:%eax = old value
761:
77	movl	16(%esp), %ebx
78	movl	20(%esp), %ecx	// %ecx:%ebx = delta
79	addl	%eax, %ebx
80	adcl	%edx, %ecx	// %ecx:%ebx = new value
81	lock
82	cmpxchg8b (%edi)	// try to stick it in
83	jne	1b
84	movl	%ebx, %eax
85	movl	%ecx, %edx	// return new value
86	popl	%ebx
87	popl	%edi
88	ret
89	SET_SIZE(atomic_add_64_nv)
90	SET_SIZE(atomic_add_64)
91
92	ENTRY(atomic_or_8_nv)
93	movl	4(%esp), %edx	// %edx = target address
94	movb	(%edx), %al	// %al = old value
951:
96	movl	8(%esp), %ecx	// %ecx = delta
97	orb	%al, %cl	// %cl = new value
98	lock
99	cmpxchgb %cl, (%edx)	// try to stick it in
100	jne	1b
101	movzbl	%cl, %eax	// return new value
102	ret
103	SET_SIZE(atomic_or_8_nv)
104
105	ENTRY(atomic_cas_32)
106	movl	4(%esp), %edx
107	movl	8(%esp), %eax
108	movl	12(%esp), %ecx
109	lock
110	cmpxchgl %ecx, (%edx)
111	ret
112	SET_SIZE(atomic_cas_32)
113
114	ENTRY(atomic_cas_64)
115	pushl	%ebx
116	pushl	%esi
117	movl	12(%esp), %esi
118	movl	16(%esp), %eax
119	movl	20(%esp), %edx
120	movl	24(%esp), %ebx
121	movl	28(%esp), %ecx
122	lock
123	cmpxchg8b (%esi)
124	popl	%esi
125	popl	%ebx
126	ret
127	SET_SIZE(atomic_cas_64)
128
129	ENTRY(membar_producer)
130	lock
131	xorl	$0, (%esp)
132	ret
133	SET_SIZE(membar_producer)
134