]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - reference/newlib-c/memset.c
Import the Linaro Cortex Strings library from
[FreeBSD/FreeBSD.git] / reference / newlib-c / memset.c
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 "shim.h"
37 #include <string.h>
38
39 #define LBLOCKSIZE (sizeof(long))
40 #define UNALIGNED(X)   ((long)X & (LBLOCKSIZE - 1))
41 #define TOO_SMALL(LEN) ((LEN) < LBLOCKSIZE)
42
43 _PTR
44 _DEFUN (memset, (m, c, n),
45         _PTR m _AND
46         int c _AND
47         size_t n)
48 {
49   char *s = (char *) m;
50
51 #if !defined(PREFER_SIZE_OVER_SPEED) && !defined(__OPTIMIZE_SIZE__)
52   int i;
53   unsigned long buffer;
54   unsigned long *aligned_addr;
55   unsigned int d = c & 0xff;    /* To avoid sign extension, copy C to an
56                                    unsigned variable.  */
57
58   while (UNALIGNED (s))
59     {
60       if (n--)
61         *s++ = (char) c;
62       else
63         return m;
64     }
65
66   if (!TOO_SMALL (n))
67     {
68       /* If we get this far, we know that n is large and s is word-aligned. */
69       aligned_addr = (unsigned long *) s;
70
71       /* Store D into each char sized location in BUFFER so that
72          we can set large blocks quickly.  */
73       buffer = (d << 8) | d;
74       buffer |= (buffer << 16);
75       for (i = 32; i < LBLOCKSIZE * 8; i <<= 1)
76         buffer = (buffer << i) | buffer;
77
78       /* Unroll the loop.  */
79       while (n >= LBLOCKSIZE*4)
80         {
81           *aligned_addr++ = buffer;
82           *aligned_addr++ = buffer;
83           *aligned_addr++ = buffer;
84           *aligned_addr++ = buffer;
85           n -= 4*LBLOCKSIZE;
86         }
87
88       while (n >= LBLOCKSIZE)
89         {
90           *aligned_addr++ = buffer;
91           n -= LBLOCKSIZE;
92         }
93       /* Pick up the remainder with a bytewise loop.  */
94       s = (char*)aligned_addr;
95     }
96
97 #endif /* not PREFER_SIZE_OVER_SPEED */
98
99   while (n--)
100     *s++ = (char) c;
101
102   return m;
103 }