1*42145Sbostic /*- 2*42145Sbostic * Copyright (c) 1990 The Regents of the University of California. 335110Sbostic * All rights reserved. 435110Sbostic * 5*42145Sbostic * This code is derived from software contributed to Berkeley by 6*42145Sbostic * Chris Torek. 7*42145Sbostic * 8*42145Sbostic * %sccs.include.redist.c% 930423Smckusick */ 1030423Smckusick 1130423Smckusick #if defined(LIBC_SCCS) && !defined(lint) 12*42145Sbostic static char sccsid[] = "@(#)bcopy.c 5.7 (Berkeley) 05/16/90"; 1335110Sbostic #endif /* LIBC_SCCS and not lint */ 1430423Smckusick 15*42145Sbostic #include <sys/stdc.h> 16*42145Sbostic #include <string.h> 1737105Sbostic 1830423Smckusick /* 19*42145Sbostic * sizeof(word) MUST BE A POWER OF TWO 20*42145Sbostic * SO THAT wmask BELOW IS ALL ONES 2130423Smckusick */ 22*42145Sbostic typedef int word; /* "word" used for optimal copy speed */ 2338485Skarels 24*42145Sbostic #define wsize sizeof(word) 25*42145Sbostic #define wmask (wsize - 1) 2638485Skarels 27*42145Sbostic /* 28*42145Sbostic * Copy a block of memory, handling overlap. 29*42145Sbostic * This is the routine that actually implements 30*42145Sbostic * (the portable versions of) bcopy, memcpy, and memmove. 31*42145Sbostic */ 32*42145Sbostic void 33*42145Sbostic bcopy(src0, dst0, length) 34*42145Sbostic char *dst0; 35*42145Sbostic const char *src0; 36*42145Sbostic register size_t length; 3730423Smckusick { 38*42145Sbostic register char *dst = dst0; 39*42145Sbostic register const char *src = src0; 40*42145Sbostic register size_t t; 41*42145Sbostic 42*42145Sbostic if (length == 0 || dst == src) /* nothing to do */ 43*42145Sbostic return; 44*42145Sbostic 45*42145Sbostic /* 46*42145Sbostic * Macros: loop-t-times; and loop-t-times, t>0 47*42145Sbostic */ 48*42145Sbostic #define TLOOP(s) if (t) TLOOP1(s) 49*42145Sbostic #define TLOOP1(s) do { s; } while (--t) 50*42145Sbostic 51*42145Sbostic if ((unsigned long)dst < (unsigned long)src) { 52*42145Sbostic /* 53*42145Sbostic * Copy forward. 54*42145Sbostic */ 55*42145Sbostic t = (int)src; /* only need low bits */ 56*42145Sbostic if ((t | (int)dst) & wmask) { 57*42145Sbostic /* 58*42145Sbostic * Try to align operands. This cannot be done 59*42145Sbostic * unless the low bits match. 60*42145Sbostic */ 61*42145Sbostic if ((t ^ (int)dst) & wmask || length < wsize) 62*42145Sbostic t = length; 63*42145Sbostic else 64*42145Sbostic t = wsize - (t & wmask); 65*42145Sbostic length -= t; 66*42145Sbostic TLOOP1(*dst++ = *src++); 6730423Smckusick } 68*42145Sbostic /* 69*42145Sbostic * Copy whole words, then mop up any trailing bytes. 70*42145Sbostic */ 71*42145Sbostic t = length / wsize; 72*42145Sbostic TLOOP(*(word *)dst = *(word *)src; src += wsize; dst += wsize); 73*42145Sbostic t = length & wmask; 74*42145Sbostic TLOOP(*dst++ = *src++); 75*42145Sbostic } else { 76*42145Sbostic /* 77*42145Sbostic * Copy backwards. Otherwise essentially the same. 78*42145Sbostic * Alignment works as before, except that it takes 79*42145Sbostic * (t&wmask) bytes to align, not wsize-(t&wmask). 80*42145Sbostic */ 81*42145Sbostic src += length; 82*42145Sbostic dst += length; 83*42145Sbostic t = (int)src; 84*42145Sbostic if ((t | (int)dst) & wmask) { 85*42145Sbostic if ((t ^ (int)dst) & wmask || length <= wsize) 86*42145Sbostic t = length; 87*42145Sbostic else 88*42145Sbostic t &= wmask; 89*42145Sbostic length -= t; 90*42145Sbostic TLOOP1(*--dst = *--src); 91*42145Sbostic } 92*42145Sbostic t = length / wsize; 93*42145Sbostic TLOOP(src -= wsize; dst -= wsize; *(word *)dst = *(word *)src); 94*42145Sbostic t = length & wmask; 95*42145Sbostic TLOOP(*--dst = *--src); 96*42145Sbostic } 97*42145Sbostic return; 9830423Smckusick } 99