84d14d1b118ed35e9ecdf39945b562c61ec98f44
[linux-2.6.git] / 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         rlwimi  r4,r4,8,16,23
70         rlwimi  r4,r4,16,0,15
71         addi    r6,r3,-4
72         cmplwi  0,r5,4
73         blt     7f
74         stwu    r4,4(r6)
75         beqlr
76         andi.   r0,r6,3
77         add     r5,r0,r5
78         subf    r6,r0,r6
79         srwi    r0,r5,2
80         mtctr   r0
81         bdz     6f
82 1:      stwu    r4,4(r6)
83         bdnz    1b
84 6:      andi.   r5,r5,3
85 7:      cmpwi   0,r5,0
86         beqlr
87         mtctr   r5
88         addi    r6,r6,3
89 8:      stbu    r4,1(r6)
90         bdnz    8b
91         blr
92
93 _GLOBAL(memmove)
94         cmplw   0,r3,r4
95         bgt     .backwards_memcpy
96         b       .memcpy
97
98 _GLOBAL(backwards_memcpy)
99         rlwinm. r7,r5,32-3,3,31         /* r0 = r5 >> 3 */
100         add     r6,r3,r5
101         add     r4,r4,r5
102         beq     2f
103         andi.   r0,r6,3
104         mtctr   r7
105         bne     5f
106 1:      lwz     r7,-4(r4)
107         lwzu    r8,-8(r4)
108         stw     r7,-4(r6)
109         stwu    r8,-8(r6)
110         bdnz    1b
111         andi.   r5,r5,7
112 2:      cmplwi  0,r5,4
113         blt     3f
114         lwzu    r0,-4(r4)
115         subi    r5,r5,4
116         stwu    r0,-4(r6)
117 3:      cmpwi   0,r5,0
118         beqlr
119         mtctr   r5
120 4:      lbzu    r0,-1(r4)
121         stbu    r0,-1(r6)
122         bdnz    4b
123         blr
124 5:      mtctr   r0
125 6:      lbzu    r7,-1(r4)
126         stbu    r7,-1(r6)
127         bdnz    6b
128         subf    r5,r0,r5
129         rlwinm. r7,r5,32-3,3,31
130         beq     2b
131         mtctr   r7
132         b       1b
133         
134 _GLOBAL(memcmp)
135         cmpwi   0,r5,0
136         ble-    2f
137         mtctr   r5
138         addi    r6,r3,-1
139         addi    r4,r4,-1
140 1:      lbzu    r3,1(r6)
141         lbzu    r0,1(r4)
142         subf.   r3,r0,r3
143         bdnzt   2,1b
144         blr
145 2:      li      r3,0
146         blr
147
148 _GLOBAL(memchr)
149         cmpwi   0,r5,0
150         ble-    2f
151         mtctr   r5
152         addi    r3,r3,-1
153 1:      lbzu    r0,1(r3)
154         cmpw    0,r0,r4
155         bdnzf   2,1b
156         beqlr
157 2:      li      r3,0
158         blr
159
160 _GLOBAL(__clear_user)
161         addi    r6,r3,-4
162         li      r3,0
163         li      r5,0
164         cmplwi  0,r4,4
165         blt     7f
166         /* clear a single word */
167 11:     stwu    r5,4(r6)
168         beqlr
169         /* clear word sized chunks */
170         andi.   r0,r6,3
171         add     r4,r0,r4
172         subf    r6,r0,r6
173         srwi    r0,r4,2
174         andi.   r4,r4,3
175         mtctr   r0
176         bdz     7f
177 1:      stwu    r5,4(r6)
178         bdnz    1b
179         /* clear byte sized chunks */
180 7:      cmpwi   0,r4,0
181         beqlr
182         mtctr   r4
183         addi    r6,r6,3
184 8:      stbu    r5,1(r6)
185         bdnz    8b
186         blr
187 90:     mr      r3,r4
188         blr
189 91:     mfctr   r3
190         slwi    r3,r3,2
191         add     r3,r3,r4
192         blr
193 92:     mfctr   r3
194         blr
195
196         .section __ex_table,"a"
197         .align  3
198         .llong  11b,90b
199         .llong  1b,91b
200         .llong  8b,92b
201         .text
202
203 /* r3 = dst, r4 = src, r5 = count */
204 _GLOBAL(__strncpy_from_user)
205         addi    r6,r3,-1
206         addi    r4,r4,-1
207         cmpwi   0,r5,0
208         beq     2f
209         mtctr   r5
210 1:      lbzu    r0,1(r4)
211         cmpwi   0,r0,0
212         stbu    r0,1(r6)
213         bdnzf   2,1b            /* dec ctr, branch if ctr != 0 && !cr0.eq */
214         beq     3f
215 2:      addi    r6,r6,1
216 3:      subf    r3,r3,r6
217         blr
218 99:     li      r3,-EFAULT
219         blr
220
221         .section __ex_table,"a"
222         .align  3
223         .llong  1b,99b
224         .text
225
226 /* r3 = str, r4 = len (> 0) */
227 _GLOBAL(__strnlen_user)
228         addi    r7,r3,-1
229         mtctr   r4              /* ctr = len */
230 1:      lbzu    r0,1(r7)        /* get next byte */
231         cmpwi   0,r0,0
232         bdnzf   2,1b            /* loop if --ctr != 0 && byte != 0 */
233         addi    r7,r7,1
234         subf    r3,r3,r7        /* number of bytes we have looked at */
235         beqlr                   /* return if we found a 0 byte */
236         cmpw    0,r3,r4         /* did we look at all len bytes? */
237         blt     99f             /* if not, must have hit top */
238         addi    r3,r4,1         /* return len + 1 to indicate no null found */
239         blr
240 99:     li      r3,0            /* bad address, return 0 */
241         blr
242
243         .section __ex_table,"a"
244         .align  3
245         .llong  1b,99b