Add the rt linux 4.1.3-rt3 as base
[kvmfornfv.git] / kernel / arch / tile / lib / memmove.c
diff --git a/kernel/arch/tile/lib/memmove.c b/kernel/arch/tile/lib/memmove.c
new file mode 100644 (file)
index 0000000..fd615ae
--- /dev/null
@@ -0,0 +1,63 @@
+/*
+ * Copyright 2010 Tilera Corporation. All Rights Reserved.
+ *
+ *   This program is free software; you can redistribute it and/or
+ *   modify it under the terms of the GNU General Public License
+ *   as published by the Free Software Foundation, version 2.
+ *
+ *   This program is distributed in the hope that it will be useful, but
+ *   WITHOUT ANY WARRANTY; without even the implied warranty of
+ *   MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
+ *   NON INFRINGEMENT.  See the GNU General Public License for
+ *   more details.
+ */
+
+#include <linux/types.h>
+#include <linux/string.h>
+#include <linux/module.h>
+
+void *memmove(void *dest, const void *src, size_t n)
+{
+       if ((const char *)src >= (char *)dest + n
+           || (char *)dest >= (const char *)src + n) {
+               /* We found no overlap, so let memcpy do all the heavy
+                * lifting (prefetching, etc.)
+                */
+               return memcpy(dest, src, n);
+       }
+
+       if (n != 0) {
+               const uint8_t *in;
+               uint8_t x;
+               uint8_t *out;
+               int stride;
+
+               if (src < dest) {
+                       /* copy backwards */
+                       in = (const uint8_t *)src + n - 1;
+                       out = (uint8_t *)dest + n - 1;
+                       stride = -1;
+               } else {
+                       /* copy forwards */
+                       in = (const uint8_t *)src;
+                       out = (uint8_t *)dest;
+                       stride = 1;
+               }
+
+               /* Manually software-pipeline this loop. */
+               x = *in;
+               in += stride;
+
+               while (--n != 0) {
+                       *out = x;
+                       out += stride;
+                       x = *in;
+                       in += stride;
+               }
+
+               *out = x;
+       }
+
+       return dest;
+}
+EXPORT_SYMBOL(memmove);