Merge remote-tracking branch 'regmap/for-next'
[deliverable/linux.git] / 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 #include <asm/unwind.h>
15 #include <asm/export.h>
16
17 .text
18 .align 5
19
20 ENTRY(mmioset)
21 ENTRY(memset)
22 UNWIND( .fnstart )
23 ands r3, r0, #3 @ 1 unaligned?
24 mov ip, r0 @ preserve r0 as return value
25 bne 6f @ 1
26 /*
27 * we know that the pointer in ip is aligned to a word boundary.
28 */
29 1: orr r1, r1, r1, lsl #8
30 orr r1, r1, r1, lsl #16
31 mov r3, r1
32 cmp r2, #16
33 blt 4f
34
35 #if ! CALGN(1)+0
36
37 /*
38 * We need 2 extra registers for this loop - use r8 and the LR
39 */
40 stmfd sp!, {r8, lr}
41 UNWIND( .fnend )
42 UNWIND( .fnstart )
43 UNWIND( .save {r8, lr} )
44 mov r8, r1
45 mov lr, r1
46
47 2: subs r2, r2, #64
48 stmgeia ip!, {r1, r3, r8, lr} @ 64 bytes at a time.
49 stmgeia ip!, {r1, r3, r8, lr}
50 stmgeia ip!, {r1, r3, r8, lr}
51 stmgeia ip!, {r1, r3, r8, lr}
52 bgt 2b
53 ldmeqfd sp!, {r8, pc} @ Now <64 bytes to go.
54 /*
55 * No need to correct the count; we're only testing bits from now on
56 */
57 tst r2, #32
58 stmneia ip!, {r1, r3, r8, lr}
59 stmneia ip!, {r1, r3, r8, lr}
60 tst r2, #16
61 stmneia ip!, {r1, r3, r8, lr}
62 ldmfd sp!, {r8, lr}
63 UNWIND( .fnend )
64
65 #else
66
67 /*
68 * This version aligns the destination pointer in order to write
69 * whole cache lines at once.
70 */
71
72 stmfd sp!, {r4-r8, lr}
73 UNWIND( .fnend )
74 UNWIND( .fnstart )
75 UNWIND( .save {r4-r8, lr} )
76 mov r4, r1
77 mov r5, r1
78 mov r6, r1
79 mov r7, r1
80 mov r8, r1
81 mov lr, r1
82
83 cmp r2, #96
84 tstgt ip, #31
85 ble 3f
86
87 and r8, ip, #31
88 rsb r8, r8, #32
89 sub r2, r2, r8
90 movs r8, r8, lsl #(32 - 4)
91 stmcsia ip!, {r4, r5, r6, r7}
92 stmmiia ip!, {r4, r5}
93 tst r8, #(1 << 30)
94 mov r8, r1
95 strne r1, [ip], #4
96
97 3: subs r2, r2, #64
98 stmgeia ip!, {r1, r3-r8, lr}
99 stmgeia ip!, {r1, r3-r8, lr}
100 bgt 3b
101 ldmeqfd sp!, {r4-r8, pc}
102
103 tst r2, #32
104 stmneia ip!, {r1, r3-r8, lr}
105 tst r2, #16
106 stmneia ip!, {r4-r7}
107 ldmfd sp!, {r4-r8, lr}
108 UNWIND( .fnend )
109
110 #endif
111
112 UNWIND( .fnstart )
113 4: tst r2, #8
114 stmneia ip!, {r1, r3}
115 tst r2, #4
116 strne r1, [ip], #4
117 /*
118 * When we get here, we've got less than 4 bytes to zero. We
119 * may have an unaligned pointer as well.
120 */
121 5: tst r2, #2
122 strneb r1, [ip], #1
123 strneb r1, [ip], #1
124 tst r2, #1
125 strneb r1, [ip], #1
126 ret lr
127
128 6: subs r2, r2, #4 @ 1 do we have enough
129 blt 5b @ 1 bytes to align with?
130 cmp r3, #2 @ 1
131 strltb r1, [ip], #1 @ 1
132 strleb r1, [ip], #1 @ 1
133 strb r1, [ip], #1 @ 1
134 add r2, r2, r3 @ 1 (r2 = r2 - (4 - r3))
135 b 1b
136 UNWIND( .fnend )
137 ENDPROC(memset)
138 ENDPROC(mmioset)
139 EXPORT_SYMBOL(memset)
140 EXPORT_SYMBOL(mmioset)
This page took 0.034359 seconds and 5 git commands to generate.