atomic.S revision 1.1 1 /* $NetBSD: atomic.S,v 1.1 2007/11/28 01:33:49 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,b) .align b; LABEL(a)
45 #else
46 #define LOCK(n) lock
47 #define ALIAS(f, t) WEAK_ALIAS(f,t)
48 #define END(a,b) /* 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 LOCK(11)
125 xchgl %esi, (%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 LOCK(23)
207 xchgq %rsi, (%rdi)
208 ret
209
210 NENTRY(_atomic_cas_64)
211 movq %rsi, %rax
212 LOCK(24)
213 cmpxchgl %edx, (%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, 8)
224
225 NENTRY(_membar_producer)
226 /* A store is enough */
227 movq $0, -8(%rsp)
228 ret
229 END(membar_producer_end, 8)
230
231 NENTRY(_membar_enter)
232 /* A store is enough */
233 movq $0, -8(%rsp)
234 ret
235 END(membar_enter_end, 8)
236
237 NENTRY(_membar_exit)
238 /* A store is enough */
239 movq $0, -8(%rsp)
240 ret
241 END(membar_exit_end, 8)
242
243 NENTRY(_membar_sync)
244 LOCK(26)
245 addq $0, -8(%rsp)
246 ret
247 END(membar_sync_end, 8)
248
249 #ifdef _KERNEL
250 NENTRY(membar_nop)
251 /* Nothing */
252 ret
253 END(membar_nop_end, 8)
254
255 NENTRY(sse2_lfence)
256 lfence
257 ret
258 END(sse2_lfence_end, 8)
259
260 NENTRY(sse2_mfence)
261 mfence
262 ret
263 END(sse2_mfence_end, 8)
264
265 atomic_lockpatch:
266 .globl atomic_lockpatch
267 .long .Lpatch1, .Lpatch2, .Lpatch3, .Lpatch4, .Lpatch5
268 .long .Lpatch6, .Lpatch7, .Lpatch8, .Lpatch9, .Lpatch10
269 .long .Lpatch11, .Lpatch12, .Lpatch13, .Lpatch14, .Lpatch15
270 .long .Lpatch16, .Lpatch17, .Lpatch18, .Lpatch19, .Lpatch20
271 .long .Lpatch21, .Lpatch22, .Lpatch23, .Lpatch24, .Lpatch25
272 .long .Lpatch26, 0
273 #endif /* _KERNEL */
274
275 ALIAS(atomic_add_32,_atomic_add_32)
276 ALIAS(atomic_add_64,_atomic_add_64)
277 ALIAS(atomic_add_uint,_atomic_add_32)
278 ALIAS(atomic_add_ulong,_atomic_add_64)
279 ALIAS(atomic_add_ptr,_atomic_add_64)
280
281 ALIAS(atomic_add_32_nv,_atomic_add_32_nv)
282 ALIAS(atomic_add_64_nv,_atomic_add_64_nv)
283 ALIAS(atomic_add_uint_nv,_atomic_add_32_nv)
284 ALIAS(atomic_add_ulong_nv,_atomic_add_64_nv)
285 ALIAS(atomic_add_ptr_nv,_atomic_add_64_nv)
286
287 ALIAS(atomic_and_32,_atomic_and_32)
288 ALIAS(atomic_and_64,_atomic_and_64)
289 ALIAS(atomic_and_uint,_atomic_and_32)
290 ALIAS(atomic_and_ulong,_atomic_and_64)
291 ALIAS(atomic_and_ptr,_atomic_and_64)
292
293 ALIAS(atomic_and_32_nv,_atomic_and_32_nv)
294 ALIAS(atomic_and_64_nv,_atomic_and_64_nv)
295 ALIAS(atomic_and_uint_nv,_atomic_and_32_nv)
296 ALIAS(atomic_and_ulong_nv,_atomic_and_64_nv)
297 ALIAS(atomic_and_ptr_nv,_atomic_and_64_nv)
298
299 ALIAS(atomic_dec_32,_atomic_dec_32)
300 ALIAS(atomic_dec_64,_atomic_dec_64)
301 ALIAS(atomic_dec_uint,_atomic_dec_32)
302 ALIAS(atomic_dec_ulong,_atomic_dec_64)
303 ALIAS(atomic_dec_ptr,_atomic_dec_64)
304
305 ALIAS(atomic_dec_32_nv,_atomic_dec_32_nv)
306 ALIAS(atomic_dec_64_nv,_atomic_dec_64_nv)
307 ALIAS(atomic_dec_uint_nv,_atomic_dec_32_nv)
308 ALIAS(atomic_dec_ulong_nv,_atomic_dec_64_nv)
309 ALIAS(atomic_dec_ptr_nv,_atomic_dec_64_nv)
310
311 ALIAS(atomic_inc_32,_atomic_inc_32)
312 ALIAS(atomic_inc_64,_atomic_inc_64)
313 ALIAS(atomic_inc_uint,_atomic_inc_32)
314 ALIAS(atomic_inc_ulong,_atomic_inc_64)
315 ALIAS(atomic_inc_ptr,_atomic_inc_64)
316
317 ALIAS(atomic_inc_32_nv,_atomic_inc_32_nv)
318 ALIAS(atomic_inc_64_nv,_atomic_inc_64_nv)
319 ALIAS(atomic_inc_uint_nv,_atomic_inc_32_nv)
320 ALIAS(atomic_inc_ulong_nv,_atomic_inc_64_nv)
321 ALIAS(atomic_inc_ptr_nv,_atomic_inc_64_nv)
322
323 ALIAS(atomic_or_32,_atomic_or_32)
324 ALIAS(atomic_or_uint,_atomic_or_32)
325 ALIAS(atomic_or_ulong,_atomic_or_64)
326 ALIAS(atomic_or_ptr,_atomic_or_64)
327
328 ALIAS(atomic_or_32_nv,_atomic_or_32_nv)
329 ALIAS(atomic_or_64_nv,_atomic_or_64_nv)
330 ALIAS(atomic_or_uint_nv,_atomic_or_32_nv)
331 ALIAS(atomic_or_ulong_nv,_atomic_or_64_nv)
332 ALIAS(atomic_or_ptr_nv,_atomic_or_64_nv)
333
334 ALIAS(atomic_swap_32,_atomic_swap_32)
335 ALIAS(atomic_swap_64,_atomic_swap_64)
336 ALIAS(atomic_swap_uint,_atomic_swap_32)
337 ALIAS(atomic_swap_ulong,_atomic_swap_64)
338 ALIAS(atomic_swap_ptr,_atomic_swap_64)
339
340 ALIAS(atomic_cas_32,_atomic_cas_32)
341 ALIAS(atomic_cas_64,_atomic_cas_64)
342 ALIAS(atomic_cas_uint,_atomic_cas_32)
343 ALIAS(atomic_cas_ulong,_atomic_cas_64)
344 ALIAS(atomic_cas_ptr,_atomic_cas_64)
345
346 ALIAS(membar_consumer,_membar_consumer)
347 ALIAS(membar_producer,_membar_producer)
348 ALIAS(membar_enter,_membar_enter)
349 ALIAS(membar_exit,_membar_exit)
350 ALIAS(membar_sync,_membar_sync)
351