123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457 |
- /*
- ********************************************************************************
- **
- ** \file ./boot/startup/src/memcpy.c
- **
- ** \version $Id: memcpy.c 7112 2011-08-15 15:24:45Z dkless $
- **
- ** \brief ARM1176 function retargeting.
- **
- ** This files implements an optimized memcpy().
- **
- ** \attention THIS SAMPLE CODE IS PROVIDED AS IS. FUJITSU SEMICONDUCTOR
- ** ACCEPTS NO RESPONSIBILITY OR LIABILITY FOR ANY ERRORS OR
- ** OMMISSIONS.
- **
- ** (C) Copyright 2006-2010 by Fujitsu Microelectronics Europe GmbH
- **
- *****************************************************************************
- */
- /********************************************************************
- ** File: memcpy.c
- **
- ** Copyright (C) 1999-2010 Daniel Vik
- **
- ** This software is provided 'as-is', without any express or implied
- ** warranty. In no event will the authors be held liable for any
- ** damages arising from the use of this software.
- ** Permission is granted to anyone to use this software for any
- ** purpose, including commercial applications, and to alter it and
- ** redistribute it freely, subject to the following restrictions:
- **
- ** 1. The origin of this software must not be misrepresented; you
- ** must not claim that you wrote the original software. If you
- ** use this software in a product, an acknowledgment in the
- ** product documentation would be appreciated but is not
- ** required.
- **
- ** 2. Altered source versions must be plainly marked as such, and
- ** must not be misrepresented as being the original software.
- **
- ** 3. This notice may not be removed or altered from any source
- ** distribution.
- **
- **
- ** Description: Implementation of the standard library function memcpy.
- ** This implementation of memcpy() is ANSI-C89 compatible.
- **
- ** The following configuration options can be set:
- **
- ** LITTLE_ENDIAN - Uses processor with little endian
- ** addressing. Default is big endian.
- **
- ** PRE_INC_PTRS - Use pre increment of pointers.
- ** Default is post increment of
- ** pointers.
- **
- ** INDEXED_COPY - Copying data using array indexing.
- ** Using this option, disables the
- ** PRE_INC_PTRS option.
- **
- ** MEMCPY_64BIT - Compiles memcpy for 64 bit
- ** architectures
- **
- **
- ** Best Settings:
- **
- ** Intel x86: LITTLE_ENDIAN and INDEXED_COPY
- **
- *******************************************************************/
- /*lint -save -e* */
- /********************************************************************
- ** Configuration definitions.
- *******************************************************************/
- #define LITTLE_ENDIAN
- #define INDEXED_COPY
- #define MEMCPY_64BIT
- /********************************************************************
- ** Includes for size_t definition
- *******************************************************************/
- #include <stddef.h>
- #include <stdint.h>
- /********************************************************************
- ** Typedefs
- *******************************************************************/
- /*lint -save -e751 */
- typedef unsigned char UInt8;
- typedef unsigned short UInt16;
- typedef unsigned int UInt32;
- #ifdef _WIN32
- typedef unsigned __int64 UInt64;
- #else
- typedef unsigned long long UInt64;
- #endif
- #ifdef MEMCPY_64BIT
- typedef UInt64 UIntN;
- #define TYPE_WIDTH 8L
- #else
- typedef UInt32 UIntN;
- #define TYPE_WIDTH 4L
- #endif
- /********************************************************************
- ** Remove definitions when INDEXED_COPY is defined.
- *******************************************************************/
- #if defined (INDEXED_COPY)
- #if defined (PRE_INC_PTRS)
- #undef PRE_INC_PTRS
- #endif /*PRE_INC_PTRS*/
- #endif /*INDEXED_COPY*/
- /********************************************************************
- ** Definitions for pre and post increment of pointers.
- *******************************************************************/
- #if defined (PRE_INC_PTRS)
- #define START_VAL(x) (x)--
- #define INC_VAL(x) *++(x)
- #define CAST_TO_U8(p, o) ((UInt8*)p + o + TYPE_WIDTH)
- #define WHILE_DEST_BREAK (TYPE_WIDTH - 1)
- #define PRE_LOOP_ADJUST - (TYPE_WIDTH - 1)
- #define PRE_SWITCH_ADJUST + 1
- #else /*PRE_INC_PTRS*/
- #define START_VAL(x)
- #define INC_VAL(x) *(x)++
- #define CAST_TO_U8(p, o) ((UInt8*)p + o)
- #define WHILE_DEST_BREAK 0
- #define PRE_LOOP_ADJUST
- #define PRE_SWITCH_ADJUST
- #endif /*PRE_INC_PTRS*/
- /********************************************************************
- ** Definitions for endians
- *******************************************************************/
- #if defined (LITTLE_ENDIAN)
- #define SHL >>
- #define SHR <<
- #else /* LITTLE_ENDIAN */
- #define SHL <<
- #define SHR >>
- #endif /* LITTLE_ENDIAN */
- /********************************************************************
- ** Macros for copying words of different alignment.
- ** Uses incremening pointers.
- *******************************************************************/
- #define CP_INCR() { \
- INC_VAL(dstN) = INC_VAL(srcN); \
- }
- #define CP_INCR_SH(shl, shr) { \
- dstWord = srcWord SHL shl; \
- srcWord = INC_VAL(srcN); \
- dstWord |= srcWord SHR shr; \
- INC_VAL(dstN) = dstWord; \
- }
- /********************************************************************
- ** Macros for copying words of different alignment.
- ** Uses array indexes.
- *******************************************************************/
- #define CP_INDEX(idx) { \
- dstN[idx] = srcN[idx]; \
- }
- #define CP_INDEX_SH(x, shl, shr) { \
- dstWord = srcWord SHL shl; \
- srcWord = srcN[x]; \
- dstWord |= srcWord SHR shr; \
- dstN[x] = dstWord; \
- }
- /********************************************************************
- ** Macros for copying words of different alignment.
- ** Uses incremening pointers or array indexes depending on
- ** configuration.
- *******************************************************************/
- #if defined (INDEXED_COPY)
- #define CP(idx) CP_INDEX(idx)
- #define CP_SH(idx, shl, shr) CP_INDEX_SH(idx, shl, shr)
- #define INC_INDEX(p, o) ((p) += (o))
- #else /* INDEXED_COPY */
- #define CP(idx) CP_INCR()
- #define CP_SH(idx, shl, shr) CP_INCR_SH(shl, shr)
- #define INC_INDEX(p, o)
- #endif /* INDEXED_COPY */
- #define COPY_REMAINING(count) { \
- START_VAL(dst8); \
- START_VAL(src8); \
- \
- switch (count) { \
- case 7: INC_VAL(dst8) = INC_VAL(src8); \
- case 6: INC_VAL(dst8) = INC_VAL(src8); \
- case 5: INC_VAL(dst8) = INC_VAL(src8); \
- case 4: INC_VAL(dst8) = INC_VAL(src8); \
- case 3: INC_VAL(dst8) = INC_VAL(src8); \
- case 2: INC_VAL(dst8) = INC_VAL(src8); \
- case 1: INC_VAL(dst8) = INC_VAL(src8); \
- case 0: \
- default: break; \
- } \
- }
- #define COPY_NO_SHIFT() { \
- UIntN* dstN = (UIntN*)(dst8 PRE_LOOP_ADJUST); \
- UIntN* srcN = (UIntN*)(src8 PRE_LOOP_ADJUST); \
- size_t length = count / TYPE_WIDTH; \
- \
- while (length & 7) { \
- CP_INCR(); \
- length--; \
- } \
- \
- length /= 8; \
- \
- while (length--) { \
- CP(0); \
- CP(1); \
- CP(2); \
- CP(3); \
- CP(4); \
- CP(5); \
- CP(6); \
- CP(7); \
- \
- INC_INDEX(dstN, 8); \
- INC_INDEX(srcN, 8); \
- } \
- \
- src8 = CAST_TO_U8(srcN, 0); \
- dst8 = CAST_TO_U8(dstN, 0); \
- \
- COPY_REMAINING(count & (TYPE_WIDTH - 1)); \
- \
- return dest; \
- }
- #define COPY_SHIFT(shift) { \
- UIntN* dstN = (UIntN*)(intptr_t)((((UIntN)(intptr_t)dst8) PRE_LOOP_ADJUST) & \
- ~(TYPE_WIDTH - 1)); \
- UIntN* srcN = (UIntN*)(intptr_t)((((UIntN)(intptr_t)src8) PRE_LOOP_ADJUST) & \
- ~(TYPE_WIDTH - 1)); \
- size_t length = count / TYPE_WIDTH; \
- UIntN srcWord = INC_VAL(srcN); \
- UIntN dstWord; \
- \
- while (length & 7) { \
- CP_INCR_SH(8 * shift, 8 * (TYPE_WIDTH - shift)); \
- length--; \
- } \
- \
- length /= 8; \
- \
- while (length--) { \
- CP_SH(0, 8 * shift, 8 * (TYPE_WIDTH - shift)); \
- CP_SH(1, 8 * shift, 8 * (TYPE_WIDTH - shift)); \
- CP_SH(2, 8 * shift, 8 * (TYPE_WIDTH - shift)); \
- CP_SH(3, 8 * shift, 8 * (TYPE_WIDTH - shift)); \
- CP_SH(4, 8 * shift, 8 * (TYPE_WIDTH - shift)); \
- CP_SH(5, 8 * shift, 8 * (TYPE_WIDTH - shift)); \
- CP_SH(6, 8 * shift, 8 * (TYPE_WIDTH - shift)); \
- CP_SH(7, 8 * shift, 8 * (TYPE_WIDTH - shift)); \
- \
- INC_INDEX(dstN, 8); \
- INC_INDEX(srcN, 8); \
- } \
- \
- src8 = CAST_TO_U8(srcN, (shift - TYPE_WIDTH)); \
- dst8 = CAST_TO_U8(dstN, 0); \
- \
- COPY_REMAINING(count & (TYPE_WIDTH - 1)); \
- \
- return dest; \
- }
- /********************************************************************
- **
- ** void *memcpy(void *dest, const void *src, size_t count)
- **
- ** Args: dest - pointer to destination buffer
- ** src - pointer to source buffer
- ** count - number of bytes to copy
- **
- ** Return: A pointer to destination buffer
- **
- ** Purpose: Copies count bytes from src to dest.
- ** No overlap check is performed.
- **
- *******************************************************************/
- #if 0//use libc 's api to improve performance.
- void *memcpy(void *dest, const void *src, size_t count)
- {
- UInt8* dst8 = (UInt8*)dest;
- UInt8* src8 = (UInt8*)src;
- if (count < 8) {
- COPY_REMAINING(count);
- return dest;
- }
- START_VAL(dst8);
- START_VAL(src8);
- while (((UIntN)(intptr_t)dst8 & (TYPE_WIDTH - 1)) != WHILE_DEST_BREAK) {
- INC_VAL(dst8) = INC_VAL(src8);
- count--;
- }
- switch ((((UIntN)(intptr_t)src8) PRE_SWITCH_ADJUST) & (TYPE_WIDTH - 1)) {
- case 0: COPY_NO_SHIFT();
- case 1: COPY_SHIFT(1);
- case 2: COPY_SHIFT(2);
- case 3: COPY_SHIFT(3);
- #if TYPE_WIDTH >= 4
- case 4: COPY_SHIFT(4);
- case 5: COPY_SHIFT(5);
- case 6: COPY_SHIFT(6);
- case 7: COPY_SHIFT(7);
- #endif
- }
- return 0;
- }
- /**
- * memset - Fill a region of memory with the given value
- * @s: Pointer to the start of the area.
- * @c: The byte to fill the area with
- * @count: The size of the area.
- *
- * Do not use memset() to access IO space, use memset_io() instead.
- */
- void * memset(void * s,int c,size_t count)
- {
- unsigned long *sl = (unsigned long *) s;
- unsigned long cl = 0;
- char *s8;
- int i;
- /* do it one word at a time (32 bits or 64 bits) while possible */
- if ( ((unsigned long)s & (sizeof(*sl) - 1)) == 0) {
- for (i = 0; i < sizeof(*sl); i++) {
- cl <<= 8;
- cl |= c & 0xff;
- }
- while (count >= sizeof(*sl)) {
- *sl++ = cl;
- count -= sizeof(*sl);
- }
- }
- /* fill 8 bits at a time */
- s8 = (char *)sl;
- while (count--)
- *s8++ = c;
- return s;
- }
- /**
- * memmove - Copy one area of memory to another
- * @dest: Where to copy to
- * @src: Where to copy from
- * @count: The size of the area.
- *
- * Unlike memcpy(), memmove() copes with overlapping areas.
- */
- void * memmove(void * dest,const void *src,size_t count)
- {
- char *tmp, *s;
- if (src == dest)
- return dest;
- if (dest <= src) {
- tmp = (char *) dest;
- s = (char *) src;
- while (count--)
- *tmp++ = *s++;
- }
- else {
- tmp = (char *) dest + count;
- s = (char *) src + count;
- while (count--)
- *--tmp = *--s;
- }
- return dest;
- }
- /**
- * memcmp - Compare two areas of memory
- * @cs: One area of memory
- * @ct: Another area of memory
- * @count: The size of the area.
- */
- int memcmp(const void * cs,const void * ct,size_t count)
- {
- const unsigned char *su1, *su2;
- int res = 0;
- for( su1 = cs, su2 = ct; 0 < count; ++su1, ++su2, count--)
- if ((res = *su1 - *su2) != 0)
- break;
- return res;
- }
- #endif
- /*lint -restore */
|