Update copyright notices with scripts/update-copyrights
[glibc.git] / sysdeps / powerpc / powerpc64 / strcpy.S
blob42b39a105a51e42463628046d59358287902a045
1 /* Optimized strcpy implementation for PowerPC64.
2    Copyright (C) 1997-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 /* See strlen.s for comments on how the end-of-string testing works.  */
23 /* char * [r3] strcpy (char *dest [r3], const char *src [r4])  */
25 #ifdef USE_AS_STPCPY
26 # define FUNC_NAME __stpcpy
27 #else
28 # define FUNC_NAME strcpy
29 #endif
31 EALIGN (FUNC_NAME, 4, 0)
32         CALL_MCOUNT 2
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 */
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)
55 /* For doubleword aligned memory, operate using doubleword load and stores.  */
56         addi    rRTN, rRTN, -8
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)
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)
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
134 L(check_word_alignment):
135         clrldi. rTMP, rTMP, 62
136         bne     L(unaligned)
138 /* For word aligned memory, operate using word load and stores.  */
139         addi    rRTN, rRTN, -4
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)
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)
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
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)
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)
214 #ifndef USE_AS_STPCPY
215 libc_hidden_builtin_def (strcpy)
216 #endif