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