xref: /openbmc/linux/arch/loongarch/lib/copy_user.S (revision c900529f3d9161bfde5cca0754f83b4d3c3e0220)
1559671e0SHuacai Chen/* SPDX-License-Identifier: GPL-2.0 */
2559671e0SHuacai Chen/*
3559671e0SHuacai Chen * Copyright (C) 2020-2022 Loongson Technology Corporation Limited
4559671e0SHuacai Chen */
5559671e0SHuacai Chen
655b46ff9SMasahiro Yamada#include <linux/export.h>
7a275a82dSHuacai Chen#include <asm/alternative-asm.h>
8559671e0SHuacai Chen#include <asm/asm.h>
9559671e0SHuacai Chen#include <asm/asmmacro.h>
10508f28c6SYouling Tang#include <asm/asm-extable.h>
11a275a82dSHuacai Chen#include <asm/cpu.h>
12559671e0SHuacai Chen#include <asm/regdef.h>
13559671e0SHuacai Chen
14a275a82dSHuacai ChenSYM_FUNC_START(__copy_user)
15559671e0SHuacai Chen	/*
16a275a82dSHuacai Chen	 * Some CPUs support hardware unaligned access
17a275a82dSHuacai Chen	 */
18a275a82dSHuacai Chen	ALTERNATIVE	"b __copy_user_generic",	\
19a275a82dSHuacai Chen			"b __copy_user_fast", CPU_FEATURE_UAL
20a275a82dSHuacai ChenSYM_FUNC_END(__copy_user)
21a275a82dSHuacai Chen
22a275a82dSHuacai ChenEXPORT_SYMBOL(__copy_user)
23a275a82dSHuacai Chen
24a275a82dSHuacai Chen/*
25a275a82dSHuacai Chen * unsigned long __copy_user_generic(void *to, const void *from, size_t n)
26559671e0SHuacai Chen *
27559671e0SHuacai Chen * a0: to
28559671e0SHuacai Chen * a1: from
29559671e0SHuacai Chen * a2: n
30559671e0SHuacai Chen */
31a275a82dSHuacai ChenSYM_FUNC_START(__copy_user_generic)
32559671e0SHuacai Chen	beqz	a2, 3f
33559671e0SHuacai Chen
34559671e0SHuacai Chen1:	ld.b	t0, a1, 0
35559671e0SHuacai Chen2:	st.b	t0, a0, 0
36559671e0SHuacai Chen	addi.d	a0, a0, 1
37559671e0SHuacai Chen	addi.d	a1, a1, 1
38559671e0SHuacai Chen	addi.d	a2, a2, -1
391fdb9a92SWANG Xuerui	bgtz	a2, 1b
40559671e0SHuacai Chen
41559671e0SHuacai Chen3:	move	a0, a2
42559671e0SHuacai Chen	jr	ra
43559671e0SHuacai Chen
44*937f6593SWeihao Li	_asm_extable 1b, 3b
45*937f6593SWeihao Li	_asm_extable 2b, 3b
46a275a82dSHuacai ChenSYM_FUNC_END(__copy_user_generic)
47559671e0SHuacai Chen
48a275a82dSHuacai Chen/*
49a275a82dSHuacai Chen * unsigned long __copy_user_fast(void *to, const void *from, unsigned long n)
50a275a82dSHuacai Chen *
51a275a82dSHuacai Chen * a0: to
52a275a82dSHuacai Chen * a1: from
53a275a82dSHuacai Chen * a2: n
54a275a82dSHuacai Chen */
55a275a82dSHuacai ChenSYM_FUNC_START(__copy_user_fast)
568941e93cSWANG Rui	sltui	t0, a2, 9
578941e93cSWANG Rui	bnez	t0, .Lsmall
58a275a82dSHuacai Chen
598941e93cSWANG Rui0:	ld.d	t0, a1, 0
608941e93cSWANG Rui1:	st.d	t0, a0, 0
61*937f6593SWeihao Li	add.d	a3, a1, a2
62*937f6593SWeihao Li	add.d	a2, a0, a2
638941e93cSWANG Rui
648941e93cSWANG Rui	/* align up destination address */
658941e93cSWANG Rui	andi	t1, a0, 7
668941e93cSWANG Rui	sub.d	t0, zero, t1
678941e93cSWANG Rui	addi.d	t0, t0, 8
688941e93cSWANG Rui	add.d	a1, a1, t0
698941e93cSWANG Rui	add.d	a0, a0, t0
708941e93cSWANG Rui
718941e93cSWANG Rui	addi.d	a4, a3, -64
728941e93cSWANG Rui	bgeu	a1, a4, .Llt64
73a275a82dSHuacai Chen
74a275a82dSHuacai Chen	/* copy 64 bytes at a time */
758941e93cSWANG Rui.Lloop64:
768941e93cSWANG Rui2:	ld.d	t0, a1, 0
778941e93cSWANG Rui3:	ld.d	t1, a1, 8
788941e93cSWANG Rui4:	ld.d	t2, a1, 16
798941e93cSWANG Rui5:	ld.d	t3, a1, 24
808941e93cSWANG Rui6:	ld.d	t4, a1, 32
818941e93cSWANG Rui7:	ld.d	t5, a1, 40
828941e93cSWANG Rui8:	ld.d	t6, a1, 48
838941e93cSWANG Rui9:	ld.d	t7, a1, 56
848941e93cSWANG Rui10:	st.d	t0, a0, 0
858941e93cSWANG Rui11:	st.d	t1, a0, 8
868941e93cSWANG Rui12:	st.d	t2, a0, 16
878941e93cSWANG Rui13:	st.d	t3, a0, 24
888941e93cSWANG Rui14:	st.d	t4, a0, 32
898941e93cSWANG Rui15:	st.d	t5, a0, 40
908941e93cSWANG Rui16:	st.d	t6, a0, 48
918941e93cSWANG Rui17:	st.d	t7, a0, 56
92*937f6593SWeihao Li	addi.d	a1, a1, 64
938941e93cSWANG Rui	addi.d	a0, a0, 64
948941e93cSWANG Rui	bltu	a1, a4, .Lloop64
95a275a82dSHuacai Chen
96a275a82dSHuacai Chen	/* copy the remaining bytes */
978941e93cSWANG Rui.Llt64:
988941e93cSWANG Rui	addi.d	a4, a3, -32
998941e93cSWANG Rui	bgeu	a1, a4, .Llt32
1008941e93cSWANG Rui18:	ld.d	t0, a1, 0
1018941e93cSWANG Rui19:	ld.d	t1, a1, 8
1028941e93cSWANG Rui20:	ld.d	t2, a1, 16
1038941e93cSWANG Rui21:	ld.d	t3, a1, 24
1048941e93cSWANG Rui22:	st.d	t0, a0, 0
1058941e93cSWANG Rui23:	st.d	t1, a0, 8
1068941e93cSWANG Rui24:	st.d	t2, a0, 16
1078941e93cSWANG Rui25:	st.d	t3, a0, 24
108*937f6593SWeihao Li	addi.d	a1, a1, 32
1098941e93cSWANG Rui	addi.d	a0, a0, 32
1108941e93cSWANG Rui
1118941e93cSWANG Rui.Llt32:
1128941e93cSWANG Rui	addi.d	a4, a3, -16
1138941e93cSWANG Rui	bgeu	a1, a4, .Llt16
1148941e93cSWANG Rui26:	ld.d	t0, a1, 0
1158941e93cSWANG Rui27:	ld.d	t1, a1, 8
1168941e93cSWANG Rui28:	st.d	t0, a0, 0
1178941e93cSWANG Rui29:	st.d	t1, a0, 8
118*937f6593SWeihao Li	addi.d	a1, a1, 16
1198941e93cSWANG Rui	addi.d	a0, a0, 16
1208941e93cSWANG Rui
1218941e93cSWANG Rui.Llt16:
1228941e93cSWANG Rui	addi.d	a4, a3, -8
1238941e93cSWANG Rui	bgeu	a1, a4, .Llt8
1248941e93cSWANG Rui30:	ld.d	t0, a1, 0
1258941e93cSWANG Rui31:	st.d	t0, a0, 0
126*937f6593SWeihao Li	addi.d	a1, a1, 8
127e66d511fSWANG Rui	addi.d	a0, a0, 8
1288941e93cSWANG Rui
1298941e93cSWANG Rui.Llt8:
1308941e93cSWANG Rui32:	ld.d	t0, a3, -8
1318941e93cSWANG Rui33:	st.d	t0, a2, -8
132a275a82dSHuacai Chen
133a275a82dSHuacai Chen	/* return */
1348941e93cSWANG Rui	move	a0, zero
1358941e93cSWANG Rui	jr	ra
1368941e93cSWANG Rui
1378941e93cSWANG Rui	.align	5
1388941e93cSWANG Rui.Lsmall:
1398941e93cSWANG Rui	pcaddi	t0, 8
1408941e93cSWANG Rui	slli.d	a3, a2, 5
1418941e93cSWANG Rui	add.d	t0, t0, a3
1428941e93cSWANG Rui	jr	t0
1438941e93cSWANG Rui
1448941e93cSWANG Rui	.align	5
1458941e93cSWANG Rui	move	a0, zero
1468941e93cSWANG Rui	jr	ra
1478941e93cSWANG Rui
1488941e93cSWANG Rui	.align	5
1498941e93cSWANG Rui34:	ld.b	t0, a1, 0
1508941e93cSWANG Rui35:	st.b	t0, a0, 0
1518941e93cSWANG Rui	move	a0, zero
1528941e93cSWANG Rui	jr	ra
1538941e93cSWANG Rui
1548941e93cSWANG Rui	.align	5
1558941e93cSWANG Rui36:	ld.h	t0, a1, 0
1568941e93cSWANG Rui37:	st.h	t0, a0, 0
1578941e93cSWANG Rui	move	a0, zero
1588941e93cSWANG Rui	jr	ra
1598941e93cSWANG Rui
1608941e93cSWANG Rui	.align	5
1618941e93cSWANG Rui38:	ld.h	t0, a1, 0
1628941e93cSWANG Rui39:	ld.b	t1, a1, 2
1638941e93cSWANG Rui40:	st.h	t0, a0, 0
1648941e93cSWANG Rui41:	st.b	t1, a0, 2
1658941e93cSWANG Rui	move	a0, zero
1668941e93cSWANG Rui	jr	ra
1678941e93cSWANG Rui
1688941e93cSWANG Rui	.align	5
1698941e93cSWANG Rui42:	ld.w	t0, a1, 0
1708941e93cSWANG Rui43:	st.w	t0, a0, 0
1718941e93cSWANG Rui	move	a0, zero
1728941e93cSWANG Rui	jr	ra
1738941e93cSWANG Rui
1748941e93cSWANG Rui	.align	5
1758941e93cSWANG Rui44:	ld.w	t0, a1, 0
1768941e93cSWANG Rui45:	ld.b	t1, a1, 4
1778941e93cSWANG Rui46:	st.w	t0, a0, 0
1788941e93cSWANG Rui47:	st.b	t1, a0, 4
1798941e93cSWANG Rui	move	a0, zero
1808941e93cSWANG Rui	jr	ra
1818941e93cSWANG Rui
1828941e93cSWANG Rui	.align	5
1838941e93cSWANG Rui48:	ld.w	t0, a1, 0
1848941e93cSWANG Rui49:	ld.h	t1, a1, 4
1858941e93cSWANG Rui50:	st.w	t0, a0, 0
1868941e93cSWANG Rui51:	st.h	t1, a0, 4
1878941e93cSWANG Rui	move	a0, zero
1888941e93cSWANG Rui	jr	ra
1898941e93cSWANG Rui
1908941e93cSWANG Rui	.align	5
1918941e93cSWANG Rui52:	ld.w	t0, a1, 0
1928941e93cSWANG Rui53:	ld.w	t1, a1, 3
1938941e93cSWANG Rui54:	st.w	t0, a0, 0
1948941e93cSWANG Rui55:	st.w	t1, a0, 3
1958941e93cSWANG Rui	move	a0, zero
1968941e93cSWANG Rui	jr	ra
1978941e93cSWANG Rui
1988941e93cSWANG Rui	.align	5
1998941e93cSWANG Rui56:	ld.d	t0, a1, 0
2008941e93cSWANG Rui57:	st.d	t0, a0, 0
2018941e93cSWANG Rui	move	a0, zero
202a275a82dSHuacai Chen	jr	ra
203a275a82dSHuacai Chen
204a275a82dSHuacai Chen	/* fixup and ex_table */
205*937f6593SWeihao Li.Llarge_fixup:
206*937f6593SWeihao Li	sub.d	a2, a2, a0
207*937f6593SWeihao Li
208*937f6593SWeihao Li.Lsmall_fixup:
209*937f6593SWeihao Li58:	ld.b	t0, a1, 0
210*937f6593SWeihao Li59:	st.b	t0, a0, 0
211*937f6593SWeihao Li	addi.d	a0, a0, 1
212*937f6593SWeihao Li	addi.d	a1, a1, 1
213*937f6593SWeihao Li	addi.d	a2, a2, -1
214*937f6593SWeihao Li	bgt	a2, zero, 58b
215*937f6593SWeihao Li
216*937f6593SWeihao Li.Lexit:
217*937f6593SWeihao Li	move	a0, a2
218*937f6593SWeihao Li	jr	ra
219*937f6593SWeihao Li
220*937f6593SWeihao Li	_asm_extable 0b, .Lsmall_fixup
221*937f6593SWeihao Li	_asm_extable 1b, .Lsmall_fixup
222*937f6593SWeihao Li	_asm_extable 2b, .Llarge_fixup
223*937f6593SWeihao Li	_asm_extable 3b, .Llarge_fixup
224*937f6593SWeihao Li	_asm_extable 4b, .Llarge_fixup
225*937f6593SWeihao Li	_asm_extable 5b, .Llarge_fixup
226*937f6593SWeihao Li	_asm_extable 6b, .Llarge_fixup
227*937f6593SWeihao Li	_asm_extable 7b, .Llarge_fixup
228*937f6593SWeihao Li	_asm_extable 8b, .Llarge_fixup
229*937f6593SWeihao Li	_asm_extable 9b, .Llarge_fixup
230*937f6593SWeihao Li	_asm_extable 10b, .Llarge_fixup
231*937f6593SWeihao Li	_asm_extable 11b, .Llarge_fixup
232*937f6593SWeihao Li	_asm_extable 12b, .Llarge_fixup
233*937f6593SWeihao Li	_asm_extable 13b, .Llarge_fixup
234*937f6593SWeihao Li	_asm_extable 14b, .Llarge_fixup
235*937f6593SWeihao Li	_asm_extable 15b, .Llarge_fixup
236*937f6593SWeihao Li	_asm_extable 16b, .Llarge_fixup
237*937f6593SWeihao Li	_asm_extable 17b, .Llarge_fixup
238*937f6593SWeihao Li	_asm_extable 18b, .Llarge_fixup
239*937f6593SWeihao Li	_asm_extable 19b, .Llarge_fixup
240*937f6593SWeihao Li	_asm_extable 20b, .Llarge_fixup
241*937f6593SWeihao Li	_asm_extable 21b, .Llarge_fixup
242*937f6593SWeihao Li	_asm_extable 22b, .Llarge_fixup
243*937f6593SWeihao Li	_asm_extable 23b, .Llarge_fixup
244*937f6593SWeihao Li	_asm_extable 24b, .Llarge_fixup
245*937f6593SWeihao Li	_asm_extable 25b, .Llarge_fixup
246*937f6593SWeihao Li	_asm_extable 26b, .Llarge_fixup
247*937f6593SWeihao Li	_asm_extable 27b, .Llarge_fixup
248*937f6593SWeihao Li	_asm_extable 28b, .Llarge_fixup
249*937f6593SWeihao Li	_asm_extable 29b, .Llarge_fixup
250*937f6593SWeihao Li	_asm_extable 30b, .Llarge_fixup
251*937f6593SWeihao Li	_asm_extable 31b, .Llarge_fixup
252*937f6593SWeihao Li	_asm_extable 32b, .Llarge_fixup
253*937f6593SWeihao Li	_asm_extable 33b, .Llarge_fixup
254*937f6593SWeihao Li	_asm_extable 34b, .Lexit
255*937f6593SWeihao Li	_asm_extable 35b, .Lexit
256*937f6593SWeihao Li	_asm_extable 36b, .Lsmall_fixup
257*937f6593SWeihao Li	_asm_extable 37b, .Lsmall_fixup
258*937f6593SWeihao Li	_asm_extable 38b, .Lsmall_fixup
259*937f6593SWeihao Li	_asm_extable 39b, .Lsmall_fixup
260*937f6593SWeihao Li	_asm_extable 40b, .Lsmall_fixup
261*937f6593SWeihao Li	_asm_extable 41b, .Lsmall_fixup
262*937f6593SWeihao Li	_asm_extable 42b, .Lsmall_fixup
263*937f6593SWeihao Li	_asm_extable 43b, .Lsmall_fixup
264*937f6593SWeihao Li	_asm_extable 44b, .Lsmall_fixup
265*937f6593SWeihao Li	_asm_extable 45b, .Lsmall_fixup
266*937f6593SWeihao Li	_asm_extable 46b, .Lsmall_fixup
267*937f6593SWeihao Li	_asm_extable 47b, .Lsmall_fixup
268*937f6593SWeihao Li	_asm_extable 48b, .Lsmall_fixup
269*937f6593SWeihao Li	_asm_extable 49b, .Lsmall_fixup
270*937f6593SWeihao Li	_asm_extable 50b, .Lsmall_fixup
271*937f6593SWeihao Li	_asm_extable 51b, .Lsmall_fixup
272*937f6593SWeihao Li	_asm_extable 52b, .Lsmall_fixup
273*937f6593SWeihao Li	_asm_extable 53b, .Lsmall_fixup
274*937f6593SWeihao Li	_asm_extable 54b, .Lsmall_fixup
275*937f6593SWeihao Li	_asm_extable 55b, .Lsmall_fixup
276*937f6593SWeihao Li	_asm_extable 56b, .Lsmall_fixup
277*937f6593SWeihao Li	_asm_extable 57b, .Lsmall_fixup
278*937f6593SWeihao Li	_asm_extable 58b, .Lexit
279*937f6593SWeihao Li	_asm_extable 59b, .Lexit
280a275a82dSHuacai ChenSYM_FUNC_END(__copy_user_fast)
281