]> git.ipfire.org Git - thirdparty/glibc.git/blob - sysdeps/powerpc/powerpc64/strcpy.S
Update copyright dates with scripts/update-copyrights.
[thirdparty/glibc.git] / sysdeps / powerpc / powerpc64 / strcpy.S
1 /* Optimized strcpy implementation for PowerPC64.
2 Copyright (C) 1997-2015 Free Software Foundation, Inc.
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
16 License along with the GNU C Library; if not, see
17 <http://www.gnu.org/licenses/>. */
18
19 #include <sysdep.h>
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
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)
32 CALL_MCOUNT 2
33
34 #define rTMP r0
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 */
41 #define rWORD r6 /* current word from src */
42 #define rFEFE r7 /* constant 0xfefefeff | 0xfefefefefefefeff */
43 #define r7F7F r8 /* constant 0x7f7f7f7f | 0x7f7f7f7f7f7f7f7f */
44 #define rNEG r9 /* ~(word in s1 | r7F7F) */
45 #define rALT r10 /* alternate word from src */
46
47 #ifndef USE_AS_STPCPY
48 /* Save the dst pointer to use as return value. */
49 mr rRTN, r3
50 #endif
51 or rTMP, rSRC, rRTN
52 clrldi. rTMP, rTMP, 61
53 bne L(check_word_alignment)
54
55 /* For doubleword aligned memory, operate using doubleword load and stores. */
56 addi rRTN, rRTN, -8
57
58 lis rFEFE, -0x101
59 lis r7F7F, 0x7f7f
60 ld rWORD, 0(rSRC)
61 addi rFEFE, rFEFE, -0x101
62 addi r7F7F, r7F7F, 0x7f7f
63 sldi rTMP, rFEFE, 32
64 insrdi r7F7F, r7F7F, 32, 0
65 add rFEFE, rFEFE, rTMP
66 b L(g2)
67
68 L(g0): ldu rALT, 8(rSRC)
69 stdu rWORD, 8(rRTN)
70 add rTMP, rFEFE, rALT
71 nor rNEG, r7F7F, rALT
72 and. rTMP, rTMP, rNEG
73 bne- L(g1)
74 ldu rWORD, 8(rSRC)
75 stdu rALT, 8(rRTN)
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. */
83 L(g1):
84 #ifdef __LITTLE_ENDIAN__
85 extrdi. rTMP, rALT, 8, 56
86 stbu rALT, 8(rRTN)
87 beqlr-
88 extrdi. rTMP, rALT, 8, 48
89 stbu rTMP, 1(rRTN)
90 beqlr-
91 extrdi. rTMP, rALT, 8, 40
92 stbu rTMP, 1(rRTN)
93 beqlr-
94 extrdi. rTMP, rALT, 8, 32
95 stbu rTMP, 1(rRTN)
96 beqlr-
97 extrdi. rTMP, rALT, 8, 24
98 stbu rTMP, 1(rRTN)
99 beqlr-
100 extrdi. rTMP, rALT, 8, 16
101 stbu rTMP, 1(rRTN)
102 beqlr-
103 extrdi. rTMP, rALT, 8, 8
104 stbu rTMP, 1(rRTN)
105 beqlr-
106 extrdi rTMP, rALT, 8, 0
107 stbu rTMP, 1(rRTN)
108 #else
109 extrdi. rTMP, rALT, 8, 0
110 stbu rTMP, 8(rRTN)
111 beqlr-
112 extrdi. rTMP, rALT, 8, 8
113 stbu rTMP, 1(rRTN)
114 beqlr-
115 extrdi. rTMP, rALT, 8, 16
116 stbu rTMP, 1(rRTN)
117 beqlr-
118 extrdi. rTMP, rALT, 8, 24
119 stbu rTMP, 1(rRTN)
120 beqlr-
121 extrdi. rTMP, rALT, 8, 32
122 stbu rTMP, 1(rRTN)
123 beqlr
124 extrdi. rTMP, rALT, 8, 40
125 stbu rTMP, 1(rRTN)
126 beqlr-
127 extrdi. rTMP, rALT, 8, 48
128 stbu rTMP, 1(rRTN)
129 beqlr-
130 stbu rALT, 1(rRTN)
131 #endif
132 blr
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)
187 #endif
188 blr
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)
195 addi rRTN, rRTN, -1
196 cmpwi rWORD, 0
197 beq- L(u2)
198
199 L(u0): lbzu rALT, 1(rSRC)
200 stbu rWORD, 1(rRTN)
201 cmpwi rALT, 0
202 beq- L(u1)
203 nop /* Let 601 load start of loop. */
204 lbzu rWORD, 1(rSRC)
205 stbu rALT, 1(rRTN)
206 cmpwi rWORD, 0
207 bne+ L(u0)
208 L(u2): stbu rWORD, 1(rRTN)
209 blr
210 L(u1): stbu rALT, 1(rRTN)
211 blr
212 END (FUNC_NAME)
213
214 #ifndef USE_AS_STPCPY
215 libc_hidden_builtin_def (strcpy)
216 #endif