1 /* Copyright (c) 2009 Xilinx, Inc. All rights reserved.
2
3 Redistribution and use in source and binary forms, with or without
4 modification, are permitted provided that the following conditions are
5 met:
6
7 1. Redistributions source code must retain the above copyright notice,
8 this list of conditions and the following disclaimer.
9
10 2. Redistributions in binary form must reproduce the above copyright
11 notice, this list of conditions and the following disclaimer in the
12 documentation and/or other materials provided with the distribution.
13
14 3. Neither the name of Xilinx nor the names of its contributors may be
15 used to endorse or promote products derived from this software without
16 specific prior written permission.
17
18 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER AND CONTRIBUTORS "AS
19 IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
20 TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
21 PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
22 HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23 SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
24 TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
25 PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
26 LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
27 NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
28 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29
30
31 FUNCTION
32 <<strcpy>>---copy string
33
34 INDEX
35 strcpy
36
37 SYNOPSIS
38 #include <string.h>
39 char *strcpy(char *restrict <[dst]>, const char *restrict <[src]>);
40
41 DESCRIPTION
42 <<strcpy>> copies the string pointed to by <[src]>
43 (including the terminating null character) to the array
44 pointed to by <[dst]>.
45
46 RETURNS
47 This function returns the initial value of <[dst]>.
48
49 PORTABILITY
50 <<strcpy>> is ANSI C.
51
52 <<strcpy>> requires no supporting OS subroutines.
53
54 QUICKREF
55 strcpy ansi pure
56 */
57
58 #include <picolibc.h>
59
60 #include <string.h>
61 #include <limits.h>
62
63 /*SUPPRESS 560*/
64 /*SUPPRESS 530*/
65
66 /* Nonzero if either X or Y is not aligned on a "long" boundary. */
67 #define UNALIGNED(X, Y) \
68 (((long)X & (sizeof (long) - 1)) | ((long)Y & (sizeof (long) - 1)))
69
70 #if LONG_MAX == 2147483647L
71 #define DETECTNULL(X) (((X) - 0x01010101) & ~(X) & 0x80808080)
72 #else
73 #if LONG_MAX == 9223372036854775807L
74 /* Nonzero if X (a long int) contains a NULL byte. */
75 #define DETECTNULL(X) (((X) - 0x0101010101010101) & ~(X) & 0x8080808080808080)
76 #else
77 #error long int is not a 32bit or 64bit type.
78 #endif
79 #endif
80
81 #ifndef DETECTNULL
82 #error long int is not a 32bit or 64bit byte
83 #endif
84
85 char*
strcpy(char * __restrict dst0,const char * __restrict src0)86 strcpy (char *__restrict dst0,
87 const char *__restrict src0)
88 {
89
90 #ifndef HAVE_HW_PCMP
91
92 #if defined(PREFER_SIZE_OVER_SPEED) || defined(__OPTIMIZE_SIZE__)
93 char *s = dst0;
94
95 while ((*dst0++ = *src0++))
96 ;
97
98 return s;
99 #else
100 char *dst = dst0;
101 const char *src = src0;
102 long *aligned_dst;
103 const long *aligned_src;
104
105 /* If SRC or DEST is unaligned, then copy bytes. */
106 if (!UNALIGNED (src, dst))
107 {
108 aligned_dst = (long*)dst;
109 aligned_src = (long*)src;
110
111 /* SRC and DEST are both "long int" aligned, try to do "long int"
112 sized copies. */
113 while (!DETECTNULL(*aligned_src))
114 {
115 *aligned_dst++ = *aligned_src++;
116 }
117
118 dst = (char*)aligned_dst;
119 src = (char*)aligned_src;
120 }
121
122 while ((*dst++ = *src++))
123 ;
124 return dst0;
125 #endif /* not PREFER_SIZE_OVER_SPEED */
126
127 #else
128
129 #include "mb_endian.h"
130
131 __asm__ volatile (" \n\
132 or r9, r0, r0 /* Index register */ \n\
133 check_alignment: \n\
134 andi r3, r5, 3 \n\
135 andi r4, r6, 3 \n\
136 bnei r3, try_align_args \n\
137 bnei r4, regular_strcpy /* At this point we dont have a choice */ \n\
138 cpy_loop: \n"
139 LOAD4BYTES("r3", "r6", "r9")
140 " \n\
141 pcmpbf r4, r0, r3 \n\
142 bnei r4, cpy_bytes /* If r4 != 0, then null present within string */\n"
143 STORE4BYTES("r3", "r5", "r9")
144 " \n\
145 brid cpy_loop \n\
146 addik r9, r9, 4 \n\
147 cpy_bytes: \n\
148 lbu r3, r6, r9 \n\
149 sb r3, r5, r9 \n\
150 addik r4, r4, -1 \n\
151 bneid r4, cpy_bytes \n\
152 addik r9, r9, 1 /* delay slot */\n\
153 cpy_null: \n\
154 rtsd r15, 8 \n\
155 or r3, r0, r5 /* Return strcpy result */\n\
156 try_align_args: \n\
157 xor r7, r4, r3 \n\
158 bnei r7, regular_strcpy /* cannot align args */\n\
159 rsubik r10, r3, 4 /* Number of initial bytes to align */\n\
160 align_loop: \n\
161 lbu r3, r6, r9 \n\
162 sb r3, r5, r9 \n\
163 beqid r3, end_cpy /* Break if we have seen null character */\n\
164 addik r10, r10, -1 \n\
165 bneid r10, align_loop \n\
166 addik r9, r9, 1 \n\
167 bri cpy_loop \n\
168 regular_strcpy: \n\
169 lbu r3, r6, r9 \n\
170 sb r3, r5, r9 \n\
171 bneid r3, regular_strcpy \n\
172 addik r9, r9, 1 \n\
173 end_cpy: \n\
174 rtsd r15, 8 \n\
175 or r3, r0, r5 /* Return strcpy result */");
176 #endif /* ! HAVE_HW_PCMP */
177 }
178
179
180
181
182
183