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