1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27#include <linux/export.h>
28#include <linux/types.h>
29#include <linux/stddef.h>
30#include <linux/compiler.h>
31
32#include <linux/string.h>
33
34#ifdef __HAVE_ARCH_MEMCPY
35#ifndef CONFIG_OPT_LIB_FUNCTION
36void *memcpy(void *v_dst, const void *v_src, __kernel_size_t c)
37{
38 const char *src = v_src;
39 char *dst = v_dst;
40
41
42 while (c--)
43 *dst++ = *src++;
44
45 return v_dst;
46}
47#else
48void *memcpy(void *v_dst, const void *v_src, __kernel_size_t c)
49{
50 const char *src = v_src;
51 char *dst = v_dst;
52
53
54
55
56
57
58
59 const uint32_t *i_src;
60 uint32_t *i_dst;
61
62 if (likely(c >= 4)) {
63 unsigned value, buf_hold;
64
65
66
67 switch ((unsigned long)dst & 3) {
68 case 1:
69 *dst++ = *src++;
70 --c;
71 fallthrough;
72 case 2:
73 *dst++ = *src++;
74 --c;
75 fallthrough;
76 case 3:
77 *dst++ = *src++;
78 --c;
79 }
80
81 i_dst = (void *)dst;
82
83
84
85 switch ((unsigned long)src & 3) {
86 case 0x0:
87 i_src = (const void *)src;
88
89 for (; c >= 4; c -= 4)
90 *i_dst++ = *i_src++;
91
92 src = (const void *)i_src;
93 break;
94 case 0x1:
95
96 i_src = (const void *) ((unsigned)src & ~3);
97#ifndef __MICROBLAZEEL__
98
99 buf_hold = *i_src++ << 8;
100
101 for (; c >= 4; c -= 4) {
102 value = *i_src++;
103 *i_dst++ = buf_hold | value >> 24;
104 buf_hold = value << 8;
105 }
106#else
107
108 buf_hold = (*i_src++ & 0xFFFFFF00) >> 8;
109
110 for (; c >= 4; c -= 4) {
111 value = *i_src++;
112 *i_dst++ = buf_hold | ((value & 0xFF) << 24);
113 buf_hold = (value & 0xFFFFFF00) >> 8;
114 }
115#endif
116
117 src = (const void *)i_src;
118 src -= 3;
119 break;
120 case 0x2:
121
122 i_src = (const void *) ((unsigned)src & ~3);
123#ifndef __MICROBLAZEEL__
124
125 buf_hold = *i_src++ << 16;
126
127 for (; c >= 4; c -= 4) {
128 value = *i_src++;
129 *i_dst++ = buf_hold | value >> 16;
130 buf_hold = value << 16;
131 }
132#else
133
134 buf_hold = (*i_src++ & 0xFFFF0000) >> 16;
135
136 for (; c >= 4; c -= 4) {
137 value = *i_src++;
138 *i_dst++ = buf_hold | ((value & 0xFFFF) << 16);
139 buf_hold = (value & 0xFFFF0000) >> 16;
140 }
141#endif
142
143 src = (const void *)i_src;
144 src -= 2;
145 break;
146 case 0x3:
147
148 i_src = (const void *) ((unsigned)src & ~3);
149#ifndef __MICROBLAZEEL__
150
151 buf_hold = *i_src++ << 24;
152
153 for (; c >= 4; c -= 4) {
154 value = *i_src++;
155 *i_dst++ = buf_hold | value >> 8;
156 buf_hold = value << 24;
157 }
158#else
159
160 buf_hold = (*i_src++ & 0xFF000000) >> 24;
161
162 for (; c >= 4; c -= 4) {
163 value = *i_src++;
164 *i_dst++ = buf_hold | ((value & 0xFFFFFF) << 8);
165 buf_hold = (value & 0xFF000000) >> 24;
166 }
167#endif
168
169 src = (const void *)i_src;
170 src -= 1;
171 break;
172 }
173 dst = (void *)i_dst;
174 }
175
176
177
178 switch (c) {
179 case 3:
180 *dst++ = *src++;
181 fallthrough;
182 case 2:
183 *dst++ = *src++;
184 fallthrough;
185 case 1:
186 *dst++ = *src++;
187 }
188
189 return v_dst;
190}
191#endif
192EXPORT_SYMBOL(memcpy);
193#endif
194