18c2ecf20Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0 */
28c2ecf20Sopenharmony_ci/*
38c2ecf20Sopenharmony_ci * Copyright (C) 2020-2021 Loongson Technology Corporation Limited
48c2ecf20Sopenharmony_ci */
58c2ecf20Sopenharmony_ci
68c2ecf20Sopenharmony_ci#include <asm/alternative-asm.h>
78c2ecf20Sopenharmony_ci#include <asm/asm.h>
88c2ecf20Sopenharmony_ci#include <asm/asmmacro.h>
98c2ecf20Sopenharmony_ci#include <asm/asm-extable.h>
108c2ecf20Sopenharmony_ci#include <asm/cpu.h>
118c2ecf20Sopenharmony_ci#include <asm/export.h>
128c2ecf20Sopenharmony_ci#include <asm/regdef.h>
138c2ecf20Sopenharmony_ci
148c2ecf20Sopenharmony_ciSYM_FUNC_START(__clear_user)
158c2ecf20Sopenharmony_ci	/*
168c2ecf20Sopenharmony_ci	 * Some CPUs support hardware unaligned access
178c2ecf20Sopenharmony_ci	 */
188c2ecf20Sopenharmony_ci	ALTERNATIVE	"b __clear_user_generic",	\
198c2ecf20Sopenharmony_ci			"b __clear_user_fast", CPU_FEATURE_UAL
208c2ecf20Sopenharmony_ciSYM_FUNC_END(__clear_user)
218c2ecf20Sopenharmony_ci
228c2ecf20Sopenharmony_ciEXPORT_SYMBOL(__clear_user)
238c2ecf20Sopenharmony_ci
248c2ecf20Sopenharmony_ci/*
258c2ecf20Sopenharmony_ci * unsigned long __clear_user_generic(void *addr, size_t size)
268c2ecf20Sopenharmony_ci *
278c2ecf20Sopenharmony_ci * a0: addr
288c2ecf20Sopenharmony_ci * a1: size
298c2ecf20Sopenharmony_ci */
308c2ecf20Sopenharmony_ciSYM_FUNC_START(__clear_user_generic)
318c2ecf20Sopenharmony_ci	beqz	a1, 2f
328c2ecf20Sopenharmony_ci
338c2ecf20Sopenharmony_ci1:	st.b	zero, a0, 0
348c2ecf20Sopenharmony_ci	addi.d	a0, a0, 1
358c2ecf20Sopenharmony_ci	addi.d	a1, a1, -1
368c2ecf20Sopenharmony_ci	bgt	a1, zero, 1b
378c2ecf20Sopenharmony_ci
388c2ecf20Sopenharmony_ci2:	move	a0, a1
398c2ecf20Sopenharmony_ci	jr	ra
408c2ecf20Sopenharmony_ci
418c2ecf20Sopenharmony_ci	_asm_extable 1b, 2b
428c2ecf20Sopenharmony_ciSYM_FUNC_END(__clear_user_generic)
438c2ecf20Sopenharmony_ci
448c2ecf20Sopenharmony_ci/*
458c2ecf20Sopenharmony_ci * unsigned long __clear_user_fast(void *addr, unsigned long size)
468c2ecf20Sopenharmony_ci *
478c2ecf20Sopenharmony_ci * a0: addr
488c2ecf20Sopenharmony_ci * a1: size
498c2ecf20Sopenharmony_ci */
508c2ecf20Sopenharmony_ciSYM_FUNC_START(__clear_user_fast)
518c2ecf20Sopenharmony_ci	sltui	t0, a1, 9
528c2ecf20Sopenharmony_ci	bnez	t0, .Lsmall
538c2ecf20Sopenharmony_ci
548c2ecf20Sopenharmony_ci	add.d	a2, a0, a1
558c2ecf20Sopenharmony_ci0:	st.d	zero, a0, 0
568c2ecf20Sopenharmony_ci
578c2ecf20Sopenharmony_ci	/* align up address */
588c2ecf20Sopenharmony_ci	addi.d	a0, a0, 8
598c2ecf20Sopenharmony_ci	bstrins.d	a0, zero, 2, 0
608c2ecf20Sopenharmony_ci
618c2ecf20Sopenharmony_ci	addi.d	a3, a2, -64
628c2ecf20Sopenharmony_ci	bgeu	a0, a3, .Llt64
638c2ecf20Sopenharmony_ci
648c2ecf20Sopenharmony_ci	/* set 64 bytes at a time */
658c2ecf20Sopenharmony_ci.Lloop64:
668c2ecf20Sopenharmony_ci1:	st.d	zero, a0, 0
678c2ecf20Sopenharmony_ci2:	st.d	zero, a0, 8
688c2ecf20Sopenharmony_ci3:	st.d	zero, a0, 16
698c2ecf20Sopenharmony_ci4:	st.d	zero, a0, 24
708c2ecf20Sopenharmony_ci5:	st.d	zero, a0, 32
718c2ecf20Sopenharmony_ci6:	st.d	zero, a0, 40
728c2ecf20Sopenharmony_ci7:	st.d	zero, a0, 48
738c2ecf20Sopenharmony_ci8:	st.d	zero, a0, 56
748c2ecf20Sopenharmony_ci	addi.d	a0, a0, 64
758c2ecf20Sopenharmony_ci	bltu	a0, a3, .Lloop64
768c2ecf20Sopenharmony_ci
778c2ecf20Sopenharmony_ci	/* set the remaining bytes */
788c2ecf20Sopenharmony_ci.Llt64:
798c2ecf20Sopenharmony_ci	addi.d	a3, a2, -32
808c2ecf20Sopenharmony_ci	bgeu	a0, a3, .Llt32
818c2ecf20Sopenharmony_ci9:	st.d	zero, a0, 0
828c2ecf20Sopenharmony_ci10:	st.d	zero, a0, 8
838c2ecf20Sopenharmony_ci11:	st.d	zero, a0, 16
848c2ecf20Sopenharmony_ci12:	st.d	zero, a0, 24
858c2ecf20Sopenharmony_ci	addi.d	a0, a0, 32
868c2ecf20Sopenharmony_ci
878c2ecf20Sopenharmony_ci.Llt32:
888c2ecf20Sopenharmony_ci	addi.d	a3, a2, -16
898c2ecf20Sopenharmony_ci	bgeu	a0, a3, .Llt16
908c2ecf20Sopenharmony_ci13:	st.d	zero, a0, 0
918c2ecf20Sopenharmony_ci14:	st.d	zero, a0, 8
928c2ecf20Sopenharmony_ci	addi.d	a0, a0, 16
938c2ecf20Sopenharmony_ci
948c2ecf20Sopenharmony_ci.Llt16:
958c2ecf20Sopenharmony_ci	addi.d	a3, a2, -8
968c2ecf20Sopenharmony_ci	bgeu	a0, a3, .Llt8
978c2ecf20Sopenharmony_ci15:	st.d	zero, a0, 0
988c2ecf20Sopenharmony_ci	addi.d	a0, a0, 8
998c2ecf20Sopenharmony_ci
1008c2ecf20Sopenharmony_ci.Llt8:
1018c2ecf20Sopenharmony_ci16:	st.d	zero, a2, -8
1028c2ecf20Sopenharmony_ci
1038c2ecf20Sopenharmony_ci	/* return */
1048c2ecf20Sopenharmony_ci	move	a0, zero
1058c2ecf20Sopenharmony_ci	jr	ra
1068c2ecf20Sopenharmony_ci
1078c2ecf20Sopenharmony_ci	.align	4
1088c2ecf20Sopenharmony_ci.Lsmall:
1098c2ecf20Sopenharmony_ci	pcaddi	t0, 4
1108c2ecf20Sopenharmony_ci	slli.d	a2, a1, 4
1118c2ecf20Sopenharmony_ci	add.d	t0, t0, a2
1128c2ecf20Sopenharmony_ci	jr	t0
1138c2ecf20Sopenharmony_ci
1148c2ecf20Sopenharmony_ci	.align	4
1158c2ecf20Sopenharmony_ci	move	a0, zero
1168c2ecf20Sopenharmony_ci	jr	ra
1178c2ecf20Sopenharmony_ci
1188c2ecf20Sopenharmony_ci	.align	4
1198c2ecf20Sopenharmony_ci17:	st.b	zero, a0, 0
1208c2ecf20Sopenharmony_ci	move	a0, zero
1218c2ecf20Sopenharmony_ci	jr	ra
1228c2ecf20Sopenharmony_ci
1238c2ecf20Sopenharmony_ci	.align	4
1248c2ecf20Sopenharmony_ci18:	st.h	zero, a0, 0
1258c2ecf20Sopenharmony_ci	move	a0, zero
1268c2ecf20Sopenharmony_ci	jr	ra
1278c2ecf20Sopenharmony_ci
1288c2ecf20Sopenharmony_ci	.align	4
1298c2ecf20Sopenharmony_ci19:	st.h	zero, a0, 0
1308c2ecf20Sopenharmony_ci20:	st.b	zero, a0, 2
1318c2ecf20Sopenharmony_ci	move	a0, zero
1328c2ecf20Sopenharmony_ci	jr	ra
1338c2ecf20Sopenharmony_ci
1348c2ecf20Sopenharmony_ci	.align	4
1358c2ecf20Sopenharmony_ci21:	st.w	zero, a0, 0
1368c2ecf20Sopenharmony_ci	move	a0, zero
1378c2ecf20Sopenharmony_ci	jr	ra
1388c2ecf20Sopenharmony_ci
1398c2ecf20Sopenharmony_ci	.align	4
1408c2ecf20Sopenharmony_ci22:	st.w	zero, a0, 0
1418c2ecf20Sopenharmony_ci23:	st.b	zero, a0, 4
1428c2ecf20Sopenharmony_ci	move	a0, zero
1438c2ecf20Sopenharmony_ci	jr	ra
1448c2ecf20Sopenharmony_ci
1458c2ecf20Sopenharmony_ci	.align	4
1468c2ecf20Sopenharmony_ci24:	st.w	zero, a0, 0
1478c2ecf20Sopenharmony_ci25:	st.h	zero, a0, 4
1488c2ecf20Sopenharmony_ci	move	a0, zero
1498c2ecf20Sopenharmony_ci	jr	ra
1508c2ecf20Sopenharmony_ci
1518c2ecf20Sopenharmony_ci	.align	4
1528c2ecf20Sopenharmony_ci26:	st.w	zero, a0, 0
1538c2ecf20Sopenharmony_ci27:	st.w	zero, a0, 3
1548c2ecf20Sopenharmony_ci	move	a0, zero
1558c2ecf20Sopenharmony_ci	jr	ra
1568c2ecf20Sopenharmony_ci
1578c2ecf20Sopenharmony_ci	.align	4
1588c2ecf20Sopenharmony_ci28:	st.d	zero, a0, 0
1598c2ecf20Sopenharmony_ci	move	a0, zero
1608c2ecf20Sopenharmony_ci	jr	ra
1618c2ecf20Sopenharmony_ci
1628c2ecf20Sopenharmony_ci	/* fixup and ex_table */
1638c2ecf20Sopenharmony_ci.Llarge_fixup:
1648c2ecf20Sopenharmony_ci	sub.d	a1, a2, a0
1658c2ecf20Sopenharmony_ci
1668c2ecf20Sopenharmony_ci.Lsmall_fixup:
1678c2ecf20Sopenharmony_ci29:	st.b	zero, a0, 0
1688c2ecf20Sopenharmony_ci	addi.d	a0, a0, 1
1698c2ecf20Sopenharmony_ci	addi.d	a1, a1, -1
1708c2ecf20Sopenharmony_ci	bgt	a1, zero, 29b
1718c2ecf20Sopenharmony_ci
1728c2ecf20Sopenharmony_ci.Lexit:
1738c2ecf20Sopenharmony_ci	move	a0, a1
1748c2ecf20Sopenharmony_ci	jr	ra
1758c2ecf20Sopenharmony_ci
1768c2ecf20Sopenharmony_ci	_asm_extable 0b, .Lsmall_fixup
1778c2ecf20Sopenharmony_ci	_asm_extable 1b, .Llarge_fixup
1788c2ecf20Sopenharmony_ci	_asm_extable 2b, .Llarge_fixup
1798c2ecf20Sopenharmony_ci	_asm_extable 3b, .Llarge_fixup
1808c2ecf20Sopenharmony_ci	_asm_extable 4b, .Llarge_fixup
1818c2ecf20Sopenharmony_ci	_asm_extable 5b, .Llarge_fixup
1828c2ecf20Sopenharmony_ci	_asm_extable 6b, .Llarge_fixup
1838c2ecf20Sopenharmony_ci	_asm_extable 7b, .Llarge_fixup
1848c2ecf20Sopenharmony_ci	_asm_extable 8b, .Llarge_fixup
1858c2ecf20Sopenharmony_ci	_asm_extable 9b, .Llarge_fixup
1868c2ecf20Sopenharmony_ci	_asm_extable 10b, .Llarge_fixup
1878c2ecf20Sopenharmony_ci	_asm_extable 11b, .Llarge_fixup
1888c2ecf20Sopenharmony_ci	_asm_extable 12b, .Llarge_fixup
1898c2ecf20Sopenharmony_ci	_asm_extable 13b, .Llarge_fixup
1908c2ecf20Sopenharmony_ci	_asm_extable 14b, .Llarge_fixup
1918c2ecf20Sopenharmony_ci	_asm_extable 15b, .Llarge_fixup
1928c2ecf20Sopenharmony_ci	_asm_extable 16b, .Llarge_fixup
1938c2ecf20Sopenharmony_ci	_asm_extable 17b, .Lexit
1948c2ecf20Sopenharmony_ci	_asm_extable 18b, .Lsmall_fixup
1958c2ecf20Sopenharmony_ci	_asm_extable 19b, .Lsmall_fixup
1968c2ecf20Sopenharmony_ci	_asm_extable 20b, .Lsmall_fixup
1978c2ecf20Sopenharmony_ci	_asm_extable 21b, .Lsmall_fixup
1988c2ecf20Sopenharmony_ci	_asm_extable 22b, .Lsmall_fixup
1998c2ecf20Sopenharmony_ci	_asm_extable 23b, .Lsmall_fixup
2008c2ecf20Sopenharmony_ci	_asm_extable 24b, .Lsmall_fixup
2018c2ecf20Sopenharmony_ci	_asm_extable 25b, .Lsmall_fixup
2028c2ecf20Sopenharmony_ci	_asm_extable 26b, .Lsmall_fixup
2038c2ecf20Sopenharmony_ci	_asm_extable 27b, .Lsmall_fixup
2048c2ecf20Sopenharmony_ci	_asm_extable 28b, .Lsmall_fixup
2058c2ecf20Sopenharmony_ci	_asm_extable 29b, .Lexit
2068c2ecf20Sopenharmony_ciSYM_FUNC_END(__clear_user_fast)
207