diff options
author | Thomas Martitz <kugel@rockbox.org> | 2010-05-06 21:04:40 +0000 |
---|---|---|
committer | Thomas Martitz <kugel@rockbox.org> | 2010-05-06 21:04:40 +0000 |
commit | 50a6ca39ad4ed01922aa4f755f0ca579788226cf (patch) | |
tree | c7881b015b220558167310345b162324c96be15a /firmware/libc/memset.c | |
parent | adb506df14aded06ed6e9ebf8540e6fd383ffd6a (diff) |
Move c/h files implementing/defining standard library stuff into a new libc directory, also standard'ify some parts of the code base (almost entirely #include fixes).
This is to a) to cleanup firmware/common and firmware/include a bit, but also b) for Rockbox as an application which should use the host system's c library and headers, separating makes it easy to exclude our files from the build.
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@25850 a1c6a512-1295-4272-9138-f99709370657
Diffstat (limited to 'firmware/libc/memset.c')
-rw-r--r-- | firmware/libc/memset.c | 110 |
1 files changed, 110 insertions, 0 deletions
diff --git a/firmware/libc/memset.c b/firmware/libc/memset.c new file mode 100644 index 0000000000..7b8d2137e8 --- /dev/null +++ b/firmware/libc/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> +#include "_ansi.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; + unsigned int i; + unsigned long buffer; + unsigned long *aligned_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 */ +} |