1169691Skan/*- 2169691Skan * Copyright (c) 1990, 1993 3169691Skan * The Regents of the University of California. All rights reserved. 4169691Skan * 5169691Skan * This code is derived from software contributed to Berkeley by 6169691Skan * Chris Torek. 7169691Skan * 8169691Skan * Redistribution and use in source and binary forms, with or without 9169691Skan * modification, are permitted provided that the following conditions 10169691Skan * are met: 11169691Skan * 1. Redistributions of source code must retain the above copyright 12169691Skan * notice, this list of conditions and the following disclaimer. 13169691Skan * 2. Redistributions in binary form must reproduce the above copyright 14169691Skan * notice, this list of conditions and the following disclaimer in the 15169691Skan * documentation and/or other materials provided with the distribution. 16169691Skan * 3. Neither the name of the University nor the names of its contributors 17169691Skan * may be used to endorse or promote products derived from this software 18169691Skan * without specific prior written permission. 19169691Skan * 20169691Skan * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 21169691Skan * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22169691Skan * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 23169691Skan * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 24169691Skan * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 25169691Skan * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 26169691Skan * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 27169691Skan * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 28169691Skan * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 29169691Skan * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 30169691Skan * SUCH DAMAGE. 31169691Skan */ 32169691Skan 33169691Skan#if defined(LIBC_SCCS) && !defined(lint) 34169691Skanstatic char sccsid[] = "@(#)bcopy.c 8.1 (Berkeley) 6/4/93"; 35169691Skan#endif /* LIBC_SCCS and not lint */ 36169691Skan#include <sys/cdefs.h> 37169691Skan__FBSDID("$FreeBSD$"); 38169691Skan 39169691Skan#include <sys/types.h> 40169691Skan 41169691Skan/* 42169691Skan * sizeof(word) MUST BE A POWER OF TWO 43169691Skan * SO THAT wmask BELOW IS ALL ONES 44169691Skan */ 45169691Skantypedef int word; /* "word" used for optimal copy speed */ 46169691Skan 47169691Skan#define wsize sizeof(word) 48169691Skan#define wmask (wsize - 1) 49169691Skan 50169691Skan/* 51169691Skan * Copy a block of memory, handling overlap. 52169691Skan * This is the routine that actually implements 53169691Skan * (the portable versions of) bcopy, memcpy, and memmove. 54169691Skan */ 55169691Skan#if defined(MEMCOPY) || defined(MEMMOVE) 56169691Skan#include <string.h> 57169691Skan 58169691Skanvoid * 59169691Skan#ifdef MEMCOPY 60169691Skanmemcpy 61169691Skan#else 62169691Skanmemmove 63169691Skan#endif 64169691Skan(void *dst0, const void *src0, size_t length) 65169691Skan#else 66169691Skan#include <strings.h> 67169691Skan 68169691Skanvoid 69169691Skanbcopy(const void *src0, void *dst0, size_t length) 70169691Skan#endif 71169691Skan{ 72169691Skan char *dst = dst0; 73169691Skan const char *src = src0; 74169691Skan size_t t; 75169691Skan 76169691Skan if (length == 0 || dst == src) /* nothing to do */ 77169691Skan goto done; 78169691Skan 79169691Skan /* 80169691Skan * Macros: loop-t-times; and loop-t-times, t>0 81169691Skan */ 82169691Skan#define TLOOP(s) if (t) TLOOP1(s) 83169691Skan#define TLOOP1(s) do { s; } while (--t) 84169691Skan 85169691Skan if ((unsigned long)dst < (unsigned long)src) { 86169691Skan /* 87169691Skan * Copy forward. 88169691Skan */ 89169691Skan t = (uintptr_t)src; /* only need low bits */ 90169691Skan if ((t | (uintptr_t)dst) & wmask) { 91169691Skan /* 92169691Skan * Try to align operands. This cannot be done 93169691Skan * unless the low bits match. 94169691Skan */ 95169691Skan if ((t ^ (uintptr_t)dst) & wmask || length < wsize) 96169691Skan t = length; 97169691Skan else 98169691Skan t = wsize - (t & wmask); 99169691Skan length -= t; 100169691Skan TLOOP1(*dst++ = *src++); 101169691Skan } 102169691Skan /* 103169691Skan * Copy whole words, then mop up any trailing bytes. 104169691Skan */ 105169691Skan t = length / wsize; 106169691Skan TLOOP(*(word *)dst = *(word *)src; src += wsize; dst += wsize); 107169691Skan t = length & wmask; 108169691Skan TLOOP(*dst++ = *src++); 109169691Skan } else { 110169691Skan /* 111169691Skan * Copy backwards. Otherwise essentially the same. 112169691Skan * Alignment works as before, except that it takes 113169691Skan * (t&wmask) bytes to align, not wsize-(t&wmask). 114169691Skan */ 115169691Skan src += length; 116169691Skan dst += length; 117169691Skan t = (uintptr_t)src; 118169691Skan if ((t | (uintptr_t)dst) & wmask) { 119169691Skan if ((t ^ (uintptr_t)dst) & wmask || length <= wsize) 120169691Skan t = length; 121169691Skan else 122169691Skan t &= wmask; 123169691Skan length -= t; 124169691Skan TLOOP1(*--dst = *--src); 125169691Skan } 126169691Skan t = length / wsize; 127169691Skan TLOOP(src -= wsize; dst -= wsize; *(word *)dst = *(word *)src); 128169691Skan t = length & wmask; 129169691Skan TLOOP(*--dst = *--src); 130169691Skan } 131169691Skandone: 132169691Skan#if defined(MEMCOPY) || defined(MEMMOVE) 133169691Skan return (dst0); 134169691Skan#else 135169691Skan return; 136169691Skan#endif 137169691Skan} 138169691Skan