/* FUNCTION <>---set an area of memory INDEX memset SYNOPSIS #include 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 <> returns the value of <[dst]>. PORTABILITY <> is ANSI C. <> requires no supporting OS subroutines. QUICKREF memset ansi pure */ #include #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__) #if LBLOCKSIZE > 4 unsigned int i; #endif 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); #if LBLOCKSIZE > 4 for (i = 32; i < LBLOCKSIZE * 8; i <<= 1) buffer = (buffer << i) | buffer; #endif /* 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; }