diff options
-rw-r--r-- | firmware/common/memset_a.S | 81 |
1 files changed, 81 insertions, 0 deletions
diff --git a/firmware/common/memset_a.S b/firmware/common/memset_a.S index 9403e8d68e..b6a9ca8f71 100644 --- a/firmware/common/memset_a.S +++ b/firmware/common/memset_a.S | |||
@@ -18,7 +18,11 @@ | |||
18 | ****************************************************************************/ | 18 | ****************************************************************************/ |
19 | #include "config.h" | 19 | #include "config.h" |
20 | 20 | ||
21 | #ifdef CPU_ARM | ||
22 | .section .icode,"ax",%progbits | ||
23 | #elif | ||
21 | .section .icode,"ax",@progbits | 24 | .section .icode,"ax",@progbits |
25 | #endif | ||
22 | 26 | ||
23 | .align 2 | 27 | .align 2 |
24 | #if CONFIG_CPU == SH7034 | 28 | #if CONFIG_CPU == SH7034 |
@@ -234,4 +238,81 @@ memset: | |||
234 | 238 | ||
235 | .end: | 239 | .end: |
236 | .size memset,.end-memset | 240 | .size memset,.end-memset |
241 | |||
242 | #elif defined(CPU_ARM) | ||
243 | |||
244 | /* The following code is taken from the Linux kernel version 2.6.15.3 | ||
245 | * linux/arch/arm/lib/memset.S | ||
246 | * | ||
247 | * Copyright (C) 1995-2000 Russell King | ||
248 | */ | ||
249 | |||
250 | @ .word 0 | ||
251 | 1: subs r2, r2, #4 @ 1 do we have enough | ||
252 | blt 5f @ 1 bytes to align with? | ||
253 | cmp r3, #2 @ 1 | ||
254 | strltb r1, [r0], #1 @ 1 | ||
255 | strleb r1, [r0], #1 @ 1 | ||
256 | strb r1, [r0], #1 @ 1 | ||
257 | add r2, r2, r3 @ 1 (r2 = r2 - (4 - r3)) | ||
258 | /* | ||
259 | * The pointer is now aligned and the length is adjusted. Try doing the | ||
260 | * memzero again. | ||
261 | */ | ||
262 | |||
263 | .global memset | ||
264 | .type memset,%function | ||
265 | memset: | ||
266 | ands r3, r0, #3 @ 1 unaligned? | ||
267 | bne 1b @ 1 | ||
268 | /* | ||
269 | * we know that the pointer in r0 is aligned to a word boundary. | ||
270 | */ | ||
271 | orr r1, r1, r1, lsl #8 | ||
272 | orr r1, r1, r1, lsl #16 | ||
273 | mov r3, r1 | ||
274 | cmp r2, #16 | ||
275 | blt 4f | ||
276 | /* | ||
277 | * We need an extra register for this loop - save the return address and | ||
278 | * use the LR | ||
279 | */ | ||
280 | str lr, [sp, #-4]! | ||
281 | mov ip, r1 | ||
282 | mov lr, r1 | ||
283 | |||
284 | 2: subs r2, r2, #64 | ||
285 | stmgeia r0!, {r1, r3, ip, lr} @ 64 bytes at a time. | ||
286 | stmgeia r0!, {r1, r3, ip, lr} | ||
287 | stmgeia r0!, {r1, r3, ip, lr} | ||
288 | stmgeia r0!, {r1, r3, ip, lr} | ||
289 | bgt 2b | ||
290 | ldmeqfd sp!, {pc} @ Now <64 bytes to go. | ||
291 | /* | ||
292 | * No need to correct the count; we're only testing bits from now on | ||
293 | */ | ||
294 | tst r2, #32 | ||
295 | stmneia r0!, {r1, r3, ip, lr} | ||
296 | stmneia r0!, {r1, r3, ip, lr} | ||
297 | tst r2, #16 | ||
298 | stmneia r0!, {r1, r3, ip, lr} | ||
299 | ldr lr, [sp], #4 | ||
300 | |||
301 | 4: tst r2, #8 | ||
302 | stmneia r0!, {r1, r3} | ||
303 | tst r2, #4 | ||
304 | strne r1, [r0], #4 | ||
305 | /* | ||
306 | * When we get here, we've got less than 4 bytes to zero. We | ||
307 | * may have an unaligned pointer as well. | ||
308 | */ | ||
309 | 5: tst r2, #2 | ||
310 | strneb r1, [r0], #1 | ||
311 | strneb r1, [r0], #1 | ||
312 | tst r2, #1 | ||
313 | strneb r1, [r0], #1 | ||
314 | mov pc, lr | ||
315 | end: | ||
316 | .size memset,.end-memset | ||
237 | #endif | 317 | #endif |
318 | |||