1 /* $NetBSD: memcpy.c,v 1.1 2014/09/03 19:34:25 matt Exp $ */
3 * Copyright (c) 2014 The NetBSD Foundation, Inc.
6 * This code is derived from software contributed to The NetBSD Foundation
7 * by Matt Thomas of 3am Software Foundry.
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
12 * 1. Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer.
14 * 2. Redistributions in binary form must reproduce the above copyright
15 * notice, this list of conditions and the following disclaimer in the
16 * documentation and/or other materials provided with the distribution.
18 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
19 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
20 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
21 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
22 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
23 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
24 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
25 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
26 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
27 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
28 * POSSIBILITY OF SUCH DAMAGE.
31 #include <sys/cdefs.h>
33 __RCSID("$NetBSD: memcpy.c,v 1.1 2014/09/03 19:34:25 matt Exp $");
39 static inline unsigned long
40 combine_words(unsigned long w1
, unsigned long w2
, int shift1
, int shift2
)
42 #if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
43 return (w1
<< shift1
) | (w2
>> shift2
);
45 return (w1
>> shift1
) | (w2
<< shift2
);
50 memcpy(void * restrict a
, const void * restrict b
, size_t len
)
52 const unsigned char *cb
= b
;
53 unsigned char *ca
= a
;
59 * Make sure the destination is long aligned.
61 while ((uintptr_t)ca
& (sizeof(long) - 1)) {
67 unsigned long *la
= (long *)ca
;
68 const int offset
= (uintptr_t)cb
& (sizeof(*la
) - 1);
69 const unsigned long *lb
= (const unsigned long *) (cb
- offset
);
70 unsigned long * const ea
= la
+ len
/ sizeof(*la
);
74 * a & b are now both long alignment.
75 * First try to copy 4 longs at a time,
77 for (; la
+ 4 <= ea
; la
+= 4, lb
+= 4) {
84 * Now try to copy one long at a time.
90 const int shift1
= offset
* 8;
91 const int shift2
= sizeof(*la
) * 8 - shift1
;
92 unsigned long w1
= *lb
++;
95 * We try to write 4 words per loop.
97 for (; la
+ 4 <= ea
; la
+= 4, lb
+= 4) {
98 unsigned long w2
= lb
[0];
100 la
[0] = combine_words(w1
, w2
, shift1
, shift2
);
104 la
[1] = combine_words(w2
, w1
, shift1
, shift2
);
108 la
[2] = combine_words(w1
, w2
, shift1
, shift2
);
112 la
[3] = combine_words(w2
, w1
, shift1
, shift2
);
116 * Now try to copy one long at a time.
119 unsigned long w2
= *lb
++;
121 *la
++ = combine_words(w1
, w2
, shift1
, shift2
);
126 len
&= sizeof(*la
) - 1;
128 cb
= (const unsigned char *)lb
+ offset
;
129 ca
= (unsigned char *)la
;