xref: /linux/arch/loongarch/lib/clear_user.S (revision ef9226cd56b718c79184a3466d32984a51cb449c)
1/* SPDX-License-Identifier: GPL-2.0 */
2/*
3 * Copyright (C) 2020-2022 Loongson Technology Corporation Limited
4 */
5
6#include <linux/export.h>
7#include <asm/alternative-asm.h>
8#include <asm/asm.h>
9#include <asm/asmmacro.h>
10#include <asm/asm-extable.h>
11#include <asm/cpu.h>
12#include <asm/regdef.h>
13#include <asm/unwind_hints.h>
14
15SYM_FUNC_START(__clear_user)
16	/*
17	 * Some CPUs support hardware unaligned access
18	 */
19	ALTERNATIVE	"b __clear_user_generic",	\
20			"b __clear_user_fast", CPU_FEATURE_UAL
21SYM_FUNC_END(__clear_user)
22
23EXPORT_SYMBOL(__clear_user)
24
25/*
26 * unsigned long __clear_user_generic(void *addr, size_t size)
27 *
28 * a0: addr
29 * a1: size
30 */
31SYM_FUNC_START(__clear_user_generic)
32	beqz	a1, 2f
33
341:	st.b	zero, a0, 0
35	addi.d	a0, a0, 1
36	addi.d	a1, a1, -1
37	bgtz	a1, 1b
38
392:	move	a0, a1
40	jr	ra
41
42	_asm_extable 1b, 2b
43SYM_FUNC_END(__clear_user_generic)
44
45/*
46 * unsigned long __clear_user_fast(void *addr, unsigned long size)
47 *
48 * a0: addr
49 * a1: size
50 */
51SYM_FUNC_START(__clear_user_fast)
52	sltui	t0, a1, 9
53	bnez	t0, .Lsmall
54
55	add.d	a2, a0, a1
560:	st.d	zero, a0, 0
57
58	/* align up address */
59	addi.d	a0, a0, 8
60	bstrins.d	a0, zero, 2, 0
61
62	addi.d	a3, a2, -64
63	bgeu	a0, a3, .Llt64
64
65	/* set 64 bytes at a time */
66.Lloop64:
671:	st.d	zero, a0, 0
682:	st.d	zero, a0, 8
693:	st.d	zero, a0, 16
704:	st.d	zero, a0, 24
715:	st.d	zero, a0, 32
726:	st.d	zero, a0, 40
737:	st.d	zero, a0, 48
748:	st.d	zero, a0, 56
75	addi.d	a0, a0, 64
76	bltu	a0, a3, .Lloop64
77
78	/* set the remaining bytes */
79.Llt64:
80	addi.d	a3, a2, -32
81	bgeu	a0, a3, .Llt32
829:	st.d	zero, a0, 0
8310:	st.d	zero, a0, 8
8411:	st.d	zero, a0, 16
8512:	st.d	zero, a0, 24
86	addi.d	a0, a0, 32
87
88.Llt32:
89	addi.d	a3, a2, -16
90	bgeu	a0, a3, .Llt16
9113:	st.d	zero, a0, 0
9214:	st.d	zero, a0, 8
93	addi.d	a0, a0, 16
94
95.Llt16:
96	addi.d	a3, a2, -8
97	bgeu	a0, a3, .Llt8
9815:	st.d	zero, a0, 0
99	addi.d	a0, a0, 8
100
101.Llt8:
10216:	st.d	zero, a2, -8
103
104	/* return */
105	move	a0, zero
106	jr	ra
107
108	.align	4
109.Lsmall:
110	pcaddi	t0, 4
111	slli.d	a2, a1, 4
112	add.d	t0, t0, a2
113	jr	t0
114
115	.align	4
116	move	a0, zero
117	jr	ra
118
119	.align	4
12017:	st.b	zero, a0, 0
121	move	a0, zero
122	jr	ra
123
124	.align	4
12518:	st.h	zero, a0, 0
126	move	a0, zero
127	jr	ra
128
129	.align	4
13019:	st.h	zero, a0, 0
13120:	st.b	zero, a0, 2
132	move	a0, zero
133	jr	ra
134
135	.align	4
13621:	st.w	zero, a0, 0
137	move	a0, zero
138	jr	ra
139
140	.align	4
14122:	st.w	zero, a0, 0
14223:	st.b	zero, a0, 4
143	move	a0, zero
144	jr	ra
145
146	.align	4
14724:	st.w	zero, a0, 0
14825:	st.h	zero, a0, 4
149	move	a0, zero
150	jr	ra
151
152	.align	4
15326:	st.w	zero, a0, 0
15427:	st.w	zero, a0, 3
155	move	a0, zero
156	jr	ra
157
158	.align	4
15928:	st.d	zero, a0, 0
160	move	a0, zero
161	jr	ra
162
163	/* fixup and ex_table */
164.Llarge_fixup:
165	sub.d	a1, a2, a0
166
167.Lsmall_fixup:
16829:	st.b	zero, a0, 0
169	addi.d	a0, a0, 1
170	addi.d	a1, a1, -1
171	bgt	a1, zero, 29b
172
173.Lexit:
174	move	a0, a1
175	jr	ra
176
177	_asm_extable 0b, .Lsmall_fixup
178	_asm_extable 1b, .Llarge_fixup
179	_asm_extable 2b, .Llarge_fixup
180	_asm_extable 3b, .Llarge_fixup
181	_asm_extable 4b, .Llarge_fixup
182	_asm_extable 5b, .Llarge_fixup
183	_asm_extable 6b, .Llarge_fixup
184	_asm_extable 7b, .Llarge_fixup
185	_asm_extable 8b, .Llarge_fixup
186	_asm_extable 9b, .Llarge_fixup
187	_asm_extable 10b, .Llarge_fixup
188	_asm_extable 11b, .Llarge_fixup
189	_asm_extable 12b, .Llarge_fixup
190	_asm_extable 13b, .Llarge_fixup
191	_asm_extable 14b, .Llarge_fixup
192	_asm_extable 15b, .Llarge_fixup
193	_asm_extable 16b, .Llarge_fixup
194	_asm_extable 17b, .Lexit
195	_asm_extable 18b, .Lsmall_fixup
196	_asm_extable 19b, .Lsmall_fixup
197	_asm_extable 20b, .Lsmall_fixup
198	_asm_extable 21b, .Lsmall_fixup
199	_asm_extable 22b, .Lsmall_fixup
200	_asm_extable 23b, .Lsmall_fixup
201	_asm_extable 24b, .Lsmall_fixup
202	_asm_extable 25b, .Lsmall_fixup
203	_asm_extable 26b, .Lsmall_fixup
204	_asm_extable 27b, .Lsmall_fixup
205	_asm_extable 28b, .Lsmall_fixup
206	_asm_extable 29b, .Lexit
207SYM_FUNC_END(__clear_user_fast)
208
209STACK_FRAME_NON_STANDARD __clear_user_fast
210