Convert memcpy() from assembler to C, which should make it easier to
read and change, if required. And it allows the compiler to optimize
the code, and use different instructions, except for the used inline
assemblies.
Reviewed-by: Juergen Christ <jchrist@linux.ibm.com>
Signed-off-by: Heiko Carstens <hca@linux.ibm.com>
Signed-off-by: Alexander Gordeev <agordeev@linux.ibm.com>
GEN_BR_THUNK %r14
-/*
- * memcpy implementation
- *
- * void *memcpy(void *dest, const void *src, size_t n)
- */
-SYM_FUNC_START(__memcpy)
- ltgr %r4,%r4
- jz .Lmemcpy_exit
- aghi %r4,-1
- srlg %r5,%r4,8
- ltgr %r5,%r5
- lgr %r1,%r2
- jnz .Lmemcpy_loop
-.Lmemcpy_remainder:
- exrl %r4,.Lmemcpy_mvc
-.Lmemcpy_exit:
- BR_EX %r14
-.Lmemcpy_loop:
- mvc 0(256,%r1),0(%r3)
- la %r1,256(%r1)
- la %r3,256(%r3)
- brctg %r5,.Lmemcpy_loop
- j .Lmemcpy_remainder
-.Lmemcpy_mvc:
- mvc 0(1,%r1),0(%r3)
-SYM_FUNC_END(__memcpy)
-EXPORT_SYMBOL(__memcpy)
-
-SYM_FUNC_ALIAS(memcpy, __memcpy)
-EXPORT_SYMBOL(memcpy)
-
/*
* __memset16/32/64
*
EXPORT_SYMBOL(memset);
#endif
+#ifdef __HAVE_ARCH_MEMCPY
+noinstr void *__memcpy(void *dest, const void *src, size_t n)
+{
+ void *d = dest;
+
+ if (!n)
+ return d;
+ while (n >= 256) {
+ asm volatile(
+ " mvc 0(256,%[dest]),0(%[src])"
+ :
+ : [dest] "a" (dest), [src] "a" (src)
+ : "memory");
+ dest += 256;
+ src += 256;
+ n -= 256;
+ }
+ if (!n)
+ return d;
+ asm volatile(
+ " exrl %[n],1f\n"
+ " j 2f\n"
+ "1: mvc 0(1,%[dest]),0(%[src])\n"
+ "2:"
+ :
+ : [dest] "a" (dest), [src] "a" (src), [n] "a" (n - 1)
+ : "memory");
+ return d;
+}
+SYMBOL_FUNCTION_ALIAS(memcpy, __memcpy);
+EXPORT_SYMBOL(__memcpy);
+EXPORT_SYMBOL(memcpy);
+#endif
+
/*
* Helper functions to find the end of a string
*/