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