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