Merge git://git.kernel.org/pub/scm/linux/kernel/git/brodo/pcmcia-2.6
[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 #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(strncmp)
79         PPC_LCMPI r5,0
80         beqlr
81         mtctr   r5
82         addi    r5,r3,-1
83         addi    r4,r4,-1
84 1:      lbzu    r3,1(r5)
85         cmpwi   1,r3,0
86         lbzu    r0,1(r4)
87         subf.   r3,r0,r3
88         beqlr   1
89         bdnzt   eq,1b
90         blr
91
92 _GLOBAL(strlen)
93         addi    r4,r3,-1
94 1:      lbzu    r0,1(r4)
95         cmpwi   0,r0,0
96         bne     1b
97         subf    r3,r3,r4
98         blr
99
100 _GLOBAL(memcmp)
101         cmpwi   0,r5,0
102         ble-    2f
103         mtctr   r5
104         addi    r6,r3,-1
105         addi    r4,r4,-1
106 1:      lbzu    r3,1(r6)
107         lbzu    r0,1(r4)
108         subf.   r3,r0,r3
109         bdnzt   2,1b
110         blr
111 2:      li      r3,0
112         blr
113
114 _GLOBAL(memchr)
115         cmpwi   0,r5,0
116         ble-    2f
117         mtctr   r5
118         addi    r3,r3,-1
119 1:      lbzu    r0,1(r3)
120         cmpw    0,r0,r4
121         bdnzf   2,1b
122         beqlr
123 2:      li      r3,0
124         blr
125
126 _GLOBAL(__clear_user)
127         addi    r6,r3,-4
128         li      r3,0
129         li      r5,0
130         cmplwi  0,r4,4
131         blt     7f
132         /* clear a single word */
133 11:     stwu    r5,4(r6)
134         beqlr
135         /* clear word sized chunks */
136         andi.   r0,r6,3
137         add     r4,r0,r4
138         subf    r6,r0,r6
139         srwi    r0,r4,2
140         andi.   r4,r4,3
141         mtctr   r0
142         bdz     7f
143 1:      stwu    r5,4(r6)
144         bdnz    1b
145         /* clear byte sized chunks */
146 7:      cmpwi   0,r4,0
147         beqlr
148         mtctr   r4
149         addi    r6,r6,3
150 8:      stbu    r5,1(r6)
151         bdnz    8b
152         blr
153 90:     mr      r3,r4
154         blr
155 91:     mfctr   r3
156         slwi    r3,r3,2
157         add     r3,r3,r4
158         blr
159 92:     mfctr   r3
160         blr
161
162         .section __ex_table,"a"
163         EXTBL   11b,90b
164         EXTBL   1b,91b
165         EXTBL   8b,92b
166         .text
167
168 _GLOBAL(__strncpy_from_user)
169         addi    r6,r3,-1
170         addi    r4,r4,-1
171         cmpwi   0,r5,0
172         beq     2f
173         mtctr   r5
174 1:      lbzu    r0,1(r4)
175         cmpwi   0,r0,0
176         stbu    r0,1(r6)
177         bdnzf   2,1b            /* dec ctr, branch if ctr != 0 && !cr0.eq */
178         beq     3f
179 2:      addi    r6,r6,1
180 3:      subf    r3,r3,r6
181         blr
182 99:     li      r3,-EFAULT
183         blr
184
185         .section __ex_table,"a"
186         EXTBL   1b,99b
187         .text
188
189 /* r3 = str, r4 = len (> 0), r5 = top (highest addr) */
190 _GLOBAL(__strnlen_user)
191         addi    r7,r3,-1
192         subf    r6,r7,r5        /* top+1 - str */
193         cmplw   0,r4,r6
194         bge     0f
195         mr      r6,r4
196 0:      mtctr   r6              /* ctr = min(len, top - str) */
197 1:      lbzu    r0,1(r7)        /* get next byte */
198         cmpwi   0,r0,0
199         bdnzf   2,1b            /* loop if --ctr != 0 && byte != 0 */
200         addi    r7,r7,1
201         subf    r3,r3,r7        /* number of bytes we have looked at */
202         beqlr                   /* return if we found a 0 byte */
203         cmpw    0,r3,r4         /* did we look at all len bytes? */
204         blt     99f             /* if not, must have hit top */
205         addi    r3,r4,1         /* return len + 1 to indicate no null found */
206         blr
207 99:     li      r3,0            /* bad address, return 0 */
208         blr
209
210         .section __ex_table,"a"
211         EXTBL   1b,99b