xref: /csrg-svn/lib/libc/string/bcopy.c (revision 42145)
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