1 | /*=========================================================================== |
---|
2 | // |
---|
3 | // memset.c |
---|
4 | // |
---|
5 | // ANSI standard memset() 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 memset() function |
---|
47 | // Description: This file implements the memset() function defined in ANSI para |
---|
48 | // 7.11.6.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 X is not aligned on a word boundary. */ |
---|
69 | #define CYG_STR_UNALIGNED(X) ((CYG_WORD)(X) & (sizeof (CYG_WORD) - 1)) |
---|
70 | |
---|
71 | /* How many bytes are copied each iteration of the word copy loop in the |
---|
72 | * optimised string implementation |
---|
73 | */ |
---|
74 | #define CYG_STR_OPT_LITTLEBLOCKSIZE (sizeof (CYG_WORD)) |
---|
75 | |
---|
76 | /* EXPORTED SYMBOLS */ |
---|
77 | |
---|
78 | externC void * |
---|
79 | memset( void *s, int c, size_t n ) __attribute__ ((weak, alias("_memset"))); |
---|
80 | |
---|
81 | /* FUNCTIONS */ |
---|
82 | |
---|
83 | void * |
---|
84 | _memset( void *s, int c, size_t n ) |
---|
85 | { |
---|
86 | #if defined(CYGIMP_INFRA_PREFER_SMALL_TO_FAST_MEMSET) || defined(__OPTIMIZE_SIZE__) |
---|
87 | char *char_ptr = (char *)s; |
---|
88 | |
---|
89 | #ifdef CYG_TRACING_FIXED |
---|
90 | CYG_REPORT_FUNCNAMETYPE( "_memset", "returning %08x" ); |
---|
91 | CYG_REPORT_FUNCARG3( "s=%08x, c=%d, n=%d", s, c, n ); |
---|
92 | |
---|
93 | if (n != 0) |
---|
94 | { |
---|
95 | CYG_CHECK_DATA_PTR( char_ptr, "s is not a valid pointer!" ); |
---|
96 | CYG_CHECK_DATA_PTR( (&char_ptr[n-1]), "s+n-1 is not a valid address!" ); |
---|
97 | } |
---|
98 | #endif |
---|
99 | |
---|
100 | while (n-- != 0) |
---|
101 | { |
---|
102 | *char_ptr++ = (char) c; |
---|
103 | } |
---|
104 | |
---|
105 | #ifdef CYG_TRACING_FIXED |
---|
106 | CYG_REPORT_RETVAL( s ); |
---|
107 | #endif |
---|
108 | return s; |
---|
109 | #else |
---|
110 | char *char_ptr = (char *)s; |
---|
111 | cyg_ucount8 count; |
---|
112 | CYG_WORD buffer; |
---|
113 | CYG_WORD *aligned_addr; |
---|
114 | char *unaligned_addr; |
---|
115 | |
---|
116 | #ifdef CYG_TRACING_FIXED |
---|
117 | CYG_REPORT_FUNCNAMETYPE( "_memset", "returning %08x" ); |
---|
118 | CYG_REPORT_FUNCARG3( "s=%08x, c=%d, n=%d", s, c, n ); |
---|
119 | |
---|
120 | if (n != 0) |
---|
121 | { |
---|
122 | CYG_CHECK_DATA_PTR( s, "s is not a valid pointer!" ); |
---|
123 | CYG_CHECK_DATA_PTR( (char *)s+n-1, "s+n-1 is not a valid address!" ); |
---|
124 | } |
---|
125 | #endif |
---|
126 | |
---|
127 | if (n < sizeof(CYG_WORD) || CYG_STR_UNALIGNED (s)) |
---|
128 | { |
---|
129 | while (n-- != 0) |
---|
130 | { |
---|
131 | *char_ptr++ = (char) c; |
---|
132 | } |
---|
133 | #ifdef CYG_TRACING_FIXED |
---|
134 | CYG_REPORT_RETVAL( s ); |
---|
135 | #endif |
---|
136 | return s; |
---|
137 | } |
---|
138 | |
---|
139 | /* If we get this far, we know that n is large and s is word-aligned. */ |
---|
140 | |
---|
141 | aligned_addr = (CYG_WORD *)s; |
---|
142 | |
---|
143 | /* Store C into each char sized location in BUFFER so that |
---|
144 | * we can set large blocks quickly. |
---|
145 | */ |
---|
146 | c &= 0xff; |
---|
147 | if (CYG_STR_OPT_LITTLEBLOCKSIZE == 4) |
---|
148 | { |
---|
149 | buffer = (c << 8) | c; |
---|
150 | buffer |= (buffer << 16); |
---|
151 | } |
---|
152 | else |
---|
153 | { |
---|
154 | buffer = 0; |
---|
155 | for (count = 0; count < CYG_STR_OPT_LITTLEBLOCKSIZE; count++) |
---|
156 | buffer = (buffer << 8) | c; |
---|
157 | } |
---|
158 | |
---|
159 | while (n >= CYG_STR_OPT_LITTLEBLOCKSIZE*4) |
---|
160 | { |
---|
161 | *aligned_addr++ = buffer; |
---|
162 | *aligned_addr++ = buffer; |
---|
163 | *aligned_addr++ = buffer; |
---|
164 | *aligned_addr++ = buffer; |
---|
165 | n -= 4*CYG_STR_OPT_LITTLEBLOCKSIZE; |
---|
166 | } |
---|
167 | |
---|
168 | while (n >= CYG_STR_OPT_LITTLEBLOCKSIZE) |
---|
169 | { |
---|
170 | *aligned_addr++ = buffer; |
---|
171 | n -= CYG_STR_OPT_LITTLEBLOCKSIZE; |
---|
172 | } |
---|
173 | |
---|
174 | /* Pick up the remainder with a bytewise loop. */ |
---|
175 | unaligned_addr = (char*)aligned_addr; |
---|
176 | while (n) |
---|
177 | { |
---|
178 | *unaligned_addr++ = (char)c; |
---|
179 | n--; |
---|
180 | } |
---|
181 | |
---|
182 | #ifdef CYG_TRACING_FIXED |
---|
183 | CYG_REPORT_RETVAL( s ); |
---|
184 | #endif |
---|
185 | return s; |
---|
186 | #endif /* not defined(CYGIMP_PREFER_SMALL_TO_FAST_MEMSET) || |
---|
187 | * defined(__OPTIMIZE_SIZE__) */ |
---|
188 | } /* _memset() */ |
---|
189 | |
---|
190 | /* EOF memset.c */ |
---|