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