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 <<memmove>>---move possibly overlapping memory 36 37 INDEX 38 memmove 39 40 ANSI_SYNOPSIS 41 #include <string.h> 42 void *memmove(void *<[dst]>, const void *<[src]>, size_t <[length]>); 43 44 TRAD_SYNOPSIS 45 #include <string.h> 46 void *memmove(<[dst]>, <[src]>, <[length]>) 47 void *<[dst]>; 48 void *<[src]>; 49 size_t <[length]>; 50 51 DESCRIPTION 52 This function moves <[length]> characters from the block of 53 memory starting at <<*<[src]>>> to the memory starting at 54 <<*<[dst]>>>. <<memmove>> reproduces the characters correctly 55 at <<*<[dst]>>> even if the two areas overlap. 56 57 RETURNS 58 The function returns <[dst]> as passed. 59 60 PORTABILITY 61 <<memmove>> is ANSI C. 62 63 <<memmove>> requires no supporting OS subroutines. 64 65 QUICKREF 66 memmove ansi pure 67 */ 68 69 #include <string.h> 70 #include "_ansi.h" 71 #include <stddef.h> 72 #include <limits.h> 73 74 /* Nonzero if either X or Y is not aligned on a "long" boundary. */ 75 #define UNALIGNED(X, Y) \ 76 (((long)X & (sizeof(long) - 1)) | ((long)Y & (sizeof(long) - 1))) 77 78 /* How many bytes are copied each iteration of the 4X unrolled loop. */ 79 #define BIGBLOCKSIZE (sizeof(long) << 2) 80 81 /* How many bytes are copied each iteration of the word copy loop. */ 82 #define LITTLEBLOCKSIZE (sizeof(long)) 83 84 /* Threshhold for punting to the byte copier. */ 85 #define TOO_SMALL(LEN) ((LEN) < BIGBLOCKSIZE) 86 87 /* SUPPRESS 20 */ 88 _PTR 89 _DEFUN(memmove, (dst_void, src_void, length), _PTR dst_void _AND _CONST _PTR 90 src_void _AND size_t length) 91 { 92 #if defined(PREFER_SIZE_OVER_SPEED) || defined(__OPTIMIZE_SIZE__) 93 char *dst = dst_void; 94 _CONST char *src = src_void; 95 96 if (src < dst && dst < src + length) { 97 /* Have to copy backwards */ 98 src += length; 99 dst += length; 100 while (length--) 101 *--dst = *--src; 102 } else { 103 while (length--) 104 *dst++ = *src++; 105 } 106 107 return dst_void; 108 #else 109 char *dst = dst_void; 110 _CONST char *src = src_void; 111 long *aligned_dst; 112 _CONST long *aligned_src; 113 114 if (src < dst && dst < src + length) { 115 /* Destructive overlap...have to copy backwards */ 116 src += length; 117 dst += length; 118 while (length--) 119 *--dst = *--src; 120 } else { 121 /* 122 * Use optimizing algorithm for a non-destructive copy to 123 * closely match memcpy. If the size is small or either SRC or 124 * DST is unaligned, then punt into the byte copy loop. This 125 * should be rare. 126 */ 127 if (!TOO_SMALL(length) && !UNALIGNED(src, dst)) { 128 aligned_dst = (long *)dst; 129 aligned_src = (long *)src; 130 131 /* Copy 4X long words at a time if possible. */ 132 while (length >= BIGBLOCKSIZE) { 133 *aligned_dst++ = *aligned_src++; 134 *aligned_dst++ = *aligned_src++; 135 *aligned_dst++ = *aligned_src++; 136 *aligned_dst++ = *aligned_src++; 137 length -= BIGBLOCKSIZE; 138 } 139 140 /* Copy one long word at a time if possible. */ 141 while (length >= LITTLEBLOCKSIZE) { 142 *aligned_dst++ = *aligned_src++; 143 length -= LITTLEBLOCKSIZE; 144 } 145 146 /* Pick up any residual with a byte copier. */ 147 dst = (char *)aligned_dst; 148 src = (char *)aligned_src; 149 } 150 151 while (length--) 152 *dst++ = *src++; 153 } 154 155 return dst_void; 156 #endif /* not PREFER_SIZE_OVER_SPEED */ 157 } 158