Import 2.3.28
[davej-history.git] / arch / ppc / lib / string.S
blob4ab90f8b748c11a8a32779ca1effa66a0c4f2c6e
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 "../kernel/ppc_asm.tmpl"
12 #include <asm/processor.h>
13 #include <asm/errno.h>
15         .globl  strcpy
16 strcpy:
17         addi    r5,r3,-1
18         addi    r4,r4,-1
19 1:      lbzu    r0,1(r4)
20         cmpwi   0,r0,0
21         stbu    r0,1(r5)
22         bne     1b
23         blr
25         .globl  strncpy
26 strncpy:
27         cmpwi   0,r5,0
28         beqlr
29         mtctr   r5
30         addi    r6,r3,-1
31         addi    r4,r4,-1
32 1:      lbzu    r0,1(r4)
33         cmpwi   0,r0,0
34         stbu    r0,1(r6)
35         bdnzf   2,1b            /* dec ctr, branch if ctr != 0 && !cr0.eq */
36         blr
38         .globl  strcat
39 strcat:
40         addi    r5,r3,-1
41         addi    r4,r4,-1
42 1:      lbzu    r0,1(r5)
43         cmpwi   0,r0,0
44         bne     1b
45         addi    r5,r5,-1
46 1:      lbzu    r0,1(r4)
47         cmpwi   0,r0,0
48         stbu    r0,1(r5)
49         bne     1b
50         blr
52         .globl  strcmp
53 strcmp:
54         addi    r5,r3,-1
55         addi    r4,r4,-1
56 1:      lbzu    r3,1(r5)
57         cmpwi   1,r3,0
58         lbzu    r0,1(r4)
59         subf.   r3,r0,r3
60         beqlr   1
61         beq     1b
62         blr
64         .globl  strlen
65 strlen:
66         addi    r4,r3,-1
67 1:      lbzu    r0,1(r4)
68         cmpwi   0,r0,0
69         bne     1b
70         subf    r3,r3,r4
71         blr
73         .globl  memset
74 memset:
75         rlwimi  r4,r4,8,16,23
76         rlwimi  r4,r4,16,0,15
77         addi    r6,r3,-4
78         cmplwi  0,r5,4
79         blt     7f
80         stwu    r4,4(r6)
81         beqlr
82         andi.   r0,r6,3
83         add     r5,r0,r5
84         subf    r6,r0,r6
85         rlwinm  r0,r5,32-2,2,31
86         mtctr   r0
87         bdz     6f
88 1:      stwu    r4,4(r6)
89         bdnz    1b
90 6:      andi.   r5,r5,3
91 7:      cmpwi   0,r5,0
92         beqlr
93         mtctr   r5
94         addi    r6,r6,3
95 8:      stbu    r4,1(r6)
96         bdnz    8b
97         blr
99         .globl  bcopy
100 bcopy:
101         mr      r6,r3
102         mr      r3,r4
103         mr      r4,r6
104         b       memcpy
106         .globl  memmove
107 memmove:
108         cmplw   0,r3,r4
109         bgt     backwards_memcpy
110         /* fall through */
112         .globl  memcpy
113 memcpy:
114         rlwinm. r7,r5,32-3,3,31         /* r0 = r5 >> 3 */
115         addi    r6,r3,-4
116         addi    r4,r4,-4
117         beq     2f                      /* if less than 8 bytes to do */
118         andi.   r0,r6,3                 /* get dest word aligned */
119         mtctr   r7
120         bne     5f
121 1:      lwz     r7,4(r4)
122         lwzu    r8,8(r4)
123         stw     r7,4(r6)
124         stwu    r8,8(r6)
125         bdnz    1b
126         andi.   r5,r5,7
127 2:      cmplwi  0,r5,4
128         blt     3f
129         lwzu    r0,4(r4)
130         addi    r5,r5,-4
131         stwu    r0,4(r6)
132 3:      cmpwi   0,r5,0
133         beqlr
134         mtctr   r5
135         addi    r4,r4,3
136         addi    r6,r6,3
137 4:      lbzu    r0,1(r4)
138         stbu    r0,1(r6)
139         bdnz    4b
140         blr
141 5:      subfic  r0,r0,4
142         mtctr   r0
143 6:      lbz     r7,4(r4)
144         addi    r4,r4,1
145         stb     r7,4(r6)
146         addi    r6,r6,1
147         bdnz    6b
148         subf    r5,r0,r5
149         rlwinm. r7,r5,32-3,3,31
150         beq     2b
151         mtctr   r7
152         b       1b
154         .globl  backwards_memcpy
155 backwards_memcpy:
156         rlwinm. r7,r5,32-3,3,31         /* r0 = r5 >> 3 */
157         add     r6,r3,r5
158         add     r4,r4,r5
159         beq     2f
160         andi.   r0,r6,3
161         mtctr   r7
162         bne     5f
163 1:      lwz     r7,-4(r4)
164         lwzu    r8,-8(r4)
165         stw     r7,-4(r6)
166         stwu    r8,-8(r6)
167         bdnz    1b
168         andi.   r5,r5,7
169 2:      cmplwi  0,r5,4
170         blt     3f
171         lwzu    r0,-4(r4)
172         subi    r5,r5,4
173         stwu    r0,-4(r6)
174 3:      cmpwi   0,r5,0
175         beqlr
176         mtctr   r5
177 4:      lbzu    r0,-1(r4)
178         stbu    r0,-1(r6)
179         bdnz    4b
180         blr
181 5:      mtctr   r0
182 6:      lbzu    r7,-1(r4)
183         stbu    r7,-1(r6)
184         bdnz    6b
185         subf    r5,r0,r5
186         rlwinm. r7,r5,32-3,3,31
187         beq     2b
188         mtctr   r7
189         b       1b
190         
191         .globl  memcmp
192 memcmp:
193         cmpwi   0,r5,0
194         ble-    2f
195         mtctr   r5
196         addi    r6,r3,-1
197         addi    r4,r4,-1
198 1:      lbzu    r3,1(r6)
199         lbzu    r0,1(r4)
200         subf.   r3,r0,r3
201         bdnzt   2,1b
202         blr
203 2:      li      r3,0
204         blr
206         .global memchr
207 memchr:
208         cmpwi   0,r5,0
209         ble-    2f
210         mtctr   r5
211         addi    r3,r3,-1
212 1:      lbzu    r0,1(r3)
213         cmpw    0,r0,r4
214         bdnzf   2,1b
215         beqlr
216 2:      li      r3,0
217         blr
219         .globl  __copy_tofrom_user
220 __copy_tofrom_user:
221         srwi.   r7,r5,3
222         addi    r6,r3,-4
223         addi    r4,r4,-4
224         li      r3,0            /* success return value */
225         beq     2f              /* if less than 8 bytes to do */
226         andi.   r0,r6,3         /* get dest word aligned */
227         mtctr   r7
228         bne     5f
229 1:      lwz     r7,4(r4)
230 11:     lwzu    r8,8(r4)
231 12:     stw     r7,4(r6)
232 13:     stwu    r8,8(r6)
233         bdnz    1b
234         andi.   r5,r5,7
235 2:      cmplwi  0,r5,4
236         blt     3f
237 14:     lwzu    r0,4(r4)
238         addi    r5,r5,-4
239 15:     stwu    r0,4(r6)
240 3:      cmpwi   0,r5,0          /* do 1 byte at a time for the remainder */
241         beqlr
242         mtctr   r5
243         addi    r4,r4,3
244         addi    r6,r6,3
245 4:      lbzu    r0,1(r4)
246 16:     stbu    r0,1(r6)
247         bdnz    4b
248         blr
249 5:      subfic  r0,r0,4         /* copy bytes until we have the */
250         mtctr   r0              /* destination 4-byte aligned */
251         subf    r5,r0,r5
252 6:      lbz     r7,4(r4)
253         addi    r4,r4,1
254 17:     stb     r7,4(r6)
255         addi    r6,r6,1
256         bdnz    6b
257         srwi.   r7,r5,3
258         beq     2b
259         mtctr   r7
260         b       1b
261 /* we come here on a fault in the 8-byte-at-a-time loop */
262 88:     subi    r4,r4,8         /* compensate for the lwzu */
263 98:     mfctr   r0
264         rlwimi  r5,r0,3,0,28    /* use the byte-at-a-time loop to */
265         b       3b              /* copy up to the byte at fault */
266 /* here on a write fault in the single-word copy */
267 96:     subi    r4,r4,4
268         b       3b
269 /* here on a read fault in the initial single-byte copy */
270 90:     mfctr   r3
271         add     r3,r3,r5
272         b       70f
273 /* here on a read fault in the final single-byte copy */
274 99:     mfctr   r3
275         subi    r6,r6,3
276 /* clear out the rest of the destination: r3 bytes starting at 4(r6) */
277 70:     li      r0,0
278         mr.     r5,r3
279         beq     76f
280 71:     andi.   r4,r6,3
281         beq     72f
282 77:     stb     r0,4(r6)
283         addi    r6,r6,1
284         addic.  r5,r5,-1
285         bne     71b
286 72:     srwi.   r7,r5,2
287         beq     73f
288         mtctr   r7
289 74:     stwu    r0,4(r6)
290         bdnz    74b
291 73:     andi.   r5,r5,3
292         beq     76f
293         mtctr   r5
294         addi    r6,r6,3
295 75:     stbu    r0,1(r6)
296         bdnz    75b
297 76:     blr
298 /* here on a write fault in the initial single-byte copy */
299 80:     mfctr   r3
300         add     r3,r3,r5
301         blr
302 /* here on a write fault in the final single-byte copy */
303 81:     mfctr   r3
304         blr
306 .section __ex_table,"a"
307         .align  2
308         .long   1b,98b
309         .long   11b,98b
310         .long   12b,88b
311         .long   13b,88b
312         .long   14b,3b
313         .long   15b,96b
314         .long   4b,99b
315         .long   16b,81b
316         .long   6b,90b
317         .long   17b,80b
318         .long   77b,76b
319         .long   74b,76b
320         .long   75b,76b
321 .text
323         .globl  __clear_user
324 __clear_user:
325         addi    r6,r3,-4
326         li      r3,0
327         li      r5,0
328         cmplwi  0,r4,4
329         blt     7f
330         /* clear a single word */
331 11:     stwu    r5,4(r6)
332         beqlr
333         /* clear word sized chunks */
334         andi.   r0,r6,3
335         add     r4,r0,r4
336         subf    r6,r0,r6
337         /*rlwinm        r0,r4,32-2,2,31*/
338         srwi    r0,r4,2
339         mtctr   r0
340         bdz     6f
341 1:      stwu    r5,4(r6)
342         bdnz    1b
343 6:      andi.   r4,r4,3
344         /* clear byte sized chunks */
345 7:      cmpwi   0,r4,0
346         beqlr
347         mtctr   r4
348         addi    r6,r6,3
349 8:      stbu    r5,1(r6)
350         bdnz    8b
351         blr
352 99:     li      r3,-EFAULT
353         blr
354 .section __ex_table,"a"
355         .align  2
356         .long   11b,99b
357         .long   1b,99b
358         .long   8b,99b
359 .text
361         .globl  __strncpy_from_user
362 __strncpy_from_user:
363         addi    r6,r3,-1
364         addi    r4,r4,-1
365         cmpwi   0,r5,0
366         beq     2f
367         mtctr   r5
368 1:      lbzu    r0,1(r4)
369         cmpwi   0,r0,0
370         stbu    r0,1(r6)
371         bdnzf   2,1b            /* dec ctr, branch if ctr != 0 && !cr0.eq */
372         beq     3f
373 2:      addi    r6,r6,1
374 3:      subf    r3,r3,r6
375         blr
376 99:     li      r3,-EFAULT
377         blr
378 .section __ex_table,"a"
379         .align  2
380         .long   1b,99b
381 .text
383 /* r3 = str, r4 = len (> 0), r5 = top (highest addr) */
384         .globl  __strnlen_user
385 __strnlen_user:
386         addi    r7,r3,-1
387         subf    r6,r7,r5        /* top+1 - str */
388         cmplw   0,r4,r6
389         bge     0f
390         mr      r6,r4
391 0:      mtctr   r6              /* ctr = min(len, top - str) */
392 1:      lbzu    r0,1(r7)        /* get next byte */
393         cmpwi   0,r0,0
394         bdnzf   2,1b            /* loop if --ctr != 0 && byte != 0 */
395         addi    r7,r7,1
396         subf    r3,r3,r7        /* number of bytes we have looked at */
397         beqlr                   /* return if we found a 0 byte */
398         cmpw    0,r3,r4         /* did we look at all len bytes? */
399         blt     99f             /* if not, must have hit top */
400         addi    r3,r4,1         /* return len + 1 to indicate no null found */
401         blr
402 99:     li      r3,0            /* bad address, return 0 */
403         blr
404 .section __ex_table,"a"
405         .align  2
406         .long   1b,99b