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 #if defined(PREFER_SIZE_OVER_SPEED) || defined(__OPTIMIZE_SIZE__)
13 //memcpy defined in memcpy-asm.S
14 #else
15 
16 #include <string.h>
17 #include <stdint.h>
18 #include "../../string/local.h"
19 
20 #define unlikely(X) __builtin_expect (!!(X), 0)
21 
22 #undef memcpy
23 
24 void *
25 __inhibit_loop_to_libcall
memcpy(void * __restrict aa,const void * __restrict bb,size_t n)26 memcpy(void *__restrict aa, const void *__restrict bb, size_t n)
27 {
28   #define BODY(a, b, t) { \
29     t tt = *b; \
30     a++, b++; \
31     *(a - 1) = tt; \
32   }
33 
34   char *a = (char *)aa;
35   const char *b = (const char *)bb;
36   char *end = a + n;
37   uintptr_t msk = sizeof (long) - 1;
38   if (unlikely ((((uintptr_t)a & msk) != ((uintptr_t)b & msk))
39 	       || n < sizeof (long)))
40     {
41 small:
42       if (__builtin_expect (a < end, 1))
43 	while (a < end)
44 	  BODY (a, b, char);
45       return aa;
46     }
47 
48   if (unlikely (((uintptr_t)a & msk) != 0))
49     while ((uintptr_t)a & msk)
50       BODY (a, b, char);
51 
52   long *la = (long *)a;
53   const long *lb = (const long *)b;
54   long *lend = (long *)((uintptr_t)end & ~msk);
55 
56   if (unlikely (lend - la > 8))
57     {
58       while (lend - la > 8)
59 	{
60 	  long b0 = *lb++;
61 	  long b1 = *lb++;
62 	  long b2 = *lb++;
63 	  long b3 = *lb++;
64 	  long b4 = *lb++;
65 	  long b5 = *lb++;
66 	  long b6 = *lb++;
67 	  long b7 = *lb++;
68 	  long b8 = *lb++;
69 	  *la++ = b0;
70 	  *la++ = b1;
71 	  *la++ = b2;
72 	  *la++ = b3;
73 	  *la++ = b4;
74 	  *la++ = b5;
75 	  *la++ = b6;
76 	  *la++ = b7;
77 	  *la++ = b8;
78 	}
79     }
80 
81   while (la < lend)
82     BODY (la, lb, long);
83 
84   a = (char *)la;
85   b = (const char *)lb;
86   if (unlikely (a < end))
87     goto small;
88   return aa;
89 }
90 #endif
91