1*b6cbf720SGianluca Guida /* $NetBSD: bcopy.c,v 1.9 2009/03/18 12:25:06 tsutsui Exp $ */ 2*b6cbf720SGianluca Guida 3*b6cbf720SGianluca Guida /*- 4*b6cbf720SGianluca Guida * Copyright (c) 1990, 1993 5*b6cbf720SGianluca Guida * The Regents of the University of California. All rights reserved. 6*b6cbf720SGianluca Guida * 7*b6cbf720SGianluca Guida * This code is derived from software contributed to Berkeley by 8*b6cbf720SGianluca Guida * Chris Torek. 9*b6cbf720SGianluca Guida * 10*b6cbf720SGianluca Guida * Redistribution and use in source and binary forms, with or without 11*b6cbf720SGianluca Guida * modification, are permitted provided that the following conditions 12*b6cbf720SGianluca Guida * are met: 13*b6cbf720SGianluca Guida * 1. Redistributions of source code must retain the above copyright 14*b6cbf720SGianluca Guida * notice, this list of conditions and the following disclaimer. 15*b6cbf720SGianluca Guida * 2. Redistributions in binary form must reproduce the above copyright 16*b6cbf720SGianluca Guida * notice, this list of conditions and the following disclaimer in the 17*b6cbf720SGianluca Guida * documentation and/or other materials provided with the distribution. 18*b6cbf720SGianluca Guida * 3. Neither the name of the University nor the names of its contributors 19*b6cbf720SGianluca Guida * may be used to endorse or promote products derived from this software 20*b6cbf720SGianluca Guida * without specific prior written permission. 21*b6cbf720SGianluca Guida * 22*b6cbf720SGianluca Guida * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 23*b6cbf720SGianluca Guida * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 24*b6cbf720SGianluca Guida * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 25*b6cbf720SGianluca Guida * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 26*b6cbf720SGianluca Guida * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 27*b6cbf720SGianluca Guida * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 28*b6cbf720SGianluca Guida * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 29*b6cbf720SGianluca Guida * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 30*b6cbf720SGianluca Guida * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 31*b6cbf720SGianluca Guida * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 32*b6cbf720SGianluca Guida * SUCH DAMAGE. 33*b6cbf720SGianluca Guida */ 34*b6cbf720SGianluca Guida 35*b6cbf720SGianluca Guida #include <sys/cdefs.h> 36*b6cbf720SGianluca Guida #if defined(LIBC_SCCS) && !defined(lint) 37*b6cbf720SGianluca Guida #if 0 38*b6cbf720SGianluca Guida static char sccsid[] = "@(#)bcopy.c 8.1 (Berkeley) 6/4/93"; 39*b6cbf720SGianluca Guida #else 40*b6cbf720SGianluca Guida __RCSID("$NetBSD: bcopy.c,v 1.9 2009/03/18 12:25:06 tsutsui Exp $"); 41*b6cbf720SGianluca Guida #endif 42*b6cbf720SGianluca Guida #endif /* LIBC_SCCS and not lint */ 43*b6cbf720SGianluca Guida 44*b6cbf720SGianluca Guida #if !defined(_KERNEL) && !defined(_STANDALONE) 45*b6cbf720SGianluca Guida #include <assert.h> 46*b6cbf720SGianluca Guida #include <string.h> 47*b6cbf720SGianluca Guida #else 48*b6cbf720SGianluca Guida #include <lib/libkern/libkern.h> 49*b6cbf720SGianluca Guida #if !defined(MEMCOPY) && defined(_STANDALONE) 50*b6cbf720SGianluca Guida #include <lib/libsa/stand.h> 51*b6cbf720SGianluca Guida #endif 52*b6cbf720SGianluca Guida #endif 53*b6cbf720SGianluca Guida 54*b6cbf720SGianluca Guida #ifdef _FORTIFY_SOURCE 55*b6cbf720SGianluca Guida #undef bcopy 56*b6cbf720SGianluca Guida #undef memcpy 57*b6cbf720SGianluca Guida #undef memmove 58*b6cbf720SGianluca Guida #endif 59*b6cbf720SGianluca Guida 60*b6cbf720SGianluca Guida #ifndef __OPTIMIZE_SIZE__ 61*b6cbf720SGianluca Guida /* 62*b6cbf720SGianluca Guida * sizeof(word) MUST BE A POWER OF TWO 63*b6cbf720SGianluca Guida * SO THAT wmask BELOW IS ALL ONES 64*b6cbf720SGianluca Guida */ 65*b6cbf720SGianluca Guida typedef long word; /* "word" used for optimal copy speed */ 66*b6cbf720SGianluca Guida 67*b6cbf720SGianluca Guida #define wsize sizeof(word) 68*b6cbf720SGianluca Guida #define wmask (wsize - 1) 69*b6cbf720SGianluca Guida 70*b6cbf720SGianluca Guida /* 71*b6cbf720SGianluca Guida * Copy a block of memory, handling overlap. 72*b6cbf720SGianluca Guida * This is the routine that actually implements 73*b6cbf720SGianluca Guida * (the portable versions of) bcopy, memcpy, and memmove. 74*b6cbf720SGianluca Guida */ 75*b6cbf720SGianluca Guida #if defined(MEMCOPY) 76*b6cbf720SGianluca Guida void * 77*b6cbf720SGianluca Guida memcpy(void *dst0, const void *src0, size_t length) 78*b6cbf720SGianluca Guida #elif defined(MEMMOVE) 79*b6cbf720SGianluca Guida void * 80*b6cbf720SGianluca Guida memmove(void *dst0, const void *src0, size_t length) 81*b6cbf720SGianluca Guida #else 82*b6cbf720SGianluca Guida void 83*b6cbf720SGianluca Guida bcopy(const void *src0, void *dst0, size_t length) 84*b6cbf720SGianluca Guida #endif 85*b6cbf720SGianluca Guida { 86*b6cbf720SGianluca Guida char *dst = dst0; 87*b6cbf720SGianluca Guida const char *src = src0; 88*b6cbf720SGianluca Guida size_t t; 89*b6cbf720SGianluca Guida unsigned long u; 90*b6cbf720SGianluca Guida 91*b6cbf720SGianluca Guida #if !defined(_KERNEL) 92*b6cbf720SGianluca Guida _DIAGASSERT(dst0 != 0); 93*b6cbf720SGianluca Guida _DIAGASSERT(src0 != 0); 94*b6cbf720SGianluca Guida #endif 95*b6cbf720SGianluca Guida 96*b6cbf720SGianluca Guida if (length == 0 || dst == src) /* nothing to do */ 97*b6cbf720SGianluca Guida goto done; 98*b6cbf720SGianluca Guida 99*b6cbf720SGianluca Guida /* 100*b6cbf720SGianluca Guida * Macros: loop-t-times; and loop-t-times, t>0 101*b6cbf720SGianluca Guida */ 102*b6cbf720SGianluca Guida #define TLOOP(s) if (t) TLOOP1(s) 103*b6cbf720SGianluca Guida #define TLOOP1(s) do { s; } while (--t) 104*b6cbf720SGianluca Guida 105*b6cbf720SGianluca Guida if ((unsigned long)dst < (unsigned long)src) { 106*b6cbf720SGianluca Guida /* 107*b6cbf720SGianluca Guida * Copy forward. 108*b6cbf720SGianluca Guida */ 109*b6cbf720SGianluca Guida u = (unsigned long)src; /* only need low bits */ 110*b6cbf720SGianluca Guida if ((u | (unsigned long)dst) & wmask) { 111*b6cbf720SGianluca Guida /* 112*b6cbf720SGianluca Guida * Try to align operands. This cannot be done 113*b6cbf720SGianluca Guida * unless the low bits match. 114*b6cbf720SGianluca Guida */ 115*b6cbf720SGianluca Guida if ((u ^ (unsigned long)dst) & wmask || length < wsize) 116*b6cbf720SGianluca Guida t = length; 117*b6cbf720SGianluca Guida else 118*b6cbf720SGianluca Guida t = wsize - (size_t)(u & wmask); 119*b6cbf720SGianluca Guida length -= t; 120*b6cbf720SGianluca Guida TLOOP1(*dst++ = *src++); 121*b6cbf720SGianluca Guida } 122*b6cbf720SGianluca Guida /* 123*b6cbf720SGianluca Guida * Copy whole words, then mop up any trailing bytes. 124*b6cbf720SGianluca Guida */ 125*b6cbf720SGianluca Guida t = length / wsize; 126*b6cbf720SGianluca Guida TLOOP(*(word *)(void *)dst = *(const word *)(const void *)src; src += wsize; dst += wsize); 127*b6cbf720SGianluca Guida t = length & wmask; 128*b6cbf720SGianluca Guida TLOOP(*dst++ = *src++); 129*b6cbf720SGianluca Guida } else { 130*b6cbf720SGianluca Guida /* 131*b6cbf720SGianluca Guida * Copy backwards. Otherwise essentially the same. 132*b6cbf720SGianluca Guida * Alignment works as before, except that it takes 133*b6cbf720SGianluca Guida * (t&wmask) bytes to align, not wsize-(t&wmask). 134*b6cbf720SGianluca Guida */ 135*b6cbf720SGianluca Guida src += length; 136*b6cbf720SGianluca Guida dst += length; 137*b6cbf720SGianluca Guida _DIAGASSERT((unsigned long)dst >= (unsigned long)dst0); 138*b6cbf720SGianluca Guida _DIAGASSERT((unsigned long)src >= (unsigned long)src0); 139*b6cbf720SGianluca Guida u = (unsigned long)src; 140*b6cbf720SGianluca Guida if ((u | (unsigned long)dst) & wmask) { 141*b6cbf720SGianluca Guida if ((u ^ (unsigned long)dst) & wmask || length <= wsize) 142*b6cbf720SGianluca Guida t = length; 143*b6cbf720SGianluca Guida else 144*b6cbf720SGianluca Guida t = (size_t)(u & wmask); 145*b6cbf720SGianluca Guida length -= t; 146*b6cbf720SGianluca Guida TLOOP1(*--dst = *--src); 147*b6cbf720SGianluca Guida } 148*b6cbf720SGianluca Guida t = length / wsize; 149*b6cbf720SGianluca Guida TLOOP(src -= wsize; dst -= wsize; *(word *)(void *)dst = *(const word *)(const void *)src); 150*b6cbf720SGianluca Guida t = length & wmask; 151*b6cbf720SGianluca Guida TLOOP(*--dst = *--src); 152*b6cbf720SGianluca Guida } 153*b6cbf720SGianluca Guida done: 154*b6cbf720SGianluca Guida #if defined(MEMCOPY) || defined(MEMMOVE) 155*b6cbf720SGianluca Guida return (dst0); 156*b6cbf720SGianluca Guida #else 157*b6cbf720SGianluca Guida return; 158*b6cbf720SGianluca Guida #endif 159*b6cbf720SGianluca Guida } 160*b6cbf720SGianluca Guida #else /* __OPTIMIZE_SIZE__ */ 161*b6cbf720SGianluca Guida #if defined(MEMCOPY) 162*b6cbf720SGianluca Guida /* 163*b6cbf720SGianluca Guida * This is designed to be small, not fast. 164*b6cbf720SGianluca Guida */ 165*b6cbf720SGianluca Guida void * 166*b6cbf720SGianluca Guida memcpy(void *s1, const void *s2, size_t n) 167*b6cbf720SGianluca Guida { 168*b6cbf720SGianluca Guida const char *f = s2; 169*b6cbf720SGianluca Guida char *t = s1; 170*b6cbf720SGianluca Guida 171*b6cbf720SGianluca Guida while (n-- > 0) 172*b6cbf720SGianluca Guida *t++ = *f++; 173*b6cbf720SGianluca Guida return s1; 174*b6cbf720SGianluca Guida } 175*b6cbf720SGianluca Guida #elif defined(MEMMOVE) 176*b6cbf720SGianluca Guida /* 177*b6cbf720SGianluca Guida * This is designed to be small, not fast. 178*b6cbf720SGianluca Guida */ 179*b6cbf720SGianluca Guida void * 180*b6cbf720SGianluca Guida memmove(void *s1, const void *s2, size_t n) 181*b6cbf720SGianluca Guida { 182*b6cbf720SGianluca Guida const char *f = s2; 183*b6cbf720SGianluca Guida char *t = s1; 184*b6cbf720SGianluca Guida 185*b6cbf720SGianluca Guida if (f < t) { 186*b6cbf720SGianluca Guida f += n; 187*b6cbf720SGianluca Guida t += n; 188*b6cbf720SGianluca Guida while (n-- > 0) 189*b6cbf720SGianluca Guida *--t = *--f; 190*b6cbf720SGianluca Guida } else { 191*b6cbf720SGianluca Guida while (n-- > 0) 192*b6cbf720SGianluca Guida *t++ = *f++; 193*b6cbf720SGianluca Guida } 194*b6cbf720SGianluca Guida return s1; 195*b6cbf720SGianluca Guida } 196*b6cbf720SGianluca Guida #else 197*b6cbf720SGianluca Guida /* 198*b6cbf720SGianluca Guida * This is designed to be small, not fast. 199*b6cbf720SGianluca Guida */ 200*b6cbf720SGianluca Guida void 201*b6cbf720SGianluca Guida bcopy(const void *s2, void *s1, size_t n) 202*b6cbf720SGianluca Guida { 203*b6cbf720SGianluca Guida const char *f = s2; 204*b6cbf720SGianluca Guida char *t = s1; 205*b6cbf720SGianluca Guida 206*b6cbf720SGianluca Guida while (n-- > 0) 207*b6cbf720SGianluca Guida *t++ = *f++; 208*b6cbf720SGianluca Guida } 209*b6cbf720SGianluca Guida #endif 210*b6cbf720SGianluca Guida #endif /* __OPTIMIZE_SIZE__ */ 211