diff options
author | Christopher Faylor <me@cgf.cx> | 2000-02-17 19:39:52 +0000 |
---|---|---|
committer | Christopher Faylor <me@cgf.cx> | 2000-02-17 19:39:52 +0000 |
commit | 8a0efa53e44919bcf5ccb1d3353618a82afdf8bc (patch) | |
tree | 68c3dbf3f2c6fd5d49777def9914d77b5cd4589d /newlib/libc/string/memset.c | |
parent | 1fd5e000ace55b323124c7e556a7a864b972a5c4 (diff) | |
download | cygnal-8a0efa53e44919bcf5ccb1d3353618a82afdf8bc.tar.gz cygnal-8a0efa53e44919bcf5ccb1d3353618a82afdf8bc.tar.bz2 cygnal-8a0efa53e44919bcf5ccb1d3353618a82afdf8bc.zip |
import newlib-2000-02-17 snapshot
Diffstat (limited to 'newlib/libc/string/memset.c')
-rw-r--r-- | newlib/libc/string/memset.c | 110 |
1 files changed, 110 insertions, 0 deletions
diff --git a/newlib/libc/string/memset.c b/newlib/libc/string/memset.c new file mode 100644 index 000000000..f6ec46b9a --- /dev/null +++ b/newlib/libc/string/memset.c @@ -0,0 +1,110 @@ +/* +FUNCTION + <<memset>>---set an area of memory + +INDEX + memset + +ANSI_SYNOPSIS + #include <string.h> + void *memset(const void *<[dst]>, int <[c]>, size_t <[length]>); + +TRAD_SYNOPSIS + #include <string.h> + void *memset(<[dst]>, <[c]>, <[length]>) + void *<[dst]>; + int <[c]>; + size_t <[length]>; + +DESCRIPTION + This function converts the argument <[c]> into an unsigned + char and fills the first <[length]> characters of the array + pointed to by <[dst]> to the value. + +RETURNS + <<memset>> returns the value of <[m]>. + +PORTABILITY +<<memset>> is ANSI C. + + <<memset>> requires no supporting OS subroutines. + +QUICKREF + memset ansi pure +*/ + +#include <string.h> + +#define LBLOCKSIZE (sizeof(long)) +#define UNALIGNED(X) ((long)X & (LBLOCKSIZE - 1)) +#define TOO_SMALL(LEN) ((LEN) < LBLOCKSIZE) + +_PTR +_DEFUN (memset, (m, c, n), + _PTR m _AND + int c _AND + size_t n) +{ +#if defined(PREFER_SIZE_OVER_SPEED) || defined(__OPTIMIZE_SIZE__) + char *s = (char *) m; + + while (n-- != 0) + { + *s++ = (char) c; + } + + return m; +#else + char *s = (char *) m; + int count, i; + unsigned long buffer; + unsigned long *aligned_addr; + unsigned char *unaligned_addr; + + if (!TOO_SMALL (n) && !UNALIGNED (m)) + { + /* If we get this far, we know that n is large and m is word-aligned. */ + + aligned_addr = (unsigned long*)m; + + /* Store C into each char sized location in BUFFER so that + we can set large blocks quickly. */ + c &= 0xff; + if (LBLOCKSIZE == 4) + { + buffer = (c << 8) | c; + buffer |= (buffer << 16); + } + else + { + buffer = 0; + for (i = 0; i < LBLOCKSIZE; i++) + buffer = (buffer << 8) | c; + } + + while (n >= LBLOCKSIZE*4) + { + *aligned_addr++ = buffer; + *aligned_addr++ = buffer; + *aligned_addr++ = buffer; + *aligned_addr++ = buffer; + n -= 4*LBLOCKSIZE; + } + + while (n >= LBLOCKSIZE) + { + *aligned_addr++ = buffer; + n -= LBLOCKSIZE; + } + /* Pick up the remainder with a bytewise loop. */ + s = (char*)aligned_addr; + } + + while (n--) + { + *s++ = (char)c; + } + + return m; +#endif /* not PREFER_SIZE_OVER_SPEED */ +} |