xref: /netbsd-src/common/lib/libc/arch/i386/atomic/atomic.S (revision 274254cdae52594c1aa480a736aef78313d15c9c)
1/*	$NetBSD: atomic.S,v 1.17 2009/04/02 00:19:02 enami Exp $	*/
2
3/*-
4 * Copyright (c) 2007 The NetBSD Foundation, Inc.
5 * All rights reserved.
6 *
7 * This code is derived from software contributed to The NetBSD Foundation
8 * by Jason R. Thorpe, and by Andrew Doran.
9 *
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
12 * are met:
13 * 1. Redistributions of source code must retain the above copyright
14 *    notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 *    notice, this list of conditions and the following disclaimer in the
17 *    documentation and/or other materials provided with the distribution.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29 * POSSIBILITY OF SUCH DAMAGE.
30 */
31
32#include <sys/param.h>
33#include <machine/asm.h>
34
35#ifdef _HARDKERNEL
36#define	LOCK(n)		.Lpatch/**/n:	lock
37#define	ALIAS(f, t)	STRONG_ALIAS(f,t)
38#define	ENDLABEL(a)	_ALIGN_TEXT; LABEL(a)
39#else
40#define	LOCK(n)		lock
41#define	ALIAS(f, t)	WEAK_ALIAS(f,t)
42#define	ENDLABEL(a)	/* nothing */
43#endif
44
45	.text
46
47ENTRY(_atomic_add_32)
48	movl	4(%esp), %edx
49	movl	8(%esp), %eax
50	LOCK(1)
51	addl	%eax, (%edx)
52	ret
53
54ENTRY(_atomic_add_32_nv)
55	movl	4(%esp), %edx
56	movl	8(%esp), %eax
57	movl	%eax, %ecx
58	LOCK(2)
59	xaddl	%eax, (%edx)
60	addl	%ecx, %eax
61	ret
62
63ENTRY(_atomic_and_32)
64	movl	4(%esp), %edx
65	movl	8(%esp), %eax
66	LOCK(3)
67	andl	%eax, (%edx)
68	ret
69
70ENTRY(_atomic_and_32_nv)
71	movl	4(%esp), %edx
72	movl	(%edx), %eax
730:
74	movl	%eax, %ecx
75	andl	8(%esp), %ecx
76	LOCK(4)
77	cmpxchgl %ecx, (%edx)
78	jnz	1f
79	movl	%ecx, %eax
80	ret
811:
82	jmp	0b
83
84ENTRY(_atomic_dec_32)
85	movl	4(%esp), %edx
86	LOCK(5)
87	decl	(%edx)
88	ret
89
90ENTRY(_atomic_dec_32_nv)
91	movl	4(%esp), %edx
92	movl	$-1, %eax
93	LOCK(6)
94	xaddl	%eax, (%edx)
95	decl	%eax
96	ret
97
98ENTRY(_atomic_inc_32)
99	movl	4(%esp), %edx
100	LOCK(7)
101	incl	(%edx)
102	ret
103
104ENTRY(_atomic_inc_32_nv)
105	movl	4(%esp), %edx
106	movl	$1, %eax
107	LOCK(8)
108	xaddl	%eax, (%edx)
109	incl	%eax
110	ret
111
112ENTRY(_atomic_or_32)
113	movl	4(%esp), %edx
114	movl	8(%esp), %eax
115	LOCK(9)
116	orl	%eax, (%edx)
117	ret
118
119ENTRY(_atomic_or_32_nv)
120	movl	4(%esp), %edx
121	movl	(%edx), %eax
1220:
123	movl	%eax, %ecx
124	orl	8(%esp), %ecx
125	LOCK(10)
126	cmpxchgl %ecx, (%edx)
127	jnz	1f
128	movl	%ecx, %eax
129	ret
1301:
131	jmp	0b
132
133ENTRY(_atomic_swap_32)
134	movl	4(%esp), %edx
135	movl	8(%esp), %eax
136	xchgl	%eax, (%edx)
137	ret
138
139ENTRY(_atomic_cas_32)
140	movl	4(%esp), %edx
141	movl	8(%esp), %eax
142	movl	12(%esp), %ecx
143	LOCK(12)
144	cmpxchgl %ecx, (%edx)
145	/* %eax now contains the old value */
146	ret
147
148ENTRY(_atomic_cas_32_ni)
149	movl	4(%esp), %edx
150	movl	8(%esp), %eax
151	movl	12(%esp), %ecx
152	cmpxchgl %ecx, (%edx)
153	/* %eax now contains the old value */
154	ret
155
156ENTRY(_membar_consumer)
157	LOCK(13)
158	addl	$0, -4(%esp)
159	ret
160ENDLABEL(membar_consumer_end)
161
162ENTRY(_membar_producer)
163	/* A store is enough */
164	movl	$0, -4(%esp)
165	ret
166ENDLABEL(membar_producer_end)
167
168ENTRY(_membar_sync)
169	LOCK(14)
170	addl	$0, -4(%esp)
171	ret
172ENDLABEL(membar_sync_end)
173
174#ifdef _HARDKERNEL
175ENTRY(_atomic_cas_64)
176	pushf
177	cli
178	pushl	%edi
179	pushl	%ebx
180	movl	12(%esp), %edi
181	movl	16(%esp), %eax
182	movl	20(%esp), %edx
183	movl	24(%esp), %ebx
184	movl	28(%esp), %ecx
185	cmpl	0(%edi), %eax
186	jne	2f
187	cmpl	4(%edi), %edx
188	jne	2f
189	movl	%ebx, 0(%edi)
190	movl	%ecx, 4(%edi)
1911:
192	popl	%ebx
193	popl	%edi
194	popf
195	ret
1962:
197	movl	0(%edi), %eax
198	movl	4(%edi), %edx
199	jmp	1b
200ENDLABEL(_atomic_cas_64_end)
201
202ENTRY(_atomic_cas_cx8)
203	pushl	%edi
204	pushl	%ebx
205	movl	12(%esp), %edi
206	movl	16(%esp), %eax
207	movl	20(%esp), %edx
208	movl	24(%esp), %ebx
209	movl	28(%esp), %ecx
210	LOCK(15)
211	cmpxchg8b (%edi)
212	popl	%ebx
213	popl	%edi
214	ret
215#ifdef GPROF
216	.space	16, 0x90
217#else
218	.space	32, 0x90
219#endif
220ENDLABEL(_atomic_cas_cx8_end)
221
222ENTRY(sse2_lfence)
223	lfence
224	ret
225ENDLABEL(sse2_lfence_end)
226
227ENTRY(sse2_mfence)
228	mfence
229	ret
230ENDLABEL(sse2_mfence_end)
231
232atomic_lockpatch:
233	.globl	atomic_lockpatch
234	.long	.Lpatch1, .Lpatch2, .Lpatch3, .Lpatch4, .Lpatch5
235	.long	.Lpatch6, .Lpatch7, .Lpatch8, .Lpatch9, .Lpatch10
236	.long	.Lpatch12, .Lpatch13, .Lpatch14, .Lpatch15, 0
237#else
238ENTRY(_atomic_cas_64)
239	pushl	%edi
240	pushl	%ebx
241	movl	12(%esp), %edi
242	movl	16(%esp), %eax
243	movl	20(%esp), %edx
244	movl	24(%esp), %ebx
245	movl	28(%esp), %ecx
246	lock
247	cmpxchg8b (%edi)
248	popl	%ebx
249	popl	%edi
250	ret
251#endif	/* _HARDKERNEL */
252
253ALIAS(atomic_add_32,_atomic_add_32)
254ALIAS(atomic_add_int,_atomic_add_32)
255ALIAS(atomic_add_long,_atomic_add_32)
256ALIAS(atomic_add_ptr,_atomic_add_32)
257
258ALIAS(atomic_add_32_nv,_atomic_add_32_nv)
259ALIAS(atomic_add_int_nv,_atomic_add_32_nv)
260ALIAS(atomic_add_long_nv,_atomic_add_32_nv)
261ALIAS(atomic_add_ptr_nv,_atomic_add_32_nv)
262
263ALIAS(atomic_and_32,_atomic_and_32)
264ALIAS(atomic_and_uint,_atomic_and_32)
265ALIAS(atomic_and_ulong,_atomic_and_32)
266ALIAS(atomic_and_ptr,_atomic_and_32)
267
268ALIAS(atomic_and_32_nv,_atomic_and_32_nv)
269ALIAS(atomic_and_uint_nv,_atomic_and_32_nv)
270ALIAS(atomic_and_ulong_nv,_atomic_and_32_nv)
271ALIAS(atomic_and_ptr_nv,_atomic_and_32_nv)
272
273ALIAS(atomic_dec_32,_atomic_dec_32)
274ALIAS(atomic_dec_uint,_atomic_dec_32)
275ALIAS(atomic_dec_ulong,_atomic_dec_32)
276ALIAS(atomic_dec_ptr,_atomic_dec_32)
277
278ALIAS(atomic_dec_32_nv,_atomic_dec_32_nv)
279ALIAS(atomic_dec_uint_nv,_atomic_dec_32_nv)
280ALIAS(atomic_dec_ulong_nv,_atomic_dec_32_nv)
281ALIAS(atomic_dec_ptr_nv,_atomic_dec_32_nv)
282
283ALIAS(atomic_inc_32,_atomic_inc_32)
284ALIAS(atomic_inc_uint,_atomic_inc_32)
285ALIAS(atomic_inc_ulong,_atomic_inc_32)
286ALIAS(atomic_inc_ptr,_atomic_inc_32)
287
288ALIAS(atomic_inc_32_nv,_atomic_inc_32_nv)
289ALIAS(atomic_inc_uint_nv,_atomic_inc_32_nv)
290ALIAS(atomic_inc_ulong_nv,_atomic_inc_32_nv)
291ALIAS(atomic_inc_ptr_nv,_atomic_inc_32_nv)
292
293ALIAS(atomic_or_32,_atomic_or_32)
294ALIAS(atomic_or_uint,_atomic_or_32)
295ALIAS(atomic_or_ulong,_atomic_or_32)
296ALIAS(atomic_or_ptr,_atomic_or_32)
297
298ALIAS(atomic_or_32_nv,_atomic_or_32_nv)
299ALIAS(atomic_or_uint_nv,_atomic_or_32_nv)
300ALIAS(atomic_or_ulong_nv,_atomic_or_32_nv)
301ALIAS(atomic_or_ptr_nv,_atomic_or_32_nv)
302
303ALIAS(atomic_swap_32,_atomic_swap_32)
304ALIAS(atomic_swap_uint,_atomic_swap_32)
305ALIAS(atomic_swap_ulong,_atomic_swap_32)
306ALIAS(atomic_swap_ptr,_atomic_swap_32)
307
308ALIAS(atomic_cas_32,_atomic_cas_32)
309ALIAS(atomic_cas_uint,_atomic_cas_32)
310ALIAS(atomic_cas_ulong,_atomic_cas_32)
311ALIAS(atomic_cas_ptr,_atomic_cas_32)
312
313ALIAS(atomic_cas_32_ni,_atomic_cas_32_ni)
314ALIAS(atomic_cas_uint_ni,_atomic_cas_32_ni)
315ALIAS(atomic_cas_ulong_ni,_atomic_cas_32_ni)
316ALIAS(atomic_cas_ptr_ni,_atomic_cas_32_ni)
317
318ALIAS(atomic_cas_64,_atomic_cas_64)
319ALIAS(atomic_cas_64_ni,_atomic_cas_64)
320
321ALIAS(membar_consumer,_membar_consumer)
322ALIAS(membar_producer,_membar_producer)
323ALIAS(membar_enter,_membar_consumer)
324ALIAS(membar_exit,_membar_producer)
325ALIAS(membar_sync,_membar_sync)
326
327STRONG_ALIAS(_atomic_add_int,_atomic_add_32)
328STRONG_ALIAS(_atomic_add_long,_atomic_add_32)
329STRONG_ALIAS(_atomic_add_ptr,_atomic_add_32)
330
331STRONG_ALIAS(_atomic_add_int_nv,_atomic_add_32_nv)
332STRONG_ALIAS(_atomic_add_long_nv,_atomic_add_32_nv)
333STRONG_ALIAS(_atomic_add_ptr_nv,_atomic_add_32_nv)
334
335STRONG_ALIAS(_atomic_and_uint,_atomic_and_32)
336STRONG_ALIAS(_atomic_and_ulong,_atomic_and_32)
337STRONG_ALIAS(_atomic_and_ptr,_atomic_and_32)
338
339STRONG_ALIAS(_atomic_and_uint_nv,_atomic_and_32_nv)
340STRONG_ALIAS(_atomic_and_ulong_nv,_atomic_and_32_nv)
341STRONG_ALIAS(_atomic_and_ptr_nv,_atomic_and_32_nv)
342
343STRONG_ALIAS(_atomic_dec_uint,_atomic_dec_32)
344STRONG_ALIAS(_atomic_dec_ulong,_atomic_dec_32)
345STRONG_ALIAS(_atomic_dec_ptr,_atomic_dec_32)
346
347STRONG_ALIAS(_atomic_dec_uint_nv,_atomic_dec_32_nv)
348STRONG_ALIAS(_atomic_dec_ulong_nv,_atomic_dec_32_nv)
349STRONG_ALIAS(_atomic_dec_ptr_nv,_atomic_dec_32_nv)
350
351STRONG_ALIAS(_atomic_inc_uint,_atomic_inc_32)
352STRONG_ALIAS(_atomic_inc_ulong,_atomic_inc_32)
353STRONG_ALIAS(_atomic_inc_ptr,_atomic_inc_32)
354
355STRONG_ALIAS(_atomic_inc_uint_nv,_atomic_inc_32_nv)
356STRONG_ALIAS(_atomic_inc_ulong_nv,_atomic_inc_32_nv)
357STRONG_ALIAS(_atomic_inc_ptr_nv,_atomic_inc_32_nv)
358
359STRONG_ALIAS(_atomic_or_uint,_atomic_or_32)
360STRONG_ALIAS(_atomic_or_ulong,_atomic_or_32)
361STRONG_ALIAS(_atomic_or_ptr,_atomic_or_32)
362
363STRONG_ALIAS(_atomic_or_uint_nv,_atomic_or_32_nv)
364STRONG_ALIAS(_atomic_or_ulong_nv,_atomic_or_32_nv)
365STRONG_ALIAS(_atomic_or_ptr_nv,_atomic_or_32_nv)
366
367STRONG_ALIAS(_atomic_swap_uint,_atomic_swap_32)
368STRONG_ALIAS(_atomic_swap_ulong,_atomic_swap_32)
369STRONG_ALIAS(_atomic_swap_ptr,_atomic_swap_32)
370
371STRONG_ALIAS(_atomic_cas_uint,_atomic_cas_32)
372STRONG_ALIAS(_atomic_cas_ulong,_atomic_cas_32)
373STRONG_ALIAS(_atomic_cas_ptr,_atomic_cas_32)
374
375STRONG_ALIAS(_atomic_cas_uint_ni,_atomic_cas_32_ni)
376STRONG_ALIAS(_atomic_cas_ulong_ni,_atomic_cas_32_ni)
377STRONG_ALIAS(_atomic_cas_ptr_ni,_atomic_cas_32_ni)
378
379STRONG_ALIAS(_membar_enter,_membar_consumer)
380STRONG_ALIAS(_membar_exit,_membar_producer)
381