Merge branch 'devel' of master.kernel.org:/home/rmk/linux-2.6-arm
[GitHub/mt8127/android_kernel_alcatel_ttab.git] / arch / powerpc / lib / string.S
1 /*
2 * String handling functions for PowerPC.
3 *
4 * Copyright (C) 1996 Paul Mackerras.
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version
9 * 2 of the License, or (at your option) any later version.
10 */
11 #include <asm/processor.h>
12 #include <asm/errno.h>
13 #include <asm/ppc_asm.h>
14
15 .section __ex_table,"a"
16 #ifdef CONFIG_PPC64
17 .align 3
18 #define EXTBL .llong
19 #else
20 .align 2
21 #define EXTBL .long
22 #endif
23 .text
24
25 _GLOBAL(strcpy)
26 addi r5,r3,-1
27 addi r4,r4,-1
28 1: lbzu r0,1(r4)
29 cmpwi 0,r0,0
30 stbu r0,1(r5)
31 bne 1b
32 blr
33
34 /* This clears out any unused part of the destination buffer,
35 just as the libc version does. -- paulus */
36 _GLOBAL(strncpy)
37 cmpwi 0,r5,0
38 beqlr
39 mtctr r5
40 addi r6,r3,-1
41 addi r4,r4,-1
42 1: lbzu r0,1(r4)
43 cmpwi 0,r0,0
44 stbu r0,1(r6)
45 bdnzf 2,1b /* dec ctr, branch if ctr != 0 && !cr0.eq */
46 bnelr /* if we didn't hit a null char, we're done */
47 mfctr r5
48 cmpwi 0,r5,0 /* any space left in destination buffer? */
49 beqlr /* we know r0 == 0 here */
50 2: stbu r0,1(r6) /* clear it out if so */
51 bdnz 2b
52 blr
53
54 _GLOBAL(strcat)
55 addi r5,r3,-1
56 addi r4,r4,-1
57 1: lbzu r0,1(r5)
58 cmpwi 0,r0,0
59 bne 1b
60 addi r5,r5,-1
61 1: lbzu r0,1(r4)
62 cmpwi 0,r0,0
63 stbu r0,1(r5)
64 bne 1b
65 blr
66
67 _GLOBAL(strcmp)
68 addi r5,r3,-1
69 addi r4,r4,-1
70 1: lbzu r3,1(r5)
71 cmpwi 1,r3,0
72 lbzu r0,1(r4)
73 subf. r3,r0,r3
74 beqlr 1
75 beq 1b
76 blr
77
78 _GLOBAL(strlen)
79 addi r4,r3,-1
80 1: lbzu r0,1(r4)
81 cmpwi 0,r0,0
82 bne 1b
83 subf r3,r3,r4
84 blr
85
86 _GLOBAL(memcmp)
87 cmpwi 0,r5,0
88 ble- 2f
89 mtctr r5
90 addi r6,r3,-1
91 addi r4,r4,-1
92 1: lbzu r3,1(r6)
93 lbzu r0,1(r4)
94 subf. r3,r0,r3
95 bdnzt 2,1b
96 blr
97 2: li r3,0
98 blr
99
100 _GLOBAL(memchr)
101 cmpwi 0,r5,0
102 ble- 2f
103 mtctr r5
104 addi r3,r3,-1
105 1: lbzu r0,1(r3)
106 cmpw 0,r0,r4
107 bdnzf 2,1b
108 beqlr
109 2: li r3,0
110 blr
111
112 _GLOBAL(__clear_user)
113 addi r6,r3,-4
114 li r3,0
115 li r5,0
116 cmplwi 0,r4,4
117 blt 7f
118 /* clear a single word */
119 11: stwu r5,4(r6)
120 beqlr
121 /* clear word sized chunks */
122 andi. r0,r6,3
123 add r4,r0,r4
124 subf r6,r0,r6
125 srwi r0,r4,2
126 andi. r4,r4,3
127 mtctr r0
128 bdz 7f
129 1: stwu r5,4(r6)
130 bdnz 1b
131 /* clear byte sized chunks */
132 7: cmpwi 0,r4,0
133 beqlr
134 mtctr r4
135 addi r6,r6,3
136 8: stbu r5,1(r6)
137 bdnz 8b
138 blr
139 90: mr r3,r4
140 blr
141 91: mfctr r3
142 slwi r3,r3,2
143 add r3,r3,r4
144 blr
145 92: mfctr r3
146 blr
147
148 .section __ex_table,"a"
149 EXTBL 11b,90b
150 EXTBL 1b,91b
151 EXTBL 8b,92b
152 .text
153
154 _GLOBAL(__strncpy_from_user)
155 addi r6,r3,-1
156 addi r4,r4,-1
157 cmpwi 0,r5,0
158 beq 2f
159 mtctr r5
160 1: lbzu r0,1(r4)
161 cmpwi 0,r0,0
162 stbu r0,1(r6)
163 bdnzf 2,1b /* dec ctr, branch if ctr != 0 && !cr0.eq */
164 beq 3f
165 2: addi r6,r6,1
166 3: subf r3,r3,r6
167 blr
168 99: li r3,-EFAULT
169 blr
170
171 .section __ex_table,"a"
172 EXTBL 1b,99b
173 .text
174
175 /* r3 = str, r4 = len (> 0), r5 = top (highest addr) */
176 _GLOBAL(__strnlen_user)
177 addi r7,r3,-1
178 subf r6,r7,r5 /* top+1 - str */
179 cmplw 0,r4,r6
180 bge 0f
181 mr r6,r4
182 0: mtctr r6 /* ctr = min(len, top - str) */
183 1: lbzu r0,1(r7) /* get next byte */
184 cmpwi 0,r0,0
185 bdnzf 2,1b /* loop if --ctr != 0 && byte != 0 */
186 addi r7,r7,1
187 subf r3,r3,r7 /* number of bytes we have looked at */
188 beqlr /* return if we found a 0 byte */
189 cmpw 0,r3,r4 /* did we look at all len bytes? */
190 blt 99f /* if not, must have hit top */
191 addi r3,r4,1 /* return len + 1 to indicate no null found */
192 blr
193 99: li r3,0 /* bad address, return 0 */
194 blr
195
196 .section __ex_table,"a"
197 EXTBL 1b,99b