src/libc/memcopy.h

Go to the documentation of this file.
00001 
00007 /* memcopy.h -- definitions for memory copy functions.  Generic C version.
00008    Copyright (C) 1991, 1992, 1993, 1997, 2004 Free Software Foundation, Inc.
00009    This file is part of the GNU C Library.
00010    Contributed by Torbjorn Granlund (tege@sics.se).
00011 
00012    The GNU C Library is free software; you can redistribute it and/or
00013    modify it under the terms of the GNU Lesser General Public
00014    License as published by the Free Software Foundation; either
00015    version 2.1 of the License, or (at your option) any later version.
00016 
00017    The GNU C Library is distributed in the hope that it will be useful,
00018    but WITHOUT ANY WARRANTY; without even the implied warranty of
00019    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00020    Lesser General Public License for more details.
00021 
00022    You should have received a copy of the GNU Lesser General Public
00023    License along with the GNU C Library; if not, write to the Free
00024    Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
00025    02111-1307 USA.  */
00026 
00027 /* The strategy of the memory functions is:
00028 
00029      1. Copy bytes until the destination pointer is aligned.
00030 
00031      2. Copy words in unrolled loops.  If the source and destination
00032      are not aligned in the same way, use word memory operations,
00033      but shift and merge two read words before writing.
00034 
00035      3. Copy the few remaining bytes.
00036 
00037    This is fast on processors that have at least 10 registers for
00038    allocation by GCC, and that can access memory at reg+const in one
00039    instruction.
00040 
00041    I made an "exhaustive" test of this memmove when I wrote it,
00042    exhaustive in the sense that I tried all alignment and length
00043    combinations, with and without overlap.  */
00044 
00045 #include <sys/cdefs.h>
00046 #include <endian.h>
00047 #include "libc_internal.h"
00048 
00049 /* The macros defined in this file are:
00050 
00051    BYTE_COPY_FWD(dst_beg_ptr, src_beg_ptr, nbytes_to_copy)
00052 
00053    BYTE_COPY_BWD(dst_end_ptr, src_end_ptr, nbytes_to_copy)
00054 
00055    WORD_COPY_FWD(dst_beg_ptr, src_beg_ptr, nbytes_remaining, nbytes_to_copy)
00056 
00057    WORD_COPY_BWD(dst_end_ptr, src_end_ptr, nbytes_remaining, nbytes_to_copy)
00058 
00059    MERGE(old_word, sh_1, new_word, sh_2)
00060      [I fail to understand.  I feel stupid.  --roland]
00061 */
00062 
00063 /* Type to use for aligned memory operations.
00064    This should normally be the biggest type supported by a single load
00065    and store.  */
00066 #define op_t    unsigned long int
00067 #define OPSIZ   (sizeof(op_t))
00068 
00069 /* Type to use for unaligned operations.  */
00070 typedef unsigned char byte;
00071 
00072 /* Optimal type for storing bytes in registers.  */
00073 #define reg_char        char
00074 
00075 #if __BYTE_ORDER == __LITTLE_ENDIAN
00076 #define MERGE(w0, sh_1, w1, sh_2) (((w0) >> (sh_1)) | ((w1) << (sh_2)))
00077 #endif
00078 #if __BYTE_ORDER == __BIG_ENDIAN
00079 #define MERGE(w0, sh_1, w1, sh_2) (((w0) << (sh_1)) | ((w1) >> (sh_2)))
00080 #endif
00081 
00082 /* Copy exactly NBYTES bytes from SRC_BP to DST_BP,
00083    without any assumptions about alignment of the pointers.  */
00084 #define BYTE_COPY_FWD(dst_bp, src_bp, nbytes)                                 \
00085   do                                                                          \
00086     {                                                                         \
00087       size_t __nbytes = (nbytes);                                             \
00088       while (__nbytes > 0)                                                    \
00089         {                                                                     \
00090           byte __x = ((byte *) src_bp)[0];                                    \
00091           src_bp += 1;                                                        \
00092           __nbytes -= 1;                                                      \
00093           ((byte *) dst_bp)[0] = __x;                                         \
00094           dst_bp += 1;                                                        \
00095         }                                                                     \
00096     } while (0)
00097 
00098 /* Copy exactly NBYTES_TO_COPY bytes from SRC_END_PTR to DST_END_PTR,
00099    beginning at the bytes right before the pointers and continuing towards
00100    smaller addresses.  Don't assume anything about alignment of the
00101    pointers.  */
00102 #define BYTE_COPY_BWD(dst_ep, src_ep, nbytes)                                 \
00103   do                                                                          \
00104     {                                                                         \
00105       size_t __nbytes = (nbytes);                                             \
00106       while (__nbytes > 0)                                                    \
00107         {                                                                     \
00108           byte __x;                                                           \
00109           src_ep -= 1;                                                        \
00110           __x = ((byte *) src_ep)[0];                                         \
00111           dst_ep -= 1;                                                        \
00112           __nbytes -= 1;                                                      \
00113           ((byte *) dst_ep)[0] = __x;                                         \
00114         }                                                                     \
00115     } while (0)
00116 
00117 /* Copy *up to* NBYTES bytes from SRC_BP to DST_BP, with
00118    the assumption that DST_BP is aligned on an OPSIZ multiple.  If
00119    not all bytes could be easily copied, store remaining number of bytes
00120    in NBYTES_LEFT, otherwise store 0.  */
00121 #define WORD_COPY_FWD(dst_bp, src_bp, nbytes_left, nbytes)                    \
00122   do                                                                          \
00123     {                                                                         \
00124       if (src_bp % OPSIZ == 0)                                                \
00125         txc_libc_wordcopy_fwd_aligned (dst_bp, src_bp, (nbytes) / OPSIZ);             \
00126       else                                                                    \
00127         txc_libc_wordcopy_fwd_dest_aligned (dst_bp, src_bp, (nbytes) / OPSIZ);        \
00128       src_bp += (nbytes) & -OPSIZ;                                            \
00129       dst_bp += (nbytes) & -OPSIZ;                                            \
00130       (nbytes_left) = (nbytes) % OPSIZ;                                       \
00131     } while (0)
00132 
00133 /* Copy *up to* NBYTES_TO_COPY bytes from SRC_END_PTR to DST_END_PTR,
00134    beginning at the words (of type op_t) right before the pointers and
00135    continuing towards smaller addresses.  May take advantage of that
00136    DST_END_PTR is aligned on an OPSIZ multiple.  If not all bytes could be
00137    easily copied, store remaining number of bytes in NBYTES_REMAINING,
00138    otherwise store 0.  */
00139 #define WORD_COPY_BWD(dst_ep, src_ep, nbytes_left, nbytes)                    \
00140   do                                                                          \
00141     {                                                                         \
00142       if (src_ep % OPSIZ == 0)                                                \
00143         txc_libc_wordcopy_bwd_aligned (dst_ep, src_ep, (nbytes) / OPSIZ);             \
00144       else                                                                    \
00145         txc_libc_wordcopy_bwd_dest_aligned (dst_ep, src_ep, (nbytes) / OPSIZ);        \
00146       src_ep -= (nbytes) & -OPSIZ;                                            \
00147       dst_ep -= (nbytes) & -OPSIZ;                                            \
00148       (nbytes_left) = (nbytes) % OPSIZ;                                       \
00149     } while (0)
00150 
00151 
00152 /* Threshold value for when to enter the unrolled loops.  */
00153 #define OP_T_THRES      16

Generated on Wed Dec 9 20:32:39 2009 for xCalls by  doxygen 1.4.7