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