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