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