Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
torvalds
GitHub Repository: torvalds/linux
Path: blob/master/arch/microblaze/lib/memcpy.c
26424 views
1
/*
2
* Copyright (C) 2008-2009 Michal Simek <[email protected]>
3
* Copyright (C) 2008-2009 PetaLogix
4
* Copyright (C) 2007 John Williams
5
*
6
* Reasonably optimised generic C-code for memcpy on Microblaze
7
* This is generic C code to do efficient, alignment-aware memcpy.
8
*
9
* It is based on demo code originally Copyright 2001 by Intel Corp, taken from
10
* http://www.embedded.com/showArticle.jhtml?articleID=19205567
11
*
12
* Attempts were made, unsuccessfully, to contact the original
13
* author of this code (Michael Morrow, Intel). Below is the original
14
* copyright notice.
15
*
16
* This software has been developed by Intel Corporation.
17
* Intel specifically disclaims all warranties, express or
18
* implied, and all liability, including consequential and
19
* other indirect damages, for the use of this program, including
20
* liability for infringement of any proprietary rights,
21
* and including the warranties of merchantability and fitness
22
* for a particular purpose. Intel does not assume any
23
* responsibility for and errors which may appear in this program
24
* not any responsibility to update it.
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 CONFIG_OPT_LIB_FUNCTION
35
void *memcpy(void *v_dst, const void *v_src, __kernel_size_t c)
36
{
37
const char *src = v_src;
38
char *dst = v_dst;
39
40
/* The following code tries to optimize the copy by using unsigned
41
* alignment. This will work fine if both source and destination are
42
* aligned on the same boundary. However, if they are aligned on
43
* different boundaries shifts will be necessary. This might result in
44
* bad performance on MicroBlaze systems without a barrel shifter.
45
*/
46
const uint32_t *i_src;
47
uint32_t *i_dst;
48
49
if (likely(c >= 4)) {
50
unsigned value, buf_hold;
51
52
/* Align the destination to a word boundary. */
53
/* This is done in an endian independent manner. */
54
switch ((unsigned long)dst & 3) {
55
case 1:
56
*dst++ = *src++;
57
--c;
58
fallthrough;
59
case 2:
60
*dst++ = *src++;
61
--c;
62
fallthrough;
63
case 3:
64
*dst++ = *src++;
65
--c;
66
}
67
68
i_dst = (void *)dst;
69
70
/* Choose a copy scheme based on the source */
71
/* alignment relative to destination. */
72
switch ((unsigned long)src & 3) {
73
case 0x0: /* Both byte offsets are aligned */
74
i_src = (const void *)src;
75
76
for (; c >= 4; c -= 4)
77
*i_dst++ = *i_src++;
78
79
src = (const void *)i_src;
80
break;
81
case 0x1: /* Unaligned - Off by 1 */
82
/* Word align the source */
83
i_src = (const void *) ((unsigned)src & ~3);
84
#ifndef __MICROBLAZEEL__
85
/* Load the holding buffer */
86
buf_hold = *i_src++ << 8;
87
88
for (; c >= 4; c -= 4) {
89
value = *i_src++;
90
*i_dst++ = buf_hold | value >> 24;
91
buf_hold = value << 8;
92
}
93
#else
94
/* Load the holding buffer */
95
buf_hold = (*i_src++ & 0xFFFFFF00) >> 8;
96
97
for (; c >= 4; c -= 4) {
98
value = *i_src++;
99
*i_dst++ = buf_hold | ((value & 0xFF) << 24);
100
buf_hold = (value & 0xFFFFFF00) >> 8;
101
}
102
#endif
103
/* Realign the source */
104
src = (const void *)i_src;
105
src -= 3;
106
break;
107
case 0x2: /* Unaligned - Off by 2 */
108
/* Word align the source */
109
i_src = (const void *) ((unsigned)src & ~3);
110
#ifndef __MICROBLAZEEL__
111
/* Load the holding buffer */
112
buf_hold = *i_src++ << 16;
113
114
for (; c >= 4; c -= 4) {
115
value = *i_src++;
116
*i_dst++ = buf_hold | value >> 16;
117
buf_hold = value << 16;
118
}
119
#else
120
/* Load the holding buffer */
121
buf_hold = (*i_src++ & 0xFFFF0000) >> 16;
122
123
for (; c >= 4; c -= 4) {
124
value = *i_src++;
125
*i_dst++ = buf_hold | ((value & 0xFFFF) << 16);
126
buf_hold = (value & 0xFFFF0000) >> 16;
127
}
128
#endif
129
/* Realign the source */
130
src = (const void *)i_src;
131
src -= 2;
132
break;
133
case 0x3: /* Unaligned - Off by 3 */
134
/* Word align the source */
135
i_src = (const void *) ((unsigned)src & ~3);
136
#ifndef __MICROBLAZEEL__
137
/* Load the holding buffer */
138
buf_hold = *i_src++ << 24;
139
140
for (; c >= 4; c -= 4) {
141
value = *i_src++;
142
*i_dst++ = buf_hold | value >> 8;
143
buf_hold = value << 24;
144
}
145
#else
146
/* Load the holding buffer */
147
buf_hold = (*i_src++ & 0xFF000000) >> 24;
148
149
for (; c >= 4; c -= 4) {
150
value = *i_src++;
151
*i_dst++ = buf_hold | ((value & 0xFFFFFF) << 8);
152
buf_hold = (value & 0xFF000000) >> 24;
153
}
154
#endif
155
/* Realign the source */
156
src = (const void *)i_src;
157
src -= 1;
158
break;
159
}
160
dst = (void *)i_dst;
161
}
162
163
/* Finish off any remaining bytes */
164
/* simple fast copy, ... unless a cache boundary is crossed */
165
switch (c) {
166
case 3:
167
*dst++ = *src++;
168
fallthrough;
169
case 2:
170
*dst++ = *src++;
171
fallthrough;
172
case 1:
173
*dst++ = *src++;
174
}
175
176
return v_dst;
177
}
178
EXPORT_SYMBOL(memcpy);
179
#endif /* CONFIG_OPT_LIB_FUNCTION */
180
181