summaryrefslogtreecommitdiffstats
path: root/arch/x86/lib/atomic64_386_32.S
diff options
context:
space:
mode:
Diffstat (limited to 'arch/x86/lib/atomic64_386_32.S')
-rw-r--r--arch/x86/lib/atomic64_386_32.S195
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