summaryrefslogtreecommitdiffstats
path: root/bsps
diff options
context:
space:
mode:
authorSebastian Huber <sebastian.huber@embedded-brains.de>2018-04-24 07:19:46 +0200
committerSebastian Huber <sebastian.huber@embedded-brains.de>2018-04-24 10:24:23 +0200
commitb8777d93ced8f9f53bff85fdd25950e9eee42fae (patch)
tree8abe0e4e713db26583a1608d6da5f5e507f351a3 /bsps
parentbsps: Move tictac.c to bsps (diff)
downloadrtems-b8777d93ced8f9f53bff85fdd25950e9eee42fae.tar.bz2
bsps: Move memcpy.c to bsps
This patch is a part of the BSP source reorganization. Update #3285.
Diffstat (limited to 'bsps')
-rw-r--r--bsps/powerpc/shared/start/memcpy.c126
1 files changed, 126 insertions, 0 deletions
diff --git a/bsps/powerpc/shared/start/memcpy.c b/bsps/powerpc/shared/start/memcpy.c
new file mode 100644
index 0000000000..23153858aa
--- /dev/null
+++ b/bsps/powerpc/shared/start/memcpy.c
@@ -0,0 +1,126 @@
+/*
+ * Copyright (c) 2011 embedded brains GmbH. All rights reserved.
+ *
+ * embedded brains GmbH
+ * Obere Lagerstr. 30
+ * 82178 Puchheim
+ * Germany
+ * <info@embedded-brains.de>
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.org/license/LICENSE.
+ */
+
+#include <bspopts.h>
+#include <rtems/powerpc/powerpc.h>
+
+#if BSP_DATA_CACHE_ENABLED \
+ && PPC_CACHE_ALIGNMENT == 32 \
+ && !defined(BSP_DATA_CACHE_USE_WRITE_THROUGH)
+
+#include <string.h>
+#include <stdint.h>
+#include <stdbool.h>
+
+#include <libcpu/powerpc-utility.h>
+
+#define WORD_SIZE 4
+
+#define WORD_MASK (WORD_SIZE - 1)
+
+static bool aligned(const void *a, const void *b)
+{
+ return ((((uintptr_t) a) | ((uintptr_t) b)) & WORD_MASK) == 0;
+}
+
+void *memcpy(void *dst_ptr, const void *src_ptr, size_t n)
+{
+ uint8_t *dst = dst_ptr;
+ const uint8_t *src = src_ptr;
+
+ ppc_data_cache_block_touch(src);
+
+ if (__builtin_expect(n >= WORD_SIZE && aligned(src, dst), 1)) {
+ uint32_t *word_dst = (uint32_t *) dst - 1;
+ const uint32_t *word_src = (const uint32_t *) src - 1;
+
+ if (n >= 2 * PPC_CACHE_ALIGNMENT - WORD_SIZE) {
+ while ((uintptr_t) (word_dst + 1) % PPC_CACHE_ALIGNMENT != 0) {
+ uint32_t tmp;
+ __asm__ volatile (
+ "lwzu %[tmp], 0x4(%[src])\n"
+ "stwu %[tmp], 0x4(%[dst])\n"
+ : [src] "+b" (word_src),
+ [dst] "+b" (word_dst),
+ [tmp] "=&r" (tmp)
+ );
+ n -= WORD_SIZE;
+ }
+
+ while (n >= PPC_CACHE_ALIGNMENT) {
+ uint32_t dst_offset = 4;
+ uint32_t src_offset = 32 + 4;
+ uint32_t tmp0;
+ uint32_t tmp1;
+ uint32_t tmp2;
+ uint32_t tmp3;
+ __asm__ volatile (
+ "dcbz %[dst], %[dst_offset]\n"
+ "lwz %[tmp0], 0x04(%[src])\n"
+ "dcbt %[src], %[src_offset]\n"
+ "lwz %[tmp1], 0x08(%[src])\n"
+ "lwz %[tmp2], 0x0c(%[src])\n"
+ "lwz %[tmp3], 0x10(%[src])\n"
+ "stw %[tmp0], 0x04(%[dst])\n"
+ "stw %[tmp1], 0x08(%[dst])\n"
+ "stw %[tmp2], 0x0c(%[dst])\n"
+ "stw %[tmp3], 0x10(%[dst])\n"
+ "lwz %[tmp0], 0x14(%[src])\n"
+ "lwz %[tmp1], 0x18(%[src])\n"
+ "lwz %[tmp2], 0x1c(%[src])\n"
+ "lwzu %[tmp3], 0x20(%[src])\n"
+ "stw %[tmp0], 0x14(%[dst])\n"
+ "stw %[tmp1], 0x18(%[dst])\n"
+ "stw %[tmp2], 0x1c(%[dst])\n"
+ "stwu %[tmp3], 0x20(%[dst])\n"
+ : [src] "+b" (word_src),
+ [dst] "+b" (word_dst),
+ [tmp0] "=&r" (tmp0),
+ [tmp1] "=&r" (tmp1),
+ [tmp2] "=&r" (tmp2),
+ [tmp3] "=&r" (tmp3)
+ : [src_offset] "r" (src_offset),
+ [dst_offset] "r" (dst_offset)
+ );
+ n -= PPC_CACHE_ALIGNMENT;
+ }
+ }
+
+ while (n >= WORD_SIZE) {
+ uint32_t tmp;
+ __asm__ volatile (
+ "lwzu %[tmp], 0x4(%[src])\n"
+ "stwu %[tmp], 0x4(%[dst])\n"
+ : [src] "+b" (word_src),
+ [dst] "+b" (word_dst),
+ [tmp] "=&r" (tmp)
+ );
+ n -= WORD_SIZE;
+ }
+
+ dst = (uint8_t *) word_dst + 4;
+ src = (const uint8_t *) word_src + 4;
+ }
+
+ while (n > 0) {
+ *dst = *src;
+ ++src;
+ ++dst;
+ --n;
+ }
+
+ return dst_ptr;
+}
+
+#endif /* BSP_DATA_CACHE_ENABLED && PPC_CACHE_ALIGNMENT == 32 */