1
/********************************************************************
4
** Copyright (C) 1999-2010 Daniel Vik
6
** This software is provided 'as-is', without any express or implied
7
** warranty. In no event will the authors be held liable for any
8
** damages arising from the use of this software.
9
** Permission is granted to anyone to use this software for any
10
** purpose, including commercial applications, and to alter it and
11
** redistribute it freely, subject to the following restrictions:
13
** 1. The origin of this software must not be misrepresented; you
14
** must not claim that you wrote the original software. If you
15
** use this software in a product, an acknowledgment in the
16
** use this software in a product, an acknowledgment in the
17
** product documentation would be appreciated but is not
20
** 2. Altered source versions must be plainly marked as such, and
21
** must not be misrepresented as being the original software.
23
** 3. This notice may not be removed or altered from any source
27
** Description: Implementation of the standard library function memcpy.
28
** This implementation of memcpy() is ANSI-C89 compatible.
30
** The following configuration options can be set:
32
** LITTLE_ENDIAN - Uses processor with little endian
33
** addressing. Default is big endian.
35
** PRE_INC_PTRS - Use pre increment of pointers.
36
** Default is post increment of
39
** INDEXED_COPY - Copying data using array indexing.
40
** Using this option, disables the
41
** PRE_INC_PTRS option.
43
** MEMCPY_64BIT - Compiles memcpy for 64 bit
49
** Intel x86: LITTLE_ENDIAN and INDEXED_COPY
51
*******************************************************************/
55
/********************************************************************
56
** Configuration definitions.
57
*******************************************************************/
63
/********************************************************************
64
** Includes for size_t definition
65
*******************************************************************/
70
/********************************************************************
72
*******************************************************************/
74
typedef unsigned char UInt8;
75
typedef unsigned short UInt16;
76
typedef unsigned int UInt32;
78
typedef unsigned __int64 UInt64;
80
typedef unsigned long long UInt64;
92
/********************************************************************
93
** Remove definitions when INDEXED_COPY is defined.
94
*******************************************************************/
96
#if defined (INDEXED_COPY)
97
#if defined (PRE_INC_PTRS)
99
#endif /*PRE_INC_PTRS*/
100
#endif /*INDEXED_COPY*/
104
/********************************************************************
105
** Definitions for pre and post increment of pointers.
106
*******************************************************************/
108
#if defined (PRE_INC_PTRS)
110
#define START_VAL(x) (x)--
111
#define INC_VAL(x) *++(x)
112
#define CAST_TO_U8(p, o) ((UInt8*)p + o + TYPE_WIDTH)
113
#define WHILE_DEST_BREAK (TYPE_WIDTH - 1)
114
#define PRE_LOOP_ADJUST - (TYPE_WIDTH - 1)
115
#define PRE_SWITCH_ADJUST + 1
117
#else /*PRE_INC_PTRS*/
120
#define INC_VAL(x) *(x)++
121
#define CAST_TO_U8(p, o) ((UInt8*)p + o)
122
#define WHILE_DEST_BREAK 0
123
#define PRE_LOOP_ADJUST
124
#define PRE_SWITCH_ADJUST
126
#endif /*PRE_INC_PTRS*/
130
/********************************************************************
131
** Definitions for endians
132
*******************************************************************/
134
#if defined (LITTLE_ENDIAN)
139
#else /* LITTLE_ENDIAN */
144
#endif /* LITTLE_ENDIAN */
148
/********************************************************************
149
** Macros for copying words of different alignment.
150
** Uses incremening pointers.
151
*******************************************************************/
153
#define CP_INCR() { \
154
INC_VAL(dstN) = INC_VAL(srcN); \
157
#define CP_INCR_SH(shl, shr) { \
158
dstWord = srcWord SHL shl; \
159
srcWord = INC_VAL(srcN); \
160
dstWord |= srcWord SHR shr; \
161
INC_VAL(dstN) = dstWord; \
166
/********************************************************************
167
** Macros for copying words of different alignment.
168
** Uses array indexes.
169
*******************************************************************/
171
#define CP_INDEX(idx) { \
172
dstN[idx] = srcN[idx]; \
175
#define CP_INDEX_SH(x, shl, shr) { \
176
dstWord = srcWord SHL shl; \
178
dstWord |= srcWord SHR shr; \
184
/********************************************************************
185
** Macros for copying words of different alignment.
186
** Uses incremening pointers or array indexes depending on
188
*******************************************************************/
190
#if defined (INDEXED_COPY)
192
#define CP(idx) CP_INDEX(idx)
193
#define CP_SH(idx, shl, shr) CP_INDEX_SH(idx, shl, shr)
195
#define INC_INDEX(p, o) ((p) += (o))
197
#else /* INDEXED_COPY */
199
#define CP(idx) CP_INCR()
200
#define CP_SH(idx, shl, shr) CP_INCR_SH(shl, shr)
202
#define INC_INDEX(p, o)
204
#endif /* INDEXED_COPY */
207
#define COPY_REMAINING(count) { \
212
case 7: INC_VAL(dst8) = INC_VAL(src8); \
213
case 6: INC_VAL(dst8) = INC_VAL(src8); \
214
case 5: INC_VAL(dst8) = INC_VAL(src8); \
215
case 4: INC_VAL(dst8) = INC_VAL(src8); \
216
case 3: INC_VAL(dst8) = INC_VAL(src8); \
217
case 2: INC_VAL(dst8) = INC_VAL(src8); \
218
case 1: INC_VAL(dst8) = INC_VAL(src8); \
224
#define COPY_NO_SHIFT() { \
225
UIntN* dstN = (UIntN*)(dst8 PRE_LOOP_ADJUST); \
226
UIntN* srcN = (UIntN*)(src8 PRE_LOOP_ADJUST); \
227
size_t length = count / TYPE_WIDTH; \
229
while (length & 7) { \
246
INC_INDEX(dstN, 8); \
247
INC_INDEX(srcN, 8); \
250
src8 = CAST_TO_U8(srcN, 0); \
251
dst8 = CAST_TO_U8(dstN, 0); \
253
COPY_REMAINING(count & (TYPE_WIDTH - 1)); \
260
#define COPY_SHIFT(shift) { \
261
UIntN* dstN = (UIntN*)((((UIntN)dst8) PRE_LOOP_ADJUST) & \
262
~(TYPE_WIDTH - 1)); \
263
UIntN* srcN = (UIntN*)((((UIntN)src8) PRE_LOOP_ADJUST) & \
264
~(TYPE_WIDTH - 1)); \
265
size_t length = count / TYPE_WIDTH; \
266
UIntN srcWord = INC_VAL(srcN); \
269
while (length & 7) { \
270
CP_INCR_SH(8 * shift, 8 * (TYPE_WIDTH - shift)); \
277
CP_SH(0, 8 * shift, 8 * (TYPE_WIDTH - shift)); \
278
CP_SH(1, 8 * shift, 8 * (TYPE_WIDTH - shift)); \
279
CP_SH(2, 8 * shift, 8 * (TYPE_WIDTH - shift)); \
280
CP_SH(3, 8 * shift, 8 * (TYPE_WIDTH - shift)); \
281
CP_SH(4, 8 * shift, 8 * (TYPE_WIDTH - shift)); \
282
CP_SH(5, 8 * shift, 8 * (TYPE_WIDTH - shift)); \
283
CP_SH(6, 8 * shift, 8 * (TYPE_WIDTH - shift)); \
284
CP_SH(7, 8 * shift, 8 * (TYPE_WIDTH - shift)); \
286
INC_INDEX(dstN, 8); \
287
INC_INDEX(srcN, 8); \
290
src8 = CAST_TO_U8(srcN, (shift - TYPE_WIDTH)); \
291
dst8 = CAST_TO_U8(dstN, 0); \
293
COPY_REMAINING(count & (TYPE_WIDTH - 1)); \
299
/********************************************************************
301
** void *memcpy(void *dest, const void *src, size_t count)
303
** Args: dest - pointer to destination buffer
304
** src - pointer to source buffer
305
** count - number of bytes to copy
307
** Return: A pointer to destination buffer
309
** Purpose: Copies count bytes from src to dest.
310
** No overlap check is performed.
312
*******************************************************************/
314
void *fast_memcpy(void *dest, const void *src, size_t count)
316
UInt8* dst8 = (UInt8*)dest;
317
UInt8* src8 = (UInt8*)src;
320
COPY_REMAINING(count);
327
while (((UIntN)dst8 & (TYPE_WIDTH - 1)) != WHILE_DEST_BREAK) {
328
INC_VAL(dst8) = INC_VAL(src8);
332
switch ((((UIntN)src8) PRE_SWITCH_ADJUST) & (TYPE_WIDTH - 1)) {
333
case 0: COPY_NO_SHIFT(); break;
334
case 1: COPY_SHIFT(1); break;
335
case 2: COPY_SHIFT(2); break;
336
case 3: COPY_SHIFT(3); break;
338
case 4: COPY_SHIFT(4); break;
339
case 5: COPY_SHIFT(5); break;
340
case 6: COPY_SHIFT(6); break;
341
case 7: COPY_SHIFT(7); break;