From: David Hunt <david.hunt@intel.com>
To: dev@dpdk.org
Cc: Benjamin Boren <Ben.Boren@intel.com>
Subject: [dpdk-dev] [PATCH 05/11] lib: add armv8 rte_memcpy.h
Date: Fri, 23 Oct 2015 15:17:07 +0100 [thread overview]
Message-ID: <1445609833-17649-6-git-send-email-david.hunt@intel.com> (raw)
In-Reply-To: <1445609833-17649-1-git-send-email-david.hunt@intel.com>
From: Benjamin Boren <Ben.Boren@intel.com>
Signed-off-by: Benjamin Boren <Ben.Boren@intel.com>
Signed-off-by: David Hunt <david.hunt@intel.com>
---
.../common/include/arch/arm64/rte_memcpy.h | 266 +++++++++++++++++++++
1 file changed, 266 insertions(+)
create mode 100644 lib/librte_eal/common/include/arch/arm64/rte_memcpy.h
diff --git a/lib/librte_eal/common/include/arch/arm64/rte_memcpy.h b/lib/librte_eal/common/include/arch/arm64/rte_memcpy.h
new file mode 100644
index 0000000..d413045
--- /dev/null
+++ b/lib/librte_eal/common/include/arch/arm64/rte_memcpy.h
@@ -0,0 +1,266 @@
+/*
+ * BSD LICENSE
+ *
+ * Copyright (C) IBM Corporation 2014.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * 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.
+ * * Neither the name of IBM Corporation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT
+ * OWNER 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.
+*/
+
+#ifndef _RTE_MEMCPY_ARM_64_H_
+#define _RTE_MEMCPY_ARM_64_H_
+
+#include <stdint.h>
+#include <string.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include "generic/rte_memcpy.h"
+
+
+static inline void
+rte_mov16(uint8_t *dst, const uint8_t *src)
+{
+ asm volatile("LDP d0, d1, [%0]\n\t"
+ "STP d0, d1, [%1]\n\t"
+ : : "r" (src), "r" (dst) :
+ );
+}
+
+static inline void
+rte_mov32(uint8_t *dst, const uint8_t *src)
+{
+ asm volatile("LDP q0, q1, [%0]\n\t"
+ "STP q0, q1, [%1]\n\t"
+ : : "r" (src), "r" (dst) :
+ );
+}
+
+static inline void
+rte_mov48(uint8_t *dst, const uint8_t *src)
+{
+ asm volatile("LDP q0, q1, [%0]\n\t"
+ "STP q0, q1, [%1]\n\t"
+ "LDP d0, d1, [%0 , #32]\n\t"
+ "STP d0, d1, [%1 , #32]\n\t"
+ : : "r" (src), "r" (dst) :
+ );
+}
+
+static inline void
+rte_mov64(uint8_t *dst, const uint8_t *src)
+{
+ asm volatile("LDP q0, q1, [%0]\n\t"
+ "STP q0, q1, [%1]\n\t"
+ "LDP q0, q1, [%0 , #32]\n\t"
+ "STP q0, q1, [%1 , #32]\n\t"
+ : : "r" (src), "r" (dst) :
+ );
+}
+
+static inline void
+rte_mov128(uint8_t *dst, const uint8_t *src)
+{
+ asm volatile("LDP q0, q1, [%0]\n\t"
+ "STP q0, q1, [%1]\n\t"
+ "LDP q0, q1, [%0 , #32]\n\t"
+ "STP q0, q1, [%1 , #32]\n\t"
+ "LDP q0, q1, [%0 , #64]\n\t"
+ "STP q0, q1, [%1 , #64]\n\t"
+ "LDP q0, q1, [%0 , #96]\n\t"
+ "STP q0, q1, [%1 , #96]\n\t"
+ : : "r" (src), "r" (dst) :
+ );
+}
+
+static inline void
+rte_mov256(uint8_t *dst, const uint8_t *src)
+{
+ asm volatile("LDP q0, q1, [%0]\n\t"
+ "STP q0, q1, [%1]\n\t"
+ "LDP q0, q1, [%0 , #32]\n\t"
+ "STP q0, q1, [%1 , #32]\n\t"
+ "LDP q0, q1, [%0 , #64]\n\t"
+ "STP q0, q1, [%1 , #64]\n\t"
+ "LDP q0, q1, [%0 , #96]\n\t"
+ "STP q0, q1, [%1 , #96]\n\t"
+ "LDP q0, q1, [%0 , #128]\n\t"
+ "STP q0, q1, [%1 , #128]\n\t"
+ "LDP q0, q1, [%0 , #160]\n\t"
+ "STP q0, q1, [%1 , #160]\n\t"
+ "LDP q0, q1, [%0 , #192]\n\t"
+ "STP q0, q1, [%1 , #192]\n\t"
+ "LDP q0, q1, [%0 , #224]\n\t"
+ "STP q0, q1, [%1 , #224]\n\t"
+ : : "r" (src), "r" (dst) :
+ );
+}
+/*
+static inline void
+ rte_mov16(uint8_t *dst, const uint8_t *src) { memcpy(dst, src, 16); }
+static inline void
+ rte_mov32(uint8_t *dst, const uint8_t *src) { memcpy(dst, src, 32); }
+static inline void
+ rte_mov64(uint8_t *dst, const uint8_t *src) { memcpy(dst, src, 64); }
+static inline void
+ rte_mov128(uint8_t *dst, const uint8_t *src) { memcpy(dst, src, 128); }
+static inline void
+ rte_mov256(uint8_t *dst, const uint8_t *src) { memcpy(dst, src, 256); }
+static inline void
+ rte_mov48(uint8_t *dst, const uint8_t *src) { memcpy(dst, src, 48); }
+*/
+#define rte_memcpy(dst, src, n) \
+ ({ (__builtin_constant_p(n)) ? \
+ memcpy((dst), (src), (n)) : \
+ rte_memcpy_func((dst), (src), (n)); })
+
+
+static inline void *
+rte_memcpy_func(void *dst, const void *src, size_t n)
+{
+ void *ret = dst;
+
+ /* We can't copy < 16 bytes using XMM registers so do it manually. */
+ if (n < 16) {
+ if (n & 0x01) {
+ *(uint8_t *)dst = *(const uint8_t *)src;
+ dst = (uint8_t *)dst + 1;
+ src = (const uint8_t *)src + 1;
+ }
+ if (n & 0x02) {
+ *(uint16_t *)dst = *(const uint16_t *)src;
+ dst = (uint16_t *)dst + 1;
+ src = (const uint16_t *)src + 1;
+ }
+ if (n & 0x04) {
+ *(uint32_t *)dst = *(const uint32_t *)src;
+ dst = (uint32_t *)dst + 1;
+ src = (const uint32_t *)src + 1;
+ }
+ if (n & 0x08)
+ *(uint64_t *)dst = *(const uint64_t *)src;
+ return ret;
+ }
+
+ /* Special fast cases for <= 128 bytes */
+ if (n <= 32) {
+ rte_mov16((uint8_t *)dst, (const uint8_t *)src);
+ rte_mov16((uint8_t *)dst - 16 + n,
+ (const uint8_t *)src - 16 + n);
+ return ret;
+ }
+
+ if (n <= 64) {
+ rte_mov32((uint8_t *)dst, (const uint8_t *)src);
+ rte_mov32((uint8_t *)dst - 32 + n,
+ (const uint8_t *)src - 32 + n);
+ return ret;
+ }
+
+ if (n <= 128) {
+ rte_mov64((uint8_t *)dst, (const uint8_t *)src);
+ rte_mov64((uint8_t *)dst - 64 + n,
+ (const uint8_t *)src - 64 + n);
+ return ret;
+ }
+
+ /*
+ * For large copies > 128 bytes. This combination of 256, 64 and 16 byte
+ * copies was found to be faster than doing 128 and 32 byte copies as
+ * well.
+ */
+ for ( ; n >= 256; n -= 256) {
+ rte_mov256((uint8_t *)dst, (const uint8_t *)src);
+ dst = (uint8_t *)dst + 256;
+ src = (const uint8_t *)src + 256;
+ }
+
+ /*
+ * We split the remaining bytes (which will be less than 256) into
+ * 64byte (2^6) chunks.
+ * Using incrementing integers in the case labels of a switch statement
+ * enourages the compiler to use a jump table. To get incrementing
+ * integers, we shift the 2 relevant bits to the LSB position to first
+ * get decrementing integers, and then subtract.
+ */
+ switch (3 - (n >> 6)) {
+ case 0x00:
+ rte_mov64((uint8_t *)dst, (const uint8_t *)src);
+ n -= 64;
+ dst = (uint8_t *)dst + 64;
+ src = (const uint8_t *)src + 64; /* fallthrough */
+ case 0x01:
+ rte_mov64((uint8_t *)dst, (const uint8_t *)src);
+ n -= 64;
+ dst = (uint8_t *)dst + 64;
+ src = (const uint8_t *)src + 64; /* fallthrough */
+ case 0x02:
+ rte_mov64((uint8_t *)dst, (const uint8_t *)src);
+ n -= 64;
+ dst = (uint8_t *)dst + 64;
+ src = (const uint8_t *)src + 64; /* fallthrough */
+ default:
+ break;
+ }
+
+ /*
+ * We split the remaining bytes (which will be less than 64) into
+ * 16byte (2^4) chunks, using the same switch structure as above.
+ */
+ switch (3 - (n >> 4)) {
+ case 0x00:
+ rte_mov16((uint8_t *)dst, (const uint8_t *)src);
+ n -= 16;
+ dst = (uint8_t *)dst + 16;
+ src = (const uint8_t *)src + 16; /* fallthrough */
+ case 0x01:
+ rte_mov16((uint8_t *)dst, (const uint8_t *)src);
+ n -= 16;
+ dst = (uint8_t *)dst + 16;
+ src = (const uint8_t *)src + 16; /* fallthrough */
+ case 0x02:
+ rte_mov16((uint8_t *)dst, (const uint8_t *)src);
+ n -= 16;
+ dst = (uint8_t *)dst + 16;
+ src = (const uint8_t *)src + 16; /* fallthrough */
+ default:
+ break;
+ }
+
+ /* Copy any remaining bytes, without going beyond end of buffers */
+ if (n != 0)
+ rte_mov16((uint8_t *)dst - 16 + n,
+ (const uint8_t *)src - 16 + n);
+ return ret;
+}
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _RTE_MEMCPY_ARM_64_H_ */
--
2.1.4
next prev parent reply other threads:[~2015-10-23 14:17 UTC|newest]
Thread overview: 19+ messages / expand[flat|nested] mbox.gz Atom feed top
2015-10-23 14:17 [dpdk-dev] [PATCH 00/11] add armv8 architecture support David Hunt
2015-10-23 14:17 ` [dpdk-dev] [PATCH 01/11] lib: add armv8 rte_atomic.h David Hunt
2015-10-23 14:17 ` [dpdk-dev] [PATCH 02/11] lib: add armv8 rte_byteorder.h David Hunt
2015-10-23 14:17 ` [dpdk-dev] [PATCH 03/11] lib: add armv8 rte_cpuflags.h David Hunt
2015-10-26 16:23 ` Jan Viktorin
2015-10-23 14:17 ` [dpdk-dev] [PATCH 04/11] lib: add armv8 rte_cycles.h David Hunt
2015-10-23 14:17 ` David Hunt [this message]
2015-10-26 16:22 ` [dpdk-dev] [PATCH 05/11] lib: add armv8 rte_memcpy.h Jan Viktorin
2015-10-23 14:17 ` [dpdk-dev] [PATCH 06/11] lib: add armv8 rte_prefetch.h David Hunt
2015-10-23 14:17 ` [dpdk-dev] [PATCH 07/11] lib: add armv8 rte_rwlock.h David Hunt
2015-10-23 14:17 ` [dpdk-dev] [PATCH 08/11] lib: add armv8 rte_spinlock.h David Hunt
2015-10-23 14:17 ` [dpdk-dev] [PATCH 09/11] lib: add armv8 rte_vect.h David Hunt
2015-10-26 16:23 ` Jan Viktorin
2015-10-23 14:17 ` [dpdk-dev] [PATCH 10/11] mk: add makefile and config changes for armv8 architecture David Hunt
2015-10-26 16:22 ` Jan Viktorin
2015-10-27 18:24 ` Jan Viktorin
2015-10-26 16:22 ` Jan Viktorin
2015-10-23 14:17 ` [dpdk-dev] [PATCH 11/11] app: add armv8 cpuflags check to test_cpuflags application David Hunt
2015-10-26 16:21 ` [dpdk-dev] [PATCH 00/11] add armv8 architecture support Jan Viktorin
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=1445609833-17649-6-git-send-email-david.hunt@intel.com \
--to=david.hunt@intel.com \
--cc=Ben.Boren@intel.com \
--cc=dev@dpdk.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).