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