1 /* Copyright (c) 2017  SiFive Inc. All rights reserved.
2 
3    This copyrighted material is made available to anyone wishing to use,
4    modify, copy, or redistribute it subject to the terms and conditions
5    of the FreeBSD License.   This program is distributed in the hope that
6    it will be useful, but WITHOUT ANY WARRANTY expressed or implied,
7    including the implied warranties of MERCHANTABILITY or FITNESS FOR
8    A PARTICULAR PURPOSE.  A copy of this license is available at
9    http://www.opensource.org/licenses.
10 */
11 
12 #include <picolibc.h>
13 
14 #if defined(PREFER_SIZE_OVER_SPEED) || defined(__OPTIMIZE_SIZE__)
15 //memcpy defined in memcpy-asm.S
16 #else
17 
18 #include <string.h>
19 #include <stdint.h>
20 #include "../../string/local.h"
21 
22 #define unlikely(X) __builtin_expect (!!(X), 0)
23 
24 #undef memcpy
25 
26 void *
27 __inhibit_loop_to_libcall
memcpy(void * __restrict aa,const void * __restrict bb,size_t n)28 memcpy(void *__restrict aa, const void *__restrict bb, size_t n)
29 {
30   #define BODY(a, b, t) { \
31     t tt = *b; \
32     a++, b++; \
33     *(a - 1) = tt; \
34   }
35 
36   char *a = (char *)aa;
37   const char *b = (const char *)bb;
38   char *end = a + n;
39   uintptr_t msk = sizeof (long) - 1;
40   if (unlikely ((((uintptr_t)a & msk) != ((uintptr_t)b & msk))
41 	       || n < sizeof (long)))
42     {
43 small:
44       if (__builtin_expect (a < end, 1))
45 	while (a < end)
46 	  BODY (a, b, char);
47       return aa;
48     }
49 
50   if (unlikely (((uintptr_t)a & msk) != 0))
51     while ((uintptr_t)a & msk)
52       BODY (a, b, char);
53 
54   long *la = (long *)a;
55   const long *lb = (const long *)b;
56   long *lend = (long *)((uintptr_t)end & ~msk);
57 
58   if (unlikely (lend - la > 8))
59     {
60       while (lend - la > 8)
61 	{
62 	  long b0 = *lb++;
63 	  long b1 = *lb++;
64 	  long b2 = *lb++;
65 	  long b3 = *lb++;
66 	  long b4 = *lb++;
67 	  long b5 = *lb++;
68 	  long b6 = *lb++;
69 	  long b7 = *lb++;
70 	  long b8 = *lb++;
71 	  *la++ = b0;
72 	  *la++ = b1;
73 	  *la++ = b2;
74 	  *la++ = b3;
75 	  *la++ = b4;
76 	  *la++ = b5;
77 	  *la++ = b6;
78 	  *la++ = b7;
79 	  *la++ = b8;
80 	}
81     }
82 
83   while (la < lend)
84     BODY (la, lb, long);
85 
86   a = (char *)la;
87   b = (const char *)lb;
88   if (unlikely (a < end))
89     goto small;
90   return aa;
91 }
92 #endif
93