162306a36Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0-or-later */ 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * atomic64_t for 386/486 462306a36Sopenharmony_ci * 562306a36Sopenharmony_ci * Copyright © 2010 Luca Barbieri 662306a36Sopenharmony_ci */ 762306a36Sopenharmony_ci 862306a36Sopenharmony_ci#include <linux/linkage.h> 962306a36Sopenharmony_ci#include <asm/alternative.h> 1062306a36Sopenharmony_ci 1162306a36Sopenharmony_ci/* if you want SMP support, implement these with real spinlocks */ 1262306a36Sopenharmony_ci.macro IRQ_SAVE reg 1362306a36Sopenharmony_ci pushfl 1462306a36Sopenharmony_ci cli 1562306a36Sopenharmony_ci.endm 1662306a36Sopenharmony_ci 1762306a36Sopenharmony_ci.macro IRQ_RESTORE reg 1862306a36Sopenharmony_ci popfl 1962306a36Sopenharmony_ci.endm 2062306a36Sopenharmony_ci 2162306a36Sopenharmony_ci#define BEGIN_IRQ_SAVE(op) \ 2262306a36Sopenharmony_ci.macro endp; \ 2362306a36Sopenharmony_ciSYM_FUNC_END(atomic64_##op##_386); \ 2462306a36Sopenharmony_ci.purgem endp; \ 2562306a36Sopenharmony_ci.endm; \ 2662306a36Sopenharmony_ciSYM_FUNC_START(atomic64_##op##_386); \ 2762306a36Sopenharmony_ci IRQ_SAVE v; 2862306a36Sopenharmony_ci 2962306a36Sopenharmony_ci#define ENDP endp 3062306a36Sopenharmony_ci 3162306a36Sopenharmony_ci#define RET_IRQ_RESTORE \ 3262306a36Sopenharmony_ci IRQ_RESTORE v; \ 3362306a36Sopenharmony_ci RET 3462306a36Sopenharmony_ci 3562306a36Sopenharmony_ci#define v %ecx 3662306a36Sopenharmony_ciBEGIN_IRQ_SAVE(read) 3762306a36Sopenharmony_ci movl (v), %eax 3862306a36Sopenharmony_ci movl 4(v), %edx 3962306a36Sopenharmony_ci RET_IRQ_RESTORE 4062306a36Sopenharmony_ciENDP 4162306a36Sopenharmony_ci#undef v 4262306a36Sopenharmony_ci 4362306a36Sopenharmony_ci#define v %esi 4462306a36Sopenharmony_ciBEGIN_IRQ_SAVE(set) 4562306a36Sopenharmony_ci movl %ebx, (v) 4662306a36Sopenharmony_ci movl %ecx, 4(v) 4762306a36Sopenharmony_ci RET_IRQ_RESTORE 4862306a36Sopenharmony_ciENDP 4962306a36Sopenharmony_ci#undef v 5062306a36Sopenharmony_ci 5162306a36Sopenharmony_ci#define v %esi 5262306a36Sopenharmony_ciBEGIN_IRQ_SAVE(xchg) 5362306a36Sopenharmony_ci movl (v), %eax 5462306a36Sopenharmony_ci movl 4(v), %edx 5562306a36Sopenharmony_ci movl %ebx, (v) 5662306a36Sopenharmony_ci movl %ecx, 4(v) 5762306a36Sopenharmony_ci RET_IRQ_RESTORE 5862306a36Sopenharmony_ciENDP 5962306a36Sopenharmony_ci#undef v 6062306a36Sopenharmony_ci 6162306a36Sopenharmony_ci#define v %ecx 6262306a36Sopenharmony_ciBEGIN_IRQ_SAVE(add) 6362306a36Sopenharmony_ci addl %eax, (v) 6462306a36Sopenharmony_ci adcl %edx, 4(v) 6562306a36Sopenharmony_ci RET_IRQ_RESTORE 6662306a36Sopenharmony_ciENDP 6762306a36Sopenharmony_ci#undef v 6862306a36Sopenharmony_ci 6962306a36Sopenharmony_ci#define v %ecx 7062306a36Sopenharmony_ciBEGIN_IRQ_SAVE(add_return) 7162306a36Sopenharmony_ci addl (v), %eax 7262306a36Sopenharmony_ci adcl 4(v), %edx 7362306a36Sopenharmony_ci movl %eax, (v) 7462306a36Sopenharmony_ci movl %edx, 4(v) 7562306a36Sopenharmony_ci RET_IRQ_RESTORE 7662306a36Sopenharmony_ciENDP 7762306a36Sopenharmony_ci#undef v 7862306a36Sopenharmony_ci 7962306a36Sopenharmony_ci#define v %ecx 8062306a36Sopenharmony_ciBEGIN_IRQ_SAVE(sub) 8162306a36Sopenharmony_ci subl %eax, (v) 8262306a36Sopenharmony_ci sbbl %edx, 4(v) 8362306a36Sopenharmony_ci RET_IRQ_RESTORE 8462306a36Sopenharmony_ciENDP 8562306a36Sopenharmony_ci#undef v 8662306a36Sopenharmony_ci 8762306a36Sopenharmony_ci#define v %ecx 8862306a36Sopenharmony_ciBEGIN_IRQ_SAVE(sub_return) 8962306a36Sopenharmony_ci negl %edx 9062306a36Sopenharmony_ci negl %eax 9162306a36Sopenharmony_ci sbbl $0, %edx 9262306a36Sopenharmony_ci addl (v), %eax 9362306a36Sopenharmony_ci adcl 4(v), %edx 9462306a36Sopenharmony_ci movl %eax, (v) 9562306a36Sopenharmony_ci movl %edx, 4(v) 9662306a36Sopenharmony_ci RET_IRQ_RESTORE 9762306a36Sopenharmony_ciENDP 9862306a36Sopenharmony_ci#undef v 9962306a36Sopenharmony_ci 10062306a36Sopenharmony_ci#define v %esi 10162306a36Sopenharmony_ciBEGIN_IRQ_SAVE(inc) 10262306a36Sopenharmony_ci addl $1, (v) 10362306a36Sopenharmony_ci adcl $0, 4(v) 10462306a36Sopenharmony_ci RET_IRQ_RESTORE 10562306a36Sopenharmony_ciENDP 10662306a36Sopenharmony_ci#undef v 10762306a36Sopenharmony_ci 10862306a36Sopenharmony_ci#define v %esi 10962306a36Sopenharmony_ciBEGIN_IRQ_SAVE(inc_return) 11062306a36Sopenharmony_ci movl (v), %eax 11162306a36Sopenharmony_ci movl 4(v), %edx 11262306a36Sopenharmony_ci addl $1, %eax 11362306a36Sopenharmony_ci adcl $0, %edx 11462306a36Sopenharmony_ci movl %eax, (v) 11562306a36Sopenharmony_ci movl %edx, 4(v) 11662306a36Sopenharmony_ci RET_IRQ_RESTORE 11762306a36Sopenharmony_ciENDP 11862306a36Sopenharmony_ci#undef v 11962306a36Sopenharmony_ci 12062306a36Sopenharmony_ci#define v %esi 12162306a36Sopenharmony_ciBEGIN_IRQ_SAVE(dec) 12262306a36Sopenharmony_ci subl $1, (v) 12362306a36Sopenharmony_ci sbbl $0, 4(v) 12462306a36Sopenharmony_ci RET_IRQ_RESTORE 12562306a36Sopenharmony_ciENDP 12662306a36Sopenharmony_ci#undef v 12762306a36Sopenharmony_ci 12862306a36Sopenharmony_ci#define v %esi 12962306a36Sopenharmony_ciBEGIN_IRQ_SAVE(dec_return) 13062306a36Sopenharmony_ci movl (v), %eax 13162306a36Sopenharmony_ci movl 4(v), %edx 13262306a36Sopenharmony_ci subl $1, %eax 13362306a36Sopenharmony_ci sbbl $0, %edx 13462306a36Sopenharmony_ci movl %eax, (v) 13562306a36Sopenharmony_ci movl %edx, 4(v) 13662306a36Sopenharmony_ci RET_IRQ_RESTORE 13762306a36Sopenharmony_ciENDP 13862306a36Sopenharmony_ci#undef v 13962306a36Sopenharmony_ci 14062306a36Sopenharmony_ci#define v %esi 14162306a36Sopenharmony_ciBEGIN_IRQ_SAVE(add_unless) 14262306a36Sopenharmony_ci addl %eax, %ecx 14362306a36Sopenharmony_ci adcl %edx, %edi 14462306a36Sopenharmony_ci addl (v), %eax 14562306a36Sopenharmony_ci adcl 4(v), %edx 14662306a36Sopenharmony_ci cmpl %eax, %ecx 14762306a36Sopenharmony_ci je 3f 14862306a36Sopenharmony_ci1: 14962306a36Sopenharmony_ci movl %eax, (v) 15062306a36Sopenharmony_ci movl %edx, 4(v) 15162306a36Sopenharmony_ci movl $1, %eax 15262306a36Sopenharmony_ci2: 15362306a36Sopenharmony_ci RET_IRQ_RESTORE 15462306a36Sopenharmony_ci3: 15562306a36Sopenharmony_ci cmpl %edx, %edi 15662306a36Sopenharmony_ci jne 1b 15762306a36Sopenharmony_ci xorl %eax, %eax 15862306a36Sopenharmony_ci jmp 2b 15962306a36Sopenharmony_ciENDP 16062306a36Sopenharmony_ci#undef v 16162306a36Sopenharmony_ci 16262306a36Sopenharmony_ci#define v %esi 16362306a36Sopenharmony_ciBEGIN_IRQ_SAVE(inc_not_zero) 16462306a36Sopenharmony_ci movl (v), %eax 16562306a36Sopenharmony_ci movl 4(v), %edx 16662306a36Sopenharmony_ci testl %eax, %eax 16762306a36Sopenharmony_ci je 3f 16862306a36Sopenharmony_ci1: 16962306a36Sopenharmony_ci addl $1, %eax 17062306a36Sopenharmony_ci adcl $0, %edx 17162306a36Sopenharmony_ci movl %eax, (v) 17262306a36Sopenharmony_ci movl %edx, 4(v) 17362306a36Sopenharmony_ci movl $1, %eax 17462306a36Sopenharmony_ci2: 17562306a36Sopenharmony_ci RET_IRQ_RESTORE 17662306a36Sopenharmony_ci3: 17762306a36Sopenharmony_ci testl %edx, %edx 17862306a36Sopenharmony_ci jne 1b 17962306a36Sopenharmony_ci jmp 2b 18062306a36Sopenharmony_ciENDP 18162306a36Sopenharmony_ci#undef v 18262306a36Sopenharmony_ci 18362306a36Sopenharmony_ci#define v %esi 18462306a36Sopenharmony_ciBEGIN_IRQ_SAVE(dec_if_positive) 18562306a36Sopenharmony_ci movl (v), %eax 18662306a36Sopenharmony_ci movl 4(v), %edx 18762306a36Sopenharmony_ci subl $1, %eax 18862306a36Sopenharmony_ci sbbl $0, %edx 18962306a36Sopenharmony_ci js 1f 19062306a36Sopenharmony_ci movl %eax, (v) 19162306a36Sopenharmony_ci movl %edx, 4(v) 19262306a36Sopenharmony_ci1: 19362306a36Sopenharmony_ci RET_IRQ_RESTORE 19462306a36Sopenharmony_ciENDP 19562306a36Sopenharmony_ci#undef v 196