xref: /csrg-svn/lib/libc/string/bcopy.c (revision 61193)
142145Sbostic /*-
2*61193Sbostic  * Copyright (c) 1990, 1993
3*61193Sbostic  *	The Regents of the University of California.  All rights reserved.
435110Sbostic  *
542145Sbostic  * This code is derived from software contributed to Berkeley by
642145Sbostic  * Chris Torek.
742145Sbostic  *
842145Sbostic  * %sccs.include.redist.c%
930423Smckusick  */
1030423Smckusick 
1130423Smckusick #if defined(LIBC_SCCS) && !defined(lint)
12*61193Sbostic static char sccsid[] = "@(#)bcopy.c	8.1 (Berkeley) 06/04/93";
1335110Sbostic #endif /* LIBC_SCCS and not lint */
1430423Smckusick 
1546144Sbostic #include <sys/cdefs.h>
1642145Sbostic #include <string.h>
1737105Sbostic 
1830423Smckusick /*
1942145Sbostic  * sizeof(word) MUST BE A POWER OF TWO
2042145Sbostic  * SO THAT wmask BELOW IS ALL ONES
2130423Smckusick  */
2242145Sbostic typedef	int word;		/* "word" used for optimal copy speed */
2338485Skarels 
2442145Sbostic #define	wsize	sizeof(word)
2542145Sbostic #define	wmask	(wsize - 1)
2638485Skarels 
2742145Sbostic /*
2842145Sbostic  * Copy a block of memory, handling overlap.
2942145Sbostic  * This is the routine that actually implements
3042145Sbostic  * (the portable versions of) bcopy, memcpy, and memmove.
3142145Sbostic  */
3243487Sbostic #ifdef MEMCOPY
3343487Sbostic void *
memcpy(dst0,src0,length)3443487Sbostic memcpy(dst0, src0, length)
3543487Sbostic #else
3643487Sbostic #ifdef MEMMOVE
3743487Sbostic void *
3843487Sbostic memmove(dst0, src0, length)
3943487Sbostic #else
4042145Sbostic void
4142145Sbostic bcopy(src0, dst0, length)
4243487Sbostic #endif
4343487Sbostic #endif
4446609Sbostic 	void *dst0;
4546609Sbostic 	const void *src0;
4642145Sbostic 	register size_t length;
4730423Smckusick {
4842145Sbostic 	register char *dst = dst0;
4942145Sbostic 	register const char *src = src0;
5042145Sbostic 	register size_t t;
5142145Sbostic 
5242145Sbostic 	if (length == 0 || dst == src)		/* nothing to do */
5350116Storek 		goto done;
5442145Sbostic 
5542145Sbostic 	/*
5642145Sbostic 	 * Macros: loop-t-times; and loop-t-times, t>0
5742145Sbostic 	 */
5842145Sbostic #define	TLOOP(s) if (t) TLOOP1(s)
5942145Sbostic #define	TLOOP1(s) do { s; } while (--t)
6042145Sbostic 
6142145Sbostic 	if ((unsigned long)dst < (unsigned long)src) {
6242145Sbostic 		/*
6342145Sbostic 		 * Copy forward.
6442145Sbostic 		 */
6542145Sbostic 		t = (int)src;	/* only need low bits */
6642145Sbostic 		if ((t | (int)dst) & wmask) {
6742145Sbostic 			/*
6842145Sbostic 			 * Try to align operands.  This cannot be done
6942145Sbostic 			 * unless the low bits match.
7042145Sbostic 			 */
7142145Sbostic 			if ((t ^ (int)dst) & wmask || length < wsize)
7242145Sbostic 				t = length;
7342145Sbostic 			else
7442145Sbostic 				t = wsize - (t & wmask);
7542145Sbostic 			length -= t;
7642145Sbostic 			TLOOP1(*dst++ = *src++);
7730423Smckusick 		}
7842145Sbostic 		/*
7942145Sbostic 		 * Copy whole words, then mop up any trailing bytes.
8042145Sbostic 		 */
8142145Sbostic 		t = length / wsize;
8242145Sbostic 		TLOOP(*(word *)dst = *(word *)src; src += wsize; dst += wsize);
8342145Sbostic 		t = length & wmask;
8442145Sbostic 		TLOOP(*dst++ = *src++);
8542145Sbostic 	} else {
8642145Sbostic 		/*
8742145Sbostic 		 * Copy backwards.  Otherwise essentially the same.
8842145Sbostic 		 * Alignment works as before, except that it takes
8942145Sbostic 		 * (t&wmask) bytes to align, not wsize-(t&wmask).
9042145Sbostic 		 */
9142145Sbostic 		src += length;
9242145Sbostic 		dst += length;
9342145Sbostic 		t = (int)src;
9442145Sbostic 		if ((t | (int)dst) & wmask) {
9542145Sbostic 			if ((t ^ (int)dst) & wmask || length <= wsize)
9642145Sbostic 				t = length;
9742145Sbostic 			else
9842145Sbostic 				t &= wmask;
9942145Sbostic 			length -= t;
10042145Sbostic 			TLOOP1(*--dst = *--src);
10142145Sbostic 		}
10242145Sbostic 		t = length / wsize;
10342145Sbostic 		TLOOP(src -= wsize; dst -= wsize; *(word *)dst = *(word *)src);
10442145Sbostic 		t = length & wmask;
10542145Sbostic 		TLOOP(*--dst = *--src);
10642145Sbostic 	}
10750116Storek done:
10850116Storek #if defined(MEMCOPY) || defined(MEMMOVE)
10950116Storek 	return (dst0);
11043487Sbostic #else
11142145Sbostic 	return;
11243487Sbostic #endif
11330423Smckusick }
114