* sysdeps/powerpc/bp-asm.h: New file.
[kopensolaris-gnu/glibc.git] / sysdeps / powerpc / strcpy.S
1 /* Optimized strcpy 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 Library General Public License as
7    published by the Free Software Foundation; either version 2 of the
8    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    Library General Public License for more details.
14
15    You should have received a copy of the GNU Library General Public
16    License along with the GNU C Library; see the file COPYING.LIB.  If not,
17    write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18    Boston, MA 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] strcpy (char *dest [r3], const char *src [r4])  */
27
28 EALIGN (BP_SYM (strcpy), 4, 0)
29
30 #define rTMP    r0
31 #define rRTN    r3      /* incoming DEST arg preserved as result */
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 rSRC   r4      /* pointer to previous word in src */
39 # define rDEST  r5      /* pointer to previous word in dest */
40 #endif
41 #define rWORD   r6      /* current word from src */
42 #define rFEFE   r7      /* constant 0xfefefeff (-0x01010101) */
43 #define r7F7F   r8      /* constant 0x7f7f7f7f */
44 #define rNEG    r9      /* ~(word in s1 | 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, rRTN
52         clrlwi. rTMP, rTMP, 30
53 #if __BOUNDED_POINTERS__
54         addi    rDEST, rDEST, -4
55 #else
56         addi    rDEST, rRTN, -4
57 #endif
58         bne     L(unaligned)
59
60         lis     rFEFE, -0x101
61         lis     r7F7F, 0x7f7f
62         lwz     rWORD, 0(rSRC)
63         addi    rFEFE, rFEFE, -0x101
64         addi    r7F7F, r7F7F, 0x7f7f
65         b       L(g2)
66
67 L(g0):  lwzu    rALT, 4(rSRC)
68         stwu    rWORD, 4(rDEST)
69         add     rTMP, rFEFE, rALT
70         nor     rNEG, r7F7F, rALT
71         and.    rTMP, rTMP, rNEG
72         bne-    L(g1)
73         lwzu    rWORD, 4(rSRC)
74         stwu    rALT, 4(rDEST)
75 L(g2):  add     rTMP, rFEFE, rWORD
76         nor     rNEG, r7F7F, rWORD
77         and.    rTMP, rTMP, rNEG
78         beq+    L(g0)
79
80         mr      rALT, rWORD
81 /* We've hit the end of the string.  Do the rest byte-by-byte.  */
82 L(g1):  rlwinm. rTMP, rALT, 8, 24, 31
83         stb     rTMP, 4(rDEST)
84         beqlr-
85         rlwinm. rTMP, rALT, 16, 24, 31
86         stb     rTMP, 5(rDEST)
87         beqlr-
88         rlwinm. rTMP, rALT, 24, 24, 31
89         stb     rTMP, 6(rDEST)
90         beqlr-
91         stb     rALT, 7(rDEST)
92         /* GKM FIXME: check high bound.  */
93         blr
94
95 /* Oh well.  In this case, we just do a byte-by-byte copy.  */
96         .align 4
97         nop
98 L(unaligned):
99         lbz     rWORD, 0(rSRC)
100         addi    rDEST, rRTN, -1
101         cmpwi   rWORD, 0
102         beq-    L(u2)
103
104 L(u0):  lbzu    rALT, 1(rSRC)
105         stbu    rWORD, 1(rDEST)
106         cmpwi   rALT, 0
107         beq-    L(u1)
108         nop             /* Let 601 load start of loop.  */
109         lbzu    rWORD, 1(rSRC)
110         stbu    rALT, 1(rDEST)
111         cmpwi   rWORD, 0
112         bne+    L(u0)
113 L(u2):  stb     rWORD, 1(rDEST)
114         /* GKM FIXME: check high bound.  */
115         blr
116 L(u1):  stb     rALT, 1(rDEST)
117         /* GKM FIXME: check high bound.  */
118         blr
119
120 END (BP_SYM (strcpy))