xref: /netbsd-src/common/lib/libc/string/memset.c (revision 0d57af0fd1574e1b2b728e3a5cb9215da139f9bf)
1*0d57af0fSjmcneill /*	$NetBSD: memset.c,v 1.12 2019/03/30 10:18:03 jmcneill Exp $	*/
237c9f0a6Schristos 
337c9f0a6Schristos /*-
437c9f0a6Schristos  * Copyright (c) 1990, 1993
537c9f0a6Schristos  *	The Regents of the University of California.  All rights reserved.
637c9f0a6Schristos  *
737c9f0a6Schristos  * This code is derived from software contributed to Berkeley by
837c9f0a6Schristos  * Mike Hibler and Chris Torek.
937c9f0a6Schristos  *
1037c9f0a6Schristos  * Redistribution and use in source and binary forms, with or without
1137c9f0a6Schristos  * modification, are permitted provided that the following conditions
1237c9f0a6Schristos  * are met:
1337c9f0a6Schristos  * 1. Redistributions of source code must retain the above copyright
1437c9f0a6Schristos  *    notice, this list of conditions and the following disclaimer.
1537c9f0a6Schristos  * 2. Redistributions in binary form must reproduce the above copyright
1637c9f0a6Schristos  *    notice, this list of conditions and the following disclaimer in the
1737c9f0a6Schristos  *    documentation and/or other materials provided with the distribution.
1837c9f0a6Schristos  * 3. Neither the name of the University nor the names of its contributors
1937c9f0a6Schristos  *    may be used to endorse or promote products derived from this software
2037c9f0a6Schristos  *    without specific prior written permission.
2137c9f0a6Schristos  *
2237c9f0a6Schristos  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
2337c9f0a6Schristos  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
2437c9f0a6Schristos  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
2537c9f0a6Schristos  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
2637c9f0a6Schristos  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
2737c9f0a6Schristos  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2837c9f0a6Schristos  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2937c9f0a6Schristos  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
3037c9f0a6Schristos  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
3137c9f0a6Schristos  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
3237c9f0a6Schristos  * SUCH DAMAGE.
3337c9f0a6Schristos  */
3437c9f0a6Schristos 
3537c9f0a6Schristos #include <sys/cdefs.h>
3637c9f0a6Schristos #if defined(LIBC_SCCS) && !defined(lint)
3737c9f0a6Schristos #if 0
3837c9f0a6Schristos static char sccsid[] = "@(#)memset.c	8.1 (Berkeley) 6/4/93";
3937c9f0a6Schristos #else
40*0d57af0fSjmcneill __RCSID("$NetBSD: memset.c,v 1.12 2019/03/30 10:18:03 jmcneill Exp $");
4137c9f0a6Schristos #endif
4237c9f0a6Schristos #endif /* LIBC_SCCS and not lint */
4337c9f0a6Schristos 
4437c9f0a6Schristos #include <sys/types.h>
4537c9f0a6Schristos 
4637c9f0a6Schristos #if !defined(_KERNEL) && !defined(_STANDALONE)
4737c9f0a6Schristos #include <assert.h>
4837c9f0a6Schristos #include <limits.h>
4937c9f0a6Schristos #include <string.h>
5037c9f0a6Schristos #else
5137c9f0a6Schristos #include <lib/libkern/libkern.h>
52d0b9e6c9Stsutsui #if defined(BZERO) && defined(_STANDALONE)
53d0b9e6c9Stsutsui #include <lib/libsa/stand.h>
54d0b9e6c9Stsutsui #endif
5537c9f0a6Schristos #include <machine/limits.h>
5637c9f0a6Schristos #endif
5737c9f0a6Schristos 
5837c9f0a6Schristos #define	wsize	sizeof(u_int)
5937c9f0a6Schristos #define	wmask	(wsize - 1)
6037c9f0a6Schristos 
61a8565cf9Schristos #ifdef _FORTIFY_SOURCE
62a8565cf9Schristos #undef bzero
63a8565cf9Schristos #endif
644041630eSjoerg #undef memset
65a8565cf9Schristos 
66985a3d11Schristos #ifndef __OPTIMIZE_SIZE__
6737c9f0a6Schristos #ifdef BZERO
6837c9f0a6Schristos #define	RETURN	return
6937c9f0a6Schristos #define	VAL	0
7037c9f0a6Schristos #define	WIDEVAL	0
7137c9f0a6Schristos 
7237c9f0a6Schristos void
bzero(void * dst0,size_t length)73a8565cf9Schristos bzero(void *dst0, size_t length)
7437c9f0a6Schristos #else
7537c9f0a6Schristos #define	RETURN	return (dst0)
7637c9f0a6Schristos #define	VAL	c0
7737c9f0a6Schristos #define	WIDEVAL	c
7837c9f0a6Schristos 
7996f5bbd2Sjoerg #if defined(__ARM_EABI__)
8096f5bbd2Sjoerg void __aeabi_memset(void *, size_t, int);
8196f5bbd2Sjoerg void __aeabi_memclr(void *, size_t);
8296f5bbd2Sjoerg 
83*0d57af0fSjmcneill __strong_alias(__aeabi_memset4, __aeabi_memset)
84*0d57af0fSjmcneill __strong_alias(__aeabi_memset8, __aeabi_memset)
8596f5bbd2Sjoerg 
8696f5bbd2Sjoerg void
8796f5bbd2Sjoerg __aeabi_memset(void *dst0, size_t length, int c)
8896f5bbd2Sjoerg {
8996f5bbd2Sjoerg 	memset(dst0, c, length);
9096f5bbd2Sjoerg }
9196f5bbd2Sjoerg 
9296f5bbd2Sjoerg void
9396f5bbd2Sjoerg __aeabi_memclr(void *dst0, size_t length)
9496f5bbd2Sjoerg {
9596f5bbd2Sjoerg 	memset(dst0, 0, length);
9696f5bbd2Sjoerg }
9796f5bbd2Sjoerg #endif
9896f5bbd2Sjoerg 
9937c9f0a6Schristos void *
100a8565cf9Schristos memset(void *dst0, int c0, size_t length)
10137c9f0a6Schristos #endif
10237c9f0a6Schristos {
10337c9f0a6Schristos 	size_t t;
10437c9f0a6Schristos #ifndef BZERO
10537c9f0a6Schristos 	u_int c;
10637c9f0a6Schristos #endif
10737c9f0a6Schristos 	u_char *dst;
10837c9f0a6Schristos 
10937c9f0a6Schristos 	dst = dst0;
11037c9f0a6Schristos 	/*
11137c9f0a6Schristos 	 * If not enough words, just fill bytes.  A length >= 2 words
11237c9f0a6Schristos 	 * guarantees that at least one of them is `complete' after
11337c9f0a6Schristos 	 * any necessary alignment.  For instance:
11437c9f0a6Schristos 	 *
11537c9f0a6Schristos 	 *	|-----------|-----------|-----------|
11637c9f0a6Schristos 	 *	|00|01|02|03|04|05|06|07|08|09|0A|00|
11737c9f0a6Schristos 	 *	          ^---------------------^
11837c9f0a6Schristos 	 *		 dst		 dst+length-1
11937c9f0a6Schristos 	 *
12037c9f0a6Schristos 	 * but we use a minimum of 3 here since the overhead of the code
12137c9f0a6Schristos 	 * to do word writes is substantial.
12237c9f0a6Schristos 	 */
12337c9f0a6Schristos 	if (length < 3 * wsize) {
12437c9f0a6Schristos 		while (length != 0) {
12537c9f0a6Schristos 			*dst++ = VAL;
12637c9f0a6Schristos 			--length;
12737c9f0a6Schristos 		}
12837c9f0a6Schristos 		RETURN;
12937c9f0a6Schristos 	}
13037c9f0a6Schristos 
13137c9f0a6Schristos #ifndef BZERO
13237c9f0a6Schristos 	if ((c = (u_char)c0) != 0) {	/* Fill the word. */
13337c9f0a6Schristos 		c = (c << 8) | c;	/* u_int is 16 bits. */
13437c9f0a6Schristos #if UINT_MAX > 0xffff
13537c9f0a6Schristos 		c = (c << 16) | c;	/* u_int is 32 bits. */
13637c9f0a6Schristos #endif
13737c9f0a6Schristos #if UINT_MAX > 0xffffffff
13837c9f0a6Schristos 		c = (c << 32) | c;	/* u_int is 64 bits. */
13937c9f0a6Schristos #endif
14037c9f0a6Schristos 	}
14137c9f0a6Schristos #endif
14237c9f0a6Schristos 	/* Align destination by filling in bytes. */
14337c9f0a6Schristos 	if ((t = (size_t)((u_long)dst & wmask)) != 0) {
14437c9f0a6Schristos 		t = wsize - t;
14537c9f0a6Schristos 		length -= t;
14637c9f0a6Schristos 		do {
14737c9f0a6Schristos 			*dst++ = VAL;
14837c9f0a6Schristos 		} while (--t != 0);
14937c9f0a6Schristos 	}
15037c9f0a6Schristos 
15137c9f0a6Schristos 	/* Fill words.  Length was >= 2*words so we know t >= 1 here. */
15237c9f0a6Schristos 	t = length / wsize;
15337c9f0a6Schristos 	do {
15437c9f0a6Schristos 		*(u_int *)(void *)dst = WIDEVAL;
15537c9f0a6Schristos 		dst += wsize;
15637c9f0a6Schristos 	} while (--t != 0);
15737c9f0a6Schristos 
15837c9f0a6Schristos 	/* Mop up trailing bytes, if any. */
15937c9f0a6Schristos 	t = length & wmask;
16037c9f0a6Schristos 	if (t != 0)
16137c9f0a6Schristos 		do {
16237c9f0a6Schristos 			*dst++ = VAL;
16337c9f0a6Schristos 		} while (--t != 0);
16437c9f0a6Schristos 	RETURN;
16537c9f0a6Schristos }
166f5c28010Sapb #else /* __OPTIMIZE_SIZE__ */
167985a3d11Schristos #ifdef BZERO
168985a3d11Schristos void
bzero(void * dstv,size_t length)169985a3d11Schristos bzero(void *dstv, size_t length)
170985a3d11Schristos {
171985a3d11Schristos 	u_char *dst = dstv;
172985a3d11Schristos 	while (length-- > 0)
173985a3d11Schristos 		*dst++ = 0;
174985a3d11Schristos }
17573e50f11She #else
176985a3d11Schristos void *
memset(void * dstv,int c,size_t length)177985a3d11Schristos memset(void *dstv, int c, size_t length)
178985a3d11Schristos {
179985a3d11Schristos 	u_char *dst = dstv;
180985a3d11Schristos 	while (length-- > 0)
181985a3d11Schristos 		*dst++ = c;
182a58a2cddShe 	return dstv;
183985a3d11Schristos }
18473e50f11She #endif /* BZERO */
185f5c28010Sapb #endif /* __OPTIMIZE_SIZE__ */
186