1 /*
2 FUNCTION
3 <<memset>>---set an area of memory
4
5 INDEX
6 memset
7
8 ANSI_SYNOPSIS
9 #include <string.h>
10 void *memset(void *<[dst]>, int <[c]>, size_t <[length]>);
11
12 TRAD_SYNOPSIS
13 #include <string.h>
14 void *memset(<[dst]>, <[c]>, <[length]>)
15 void *<[dst]>;
16 int <[c]>;
17 size_t <[length]>;
18
19 DESCRIPTION
20 This function converts the argument <[c]> into an unsigned
21 char and fills the first <[length]> characters of the array
22 pointed to by <[dst]> to the value.
23
24 RETURNS
25 <<memset>> returns the value of <[dst]>.
26
27 PORTABILITY
28 <<memset>> is ANSI C.
29
30 <<memset>> requires no supporting OS subroutines.
31
32 QUICKREF
33 memset ansi pure
34 */
35
36 #include <section_config.h>
37 #include <basic_types.h>
38
39 #include <string.h>
40 #include "local.h"
41
42 #define LBLOCKSIZE (sizeof(long))
43 #define UNALIGNED(X) ((long)X & (LBLOCKSIZE - 1))
44 #define TOO_SMALL(LEN) ((LEN) < LBLOCKSIZE)
45
46 LIBC_ROM_TEXT_SECTION
47 _LONG_CALL_
_memset(void * m,int c,size_t n)48 void * __inhibit_loop_to_libcall _memset(void * m , int c , size_t n)
49 {
50 char *s = (char *) m;
51
52 //#if !defined(PREFER_SIZE_OVER_SPEED)
53 u32 i;
54 unsigned long buffer;
55 unsigned long *aligned_addr;
56 unsigned int d = c & 0xff; /* To avoid sign extension, copy C to an
57 unsigned variable. */
58
59 while (UNALIGNED (s))
60 {
61 if (n--)
62 *s++ = (char) c;
63 else
64 return m;
65 }
66
67 if (!TOO_SMALL (n))
68 {
69 /* If we get this far, we know that n is large and s is word-aligned. */
70 aligned_addr = (unsigned long *) s;
71
72 /* Store D into each char sized location in BUFFER so that
73 we can set large blocks quickly. */
74 buffer = (d << 8) | d;
75 buffer |= (buffer << 16);
76 for (i = 32; i < LBLOCKSIZE * 8; i <<= 1)
77 buffer = (buffer << i) | buffer;
78
79 /* Unroll the loop. */
80 while (n >= LBLOCKSIZE*4)
81 {
82 *aligned_addr++ = buffer;
83 *aligned_addr++ = buffer;
84 *aligned_addr++ = buffer;
85 *aligned_addr++ = buffer;
86 n -= 4*LBLOCKSIZE;
87 }
88
89 while (n >= LBLOCKSIZE)
90 {
91 *aligned_addr++ = buffer;
92 n -= LBLOCKSIZE;
93 }
94 /* Pick up the remainder with a bytewise loop. */
95 s = (char*)aligned_addr;
96 }
97
98 //#endif /* not PREFER_SIZE_OVER_SPEED */
99
100 while (n--)
101 *s++ = (char) c;
102
103 return m;
104 }
105