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