Merge branch 'address-masking'
[linux-2.6-microblaze.git] / arch / loongarch / lib / clear_user.S
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
15 SYM_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
21 SYM_FUNC_END(__clear_user)
22
23 EXPORT_SYMBOL(__clear_user)
24
25 /*
26  * unsigned long __clear_user_generic(void *addr, size_t size)
27  *
28  * a0: addr
29  * a1: size
30  */
31 SYM_FUNC_START(__clear_user_generic)
32         beqz    a1, 2f
33
34 1:      st.b    zero, a0, 0
35         addi.d  a0, a0, 1
36         addi.d  a1, a1, -1
37         bgtz    a1, 1b
38
39 2:      move    a0, a1
40         jr      ra
41
42         _asm_extable 1b, 2b
43 SYM_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  */
51 SYM_FUNC_START(__clear_user_fast)
52         sltui   t0, a1, 9
53         bnez    t0, .Lsmall
54
55         add.d   a2, a0, a1
56 0:      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:
67 1:      st.d    zero, a0, 0
68 2:      st.d    zero, a0, 8
69 3:      st.d    zero, a0, 16
70 4:      st.d    zero, a0, 24
71 5:      st.d    zero, a0, 32
72 6:      st.d    zero, a0, 40
73 7:      st.d    zero, a0, 48
74 8:      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
82 9:      st.d    zero, a0, 0
83 10:     st.d    zero, a0, 8
84 11:     st.d    zero, a0, 16
85 12:     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
91 13:     st.d    zero, a0, 0
92 14:     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
98 15:     st.d    zero, a0, 0
99         addi.d  a0, a0, 8
100
101 .Llt8:
102 16:     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
120 17:     st.b    zero, a0, 0
121         move    a0, zero
122         jr      ra
123
124         .align  4
125 18:     st.h    zero, a0, 0
126         move    a0, zero
127         jr      ra
128
129         .align  4
130 19:     st.h    zero, a0, 0
131 20:     st.b    zero, a0, 2
132         move    a0, zero
133         jr      ra
134
135         .align  4
136 21:     st.w    zero, a0, 0
137         move    a0, zero
138         jr      ra
139
140         .align  4
141 22:     st.w    zero, a0, 0
142 23:     st.b    zero, a0, 4
143         move    a0, zero
144         jr      ra
145
146         .align  4
147 24:     st.w    zero, a0, 0
148 25:     st.h    zero, a0, 4
149         move    a0, zero
150         jr      ra
151
152         .align  4
153 26:     st.w    zero, a0, 0
154 27:     st.w    zero, a0, 3
155         move    a0, zero
156         jr      ra
157
158         .align  4
159 28:     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:
168 29:     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
207 SYM_FUNC_END(__clear_user_fast)
208
209 STACK_FRAME_NON_STANDARD __clear_user_fast