Update copyright notices with scripts/update-copyrights
[glibc.git] / sysdeps / powerpc / powerpc64 / power7 / strcpy.S
blobce71982eaf504c0369608be336239a222f000603
1 /* Optimized strcpy/stpcpy implementation for PowerPC64/POWER7.
2    Copyright (C) 2013-2014 Free Software Foundation, Inc.
3    This file is part of the GNU C Library.
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.
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.
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/>.  */
19 #include <sysdep.h>
21 /* Implements the function
23    char * [r3] strcpy (char *dest [r3], const char *src [r4])
25    or
27    char * [r3] strcpy (char *dest [r3], const char *src [r4])
29    if USE_AS_STPCPY is defined. It tries to use aligned memory accesses
30    when possible using the following algorithm:
32    if (((((uintptr_t)dst & 0x7UL) == 0) && ((uintptr_t)src & 0x7UL) == 0))
33      goto aligned_doubleword_copy;
34    if (((((uintptr_t)dst & 0x3UL) == 0) && ((uintptr_t)src & 0x3UL) == 0))
35      goto aligned_word_copy;
36    if (((uintptr_t)dst & 0x7UL) == ((uintptr_t)src & 0x7UL))
37      goto same_alignment;
38    goto unaligned;
40    The aligned comparison are made using cmpb instructions.  */
42 #ifdef USE_AS_STPCPY
43 # define FUNC_NAME __stpcpy
44 #else
45 # define FUNC_NAME strcpy
46 #endif
48         .machine  power7
49 EALIGN (FUNC_NAME, 4, 0)
50         CALL_MCOUNT 2
52 #define rTMP    r0
53 #ifdef USE_AS_STPCPY
54 #define rRTN    r3      /* pointer to previous word/doubleword in dest */
55 #else
56 #define rRTN    r12     /* pointer to previous word/doubleword in dest */
57 #endif
58 #define rSRC    r4      /* pointer to previous word/doubleword in src */
59 #define rMASK   r5      /* mask 0xffffffff | 0xffffffffffffffff */
60 #define rWORD   r6      /* current word from src */
61 #define rALT    r7      /* alternate word from src */
62 #define rRTNAL  r8      /* alignment of return pointer */
63 #define rSRCAL  r9      /* alignment of source pointer */
64 #define rALCNT  r10     /* bytes to read to reach 8 bytes alignment */
65 #define rSUBAL  r11     /* doubleword minus unaligned displacement */
67 #ifndef USE_AS_STPCPY
68 /* Save the dst pointer to use as return value.  */
69         mr      rRTN, r3
70 #endif
71         or      rTMP, rSRC, rRTN
72         clrldi. rTMP, rTMP, 61
73         bne     L(check_word_alignment)
74         b       L(aligned_doubleword_copy)
76 L(same_alignment):
77 /* Src and dst with same alignment: align both to doubleword.  */
78         mr      rALCNT, rRTN
79         lbz     rWORD, 0(rSRC)
80         subfic  rSUBAL, rRTNAL, 8
81         addi    rRTN, rRTN, 1
82         addi    rSRC, rSRC, 1
83         cmpdi   cr7, rWORD, 0
84         stb     rWORD, 0(rALCNT)
85         beq     cr7, L(s2)
87         add     rALCNT, rALCNT, rSUBAL
88         subf    rALCNT, rRTN, rALCNT
89         addi    rALCNT, rALCNT, 1
90         mtctr   rALCNT
91         b       L(s1)
93         .align 4
94 L(s0):
95         addi    rSRC, rSRC, 1
96         lbz     rWORD, -1(rSRC)
97         cmpdi   cr7, rWORD, 0
98         stb     rWORD, -1(rALCNT)
99         beqlr   cr7
100         mr      rRTN, rALCNT
101 L(s1):
102         addi    rALCNT, rRTN,1
103         bdnz    L(s0)
104         b L(aligned_doubleword_copy)
105         .align 4
106 L(s2):
107         mr      rRTN, rALCNT
108         blr
110 /* For doubleword aligned memory, operate using doubleword load and stores.  */
111         .align 4
112 L(aligned_doubleword_copy):
113         li      rMASK, 0
114         addi    rRTN, rRTN, -8
115         ld      rWORD, 0(rSRC)
116         b       L(g2)
118         .align 4
119 L(g0):  ldu     rALT, 8(rSRC)
120         stdu    rWORD, 8(rRTN)
121         cmpb    rTMP, rALT, rMASK
122         cmpdi   rTMP, 0
123         bne     L(g1)
124         ldu     rWORD, 8(rSRC)
125         stdu    rALT, 8(rRTN)
126 L(g2):  cmpb    rTMP, rWORD, rMASK
127         cmpdi   rTMP, 0         /* If rTMP is 0, no null's have been found.  */
128         beq     L(g0)
130         mr      rALT, rWORD
131 /* We've hit the end of the string.  Do the rest byte-by-byte.  */
132 L(g1):
133 #ifdef __LITTLE_ENDIAN__
134         extrdi. rTMP, rALT, 8, 56
135         stbu    rALT, 8(rRTN)
136         beqlr-
137         extrdi. rTMP, rALT, 8, 48
138         stbu    rTMP, 1(rRTN)
139         beqlr-
140         extrdi. rTMP, rALT, 8, 40
141         stbu    rTMP, 1(rRTN)
142         beqlr-
143         extrdi. rTMP, rALT, 8, 32
144         stbu    rTMP, 1(rRTN)
145         beqlr-
146         extrdi. rTMP, rALT, 8, 24
147         stbu    rTMP, 1(rRTN)
148         beqlr-
149         extrdi. rTMP, rALT, 8, 16
150         stbu    rTMP, 1(rRTN)
151         beqlr-
152         extrdi. rTMP, rALT, 8, 8
153         stbu    rTMP, 1(rRTN)
154         beqlr-
155         extrdi  rTMP, rALT, 8, 0
156         stbu    rTMP, 1(rRTN)
157 #else
158         extrdi. rTMP, rALT, 8, 0
159         stbu    rTMP, 8(rRTN)
160         beqlr
161         extrdi. rTMP, rALT, 8, 8
162         stbu    rTMP, 1(rRTN)
163         beqlr
164         extrdi. rTMP, rALT, 8, 16
165         stbu    rTMP, 1(rRTN)
166         beqlr
167         extrdi. rTMP, rALT, 8, 24
168         stbu    rTMP, 1(rRTN)
169         beqlr
170         extrdi. rTMP, rALT, 8, 32
171         stbu    rTMP, 1(rRTN)
172         beqlr
173         extrdi. rTMP, rALT, 8, 40
174         stbu    rTMP, 1(rRTN)
175         beqlr
176         extrdi. rTMP, rALT, 8, 48
177         stbu    rTMP, 1(rRTN)
178         beqlr
179         stbu    rALT, 1(rRTN)
180 #endif
181         blr
183 L(check_word_alignment):
184         clrldi. rTMP, rTMP, 62
185         beq     L(aligned_word_copy)
186         rldicl  rRTNAL, rRTN, 0, 61
187         rldicl  rSRCAL, rSRC, 0, 61
188         cmpld   cr7, rSRCAL, rRTNAL
189         beq     cr7, L(same_alignment)
190         b       L(unaligned)
192 /* For word aligned memory, operate using word load and stores.  */
193         .align  4
194 L(aligned_word_copy):
195         li      rMASK, 0
196         addi    rRTN, rRTN, -4
197         lwz     rWORD, 0(rSRC)
198         b       L(g5)
200         .align  4
201 L(g3):  lwzu    rALT, 4(rSRC)
202         stwu    rWORD, 4(rRTN)
203         cmpb    rTMP, rALT, rMASK
204         cmpwi   rTMP, 0
205         bne     L(g4)
206         lwzu    rWORD, 4(rSRC)
207         stwu    rALT, 4(rRTN)
208 L(g5):  cmpb    rTMP, rWORD, rMASK
209         cmpwi   rTMP, 0         /* If rTMP is 0, no null in word.  */
210         beq     L(g3)
212         mr      rALT, rWORD
213 /* We've hit the end of the string.  Do the rest byte-by-byte.  */
214 L(g4):
215 #ifdef __LITTLE_ENDIAN__
216         rlwinm. rTMP, rALT, 0, 24, 31
217         stbu    rALT, 4(rRTN)
218         beqlr-
219         rlwinm. rTMP, rALT, 24, 24, 31
220         stbu    rTMP, 1(rRTN)
221         beqlr-
222         rlwinm. rTMP, rALT, 16, 24, 31
223         stbu    rTMP, 1(rRTN)
224         beqlr-
225         rlwinm  rTMP, rALT, 8, 24, 31
226         stbu    rTMP, 1(rRTN)
227 #else
228         rlwinm. rTMP, rALT, 8, 24, 31
229         stbu    rTMP, 4(rRTN)
230         beqlr
231         rlwinm. rTMP, rALT, 16, 24, 31
232         stbu    rTMP, 1(rRTN)
233         beqlr
234         rlwinm. rTMP, rALT, 24, 24, 31
235         stbu    rTMP, 1(rRTN)
236         beqlr
237         stbu    rALT, 1(rRTN)
238 #endif
239         blr
241 /* Oh well.  In this case, we just do a byte-by-byte copy.  */
242         .align  4
243 L(unaligned):
244         lbz     rWORD, 0(rSRC)
245         addi    rRTN, rRTN, -1
246         cmpdi   rWORD, 0
247         beq     L(u2)
249         .align  5
250 L(u0):  lbzu    rALT, 1(rSRC)
251         stbu    rWORD, 1(rRTN)
252         cmpdi   rALT, 0
253         beq     L(u1)
254         lbzu    rWORD, 1(rSRC)
255         stbu    rALT, 1(rRTN)
256         cmpdi   rWORD, 0
257         beq     L(u2)
258         lbzu    rALT, 1(rSRC)
259         stbu    rWORD, 1(rRTN)
260         cmpdi   rALT, 0
261         beq     L(u1)
262         lbzu    rWORD, 1(rSRC)
263         stbu    rALT, 1(rRTN)
264         cmpdi   rWORD, 0
265         bne     L(u0)
266 L(u2):  stbu    rWORD, 1(rRTN)
267         blr
268 L(u1):  stbu    rALT, 1(rRTN)
269         blr
270 END (FUNC_NAME)
272 #ifndef USE_AS_STPCPY
273 libc_hidden_builtin_def (strcpy)
274 #endif