Linux 3.11-rc3
[cris-mirror.git] / arch / arm / lib / memset.S
blob94b0650ea98fd42492c280d20c7610382a2f4a81
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>
15         .text
16         .align  5
18 ENTRY(memset)
19         ands    r3, r0, #3              @ 1 unaligned?
20         mov     ip, r0                  @ preserve r0 as return value
21         bne     6f                      @ 1
23  * we know that the pointer in ip is aligned to a word boundary.
24  */
25 1:      orr     r1, r1, r1, lsl #8
26         orr     r1, r1, r1, lsl #16
27         mov     r3, r1
28         cmp     r2, #16
29         blt     4f
31 #if ! CALGN(1)+0
34  * We need 2 extra registers for this loop - use r8 and the LR
35  */
36         stmfd   sp!, {r8, lr}
37         mov     r8, r1
38         mov     lr, r1
40 2:      subs    r2, r2, #64
41         stmgeia ip!, {r1, r3, r8, lr}   @ 64 bytes at a time.
42         stmgeia ip!, {r1, r3, r8, lr}
43         stmgeia ip!, {r1, r3, r8, lr}
44         stmgeia ip!, {r1, r3, r8, lr}
45         bgt     2b
46         ldmeqfd sp!, {r8, pc}           @ Now <64 bytes to go.
48  * No need to correct the count; we're only testing bits from now on
49  */
50         tst     r2, #32
51         stmneia ip!, {r1, r3, r8, lr}
52         stmneia ip!, {r1, r3, r8, lr}
53         tst     r2, #16
54         stmneia ip!, {r1, r3, r8, lr}
55         ldmfd   sp!, {r8, lr}
57 #else
60  * This version aligns the destination pointer in order to write
61  * whole cache lines at once.
62  */
64         stmfd   sp!, {r4-r8, lr}
65         mov     r4, r1
66         mov     r5, r1
67         mov     r6, r1
68         mov     r7, r1
69         mov     r8, r1
70         mov     lr, r1
72         cmp     r2, #96
73         tstgt   ip, #31
74         ble     3f
76         and     r8, ip, #31
77         rsb     r8, r8, #32
78         sub     r2, r2, r8
79         movs    r8, r8, lsl #(32 - 4)
80         stmcsia ip!, {r4, r5, r6, r7}
81         stmmiia ip!, {r4, r5}
82         tst     r8, #(1 << 30)
83         mov     r8, r1
84         strne   r1, [ip], #4
86 3:      subs    r2, r2, #64
87         stmgeia ip!, {r1, r3-r8, lr}
88         stmgeia ip!, {r1, r3-r8, lr}
89         bgt     3b
90         ldmeqfd sp!, {r4-r8, pc}
92         tst     r2, #32
93         stmneia ip!, {r1, r3-r8, lr}
94         tst     r2, #16
95         stmneia ip!, {r4-r7}
96         ldmfd   sp!, {r4-r8, lr}
98 #endif
100 4:      tst     r2, #8
101         stmneia ip!, {r1, r3}
102         tst     r2, #4
103         strne   r1, [ip], #4
105  * When we get here, we've got less than 4 bytes to zero.  We
106  * may have an unaligned pointer as well.
107  */
108 5:      tst     r2, #2
109         strneb  r1, [ip], #1
110         strneb  r1, [ip], #1
111         tst     r2, #1
112         strneb  r1, [ip], #1
113         mov     pc, lr
115 6:      subs    r2, r2, #4              @ 1 do we have enough
116         blt     5b                      @ 1 bytes to align with?
117         cmp     r3, #2                  @ 1
118         strltb  r1, [ip], #1            @ 1
119         strleb  r1, [ip], #1            @ 1
120         strb    r1, [ip], #1            @ 1
121         add     r2, r2, r3              @ 1 (r2 = r2 - (4 - r3))
122         b       1b
123 ENDPROC(memset)