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