diff options
Diffstat (limited to 'arch/powerpc/lib/string.S')
-rw-r--r-- | arch/powerpc/lib/string.S | 203 |
1 files changed, 203 insertions, 0 deletions
diff --git a/arch/powerpc/lib/string.S b/arch/powerpc/lib/string.S new file mode 100644 index 000000000000..15d40e9ef8b1 --- /dev/null +++ b/arch/powerpc/lib/string.S | |||
@@ -0,0 +1,203 @@ | |||
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 | ||