|
0
|
1 /*=========================================================================== |
|
|
2 // |
|
|
3 // memset.c |
|
|
4 // |
|
|
5 // ANSI standard memset() routine |
|
|
6 // |
|
|
7 //========================================================================== |
|
|
8 //####COPYRIGHTBEGIN#### |
|
|
9 // |
|
|
10 // ------------------------------------------- |
|
|
11 // The contents of this file are subject to the Cygnus eCos Public License |
|
|
12 // Version 1.0 (the "License"); you may not use this file except in |
|
|
13 // compliance with the License. You may obtain a copy of the License at |
|
|
14 // http://sourceware.cygnus.com/ecos |
|
|
15 // |
|
|
16 // Software distributed under the License is distributed on an "AS IS" |
|
|
17 // basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the |
|
|
18 // License for the specific language governing rights and limitations under |
|
|
19 // the License. |
|
|
20 // |
|
|
21 // The Original Code is eCos - Embedded Cygnus Operating System, released |
|
|
22 // September 30, 1998. |
|
|
23 // |
|
|
24 // The Initial Developer of the Original Code is Cygnus. Portions created |
|
|
25 // by Cygnus are Copyright (C) 1998 Cygnus Solutions. All Rights Reserved. |
|
|
26 // ------------------------------------------- |
|
|
27 // |
|
|
28 //####COPYRIGHTEND#### |
|
|
29 //========================================================================== |
|
|
30 //#####DESCRIPTIONBEGIN#### |
|
|
31 // |
|
|
32 // Author(s): jlarmour@cygnus.co.uk |
|
|
33 // Contributors: jlarmour@cygnus.co.uk |
|
|
34 // Date: 1998-06-04 |
|
|
35 // Purpose: This file implements the ANSI memset() function |
|
|
36 // Description: This file implements the memset() function defined in ANSI para |
|
|
37 // 7.11.6.1. This is implemented in the kernel rather than the |
|
|
38 // C library due to it being required by gcc whether or not the |
|
|
39 // C library has been configured in. |
|
|
40 // |
|
|
41 //####DESCRIPTIONEND#### |
|
|
42 // |
|
|
43 //==========================================================================*/ |
|
|
44 |
|
|
45 |
|
|
46 /* INCLUDES */ |
|
|
47 |
|
|
48 #include <pkgconf/infra.h> /* Configuration of infra package */ |
|
|
49 |
|
|
50 #include <cyg/infra/cyg_type.h> /* Common type definitions */ |
|
|
51 #include <cyg/infra/cyg_trac.h> /* Tracing support */ |
|
|
52 #include <cyg/infra/cyg_ass.h> /* Assertion support */ |
|
|
53 #include <stddef.h> /* Compiler defns such as size_t, NULL etc. */ |
|
|
54 |
|
|
55 /* MACROS */ |
|
|
56 |
|
|
57 /* Nonzero if X is not aligned on a word boundary. */ |
|
|
58 #define CYG_STR_UNALIGNED(X) ((CYG_WORD)(X) & (sizeof (CYG_WORD) - 1)) |
|
|
59 |
|
|
60 /* How many bytes are copied each iteration of the word copy loop in the |
|
|
61 * optimised string implementation |
|
|
62 */ |
|
|
63 #define CYG_STR_OPT_LITTLEBLOCKSIZE (sizeof (CYG_WORD)) |
|
|
64 |
|
|
65 /* EXPORTED SYMBOLS */ |
|
|
66 |
|
|
67 externC void * |
|
|
68 memset( void *s, int c, size_t n ) __attribute__ ((weak, alias("_memset"))); |
|
|
69 |
|
|
70 /* FUNCTIONS */ |
|
|
71 |
|
|
72 void * |
|
|
73 _memset( void *s, int c, size_t n ) |
|
|
74 { |
|
|
75 #if defined(CYGIMP_INFRA_PREFER_SMALL_TO_FAST_MEMSET) || defined(__OPTIMIZE_SIZE__) |
|
|
76 char *char_ptr = (char *)s; |
|
|
77 |
|
|
78 #ifdef CYG_TRACING_FIXED |
|
|
79 CYG_REPORT_FUNCNAMETYPE( "_memset", "returning %08x" ); |
|
|
80 CYG_REPORT_FUNCARG3( "s=%08x, c=%d, n=%d", s, c, n ); |
|
|
81 |
|
|
82 if (n != 0) |
|
|
83 { |
|
|
84 CYG_CHECK_DATA_PTR( s, "s is not a valid pointer!" ); |
|
|
85 CYG_CHECK_DATA_PTR( s+n-1, "s+n-1 is not a valid address!" ); |
|
|
86 } |
|
|
87 #endif |
|
|
88 |
|
|
89 while (n-- != 0) |
|
|
90 { |
|
|
91 *char_ptr++ = (char) c; |
|
|
92 } |
|
|
93 |
|
|
94 #ifdef CYG_TRACING_FIXED |
|
|
95 CYG_REPORT_RETVAL( s ); |
|
|
96 #endif |
|
|
97 return s; |
|
|
98 #else |
|
|
99 char *char_ptr = (char *)s; |
|
|
100 cyg_ucount8 count; |
|
|
101 CYG_WORD buffer; |
|
|
102 CYG_WORD *aligned_addr; |
|
|
103 char *unaligned_addr; |
|
|
104 |
|
|
105 #ifdef CYG_TRACING_FIXED |
|
|
106 CYG_REPORT_FUNCNAMETYPE( "_memset", "returning %08x" ); |
|
|
107 CYG_REPORT_FUNCARG3( "s=%08x, c=%d, n=%d", s, c, n ); |
|
|
108 |
|
|
109 if (n != 0) |
|
|
110 { |
|
|
111 CYG_CHECK_DATA_PTR( s, "s is not a valid pointer!" ); |
|
|
112 CYG_CHECK_DATA_PTR( (char *)s+n-1, "s+n-1 is not a valid address!" ); |
|
|
113 } |
|
|
114 #endif |
|
|
115 |
|
|
116 if (n < sizeof(CYG_WORD) || CYG_STR_UNALIGNED (s)) |
|
|
117 { |
|
|
118 while (n-- != 0) |
|
|
119 { |
|
|
120 *char_ptr++ = (char) c; |
|
|
121 } |
|
|
122 #ifdef CYG_TRACING_FIXED |
|
|
123 CYG_REPORT_RETVAL( s ); |
|
|
124 #endif |
|
|
125 return s; |
|
|
126 } |
|
|
127 |
|
|
128 /* If we get this far, we know that n is large and s is word-aligned. */ |
|
|
129 |
|
|
130 aligned_addr = (CYG_WORD *)s; |
|
|
131 |
|
|
132 /* Store C into each char sized location in BUFFER so that |
|
|
133 * we can set large blocks quickly. |
|
|
134 */ |
|
|
135 c &= 0xff; |
|
|
136 if (CYG_STR_OPT_LITTLEBLOCKSIZE == 4) |
|
|
137 { |
|
|
138 buffer = (c << 8) | c; |
|
|
139 buffer |= (buffer << 16); |
|
|
140 } |
|
|
141 else |
|
|
142 { |
|
|
143 buffer = 0; |
|
|
144 for (count = 0; count < CYG_STR_OPT_LITTLEBLOCKSIZE; count++) |
|
|
145 buffer = (buffer << 8) | c; |
|
|
146 } |
|
|
147 |
|
|
148 while (n >= CYG_STR_OPT_LITTLEBLOCKSIZE*4) |
|
|
149 { |
|
|
150 *aligned_addr++ = buffer; |
|
|
151 *aligned_addr++ = buffer; |
|
|
152 *aligned_addr++ = buffer; |
|
|
153 *aligned_addr++ = buffer; |
|
|
154 n -= 4*CYG_STR_OPT_LITTLEBLOCKSIZE; |
|
|
155 } |
|
|
156 |
|
|
157 while (n >= CYG_STR_OPT_LITTLEBLOCKSIZE) |
|
|
158 { |
|
|
159 *aligned_addr++ = buffer; |
|
|
160 n -= CYG_STR_OPT_LITTLEBLOCKSIZE; |
|
|
161 } |
|
|
162 |
|
|
163 /* Pick up the remainder with a bytewise loop. */ |
|
|
164 unaligned_addr = (char*)aligned_addr; |
|
|
165 while (n) |
|
|
166 { |
|
|
167 *unaligned_addr++ = (char)c; |
|
|
168 n--; |
|
|
169 } |
|
|
170 |
|
|
171 #ifdef CYG_TRACING_FIXED |
|
|
172 CYG_REPORT_RETVAL( s ); |
|
|
173 #endif |
|
|
174 return s; |
|
|
175 #endif /* not defined(CYGIMP_PREFER_SMALL_TO_FAST_MEMSET) || |
|
|
176 * defined(__OPTIMIZE_SIZE__) */ |
|
|
177 } /* _memset() */ |
|
|
178 |
|
|
179 /* EOF memset.c */ |