]> git.kernelconcepts.de Git - karo-tx-redboot.git/blob - packages/infra/v2_0/src/memcpy.c
unified MX27, MX25, MX37 trees
[karo-tx-redboot.git] / packages / infra / v2_0 / src / memcpy.c
1 /*===========================================================================
2 //
3 //      memcpy.c
4 //
5 //      ANSI standard memcpy() routine
6 //
7 //==========================================================================
8 //####ECOSGPLCOPYRIGHTBEGIN####
9 // -------------------------------------------
10 // This file is part of eCos, the Embedded Configurable Operating System.
11 // Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc.
12 //
13 // eCos is free software; you can redistribute it and/or modify it under
14 // the terms of the GNU General Public License as published by the Free
15 // Software Foundation; either version 2 or (at your option) any later version.
16 //
17 // eCos is distributed in the hope that it will be useful, but WITHOUT ANY
18 // WARRANTY; without even the implied warranty of MERCHANTABILITY or
19 // FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
20 // for more details.
21 //
22 // You should have received a copy of the GNU General Public License along
23 // with eCos; if not, write to the Free Software Foundation, Inc.,
24 // 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
25 //
26 // As a special exception, if other files instantiate templates or use macros
27 // or inline functions from this file, or you compile this file and link it
28 // with other works to produce a work based on this file, this file does not
29 // by itself cause the resulting work to be covered by the GNU General Public
30 // License. However the source code for this file must still be made available
31 // in accordance with section (3) of the GNU General Public License.
32 //
33 // This exception does not invalidate any other reasons why a work based on
34 // this file might be covered by the GNU General Public License.
35 //
36 // Alternative licenses for eCos may be arranged by contacting Red Hat, Inc.
37 // at http://sources.redhat.com/ecos/ecos-license/
38 // -------------------------------------------
39 //####ECOSGPLCOPYRIGHTEND####
40 //==========================================================================
41 //#####DESCRIPTIONBEGIN####
42 //
43 // Author(s):   jlarmour
44 // Contributors:  jlarmour
45 // Date:        1998-06-04
46 // Purpose:     This file implements the ANSI memcpy() function
47 // Description: This file implements the memcpy() function defined in ANSI para
48 //              7.11.2.1. This is implemented in the kernel rather than the
49 //              C library due to it being required by gcc whether or not the
50 //              C library has been configured in.
51 //
52 //####DESCRIPTIONEND####
53 //
54 //==========================================================================*/
55
56
57 /* INCLUDES */
58
59 #include <pkgconf/infra.h>      /* Configuration of infra package */
60
61 #include <cyg/infra/cyg_type.h> /* Common type definitions */
62 #include <cyg/infra/cyg_trac.h> /* Tracing support */
63 #include <cyg/infra/cyg_ass.h>  /* Assertion support */
64 #include <stddef.h>             /* Compiler defns such as size_t, NULL etc. */
65
66 /* MACROS */
67
68 /* Nonzero if either X or Y is not aligned on a word boundary. */
69 #define CYG_STR_UNALIGNED(X, Y) \
70      (((CYG_WORD)(X) & (sizeof (CYG_WORD) - 1)) | \
71       ((CYG_WORD)(Y) & (sizeof (CYG_WORD) - 1)))
72
73 /* How many bytes are copied each iteration of the 4X unrolled loop in the
74  * optimised string implementation
75  */
76 #define CYG_STR_OPT_BIGBLOCKSIZE     (sizeof(CYG_WORD) << 2)
77
78
79 /* How many bytes are copied each iteration of the word copy loop in the
80  * optimised string implementation
81  */
82 #define CYG_STR_OPT_LITTLEBLOCKSIZE (sizeof (CYG_WORD))
83
84 /* EXPORTED SYMBOLS */
85
86 externC void *
87 memcpy( void *s1, const void *s2, size_t n ) __attribute__((weak,
88                                                             alias("_memcpy")));
89
90 /* FUNCTIONS */
91
92 void *
93 _memcpy( void *s1, const void *s2, size_t n )
94 {
95     char *dst = (char *) s1;
96     const char *src = (const char *) s2;
97
98     CYG_ASSERT((dst >= (src+n)) || ((dst+n) <= src),
99                "memcpy() has undefined result for overlapping copies");
100         
101 #if defined(CYGIMP_INFRA_PREFER_SMALL_TO_FAST_MEMCPY) || defined(__OPTIMIZE_SIZE__)
102     
103 #ifdef CYG_TRACING_FIXED
104     CYG_REPORT_FUNCNAMETYPE( "_memcpy", "returning %08x" );
105     CYG_REPORT_FUNCARG3( "dst=%08x, src=%08x, n=%d", dst, src, n );
106
107     if (n != 0)
108     {
109         CYG_CHECK_DATA_PTR( dst, "dst is not a valid pointer!" );
110         CYG_CHECK_DATA_PTR( src, "src is not a valid pointer!" );
111         CYG_CHECK_DATA_PTR( dst+n-1, "dst+n-1 is not a valid address!" );
112         CYG_CHECK_DATA_PTR( src+n-1, "src+n-1 is not a valid address!" );
113     }
114 #endif
115
116     while (n--)
117     {
118         *dst++ = *src++;
119     } /* while */
120     
121 #ifdef CYG_TRACING_FIXED
122     CYG_REPORT_RETVAL( s1 );
123 #endif
124     return s1;
125 #else
126     CYG_WORD *aligned_dst;
127     const CYG_WORD *aligned_src;
128     
129 #ifdef CYG_TRACING_FIXED
130     CYG_REPORT_FUNCNAMETYPE( "_memcpy", "returning %08x" );
131 #endif
132
133
134 #ifdef CYG_TRACING_FIXED
135     CYG_REPORT_FUNCARG3( "dst=%08x, src=%08x, n=%d", dst, src, n );
136     
137     if (n != 0)
138     {
139         CYG_CHECK_DATA_PTR( dst, "dst is not a valid pointer!" );
140         CYG_CHECK_DATA_PTR( src, "src is not a valid pointer!" );
141         CYG_CHECK_DATA_PTR( dst+n-1, "dst+n-1 is not a valid address!" );
142         CYG_CHECK_DATA_PTR( src+n-1, "src+n-1 is not a valid address!" );
143     }
144 #endif
145
146     /* If the size is small, or either SRC or DST is unaligned,
147      * then punt into the byte copy loop.  This should be rare.
148      */
149     if (n < sizeof(CYG_WORD) || CYG_STR_UNALIGNED (src, dst))
150     {
151         while (n--)
152             *dst++ = *src++;
153 #ifdef CYG_TRACING_FIXED
154         CYG_REPORT_RETVAL( s1 );
155 #endif
156         return s1;
157     } /* if */
158     
159     aligned_dst = (CYG_WORD *)dst;
160     aligned_src = (const CYG_WORD *)src;
161     
162     /* Copy 4X long words at a time if possible.  */
163     while (n >= CYG_STR_OPT_BIGBLOCKSIZE)
164     {
165         *aligned_dst++ = *aligned_src++;
166         *aligned_dst++ = *aligned_src++;
167         *aligned_dst++ = *aligned_src++;
168         *aligned_dst++ = *aligned_src++;
169         n -= CYG_STR_OPT_BIGBLOCKSIZE;
170     } /* while */
171     
172     /* Copy one long word at a time if possible.  */
173     while (n >= CYG_STR_OPT_LITTLEBLOCKSIZE)
174     {
175         *aligned_dst++ = *aligned_src++;
176         n -= CYG_STR_OPT_LITTLEBLOCKSIZE;
177     } /* while */
178     
179     /* Pick up any residual with a byte copier.  */
180     dst = (char*)aligned_dst;
181     src = (const char*)aligned_src;
182     while (n--)
183         *dst++ = *src++;
184     
185 #ifdef CYG_TRACING_FIXED
186     CYG_REPORT_RETVAL( s1 );
187 #endif
188     return s1;
189 #endif /* not defined(CYGIMP_PREFER_SMALL_TO_FAST_MEMCPY) ||
190         * defined(__OPTIMIZE_SIZE__) */
191 } /* _memcpy() */
192
193 /* EOF memcpy.c */