#include <linux/string.h>
#ifdef __HAVE_ARCH_MEMMOVE
+#ifndef CONFIG_OPT_LIB_FUNCTION
void *memmove(void *v_dst, const void *v_src, __kernel_size_t c)
{
const char *src = v_src;
char *dst = v_dst;
-#ifdef CONFIG_OPT_LIB_FUNCTION
- const uint32_t *i_src;
- uint32_t *i_dst;
-#endif
-
if (!c)
return v_dst;
if (v_dst <= v_src)
return memcpy(v_dst, v_src, c);
-#ifndef CONFIG_OPT_LIB_FUNCTION
/* copy backwards, from end to beginning */
src += c;
dst += c;
*--dst = *--src;
return v_dst;
-#else
+}
+#else /* CONFIG_OPT_LIB_FUNCTION */
+void *memmove(void *v_dst, const void *v_src, __kernel_size_t c)
+{
+ const char *src = v_src;
+ char *dst = v_dst;
+ const uint32_t *i_src;
+ uint32_t *i_dst;
+
+ if (!c)
+ return v_dst;
+
+ /* Use memcpy when source is higher than dest */
+ if (v_dst <= v_src)
+ return memcpy(v_dst, v_src, c);
+
/* The following code tries to optimize the copy by using unsigned
* alignment. This will work fine if both source and destination are
* aligned on the same boundary. However, if they are aligned on
case 0x1: /* Unaligned - Off by 1 */
/* Word align the source */
i_src = (const void *) (((unsigned)src + 4) & ~3);
-
+#ifndef __MICROBLAZEEL__
/* Load the holding buffer */
buf_hold = *--i_src >> 24;
*--i_dst = buf_hold << 8 | value;
buf_hold = value >> 24;
}
+#else
+ /* Load the holding buffer */
+ buf_hold = (*--i_src & 0xFF) << 24;
+ for (; c >= 4; c -= 4) {
+ value = *--i_src;
+ *--i_dst = buf_hold | ((value & 0xFFFFFF00)>>8);
+ buf_hold = (value & 0xFF) << 24;
+ }
+#endif
/* Realign the source */
src = (const void *)i_src;
src += 1;
case 0x2: /* Unaligned - Off by 2 */
/* Word align the source */
i_src = (const void *) (((unsigned)src + 4) & ~3);
-
+#ifndef __MICROBLAZEEL__
/* Load the holding buffer */
buf_hold = *--i_src >> 16;
*--i_dst = buf_hold << 16 | value;
buf_hold = value >> 16;
}
+#else
+ /* Load the holding buffer */
+ buf_hold = (*--i_src & 0xFFFF) << 16;
+ for (; c >= 4; c -= 4) {
+ value = *--i_src;
+ *--i_dst = buf_hold | ((value & 0xFFFF0000)>>16);
+ buf_hold = (value & 0xFFFF) << 16;
+ }
+#endif
/* Realign the source */
src = (const void *)i_src;
src += 2;
case 0x3: /* Unaligned - Off by 3 */
/* Word align the source */
i_src = (const void *) (((unsigned)src + 4) & ~3);
-
+#ifndef __MICROBLAZEEL__
/* Load the holding buffer */
buf_hold = *--i_src >> 8;
*--i_dst = buf_hold << 24 | value;
buf_hold = value >> 8;
}
+#else
+ /* Load the holding buffer */
+ buf_hold = (*--i_src & 0xFFFFFF) << 8;
+ for (; c >= 4; c -= 4) {
+ value = *--i_src;
+ *--i_dst = buf_hold | ((value & 0xFF000000)>> 24);
+ buf_hold = (value & 0xFFFFFF) << 8;;
+ }
+#endif
/* Realign the source */
src = (const void *)i_src;
src += 3;
*--dst = *--src;
}
return v_dst;
-#endif
}
+#endif /* CONFIG_OPT_LIB_FUNCTION */
EXPORT_SYMBOL(memmove);
#endif /* __HAVE_ARCH_MEMMOVE */