atomic.S revision 1.3 1 /* $NetBSD: atomic.S,v 1.3 2007/11/28 18:02:29 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 xchgl %esi, (%rdi)
125 ret
126
127 NENTRY(_atomic_cas_32)
128 movl %esi, %eax
129 LOCK(12)
130 cmpxchgl %edx, (%rdi)
131 /* %eax now contains the old value */
132 ret
133
134 /* 64-bit */
135
136 NENTRY(_atomic_add_64)
137 LOCK(13)
138 addq %rsi, (%rdi)
139 ret
140
141 NENTRY(_atomic_add_64_nv)
142 movq %rsi, %rax
143 LOCK(14)
144 xaddq %rax, (%rdi)
145 addq %rsi, %rax
146 ret
147
148 NENTRY(_atomic_and_64)
149 LOCK(15)
150 andq %rsi, (%rdi)
151 ret
152
153 NENTRY(_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 NENTRY(_atomic_dec_64)
165 LOCK(17)
166 decq (%rdi)
167 ret
168
169 NENTRY(_atomic_dec_64_nv)
170 movq $-1, %rax
171 LOCK(18)
172 xaddq %rax, (%rdi)
173 decq %rax
174 ret
175
176 NENTRY(_atomic_inc_64)
177 LOCK(19)
178 incq (%rdi)
179 ret
180
181 NENTRY(_atomic_inc_64_nv)
182 movq $1, %rax
183 LOCK(20)
184 xaddq %rax, (%rdi)
185 incq %rax
186 ret
187
188 NENTRY(_atomic_or_64)
189 LOCK(21)
190 orq %rsi, (%rdi)
191 ret
192
193 NENTRY(_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 NENTRY(_atomic_swap_64)
205 xchgq %rsi, (%rdi)
206 ret
207
208 NENTRY(_atomic_cas_64)
209 movq %rsi, %rax
210 LOCK(24)
211 cmpxchgl %edx, (%rdi)
212 /* %eax now contains the old value */
213 ret
214
215 /* memory barriers */
216
217 NENTRY(_membar_consumer)
218 LOCK(25)
219 addq $0, -8(%rsp)
220 ret
221 END(membar_consumer_end)
222
223 NENTRY(_membar_producer)
224 /* A store is enough */
225 movq $0, -8(%rsp)
226 ret
227 END(membar_producer_end)
228
229 NENTRY(_membar_enter)
230 /* A store is enough */
231 movq $0, -8(%rsp)
232 ret
233 END(membar_enter_end)
234
235 NENTRY(_membar_exit)
236 /* A store is enough */
237 movq $0, -8(%rsp)
238 ret
239 END(membar_exit_end)
240
241 NENTRY(_membar_sync)
242 LOCK(26)
243 addq $0, -8(%rsp)
244 ret
245 END(membar_sync_end)
246
247 #ifdef _KERNEL
248 NENTRY(sse2_lfence)
249 lfence
250 ret
251 END(sse2_lfence_end)
252
253 NENTRY(sse2_mfence)
254 mfence
255 ret
256 END(sse2_mfence_end)
257
258 atomic_lockpatch:
259 .globl atomic_lockpatch
260 .quad .Lpatch1, .Lpatch2, .Lpatch3, .Lpatch4, .Lpatch5
261 .quad .Lpatch6, .Lpatch7, .Lpatch8, .Lpatch9, .Lpatch10
262 .quad .Lpatch12, .Lpatch13, .Lpatch14, .Lpatch15
263 .quad .Lpatch16, .Lpatch17, .Lpatch18, .Lpatch19, .Lpatch20
264 .quad .Lpatch21, .Lpatch22, .Lpatch24, .Lpatch25
265 .quad .Lpatch26, 0
266 #endif /* _KERNEL */
267
268 ALIAS(atomic_add_32,_atomic_add_32)
269 ALIAS(atomic_add_64,_atomic_add_64)
270 ALIAS(atomic_add_uint,_atomic_add_32)
271 ALIAS(atomic_add_ulong,_atomic_add_64)
272 ALIAS(atomic_add_ptr,_atomic_add_64)
273
274 ALIAS(atomic_add_32_nv,_atomic_add_32_nv)
275 ALIAS(atomic_add_64_nv,_atomic_add_64_nv)
276 ALIAS(atomic_add_uint_nv,_atomic_add_32_nv)
277 ALIAS(atomic_add_ulong_nv,_atomic_add_64_nv)
278 ALIAS(atomic_add_ptr_nv,_atomic_add_64_nv)
279
280 ALIAS(atomic_and_32,_atomic_and_32)
281 ALIAS(atomic_and_64,_atomic_and_64)
282 ALIAS(atomic_and_uint,_atomic_and_32)
283 ALIAS(atomic_and_ulong,_atomic_and_64)
284 ALIAS(atomic_and_ptr,_atomic_and_64)
285
286 ALIAS(atomic_and_32_nv,_atomic_and_32_nv)
287 ALIAS(atomic_and_64_nv,_atomic_and_64_nv)
288 ALIAS(atomic_and_uint_nv,_atomic_and_32_nv)
289 ALIAS(atomic_and_ulong_nv,_atomic_and_64_nv)
290 ALIAS(atomic_and_ptr_nv,_atomic_and_64_nv)
291
292 ALIAS(atomic_dec_32,_atomic_dec_32)
293 ALIAS(atomic_dec_64,_atomic_dec_64)
294 ALIAS(atomic_dec_uint,_atomic_dec_32)
295 ALIAS(atomic_dec_ulong,_atomic_dec_64)
296 ALIAS(atomic_dec_ptr,_atomic_dec_64)
297
298 ALIAS(atomic_dec_32_nv,_atomic_dec_32_nv)
299 ALIAS(atomic_dec_64_nv,_atomic_dec_64_nv)
300 ALIAS(atomic_dec_uint_nv,_atomic_dec_32_nv)
301 ALIAS(atomic_dec_ulong_nv,_atomic_dec_64_nv)
302 ALIAS(atomic_dec_ptr_nv,_atomic_dec_64_nv)
303
304 ALIAS(atomic_inc_32,_atomic_inc_32)
305 ALIAS(atomic_inc_64,_atomic_inc_64)
306 ALIAS(atomic_inc_uint,_atomic_inc_32)
307 ALIAS(atomic_inc_ulong,_atomic_inc_64)
308 ALIAS(atomic_inc_ptr,_atomic_inc_64)
309
310 ALIAS(atomic_inc_32_nv,_atomic_inc_32_nv)
311 ALIAS(atomic_inc_64_nv,_atomic_inc_64_nv)
312 ALIAS(atomic_inc_uint_nv,_atomic_inc_32_nv)
313 ALIAS(atomic_inc_ulong_nv,_atomic_inc_64_nv)
314 ALIAS(atomic_inc_ptr_nv,_atomic_inc_64_nv)
315
316 ALIAS(atomic_or_32,_atomic_or_32)
317 ALIAS(atomic_or_uint,_atomic_or_32)
318 ALIAS(atomic_or_ulong,_atomic_or_64)
319 ALIAS(atomic_or_ptr,_atomic_or_64)
320
321 ALIAS(atomic_or_32_nv,_atomic_or_32_nv)
322 ALIAS(atomic_or_64_nv,_atomic_or_64_nv)
323 ALIAS(atomic_or_uint_nv,_atomic_or_32_nv)
324 ALIAS(atomic_or_ulong_nv,_atomic_or_64_nv)
325 ALIAS(atomic_or_ptr_nv,_atomic_or_64_nv)
326
327 ALIAS(atomic_swap_32,_atomic_swap_32)
328 ALIAS(atomic_swap_64,_atomic_swap_64)
329 ALIAS(atomic_swap_uint,_atomic_swap_32)
330 ALIAS(atomic_swap_ulong,_atomic_swap_64)
331 ALIAS(atomic_swap_ptr,_atomic_swap_64)
332
333 ALIAS(atomic_cas_32,_atomic_cas_32)
334 ALIAS(atomic_cas_64,_atomic_cas_64)
335 ALIAS(atomic_cas_uint,_atomic_cas_32)
336 ALIAS(atomic_cas_ulong,_atomic_cas_64)
337 ALIAS(atomic_cas_ptr,_atomic_cas_64)
338
339 ALIAS(membar_consumer,_membar_consumer)
340 ALIAS(membar_producer,_membar_producer)
341 ALIAS(membar_enter,_membar_enter)
342 ALIAS(membar_exit,_membar_exit)
343 ALIAS(membar_sync,_membar_sync)
344