Add the rt linux 4.1.3-rt3 as base
[kvmfornfv.git] / kernel / arch / x86 / lib / atomic64_386_32.S
diff --git a/kernel/arch/x86/lib/atomic64_386_32.S b/kernel/arch/x86/lib/atomic64_386_32.S
new file mode 100644 (file)
index 0000000..00933d5
--- /dev/null
@@ -0,0 +1,194 @@
+/*
+ * atomic64_t for 386/486
+ *
+ * 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>
+
+/* if you want SMP support, implement these with real spinlocks */
+.macro LOCK reg
+       pushfl_cfi
+       cli
+.endm
+
+.macro UNLOCK reg
+       popfl_cfi
+.endm
+
+#define BEGIN(op) \
+.macro endp; \
+       CFI_ENDPROC; \
+ENDPROC(atomic64_##op##_386); \
+.purgem endp; \
+.endm; \
+ENTRY(atomic64_##op##_386); \
+       CFI_STARTPROC; \
+       LOCK v;
+
+#define ENDP endp
+
+#define RET \
+       UNLOCK v; \
+       ret
+
+#define RET_ENDP \
+       RET; \
+       ENDP
+
+#define v %ecx
+BEGIN(read)
+       movl  (v), %eax
+       movl 4(v), %edx
+RET_ENDP
+#undef v
+
+#define v %esi
+BEGIN(set)
+       movl %ebx,  (v)
+       movl %ecx, 4(v)
+RET_ENDP
+#undef v
+
+#define v  %esi
+BEGIN(xchg)
+       movl  (v), %eax
+       movl 4(v), %edx
+       movl %ebx,  (v)
+       movl %ecx, 4(v)
+RET_ENDP
+#undef v
+
+#define v %ecx
+BEGIN(add)
+       addl %eax,  (v)
+       adcl %edx, 4(v)
+RET_ENDP
+#undef v
+
+#define v %ecx
+BEGIN(add_return)
+       addl  (v), %eax
+       adcl 4(v), %edx
+       movl %eax,  (v)
+       movl %edx, 4(v)
+RET_ENDP
+#undef v
+
+#define v %ecx
+BEGIN(sub)
+       subl %eax,  (v)
+       sbbl %edx, 4(v)
+RET_ENDP
+#undef v
+
+#define v %ecx
+BEGIN(sub_return)
+       negl %edx
+       negl %eax
+       sbbl $0, %edx
+       addl  (v), %eax
+       adcl 4(v), %edx
+       movl %eax,  (v)
+       movl %edx, 4(v)
+RET_ENDP
+#undef v
+
+#define v %esi
+BEGIN(inc)
+       addl $1,  (v)
+       adcl $0, 4(v)
+RET_ENDP
+#undef v
+
+#define v %esi
+BEGIN(inc_return)
+       movl  (v), %eax
+       movl 4(v), %edx
+       addl $1, %eax
+       adcl $0, %edx
+       movl %eax,  (v)
+       movl %edx, 4(v)
+RET_ENDP
+#undef v
+
+#define v %esi
+BEGIN(dec)
+       subl $1,  (v)
+       sbbl $0, 4(v)
+RET_ENDP
+#undef v
+
+#define v %esi
+BEGIN(dec_return)
+       movl  (v), %eax
+       movl 4(v), %edx
+       subl $1, %eax
+       sbbl $0, %edx
+       movl %eax,  (v)
+       movl %edx, 4(v)
+RET_ENDP
+#undef v
+
+#define v %esi
+BEGIN(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
+3:
+       cmpl %edx, %edi
+       jne 1b
+       xorl %eax, %eax
+       jmp 2b
+ENDP
+#undef v
+
+#define v %esi
+BEGIN(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
+3:
+       testl %edx, %edx
+       jne 1b
+       jmp 2b
+ENDP
+#undef v
+
+#define v %esi
+BEGIN(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_ENDP
+#undef v