diff options
Diffstat (limited to 'arch/mips/lib/memset.S')
-rw-r--r-- | arch/mips/lib/memset.S | 146 |
1 files changed, 95 insertions, 51 deletions
diff --git a/arch/mips/lib/memset.S b/arch/mips/lib/memset.S index 0580194e7402..7b0e5462ca51 100644 --- a/arch/mips/lib/memset.S +++ b/arch/mips/lib/memset.S | |||
@@ -34,13 +34,27 @@ | |||
34 | #define FILLPTRG t0 | 34 | #define FILLPTRG t0 |
35 | #endif | 35 | #endif |
36 | 36 | ||
37 | #define LEGACY_MODE 1 | ||
38 | #define EVA_MODE 2 | ||
39 | |||
40 | /* | ||
41 | * No need to protect it with EVA #ifdefery. The generated block of code | ||
42 | * will never be assembled if EVA is not enabled. | ||
43 | */ | ||
44 | #define __EVAFY(insn, reg, addr) __BUILD_EVA_INSN(insn##e, reg, addr) | ||
45 | #define ___BUILD_EVA_INSN(insn, reg, addr) __EVAFY(insn, reg, addr) | ||
46 | |||
37 | #define EX(insn,reg,addr,handler) \ | 47 | #define EX(insn,reg,addr,handler) \ |
38 | 9: insn reg, addr; \ | 48 | .if \mode == LEGACY_MODE; \ |
49 | 9: insn reg, addr; \ | ||
50 | .else; \ | ||
51 | 9: ___BUILD_EVA_INSN(insn, reg, addr); \ | ||
52 | .endif; \ | ||
39 | .section __ex_table,"a"; \ | 53 | .section __ex_table,"a"; \ |
40 | PTR 9b, handler; \ | 54 | PTR 9b, handler; \ |
41 | .previous | 55 | .previous |
42 | 56 | ||
43 | .macro f_fill64 dst, offset, val, fixup | 57 | .macro f_fill64 dst, offset, val, fixup, mode |
44 | EX(LONG_S, \val, (\offset + 0 * STORSIZE)(\dst), \fixup) | 58 | EX(LONG_S, \val, (\offset + 0 * STORSIZE)(\dst), \fixup) |
45 | EX(LONG_S, \val, (\offset + 1 * STORSIZE)(\dst), \fixup) | 59 | EX(LONG_S, \val, (\offset + 1 * STORSIZE)(\dst), \fixup) |
46 | EX(LONG_S, \val, (\offset + 2 * STORSIZE)(\dst), \fixup) | 60 | EX(LONG_S, \val, (\offset + 2 * STORSIZE)(\dst), \fixup) |
@@ -63,34 +77,24 @@ | |||
63 | #endif | 77 | #endif |
64 | .endm | 78 | .endm |
65 | 79 | ||
66 | /* | ||
67 | * memset(void *s, int c, size_t n) | ||
68 | * | ||
69 | * a0: start of area to clear | ||
70 | * a1: char to fill with | ||
71 | * a2: size of area to clear | ||
72 | */ | ||
73 | .set noreorder | 80 | .set noreorder |
74 | .align 5 | 81 | .align 5 |
75 | LEAF(memset) | ||
76 | beqz a1, 1f | ||
77 | move v0, a0 /* result */ | ||
78 | 82 | ||
79 | andi a1, 0xff /* spread fillword */ | 83 | /* |
80 | LONG_SLL t1, a1, 8 | 84 | * Macro to generate the __bzero{,_user} symbol |
81 | or a1, t1 | 85 | * Arguments: |
82 | LONG_SLL t1, a1, 16 | 86 | * mode: LEGACY_MODE or EVA_MODE |
83 | #if LONGSIZE == 8 | 87 | */ |
84 | or a1, t1 | 88 | .macro __BUILD_BZERO mode |
85 | LONG_SLL t1, a1, 32 | 89 | /* Initialize __memset if this is the first time we call this macro */ |
86 | #endif | 90 | .ifnotdef __memset |
87 | or a1, t1 | 91 | .set __memset, 1 |
88 | 1: | 92 | .hidden __memset /* Make sure it does not leak */ |
93 | .endif | ||
89 | 94 | ||
90 | FEXPORT(__bzero) | ||
91 | sltiu t0, a2, STORSIZE /* very small region? */ | 95 | sltiu t0, a2, STORSIZE /* very small region? */ |
92 | bnez t0, .Lsmall_memset | 96 | bnez t0, .Lsmall_memset\@ |
93 | andi t0, a0, STORMASK /* aligned? */ | 97 | andi t0, a0, STORMASK /* aligned? */ |
94 | 98 | ||
95 | #ifdef CONFIG_CPU_MICROMIPS | 99 | #ifdef CONFIG_CPU_MICROMIPS |
96 | move t8, a1 /* used by 'swp' instruction */ | 100 | move t8, a1 /* used by 'swp' instruction */ |
@@ -98,39 +102,39 @@ FEXPORT(__bzero) | |||
98 | #endif | 102 | #endif |
99 | #ifndef CONFIG_CPU_DADDI_WORKAROUNDS | 103 | #ifndef CONFIG_CPU_DADDI_WORKAROUNDS |
100 | beqz t0, 1f | 104 | beqz t0, 1f |
101 | PTR_SUBU t0, STORSIZE /* alignment in bytes */ | 105 | PTR_SUBU t0, STORSIZE /* alignment in bytes */ |
102 | #else | 106 | #else |
103 | .set noat | 107 | .set noat |
104 | li AT, STORSIZE | 108 | li AT, STORSIZE |
105 | beqz t0, 1f | 109 | beqz t0, 1f |
106 | PTR_SUBU t0, AT /* alignment in bytes */ | 110 | PTR_SUBU t0, AT /* alignment in bytes */ |
107 | .set at | 111 | .set at |
108 | #endif | 112 | #endif |
109 | 113 | ||
110 | R10KCBARRIER(0(ra)) | 114 | R10KCBARRIER(0(ra)) |
111 | #ifdef __MIPSEB__ | 115 | #ifdef __MIPSEB__ |
112 | EX(LONG_S_L, a1, (a0), .Lfirst_fixup) /* make word/dword aligned */ | 116 | EX(LONG_S_L, a1, (a0), .Lfirst_fixup\@) /* make word/dword aligned */ |
113 | #endif | 117 | #endif |
114 | #ifdef __MIPSEL__ | 118 | #ifdef __MIPSEL__ |
115 | EX(LONG_S_R, a1, (a0), .Lfirst_fixup) /* make word/dword aligned */ | 119 | EX(LONG_S_R, a1, (a0), .Lfirst_fixup\@) /* make word/dword aligned */ |
116 | #endif | 120 | #endif |
117 | PTR_SUBU a0, t0 /* long align ptr */ | 121 | PTR_SUBU a0, t0 /* long align ptr */ |
118 | PTR_ADDU a2, t0 /* correct size */ | 122 | PTR_ADDU a2, t0 /* correct size */ |
119 | 123 | ||
120 | 1: ori t1, a2, 0x3f /* # of full blocks */ | 124 | 1: ori t1, a2, 0x3f /* # of full blocks */ |
121 | xori t1, 0x3f | 125 | xori t1, 0x3f |
122 | beqz t1, .Lmemset_partial /* no block to fill */ | 126 | beqz t1, .Lmemset_partial\@ /* no block to fill */ |
123 | andi t0, a2, 0x40-STORSIZE | 127 | andi t0, a2, 0x40-STORSIZE |
124 | 128 | ||
125 | PTR_ADDU t1, a0 /* end address */ | 129 | PTR_ADDU t1, a0 /* end address */ |
126 | .set reorder | 130 | .set reorder |
127 | 1: PTR_ADDIU a0, 64 | 131 | 1: PTR_ADDIU a0, 64 |
128 | R10KCBARRIER(0(ra)) | 132 | R10KCBARRIER(0(ra)) |
129 | f_fill64 a0, -64, FILL64RG, .Lfwd_fixup | 133 | f_fill64 a0, -64, FILL64RG, .Lfwd_fixup\@, \mode |
130 | bne t1, a0, 1b | 134 | bne t1, a0, 1b |
131 | .set noreorder | 135 | .set noreorder |
132 | 136 | ||
133 | .Lmemset_partial: | 137 | .Lmemset_partial\@: |
134 | R10KCBARRIER(0(ra)) | 138 | R10KCBARRIER(0(ra)) |
135 | PTR_LA t1, 2f /* where to start */ | 139 | PTR_LA t1, 2f /* where to start */ |
136 | #ifdef CONFIG_CPU_MICROMIPS | 140 | #ifdef CONFIG_CPU_MICROMIPS |
@@ -145,60 +149,100 @@ FEXPORT(__bzero) | |||
145 | .set at | 149 | .set at |
146 | #endif | 150 | #endif |
147 | jr t1 | 151 | jr t1 |
148 | PTR_ADDU a0, t0 /* dest ptr */ | 152 | PTR_ADDU a0, t0 /* dest ptr */ |
149 | 153 | ||
150 | .set push | 154 | .set push |
151 | .set noreorder | 155 | .set noreorder |
152 | .set nomacro | 156 | .set nomacro |
153 | f_fill64 a0, -64, FILL64RG, .Lpartial_fixup /* ... but first do longs ... */ | 157 | /* ... but first do longs ... */ |
158 | f_fill64 a0, -64, FILL64RG, .Lpartial_fixup\@, \mode | ||
154 | 2: .set pop | 159 | 2: .set pop |
155 | andi a2, STORMASK /* At most one long to go */ | 160 | andi a2, STORMASK /* At most one long to go */ |
156 | 161 | ||
157 | beqz a2, 1f | 162 | beqz a2, 1f |
158 | PTR_ADDU a0, a2 /* What's left */ | 163 | PTR_ADDU a0, a2 /* What's left */ |
159 | R10KCBARRIER(0(ra)) | 164 | R10KCBARRIER(0(ra)) |
160 | #ifdef __MIPSEB__ | 165 | #ifdef __MIPSEB__ |
161 | EX(LONG_S_R, a1, -1(a0), .Llast_fixup) | 166 | EX(LONG_S_R, a1, -1(a0), .Llast_fixup\@) |
162 | #endif | 167 | #endif |
163 | #ifdef __MIPSEL__ | 168 | #ifdef __MIPSEL__ |
164 | EX(LONG_S_L, a1, -1(a0), .Llast_fixup) | 169 | EX(LONG_S_L, a1, -1(a0), .Llast_fixup\@) |
165 | #endif | 170 | #endif |
166 | 1: jr ra | 171 | 1: jr ra |
167 | move a2, zero | 172 | move a2, zero |
168 | 173 | ||
169 | .Lsmall_memset: | 174 | .Lsmall_memset\@: |
170 | beqz a2, 2f | 175 | beqz a2, 2f |
171 | PTR_ADDU t1, a0, a2 | 176 | PTR_ADDU t1, a0, a2 |
172 | 177 | ||
173 | 1: PTR_ADDIU a0, 1 /* fill bytewise */ | 178 | 1: PTR_ADDIU a0, 1 /* fill bytewise */ |
174 | R10KCBARRIER(0(ra)) | 179 | R10KCBARRIER(0(ra)) |
175 | bne t1, a0, 1b | 180 | bne t1, a0, 1b |
176 | sb a1, -1(a0) | 181 | sb a1, -1(a0) |
177 | 182 | ||
178 | 2: jr ra /* done */ | 183 | 2: jr ra /* done */ |
179 | move a2, zero | 184 | move a2, zero |
185 | .if __memset == 1 | ||
180 | END(memset) | 186 | END(memset) |
187 | .set __memset, 0 | ||
188 | .hidden __memset | ||
189 | .endif | ||
181 | 190 | ||
182 | .Lfirst_fixup: | 191 | .Lfirst_fixup\@: |
183 | jr ra | 192 | jr ra |
184 | nop | 193 | nop |
185 | 194 | ||
186 | .Lfwd_fixup: | 195 | .Lfwd_fixup\@: |
187 | PTR_L t0, TI_TASK($28) | 196 | PTR_L t0, TI_TASK($28) |
188 | andi a2, 0x3f | 197 | andi a2, 0x3f |
189 | LONG_L t0, THREAD_BUADDR(t0) | 198 | LONG_L t0, THREAD_BUADDR(t0) |
190 | LONG_ADDU a2, t1 | 199 | LONG_ADDU a2, t1 |
191 | jr ra | 200 | jr ra |
192 | LONG_SUBU a2, t0 | 201 | LONG_SUBU a2, t0 |
193 | 202 | ||
194 | .Lpartial_fixup: | 203 | .Lpartial_fixup\@: |
195 | PTR_L t0, TI_TASK($28) | 204 | PTR_L t0, TI_TASK($28) |
196 | andi a2, STORMASK | 205 | andi a2, STORMASK |
197 | LONG_L t0, THREAD_BUADDR(t0) | 206 | LONG_L t0, THREAD_BUADDR(t0) |
198 | LONG_ADDU a2, t1 | 207 | LONG_ADDU a2, t1 |
199 | jr ra | 208 | jr ra |
200 | LONG_SUBU a2, t0 | 209 | LONG_SUBU a2, t0 |
201 | 210 | ||
202 | .Llast_fixup: | 211 | .Llast_fixup\@: |
203 | jr ra | 212 | jr ra |
204 | andi v1, a2, STORMASK | 213 | andi v1, a2, STORMASK |
214 | |||
215 | .endm | ||
216 | |||
217 | /* | ||
218 | * memset(void *s, int c, size_t n) | ||
219 | * | ||
220 | * a0: start of area to clear | ||
221 | * a1: char to fill with | ||
222 | * a2: size of area to clear | ||
223 | */ | ||
224 | |||
225 | LEAF(memset) | ||
226 | beqz a1, 1f | ||
227 | move v0, a0 /* result */ | ||
228 | |||
229 | andi a1, 0xff /* spread fillword */ | ||
230 | LONG_SLL t1, a1, 8 | ||
231 | or a1, t1 | ||
232 | LONG_SLL t1, a1, 16 | ||
233 | #if LONGSIZE == 8 | ||
234 | or a1, t1 | ||
235 | LONG_SLL t1, a1, 32 | ||
236 | #endif | ||
237 | or a1, t1 | ||
238 | 1: | ||
239 | #ifndef CONFIG_EVA | ||
240 | FEXPORT(__bzero) | ||
241 | #endif | ||
242 | __BUILD_BZERO LEGACY_MODE | ||
243 | |||
244 | #ifdef CONFIG_EVA | ||
245 | LEAF(__bzero) | ||
246 | __BUILD_BZERO EVA_MODE | ||
247 | END(__bzero) | ||
248 | #endif | ||