18c2ecf20Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0-or-later */
28c2ecf20Sopenharmony_ci/*
38c2ecf20Sopenharmony_ci * atomic64_t for 386/486
48c2ecf20Sopenharmony_ci *
58c2ecf20Sopenharmony_ci * Copyright © 2010  Luca Barbieri
68c2ecf20Sopenharmony_ci */
78c2ecf20Sopenharmony_ci
88c2ecf20Sopenharmony_ci#include <linux/linkage.h>
98c2ecf20Sopenharmony_ci#include <asm/alternative.h>
108c2ecf20Sopenharmony_ci
118c2ecf20Sopenharmony_ci/* if you want SMP support, implement these with real spinlocks */
128c2ecf20Sopenharmony_ci.macro IRQ_SAVE reg
138c2ecf20Sopenharmony_ci	pushfl
148c2ecf20Sopenharmony_ci	cli
158c2ecf20Sopenharmony_ci.endm
168c2ecf20Sopenharmony_ci
178c2ecf20Sopenharmony_ci.macro IRQ_RESTORE reg
188c2ecf20Sopenharmony_ci	popfl
198c2ecf20Sopenharmony_ci.endm
208c2ecf20Sopenharmony_ci
218c2ecf20Sopenharmony_ci#define BEGIN_IRQ_SAVE(op) \
228c2ecf20Sopenharmony_ci.macro endp; \
238c2ecf20Sopenharmony_ciSYM_FUNC_END(atomic64_##op##_386); \
248c2ecf20Sopenharmony_ci.purgem endp; \
258c2ecf20Sopenharmony_ci.endm; \
268c2ecf20Sopenharmony_ciSYM_FUNC_START(atomic64_##op##_386); \
278c2ecf20Sopenharmony_ci	IRQ_SAVE v;
288c2ecf20Sopenharmony_ci
298c2ecf20Sopenharmony_ci#define ENDP endp
308c2ecf20Sopenharmony_ci
318c2ecf20Sopenharmony_ci#define RET_IRQ_RESTORE \
328c2ecf20Sopenharmony_ci	IRQ_RESTORE v; \
338c2ecf20Sopenharmony_ci	RET
348c2ecf20Sopenharmony_ci
358c2ecf20Sopenharmony_ci#define v %ecx
368c2ecf20Sopenharmony_ciBEGIN_IRQ_SAVE(read)
378c2ecf20Sopenharmony_ci	movl  (v), %eax
388c2ecf20Sopenharmony_ci	movl 4(v), %edx
398c2ecf20Sopenharmony_ci	RET_IRQ_RESTORE
408c2ecf20Sopenharmony_ciENDP
418c2ecf20Sopenharmony_ci#undef v
428c2ecf20Sopenharmony_ci
438c2ecf20Sopenharmony_ci#define v %esi
448c2ecf20Sopenharmony_ciBEGIN_IRQ_SAVE(set)
458c2ecf20Sopenharmony_ci	movl %ebx,  (v)
468c2ecf20Sopenharmony_ci	movl %ecx, 4(v)
478c2ecf20Sopenharmony_ci	RET_IRQ_RESTORE
488c2ecf20Sopenharmony_ciENDP
498c2ecf20Sopenharmony_ci#undef v
508c2ecf20Sopenharmony_ci
518c2ecf20Sopenharmony_ci#define v  %esi
528c2ecf20Sopenharmony_ciBEGIN_IRQ_SAVE(xchg)
538c2ecf20Sopenharmony_ci	movl  (v), %eax
548c2ecf20Sopenharmony_ci	movl 4(v), %edx
558c2ecf20Sopenharmony_ci	movl %ebx,  (v)
568c2ecf20Sopenharmony_ci	movl %ecx, 4(v)
578c2ecf20Sopenharmony_ci	RET_IRQ_RESTORE
588c2ecf20Sopenharmony_ciENDP
598c2ecf20Sopenharmony_ci#undef v
608c2ecf20Sopenharmony_ci
618c2ecf20Sopenharmony_ci#define v %ecx
628c2ecf20Sopenharmony_ciBEGIN_IRQ_SAVE(add)
638c2ecf20Sopenharmony_ci	addl %eax,  (v)
648c2ecf20Sopenharmony_ci	adcl %edx, 4(v)
658c2ecf20Sopenharmony_ci	RET_IRQ_RESTORE
668c2ecf20Sopenharmony_ciENDP
678c2ecf20Sopenharmony_ci#undef v
688c2ecf20Sopenharmony_ci
698c2ecf20Sopenharmony_ci#define v %ecx
708c2ecf20Sopenharmony_ciBEGIN_IRQ_SAVE(add_return)
718c2ecf20Sopenharmony_ci	addl  (v), %eax
728c2ecf20Sopenharmony_ci	adcl 4(v), %edx
738c2ecf20Sopenharmony_ci	movl %eax,  (v)
748c2ecf20Sopenharmony_ci	movl %edx, 4(v)
758c2ecf20Sopenharmony_ci	RET_IRQ_RESTORE
768c2ecf20Sopenharmony_ciENDP
778c2ecf20Sopenharmony_ci#undef v
788c2ecf20Sopenharmony_ci
798c2ecf20Sopenharmony_ci#define v %ecx
808c2ecf20Sopenharmony_ciBEGIN_IRQ_SAVE(sub)
818c2ecf20Sopenharmony_ci	subl %eax,  (v)
828c2ecf20Sopenharmony_ci	sbbl %edx, 4(v)
838c2ecf20Sopenharmony_ci	RET_IRQ_RESTORE
848c2ecf20Sopenharmony_ciENDP
858c2ecf20Sopenharmony_ci#undef v
868c2ecf20Sopenharmony_ci
878c2ecf20Sopenharmony_ci#define v %ecx
888c2ecf20Sopenharmony_ciBEGIN_IRQ_SAVE(sub_return)
898c2ecf20Sopenharmony_ci	negl %edx
908c2ecf20Sopenharmony_ci	negl %eax
918c2ecf20Sopenharmony_ci	sbbl $0, %edx
928c2ecf20Sopenharmony_ci	addl  (v), %eax
938c2ecf20Sopenharmony_ci	adcl 4(v), %edx
948c2ecf20Sopenharmony_ci	movl %eax,  (v)
958c2ecf20Sopenharmony_ci	movl %edx, 4(v)
968c2ecf20Sopenharmony_ci	RET_IRQ_RESTORE
978c2ecf20Sopenharmony_ciENDP
988c2ecf20Sopenharmony_ci#undef v
998c2ecf20Sopenharmony_ci
1008c2ecf20Sopenharmony_ci#define v %esi
1018c2ecf20Sopenharmony_ciBEGIN_IRQ_SAVE(inc)
1028c2ecf20Sopenharmony_ci	addl $1,  (v)
1038c2ecf20Sopenharmony_ci	adcl $0, 4(v)
1048c2ecf20Sopenharmony_ci	RET_IRQ_RESTORE
1058c2ecf20Sopenharmony_ciENDP
1068c2ecf20Sopenharmony_ci#undef v
1078c2ecf20Sopenharmony_ci
1088c2ecf20Sopenharmony_ci#define v %esi
1098c2ecf20Sopenharmony_ciBEGIN_IRQ_SAVE(inc_return)
1108c2ecf20Sopenharmony_ci	movl  (v), %eax
1118c2ecf20Sopenharmony_ci	movl 4(v), %edx
1128c2ecf20Sopenharmony_ci	addl $1, %eax
1138c2ecf20Sopenharmony_ci	adcl $0, %edx
1148c2ecf20Sopenharmony_ci	movl %eax,  (v)
1158c2ecf20Sopenharmony_ci	movl %edx, 4(v)
1168c2ecf20Sopenharmony_ci	RET_IRQ_RESTORE
1178c2ecf20Sopenharmony_ciENDP
1188c2ecf20Sopenharmony_ci#undef v
1198c2ecf20Sopenharmony_ci
1208c2ecf20Sopenharmony_ci#define v %esi
1218c2ecf20Sopenharmony_ciBEGIN_IRQ_SAVE(dec)
1228c2ecf20Sopenharmony_ci	subl $1,  (v)
1238c2ecf20Sopenharmony_ci	sbbl $0, 4(v)
1248c2ecf20Sopenharmony_ci	RET_IRQ_RESTORE
1258c2ecf20Sopenharmony_ciENDP
1268c2ecf20Sopenharmony_ci#undef v
1278c2ecf20Sopenharmony_ci
1288c2ecf20Sopenharmony_ci#define v %esi
1298c2ecf20Sopenharmony_ciBEGIN_IRQ_SAVE(dec_return)
1308c2ecf20Sopenharmony_ci	movl  (v), %eax
1318c2ecf20Sopenharmony_ci	movl 4(v), %edx
1328c2ecf20Sopenharmony_ci	subl $1, %eax
1338c2ecf20Sopenharmony_ci	sbbl $0, %edx
1348c2ecf20Sopenharmony_ci	movl %eax,  (v)
1358c2ecf20Sopenharmony_ci	movl %edx, 4(v)
1368c2ecf20Sopenharmony_ci	RET_IRQ_RESTORE
1378c2ecf20Sopenharmony_ciENDP
1388c2ecf20Sopenharmony_ci#undef v
1398c2ecf20Sopenharmony_ci
1408c2ecf20Sopenharmony_ci#define v %esi
1418c2ecf20Sopenharmony_ciBEGIN_IRQ_SAVE(add_unless)
1428c2ecf20Sopenharmony_ci	addl %eax, %ecx
1438c2ecf20Sopenharmony_ci	adcl %edx, %edi
1448c2ecf20Sopenharmony_ci	addl  (v), %eax
1458c2ecf20Sopenharmony_ci	adcl 4(v), %edx
1468c2ecf20Sopenharmony_ci	cmpl %eax, %ecx
1478c2ecf20Sopenharmony_ci	je 3f
1488c2ecf20Sopenharmony_ci1:
1498c2ecf20Sopenharmony_ci	movl %eax,  (v)
1508c2ecf20Sopenharmony_ci	movl %edx, 4(v)
1518c2ecf20Sopenharmony_ci	movl $1, %eax
1528c2ecf20Sopenharmony_ci2:
1538c2ecf20Sopenharmony_ci	RET_IRQ_RESTORE
1548c2ecf20Sopenharmony_ci3:
1558c2ecf20Sopenharmony_ci	cmpl %edx, %edi
1568c2ecf20Sopenharmony_ci	jne 1b
1578c2ecf20Sopenharmony_ci	xorl %eax, %eax
1588c2ecf20Sopenharmony_ci	jmp 2b
1598c2ecf20Sopenharmony_ciENDP
1608c2ecf20Sopenharmony_ci#undef v
1618c2ecf20Sopenharmony_ci
1628c2ecf20Sopenharmony_ci#define v %esi
1638c2ecf20Sopenharmony_ciBEGIN_IRQ_SAVE(inc_not_zero)
1648c2ecf20Sopenharmony_ci	movl  (v), %eax
1658c2ecf20Sopenharmony_ci	movl 4(v), %edx
1668c2ecf20Sopenharmony_ci	testl %eax, %eax
1678c2ecf20Sopenharmony_ci	je 3f
1688c2ecf20Sopenharmony_ci1:
1698c2ecf20Sopenharmony_ci	addl $1, %eax
1708c2ecf20Sopenharmony_ci	adcl $0, %edx
1718c2ecf20Sopenharmony_ci	movl %eax,  (v)
1728c2ecf20Sopenharmony_ci	movl %edx, 4(v)
1738c2ecf20Sopenharmony_ci	movl $1, %eax
1748c2ecf20Sopenharmony_ci2:
1758c2ecf20Sopenharmony_ci	RET_IRQ_RESTORE
1768c2ecf20Sopenharmony_ci3:
1778c2ecf20Sopenharmony_ci	testl %edx, %edx
1788c2ecf20Sopenharmony_ci	jne 1b
1798c2ecf20Sopenharmony_ci	jmp 2b
1808c2ecf20Sopenharmony_ciENDP
1818c2ecf20Sopenharmony_ci#undef v
1828c2ecf20Sopenharmony_ci
1838c2ecf20Sopenharmony_ci#define v %esi
1848c2ecf20Sopenharmony_ciBEGIN_IRQ_SAVE(dec_if_positive)
1858c2ecf20Sopenharmony_ci	movl  (v), %eax
1868c2ecf20Sopenharmony_ci	movl 4(v), %edx
1878c2ecf20Sopenharmony_ci	subl $1, %eax
1888c2ecf20Sopenharmony_ci	sbbl $0, %edx
1898c2ecf20Sopenharmony_ci	js 1f
1908c2ecf20Sopenharmony_ci	movl %eax,  (v)
1918c2ecf20Sopenharmony_ci	movl %edx, 4(v)
1928c2ecf20Sopenharmony_ci1:
1938c2ecf20Sopenharmony_ci	RET_IRQ_RESTORE
1948c2ecf20Sopenharmony_ciENDP
1958c2ecf20Sopenharmony_ci#undef v
196