123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226 |
- /*
- * atomic64_t for 586+
- *
- * Copied from arch/x86/lib/atomic64_cx8_32.S
- *
- * Copyright © 2010 Luca Barbieri
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- */
- #include <linux/linkage.h>
- #include <asm/alternative-asm.h>
- #include <asm/dwarf2.h>
- .macro SAVE reg
- pushl_cfi %\reg
- CFI_REL_OFFSET \reg, 0
- .endm
- .macro RESTORE reg
- popl_cfi %\reg
- CFI_RESTORE \reg
- .endm
- .macro read64 reg
- movl %ebx, %eax
- movl %ecx, %edx
- /* we need LOCK_PREFIX since otherwise cmpxchg8b always does the write */
- LOCK_PREFIX
- cmpxchg8b (\reg)
- .endm
- ENTRY(atomic64_read_cx8)
- CFI_STARTPROC
- read64 %ecx
- ret
- CFI_ENDPROC
- ENDPROC(atomic64_read_cx8)
- ENTRY(atomic64_set_cx8)
- CFI_STARTPROC
- 1:
- /* we don't need LOCK_PREFIX since aligned 64-bit writes
- * are atomic on 586 and newer */
- cmpxchg8b (%esi)
- jne 1b
- ret
- CFI_ENDPROC
- ENDPROC(atomic64_set_cx8)
- ENTRY(atomic64_xchg_cx8)
- CFI_STARTPROC
- movl %ebx, %eax
- movl %ecx, %edx
- 1:
- LOCK_PREFIX
- cmpxchg8b (%esi)
- jne 1b
- ret
- CFI_ENDPROC
- ENDPROC(atomic64_xchg_cx8)
- .macro addsub_return func ins insc
- ENTRY(atomic64_\func\()_return_cx8)
- CFI_STARTPROC
- SAVE ebp
- SAVE ebx
- SAVE esi
- SAVE edi
- movl %eax, %esi
- movl %edx, %edi
- movl %ecx, %ebp
- read64 %ebp
- 1:
- movl %eax, %ebx
- movl %edx, %ecx
- \ins\()l %esi, %ebx
- \insc\()l %edi, %ecx
- LOCK_PREFIX
- cmpxchg8b (%ebp)
- jne 1b
- 10:
- movl %ebx, %eax
- movl %ecx, %edx
- RESTORE edi
- RESTORE esi
- RESTORE ebx
- RESTORE ebp
- ret
- CFI_ENDPROC
- ENDPROC(atomic64_\func\()_return_cx8)
- .endm
- addsub_return add add adc
- addsub_return sub sub sbb
- .macro incdec_return func ins insc
- ENTRY(atomic64_\func\()_return_cx8)
- CFI_STARTPROC
- SAVE ebx
- read64 %esi
- 1:
- movl %eax, %ebx
- movl %edx, %ecx
- \ins\()l $1, %ebx
- \insc\()l $0, %ecx
- LOCK_PREFIX
- cmpxchg8b (%esi)
- jne 1b
- 10:
- movl %ebx, %eax
- movl %ecx, %edx
- RESTORE ebx
- ret
- CFI_ENDPROC
- ENDPROC(atomic64_\func\()_return_cx8)
- .endm
- incdec_return inc add adc
- incdec_return dec sub sbb
- ENTRY(atomic64_dec_if_positive_cx8)
- CFI_STARTPROC
- SAVE ebx
- read64 %esi
- 1:
- movl %eax, %ebx
- movl %edx, %ecx
- subl $1, %ebx
- sbb $0, %ecx
- js 2f
- LOCK_PREFIX
- cmpxchg8b (%esi)
- jne 1b
- 2:
- movl %ebx, %eax
- movl %ecx, %edx
- RESTORE ebx
- ret
- CFI_ENDPROC
- ENDPROC(atomic64_dec_if_positive_cx8)
- ENTRY(atomic64_add_unless_cx8)
- CFI_STARTPROC
- SAVE ebp
- SAVE ebx
- /* these just push these two parameters on the stack */
- SAVE edi
- SAVE esi
- movl %ecx, %ebp
- movl %eax, %esi
- movl %edx, %edi
- read64 %ebp
- 1:
- cmpl %eax, 0(%esp)
- je 4f
- 2:
- movl %eax, %ebx
- movl %edx, %ecx
- addl %esi, %ebx
- adcl %edi, %ecx
- LOCK_PREFIX
- cmpxchg8b (%ebp)
- jne 1b
- movl $1, %eax
- 3:
- addl $8, %esp
- CFI_ADJUST_CFA_OFFSET -8
- RESTORE ebx
- RESTORE ebp
- ret
- 4:
- cmpl %edx, 4(%esp)
- jne 2b
- xorl %eax, %eax
- jmp 3b
- CFI_ENDPROC
- ENDPROC(atomic64_add_unless_cx8)
- ENTRY(atomic64_inc_not_zero_cx8)
- CFI_STARTPROC
- SAVE ebx
- read64 %esi
- 1:
- testl %eax, %eax
- je 4f
- 2:
- movl %eax, %ebx
- movl %edx, %ecx
- addl $1, %ebx
- adcl $0, %ecx
- LOCK_PREFIX
- cmpxchg8b (%esi)
- jne 1b
- movl $1, %eax
- 3:
- RESTORE ebx
- ret
- 4:
- testl %edx, %edx
- jne 2b
- jmp 3b
- CFI_ENDPROC
- ENDPROC(atomic64_inc_not_zero_cx8)
|