diff options
Diffstat (limited to 'arch/x86/lib/atomic64_386_32.S')
-rw-r--r-- | arch/x86/lib/atomic64_386_32.S | 195 |
1 files changed, 195 insertions, 0 deletions
diff --git a/arch/x86/lib/atomic64_386_32.S b/arch/x86/lib/atomic64_386_32.S new file mode 100644 index 000000000..e768815e5 --- /dev/null +++ b/arch/x86/lib/atomic64_386_32.S @@ -0,0 +1,195 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ +/* + * atomic64_t for 386/486 + * + * Copyright © 2010 Luca Barbieri + */ + +#include <linux/linkage.h> +#include <asm/alternative.h> + +/* if you want SMP support, implement these with real spinlocks */ +.macro IRQ_SAVE reg + pushfl + cli +.endm + +.macro IRQ_RESTORE reg + popfl +.endm + +#define BEGIN_IRQ_SAVE(op) \ +.macro endp; \ +SYM_FUNC_END(atomic64_##op##_386); \ +.purgem endp; \ +.endm; \ +SYM_FUNC_START(atomic64_##op##_386); \ + IRQ_SAVE v; + +#define ENDP endp + +#define RET_IRQ_RESTORE \ + IRQ_RESTORE v; \ + RET + +#define v %ecx +BEGIN_IRQ_SAVE(read) + movl (v), %eax + movl 4(v), %edx + RET_IRQ_RESTORE +ENDP +#undef v + +#define v %esi +BEGIN_IRQ_SAVE(set) + movl %ebx, (v) + movl %ecx, 4(v) + RET_IRQ_RESTORE +ENDP +#undef v + +#define v %esi +BEGIN_IRQ_SAVE(xchg) + movl (v), %eax + movl 4(v), %edx + movl %ebx, (v) + movl %ecx, 4(v) + RET_IRQ_RESTORE +ENDP +#undef v + +#define v %ecx +BEGIN_IRQ_SAVE(add) + addl %eax, (v) + adcl %edx, 4(v) + RET_IRQ_RESTORE +ENDP +#undef v + +#define v %ecx +BEGIN_IRQ_SAVE(add_return) + addl (v), %eax + adcl 4(v), %edx + movl %eax, (v) + movl %edx, 4(v) + RET_IRQ_RESTORE +ENDP +#undef v + +#define v %ecx +BEGIN_IRQ_SAVE(sub) + subl %eax, (v) + sbbl %edx, 4(v) + RET_IRQ_RESTORE +ENDP +#undef v + +#define v %ecx +BEGIN_IRQ_SAVE(sub_return) + negl %edx + negl %eax + sbbl $0, %edx + addl (v), %eax + adcl 4(v), %edx + movl %eax, (v) + movl %edx, 4(v) + RET_IRQ_RESTORE +ENDP +#undef v + +#define v %esi +BEGIN_IRQ_SAVE(inc) + addl $1, (v) + adcl $0, 4(v) + RET_IRQ_RESTORE +ENDP +#undef v + +#define v %esi +BEGIN_IRQ_SAVE(inc_return) + movl (v), %eax + movl 4(v), %edx + addl $1, %eax + adcl $0, %edx + movl %eax, (v) + movl %edx, 4(v) + RET_IRQ_RESTORE +ENDP +#undef v + +#define v %esi +BEGIN_IRQ_SAVE(dec) + subl $1, (v) + sbbl $0, 4(v) + RET_IRQ_RESTORE +ENDP +#undef v + +#define v %esi +BEGIN_IRQ_SAVE(dec_return) + movl (v), %eax + movl 4(v), %edx + subl $1, %eax + sbbl $0, %edx + movl %eax, (v) + movl %edx, 4(v) + RET_IRQ_RESTORE +ENDP +#undef v + +#define v %esi +BEGIN_IRQ_SAVE(add_unless) + addl %eax, %ecx + adcl %edx, %edi + addl (v), %eax + adcl 4(v), %edx + cmpl %eax, %ecx + je 3f +1: + movl %eax, (v) + movl %edx, 4(v) + movl $1, %eax +2: + RET_IRQ_RESTORE +3: + cmpl %edx, %edi + jne 1b + xorl %eax, %eax + jmp 2b +ENDP +#undef v + +#define v %esi +BEGIN_IRQ_SAVE(inc_not_zero) + movl (v), %eax + movl 4(v), %edx + testl %eax, %eax + je 3f +1: + addl $1, %eax + adcl $0, %edx + movl %eax, (v) + movl %edx, 4(v) + movl $1, %eax +2: + RET_IRQ_RESTORE +3: + testl %edx, %edx + jne 1b + jmp 2b +ENDP +#undef v + +#define v %esi +BEGIN_IRQ_SAVE(dec_if_positive) + movl (v), %eax + movl 4(v), %edx + subl $1, %eax + sbbl $0, %edx + js 1f + movl %eax, (v) + movl %edx, 4(v) +1: + RET_IRQ_RESTORE +ENDP +#undef v |