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