summaryrefslogtreecommitdiffstats
path: root/c/src/lib/libcpu/powerpc/mpc55xx/misc/copy.S
diff options
context:
space:
mode:
Diffstat (limited to 'c/src/lib/libcpu/powerpc/mpc55xx/misc/copy.S')
-rw-r--r--c/src/lib/libcpu/powerpc/mpc55xx/misc/copy.S150
1 files changed, 150 insertions, 0 deletions
diff --git a/c/src/lib/libcpu/powerpc/mpc55xx/misc/copy.S b/c/src/lib/libcpu/powerpc/mpc55xx/misc/copy.S
new file mode 100644
index 0000000000..ef529d6e4b
--- /dev/null
+++ b/c/src/lib/libcpu/powerpc/mpc55xx/misc/copy.S
@@ -0,0 +1,150 @@
+/**
+ * @file
+ *
+ * @ingroup mpc55xx_asm
+ *
+ * @brief Memory copy and zero functions.
+ */
+
+/*
+ * Copyright (c) 2008
+ * Embedded Brains GmbH
+ * Obere Lagerstr. 30
+ * D-82178 Puchheim
+ * Germany
+ * rtems@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.com/license/LICENSE.
+ */
+
+#include <libcpu/powerpc-utility.h>
+
+.section ".text"
+
+/**
+ * @fn int mpc55xx_copy_8( const void *src, void *dest, size_t n)
+ *
+ * @brief Copy @a n bytes from @a src to @a dest with 8 byte reads and writes.
+ *
+ * The memory areas should not overlap. The addresses @a src and @a dest have
+ * to be aligned on 8 byte boundaries. The size @a n must be evenly divisible by 8.
+ * The SPE operations @b evxor, @b evlddx and @b evstddx will be used.
+ */
+GLOBAL_FUNCTION mpc55xx_copy_8
+ /* Loop counter = data size / 8 */
+ srwi. r5, r5, 3
+ beqlr
+ mtctr r5
+
+ /* Set offset */
+ evxor r5, r5, r5
+
+copy_data:
+ evlddx r6, r3, r5
+ evstddx r6, r4, r5
+ addi r5, r5, 8
+ bdnz copy_data
+
+ /* Return */
+ blr
+
+/**
+ * @fn int mpc55xx_zero_8( void *dest, size_t n)
+ *
+ * @brief Zero all @a n bytes starting at @a dest with 8 byte writes.
+ *
+ * The address @a dest has to be aligned on 8 byte boundaries. The size @a n
+ * must be evenly divisible by 8. The SPE operations @b evxor and @b evstddx will be used.
+ */
+GLOBAL_FUNCTION mpc55xx_zero_8
+ /* Create zero */
+ evxor r0, r0, r0
+
+ /* Set offset */
+ evxor r5, r5, r5
+
+ /* Loop counter for the first bytes up to 32 bytes */
+ rlwinm. r9, r4, 29, 30, 31
+ beq zero_more
+ mtctr r9
+
+zero_data:
+ evstddx r0, r3, r5
+ addi r5, r5, 8
+ bdnz zero_data
+
+zero_more:
+ /* More than 32 bytes? */
+ srwi. r9, r4, 5
+ beqlr
+ mtctr r9
+
+ /* Set offsets */
+ addi r6, r5, 8
+ addi r7, r5, 16
+ addi r8, r5, 24
+
+zero_big_data:
+ evstddx r0, r3, r5
+ addi r5, r5, 32
+ evstddx r0, r3, r6
+ addi r6, r6, 32
+ evstddx r0, r3, r7
+ addi r7, r7, 32
+ evstddx r0, r3, r8
+ addi r8, r8, 32
+ bdnz zero_big_data
+
+ /* Return */
+ blr
+
+/**
+ * @fn int mpc55xx_zero_32( void *dest, size_t n)
+ *
+ * @brief Zero all @a n bytes starting at @a dest with 32 byte writes.
+ *
+ * The address @a dest has to be aligned on 32 byte boundaries. The size @a n
+ * must be evenly divisible by 32. The function operates with the cache block zero
+ * operation @b dcbz.
+ *
+ * @note The cache has to be enabled for the desired memory area.
+ */
+GLOBAL_FUNCTION mpc55xx_zero_32
+ /* Set offset */
+ xor r5, r5, r5
+
+ /* Loop counter for the first bytes up to 128 bytes */
+ rlwinm. r9, r4, 27, 28, 31
+ beq zero_more_lines
+ mtctr r9
+
+zero_line:
+ dcbz r3, r5
+ addi r5, r5, 32
+ bdnz zero_line
+
+zero_more_lines:
+ /* More than 128 bytes? */
+ srwi. r9, r4, 7
+ beqlr
+ mtctr r9
+
+ /* Set offsets */
+ addi r6, r5, 32
+ addi r7, r5, 64
+ addi r8, r5, 96
+
+zero_big_line:
+ dcbz r3, r5
+ addi r5, r5, 128
+ dcbz r3, r6
+ addi r6, r6, 128
+ dcbz r3, r7
+ addi r7, r7, 128
+ dcbz r3, r8
+ addi r8, r8, 128
+ bdnz zero_big_line
+
+ /* Return */
+ blr