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