11573Srgrimes/*- 21573Srgrimes * Copyright (c) 1990, 1993 31573Srgrimes * The Regents of the University of California. All rights reserved. 41573Srgrimes * 51573Srgrimes * This code is derived from software contributed to Berkeley by 61573Srgrimes * Chris Torek. 71573Srgrimes * 81573Srgrimes * Redistribution and use in source and binary forms, with or without 91573Srgrimes * modification, are permitted provided that the following conditions 101573Srgrimes * are met: 111573Srgrimes * 1. Redistributions of source code must retain the above copyright 121573Srgrimes * notice, this list of conditions and the following disclaimer. 131573Srgrimes * 2. Redistributions in binary form must reproduce the above copyright 141573Srgrimes * notice, this list of conditions and the following disclaimer in the 151573Srgrimes * documentation and/or other materials provided with the distribution. 16251069Semaste * 3. Neither the name of the University nor the names of its contributors 171573Srgrimes * may be used to endorse or promote products derived from this software 181573Srgrimes * without specific prior written permission. 191573Srgrimes * 201573Srgrimes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 211573Srgrimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 221573Srgrimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 231573Srgrimes * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 241573Srgrimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 251573Srgrimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 261573Srgrimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 271573Srgrimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 281573Srgrimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 291573Srgrimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 301573Srgrimes * SUCH DAMAGE. 311573Srgrimes */ 321573Srgrimes 331573Srgrimes#if defined(LIBC_SCCS) && !defined(lint) 341573Srgrimesstatic char sccsid[] = "@(#)bcopy.c 8.1 (Berkeley) 6/4/93"; 351573Srgrimes#endif /* LIBC_SCCS and not lint */ 3686170Sobrien#include <sys/cdefs.h> 3786170Sobrien__FBSDID("$FreeBSD$"); 381573Srgrimes 39121531Speter#include <sys/types.h> 40121531Speter 411573Srgrimes/* 421573Srgrimes * sizeof(word) MUST BE A POWER OF TWO 431573Srgrimes * SO THAT wmask BELOW IS ALL ONES 441573Srgrimes */ 451573Srgrimestypedef int word; /* "word" used for optimal copy speed */ 461573Srgrimes 471573Srgrimes#define wsize sizeof(word) 481573Srgrimes#define wmask (wsize - 1) 491573Srgrimes 501573Srgrimes/* 511573Srgrimes * Copy a block of memory, handling overlap. 521573Srgrimes * This is the routine that actually implements 531573Srgrimes * (the portable versions of) bcopy, memcpy, and memmove. 541573Srgrimes */ 55102809Srobert#if defined(MEMCOPY) || defined(MEMMOVE) 56102809Srobert#include <string.h> 57102809Srobert 58102809Srobertvoid * 591573Srgrimes#ifdef MEMCOPY 60102809Srobertmemcpy 611573Srgrimes#else 62102809Srobertmemmove 63102809Srobert#endif 64102809Srobert(void *dst0, const void *src0, size_t length) 651573Srgrimes#else 66102809Srobert#include <strings.h> 67102809Srobert 681573Srgrimesvoid 69102809Srobertbcopy(const void *src0, void *dst0, size_t length) 701573Srgrimes#endif 711573Srgrimes{ 7292889Sobrien char *dst = dst0; 7392889Sobrien const char *src = src0; 7492889Sobrien size_t t; 751573Srgrimes 761573Srgrimes if (length == 0 || dst == src) /* nothing to do */ 771573Srgrimes goto done; 781573Srgrimes 791573Srgrimes /* 801573Srgrimes * Macros: loop-t-times; and loop-t-times, t>0 811573Srgrimes */ 821573Srgrimes#define TLOOP(s) if (t) TLOOP1(s) 831573Srgrimes#define TLOOP1(s) do { s; } while (--t) 841573Srgrimes 851573Srgrimes if ((unsigned long)dst < (unsigned long)src) { 861573Srgrimes /* 871573Srgrimes * Copy forward. 881573Srgrimes */ 89121531Speter t = (uintptr_t)src; /* only need low bits */ 90121531Speter if ((t | (uintptr_t)dst) & wmask) { 911573Srgrimes /* 921573Srgrimes * Try to align operands. This cannot be done 931573Srgrimes * unless the low bits match. 941573Srgrimes */ 95121531Speter if ((t ^ (uintptr_t)dst) & wmask || length < wsize) 961573Srgrimes t = length; 971573Srgrimes else 981573Srgrimes t = wsize - (t & wmask); 991573Srgrimes length -= t; 1001573Srgrimes TLOOP1(*dst++ = *src++); 1011573Srgrimes } 1021573Srgrimes /* 1031573Srgrimes * Copy whole words, then mop up any trailing bytes. 1041573Srgrimes */ 1051573Srgrimes t = length / wsize; 1061573Srgrimes TLOOP(*(word *)dst = *(word *)src; src += wsize; dst += wsize); 1071573Srgrimes t = length & wmask; 1081573Srgrimes TLOOP(*dst++ = *src++); 1091573Srgrimes } else { 1101573Srgrimes /* 1111573Srgrimes * Copy backwards. Otherwise essentially the same. 1121573Srgrimes * Alignment works as before, except that it takes 1131573Srgrimes * (t&wmask) bytes to align, not wsize-(t&wmask). 1141573Srgrimes */ 1151573Srgrimes src += length; 1161573Srgrimes dst += length; 117121531Speter t = (uintptr_t)src; 118121531Speter if ((t | (uintptr_t)dst) & wmask) { 119121531Speter if ((t ^ (uintptr_t)dst) & wmask || length <= wsize) 1201573Srgrimes t = length; 1211573Srgrimes else 1221573Srgrimes t &= wmask; 1231573Srgrimes length -= t; 1241573Srgrimes TLOOP1(*--dst = *--src); 1251573Srgrimes } 1261573Srgrimes t = length / wsize; 1271573Srgrimes TLOOP(src -= wsize; dst -= wsize; *(word *)dst = *(word *)src); 1281573Srgrimes t = length & wmask; 1291573Srgrimes TLOOP(*--dst = *--src); 1301573Srgrimes } 1311573Srgrimesdone: 1321573Srgrimes#if defined(MEMCOPY) || defined(MEMMOVE) 1331573Srgrimes return (dst0); 1341573Srgrimes#else 1351573Srgrimes return; 1361573Srgrimes#endif 1371573Srgrimes} 138