manual update from upstream:
[linux-2.6] / arch / arm / lib / memzero.S
1 /*
2  *  linux/arch/arm/lib/memzero.S
3  *
4  *  Copyright (C) 1995-2000 Russell King
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License version 2 as
8  * published by the Free Software Foundation.
9  */
10 #include <linux/linkage.h>
11 #include <asm/assembler.h>
12
13         .text
14         .align  5
15         .word   0
16 /*
17  * Align the pointer in r0.  r3 contains the number of bytes that we are
18  * mis-aligned by, and r1 is the number of bytes.  If r1 < 4, then we
19  * don't bother; we use byte stores instead.
20  */
21 1:      subs    r1, r1, #4              @ 1 do we have enough
22         blt     5f                      @ 1 bytes to align with?
23         cmp     r3, #2                  @ 1
24         strltb  r2, [r0], #1            @ 1
25         strleb  r2, [r0], #1            @ 1
26         strb    r2, [r0], #1            @ 1
27         add     r1, r1, r3              @ 1 (r1 = r1 - (4 - r3))
28 /*
29  * The pointer is now aligned and the length is adjusted.  Try doing the
30  * memzero again.
31  */
32
33 ENTRY(__memzero)
34         mov     r2, #0                  @ 1
35         ands    r3, r0, #3              @ 1 unaligned?
36         bne     1b                      @ 1
37 /*
38  * r3 = 0, and we know that the pointer in r0 is aligned to a word boundary.
39  */
40         cmp     r1, #16                 @ 1 we can skip this chunk if we
41         blt     4f                      @ 1 have < 16 bytes
42 /*
43  * We need an extra register for this loop - save the return address and
44  * use the LR
45  */
46         str     lr, [sp, #-4]!          @ 1
47         mov     ip, r2                  @ 1
48         mov     lr, r2                  @ 1
49
50 3:      subs    r1, r1, #64             @ 1 write 32 bytes out per loop
51         stmgeia r0!, {r2, r3, ip, lr}   @ 4
52         stmgeia r0!, {r2, r3, ip, lr}   @ 4
53         stmgeia r0!, {r2, r3, ip, lr}   @ 4
54         stmgeia r0!, {r2, r3, ip, lr}   @ 4
55         bgt     3b                      @ 1
56         LOADREGS(eqfd, sp!, {pc})       @ 1/2 quick exit
57 /*
58  * No need to correct the count; we're only testing bits from now on
59  */
60         tst     r1, #32                 @ 1
61         stmneia r0!, {r2, r3, ip, lr}   @ 4
62         stmneia r0!, {r2, r3, ip, lr}   @ 4
63         tst     r1, #16                 @ 1 16 bytes or more?
64         stmneia r0!, {r2, r3, ip, lr}   @ 4
65         ldr     lr, [sp], #4            @ 1
66
67 4:      tst     r1, #8                  @ 1 8 bytes or more?
68         stmneia r0!, {r2, r3}           @ 2
69         tst     r1, #4                  @ 1 4 bytes or more?
70         strne   r2, [r0], #4            @ 1
71 /*
72  * When we get here, we've got less than 4 bytes to zero.  We
73  * may have an unaligned pointer as well.
74  */
75 5:      tst     r1, #2                  @ 1 2 bytes or more?
76         strneb  r2, [r0], #1            @ 1
77         strneb  r2, [r0], #1            @ 1
78         tst     r1, #1                  @ 1 a byte left over
79         strneb  r2, [r0], #1            @ 1
80         RETINSTR(mov,pc,lr)             @ 1