Update to LGPL v2.1.
[kopensolaris-gnu/glibc.git] / sysdeps / powerpc / stpcpy.S
1 /* Optimized stpcpy implementation for PowerPC.
2    Copyright (C) 1997, 1999, 2000 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, write to the Free
17    Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
18    02111-1307 USA.  */
19
20 #include <sysdep.h>
21 #include <bp-sym.h>
22 #include <bp-asm.h>
23
24 /* See strlen.s for comments on how the end-of-string testing works.  */
25
26 /* char * [r3] stpcpy (char *dest [r3], const char *src [r4])  */
27
28 EALIGN (BP_SYM (__stpcpy), 4, 0)
29
30 #define rTMP    r0
31 #define rRTN    r3
32 #if __BOUNDED_POINTERS__
33 # define rDEST  r4              /* pointer to previous word in dest */
34 # define rSRC   r5              /* pointer to previous word in src */
35 # define rLOW   r11
36 # define rHIGH  r12
37 #else
38 # define rDEST  r3              /* pointer to previous word in dest */
39 # define rSRC   r4              /* pointer to previous word in src */
40 #endif
41 #define rWORD   r6              /* current word from src */
42 #define rFEFE   r7              /* 0xfefefeff */
43 #define r7F7F   r8              /* 0x7f7f7f7f */
44 #define rNEG    r9              /* ~(word in src | 0x7f7f7f7f) */
45 #define rALT    r10             /* alternate word from src */
46
47         CHECK_BOUNDS_LOW (rSRC, rLOW, rHIGH)
48         CHECK_BOUNDS_LOW (rDEST, rLOW, rHIGH)
49         STORE_RETURN_BOUNDS (rLOW, rHIGH)
50
51         or      rTMP, rSRC, rDEST
52         clrlwi. rTMP, rTMP, 30
53         addi    rDEST, rDEST, -4
54         bne     L(unaligned)
55
56         lis     rFEFE, -0x101
57         lis     r7F7F, 0x7f7f
58         lwz     rWORD, 0(rSRC)
59         addi    rFEFE, rFEFE, -0x101
60         addi    r7F7F, r7F7F, 0x7f7f
61         b       L(g2)
62
63 L(g0):  lwzu    rALT, 4(rSRC)
64         stwu    rWORD, 4(rDEST)
65         add     rTMP, rFEFE, rALT
66         nor     rNEG, r7F7F, rALT
67         and.    rTMP, rTMP, rNEG
68         bne-    L(g1)
69         lwzu    rWORD, 4(rSRC)
70         stwu    rALT, 4(rDEST)
71 L(g2):  add     rTMP, rFEFE, rWORD
72         nor     rNEG, r7F7F, rWORD
73         and.    rTMP, rTMP, rNEG
74         beq+    L(g0)
75
76         mr      rALT, rWORD
77 /* We've hit the end of the string.  Do the rest byte-by-byte.  */
78 L(g1):  rlwinm. rTMP, rALT, 8, 24, 31
79         stbu    rTMP, 4(rDEST)
80         beqlr-
81         rlwinm. rTMP, rALT, 16, 24, 31
82         stbu    rTMP, 1(rDEST)
83         beqlr-
84         rlwinm. rTMP, rALT, 24, 24, 31
85         stbu    rTMP, 1(rDEST)
86         beqlr-
87         stbu    rALT, 1(rDEST)
88         CHECK_BOUNDS_HIGH (rDEST, rHIGH, twlgt)
89         STORE_RETURN_VALUE (rDEST)
90         blr
91
92 /* Oh well.  In this case, we just do a byte-by-byte copy.  */
93         .align 4
94         nop
95 L(unaligned):
96         lbz     rWORD, 0(rSRC)
97         addi    rDEST, rDEST, 3
98         cmpwi   rWORD, 0
99         beq-    L(u2)
100
101 L(u0):  lbzu    rALT, 1(rSRC)
102         stbu    rWORD, 1(rDEST)
103         cmpwi   rALT, 0
104         beq-    L(u1)
105         nop             /* Let 601 load start of loop.  */
106         lbzu    rWORD, 1(rSRC)
107         stbu    rALT, 1(rDEST)
108         cmpwi   rWORD, 0
109         bne+    L(u0)
110 L(u2):  stbu    rWORD, 1(rDEST)
111         CHECK_BOUNDS_HIGH (rDEST, rHIGH, twlgt)
112         STORE_RETURN_VALUE (rDEST)
113         blr
114 L(u1):  stbu    rALT, 1(rDEST)
115         CHECK_BOUNDS_HIGH (rDEST, rHIGH, twlgt)
116         STORE_RETURN_VALUE (rDEST)
117         blr
118 END (BP_SYM (__stpcpy))
119
120 weak_alias (BP_SYM (__stpcpy), BP_SYM (stpcpy))