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