Add atomic_sub_* functions to libspl.
[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_sub_8)
236         ALTENTRY(atomic_sub_char)
237         lock
238         subb    %sil, (%rdi)
239         ret
240         SET_SIZE(atomic_sub_char)
241         SET_SIZE(atomic_sub_8)
242
243         ENTRY(atomic_sub_16)
244         ALTENTRY(atomic_sub_short)
245         lock
246         subw    %si, (%rdi)
247         ret
248         SET_SIZE(atomic_sub_short)
249         SET_SIZE(atomic_sub_16)
250
251         ENTRY(atomic_sub_32)
252         ALTENTRY(atomic_sub_int)
253         lock
254         subl    %esi, (%rdi)
255         ret
256         SET_SIZE(atomic_sub_int)
257         SET_SIZE(atomic_sub_32)
258
259         ENTRY(atomic_sub_64)
260         ALTENTRY(atomic_sub_ptr)
261         ALTENTRY(atomic_sub_long)
262         lock
263         subq    %rsi, (%rdi)
264         ret
265         SET_SIZE(atomic_sub_long)
266         SET_SIZE(atomic_sub_ptr)
267         SET_SIZE(atomic_sub_64)
268
269         ENTRY(atomic_or_8)
270         ALTENTRY(atomic_or_uchar)
271         lock
272         orb     %sil, (%rdi)
273         ret
274         SET_SIZE(atomic_or_uchar)
275         SET_SIZE(atomic_or_8)
276
277         ENTRY(atomic_or_16)
278         ALTENTRY(atomic_or_ushort)
279         lock
280         orw     %si, (%rdi)
281         ret
282         SET_SIZE(atomic_or_ushort)
283         SET_SIZE(atomic_or_16)
284
285         ENTRY(atomic_or_32)
286         ALTENTRY(atomic_or_uint)
287         lock
288         orl     %esi, (%rdi)
289         ret
290         SET_SIZE(atomic_or_uint)
291         SET_SIZE(atomic_or_32)
292
293         ENTRY(atomic_or_64)
294         ALTENTRY(atomic_or_ulong)
295         lock
296         orq     %rsi, (%rdi)
297         ret
298         SET_SIZE(atomic_or_ulong)
299         SET_SIZE(atomic_or_64)
300
301         ENTRY(atomic_and_8)
302         ALTENTRY(atomic_and_uchar)
303         lock
304         andb    %sil, (%rdi)
305         ret
306         SET_SIZE(atomic_and_uchar)
307         SET_SIZE(atomic_and_8)
308
309         ENTRY(atomic_and_16)
310         ALTENTRY(atomic_and_ushort)
311         lock
312         andw    %si, (%rdi)
313         ret
314         SET_SIZE(atomic_and_ushort)
315         SET_SIZE(atomic_and_16)
316
317         ENTRY(atomic_and_32)
318         ALTENTRY(atomic_and_uint)
319         lock
320         andl    %esi, (%rdi)
321         ret
322         SET_SIZE(atomic_and_uint)
323         SET_SIZE(atomic_and_32)
324
325         ENTRY(atomic_and_64)
326         ALTENTRY(atomic_and_ulong)
327         lock
328         andq    %rsi, (%rdi)
329         ret
330         SET_SIZE(atomic_and_ulong)
331         SET_SIZE(atomic_and_64)
332
333         ENTRY(atomic_add_8_nv)
334         ALTENTRY(atomic_add_char_nv)
335         movb    (%rdi), %al
336 1:
337         movb    %sil, %cl
338         addb    %al, %cl
339         lock
340         cmpxchgb %cl, (%rdi)
341         jne     1b
342         movzbl  %cl, %eax
343         ret
344         SET_SIZE(atomic_add_char_nv)
345         SET_SIZE(atomic_add_8_nv)
346
347         ENTRY(atomic_add_16_nv)
348         ALTENTRY(atomic_add_short_nv)
349         movw    (%rdi), %ax
350 1:
351         movw    %si, %cx
352         addw    %ax, %cx
353         lock
354         cmpxchgw %cx, (%rdi)
355         jne     1b
356         movzwl  %cx, %eax
357         ret
358         SET_SIZE(atomic_add_short_nv)
359         SET_SIZE(atomic_add_16_nv)
360
361         ENTRY(atomic_add_32_nv)
362         ALTENTRY(atomic_add_int_nv)
363         movl    (%rdi), %eax
364 1:
365         movl    %esi, %ecx
366         addl    %eax, %ecx
367         lock
368         cmpxchgl %ecx, (%rdi)
369         jne     1b
370         movl    %ecx, %eax
371         ret
372         SET_SIZE(atomic_add_int_nv)
373         SET_SIZE(atomic_add_32_nv)
374
375         ENTRY(atomic_add_64_nv)
376         ALTENTRY(atomic_add_ptr_nv)
377         ALTENTRY(atomic_add_long_nv)
378         movq    (%rdi), %rax
379 1:
380         movq    %rsi, %rcx
381         addq    %rax, %rcx
382         lock
383         cmpxchgq %rcx, (%rdi)
384         jne     1b
385         movq    %rcx, %rax
386         ret
387         SET_SIZE(atomic_add_long_nv)
388         SET_SIZE(atomic_add_ptr_nv)
389         SET_SIZE(atomic_add_64_nv)
390
391         ENTRY(atomic_sub_8_nv)
392         ALTENTRY(atomic_sub_char_nv)
393         movb    (%rdi), %al
394 1:
395         movb    %sil, %cl
396         subb    %al, %cl
397         lock
398         cmpxchgb %cl, (%rdi)
399         jne     1b
400         movzbl  %cl, %eax
401         ret
402         SET_SIZE(atomic_sub_char_nv)
403         SET_SIZE(atomic_sub_8_nv)
404
405         ENTRY(atomic_sub_16_nv)
406         ALTENTRY(atomic_sub_short_nv)
407         movw    (%rdi), %ax
408 1:
409         movw    %si, %cx
410         subw    %ax, %cx
411         lock
412         cmpxchgw %cx, (%rdi)
413         jne     1b
414         movzwl  %cx, %eax
415         ret
416         SET_SIZE(atomic_sub_short_nv)
417         SET_SIZE(atomic_sub_16_nv)
418
419         ENTRY(atomic_sub_32_nv)
420         ALTENTRY(atomic_sub_int_nv)
421         movl    (%rdi), %eax
422 1:
423         movl    %esi, %ecx
424         subl    %eax, %ecx
425         lock
426         cmpxchgl %ecx, (%rdi)
427         jne     1b
428         movl    %ecx, %eax
429         ret
430         SET_SIZE(atomic_sub_int_nv)
431         SET_SIZE(atomic_sub_32_nv)
432
433         ENTRY(atomic_sub_64_nv)
434         ALTENTRY(atomic_sub_ptr_nv)
435         ALTENTRY(atomic_sub_long_nv)
436         movq    (%rdi), %rax
437 1:
438         movq    %rsi, %rcx
439         subq    %rax, %rcx
440         lock
441         cmpxchgq %rcx, (%rdi)
442         jne     1b
443         movq    %rcx, %rax
444         ret
445         SET_SIZE(atomic_sub_long_nv)
446         SET_SIZE(atomic_sub_ptr_nv)
447         SET_SIZE(atomic_sub_64_nv)
448
449         ENTRY(atomic_and_8_nv)
450         ALTENTRY(atomic_and_uchar_nv)
451         movb    (%rdi), %al
452 1:
453         movb    %sil, %cl
454         andb    %al, %cl
455         lock
456         cmpxchgb %cl, (%rdi)
457         jne     1b
458         movzbl  %cl, %eax
459         ret
460         SET_SIZE(atomic_and_uchar_nv)
461         SET_SIZE(atomic_and_8_nv)
462
463         ENTRY(atomic_and_16_nv)
464         ALTENTRY(atomic_and_ushort_nv)
465         movw    (%rdi), %ax
466 1:
467         movw    %si, %cx
468         andw    %ax, %cx
469         lock
470         cmpxchgw %cx, (%rdi)
471         jne     1b
472         movzwl  %cx, %eax
473         ret
474         SET_SIZE(atomic_and_ushort_nv)
475         SET_SIZE(atomic_and_16_nv)
476
477         ENTRY(atomic_and_32_nv)
478         ALTENTRY(atomic_and_uint_nv)
479         movl    (%rdi), %eax
480 1:
481         movl    %esi, %ecx
482         andl    %eax, %ecx
483         lock
484         cmpxchgl %ecx, (%rdi)
485         jne     1b
486         movl    %ecx, %eax
487         ret
488         SET_SIZE(atomic_and_uint_nv)
489         SET_SIZE(atomic_and_32_nv)
490
491         ENTRY(atomic_and_64_nv)
492         ALTENTRY(atomic_and_ulong_nv)
493         movq    (%rdi), %rax
494 1:
495         movq    %rsi, %rcx
496         andq    %rax, %rcx
497         lock
498         cmpxchgq %rcx, (%rdi)
499         jne     1b
500         movq    %rcx, %rax
501         ret
502         SET_SIZE(atomic_and_ulong_nv)
503         SET_SIZE(atomic_and_64_nv)
504
505         ENTRY(atomic_or_8_nv)
506         ALTENTRY(atomic_or_uchar_nv)
507         movb    (%rdi), %al
508 1:
509         movb    %sil, %cl
510         orb     %al, %cl
511         lock
512         cmpxchgb %cl, (%rdi)
513         jne     1b
514         movzbl  %cl, %eax
515         ret
516         SET_SIZE(atomic_and_uchar_nv)
517         SET_SIZE(atomic_and_8_nv)
518
519         ENTRY(atomic_or_16_nv)
520         ALTENTRY(atomic_or_ushort_nv)
521         movw    (%rdi), %ax
522 1:
523         movw    %si, %cx
524         orw     %ax, %cx
525         lock
526         cmpxchgw %cx, (%rdi)
527         jne     1b
528         movzwl  %cx, %eax
529         ret
530         SET_SIZE(atomic_or_ushort_nv)
531         SET_SIZE(atomic_or_16_nv)
532
533         ENTRY(atomic_or_32_nv)
534         ALTENTRY(atomic_or_uint_nv)
535         movl    (%rdi), %eax
536 1:
537         movl    %esi, %ecx
538         orl     %eax, %ecx
539         lock
540         cmpxchgl %ecx, (%rdi)
541         jne     1b
542         movl    %ecx, %eax
543         ret
544         SET_SIZE(atomic_or_uint_nv)
545         SET_SIZE(atomic_or_32_nv)
546
547         ENTRY(atomic_or_64_nv)
548         ALTENTRY(atomic_or_ulong_nv)
549         movq    (%rdi), %rax
550 1:
551         movq    %rsi, %rcx
552         orq     %rax, %rcx
553         lock
554         cmpxchgq %rcx, (%rdi)
555         jne     1b
556         movq    %rcx, %rax
557         ret
558         SET_SIZE(atomic_or_ulong_nv)
559         SET_SIZE(atomic_or_64_nv)
560
561         ENTRY(atomic_cas_8)
562         ALTENTRY(atomic_cas_uchar)
563         movzbl  %sil, %eax
564         lock
565         cmpxchgb %dl, (%rdi)
566         ret
567         SET_SIZE(atomic_cas_uchar)
568         SET_SIZE(atomic_cas_8)
569
570         ENTRY(atomic_cas_16)
571         ALTENTRY(atomic_cas_ushort)
572         movzwl  %si, %eax
573         lock
574         cmpxchgw %dx, (%rdi)
575         ret
576         SET_SIZE(atomic_cas_ushort)
577         SET_SIZE(atomic_cas_16)
578
579         ENTRY(atomic_cas_32)
580         ALTENTRY(atomic_cas_uint)
581         movl    %esi, %eax
582         lock
583         cmpxchgl %edx, (%rdi)
584         ret
585         SET_SIZE(atomic_cas_uint)
586         SET_SIZE(atomic_cas_32)
587
588         ENTRY(atomic_cas_64)
589         ALTENTRY(atomic_cas_ulong)
590         ALTENTRY(atomic_cas_ptr)
591         movq    %rsi, %rax
592         lock
593         cmpxchgq %rdx, (%rdi)
594         ret
595         SET_SIZE(atomic_cas_ptr)
596         SET_SIZE(atomic_cas_ulong)
597         SET_SIZE(atomic_cas_64)
598
599         ENTRY(atomic_swap_8)
600         ALTENTRY(atomic_swap_uchar)
601         movzbl  %sil, %eax
602         lock
603         xchgb %al, (%rdi)
604         ret
605         SET_SIZE(atomic_swap_uchar)
606         SET_SIZE(atomic_swap_8)
607
608         ENTRY(atomic_swap_16)
609         ALTENTRY(atomic_swap_ushort)
610         movzwl  %si, %eax
611         lock
612         xchgw %ax, (%rdi)
613         ret
614         SET_SIZE(atomic_swap_ushort)
615         SET_SIZE(atomic_swap_16)
616
617         ENTRY(atomic_swap_32)
618         ALTENTRY(atomic_swap_uint)
619         movl    %esi, %eax
620         lock
621         xchgl %eax, (%rdi)
622         ret
623         SET_SIZE(atomic_swap_uint)
624         SET_SIZE(atomic_swap_32)
625
626         ENTRY(atomic_swap_64)
627         ALTENTRY(atomic_swap_ulong)
628         ALTENTRY(atomic_swap_ptr)
629         movq    %rsi, %rax
630         lock
631         xchgq %rax, (%rdi)
632         ret
633         SET_SIZE(atomic_swap_ptr)
634         SET_SIZE(atomic_swap_ulong)
635         SET_SIZE(atomic_swap_64)
636
637         ENTRY(atomic_set_long_excl)
638         xorl    %eax, %eax
639         lock
640         btsq    %rsi, (%rdi)
641         jnc     1f
642         decl    %eax
643 1:
644         ret
645         SET_SIZE(atomic_set_long_excl)
646
647         ENTRY(atomic_clear_long_excl)
648         xorl    %eax, %eax
649         lock
650         btrq    %rsi, (%rdi)
651         jc      1f
652         decl    %eax
653 1:
654         ret
655         SET_SIZE(atomic_clear_long_excl)
656
657         /*
658          * NOTE: membar_enter, and membar_exit are identical routines. 
659          * We define them separately, instead of using an ALTENTRY
660          * definitions to alias them together, so that DTrace and
661          * debuggers will see a unique address for them, allowing 
662          * more accurate tracing.
663         */
664
665         ENTRY(membar_enter)
666         mfence
667         ret
668         SET_SIZE(membar_enter)
669
670         ENTRY(membar_exit)
671         mfence
672         ret
673         SET_SIZE(membar_exit)
674
675         ENTRY(membar_producer)
676         sfence
677         ret
678         SET_SIZE(membar_producer)
679
680         ENTRY(membar_consumer)
681         lfence
682         ret
683         SET_SIZE(membar_consumer)
684
685 #ifdef __ELF__
686 .section .note.GNU-stack,"",%progbits
687 #endif