Module Name:    src
Committed By:   matt
Date:           Mon Aug 17 17:24:25 UTC 2009

Added Files:
        src/common/lib/libc/string [matt-nb5-mips64]: bzero2.c memset2.c

Log Message:
Add word-load-store optimized version of memset/bzero.  On platforms with
64bit registers they can be as efficient as assembly coded version.


To generate a diff of this commit:
cvs rdiff -u -r0 -r1.1.2.1 src/common/lib/libc/string/bzero2.c \
    src/common/lib/libc/string/memset2.c

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Added files:

Index: src/common/lib/libc/string/bzero2.c
diff -u /dev/null src/common/lib/libc/string/bzero2.c:1.1.2.1
--- /dev/null	Mon Aug 17 17:24:25 2009
+++ src/common/lib/libc/string/bzero2.c	Mon Aug 17 17:24:25 2009
@@ -0,0 +1,36 @@
+/*-
+ * Copyright (c) 2009 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Matt Thomas <[email protected]>.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#define	BZERO
+
+#include "memset2.c"
+
+#if defined(LIBC_SCCS) && !defined(lint)
+__RCSID("$NetBSD: bzero2.c,v 1.1.2.1 2009/08/17 17:24:25 matt Exp $");
+#endif /* LIBC_SCCS and not lint */
Index: src/common/lib/libc/string/memset2.c
diff -u /dev/null src/common/lib/libc/string/memset2.c:1.1.2.1
--- /dev/null	Mon Aug 17 17:24:25 2009
+++ src/common/lib/libc/string/memset2.c	Mon Aug 17 17:24:25 2009
@@ -0,0 +1,208 @@
+/*-
+ * Copyright (c) 2009 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Matt Thomas <[email protected]>.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/types.h>
+
+#if !defined(_KERNEL) && !defined(_STANDALONE)
+#include <assert.h>
+#include <limits.h>
+#include <string.h>
+#include <inttypes.h>
+#else
+#include <lib/libkern/libkern.h>
+#include <machine/limits.h>
+#endif 
+
+#include <sys/endian.h>
+#include <machine/types.h>
+
+#ifdef _FORTIFY_SOURCE
+#undef bzero
+#undef memset
+#endif
+
+#if defined(LIBC_SCCS) && !defined(lint)
+__RCSID("$NetBSD: memset2.c,v 1.1.2.1 2009/08/17 17:24:25 matt Exp $");    
+#endif /* LIBC_SCCS and not lint */
+
+/*
+ * Assume register_t is the widest non-synthetic type.
+ */
+typedef register_t memword_t;
+
+#ifdef BZERO
+static inline
+#define	memset memset0
+#endif
+
+void *
+memset(void *addr, int c, size_t len)
+{
+	memword_t *dstp = addr;
+	memword_t *edstp;
+	memword_t fill;
+#ifndef __OPTIMIZE_SIZE__
+	memword_t keep_mask = 0;
+#endif
+	size_t fill_count;
+
+	_DIAGASSERT(addr != 0);
+
+	if (__predict_false(len == 0))
+		return addr;
+
+	/*
+	 * Pad out the fill byte (v) across a memword_t.
+	 * The conditional at the end prevents GCC from complaing about
+	 * shift count >= width of type 
+	 */
+	fill = c;
+	fill |= fill << 8;
+	fill |= fill << 16;
+	fill |= fill << (sizeof(c) < sizeof(fill) ? 32 : 0);
+
+	/*
+	 * Get the number of unaligned bytes to fill in the first word.
+	 */
+	fill_count = -(uintptr_t)addr & (sizeof(memword_t) - 1);
+
+	if (__predict_false(fill_count != 0)) {
+#ifndef __OPTIMIZE_SIZE__
+		/*
+		 * We want to clear <fill_count> trailing bytes in the word.
+		 * On big/little endian, these are the least/most significant,
+		 * bits respectively.  So as we shift, the keep_mask will only
+		 * have bits set for the bytes we won't be filling.
+		 */
+#if BYTE_ORDER == BIG_ENDIAN
+		keep_mask = ~(memword_t)0U << (fill_count * 8);
+#endif
+#if BYTE_ORDER == LITTLE_ENDIAN
+		keep_mask = ~(memword_t)0U << (fill_count * 8);
+#endif
+		/*
+		 * Make sure dstp is aligned to a memword_t boundary.
+		 */
+		dstp = (memword_t *)((uintptr_t)addr & -sizeof(memword_t));
+		if (len >= fill_count) {
+			/*
+			 * If we can fill the rest of this word, then we mask
+			 * off the bytes we are filling and then fill in those
+			 * bytes with the new fill value.
+			 */
+			*dstp = (*dstp & keep_mask) | (fill & ~keep_mask);
+			len -= fill_count;
+			if (__predict_false(len == 0))
+				return addr;
+			/*
+			 * Since we were able to fill the rest of this word,
+			 * we will advance to the next word and thus have no
+			 * bytes to preserve.
+			 *
+			 * If we don't have enough to fill the rest of this
+			 * word, we will fall through the following loop
+			 * (since there are no full words to fill).  Then we
+			 * use the keep_mask above to preserve the leading
+			 * bytes of word.
+			 */
+			dstp++;
+			keep_mask = 0;
+		}
+#else /* __OPTIMIZE_SIZE__ */
+		uint8_t *dp, *ep;
+		for (dp = (uint8_t *)dstp, ep = dp + fill_count;
+		     dp != ep; dp++)
+			*dp = fill;
+		dstp = (memword_t *)ep;
+		len -= fill_count;
+#endif /* __OPTIMIZE_SIZE__ */
+	}
+
+	/*
+	 * Simply fill memory one word at time (for as many full words we have
+	 * to write).
+	 */
+	for (edstp = dstp + len / sizeof(memword_t); dstp != edstp; dstp++)
+		*dstp = fill;
+
+	/*
+	 * We didn't subtract out the full words we just filled since we know
+	 * by the time we get here we will have less than a words worth to
+	 * write.  So we can concern ourselves with only the subword len bits.
+	 */
+	len &= sizeof(memword_t)-1;
+	if (len > 0) {
+#ifndef __OPTIMIZE_SIZE__
+		/*
+		 * We want to clear <len> leading bytes in the word.
+		 * On big/little endian, these are the most/least significant
+		 * bits, respectively,  But as we want the mask of the bytes to
+		 * keep, we have to complement the mask.  So after we shift,
+		 * the keep_mask will only have bits set for the bytes we won't
+		 * be filling.
+		 *
+		 * But the keep_mask could already have bytes to preserve
+		 * if the amount to fill was less than the amount of traiing
+		 * space in the first word.
+		 */
+#if BYTE_ORDER == BIG_ENDIAN
+		keep_mask |= ~(~(memword_t)0U >> (len * 8));
+#endif
+#if BYTE_ORDER == LITTLE_ENDIAN
+		keep_mask |= ~(~(memword_t)0U << (len * 8));
+#endif
+		/*
+		 * Now we mask off the bytes we are filling and then fill in
+		 * those bytes with the new fill value.
+		 */
+		*dstp = (*dstp & keep_mask) | (fill & ~keep_mask);
+#else /* __OPTIMIZE_SIZE__ */
+		uint8_t *dp, *ep;
+		for (dp = (uint8_t *)dstp, ep = dp + len;
+		     dp != ep; dp++)
+			*dp = fill;
+#endif /* __OPTIMIZE_SIZE__ */
+	}
+
+	/*
+	 * Return the initial addr
+	 */
+	return addr;
+}
+
+#ifdef BZERO
+/*
+ * For bzero, simply inline memset and let the compiler optimize things away.
+ */
+void
+bzero(void *addr, size_t len)
+{
+	memset(addr, 0, len);
+}
+#endif

Reply via email to