162306a36Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0 */
262306a36Sopenharmony_ci/*
362306a36Sopenharmony_ci * Copyright (C) 2020-2022 Loongson Technology Corporation Limited
462306a36Sopenharmony_ci */
562306a36Sopenharmony_ci
662306a36Sopenharmony_ci#include <linux/export.h>
762306a36Sopenharmony_ci#include <asm/alternative-asm.h>
862306a36Sopenharmony_ci#include <asm/asm.h>
962306a36Sopenharmony_ci#include <asm/asmmacro.h>
1062306a36Sopenharmony_ci#include <asm/asm-extable.h>
1162306a36Sopenharmony_ci#include <asm/cpu.h>
1262306a36Sopenharmony_ci#include <asm/regdef.h>
1362306a36Sopenharmony_ci
1462306a36Sopenharmony_ciSYM_FUNC_START(__clear_user)
1562306a36Sopenharmony_ci	/*
1662306a36Sopenharmony_ci	 * Some CPUs support hardware unaligned access
1762306a36Sopenharmony_ci	 */
1862306a36Sopenharmony_ci	ALTERNATIVE	"b __clear_user_generic",	\
1962306a36Sopenharmony_ci			"b __clear_user_fast", CPU_FEATURE_UAL
2062306a36Sopenharmony_ciSYM_FUNC_END(__clear_user)
2162306a36Sopenharmony_ci
2262306a36Sopenharmony_ciEXPORT_SYMBOL(__clear_user)
2362306a36Sopenharmony_ci
2462306a36Sopenharmony_ci/*
2562306a36Sopenharmony_ci * unsigned long __clear_user_generic(void *addr, size_t size)
2662306a36Sopenharmony_ci *
2762306a36Sopenharmony_ci * a0: addr
2862306a36Sopenharmony_ci * a1: size
2962306a36Sopenharmony_ci */
3062306a36Sopenharmony_ciSYM_FUNC_START(__clear_user_generic)
3162306a36Sopenharmony_ci	beqz	a1, 2f
3262306a36Sopenharmony_ci
3362306a36Sopenharmony_ci1:	st.b	zero, a0, 0
3462306a36Sopenharmony_ci	addi.d	a0, a0, 1
3562306a36Sopenharmony_ci	addi.d	a1, a1, -1
3662306a36Sopenharmony_ci	bgtz	a1, 1b
3762306a36Sopenharmony_ci
3862306a36Sopenharmony_ci2:	move	a0, a1
3962306a36Sopenharmony_ci	jr	ra
4062306a36Sopenharmony_ci
4162306a36Sopenharmony_ci	_asm_extable 1b, 2b
4262306a36Sopenharmony_ciSYM_FUNC_END(__clear_user_generic)
4362306a36Sopenharmony_ci
4462306a36Sopenharmony_ci/*
4562306a36Sopenharmony_ci * unsigned long __clear_user_fast(void *addr, unsigned long size)
4662306a36Sopenharmony_ci *
4762306a36Sopenharmony_ci * a0: addr
4862306a36Sopenharmony_ci * a1: size
4962306a36Sopenharmony_ci */
5062306a36Sopenharmony_ciSYM_FUNC_START(__clear_user_fast)
5162306a36Sopenharmony_ci	sltui	t0, a1, 9
5262306a36Sopenharmony_ci	bnez	t0, .Lsmall
5362306a36Sopenharmony_ci
5462306a36Sopenharmony_ci	add.d	a2, a0, a1
5562306a36Sopenharmony_ci0:	st.d	zero, a0, 0
5662306a36Sopenharmony_ci
5762306a36Sopenharmony_ci	/* align up address */
5862306a36Sopenharmony_ci	addi.d	a0, a0, 8
5962306a36Sopenharmony_ci	bstrins.d	a0, zero, 2, 0
6062306a36Sopenharmony_ci
6162306a36Sopenharmony_ci	addi.d	a3, a2, -64
6262306a36Sopenharmony_ci	bgeu	a0, a3, .Llt64
6362306a36Sopenharmony_ci
6462306a36Sopenharmony_ci	/* set 64 bytes at a time */
6562306a36Sopenharmony_ci.Lloop64:
6662306a36Sopenharmony_ci1:	st.d	zero, a0, 0
6762306a36Sopenharmony_ci2:	st.d	zero, a0, 8
6862306a36Sopenharmony_ci3:	st.d	zero, a0, 16
6962306a36Sopenharmony_ci4:	st.d	zero, a0, 24
7062306a36Sopenharmony_ci5:	st.d	zero, a0, 32
7162306a36Sopenharmony_ci6:	st.d	zero, a0, 40
7262306a36Sopenharmony_ci7:	st.d	zero, a0, 48
7362306a36Sopenharmony_ci8:	st.d	zero, a0, 56
7462306a36Sopenharmony_ci	addi.d	a0, a0, 64
7562306a36Sopenharmony_ci	bltu	a0, a3, .Lloop64
7662306a36Sopenharmony_ci
7762306a36Sopenharmony_ci	/* set the remaining bytes */
7862306a36Sopenharmony_ci.Llt64:
7962306a36Sopenharmony_ci	addi.d	a3, a2, -32
8062306a36Sopenharmony_ci	bgeu	a0, a3, .Llt32
8162306a36Sopenharmony_ci9:	st.d	zero, a0, 0
8262306a36Sopenharmony_ci10:	st.d	zero, a0, 8
8362306a36Sopenharmony_ci11:	st.d	zero, a0, 16
8462306a36Sopenharmony_ci12:	st.d	zero, a0, 24
8562306a36Sopenharmony_ci	addi.d	a0, a0, 32
8662306a36Sopenharmony_ci
8762306a36Sopenharmony_ci.Llt32:
8862306a36Sopenharmony_ci	addi.d	a3, a2, -16
8962306a36Sopenharmony_ci	bgeu	a0, a3, .Llt16
9062306a36Sopenharmony_ci13:	st.d	zero, a0, 0
9162306a36Sopenharmony_ci14:	st.d	zero, a0, 8
9262306a36Sopenharmony_ci	addi.d	a0, a0, 16
9362306a36Sopenharmony_ci
9462306a36Sopenharmony_ci.Llt16:
9562306a36Sopenharmony_ci	addi.d	a3, a2, -8
9662306a36Sopenharmony_ci	bgeu	a0, a3, .Llt8
9762306a36Sopenharmony_ci15:	st.d	zero, a0, 0
9862306a36Sopenharmony_ci	addi.d	a0, a0, 8
9962306a36Sopenharmony_ci
10062306a36Sopenharmony_ci.Llt8:
10162306a36Sopenharmony_ci16:	st.d	zero, a2, -8
10262306a36Sopenharmony_ci
10362306a36Sopenharmony_ci	/* return */
10462306a36Sopenharmony_ci	move	a0, zero
10562306a36Sopenharmony_ci	jr	ra
10662306a36Sopenharmony_ci
10762306a36Sopenharmony_ci	.align	4
10862306a36Sopenharmony_ci.Lsmall:
10962306a36Sopenharmony_ci	pcaddi	t0, 4
11062306a36Sopenharmony_ci	slli.d	a2, a1, 4
11162306a36Sopenharmony_ci	add.d	t0, t0, a2
11262306a36Sopenharmony_ci	jr	t0
11362306a36Sopenharmony_ci
11462306a36Sopenharmony_ci	.align	4
11562306a36Sopenharmony_ci	move	a0, zero
11662306a36Sopenharmony_ci	jr	ra
11762306a36Sopenharmony_ci
11862306a36Sopenharmony_ci	.align	4
11962306a36Sopenharmony_ci17:	st.b	zero, a0, 0
12062306a36Sopenharmony_ci	move	a0, zero
12162306a36Sopenharmony_ci	jr	ra
12262306a36Sopenharmony_ci
12362306a36Sopenharmony_ci	.align	4
12462306a36Sopenharmony_ci18:	st.h	zero, a0, 0
12562306a36Sopenharmony_ci	move	a0, zero
12662306a36Sopenharmony_ci	jr	ra
12762306a36Sopenharmony_ci
12862306a36Sopenharmony_ci	.align	4
12962306a36Sopenharmony_ci19:	st.h	zero, a0, 0
13062306a36Sopenharmony_ci20:	st.b	zero, a0, 2
13162306a36Sopenharmony_ci	move	a0, zero
13262306a36Sopenharmony_ci	jr	ra
13362306a36Sopenharmony_ci
13462306a36Sopenharmony_ci	.align	4
13562306a36Sopenharmony_ci21:	st.w	zero, a0, 0
13662306a36Sopenharmony_ci	move	a0, zero
13762306a36Sopenharmony_ci	jr	ra
13862306a36Sopenharmony_ci
13962306a36Sopenharmony_ci	.align	4
14062306a36Sopenharmony_ci22:	st.w	zero, a0, 0
14162306a36Sopenharmony_ci23:	st.b	zero, a0, 4
14262306a36Sopenharmony_ci	move	a0, zero
14362306a36Sopenharmony_ci	jr	ra
14462306a36Sopenharmony_ci
14562306a36Sopenharmony_ci	.align	4
14662306a36Sopenharmony_ci24:	st.w	zero, a0, 0
14762306a36Sopenharmony_ci25:	st.h	zero, a0, 4
14862306a36Sopenharmony_ci	move	a0, zero
14962306a36Sopenharmony_ci	jr	ra
15062306a36Sopenharmony_ci
15162306a36Sopenharmony_ci	.align	4
15262306a36Sopenharmony_ci26:	st.w	zero, a0, 0
15362306a36Sopenharmony_ci27:	st.w	zero, a0, 3
15462306a36Sopenharmony_ci	move	a0, zero
15562306a36Sopenharmony_ci	jr	ra
15662306a36Sopenharmony_ci
15762306a36Sopenharmony_ci	.align	4
15862306a36Sopenharmony_ci28:	st.d	zero, a0, 0
15962306a36Sopenharmony_ci	move	a0, zero
16062306a36Sopenharmony_ci	jr	ra
16162306a36Sopenharmony_ci
16262306a36Sopenharmony_ci	/* fixup and ex_table */
16362306a36Sopenharmony_ci.Llarge_fixup:
16462306a36Sopenharmony_ci	sub.d	a1, a2, a0
16562306a36Sopenharmony_ci
16662306a36Sopenharmony_ci.Lsmall_fixup:
16762306a36Sopenharmony_ci29:	st.b	zero, a0, 0
16862306a36Sopenharmony_ci	addi.d	a0, a0, 1
16962306a36Sopenharmony_ci	addi.d	a1, a1, -1
17062306a36Sopenharmony_ci	bgt	a1, zero, 29b
17162306a36Sopenharmony_ci
17262306a36Sopenharmony_ci.Lexit:
17362306a36Sopenharmony_ci	move	a0, a1
17462306a36Sopenharmony_ci	jr	ra
17562306a36Sopenharmony_ci
17662306a36Sopenharmony_ci	_asm_extable 0b, .Lsmall_fixup
17762306a36Sopenharmony_ci	_asm_extable 1b, .Llarge_fixup
17862306a36Sopenharmony_ci	_asm_extable 2b, .Llarge_fixup
17962306a36Sopenharmony_ci	_asm_extable 3b, .Llarge_fixup
18062306a36Sopenharmony_ci	_asm_extable 4b, .Llarge_fixup
18162306a36Sopenharmony_ci	_asm_extable 5b, .Llarge_fixup
18262306a36Sopenharmony_ci	_asm_extable 6b, .Llarge_fixup
18362306a36Sopenharmony_ci	_asm_extable 7b, .Llarge_fixup
18462306a36Sopenharmony_ci	_asm_extable 8b, .Llarge_fixup
18562306a36Sopenharmony_ci	_asm_extable 9b, .Llarge_fixup
18662306a36Sopenharmony_ci	_asm_extable 10b, .Llarge_fixup
18762306a36Sopenharmony_ci	_asm_extable 11b, .Llarge_fixup
18862306a36Sopenharmony_ci	_asm_extable 12b, .Llarge_fixup
18962306a36Sopenharmony_ci	_asm_extable 13b, .Llarge_fixup
19062306a36Sopenharmony_ci	_asm_extable 14b, .Llarge_fixup
19162306a36Sopenharmony_ci	_asm_extable 15b, .Llarge_fixup
19262306a36Sopenharmony_ci	_asm_extable 16b, .Llarge_fixup
19362306a36Sopenharmony_ci	_asm_extable 17b, .Lexit
19462306a36Sopenharmony_ci	_asm_extable 18b, .Lsmall_fixup
19562306a36Sopenharmony_ci	_asm_extable 19b, .Lsmall_fixup
19662306a36Sopenharmony_ci	_asm_extable 20b, .Lsmall_fixup
19762306a36Sopenharmony_ci	_asm_extable 21b, .Lsmall_fixup
19862306a36Sopenharmony_ci	_asm_extable 22b, .Lsmall_fixup
19962306a36Sopenharmony_ci	_asm_extable 23b, .Lsmall_fixup
20062306a36Sopenharmony_ci	_asm_extable 24b, .Lsmall_fixup
20162306a36Sopenharmony_ci	_asm_extable 25b, .Lsmall_fixup
20262306a36Sopenharmony_ci	_asm_extable 26b, .Lsmall_fixup
20362306a36Sopenharmony_ci	_asm_extable 27b, .Lsmall_fixup
20462306a36Sopenharmony_ci	_asm_extable 28b, .Lsmall_fixup
20562306a36Sopenharmony_ci	_asm_extable 29b, .Lexit
20662306a36Sopenharmony_ciSYM_FUNC_END(__clear_user_fast)
207