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