Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/sparc-2.6
[linux-2.6] / arch / arm / lib / memset.S
1 /*
2  *  linux/arch/arm/lib/memset.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  *  ASM optimised string functions
11  */
12 #include <linux/linkage.h>
13 #include <asm/assembler.h>
14
15         .text
16         .align  5
17         .word   0
18
19 1:      subs    r2, r2, #4              @ 1 do we have enough
20         blt     5f                      @ 1 bytes to align with?
21         cmp     r3, #2                  @ 1
22         strltb  r1, [r0], #1            @ 1
23         strleb  r1, [r0], #1            @ 1
24         strb    r1, [r0], #1            @ 1
25         add     r2, r2, r3              @ 1 (r2 = r2 - (4 - r3))
26 /*
27  * The pointer is now aligned and the length is adjusted.  Try doing the
28  * memzero again.
29  */
30
31 ENTRY(memset)
32         ands    r3, r0, #3              @ 1 unaligned?
33         bne     1b                      @ 1
34 /*
35  * we know that the pointer in r0 is aligned to a word boundary.
36  */
37         orr     r1, r1, r1, lsl #8
38         orr     r1, r1, r1, lsl #16
39         mov     r3, r1
40         cmp     r2, #16
41         blt     4f
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]!
47         mov     ip, r1
48         mov     lr, r1
49
50 2:      subs    r2, r2, #64
51         stmgeia r0!, {r1, r3, ip, lr}   @ 64 bytes at a time.
52         stmgeia r0!, {r1, r3, ip, lr}
53         stmgeia r0!, {r1, r3, ip, lr}
54         stmgeia r0!, {r1, r3, ip, lr}
55         bgt     2b
56         ldmeqfd sp!, {pc}               @ Now <64 bytes to go.
57 /*
58  * No need to correct the count; we're only testing bits from now on
59  */
60         tst     r2, #32
61         stmneia r0!, {r1, r3, ip, lr}
62         stmneia r0!, {r1, r3, ip, lr}
63         tst     r2, #16
64         stmneia r0!, {r1, r3, ip, lr}
65         ldr     lr, [sp], #4
66
67 4:      tst     r2, #8
68         stmneia r0!, {r1, r3}
69         tst     r2, #4
70         strne   r1, [r0], #4
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     r2, #2
76         strneb  r1, [r0], #1
77         strneb  r1, [r0], #1
78         tst     r2, #1
79         strneb  r1, [r0], #1
80         mov     pc, lr