Add linux libspl support
[zfs.git] / lib / libspl / asm-x86_64 / atomic.S
1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License (the "License").
6  * You may not use this file except in compliance with the License.
7  *
8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9  * or http://www.opensolaris.org/os/licensing.
10  * See the License for the specific language governing permissions
11  * and limitations under the License.
12  *
13  * When distributing Covered Code, include this CDDL HEADER in each
14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15  * If applicable, add the following below this CDDL HEADER, with the
16  * fields enclosed by brackets "[]" replaced with your own identifying
17  * information: Portions Copyright [yyyy] [name of copyright owner]
18  *
19  * CDDL HEADER END
20  */
21 /*
22  * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
23  * Use is subject to license terms.
24  */
25
26         .ident  "%Z%%M% %I%     %E% SMI"
27
28         .file   "%M%"
29
30 #define _ASM
31 #include <ia32/sys/asm_linkage.h>
32
33         ENTRY(atomic_inc_8)
34         ALTENTRY(atomic_inc_uchar)
35         lock
36         incb    (%rdi)
37         ret
38         SET_SIZE(atomic_inc_uchar)
39         SET_SIZE(atomic_inc_8)
40
41         ENTRY(atomic_inc_16)
42         ALTENTRY(atomic_inc_ushort)
43         lock
44         incw    (%rdi)
45         ret
46         SET_SIZE(atomic_inc_ushort)
47         SET_SIZE(atomic_inc_16)
48
49         ENTRY(atomic_inc_32)
50         ALTENTRY(atomic_inc_uint)
51         lock
52         incl    (%rdi)
53         ret
54         SET_SIZE(atomic_inc_uint)
55         SET_SIZE(atomic_inc_32)
56
57         ENTRY(atomic_inc_64)
58         ALTENTRY(atomic_inc_ulong)
59         lock
60         incq    (%rdi)
61         ret
62         SET_SIZE(atomic_inc_ulong)
63         SET_SIZE(atomic_inc_64)
64
65         ENTRY(atomic_inc_8_nv)
66         ALTENTRY(atomic_inc_uchar_nv)
67         movb    (%rdi), %al
68 1:
69         leaq    1(%rax), %rcx
70         lock
71         cmpxchgb %cl, (%rdi)
72         jne     1b
73         movzbl  %cl, %eax
74         ret
75         SET_SIZE(atomic_inc_uchar_nv)
76         SET_SIZE(atomic_inc_8_nv)
77
78         ENTRY(atomic_inc_16_nv)
79         ALTENTRY(atomic_inc_ushort_nv)
80         movw    (%rdi), %ax
81 1:
82         leaq    1(%rax), %rcx
83         lock
84         cmpxchgw %cx, (%rdi)
85         jne     1b
86         movzwl  %cx, %eax
87         ret
88         SET_SIZE(atomic_inc_ushort_nv)
89         SET_SIZE(atomic_inc_16_nv)
90
91         ENTRY(atomic_inc_32_nv)
92         ALTENTRY(atomic_inc_uint_nv)
93         movl    (%rdi), %eax
94 1:
95         leaq    1(%rax), %rcx
96         lock
97         cmpxchgl %ecx, (%rdi)
98         jne     1b
99         movl    %ecx, %eax
100         ret
101         SET_SIZE(atomic_inc_uint_nv)
102         SET_SIZE(atomic_inc_32_nv)
103
104         ENTRY(atomic_inc_64_nv)
105         ALTENTRY(atomic_inc_ulong_nv)
106         movq    (%rdi), %rax
107 1:
108         leaq    1(%rax), %rcx
109         lock
110         cmpxchgq %rcx, (%rdi)
111         jne     1b
112         movq    %rcx, %rax
113         ret
114         SET_SIZE(atomic_inc_ulong_nv)
115         SET_SIZE(atomic_inc_64_nv)
116
117         ENTRY(atomic_dec_8)
118         ALTENTRY(atomic_dec_uchar)
119         lock
120         decb    (%rdi)
121         ret
122         SET_SIZE(atomic_dec_uchar)
123         SET_SIZE(atomic_dec_8)
124
125         ENTRY(atomic_dec_16)
126         ALTENTRY(atomic_dec_ushort)
127         lock
128         decw    (%rdi)
129         ret
130         SET_SIZE(atomic_dec_ushort)
131         SET_SIZE(atomic_dec_16)
132
133         ENTRY(atomic_dec_32)
134         ALTENTRY(atomic_dec_uint)
135         lock
136         decl    (%rdi)
137         ret
138         SET_SIZE(atomic_dec_uint)
139         SET_SIZE(atomic_dec_32)
140
141         ENTRY(atomic_dec_64)
142         ALTENTRY(atomic_dec_ulong)
143         lock
144         decq    (%rdi)
145         ret
146         SET_SIZE(atomic_dec_ulong)
147         SET_SIZE(atomic_dec_64)
148
149         ENTRY(atomic_dec_8_nv)
150         ALTENTRY(atomic_dec_uchar_nv)
151         movb    (%rdi), %al
152 1:
153         leaq    -1(%rax), %rcx
154         lock
155         cmpxchgb %cl, (%rdi)
156         jne     1b
157         movzbl  %cl, %eax
158         ret
159         SET_SIZE(atomic_dec_uchar_nv)
160         SET_SIZE(atomic_dec_8_nv)
161
162         ENTRY(atomic_dec_16_nv)
163         ALTENTRY(atomic_dec_ushort_nv)
164         movw    (%rdi), %ax
165 1:
166         leaq    -1(%rax), %rcx
167         lock
168         cmpxchgw %cx, (%rdi)
169         jne     1b
170         movzwl  %cx, %eax
171         ret
172         SET_SIZE(atomic_dec_ushort_nv)
173         SET_SIZE(atomic_dec_16_nv)
174
175         ENTRY(atomic_dec_32_nv)
176         ALTENTRY(atomic_dec_uint_nv)
177         movl    (%rdi), %eax
178 1:
179         leaq    -1(%rax), %rcx
180         lock
181         cmpxchgl %ecx, (%rdi)
182         jne     1b
183         movl    %ecx, %eax
184         ret
185         SET_SIZE(atomic_dec_uint_nv)
186         SET_SIZE(atomic_dec_32_nv)
187
188         ENTRY(atomic_dec_64_nv)
189         ALTENTRY(atomic_dec_ulong_nv)
190         movq    (%rdi), %rax
191 1:
192         leaq    -1(%rax), %rcx
193         lock
194         cmpxchgq %rcx, (%rdi)
195         jne     1b
196         movq    %rcx, %rax
197         ret
198         SET_SIZE(atomic_dec_ulong_nv)
199         SET_SIZE(atomic_dec_64_nv)
200
201         ENTRY(atomic_add_8)
202         ALTENTRY(atomic_add_char)
203         lock
204         addb    %sil, (%rdi)
205         ret
206         SET_SIZE(atomic_add_char)
207         SET_SIZE(atomic_add_8)
208
209         ENTRY(atomic_add_16)
210         ALTENTRY(atomic_add_short)
211         lock
212         addw    %si, (%rdi)
213         ret
214         SET_SIZE(atomic_add_short)
215         SET_SIZE(atomic_add_16)
216
217         ENTRY(atomic_add_32)
218         ALTENTRY(atomic_add_int)
219         lock
220         addl    %esi, (%rdi)
221         ret
222         SET_SIZE(atomic_add_int)
223         SET_SIZE(atomic_add_32)
224
225         ENTRY(atomic_add_64)
226         ALTENTRY(atomic_add_ptr)
227         ALTENTRY(atomic_add_long)
228         lock
229         addq    %rsi, (%rdi)
230         ret
231         SET_SIZE(atomic_add_long)
232         SET_SIZE(atomic_add_ptr)
233         SET_SIZE(atomic_add_64)
234
235         ENTRY(atomic_or_8)
236         ALTENTRY(atomic_or_uchar)
237         lock
238         orb     %sil, (%rdi)
239         ret
240         SET_SIZE(atomic_or_uchar)
241         SET_SIZE(atomic_or_8)
242
243         ENTRY(atomic_or_16)
244         ALTENTRY(atomic_or_ushort)
245         lock
246         orw     %si, (%rdi)
247         ret
248         SET_SIZE(atomic_or_ushort)
249         SET_SIZE(atomic_or_16)
250
251         ENTRY(atomic_or_32)
252         ALTENTRY(atomic_or_uint)
253         lock
254         orl     %esi, (%rdi)
255         ret
256         SET_SIZE(atomic_or_uint)
257         SET_SIZE(atomic_or_32)
258
259         ENTRY(atomic_or_64)
260         ALTENTRY(atomic_or_ulong)
261         lock
262         orq     %rsi, (%rdi)
263         ret
264         SET_SIZE(atomic_or_ulong)
265         SET_SIZE(atomic_or_64)
266
267         ENTRY(atomic_and_8)
268         ALTENTRY(atomic_and_uchar)
269         lock
270         andb    %sil, (%rdi)
271         ret
272         SET_SIZE(atomic_and_uchar)
273         SET_SIZE(atomic_and_8)
274
275         ENTRY(atomic_and_16)
276         ALTENTRY(atomic_and_ushort)
277         lock
278         andw    %si, (%rdi)
279         ret
280         SET_SIZE(atomic_and_ushort)
281         SET_SIZE(atomic_and_16)
282
283         ENTRY(atomic_and_32)
284         ALTENTRY(atomic_and_uint)
285         lock
286         andl    %esi, (%rdi)
287         ret
288         SET_SIZE(atomic_and_uint)
289         SET_SIZE(atomic_and_32)
290
291         ENTRY(atomic_and_64)
292         ALTENTRY(atomic_and_ulong)
293         lock
294         andq    %rsi, (%rdi)
295         ret
296         SET_SIZE(atomic_and_ulong)
297         SET_SIZE(atomic_and_64)
298
299         ENTRY(atomic_add_8_nv)
300         ALTENTRY(atomic_add_char_nv)
301         movb    (%rdi), %al
302 1:
303         movb    %sil, %cl
304         addb    %al, %cl
305         lock
306         cmpxchgb %cl, (%rdi)
307         jne     1b
308         movzbl  %cl, %eax
309         ret
310         SET_SIZE(atomic_add_char_nv)
311         SET_SIZE(atomic_add_8_nv)
312
313         ENTRY(atomic_add_16_nv)
314         ALTENTRY(atomic_add_short_nv)
315         movw    (%rdi), %ax
316 1:
317         movw    %si, %cx
318         addw    %ax, %cx
319         lock
320         cmpxchgw %cx, (%rdi)
321         jne     1b
322         movzwl  %cx, %eax
323         ret
324         SET_SIZE(atomic_add_short_nv)
325         SET_SIZE(atomic_add_16_nv)
326
327         ENTRY(atomic_add_32_nv)
328         ALTENTRY(atomic_add_int_nv)
329         movl    (%rdi), %eax
330 1:
331         movl    %esi, %ecx
332         addl    %eax, %ecx
333         lock
334         cmpxchgl %ecx, (%rdi)
335         jne     1b
336         movl    %ecx, %eax
337         ret
338         SET_SIZE(atomic_add_int_nv)
339         SET_SIZE(atomic_add_32_nv)
340
341         ENTRY(atomic_add_64_nv)
342         ALTENTRY(atomic_add_ptr_nv)
343         ALTENTRY(atomic_add_long_nv)
344         movq    (%rdi), %rax
345 1:
346         movq    %rsi, %rcx
347         addq    %rax, %rcx
348         lock
349         cmpxchgq %rcx, (%rdi)
350         jne     1b
351         movq    %rcx, %rax
352         ret
353         SET_SIZE(atomic_add_long_nv)
354         SET_SIZE(atomic_add_ptr_nv)
355         SET_SIZE(atomic_add_64_nv)
356
357         ENTRY(atomic_and_8_nv)
358         ALTENTRY(atomic_and_uchar_nv)
359         movb    (%rdi), %al
360 1:
361         movb    %sil, %cl
362         andb    %al, %cl
363         lock
364         cmpxchgb %cl, (%rdi)
365         jne     1b
366         movzbl  %cl, %eax
367         ret
368         SET_SIZE(atomic_and_uchar_nv)
369         SET_SIZE(atomic_and_8_nv)
370
371         ENTRY(atomic_and_16_nv)
372         ALTENTRY(atomic_and_ushort_nv)
373         movw    (%rdi), %ax
374 1:
375         movw    %si, %cx
376         andw    %ax, %cx
377         lock
378         cmpxchgw %cx, (%rdi)
379         jne     1b
380         movzwl  %cx, %eax
381         ret
382         SET_SIZE(atomic_and_ushort_nv)
383         SET_SIZE(atomic_and_16_nv)
384
385         ENTRY(atomic_and_32_nv)
386         ALTENTRY(atomic_and_uint_nv)
387         movl    (%rdi), %eax
388 1:
389         movl    %esi, %ecx
390         andl    %eax, %ecx
391         lock
392         cmpxchgl %ecx, (%rdi)
393         jne     1b
394         movl    %ecx, %eax
395         ret
396         SET_SIZE(atomic_and_uint_nv)
397         SET_SIZE(atomic_and_32_nv)
398
399         ENTRY(atomic_and_64_nv)
400         ALTENTRY(atomic_and_ulong_nv)
401         movq    (%rdi), %rax
402 1:
403         movq    %rsi, %rcx
404         andq    %rax, %rcx
405         lock
406         cmpxchgq %rcx, (%rdi)
407         jne     1b
408         movq    %rcx, %rax
409         ret
410         SET_SIZE(atomic_and_ulong_nv)
411         SET_SIZE(atomic_and_64_nv)
412
413         ENTRY(atomic_or_8_nv)
414         ALTENTRY(atomic_or_uchar_nv)
415         movb    (%rdi), %al
416 1:
417         movb    %sil, %cl
418         orb     %al, %cl
419         lock
420         cmpxchgb %cl, (%rdi)
421         jne     1b
422         movzbl  %cl, %eax
423         ret
424         SET_SIZE(atomic_and_uchar_nv)
425         SET_SIZE(atomic_and_8_nv)
426
427         ENTRY(atomic_or_16_nv)
428         ALTENTRY(atomic_or_ushort_nv)
429         movw    (%rdi), %ax
430 1:
431         movw    %si, %cx
432         orw     %ax, %cx
433         lock
434         cmpxchgw %cx, (%rdi)
435         jne     1b
436         movzwl  %cx, %eax
437         ret
438         SET_SIZE(atomic_or_ushort_nv)
439         SET_SIZE(atomic_or_16_nv)
440
441         ENTRY(atomic_or_32_nv)
442         ALTENTRY(atomic_or_uint_nv)
443         movl    (%rdi), %eax
444 1:
445         movl    %esi, %ecx
446         orl     %eax, %ecx
447         lock
448         cmpxchgl %ecx, (%rdi)
449         jne     1b
450         movl    %ecx, %eax
451         ret
452         SET_SIZE(atomic_or_uint_nv)
453         SET_SIZE(atomic_or_32_nv)
454
455         ENTRY(atomic_or_64_nv)
456         ALTENTRY(atomic_or_ulong_nv)
457         movq    (%rdi), %rax
458 1:
459         movq    %rsi, %rcx
460         orq     %rax, %rcx
461         lock
462         cmpxchgq %rcx, (%rdi)
463         jne     1b
464         movq    %rcx, %rax
465         ret
466         SET_SIZE(atomic_or_ulong_nv)
467         SET_SIZE(atomic_or_64_nv)
468
469         ENTRY(atomic_cas_8)
470         ALTENTRY(atomic_cas_uchar)
471         movzbl  %sil, %eax
472         lock
473         cmpxchgb %dl, (%rdi)
474         ret
475         SET_SIZE(atomic_cas_uchar)
476         SET_SIZE(atomic_cas_8)
477
478         ENTRY(atomic_cas_16)
479         ALTENTRY(atomic_cas_ushort)
480         movzwl  %si, %eax
481         lock
482         cmpxchgw %dx, (%rdi)
483         ret
484         SET_SIZE(atomic_cas_ushort)
485         SET_SIZE(atomic_cas_16)
486
487         ENTRY(atomic_cas_32)
488         ALTENTRY(atomic_cas_uint)
489         movl    %esi, %eax
490         lock
491         cmpxchgl %edx, (%rdi)
492         ret
493         SET_SIZE(atomic_cas_uint)
494         SET_SIZE(atomic_cas_32)
495
496         ENTRY(atomic_cas_64)
497         ALTENTRY(atomic_cas_ulong)
498         ALTENTRY(atomic_cas_ptr)
499         movq    %rsi, %rax
500         lock
501         cmpxchgq %rdx, (%rdi)
502         ret
503         SET_SIZE(atomic_cas_ptr)
504         SET_SIZE(atomic_cas_ulong)
505         SET_SIZE(atomic_cas_64)
506
507         ENTRY(atomic_swap_8)
508         ALTENTRY(atomic_swap_uchar)
509         movzbl  %sil, %eax
510         lock
511         xchgb %al, (%rdi)
512         ret
513         SET_SIZE(atomic_swap_uchar)
514         SET_SIZE(atomic_swap_8)
515
516         ENTRY(atomic_swap_16)
517         ALTENTRY(atomic_swap_ushort)
518         movzwl  %si, %eax
519         lock
520         xchgw %ax, (%rdi)
521         ret
522         SET_SIZE(atomic_swap_ushort)
523         SET_SIZE(atomic_swap_16)
524
525         ENTRY(atomic_swap_32)
526         ALTENTRY(atomic_swap_uint)
527         movl    %esi, %eax
528         lock
529         xchgl %eax, (%rdi)
530         ret
531         SET_SIZE(atomic_swap_uint)
532         SET_SIZE(atomic_swap_32)
533
534         ENTRY(atomic_swap_64)
535         ALTENTRY(atomic_swap_ulong)
536         ALTENTRY(atomic_swap_ptr)
537         movq    %rsi, %rax
538         lock
539         xchgq %rax, (%rdi)
540         ret
541         SET_SIZE(atomic_swap_ptr)
542         SET_SIZE(atomic_swap_ulong)
543         SET_SIZE(atomic_swap_64)
544
545         ENTRY(atomic_set_long_excl)
546         xorl    %eax, %eax
547         lock
548         btsq    %rsi, (%rdi)
549         jnc     1f
550         decl    %eax
551 1:
552         ret
553         SET_SIZE(atomic_set_long_excl)
554
555         ENTRY(atomic_clear_long_excl)
556         xorl    %eax, %eax
557         lock
558         btrq    %rsi, (%rdi)
559         jc      1f
560         decl    %eax
561 1:
562         ret
563         SET_SIZE(atomic_clear_long_excl)
564
565         /*
566          * NOTE: membar_enter, and membar_exit are identical routines. 
567          * We define them separately, instead of using an ALTENTRY
568          * definitions to alias them together, so that DTrace and
569          * debuggers will see a unique address for them, allowing 
570          * more accurate tracing.
571         */
572
573         ENTRY(membar_enter)
574         mfence
575         ret
576         SET_SIZE(membar_enter)
577
578         ENTRY(membar_exit)
579         mfence
580         ret
581         SET_SIZE(membar_exit)
582
583         ENTRY(membar_producer)
584         sfence
585         ret
586         SET_SIZE(membar_producer)
587
588         ENTRY(membar_consumer)
589         lfence
590         ret
591         SET_SIZE(membar_consumer)
592
593 #ifdef __ELF__
594 .section .note.GNU-stack,"",%progbits
595 #endif