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