1281494Sandrew/*-
2281494Sandrew * Copyright (c) 1990 The Regents of the University of California.
3281494Sandrew * All rights reserved.
4281494Sandrew *
5281494Sandrew * This code is derived from software contributed to Berkeley by
6281494Sandrew * Chris Torek.
7281494Sandrew *
8281494Sandrew * Redistribution and use in source and binary forms, with or without
9281494Sandrew * modification, are permitted provided that the following conditions
10281494Sandrew * are met:
11281494Sandrew * 1. Redistributions of source code must retain the above copyright
12281494Sandrew *    notice, this list of conditions and the following disclaimer.
13281494Sandrew * 2. Redistributions in binary form must reproduce the above copyright
14281494Sandrew *    notice, this list of conditions and the following disclaimer in the
15281494Sandrew *    documentation and/or other materials provided with the distribution.
16281494Sandrew * 3. Neither the name of the University nor the names of its contributors
17281494Sandrew *    may be used to endorse or promote products derived from this software
18281494Sandrew *    without specific prior written permission.
19281494Sandrew *
20281494Sandrew * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
21281494Sandrew * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22281494Sandrew * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23281494Sandrew * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
24281494Sandrew * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25281494Sandrew * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26281494Sandrew * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27281494Sandrew * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28281494Sandrew * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29281494Sandrew * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30281494Sandrew * SUCH DAMAGE.
31281494Sandrew *
32281494Sandrew * From: sys/powerpc/powerpc/bcopy.c
33281494Sandrew */
34281494Sandrew
35281494Sandrew#include <sys/cdefs.h>
36281494Sandrew__FBSDID("$FreeBSD$");
37281494Sandrew
38281494Sandrew#include <sys/param.h>
39281494Sandrew#include <sys/systm.h>
40281494Sandrew
41281494Sandrew/*
42281494Sandrew * sizeof(word) MUST BE A POWER OF TWO
43281494Sandrew * SO THAT wmask BELOW IS ALL ONES
44281494Sandrew */
45281494Sandrewtypedef	long	word;		/* "word" used for optimal copy speed */
46281494Sandrew
47281494Sandrew#define	wsize	sizeof(word)
48281494Sandrew#define wmask	(wsize - 1)
49281494Sandrew
50281494Sandrew/*
51281494Sandrew * Copy a block of memory, handling overlap.
52281494Sandrew * This is the routine that actually implements
53281494Sandrew * (the portable versions of) bcopy, memcpy, and memmove.
54281494Sandrew */
55281494Sandrewvoid *
56281494Sandrewmemcpy(void *dst0, const void *src0, size_t length)
57281494Sandrew{
58281494Sandrew	char		*dst;
59281494Sandrew	const char	*src;
60281494Sandrew	size_t		t;
61281494Sandrew
62281494Sandrew	dst = dst0;
63281494Sandrew	src = src0;
64281494Sandrew
65281494Sandrew	if (length == 0 || dst == src) {	/* nothing to do */
66281494Sandrew		goto done;
67281494Sandrew	}
68281494Sandrew
69281494Sandrew	/*
70281494Sandrew	 * Macros: loop-t-times; and loop-t-times, t>0
71281494Sandrew	 */
72281494Sandrew#define	TLOOP(s) if (t) TLOOP1(s)
73281494Sandrew#define	TLOOP1(s) do { s; } while (--t)
74281494Sandrew
75281494Sandrew	if ((unsigned long)dst < (unsigned long)src) {
76281494Sandrew		/*
77281494Sandrew		 * Copy forward.
78281494Sandrew		 */
79281494Sandrew		t = (size_t)src;	/* only need low bits */
80281494Sandrew
81281494Sandrew		if ((t | (uintptr_t)dst) & wmask) {
82281494Sandrew			/*
83281494Sandrew			 * Try to align operands.  This cannot be done
84281494Sandrew			 * unless the low bits match.
85281494Sandrew			 */
86281494Sandrew			if ((t ^ (uintptr_t)dst) & wmask || length < wsize) {
87281494Sandrew				t = length;
88281494Sandrew			} else {
89281494Sandrew				t = wsize - (t & wmask);
90281494Sandrew			}
91281494Sandrew
92281494Sandrew			length -= t;
93281494Sandrew			TLOOP1(*dst++ = *src++);
94281494Sandrew		}
95281494Sandrew		/*
96281494Sandrew		 * Copy whole words, then mop up any trailing bytes.
97281494Sandrew		 */
98281494Sandrew		t = length / wsize;
99281494Sandrew		TLOOP(*(word *)dst = *(const word *)src; src += wsize;
100281494Sandrew		    dst += wsize);
101281494Sandrew		t = length & wmask;
102281494Sandrew		TLOOP(*dst++ = *src++);
103281494Sandrew	} else {
104281494Sandrew		/*
105281494Sandrew		 * Copy backwards.  Otherwise essentially the same.
106281494Sandrew		 * Alignment works as before, except that it takes
107281494Sandrew		 * (t&wmask) bytes to align, not wsize-(t&wmask).
108281494Sandrew		 */
109281494Sandrew		src += length;
110281494Sandrew		dst += length;
111281494Sandrew		t = (uintptr_t)src;
112281494Sandrew
113281494Sandrew		if ((t | (uintptr_t)dst) & wmask) {
114281494Sandrew			if ((t ^ (uintptr_t)dst) & wmask || length <= wsize) {
115281494Sandrew				t = length;
116281494Sandrew			} else {
117281494Sandrew				t &= wmask;
118281494Sandrew			}
119281494Sandrew
120281494Sandrew			length -= t;
121281494Sandrew			TLOOP1(*--dst = *--src);
122281494Sandrew		}
123281494Sandrew		t = length / wsize;
124281494Sandrew		TLOOP(src -= wsize; dst -= wsize;
125281494Sandrew		    *(word *)dst = *(const word *)src);
126281494Sandrew		t = length & wmask;
127281494Sandrew		TLOOP(*--dst = *--src);
128281494Sandrew	}
129281494Sandrewdone:
130281494Sandrew	return (dst0);
131281494Sandrew}
132281494Sandrew
133281494Sandrewvoid
134281494Sandrewbcopy(const void *src0, void *dst0, size_t length)
135281494Sandrew{
136281494Sandrew
137281494Sandrew	memcpy(dst0, src0, length);
138281494Sandrew}
139281494Sandrew
140