/* 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