1/*	$OpenBSD: memset.c,v 1.8 2017/01/24 08:09:05 kettenis Exp $	*/
2/*	$NetBSD: memset.c,v 1.6 1998/03/27 05:35:47 cgd Exp $	*/
3
4/*-
5 * Copyright (c) 1990, 1993
6 *	The Regents of the University of California.  All rights reserved.
7 *
8 * This code is derived from software contributed to Berkeley by
9 * Mike Hibler and Chris Torek.
10 *
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
13 * are met:
14 * 1. Redistributions of source code must retain the above copyright
15 *    notice, this list of conditions and the following disclaimer.
16 * 2. Redistributions in binary form must reproduce the above copyright
17 *    notice, this list of conditions and the following disclaimer in the
18 *    documentation and/or other materials provided with the distribution.
19 * 3. Neither the name of the University nor the names of its contributors
20 *    may be used to endorse or promote products derived from this software
21 *    without specific prior written permission.
22 *
23 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
24 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
27 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
28 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
29 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
32 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33 * SUCH DAMAGE.
34 */
35
36#include <sys/types.h>
37
38#include <sys/limits.h>
39#include <sys/systm.h>
40#include <lib/libkern/libkern.h>
41
42#undef bzero
43#undef memset
44
45#define	wsize	sizeof(u_int)
46#define	wmask	(wsize - 1)
47
48#ifdef BZERO
49#define	RETURN	return
50#define	VAL	0
51#define	WIDEVAL	0
52
53void
54bzero(void *dst0, size_t length)
55#else
56#define	RETURN	return (dst0)
57#define	VAL	c0
58#define	WIDEVAL	c
59
60void *
61memset(void *dst0, int c0, size_t length)
62#endif
63{
64	size_t t;
65#ifndef BZERO
66	u_int c;
67#endif
68	u_char *dst;
69
70	dst = dst0;
71	/*
72	 * If not enough words, just fill bytes.  A length >= 2 words
73	 * guarantees that at least one of them is `complete' after
74	 * any necessary alignment.  For instance:
75	 *
76	 *	|-----------|-----------|-----------|
77	 *	|00|01|02|03|04|05|06|07|08|09|0A|00|
78	 *	          ^---------------------^
79	 *		 dst		 dst+length-1
80	 *
81	 * but we use a minimum of 3 here since the overhead of the code
82	 * to do word writes is substantial.
83	 */
84	if (length < 3 * wsize) {
85		while (length != 0) {
86			*dst++ = VAL;
87			--length;
88		}
89		RETURN;
90	}
91
92#ifndef BZERO
93	if ((c = (u_char)c0) != 0) {	/* Fill the word. */
94		c = (c << 8) | c;	/* u_int is 16 bits. */
95#if UINT_MAX > 0xffff
96		c = (c << 16) | c;	/* u_int is 32 bits. */
97#endif
98#if UINT_MAX > 0xffffffff
99		c = (c << 32) | c;	/* u_int is 64 bits. */
100#endif
101	}
102#endif
103	/* Align destination by filling in bytes. */
104	if ((t = (u_long)dst & wmask) != 0) {
105		t = wsize - t;
106		length -= t;
107		do {
108			*dst++ = VAL;
109		} while (--t != 0);
110	}
111
112	/* Fill words.  Length was >= 2*words so we know t >= 1 here. */
113	t = length / wsize;
114	do {
115		*(u_int *)dst = WIDEVAL;
116		dst += wsize;
117	} while (--t != 0);
118
119	/* Mop up trailing bytes, if any. */
120	t = length & wmask;
121	if (t != 0)
122		do {
123			*dst++ = VAL;
124		} while (--t != 0);
125	RETURN;
126}
127