177957Sbenno/*-
277957Sbenno * Copyright (c) 1990 The Regents of the University of California.
377957Sbenno * All rights reserved.
477957Sbenno *
577957Sbenno * This code is derived from software contributed to Berkeley by
677957Sbenno * Chris Torek.
777957Sbenno *
877957Sbenno * Redistribution and use in source and binary forms, with or without
977957Sbenno * modification, are permitted provided that the following conditions
1077957Sbenno * are met:
1177957Sbenno * 1. Redistributions of source code must retain the above copyright
1277957Sbenno *    notice, this list of conditions and the following disclaimer.
1377957Sbenno * 2. Redistributions in binary form must reproduce the above copyright
1477957Sbenno *    notice, this list of conditions and the following disclaimer in the
1577957Sbenno *    documentation and/or other materials provided with the distribution.
1677957Sbenno * 4. Neither the name of the University nor the names of its contributors
1777957Sbenno *    may be used to endorse or promote products derived from this software
1877957Sbenno *    without specific prior written permission.
1977957Sbenno *
2077957Sbenno * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
2177957Sbenno * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
2277957Sbenno * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
2377957Sbenno * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
2477957Sbenno * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
2577957Sbenno * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2677957Sbenno * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2777957Sbenno * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2877957Sbenno * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
2977957Sbenno * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
3077957Sbenno * SUCH DAMAGE.
3177957Sbenno */
3277957Sbenno
3377957Sbenno#if defined(LIBC_SCCS) && !defined(lint)
3477957Sbenno#if 0
3577957Sbennostatic char *sccsid = "from: @(#)bcopy.c      5.11 (Berkeley) 6/21/91";
3677957Sbenno#endif
3777957Sbenno#if 0
3877957Sbennostatic char *rcsid = "$NetBSD: bcopy.c,v 1.2 1997/04/16 22:09:41 thorpej Exp $";
3977957Sbenno#endif
4077957Sbenno#endif /* LIBC_SCCS and not lint */
41113038Sobrien#include <sys/cdefs.h>
42113038Sobrien__FBSDID("$FreeBSD$");
4377957Sbenno
4477957Sbenno#include <sys/param.h>
4577957Sbenno#ifdef _KERNEL
4677957Sbenno#include <sys/systm.h>
4777957Sbenno#else
4877957Sbenno#include <string.h>
4977957Sbenno#endif
5077957Sbenno
5177957Sbenno/*
5277957Sbenno * sizeof(word) MUST BE A POWER OF TWO
5377957Sbenno * SO THAT wmask BELOW IS ALL ONES
5477957Sbenno */
55209850Snwhitehorntypedef	long	word;		/* "word" used for optimal copy speed */
5677957Sbenno
5777957Sbenno#define	wsize	sizeof(word)
5877957Sbenno#define wmask	(wsize - 1)
5977957Sbenno
6077957Sbenno/*
6177957Sbenno * Copy a block of memory, handling overlap.
6277957Sbenno * This is the routine that actually implements
6377957Sbenno * (the portable versions of) bcopy, memcpy, and memmove.
6477957Sbenno */
6577957Sbennovoid *
6677957Sbennomemcpy(void *dst0, const void *src0, size_t length)
6777957Sbenno{
6877957Sbenno	char		*dst;
6977957Sbenno	const char	*src;
7077957Sbenno	size_t		t;
7177957Sbenno
7277957Sbenno	dst = dst0;
7377957Sbenno	src = src0;
7477957Sbenno
7577957Sbenno	if (length == 0 || dst == src) {	/* nothing to do */
7677957Sbenno		goto done;
7777957Sbenno	}
7877957Sbenno
7977957Sbenno	/*
8077957Sbenno	 * Macros: loop-t-times; and loop-t-times, t>0
8177957Sbenno	 */
8277957Sbenno#define	TLOOP(s) if (t) TLOOP1(s)
8377957Sbenno#define	TLOOP1(s) do { s; } while (--t)
8477957Sbenno
8577957Sbenno	if ((unsigned long)dst < (unsigned long)src) {
8677957Sbenno		/*
8777957Sbenno		 * Copy forward.
8877957Sbenno		 */
89209850Snwhitehorn		t = (size_t)src;	/* only need low bits */
9077957Sbenno
91209850Snwhitehorn		if ((t | (uintptr_t)dst) & wmask) {
9277957Sbenno			/*
9377957Sbenno			 * Try to align operands.  This cannot be done
9477957Sbenno			 * unless the low bits match.
9577957Sbenno			 */
96209850Snwhitehorn			if ((t ^ (uintptr_t)dst) & wmask || length < wsize) {
9777957Sbenno				t = length;
9877957Sbenno			} else {
9977957Sbenno				t = wsize - (t & wmask);
10077957Sbenno			}
10177957Sbenno
10277957Sbenno			length -= t;
10377957Sbenno			TLOOP1(*dst++ = *src++);
10477957Sbenno		}
10577957Sbenno		/*
10677957Sbenno		 * Copy whole words, then mop up any trailing bytes.
10777957Sbenno		 */
10877957Sbenno		t = length / wsize;
10977957Sbenno		TLOOP(*(word *)dst = *(const word *)src; src += wsize;
11077957Sbenno		    dst += wsize);
11177957Sbenno		t = length & wmask;
11277957Sbenno		TLOOP(*dst++ = *src++);
11377957Sbenno	} else {
11477957Sbenno		/*
11577957Sbenno		 * Copy backwards.  Otherwise essentially the same.
11677957Sbenno		 * Alignment works as before, except that it takes
11777957Sbenno		 * (t&wmask) bytes to align, not wsize-(t&wmask).
11877957Sbenno		 */
11977957Sbenno		src += length;
12077957Sbenno		dst += length;
121209850Snwhitehorn		t = (uintptr_t)src;
12277957Sbenno
123209850Snwhitehorn		if ((t | (uintptr_t)dst) & wmask) {
124209850Snwhitehorn			if ((t ^ (uintptr_t)dst) & wmask || length <= wsize) {
12577957Sbenno				t = length;
12677957Sbenno			} else {
12777957Sbenno				t &= wmask;
12877957Sbenno			}
12977957Sbenno
13077957Sbenno			length -= t;
13177957Sbenno			TLOOP1(*--dst = *--src);
13277957Sbenno		}
13377957Sbenno		t = length / wsize;
13477957Sbenno		TLOOP(src -= wsize; dst -= wsize;
13577957Sbenno		    *(word *)dst = *(const word *)src);
13677957Sbenno		t = length & wmask;
13777957Sbenno		TLOOP(*--dst = *--src);
13877957Sbenno	}
13977957Sbennodone:
14077957Sbenno	return (dst0);
14177957Sbenno}
14277957Sbenno
14377957Sbennovoid
14477957Sbennobcopy(const void *src0, void *dst0, size_t length)
14577957Sbenno{
14677957Sbenno
14777957Sbenno	memcpy(dst0, src0, length);
14877957Sbenno}
14999035Sbenno
150