1*5aa07b05SWarner Losh /*- 2*5aa07b05SWarner Losh * SPDX-License-Identifier: BSD-3-Clause 3*5aa07b05SWarner Losh * Copyright (c) 1990 The Regents of the University of California. 4*5aa07b05SWarner Losh * 5*5aa07b05SWarner Losh * All rights reserved. 6*5aa07b05SWarner Losh * 7*5aa07b05SWarner Losh * This code is derived from software contributed to Berkeley by 8*5aa07b05SWarner Losh * Chris Torek. 9*5aa07b05SWarner Losh * 10*5aa07b05SWarner Losh * Redistribution and use in source and binary forms, with or without 11*5aa07b05SWarner Losh * modification, are permitted provided that the following conditions 12*5aa07b05SWarner Losh * are met: 13*5aa07b05SWarner Losh * 1. Redistributions of source code must retain the above copyright 14*5aa07b05SWarner Losh * notice, this list of conditions and the following disclaimer. 15*5aa07b05SWarner Losh * 2. Redistributions in binary form must reproduce the above copyright 16*5aa07b05SWarner Losh * notice, this list of conditions and the following disclaimer in the 17*5aa07b05SWarner Losh * documentation and/or other materials provided with the distribution. 18*5aa07b05SWarner Losh * 3. Neither the name of the University nor the names of its contributors 19*5aa07b05SWarner Losh * may be used to endorse or promote products derived from this software 20*5aa07b05SWarner Losh * without specific prior written permission. 21*5aa07b05SWarner Losh * 22*5aa07b05SWarner Losh * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 23*5aa07b05SWarner Losh * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 24*5aa07b05SWarner Losh * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 25*5aa07b05SWarner Losh * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 26*5aa07b05SWarner Losh * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 27*5aa07b05SWarner Losh * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 28*5aa07b05SWarner Losh * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 29*5aa07b05SWarner Losh * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 30*5aa07b05SWarner Losh * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 31*5aa07b05SWarner Losh * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 32*5aa07b05SWarner Losh * SUCH DAMAGE. 33*5aa07b05SWarner Losh */ 34*5aa07b05SWarner Losh 35*5aa07b05SWarner Losh #if defined(LIBC_SCCS) && !defined(lint) 36*5aa07b05SWarner Losh #if 0 37*5aa07b05SWarner Losh static char *sccsid = "from: @(#)bcopy.c 5.11 (Berkeley) 6/21/91"; 38*5aa07b05SWarner Losh #endif 39*5aa07b05SWarner Losh #if 0 40*5aa07b05SWarner Losh static char *rcsid = "$NetBSD: bcopy.c,v 1.2 1997/04/16 22:09:41 thorpej Exp $"; 41*5aa07b05SWarner Losh #endif 42*5aa07b05SWarner Losh #endif /* LIBC_SCCS and not lint */ 43*5aa07b05SWarner Losh #include <sys/cdefs.h> 44*5aa07b05SWarner Losh __FBSDID("$FreeBSD$"); 45*5aa07b05SWarner Losh 46*5aa07b05SWarner Losh #include <sys/param.h> 47*5aa07b05SWarner Losh #ifdef _KERNEL 48*5aa07b05SWarner Losh #include <sys/systm.h> 49*5aa07b05SWarner Losh #else 50*5aa07b05SWarner Losh #include <string.h> 51*5aa07b05SWarner Losh #endif 52*5aa07b05SWarner Losh 53*5aa07b05SWarner Losh /* 54*5aa07b05SWarner Losh * sizeof(word) MUST BE A POWER OF TWO 55*5aa07b05SWarner Losh * SO THAT wmask BELOW IS ALL ONES 56*5aa07b05SWarner Losh */ 57*5aa07b05SWarner Losh typedef long word; /* "word" used for optimal copy speed */ 58*5aa07b05SWarner Losh 59*5aa07b05SWarner Losh #define wsize sizeof(word) 60*5aa07b05SWarner Losh #define wmask (wsize - 1) 61*5aa07b05SWarner Losh 62*5aa07b05SWarner Losh /* 63*5aa07b05SWarner Losh * Copy a block of memory, handling overlap. 64*5aa07b05SWarner Losh * This is the routine that actually implements 65*5aa07b05SWarner Losh * (the portable versions of) bcopy, memcpy, and memmove. 66*5aa07b05SWarner Losh */ 67*5aa07b05SWarner Losh void * 68*5aa07b05SWarner Losh memcpy(void *dst0, const void *src0, size_t length) 69*5aa07b05SWarner Losh { 70*5aa07b05SWarner Losh char *dst; 71*5aa07b05SWarner Losh const char *src; 72*5aa07b05SWarner Losh size_t t; 73*5aa07b05SWarner Losh 74*5aa07b05SWarner Losh dst = dst0; 75*5aa07b05SWarner Losh src = src0; 76*5aa07b05SWarner Losh 77*5aa07b05SWarner Losh if (length == 0 || dst == src) { /* nothing to do */ 78*5aa07b05SWarner Losh goto done; 79*5aa07b05SWarner Losh } 80*5aa07b05SWarner Losh 81*5aa07b05SWarner Losh /* 82*5aa07b05SWarner Losh * Macros: loop-t-times; and loop-t-times, t>0 83*5aa07b05SWarner Losh */ 84*5aa07b05SWarner Losh #define TLOOP(s) if (t) TLOOP1(s) 85*5aa07b05SWarner Losh #define TLOOP1(s) do { s; } while (--t) 86*5aa07b05SWarner Losh 87*5aa07b05SWarner Losh if ((unsigned long)dst < (unsigned long)src) { 88*5aa07b05SWarner Losh /* 89*5aa07b05SWarner Losh * Copy forward. 90*5aa07b05SWarner Losh */ 91*5aa07b05SWarner Losh t = (size_t)src; /* only need low bits */ 92*5aa07b05SWarner Losh 93*5aa07b05SWarner Losh if ((t | (uintptr_t)dst) & wmask) { 94*5aa07b05SWarner Losh /* 95*5aa07b05SWarner Losh * Try to align operands. This cannot be done 96*5aa07b05SWarner Losh * unless the low bits match. 97*5aa07b05SWarner Losh */ 98*5aa07b05SWarner Losh if ((t ^ (uintptr_t)dst) & wmask || length < wsize) { 99*5aa07b05SWarner Losh t = length; 100*5aa07b05SWarner Losh } else { 101*5aa07b05SWarner Losh t = wsize - (t & wmask); 102*5aa07b05SWarner Losh } 103*5aa07b05SWarner Losh 104*5aa07b05SWarner Losh length -= t; 105*5aa07b05SWarner Losh TLOOP1(*dst++ = *src++); 106*5aa07b05SWarner Losh } 107*5aa07b05SWarner Losh /* 108*5aa07b05SWarner Losh * Copy whole words, then mop up any trailing bytes. 109*5aa07b05SWarner Losh */ 110*5aa07b05SWarner Losh t = length / wsize; 111*5aa07b05SWarner Losh TLOOP(*(word *)dst = *(const word *)src; src += wsize; 112*5aa07b05SWarner Losh dst += wsize); 113*5aa07b05SWarner Losh t = length & wmask; 114*5aa07b05SWarner Losh TLOOP(*dst++ = *src++); 115*5aa07b05SWarner Losh } else { 116*5aa07b05SWarner Losh /* 117*5aa07b05SWarner Losh * Copy backwards. Otherwise essentially the same. 118*5aa07b05SWarner Losh * Alignment works as before, except that it takes 119*5aa07b05SWarner Losh * (t&wmask) bytes to align, not wsize-(t&wmask). 120*5aa07b05SWarner Losh */ 121*5aa07b05SWarner Losh src += length; 122*5aa07b05SWarner Losh dst += length; 123*5aa07b05SWarner Losh t = (uintptr_t)src; 124*5aa07b05SWarner Losh 125*5aa07b05SWarner Losh if ((t | (uintptr_t)dst) & wmask) { 126*5aa07b05SWarner Losh if ((t ^ (uintptr_t)dst) & wmask || length <= wsize) { 127*5aa07b05SWarner Losh t = length; 128*5aa07b05SWarner Losh } else { 129*5aa07b05SWarner Losh t &= wmask; 130*5aa07b05SWarner Losh } 131*5aa07b05SWarner Losh 132*5aa07b05SWarner Losh length -= t; 133*5aa07b05SWarner Losh TLOOP1(*--dst = *--src); 134*5aa07b05SWarner Losh } 135*5aa07b05SWarner Losh t = length / wsize; 136*5aa07b05SWarner Losh TLOOP(src -= wsize; dst -= wsize; 137*5aa07b05SWarner Losh *(word *)dst = *(const word *)src); 138*5aa07b05SWarner Losh t = length & wmask; 139*5aa07b05SWarner Losh TLOOP(*--dst = *--src); 140*5aa07b05SWarner Losh } 141*5aa07b05SWarner Losh done: 142*5aa07b05SWarner Losh return (dst0); 143*5aa07b05SWarner Losh } 144*5aa07b05SWarner Losh 145*5aa07b05SWarner Losh void 146*5aa07b05SWarner Losh (bcopy)(const void *src0, void *dst0, size_t length) 147*5aa07b05SWarner Losh { 148*5aa07b05SWarner Losh 149*5aa07b05SWarner Losh memcpy(dst0, src0, length); 150*5aa07b05SWarner Losh } 151*5aa07b05SWarner Losh 152