xref: /optee_os/lib/libutils/isoc/newlib/memcpy.c (revision b01047730e77127c23a36591643eeb8bb0487d68)
1*b0104773SPascal Brand /*
2*b0104773SPascal Brand  * Copyright (c) 1994-2009  Red Hat, Inc.
3*b0104773SPascal Brand  * All rights reserved.
4*b0104773SPascal Brand  *
5*b0104773SPascal Brand  * Redistribution and use in source and binary forms, with or without
6*b0104773SPascal Brand  * modification, are permitted provided that the following conditions are met:
7*b0104773SPascal Brand  *
8*b0104773SPascal Brand  * 1. Redistributions of source code must retain the above copyright notice,
9*b0104773SPascal Brand  * this list of conditions and the following disclaimer.
10*b0104773SPascal Brand  *
11*b0104773SPascal Brand  * 2. Redistributions in binary form must reproduce the above copyright notice,
12*b0104773SPascal Brand  * this list of conditions and the following disclaimer in the documentation
13*b0104773SPascal Brand  * and/or other materials provided with the distribution.
14*b0104773SPascal Brand  *
15*b0104773SPascal Brand  * 3. Neither the name of the copyright holder nor the names of its
16*b0104773SPascal Brand  * contributors may be used to endorse or promote products derived from this
17*b0104773SPascal Brand  * software without specific prior written permission.
18*b0104773SPascal Brand  *
19*b0104773SPascal Brand  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
20*b0104773SPascal Brand  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21*b0104773SPascal Brand  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22*b0104773SPascal Brand  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
23*b0104773SPascal Brand  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24*b0104773SPascal Brand  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25*b0104773SPascal Brand  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26*b0104773SPascal Brand  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27*b0104773SPascal Brand  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28*b0104773SPascal Brand  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29*b0104773SPascal Brand  * POSSIBILITY OF SUCH DAMAGE.
30*b0104773SPascal Brand  */
31*b0104773SPascal Brand 
32*b0104773SPascal Brand /*
33*b0104773SPascal Brand FUNCTION
34*b0104773SPascal Brand 	<<memcpy>>---copy memory regions
35*b0104773SPascal Brand 
36*b0104773SPascal Brand ANSI_SYNOPSIS
37*b0104773SPascal Brand 	#include <string.h>
38*b0104773SPascal Brand 	void* memcpy(void *<[out]>, const void *<[in]>, size_t <[n]>);
39*b0104773SPascal Brand 
40*b0104773SPascal Brand TRAD_SYNOPSIS
41*b0104773SPascal Brand 	#include <string.h>
42*b0104773SPascal Brand 	void *memcpy(<[out]>, <[in]>, <[n]>
43*b0104773SPascal Brand 	void *<[out]>;
44*b0104773SPascal Brand 	void *<[in]>;
45*b0104773SPascal Brand 	size_t <[n]>;
46*b0104773SPascal Brand 
47*b0104773SPascal Brand DESCRIPTION
48*b0104773SPascal Brand 	This function copies <[n]> bytes from the memory region
49*b0104773SPascal Brand 	pointed to by <[in]> to the memory region pointed to by
50*b0104773SPascal Brand 	<[out]>.
51*b0104773SPascal Brand 
52*b0104773SPascal Brand 	If the regions overlap, the behavior is undefined.
53*b0104773SPascal Brand 
54*b0104773SPascal Brand RETURNS
55*b0104773SPascal Brand 	<<memcpy>> returns a pointer to the first byte of the <[out]>
56*b0104773SPascal Brand 	region.
57*b0104773SPascal Brand 
58*b0104773SPascal Brand PORTABILITY
59*b0104773SPascal Brand <<memcpy>> is ANSI C.
60*b0104773SPascal Brand 
61*b0104773SPascal Brand <<memcpy>> requires no supporting OS subroutines.
62*b0104773SPascal Brand 
63*b0104773SPascal Brand QUICKREF
64*b0104773SPascal Brand 	memcpy ansi pure
65*b0104773SPascal Brand */
66*b0104773SPascal Brand 
67*b0104773SPascal Brand #include "_ansi.h"
68*b0104773SPascal Brand #include <string.h>
69*b0104773SPascal Brand 
70*b0104773SPascal Brand /* Nonzero if either X or Y is not aligned on a "long" boundary.  */
71*b0104773SPascal Brand #define UNALIGNED(X, Y) \
72*b0104773SPascal Brand 	(((long)X & (sizeof(long) - 1)) | ((long)Y & (sizeof(long) - 1)))
73*b0104773SPascal Brand 
74*b0104773SPascal Brand /* How many bytes are copied each iteration of the 4X unrolled loop.  */
75*b0104773SPascal Brand #define BIGBLOCKSIZE    (sizeof(long) << 2)
76*b0104773SPascal Brand 
77*b0104773SPascal Brand /* How many bytes are copied each iteration of the word copy loop.  */
78*b0104773SPascal Brand #define LITTLEBLOCKSIZE (sizeof(long))
79*b0104773SPascal Brand 
80*b0104773SPascal Brand /* Threshhold for punting to the byte copier.  */
81*b0104773SPascal Brand #define TOO_SMALL(LEN)  ((LEN) < BIGBLOCKSIZE)
82*b0104773SPascal Brand 
83*b0104773SPascal Brand _PTR
84*b0104773SPascal Brand _DEFUN(memcpy, (dst0, src0, len0), _PTR dst0 _AND _CONST _PTR src0 _AND
85*b0104773SPascal Brand 	 size_t len0)
86*b0104773SPascal Brand {
87*b0104773SPascal Brand #if defined(PREFER_SIZE_OVER_SPEED) || defined(__OPTIMIZE_SIZE__)
88*b0104773SPascal Brand 	char *dst = (char *)dst0;
89*b0104773SPascal Brand 	char *src = (char *)src0;
90*b0104773SPascal Brand 
91*b0104773SPascal Brand 	_PTR save = dst0;
92*b0104773SPascal Brand 
93*b0104773SPascal Brand 	while (len0--)
94*b0104773SPascal Brand 		*dst++ = *src++;
95*b0104773SPascal Brand 
96*b0104773SPascal Brand 	return save;
97*b0104773SPascal Brand #else
98*b0104773SPascal Brand 	char *dst = dst0;
99*b0104773SPascal Brand 	_CONST char *src = src0;
100*b0104773SPascal Brand 	long *aligned_dst;
101*b0104773SPascal Brand 	_CONST long *aligned_src;
102*b0104773SPascal Brand 
103*b0104773SPascal Brand 	/* If the size is small, or either SRC or DST is unaligned,
104*b0104773SPascal Brand 	   then punt into the byte copy loop.  This should be rare.  */
105*b0104773SPascal Brand 	if (!TOO_SMALL(len0) && !UNALIGNED(src, dst)) {
106*b0104773SPascal Brand 		aligned_dst = (long *)dst;
107*b0104773SPascal Brand 		aligned_src = (long *)src;
108*b0104773SPascal Brand 
109*b0104773SPascal Brand 		/* Copy 4X long words at a time if possible.  */
110*b0104773SPascal Brand 		while (len0 >= BIGBLOCKSIZE) {
111*b0104773SPascal Brand 			*aligned_dst++ = *aligned_src++;
112*b0104773SPascal Brand 			*aligned_dst++ = *aligned_src++;
113*b0104773SPascal Brand 			*aligned_dst++ = *aligned_src++;
114*b0104773SPascal Brand 			*aligned_dst++ = *aligned_src++;
115*b0104773SPascal Brand 			len0 -= BIGBLOCKSIZE;
116*b0104773SPascal Brand 		}
117*b0104773SPascal Brand 
118*b0104773SPascal Brand 		/* Copy one long word at a time if possible.  */
119*b0104773SPascal Brand 		while (len0 >= LITTLEBLOCKSIZE) {
120*b0104773SPascal Brand 			*aligned_dst++ = *aligned_src++;
121*b0104773SPascal Brand 			len0 -= LITTLEBLOCKSIZE;
122*b0104773SPascal Brand 		}
123*b0104773SPascal Brand 
124*b0104773SPascal Brand 		/* Pick up any residual with a byte copier.  */
125*b0104773SPascal Brand 		dst = (char *)aligned_dst;
126*b0104773SPascal Brand 		src = (char *)aligned_src;
127*b0104773SPascal Brand 	}
128*b0104773SPascal Brand 
129*b0104773SPascal Brand 	while (len0--)
130*b0104773SPascal Brand 		*dst++ = *src++;
131*b0104773SPascal Brand 
132*b0104773SPascal Brand 	return dst0;
133*b0104773SPascal Brand #endif /* not PREFER_SIZE_OVER_SPEED */
134*b0104773SPascal Brand }
135