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