1 /*
2 FUNCTION
3         <<memcpy>>---copy memory regions
4 
5 ANSI_SYNOPSIS
6         #include <string.h>
7         void* memcpy(void *restrict <[out]>, const void *restrict <[in]>,
8                      size_t <[n]>);
9 
10 TRAD_SYNOPSIS
11         #include <string.h>
12         void *memcpy(<[out]>, <[in]>, <[n]>
13         void *<[out]>;
14         void *<[in]>;
15         size_t <[n]>;
16 
17 DESCRIPTION
18         This function copies <[n]> bytes from the memory region
19         pointed to by <[in]> to the memory region pointed to by
20         <[out]>.
21 
22         If the regions overlap, the behavior is undefined.
23 
24 RETURNS
25         <<memcpy>> returns a pointer to the first byte of the <[out]>
26         region.
27 
28 PORTABILITY
29 <<memcpy>> is ANSI C.
30 
31 <<memcpy>> requires no supporting OS subroutines.
32 
33 QUICKREF
34         memcpy ansi pure
35 	*/
36 
37 #include <section_config.h>
38 #include <basic_types.h>
39 
40 #include <_ansi.h>
41 #include <string.h>
42 
43 /* Nonzero if either X or Y is not aligned on a "long" boundary.  */
44 #define UNALIGNED(X, Y) \
45   (((long)X & (sizeof (long) - 1)) | ((long)Y & (sizeof (long) - 1)))
46 
47 /* How many bytes are copied each iteration of the 4X unrolled loop.  */
48 #define BIGBLOCKSIZE    (sizeof (long) << 2)
49 
50 /* How many bytes are copied each iteration of the word copy loop.  */
51 #define LITTLEBLOCKSIZE (sizeof (long))
52 
53 /* Threshhold for punting to the byte copier.  */
54 #define TOO_SMALL(LEN)  ((LEN) < BIGBLOCKSIZE)
55 
56 LIBC_ROM_TEXT_SECTION
57 _LONG_CALL_
_memcpy(void * __restrict dst0,const void * __restrict src0,size_t len0)58 void * _memcpy(void * __restrict dst0 , const void * __restrict src0 , size_t len0)
59 {
60 #if defined(PREFER_SIZE_OVER_SPEED)
61   char *dst = (char *) dst0;
62   char *src = (char *) src0;
63 
64   void * save = dst0;
65 
66   while (len0--)
67     {
68       *dst++ = *src++;
69     }
70 
71   return save;
72 #else
73   char *dst = dst0;
74   const char *src = src0;
75   long *aligned_dst;
76   const long *aligned_src;
77 
78   /* If the size is small, or either SRC or DST is unaligned,
79      then punt into the byte copy loop.  This should be rare.  */
80   if (!TOO_SMALL(len0) && !UNALIGNED (src, dst))
81     {
82       aligned_dst = (long*)dst;
83       aligned_src = (long*)src;
84 
85       /* Copy 4X long words at a time if possible.  */
86       while (len0 >= BIGBLOCKSIZE)
87         {
88           *aligned_dst++ = *aligned_src++;
89           *aligned_dst++ = *aligned_src++;
90           *aligned_dst++ = *aligned_src++;
91           *aligned_dst++ = *aligned_src++;
92           len0 -= BIGBLOCKSIZE;
93         }
94 
95       /* Copy one long word at a time if possible.  */
96       while (len0 >= LITTLEBLOCKSIZE)
97         {
98           *aligned_dst++ = *aligned_src++;
99           len0 -= LITTLEBLOCKSIZE;
100         }
101 
102        /* Pick up any residual with a byte copier.  */
103       dst = (char*)aligned_dst;
104       src = (char*)aligned_src;
105     }
106 
107   while (len0--)
108     *dst++ = *src++;
109 
110   return dst0;
111 #endif /* not PREFER_SIZE_OVER_SPEED */
112 }
113