Merge /spare/repo/linux-2.6/
[linux-2.6] / arch / ppc64 / 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 _GLOBAL(strcpy)
16         addi    r5,r3,-1
17         addi    r4,r4,-1
18 1:      lbzu    r0,1(r4)
19         cmpwi   0,r0,0
20         stbu    r0,1(r5)
21         bne     1b
22         blr
23
24 _GLOBAL(strncpy)
25         cmpwi   0,r5,0
26         beqlr
27         mtctr   r5
28         addi    r6,r3,-1
29         addi    r4,r4,-1
30 1:      lbzu    r0,1(r4)
31         cmpwi   0,r0,0
32         stbu    r0,1(r6)
33         bdnzf   2,1b            /* dec ctr, branch if ctr != 0 && !cr0.eq */
34         blr
35
36 _GLOBAL(strcat)
37         addi    r5,r3,-1
38         addi    r4,r4,-1
39 1:      lbzu    r0,1(r5)
40         cmpwi   0,r0,0
41         bne     1b
42         addi    r5,r5,-1
43 1:      lbzu    r0,1(r4)
44         cmpwi   0,r0,0
45         stbu    r0,1(r5)
46         bne     1b
47         blr
48
49 _GLOBAL(strcmp)
50         addi    r5,r3,-1
51         addi    r4,r4,-1
52 1:      lbzu    r3,1(r5)
53         cmpwi   1,r3,0
54         lbzu    r0,1(r4)
55         subf.   r3,r0,r3
56         beqlr   1
57         beq     1b
58         blr
59
60 _GLOBAL(strlen)
61         addi    r4,r3,-1
62 1:      lbzu    r0,1(r4)
63         cmpwi   0,r0,0
64         bne     1b
65         subf    r3,r3,r4
66         blr
67
68 _GLOBAL(memset)
69         neg     r0,r3
70         rlwimi  r4,r4,8,16,23
71         andi.   r0,r0,7                 /* # bytes to be 8-byte aligned */
72         rlwimi  r4,r4,16,0,15
73         cmplw   cr1,r5,r0               /* do we get that far? */
74         rldimi  r4,r4,32,0
75         mtcrf   1,r0
76         mr      r6,r3
77         blt     cr1,8f
78         beq+    3f                      /* if already 8-byte aligned */
79         subf    r5,r0,r5
80         bf      31,1f
81         stb     r4,0(r6)
82         addi    r6,r6,1
83 1:      bf      30,2f
84         sth     r4,0(r6)
85         addi    r6,r6,2
86 2:      bf      29,3f
87         stw     r4,0(r6)
88         addi    r6,r6,4
89 3:      srdi.   r0,r5,6
90         clrldi  r5,r5,58
91         mtctr   r0
92         beq     5f
93 4:      std     r4,0(r6)
94         std     r4,8(r6)
95         std     r4,16(r6)
96         std     r4,24(r6)
97         std     r4,32(r6)
98         std     r4,40(r6)
99         std     r4,48(r6)
100         std     r4,56(r6)
101         addi    r6,r6,64
102         bdnz    4b
103 5:      srwi.   r0,r5,3
104         clrlwi  r5,r5,29
105         mtcrf   1,r0
106         beq     8f
107         bf      29,6f
108         std     r4,0(r6)
109         std     r4,8(r6)
110         std     r4,16(r6)
111         std     r4,24(r6)
112         addi    r6,r6,32
113 6:      bf      30,7f
114         std     r4,0(r6)
115         std     r4,8(r6)
116         addi    r6,r6,16
117 7:      bf      31,8f
118         std     r4,0(r6)
119         addi    r6,r6,8
120 8:      cmpwi   r5,0
121         mtcrf   1,r5
122         beqlr+
123         bf      29,9f
124         stw     r4,0(r6)
125         addi    r6,r6,4
126 9:      bf      30,10f
127         sth     r4,0(r6)
128         addi    r6,r6,2
129 10:     bflr    31
130         stb     r4,0(r6)
131         blr
132
133 _GLOBAL(memmove)
134         cmplw   0,r3,r4
135         bgt     .backwards_memcpy
136         b       .memcpy
137
138 _GLOBAL(backwards_memcpy)
139         rlwinm. r7,r5,32-3,3,31         /* r0 = r5 >> 3 */
140         add     r6,r3,r5
141         add     r4,r4,r5
142         beq     2f
143         andi.   r0,r6,3
144         mtctr   r7
145         bne     5f
146 1:      lwz     r7,-4(r4)
147         lwzu    r8,-8(r4)
148         stw     r7,-4(r6)
149         stwu    r8,-8(r6)
150         bdnz    1b
151         andi.   r5,r5,7
152 2:      cmplwi  0,r5,4
153         blt     3f
154         lwzu    r0,-4(r4)
155         subi    r5,r5,4
156         stwu    r0,-4(r6)
157 3:      cmpwi   0,r5,0
158         beqlr
159         mtctr   r5
160 4:      lbzu    r0,-1(r4)
161         stbu    r0,-1(r6)
162         bdnz    4b
163         blr
164 5:      mtctr   r0
165 6:      lbzu    r7,-1(r4)
166         stbu    r7,-1(r6)
167         bdnz    6b
168         subf    r5,r0,r5
169         rlwinm. r7,r5,32-3,3,31
170         beq     2b
171         mtctr   r7
172         b       1b
173         
174 _GLOBAL(memcmp)
175         cmpwi   0,r5,0
176         ble-    2f
177         mtctr   r5
178         addi    r6,r3,-1
179         addi    r4,r4,-1
180 1:      lbzu    r3,1(r6)
181         lbzu    r0,1(r4)
182         subf.   r3,r0,r3
183         bdnzt   2,1b
184         blr
185 2:      li      r3,0
186         blr
187
188 _GLOBAL(memchr)
189         cmpwi   0,r5,0
190         ble-    2f
191         mtctr   r5
192         addi    r3,r3,-1
193 1:      lbzu    r0,1(r3)
194         cmpw    0,r0,r4
195         bdnzf   2,1b
196         beqlr
197 2:      li      r3,0
198         blr
199
200 _GLOBAL(__clear_user)
201         addi    r6,r3,-4
202         li      r3,0
203         li      r5,0
204         cmplwi  0,r4,4
205         blt     7f
206         /* clear a single word */
207 11:     stwu    r5,4(r6)
208         beqlr
209         /* clear word sized chunks */
210         andi.   r0,r6,3
211         add     r4,r0,r4
212         subf    r6,r0,r6
213         srwi    r0,r4,2
214         andi.   r4,r4,3
215         mtctr   r0
216         bdz     7f
217 1:      stwu    r5,4(r6)
218         bdnz    1b
219         /* clear byte sized chunks */
220 7:      cmpwi   0,r4,0
221         beqlr
222         mtctr   r4
223         addi    r6,r6,3
224 8:      stbu    r5,1(r6)
225         bdnz    8b
226         blr
227 90:     mr      r3,r4
228         blr
229 91:     mfctr   r3
230         slwi    r3,r3,2
231         add     r3,r3,r4
232         blr
233 92:     mfctr   r3
234         blr
235
236         .section __ex_table,"a"
237         .align  3
238         .llong  11b,90b
239         .llong  1b,91b
240         .llong  8b,92b
241         .text
242
243 /* r3 = dst, r4 = src, r5 = count */
244 _GLOBAL(__strncpy_from_user)
245         addi    r6,r3,-1
246         addi    r4,r4,-1
247         cmpwi   0,r5,0
248         beq     2f
249         mtctr   r5
250 1:      lbzu    r0,1(r4)
251         cmpwi   0,r0,0
252         stbu    r0,1(r6)
253         bdnzf   2,1b            /* dec ctr, branch if ctr != 0 && !cr0.eq */
254         beq     3f
255 2:      addi    r6,r6,1
256 3:      subf    r3,r3,r6
257         blr
258 99:     li      r3,-EFAULT
259         blr
260
261         .section __ex_table,"a"
262         .align  3
263         .llong  1b,99b
264         .text
265
266 /* r3 = str, r4 = len (> 0) */
267 _GLOBAL(__strnlen_user)
268         addi    r7,r3,-1
269         mtctr   r4              /* ctr = len */
270 1:      lbzu    r0,1(r7)        /* get next byte */
271         cmpwi   0,r0,0
272         bdnzf   2,1b            /* loop if --ctr != 0 && byte != 0 */
273         addi    r7,r7,1
274         subf    r3,r3,r7        /* number of bytes we have looked at */
275         beqlr                   /* return if we found a 0 byte */
276         cmpw    0,r3,r4         /* did we look at all len bytes? */
277         blt     99f             /* if not, must have hit top */
278         addi    r3,r4,1         /* return len + 1 to indicate no null found */
279         blr
280 99:     li      r3,0            /* bad address, return 0 */
281         blr
282
283         .section __ex_table,"a"
284         .align  3
285         .llong  1b,99b