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