Commit | Line | Data |
---|---|---|
8d1088c3 KB |
1 | /*- |
2 | * Copyright (c) 1990 The Regents of the University of California. | |
acca4551 KB |
3 | * All rights reserved. |
4 | * | |
8d1088c3 KB |
5 | * This code is derived from software contributed to Berkeley by |
6 | * Chris Torek. | |
7 | * | |
8 | * %sccs.include.redist.c% | |
dba1d438 KM |
9 | */ |
10 | ||
11 | #if defined(LIBC_SCCS) && !defined(lint) | |
a64329b4 | 12 | static char sccsid[] = "@(#)bcopy.c 5.9 (Berkeley) %G%"; |
acca4551 | 13 | #endif /* LIBC_SCCS and not lint */ |
dba1d438 | 14 | |
a64329b4 | 15 | #include <sys/cdefs.h> |
8d1088c3 | 16 | #include <string.h> |
a5190670 | 17 | |
dba1d438 | 18 | /* |
8d1088c3 KB |
19 | * sizeof(word) MUST BE A POWER OF TWO |
20 | * SO THAT wmask BELOW IS ALL ONES | |
dba1d438 | 21 | */ |
8d1088c3 | 22 | typedef int word; /* "word" used for optimal copy speed */ |
fc2647ae | 23 | |
8d1088c3 KB |
24 | #define wsize sizeof(word) |
25 | #define wmask (wsize - 1) | |
fc2647ae | 26 | |
8d1088c3 KB |
27 | /* |
28 | * Copy a block of memory, handling overlap. | |
29 | * This is the routine that actually implements | |
30 | * (the portable versions of) bcopy, memcpy, and memmove. | |
31 | */ | |
65bef021 KB |
32 | #ifdef MEMCOPY |
33 | void * | |
34 | memcpy(dst0, src0, length) | |
35 | #else | |
36 | #ifdef MEMMOVE | |
37 | void * | |
38 | memmove(dst0, src0, length) | |
39 | #else | |
8d1088c3 KB |
40 | void |
41 | bcopy(src0, dst0, length) | |
65bef021 KB |
42 | #endif |
43 | #endif | |
8d1088c3 KB |
44 | char *dst0; |
45 | const char *src0; | |
46 | register size_t length; | |
dba1d438 | 47 | { |
8d1088c3 KB |
48 | register char *dst = dst0; |
49 | register const char *src = src0; | |
50 | register size_t t; | |
51 | ||
52 | if (length == 0 || dst == src) /* nothing to do */ | |
53 | return; | |
54 | ||
55 | /* | |
56 | * Macros: loop-t-times; and loop-t-times, t>0 | |
57 | */ | |
58 | #define TLOOP(s) if (t) TLOOP1(s) | |
59 | #define TLOOP1(s) do { s; } while (--t) | |
60 | ||
61 | if ((unsigned long)dst < (unsigned long)src) { | |
62 | /* | |
63 | * Copy forward. | |
64 | */ | |
65 | t = (int)src; /* only need low bits */ | |
66 | if ((t | (int)dst) & wmask) { | |
67 | /* | |
68 | * Try to align operands. This cannot be done | |
69 | * unless the low bits match. | |
70 | */ | |
71 | if ((t ^ (int)dst) & wmask || length < wsize) | |
72 | t = length; | |
73 | else | |
74 | t = wsize - (t & wmask); | |
75 | length -= t; | |
76 | TLOOP1(*dst++ = *src++); | |
77 | } | |
78 | /* | |
79 | * Copy whole words, then mop up any trailing bytes. | |
80 | */ | |
81 | t = length / wsize; | |
82 | TLOOP(*(word *)dst = *(word *)src; src += wsize; dst += wsize); | |
83 | t = length & wmask; | |
84 | TLOOP(*dst++ = *src++); | |
85 | } else { | |
86 | /* | |
87 | * Copy backwards. Otherwise essentially the same. | |
88 | * Alignment works as before, except that it takes | |
89 | * (t&wmask) bytes to align, not wsize-(t&wmask). | |
90 | */ | |
91 | src += length; | |
92 | dst += length; | |
93 | t = (int)src; | |
94 | if ((t | (int)dst) & wmask) { | |
95 | if ((t ^ (int)dst) & wmask || length <= wsize) | |
96 | t = length; | |
97 | else | |
98 | t &= wmask; | |
99 | length -= t; | |
100 | TLOOP1(*--dst = *--src); | |
dba1d438 | 101 | } |
8d1088c3 KB |
102 | t = length / wsize; |
103 | TLOOP(src -= wsize; dst -= wsize; *(word *)dst = *(word *)src); | |
104 | t = length & wmask; | |
105 | TLOOP(*--dst = *--src); | |
106 | } | |
65bef021 KB |
107 | #ifdef MEMCOPY |
108 | return(dst0); | |
109 | #else | |
110 | #ifdef MEMMOVE | |
111 | return(dst0); | |
112 | #else | |
8d1088c3 | 113 | return; |
65bef021 KB |
114 | #endif |
115 | #endif | |
dba1d438 | 116 | } |