diff options
author | Oxore <oxore@protonmail.com> | 2023-03-07 16:05:46 +0300 |
---|---|---|
committer | Oxore <oxore@protonmail.com> | 2023-03-07 17:58:42 +0300 |
commit | 5f7d4d6e9f47d328e7c4ef71030bdc9e34892798 (patch) | |
tree | 1f4dbecf6b27e268c0590404399c5d5fd91965d0 /third_party/newlib/string/memset.c | |
parent | e4a9be2a4f68781d318770296a50f4823c419805 (diff) |
Get rid of libc, take just parts of it
Diffstat (limited to 'third_party/newlib/string/memset.c')
-rw-r--r-- | third_party/newlib/string/memset.c | 96 |
1 files changed, 96 insertions, 0 deletions
diff --git a/third_party/newlib/string/memset.c b/third_party/newlib/string/memset.c new file mode 100644 index 0000000..e8e667a --- /dev/null +++ b/third_party/newlib/string/memset.c @@ -0,0 +1,96 @@ +/* +FUNCTION + <<memset>>---set an area of memory + +INDEX + memset + +SYNOPSIS + #include <string.h> + void *memset(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 <[dst]>. + +PORTABILITY +<<memset>> is ANSI C. + + <<memset>> requires no supporting OS subroutines. + +QUICKREF + memset ansi pure +*/ + +#include <string.h> +#include "local.h" + +#define LBLOCKSIZE (sizeof(long)) +#define UNALIGNED(X) ((long)X & (LBLOCKSIZE - 1)) +#define TOO_SMALL(LEN) ((LEN) < LBLOCKSIZE) + +void * +__inhibit_loop_to_libcall +memset (void *m, + int c, + size_t n) +{ + char *s = (char *) m; + +#if !defined(PREFER_SIZE_OVER_SPEED) && !defined(__OPTIMIZE_SIZE__) + unsigned int i; + unsigned long buffer; + unsigned long *aligned_addr; + unsigned int d = c & 0xff; /* To avoid sign extension, copy C to an + unsigned variable. */ + + while (UNALIGNED (s)) + { + if (n--) + *s++ = (char) c; + else + return m; + } + + if (!TOO_SMALL (n)) + { + /* If we get this far, we know that n is large and s is word-aligned. */ + aligned_addr = (unsigned long *) s; + + /* Store D into each char sized location in BUFFER so that + we can set large blocks quickly. */ + buffer = (d << 8) | d; + buffer |= (buffer << 16); + for (i = 32; i < LBLOCKSIZE * 8; i <<= 1) + buffer = (buffer << i) | buffer; + + /* Unroll the loop. */ + 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; + } + +#endif /* not PREFER_SIZE_OVER_SPEED */ + + while (n--) + *s++ = (char) c; + + return m; +} |