summaryrefslogtreecommitdiff
path: root/firmware/libc/memset.c
diff options
context:
space:
mode:
authorThomas Martitz <kugel@rockbox.org>2010-05-06 21:04:40 +0000
committerThomas Martitz <kugel@rockbox.org>2010-05-06 21:04:40 +0000
commit50a6ca39ad4ed01922aa4f755f0ca579788226cf (patch)
treec7881b015b220558167310345b162324c96be15a /firmware/libc/memset.c
parentadb506df14aded06ed6e9ebf8540e6fd383ffd6a (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.c110
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 */
+}