]>
Commit | Line | Data |
---|---|---|
cfc91acd | 1 | /* Optimized strcpy implementation for PowerPC64. |
b168057a | 2 | Copyright (C) 1997-2015 Free Software Foundation, Inc. |
cfc91acd RM |
3 | This file is part of the GNU C Library. |
4 | ||
5 | The GNU C Library is free software; you can redistribute it and/or | |
6 | modify it under the terms of the GNU Lesser General Public | |
7 | License as published by the Free Software Foundation; either | |
8 | version 2.1 of the License, or (at your option) any later version. | |
9 | ||
10 | The GNU C Library is distributed in the hope that it will be useful, | |
11 | but WITHOUT ANY WARRANTY; without even the implied warranty of | |
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
13 | Lesser General Public License for more details. | |
14 | ||
15 | You should have received a copy of the GNU Lesser General Public | |
59ba27a6 PE |
16 | License along with the GNU C Library; if not, see |
17 | <http://www.gnu.org/licenses/>. */ | |
cfc91acd RM |
18 | |
19 | #include <sysdep.h> | |
cfc91acd RM |
20 | |
21 | /* See strlen.s for comments on how the end-of-string testing works. */ | |
22 | ||
23 | /* char * [r3] strcpy (char *dest [r3], const char *src [r4]) */ | |
24 | ||
69f13dbf AZ |
25 | #ifdef USE_AS_STPCPY |
26 | # define FUNC_NAME __stpcpy | |
27 | #else | |
28 | # define FUNC_NAME strcpy | |
29 | #endif | |
30 | ||
31 | EALIGN (FUNC_NAME, 4, 0) | |
d7d06f79 | 32 | CALL_MCOUNT 2 |
cfc91acd RM |
33 | |
34 | #define rTMP r0 | |
69f13dbf AZ |
35 | #ifdef USE_AS_STPCPY |
36 | #define rRTN r3 /* pointer to previous word/doubleword in dest */ | |
37 | #else | |
38 | #define rRTN r12 /* pointer to previous word/doubleword in dest */ | |
39 | #endif | |
40 | #define rSRC r4 /* pointer to previous word/doubleword in src */ | |
cfc91acd | 41 | #define rWORD r6 /* current word from src */ |
69f13dbf AZ |
42 | #define rFEFE r7 /* constant 0xfefefeff | 0xfefefefefefefeff */ |
43 | #define r7F7F r8 /* constant 0x7f7f7f7f | 0x7f7f7f7f7f7f7f7f */ | |
44 | #define rNEG r9 /* ~(word in s1 | r7F7F) */ | |
cfc91acd RM |
45 | #define rALT r10 /* alternate word from src */ |
46 | ||
69f13dbf AZ |
47 | #ifndef USE_AS_STPCPY |
48 | /* Save the dst pointer to use as return value. */ | |
49 | mr rRTN, r3 | |
50 | #endif | |
cfc91acd | 51 | or rTMP, rSRC, rRTN |
482eb33c | 52 | clrldi. rTMP, rTMP, 61 |
69f13dbf AZ |
53 | bne L(check_word_alignment) |
54 | ||
55 | /* For doubleword aligned memory, operate using doubleword load and stores. */ | |
56 | addi rRTN, rRTN, -8 | |
cfc91acd RM |
57 | |
58 | lis rFEFE, -0x101 | |
59 | lis r7F7F, 0x7f7f | |
482eb33c | 60 | ld rWORD, 0(rSRC) |
cfc91acd RM |
61 | addi rFEFE, rFEFE, -0x101 |
62 | addi r7F7F, r7F7F, 0x7f7f | |
482eb33c UD |
63 | sldi rTMP, rFEFE, 32 |
64 | insrdi r7F7F, r7F7F, 32, 0 | |
65 | add rFEFE, rFEFE, rTMP | |
cfc91acd RM |
66 | b L(g2) |
67 | ||
482eb33c | 68 | L(g0): ldu rALT, 8(rSRC) |
69f13dbf | 69 | stdu rWORD, 8(rRTN) |
cfc91acd RM |
70 | add rTMP, rFEFE, rALT |
71 | nor rNEG, r7F7F, rALT | |
72 | and. rTMP, rTMP, rNEG | |
73 | bne- L(g1) | |
482eb33c | 74 | ldu rWORD, 8(rSRC) |
69f13dbf | 75 | stdu rALT, 8(rRTN) |
cfc91acd RM |
76 | L(g2): add rTMP, rFEFE, rWORD |
77 | nor rNEG, r7F7F, rWORD | |
78 | and. rTMP, rTMP, rNEG | |
79 | beq+ L(g0) | |
80 | ||
81 | mr rALT, rWORD | |
82 | /* We've hit the end of the string. Do the rest byte-by-byte. */ | |
482eb33c | 83 | L(g1): |
43b84013 AM |
84 | #ifdef __LITTLE_ENDIAN__ |
85 | extrdi. rTMP, rALT, 8, 56 | |
69f13dbf | 86 | stbu rALT, 8(rRTN) |
43b84013 AM |
87 | beqlr- |
88 | extrdi. rTMP, rALT, 8, 48 | |
69f13dbf | 89 | stbu rTMP, 1(rRTN) |
43b84013 AM |
90 | beqlr- |
91 | extrdi. rTMP, rALT, 8, 40 | |
69f13dbf | 92 | stbu rTMP, 1(rRTN) |
43b84013 AM |
93 | beqlr- |
94 | extrdi. rTMP, rALT, 8, 32 | |
69f13dbf | 95 | stbu rTMP, 1(rRTN) |
43b84013 AM |
96 | beqlr- |
97 | extrdi. rTMP, rALT, 8, 24 | |
69f13dbf | 98 | stbu rTMP, 1(rRTN) |
43b84013 AM |
99 | beqlr- |
100 | extrdi. rTMP, rALT, 8, 16 | |
69f13dbf | 101 | stbu rTMP, 1(rRTN) |
43b84013 AM |
102 | beqlr- |
103 | extrdi. rTMP, rALT, 8, 8 | |
69f13dbf | 104 | stbu rTMP, 1(rRTN) |
43b84013 AM |
105 | beqlr- |
106 | extrdi rTMP, rALT, 8, 0 | |
69f13dbf | 107 | stbu rTMP, 1(rRTN) |
43b84013 | 108 | #else |
482eb33c | 109 | extrdi. rTMP, rALT, 8, 0 |
69f13dbf | 110 | stbu rTMP, 8(rRTN) |
cfc91acd | 111 | beqlr- |
482eb33c | 112 | extrdi. rTMP, rALT, 8, 8 |
69f13dbf | 113 | stbu rTMP, 1(rRTN) |
cfc91acd | 114 | beqlr- |
482eb33c | 115 | extrdi. rTMP, rALT, 8, 16 |
69f13dbf | 116 | stbu rTMP, 1(rRTN) |
cfc91acd | 117 | beqlr- |
482eb33c | 118 | extrdi. rTMP, rALT, 8, 24 |
69f13dbf | 119 | stbu rTMP, 1(rRTN) |
482eb33c UD |
120 | beqlr- |
121 | extrdi. rTMP, rALT, 8, 32 | |
69f13dbf AZ |
122 | stbu rTMP, 1(rRTN) |
123 | beqlr | |
482eb33c | 124 | extrdi. rTMP, rALT, 8, 40 |
69f13dbf | 125 | stbu rTMP, 1(rRTN) |
482eb33c UD |
126 | beqlr- |
127 | extrdi. rTMP, rALT, 8, 48 | |
69f13dbf | 128 | stbu rTMP, 1(rRTN) |
482eb33c | 129 | beqlr- |
69f13dbf AZ |
130 | stbu rALT, 1(rRTN) |
131 | #endif | |
cfc91acd | 132 | blr |
69f13dbf AZ |
133 | |
134 | L(check_word_alignment): | |
135 | clrldi. rTMP, rTMP, 62 | |
136 | bne L(unaligned) | |
137 | ||
138 | /* For word aligned memory, operate using word load and stores. */ | |
139 | addi rRTN, rRTN, -4 | |
140 | ||
141 | lis rFEFE, -0x101 | |
142 | lis r7F7F, 0x7f7f | |
143 | lwz rWORD, 0(rSRC) | |
144 | addi rFEFE, rFEFE, -0x101 | |
145 | addi r7F7F, r7F7F, 0x7f7f | |
146 | b L(g5) | |
147 | ||
148 | L(g3): lwzu rALT, 4(rSRC) | |
149 | stwu rWORD, 4(rRTN) | |
150 | add rTMP, rFEFE, rALT | |
151 | nor rNEG, r7F7F, rALT | |
152 | and. rTMP, rTMP, rNEG | |
153 | bne- L(g4) | |
154 | lwzu rWORD, 4(rSRC) | |
155 | stwu rALT, 4(rRTN) | |
156 | L(g5): add rTMP, rFEFE, rWORD | |
157 | nor rNEG, r7F7F, rWORD | |
158 | and. rTMP, rTMP, rNEG | |
159 | beq+ L(g3) | |
160 | ||
161 | mr rALT, rWORD | |
162 | /* We've hit the end of the string. Do the rest byte-by-byte. */ | |
163 | L(g4): | |
164 | #ifdef __LITTLE_ENDIAN__ | |
165 | rlwinm. rTMP, rALT, 0, 24, 31 | |
166 | stbu rALT, 4(rRTN) | |
167 | beqlr- | |
168 | rlwinm. rTMP, rALT, 24, 24, 31 | |
169 | stbu rTMP, 1(rRTN) | |
170 | beqlr- | |
171 | rlwinm. rTMP, rALT, 16, 24, 31 | |
172 | stbu rTMP, 1(rRTN) | |
173 | beqlr- | |
174 | rlwinm rTMP, rALT, 8, 24, 31 | |
175 | stbu rTMP, 1(rRTN) | |
176 | #else | |
177 | rlwinm. rTMP, rALT, 8, 24, 31 | |
178 | stbu rTMP, 4(rRTN) | |
179 | beqlr- | |
180 | rlwinm. rTMP, rALT, 16, 24, 31 | |
181 | stbu rTMP, 1(rRTN) | |
182 | beqlr- | |
183 | rlwinm. rTMP, rALT, 24, 24, 31 | |
184 | stbu rTMP, 1(rRTN) | |
185 | beqlr- | |
186 | stbu rALT, 1(rRTN) | |
43b84013 | 187 | #endif |
69f13dbf | 188 | blr |
cfc91acd RM |
189 | |
190 | /* Oh well. In this case, we just do a byte-by-byte copy. */ | |
191 | .align 4 | |
192 | nop | |
193 | L(unaligned): | |
194 | lbz rWORD, 0(rSRC) | |
69f13dbf | 195 | addi rRTN, rRTN, -1 |
cfc91acd RM |
196 | cmpwi rWORD, 0 |
197 | beq- L(u2) | |
198 | ||
199 | L(u0): lbzu rALT, 1(rSRC) | |
69f13dbf | 200 | stbu rWORD, 1(rRTN) |
cfc91acd RM |
201 | cmpwi rALT, 0 |
202 | beq- L(u1) | |
203 | nop /* Let 601 load start of loop. */ | |
204 | lbzu rWORD, 1(rSRC) | |
69f13dbf | 205 | stbu rALT, 1(rRTN) |
cfc91acd RM |
206 | cmpwi rWORD, 0 |
207 | bne+ L(u0) | |
69f13dbf | 208 | L(u2): stbu rWORD, 1(rRTN) |
cfc91acd | 209 | blr |
69f13dbf | 210 | L(u1): stbu rALT, 1(rRTN) |
cfc91acd | 211 | blr |
69f13dbf | 212 | END (FUNC_NAME) |
cfc91acd | 213 | |
69f13dbf | 214 | #ifndef USE_AS_STPCPY |
85dd1003 | 215 | libc_hidden_builtin_def (strcpy) |
69f13dbf | 216 | #endif |