LoongArch: Optimize memory ops (memset/memcpy/memmove)
[linux-block.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 <asm/alternative-asm.h>
7 #include <asm/asm.h>
8 #include <asm/asmmacro.h>
9 #include <asm/asm-extable.h>
10 #include <asm/cpu.h>
11 #include <asm/export.h>
12 #include <asm/regdef.h>
13
14 .irp to, 0, 1, 2, 3, 4, 5, 6, 7
15 .L_fixup_handle_\to\():
16         sub.d   a0, a2, a0
17         addi.d  a0, a0, (\to) * (-8)
18         jr      ra
19 .endr
20
21 .irp to, 0, 2, 4
22 .L_fixup_handle_s\to\():
23         addi.d  a0, a1, -\to
24         jr      ra
25 .endr
26
27 SYM_FUNC_START(__clear_user)
28         /*
29          * Some CPUs support hardware unaligned access
30          */
31         ALTERNATIVE     "b __clear_user_generic",       \
32                         "b __clear_user_fast", CPU_FEATURE_UAL
33 SYM_FUNC_END(__clear_user)
34
35 EXPORT_SYMBOL(__clear_user)
36
37 /*
38  * unsigned long __clear_user_generic(void *addr, size_t size)
39  *
40  * a0: addr
41  * a1: size
42  */
43 SYM_FUNC_START(__clear_user_generic)
44         beqz    a1, 2f
45
46 1:      st.b    zero, a0, 0
47         addi.d  a0, a0, 1
48         addi.d  a1, a1, -1
49         bgtz    a1, 1b
50
51 2:      move    a0, a1
52         jr      ra
53
54         _asm_extable 1b, .L_fixup_handle_s0
55 SYM_FUNC_END(__clear_user_generic)
56
57 /*
58  * unsigned long __clear_user_fast(void *addr, unsigned long size)
59  *
60  * a0: addr
61  * a1: size
62  */
63 SYM_FUNC_START(__clear_user_fast)
64         sltui   t0, a1, 9
65         bnez    t0, .Lsmall
66
67         add.d   a2, a0, a1
68 0:      st.d    zero, a0, 0
69
70         /* align up address */
71         addi.d  a0, a0, 8
72         bstrins.d       a0, zero, 2, 0
73
74         addi.d  a3, a2, -64
75         bgeu    a0, a3, .Llt64
76
77         /* set 64 bytes at a time */
78 .Lloop64:
79 1:      st.d    zero, a0, 0
80 2:      st.d    zero, a0, 8
81 3:      st.d    zero, a0, 16
82 4:      st.d    zero, a0, 24
83 5:      st.d    zero, a0, 32
84 6:      st.d    zero, a0, 40
85 7:      st.d    zero, a0, 48
86 8:      st.d    zero, a0, 56
87         addi.d  a0, a0, 64
88         bltu    a0, a3, .Lloop64
89
90         /* set the remaining bytes */
91 .Llt64:
92         addi.d  a3, a2, -32
93         bgeu    a0, a3, .Llt32
94 9:      st.d    zero, a0, 0
95 10:     st.d    zero, a0, 8
96 11:     st.d    zero, a0, 16
97 12:     st.d    zero, a0, 24
98         addi.d  a0, a0, 32
99
100 .Llt32:
101         addi.d  a3, a2, -16
102         bgeu    a0, a3, .Llt16
103 13:     st.d    zero, a0, 0
104 14:     st.d    zero, a0, 8
105         addi.d  a0, a0, 16
106
107 .Llt16:
108         addi.d  a3, a2, -8
109         bgeu    a0, a3, .Llt8
110 15:     st.d    zero, a0, 0
111
112 .Llt8:
113 16:     st.d    zero, a2, -8
114
115         /* return */
116         move    a0, zero
117         jr      ra
118
119         .align  4
120 .Lsmall:
121         pcaddi  t0, 4
122         slli.d  a2, a1, 4
123         add.d   t0, t0, a2
124         jr      t0
125
126         .align  4
127         move    a0, zero
128         jr      ra
129
130         .align  4
131 17:     st.b    zero, a0, 0
132         move    a0, zero
133         jr      ra
134
135         .align  4
136 18:     st.h    zero, a0, 0
137         move    a0, zero
138         jr      ra
139
140         .align  4
141 19:     st.h    zero, a0, 0
142 20:     st.b    zero, a0, 2
143         move    a0, zero
144         jr      ra
145
146         .align  4
147 21:     st.w    zero, a0, 0
148         move    a0, zero
149         jr      ra
150
151         .align  4
152 22:     st.w    zero, a0, 0
153 23:     st.b    zero, a0, 4
154         move    a0, zero
155         jr      ra
156
157         .align  4
158 24:     st.w    zero, a0, 0
159 25:     st.h    zero, a0, 4
160         move    a0, zero
161         jr      ra
162
163         .align  4
164 26:     st.w    zero, a0, 0
165 27:     st.w    zero, a0, 3
166         move    a0, zero
167         jr      ra
168
169         .align  4
170 28:     st.d    zero, a0, 0
171         move    a0, zero
172         jr      ra
173
174         /* fixup and ex_table */
175         _asm_extable 0b, .L_fixup_handle_0
176         _asm_extable 1b, .L_fixup_handle_0
177         _asm_extable 2b, .L_fixup_handle_1
178         _asm_extable 3b, .L_fixup_handle_2
179         _asm_extable 4b, .L_fixup_handle_3
180         _asm_extable 5b, .L_fixup_handle_4
181         _asm_extable 6b, .L_fixup_handle_5
182         _asm_extable 7b, .L_fixup_handle_6
183         _asm_extable 8b, .L_fixup_handle_7
184         _asm_extable 9b, .L_fixup_handle_0
185         _asm_extable 10b, .L_fixup_handle_1
186         _asm_extable 11b, .L_fixup_handle_2
187         _asm_extable 12b, .L_fixup_handle_3
188         _asm_extable 13b, .L_fixup_handle_0
189         _asm_extable 14b, .L_fixup_handle_1
190         _asm_extable 15b, .L_fixup_handle_0
191         _asm_extable 16b, .L_fixup_handle_1
192         _asm_extable 17b, .L_fixup_handle_s0
193         _asm_extable 18b, .L_fixup_handle_s0
194         _asm_extable 19b, .L_fixup_handle_s0
195         _asm_extable 20b, .L_fixup_handle_s2
196         _asm_extable 21b, .L_fixup_handle_s0
197         _asm_extable 22b, .L_fixup_handle_s0
198         _asm_extable 23b, .L_fixup_handle_s4
199         _asm_extable 24b, .L_fixup_handle_s0
200         _asm_extable 25b, .L_fixup_handle_s4
201         _asm_extable 26b, .L_fixup_handle_s0
202         _asm_extable 27b, .L_fixup_handle_s4
203         _asm_extable 28b, .L_fixup_handle_s0
204 SYM_FUNC_END(__clear_user_fast)