OpenCores
URL https://opencores.org/ocsvn/amber/amber/trunk

Subversion Repositories amber

[/] [amber/] [trunk/] [sw/] [mini-libc/] [memcpy.c] - Rev 2

Compare with Previous | Blame | View Log

/********************************************************************
 ** 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
 **    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
 **
 *******************************************************************/
 
 
 
/********************************************************************
 ** Configuration definitions.
 *******************************************************************/
 
#define LITTLE_ENDIAN
#define INDEXED_COPY
 
 
/********************************************************************
 ** Includes for size_t definition
 *******************************************************************/
 
#include "stdio.h"
 
 
/********************************************************************
 ** Typedefs
 *******************************************************************/
 
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          8
#else
typedef UInt32              UIntN;
#define TYPE_WIDTH          4
#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*)((((UIntN)dst8) PRE_LOOP_ADJUST) &       \
                             ~(TYPE_WIDTH - 1));                    \
    UIntN* srcN  = (UIntN*)((((UIntN)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.
 **
 *******************************************************************/
 
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)dst8 & (TYPE_WIDTH - 1)) != WHILE_DEST_BREAK) {
        INC_VAL(dst8) = INC_VAL(src8);
        count--;
    }
 
    switch ((((UIntN)src8) PRE_SWITCH_ADJUST) & (TYPE_WIDTH - 1)) {
    case 0: COPY_NO_SHIFT(); break;
    case 1: COPY_SHIFT(1);   break;
    case 2: COPY_SHIFT(2);   break;
    case 3: COPY_SHIFT(3);   break;
    }
}
 

Compare with Previous | Blame | View Log

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.