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