Update.
[glibc.git] / sysdeps / powerpc / powerpc64 / strcpy.S
blob4d12b82e5e3030be42f75838da32b80bda0dca78
1 /* Optimized strcpy implementation for PowerPC64.
2    Copyright (C) 1997, 1999, 2000, 2002, 2003 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, write to the Free
17    Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
18    02111-1307 USA.  */
20 #include <sysdep.h>
21 #include <bp-sym.h>
22 #include <bp-asm.h>
24 /* See strlen.s for comments on how the end-of-string testing works.  */
26 /* char * [r3] strcpy (char *dest [r3], const char *src [r4])  */
28 EALIGN (BP_SYM (strcpy), 4, 0)
30 #define rTMP    r0
31 #define rRTN    r3      /* incoming DEST arg preserved as result */
32 /* Note.  The Bounded pointer support in this code is broken.  This code
33    was inherited from PPC32 and and that support was never completed.  
34    Current PPC gcc does not support -fbounds-check or -fbounded-pointers.
35    These artifacts are left in the code as a reminder in case we need
36    bounded pointer support in the future.  */
37 #if __BOUNDED_POINTERS__
38 # define rDEST  r4      /* pointer to previous word in dest */
39 # define rSRC   r5      /* pointer to previous word in src */
40 # define rLOW   r11
41 # define rHIGH  r12
42 #else
43 # define rSRC   r4      /* pointer to previous word in src */
44 # define rDEST  r5      /* pointer to previous word in dest */
45 #endif
46 #define rWORD   r6      /* current word from src */
47 #define rFEFE   r7      /* constant 0xfefefefefefefeff (-0x0101010101010101) */
48 #define r7F7F   r8      /* constant 0x7f7f7f7f7f7f7f7f */
49 #define rNEG    r9      /* ~(word in s1 | 0x7f7f7f7f7f7f7f7f) */
50 #define rALT    r10     /* alternate word from src */
52         CHECK_BOUNDS_LOW (rSRC, rLOW, rHIGH)
53         CHECK_BOUNDS_LOW (rDEST, rLOW, rHIGH)
54         STORE_RETURN_BOUNDS (rLOW, rHIGH)
56         dcbt    0,rSRC
57         or      rTMP, rSRC, rRTN
58         clrldi. rTMP, rTMP, 61
59 #if __BOUNDED_POINTERS__
60         addi    rDEST, rDEST, -8
61 #else
62         addi    rDEST, rRTN, -8
63 #endif
64         dcbtst  0,rRTN
65         bne     L(unaligned)
67         lis     rFEFE, -0x101
68         lis     r7F7F, 0x7f7f
69         ld      rWORD, 0(rSRC)
70         addi    rFEFE, rFEFE, -0x101
71         addi    r7F7F, r7F7F, 0x7f7f
72         sldi    rTMP, rFEFE, 32
73         insrdi  r7F7F, r7F7F, 32, 0
74         add     rFEFE, rFEFE, rTMP
75         b       L(g2)
77 L(g0):  ldu     rALT, 8(rSRC)
78         stdu    rWORD, 8(rDEST)
79         add     rTMP, rFEFE, rALT
80         nor     rNEG, r7F7F, rALT
81         and.    rTMP, rTMP, rNEG
82         bne-    L(g1)
83         ldu     rWORD, 8(rSRC)
84         stdu    rALT, 8(rDEST)
85 L(g2):  add     rTMP, rFEFE, rWORD
86         nor     rNEG, r7F7F, rWORD
87         and.    rTMP, rTMP, rNEG
88         beq+    L(g0)
90         mr      rALT, rWORD
91 /* We've hit the end of the string.  Do the rest byte-by-byte.  */
92 L(g1):
93         extrdi. rTMP, rALT, 8, 0
94         stb     rTMP, 8(rDEST)
95         beqlr-
96         extrdi. rTMP, rALT, 8, 8
97         stb     rTMP, 9(rDEST)
98         beqlr-
99         extrdi. rTMP, rALT, 8, 16
100         stb     rTMP, 10(rDEST)
101         beqlr-
102         extrdi. rTMP, rALT, 8, 24
103         stb     rTMP, 11(rDEST)
104         beqlr-
105         extrdi. rTMP, rALT, 8, 32
106         stb     rTMP, 12(rDEST)
107         beqlr-
108         extrdi. rTMP, rALT, 8, 40
109         stb     rTMP, 13(rDEST)
110         beqlr-
111         extrdi. rTMP, rALT, 8, 48
112         stb     rTMP, 14(rDEST)
113         beqlr-
114         stb     rALT, 15(rDEST)
115         /* GKM FIXME: check high bound.  */
116         blr
118 /* Oh well.  In this case, we just do a byte-by-byte copy.  */
119         .align 4
120         nop
121 L(unaligned):
122         lbz     rWORD, 0(rSRC)
123         addi    rDEST, rRTN, -1
124         cmpwi   rWORD, 0
125         beq-    L(u2)
127 L(u0):  lbzu    rALT, 1(rSRC)
128         stbu    rWORD, 1(rDEST)
129         cmpwi   rALT, 0
130         beq-    L(u1)
131         nop             /* Let 601 load start of loop.  */
132         lbzu    rWORD, 1(rSRC)
133         stbu    rALT, 1(rDEST)
134         cmpwi   rWORD, 0
135         bne+    L(u0)
136 L(u2):  stb     rWORD, 1(rDEST)
137         /* GKM FIXME: check high bound.  */
138         blr
139 L(u1):  stb     rALT, 1(rDEST)
140         /* GKM FIXME: check high bound.  */
141         blr
143 END (BP_SYM (strcpy))
144 libc_hidden_builtin_def (strcpy)