1 // SPDX-License-Identifier: BSD-3-Clause 2 /* 3 * Copyright (c) 1994-2009 Red Hat, Inc. 4 * All rights reserved. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions are met: 8 * 9 * 1. Redistributions of source code must retain the above copyright notice, 10 * this list of conditions and the following disclaimer. 11 * 12 * 2. Redistributions in binary form must reproduce the above copyright notice, 13 * this list of conditions and the following disclaimer in the documentation 14 * and/or other materials provided with the distribution. 15 * 16 * 3. Neither the name of the copyright holder nor the names of its 17 * contributors may be used to endorse or promote products derived from this 18 * software without specific prior written permission. 19 * 20 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 21 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 23 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 24 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 25 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 26 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 27 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 28 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 29 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 30 * POSSIBILITY OF SUCH DAMAGE. 31 */ 32 33 /* 34 FUNCTION 35 <<memcpy>>---copy memory regions 36 37 ANSI_SYNOPSIS 38 #include <string.h> 39 void* memcpy(void *<[out]>, const void *<[in]>, size_t <[n]>); 40 41 TRAD_SYNOPSIS 42 #include <string.h> 43 void *memcpy(<[out]>, <[in]>, <[n]> 44 void *<[out]>; 45 void *<[in]>; 46 size_t <[n]>; 47 48 DESCRIPTION 49 This function copies <[n]> bytes from the memory region 50 pointed to by <[in]> to the memory region pointed to by 51 <[out]>. 52 53 If the regions overlap, the behavior is undefined. 54 55 RETURNS 56 <<memcpy>> returns a pointer to the first byte of the <[out]> 57 region. 58 59 PORTABILITY 60 <<memcpy>> is ANSI C. 61 62 <<memcpy>> requires no supporting OS subroutines. 63 64 QUICKREF 65 memcpy ansi pure 66 */ 67 68 #include "_ansi.h" 69 #include <string.h> 70 71 /* Nonzero if either X or Y is not aligned on a "long" boundary. */ 72 #define UNALIGNED(X, Y) \ 73 (((long)X & (sizeof(long) - 1)) | ((long)Y & (sizeof(long) - 1))) 74 75 /* How many bytes are copied each iteration of the 4X unrolled loop. */ 76 #define BIGBLOCKSIZE (sizeof(long) << 2) 77 78 /* How many bytes are copied each iteration of the word copy loop. */ 79 #define LITTLEBLOCKSIZE (sizeof(long)) 80 81 /* Threshhold for punting to the byte copier. */ 82 #define TOO_SMALL(LEN) ((LEN) < BIGBLOCKSIZE) 83 84 _PTR 85 _DEFUN(memcpy, (dst0, src0, len0), _PTR dst0 _AND _CONST _PTR src0 _AND 86 size_t len0) 87 { 88 #if defined(PREFER_SIZE_OVER_SPEED) || defined(__OPTIMIZE_SIZE__) 89 char *dst = (char *)dst0; 90 char *src = (char *)src0; 91 92 _PTR save = dst0; 93 94 while (len0--) 95 *dst++ = *src++; 96 97 return save; 98 #else 99 char *dst = dst0; 100 _CONST char *src = src0; 101 long *aligned_dst; 102 _CONST long *aligned_src; 103 104 /* If the size is small, or either SRC or DST is unaligned, 105 then punt into the byte copy loop. This should be rare. */ 106 if (!TOO_SMALL(len0) && !UNALIGNED(src, dst)) { 107 aligned_dst = (long *)dst; 108 aligned_src = (long *)src; 109 110 /* Copy 4X long words at a time if possible. */ 111 while (len0 >= BIGBLOCKSIZE) { 112 *aligned_dst++ = *aligned_src++; 113 *aligned_dst++ = *aligned_src++; 114 *aligned_dst++ = *aligned_src++; 115 *aligned_dst++ = *aligned_src++; 116 len0 -= BIGBLOCKSIZE; 117 } 118 119 /* Copy one long word at a time if possible. */ 120 while (len0 >= LITTLEBLOCKSIZE) { 121 *aligned_dst++ = *aligned_src++; 122 len0 -= LITTLEBLOCKSIZE; 123 } 124 125 /* Pick up any residual with a byte copier. */ 126 dst = (char *)aligned_dst; 127 src = (char *)aligned_src; 128 } 129 130 while (len0--) 131 *dst++ = *src++; 132 133 return dst0; 134 #endif /* not PREFER_SIZE_OVER_SPEED */ 135 } 136