| /* |
| * 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_ADJUST_CFA_OFFSET 4 |
| cli |
| .endm |
| |
| .macro UNLOCK reg |
| popfl |
| CFI_ADJUST_CFA_OFFSET -4 |
| .endm |
| |
| .macro BEGIN func reg |
| $v = \reg |
| |
| ENTRY(atomic64_\func\()_386) |
| CFI_STARTPROC |
| LOCK $v |
| |
| .macro RETURN |
| UNLOCK $v |
| ret |
| .endm |
| |
| .macro END_ |
| CFI_ENDPROC |
| ENDPROC(atomic64_\func\()_386) |
| .purgem RETURN |
| .purgem END_ |
| .purgem END |
| .endm |
| |
| .macro END |
| RETURN |
| END_ |
| .endm |
| .endm |
| |
| BEGIN read %ecx |
| movl ($v), %eax |
| movl 4($v), %edx |
| END |
| |
| BEGIN set %esi |
| movl %ebx, ($v) |
| movl %ecx, 4($v) |
| END |
| |
| BEGIN xchg %esi |
| movl ($v), %eax |
| movl 4($v), %edx |
| movl %ebx, ($v) |
| movl %ecx, 4($v) |
| END |
| |
| BEGIN add %ecx |
| addl %eax, ($v) |
| adcl %edx, 4($v) |
| END |
| |
| BEGIN add_return %ecx |
| addl ($v), %eax |
| adcl 4($v), %edx |
| movl %eax, ($v) |
| movl %edx, 4($v) |
| END |
| |
| BEGIN sub %ecx |
| subl %eax, ($v) |
| sbbl %edx, 4($v) |
| END |
| |
| BEGIN sub_return %ecx |
| negl %edx |
| negl %eax |
| sbbl $0, %edx |
| addl ($v), %eax |
| adcl 4($v), %edx |
| movl %eax, ($v) |
| movl %edx, 4($v) |
| END |
| |
| BEGIN inc %esi |
| addl $1, ($v) |
| adcl $0, 4($v) |
| END |
| |
| BEGIN inc_return %esi |
| movl ($v), %eax |
| movl 4($v), %edx |
| addl $1, %eax |
| adcl $0, %edx |
| movl %eax, ($v) |
| movl %edx, 4($v) |
| END |
| |
| BEGIN dec %esi |
| subl $1, ($v) |
| sbbl $0, 4($v) |
| END |
| |
| BEGIN dec_return %esi |
| movl ($v), %eax |
| movl 4($v), %edx |
| subl $1, %eax |
| sbbl $0, %edx |
| movl %eax, ($v) |
| movl %edx, 4($v) |
| END |
| |
| BEGIN add_unless %ecx |
| addl %eax, %esi |
| adcl %edx, %edi |
| addl ($v), %eax |
| adcl 4($v), %edx |
| cmpl %eax, %esi |
| je 3f |
| 1: |
| movl %eax, ($v) |
| movl %edx, 4($v) |
| movl $1, %eax |
| 2: |
| RETURN |
| 3: |
| cmpl %edx, %edi |
| jne 1b |
| xorl %eax, %eax |
| jmp 2b |
| END_ |
| |
| BEGIN inc_not_zero %esi |
| 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: |
| RETURN |
| 3: |
| testl %edx, %edx |
| jne 1b |
| jmp 2b |
| END_ |
| |
| BEGIN dec_if_positive %esi |
| movl ($v), %eax |
| movl 4($v), %edx |
| subl $1, %eax |
| sbbl $0, %edx |
| js 1f |
| movl %eax, ($v) |
| movl %edx, 4($v) |
| 1: |
| END |