.
[glibc/history.git] / sysdeps / powerpc / powerpc64 / stpcpy.S
blobcc7a6ab66a31ac6cf72a4ce938f9dee7dd77a755
1 /* Optimized stpcpy implementation for PowerPC64.
2    Copyright (C) 1997, 1999, 2000, 2002, 2004 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] stpcpy (char *dest [r3], const char *src [r4])  */
28 EALIGN (BP_SYM (__stpcpy), 4, 0)
29         CALL_MCOUNT 2
31 #define rTMP    r0
32 #define rRTN    r3
33 #if __BOUNDED_POINTERS__
34 # define rDEST  r4              /* pointer to previous word in dest */
35 # define rSRC   r5              /* pointer to previous word in src */
36 # define rLOW   r11
37 # define rHIGH  r12
38 #else
39 # define rDEST  r3              /* pointer to previous word in dest */
40 # define rSRC   r4              /* pointer to previous word in src */
41 #endif
42 #define rWORD   r6              /* current word from src */
43 #define rFEFE   r7              /* 0xfefefeff */
44 #define r7F7F   r8              /* 0x7f7f7f7f */
45 #define rNEG    r9              /* ~(word in src | 0x7f7f7f7f) */
46 #define rALT    r10             /* alternate word from src */
48         CHECK_BOUNDS_LOW (rSRC, rLOW, rHIGH)
49         CHECK_BOUNDS_LOW (rDEST, rLOW, rHIGH)
50         STORE_RETURN_BOUNDS (rLOW, rHIGH)
52         or      rTMP, rSRC, rDEST
53         clrldi. rTMP, rTMP, 62
54         addi    rDEST, rDEST, -4
55         bne     L(unaligned)
57         lis     rFEFE, -0x101
58         lis     r7F7F, 0x7f7f
59         lwz     rWORD, 0(rSRC)
60         addi    rFEFE, rFEFE, -0x101
61         addi    r7F7F, r7F7F, 0x7f7f
62         b       L(g2)
64 L(g0):  lwzu    rALT, 4(rSRC)
65         stwu    rWORD, 4(rDEST)
66         add     rTMP, rFEFE, rALT
67         nor     rNEG, r7F7F, rALT
68         and.    rTMP, rTMP, rNEG
69         bne-    L(g1)
70         lwzu    rWORD, 4(rSRC)
71         stwu    rALT, 4(rDEST)
72 L(g2):  add     rTMP, rFEFE, rWORD
73         nor     rNEG, r7F7F, rWORD
74         and.    rTMP, rTMP, rNEG
75         beq+    L(g0)
77         mr      rALT, rWORD
78 /* We've hit the end of the string.  Do the rest byte-by-byte.  */
79 L(g1):  rlwinm. rTMP, rALT, 8, 24, 31
80         stbu    rTMP, 4(rDEST)
81         beqlr-
82         rlwinm. rTMP, rALT, 16, 24, 31
83         stbu    rTMP, 1(rDEST)
84         beqlr-
85         rlwinm. rTMP, rALT, 24, 24, 31
86         stbu    rTMP, 1(rDEST)
87         beqlr-
88         stbu    rALT, 1(rDEST)
89         CHECK_BOUNDS_HIGH (rDEST, rHIGH, twlgt)
90         STORE_RETURN_VALUE (rDEST)
91         blr
93 /* Oh well.  In this case, we just do a byte-by-byte copy.  */
94         .align 4
95         nop
96 L(unaligned):
97         lbz     rWORD, 0(rSRC)
98         addi    rDEST, rDEST, 3
99         cmpwi   rWORD, 0
100         beq-    L(u2)
102 L(u0):  lbzu    rALT, 1(rSRC)
103         stbu    rWORD, 1(rDEST)
104         cmpwi   rALT, 0
105         beq-    L(u1)
106         nop             /* Let 601 load start of loop.  */
107         lbzu    rWORD, 1(rSRC)
108         stbu    rALT, 1(rDEST)
109         cmpwi   rWORD, 0
110         bne+    L(u0)
111 L(u2):  stbu    rWORD, 1(rDEST)
112         CHECK_BOUNDS_HIGH (rDEST, rHIGH, twlgt)
113         STORE_RETURN_VALUE (rDEST)
114         blr
115 L(u1):  stbu    rALT, 1(rDEST)
116         CHECK_BOUNDS_HIGH (rDEST, rHIGH, twlgt)
117         STORE_RETURN_VALUE (rDEST)
118         blr
119 END (BP_SYM (__stpcpy))
121 weak_alias (BP_SYM (__stpcpy), BP_SYM (stpcpy))
122 libc_hidden_def (__stpcpy)
123 libc_hidden_builtin_def (stpcpy)