SPM: Restructure memory operation functions

SPM calls spm_memcpy/spm_memset, and SP just calls memset, memcpy,
memmove and memcmp. SPM has its own header files for
spm_memcpy/spm_memset prototypes, while SP relies on toolchain headers
string.h for prototypes.
As -fno-builtin is applied, our memcpy would replace the same function
in toolchain library.

Change-Id: Iab240c96e06d55144daa0125b2d17574b648f9e1
Signed-off-by: Summer Qin <summer.qin@arm.com>
diff --git a/secure_fw/partitions/lib/sprt/crt_memmove.c b/secure_fw/partitions/lib/sprt/crt_memmove.c
new file mode 100644
index 0000000..b24a39d
--- /dev/null
+++ b/secure_fw/partitions/lib/sprt/crt_memmove.c
@@ -0,0 +1,66 @@
+/*
+ * Copyright (c) 2019-2020, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+#include <string.h>
+#include "crt_impl_private.h"
+
+static void *memcpy_r(void *dest, const void *src, size_t n)
+{
+    union tfm_mem_addr_t p_dest, p_src;
+
+    p_dest.uint_addr = (uintptr_t)dest + n;
+    p_src.uint_addr = (uintptr_t)src + n;
+
+    /* Byte copy for unaligned address. check the last bit of address. */
+    while (n && (GET_MEM_ADDR_BIT0(p_dest.uint_addr) ||
+           GET_MEM_ADDR_BIT0(p_src.uint_addr))) {
+        *(--p_dest.p_byte) = *(--p_src.p_byte);
+        n--;
+    }
+
+    /* Double byte copy for aligned address.
+     * Check the 2nd last bit of address.
+     */
+    while (n >= sizeof(uint16_t) && (GET_MEM_ADDR_BIT1(p_dest.uint_addr) ||
+           GET_MEM_ADDR_BIT1(p_src.uint_addr))) {
+        *(--p_dest.p_dbyte) = *(--p_src.p_dbyte);
+        n -= sizeof(uint16_t);
+    }
+
+    /* Quad byte copy for aligned address. */
+    while (n >= sizeof(uint32_t)) {
+        *(--p_dest.p_qbyte) = *(--p_src.p_qbyte);
+        n -= sizeof(uint32_t);
+    }
+
+    /* Byte copy for the remaining bytes. */
+    while (n--) {
+        *(--p_dest.p_byte) = *(--p_src.p_byte);
+    }
+
+    return dest;
+}
+
+/*
+ * For overlapped memory area:
+ * 1) overlapped: use reverse memory move.
+ * 2) non-overlapped: use forward memory move.
+ */
+void *memmove(void *dest, const void *src, size_t n)
+{
+    /*
+     * FixMe: Add a "assert (dest == NULL || src == NULL)" here
+     * after "assert()" for sprtl is implemented.
+     */
+    if (src >= dest) {
+        memcpy(dest, src, n);
+    } else {
+        memcpy_r(dest, src, n);
+    }
+
+    return dest;
+}