atomic.S revision 1.22 1 /* $NetBSD: atomic.S,v 1.22 2014/05/23 03:17:31 uebayasi 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 * __HAVE_ constants should not be in <machine/types.h>
36 * because we can't use them from assembly. OTOH we
37 * only need __HAVE_ATOMIC64_OPS here, and we don't.
38 */
39 #ifdef _KERNEL
40 #define ALIAS(f, t) STRONG_ALIAS(f,t)
41 #else
42 #define ALIAS(f, t) WEAK_ALIAS(f,t)
43 #endif
44
45 #ifdef _HARDKERNEL
46 #define LOCK(n) .Lpatch ## n: lock
47 #define ENDLABEL(a) _ALIGN_TEXT; LABEL(a)
48 #else
49 #define LOCK(n) lock
50 #define ENDLABEL(a) /* nothing */
51 #endif
52
53 .text
54
55 ENTRY(_atomic_add_32)
56 movl 4(%esp), %edx
57 movl 8(%esp), %eax
58 LOCK(1)
59 addl %eax, (%edx)
60 ret
61 END(_atomic_add_32)
62
63 ENTRY(_atomic_add_32_nv)
64 movl 4(%esp), %edx
65 movl 8(%esp), %eax
66 movl %eax, %ecx
67 LOCK(2)
68 xaddl %eax, (%edx)
69 addl %ecx, %eax
70 ret
71 END(_atomic_add_32_nv)
72
73 ENTRY(_atomic_and_32)
74 movl 4(%esp), %edx
75 movl 8(%esp), %eax
76 LOCK(3)
77 andl %eax, (%edx)
78 ret
79 END(_atomic_and_32)
80
81 ENTRY(_atomic_and_32_nv)
82 movl 4(%esp), %edx
83 movl (%edx), %eax
84 0:
85 movl %eax, %ecx
86 andl 8(%esp), %ecx
87 LOCK(4)
88 cmpxchgl %ecx, (%edx)
89 jnz 1f
90 movl %ecx, %eax
91 ret
92 1:
93 jmp 0b
94 END(_atomic_and_32_nv)
95
96 ENTRY(_atomic_dec_32)
97 movl 4(%esp), %edx
98 LOCK(5)
99 decl (%edx)
100 ret
101 END(_atomic_dec_32)
102
103 ENTRY(_atomic_dec_32_nv)
104 movl 4(%esp), %edx
105 movl $-1, %eax
106 LOCK(6)
107 xaddl %eax, (%edx)
108 decl %eax
109 ret
110 END(_atomic_dec_32_nv)
111
112 ENTRY(_atomic_inc_32)
113 movl 4(%esp), %edx
114 LOCK(7)
115 incl (%edx)
116 ret
117 END(_atomic_inc_32)
118
119 ENTRY(_atomic_inc_32_nv)
120 movl 4(%esp), %edx
121 movl $1, %eax
122 LOCK(8)
123 xaddl %eax, (%edx)
124 incl %eax
125 ret
126 END(_atomic_inc_32_nv)
127
128 ENTRY(_atomic_or_32)
129 movl 4(%esp), %edx
130 movl 8(%esp), %eax
131 LOCK(9)
132 orl %eax, (%edx)
133 ret
134 END(_atomic_or_32)
135
136 ENTRY(_atomic_or_32_nv)
137 movl 4(%esp), %edx
138 movl (%edx), %eax
139 0:
140 movl %eax, %ecx
141 orl 8(%esp), %ecx
142 LOCK(10)
143 cmpxchgl %ecx, (%edx)
144 jnz 1f
145 movl %ecx, %eax
146 ret
147 1:
148 jmp 0b
149 END(_atomic_or_32_nv)
150
151 ENTRY(_atomic_swap_32)
152 movl 4(%esp), %edx
153 movl 8(%esp), %eax
154 xchgl %eax, (%edx)
155 ret
156 END(_atomic_swap_32)
157
158 ENTRY(_atomic_cas_32)
159 movl 4(%esp), %edx
160 movl 8(%esp), %eax
161 movl 12(%esp), %ecx
162 LOCK(12)
163 cmpxchgl %ecx, (%edx)
164 /* %eax now contains the old value */
165 ret
166 END(_atomic_cas_32)
167
168 ENTRY(_atomic_cas_32_ni)
169 movl 4(%esp), %edx
170 movl 8(%esp), %eax
171 movl 12(%esp), %ecx
172 cmpxchgl %ecx, (%edx)
173 /* %eax now contains the old value */
174 ret
175 END(_atomic_cas_32_ni)
176
177 ENTRY(_membar_consumer)
178 LOCK(13)
179 addl $0, -4(%esp)
180 ret
181 END(_membar_consumer)
182 ENDLABEL(membar_consumer_end)
183
184 ENTRY(_membar_producer)
185 /* A store is enough */
186 movl $0, -4(%esp)
187 ret
188 END(_membar_producer)
189 ENDLABEL(membar_producer_end)
190
191 ENTRY(_membar_sync)
192 LOCK(14)
193 addl $0, -4(%esp)
194 ret
195 END(_membar_sync)
196 ENDLABEL(membar_sync_end)
197
198 #if defined(__HAVE_ATOMIC64_OPS) || defined(_KERNEL)
199 ENTRY(_atomic_cas_64)
200 #ifdef _HARDKERNEL
201 pushf
202 cli
203 #endif /* _HARDKERNEL */
204 pushl %edi
205 pushl %ebx
206 movl 12(%esp), %edi
207 movl 16(%esp), %eax
208 movl 20(%esp), %edx
209 movl 24(%esp), %ebx
210 movl 28(%esp), %ecx
211 cmpl 0(%edi), %eax
212 jne 2f
213 cmpl 4(%edi), %edx
214 jne 2f
215 movl %ebx, 0(%edi)
216 movl %ecx, 4(%edi)
217 1:
218 popl %ebx
219 popl %edi
220 #ifdef _HARDKERNEL
221 popf
222 #endif /* _HARDKERNEL */
223 ret
224 2:
225 movl 0(%edi), %eax
226 movl 4(%edi), %edx
227 jmp 1b
228 END(_atomic_cas_64)
229 ENDLABEL(_atomic_cas_64_end)
230
231 ENTRY(_atomic_cas_cx8)
232 pushl %edi
233 pushl %ebx
234 movl 12(%esp), %edi
235 movl 16(%esp), %eax
236 movl 20(%esp), %edx
237 movl 24(%esp), %ebx
238 movl 28(%esp), %ecx
239 LOCK(15)
240 cmpxchg8b (%edi)
241 popl %ebx
242 popl %edi
243 ret
244 #ifdef _HARDKERNEL
245 #ifdef GPROF
246 .space 16, 0x90
247 #else
248 .space 32, 0x90
249 #endif
250 #endif /* _HARDKERNEL */
251 END(_atomic_cas_cx8)
252 ENDLABEL(_atomic_cas_cx8_end)
253 #endif /* __HAVE_ATOMIC64_OPS || _KERNEL */
254
255 #ifdef _HARDKERNEL
256 ENTRY(sse2_lfence)
257 lfence
258 ret
259 END(sse2_lfence)
260 ENDLABEL(sse2_lfence_end)
261
262 ENTRY(sse2_mfence)
263 mfence
264 ret
265 END(sse2_mfence)
266 ENDLABEL(sse2_mfence_end)
267
268 atomic_lockpatch:
269 .globl atomic_lockpatch
270 .long .Lpatch1, .Lpatch2, .Lpatch3, .Lpatch4, .Lpatch5
271 .long .Lpatch6, .Lpatch7, .Lpatch8, .Lpatch9, .Lpatch10
272 .long .Lpatch12, .Lpatch13, .Lpatch14, .Lpatch15, 0
273 #endif /* _HARDKERNEL */
274
275 ALIAS(atomic_add_32,_atomic_add_32)
276 ALIAS(atomic_add_int,_atomic_add_32)
277 ALIAS(atomic_add_long,_atomic_add_32)
278 ALIAS(atomic_add_ptr,_atomic_add_32)
279
280 ALIAS(atomic_add_32_nv,_atomic_add_32_nv)
281 ALIAS(atomic_add_int_nv,_atomic_add_32_nv)
282 ALIAS(atomic_add_long_nv,_atomic_add_32_nv)
283 ALIAS(atomic_add_ptr_nv,_atomic_add_32_nv)
284
285 ALIAS(atomic_and_32,_atomic_and_32)
286 ALIAS(atomic_and_uint,_atomic_and_32)
287 ALIAS(atomic_and_ulong,_atomic_and_32)
288 ALIAS(atomic_and_ptr,_atomic_and_32)
289
290 ALIAS(atomic_and_32_nv,_atomic_and_32_nv)
291 ALIAS(atomic_and_uint_nv,_atomic_and_32_nv)
292 ALIAS(atomic_and_ulong_nv,_atomic_and_32_nv)
293 ALIAS(atomic_and_ptr_nv,_atomic_and_32_nv)
294
295 ALIAS(atomic_dec_32,_atomic_dec_32)
296 ALIAS(atomic_dec_uint,_atomic_dec_32)
297 ALIAS(atomic_dec_ulong,_atomic_dec_32)
298 ALIAS(atomic_dec_ptr,_atomic_dec_32)
299
300 ALIAS(atomic_dec_32_nv,_atomic_dec_32_nv)
301 ALIAS(atomic_dec_uint_nv,_atomic_dec_32_nv)
302 ALIAS(atomic_dec_ulong_nv,_atomic_dec_32_nv)
303 ALIAS(atomic_dec_ptr_nv,_atomic_dec_32_nv)
304
305 ALIAS(atomic_inc_32,_atomic_inc_32)
306 ALIAS(atomic_inc_uint,_atomic_inc_32)
307 ALIAS(atomic_inc_ulong,_atomic_inc_32)
308 ALIAS(atomic_inc_ptr,_atomic_inc_32)
309
310 ALIAS(atomic_inc_32_nv,_atomic_inc_32_nv)
311 ALIAS(atomic_inc_uint_nv,_atomic_inc_32_nv)
312 ALIAS(atomic_inc_ulong_nv,_atomic_inc_32_nv)
313 ALIAS(atomic_inc_ptr_nv,_atomic_inc_32_nv)
314
315 ALIAS(atomic_or_32,_atomic_or_32)
316 ALIAS(atomic_or_uint,_atomic_or_32)
317 ALIAS(atomic_or_ulong,_atomic_or_32)
318 ALIAS(atomic_or_ptr,_atomic_or_32)
319
320 ALIAS(atomic_or_32_nv,_atomic_or_32_nv)
321 ALIAS(atomic_or_uint_nv,_atomic_or_32_nv)
322 ALIAS(atomic_or_ulong_nv,_atomic_or_32_nv)
323 ALIAS(atomic_or_ptr_nv,_atomic_or_32_nv)
324
325 ALIAS(atomic_swap_32,_atomic_swap_32)
326 ALIAS(atomic_swap_uint,_atomic_swap_32)
327 ALIAS(atomic_swap_ulong,_atomic_swap_32)
328 ALIAS(atomic_swap_ptr,_atomic_swap_32)
329
330 ALIAS(atomic_cas_32,_atomic_cas_32)
331 ALIAS(atomic_cas_uint,_atomic_cas_32)
332 ALIAS(atomic_cas_ulong,_atomic_cas_32)
333 ALIAS(atomic_cas_ptr,_atomic_cas_32)
334
335 ALIAS(atomic_cas_32_ni,_atomic_cas_32_ni)
336 ALIAS(atomic_cas_uint_ni,_atomic_cas_32_ni)
337 ALIAS(atomic_cas_ulong_ni,_atomic_cas_32_ni)
338 ALIAS(atomic_cas_ptr_ni,_atomic_cas_32_ni)
339
340 #if defined(__HAVE_ATOMIC64_OPS) || defined(_KERNEL)
341 ALIAS(atomic_cas_64,_atomic_cas_64)
342 ALIAS(atomic_cas_64_ni,_atomic_cas_64)
343 ALIAS(__sync_val_compare_and_swap_8,_atomic_cas_64)
344 #endif /* __HAVE_ATOMIC64_OPS || _KERNEL */
345
346 ALIAS(membar_consumer,_membar_consumer)
347 ALIAS(membar_producer,_membar_producer)
348 ALIAS(membar_enter,_membar_consumer)
349 ALIAS(membar_exit,_membar_producer)
350 ALIAS(membar_sync,_membar_sync)
351
352 STRONG_ALIAS(_atomic_add_int,_atomic_add_32)
353 STRONG_ALIAS(_atomic_add_long,_atomic_add_32)
354 STRONG_ALIAS(_atomic_add_ptr,_atomic_add_32)
355
356 STRONG_ALIAS(_atomic_add_int_nv,_atomic_add_32_nv)
357 STRONG_ALIAS(_atomic_add_long_nv,_atomic_add_32_nv)
358 STRONG_ALIAS(_atomic_add_ptr_nv,_atomic_add_32_nv)
359
360 STRONG_ALIAS(_atomic_and_uint,_atomic_and_32)
361 STRONG_ALIAS(_atomic_and_ulong,_atomic_and_32)
362 STRONG_ALIAS(_atomic_and_ptr,_atomic_and_32)
363
364 STRONG_ALIAS(_atomic_and_uint_nv,_atomic_and_32_nv)
365 STRONG_ALIAS(_atomic_and_ulong_nv,_atomic_and_32_nv)
366 STRONG_ALIAS(_atomic_and_ptr_nv,_atomic_and_32_nv)
367
368 STRONG_ALIAS(_atomic_dec_uint,_atomic_dec_32)
369 STRONG_ALIAS(_atomic_dec_ulong,_atomic_dec_32)
370 STRONG_ALIAS(_atomic_dec_ptr,_atomic_dec_32)
371
372 STRONG_ALIAS(_atomic_dec_uint_nv,_atomic_dec_32_nv)
373 STRONG_ALIAS(_atomic_dec_ulong_nv,_atomic_dec_32_nv)
374 STRONG_ALIAS(_atomic_dec_ptr_nv,_atomic_dec_32_nv)
375
376 STRONG_ALIAS(_atomic_inc_uint,_atomic_inc_32)
377 STRONG_ALIAS(_atomic_inc_ulong,_atomic_inc_32)
378 STRONG_ALIAS(_atomic_inc_ptr,_atomic_inc_32)
379
380 STRONG_ALIAS(_atomic_inc_uint_nv,_atomic_inc_32_nv)
381 STRONG_ALIAS(_atomic_inc_ulong_nv,_atomic_inc_32_nv)
382 STRONG_ALIAS(_atomic_inc_ptr_nv,_atomic_inc_32_nv)
383
384 STRONG_ALIAS(_atomic_or_uint,_atomic_or_32)
385 STRONG_ALIAS(_atomic_or_ulong,_atomic_or_32)
386 STRONG_ALIAS(_atomic_or_ptr,_atomic_or_32)
387
388 STRONG_ALIAS(_atomic_or_uint_nv,_atomic_or_32_nv)
389 STRONG_ALIAS(_atomic_or_ulong_nv,_atomic_or_32_nv)
390 STRONG_ALIAS(_atomic_or_ptr_nv,_atomic_or_32_nv)
391
392 STRONG_ALIAS(_atomic_swap_uint,_atomic_swap_32)
393 STRONG_ALIAS(_atomic_swap_ulong,_atomic_swap_32)
394 STRONG_ALIAS(_atomic_swap_ptr,_atomic_swap_32)
395
396 STRONG_ALIAS(_atomic_cas_uint,_atomic_cas_32)
397 STRONG_ALIAS(_atomic_cas_ulong,_atomic_cas_32)
398 STRONG_ALIAS(_atomic_cas_ptr,_atomic_cas_32)
399
400 STRONG_ALIAS(_atomic_cas_uint_ni,_atomic_cas_32_ni)
401 STRONG_ALIAS(_atomic_cas_ulong_ni,_atomic_cas_32_ni)
402 STRONG_ALIAS(_atomic_cas_ptr_ni,_atomic_cas_32_ni)
403
404 STRONG_ALIAS(_membar_enter,_membar_consumer)
405 STRONG_ALIAS(_membar_exit,_membar_producer)
406