1168482Spjd/*
2168482Spjd * CDDL HEADER START
3168482Spjd *
4168482Spjd * The contents of this file are subject to the terms of the
5185029Spjd * Common Development and Distribution License (the "License").
6185029Spjd * You may not use this file except in compliance with the License.
7168482Spjd *
8168482Spjd * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9168482Spjd * or http://www.opensolaris.org/os/licensing.
10168482Spjd * See the License for the specific language governing permissions
11168482Spjd * and limitations under the License.
12168482Spjd *
13168482Spjd * When distributing Covered Code, include this CDDL HEADER in each
14168482Spjd * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15168482Spjd * If applicable, add the following below this CDDL HEADER, with the
16168482Spjd * fields enclosed by brackets "[]" replaced with your own identifying
17168482Spjd * information: Portions Copyright [yyyy] [name of copyright owner]
18168482Spjd *
19168482Spjd * CDDL HEADER END
20168482Spjd */
21185029Spjd
22168482Spjd/*
23219089Spjd * Copyright 2010 Sun Microsystems, Inc.  All rights reserved.
24168482Spjd * Use is subject to license terms.
25168482Spjd */
26168482Spjd
27185029Spjd	.file	"atomic.s"
28168482Spjd
29168482Spjd#define	_ASM
30168482Spjd#include <sys/asm_linkage.h>
31168482Spjd
32185029Spjd	/*
33185029Spjd	 * NOTE: If atomic_dec_64 and atomic_dec_64_nv are ever
34185029Spjd	 * separated, it is important to edit the libc i386 platform
35185029Spjd	 * specific mapfile and remove the NODYNSORT attribute
36185029Spjd	 * from atomic_dec_64_nv.
37185029Spjd	 */
38185029Spjd	ENTRY(atomic_dec_64)
39185029Spjd	ALTENTRY(atomic_dec_64_nv)
40185029Spjd	pushl	%edi
41185029Spjd	pushl	%ebx
42185029Spjd	movl	12(%esp), %edi	// %edi = target address
43185029Spjd	movl	(%edi), %eax
44185029Spjd	movl	4(%edi), %edx	// %edx:%eax = old value
45185029Spjd1:
46185029Spjd	xorl	%ebx, %ebx
47185029Spjd	xorl	%ecx, %ecx
48185029Spjd	not	%ecx
49185029Spjd	not	%ebx		// %ecx:%ebx = -1
50185029Spjd	addl	%eax, %ebx
51185029Spjd	adcl	%edx, %ecx	// add in the carry from inc
52185029Spjd	lock
53185029Spjd	cmpxchg8b (%edi)	// try to stick it in
54185029Spjd	jne	1b
55185029Spjd	movl	%ebx, %eax
56185029Spjd	movl	%ecx, %edx	// return new value
57185029Spjd	popl	%ebx
58185029Spjd	popl	%edi
59185029Spjd	ret
60185029Spjd	SET_SIZE(atomic_dec_64_nv)
61185029Spjd	SET_SIZE(atomic_dec_64)
62185029Spjd
63185029Spjd	/*
64185029Spjd	 * NOTE: If atomic_add_64 and atomic_add_64_nv are ever
65185029Spjd	 * separated, it is important to edit the libc i386 platform
66185029Spjd	 * specific mapfile and remove the NODYNSORT attribute
67185029Spjd	 * from atomic_add_64_nv.
68185029Spjd	 */
69168482Spjd	ENTRY(atomic_add_64)
70168482Spjd	ALTENTRY(atomic_add_64_nv)
71168482Spjd	pushl	%edi
72168482Spjd	pushl	%ebx
73168675Spjd	movl	12(%esp), %edi	// %edi = target address
74168482Spjd	movl	(%edi), %eax
75168675Spjd	movl	4(%edi), %edx	// %edx:%eax = old value
76168482Spjd1:
77168482Spjd	movl	16(%esp), %ebx
78168675Spjd	movl	20(%esp), %ecx	// %ecx:%ebx = delta
79168482Spjd	addl	%eax, %ebx
80168675Spjd	adcl	%edx, %ecx	// %ecx:%ebx = new value
81168482Spjd	lock
82168675Spjd	cmpxchg8b (%edi)	// try to stick it in
83168482Spjd	jne	1b
84168482Spjd	movl	%ebx, %eax
85168675Spjd	movl	%ecx, %edx	// return new value
86168482Spjd	popl	%ebx
87168482Spjd	popl	%edi
88168482Spjd	ret
89168482Spjd	SET_SIZE(atomic_add_64_nv)
90168482Spjd	SET_SIZE(atomic_add_64)
91168482Spjd
92168482Spjd	ENTRY(atomic_or_8_nv)
93168675Spjd	movl	4(%esp), %edx	// %edx = target address
94168675Spjd	movb	(%edx), %al	// %al = old value
95168482Spjd1:
96168675Spjd	movl	8(%esp), %ecx	// %ecx = delta
97168675Spjd	orb	%al, %cl	// %cl = new value
98168482Spjd	lock
99168675Spjd	cmpxchgb %cl, (%edx)	// try to stick it in
100168482Spjd	jne	1b
101168675Spjd	movzbl	%cl, %eax	// return new value
102168482Spjd	ret
103168482Spjd	SET_SIZE(atomic_or_8_nv)
104168482Spjd
105219089Spjd	ENTRY(atomic_cas_32)
106168482Spjd	movl	4(%esp), %edx
107168482Spjd	movl	8(%esp), %eax
108168482Spjd	movl	12(%esp), %ecx
109168482Spjd	lock
110168482Spjd	cmpxchgl %ecx, (%edx)
111168482Spjd	ret
112219089Spjd	SET_SIZE(atomic_cas_32)
113168482Spjd
114168482Spjd	ENTRY(atomic_cas_64)
115168482Spjd	pushl	%ebx
116168482Spjd	pushl	%esi
117168482Spjd	movl	12(%esp), %esi
118168482Spjd	movl	16(%esp), %eax
119168482Spjd	movl	20(%esp), %edx
120168482Spjd	movl	24(%esp), %ebx
121168482Spjd	movl	28(%esp), %ecx
122168482Spjd	lock
123168482Spjd	cmpxchg8b (%esi)
124168482Spjd	popl	%esi
125168482Spjd	popl	%ebx
126168482Spjd	ret
127168482Spjd	SET_SIZE(atomic_cas_64)
128168482Spjd
129170431Spjd	ENTRY(membar_producer)
130168482Spjd	lock
131168482Spjd	xorl	$0, (%esp)
132168482Spjd	ret
133168482Spjd	SET_SIZE(membar_producer)
134