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