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