Implement memmove in C, dropping the asm implementation which does no particular optimisation & was duplicated needlessly for octeon. Signed-off-by: Paul Burton <paul.burton@xxxxxxxxxx> --- arch/mips/cavium-octeon/octeon-memcpy.S | 50 +---------------------------- arch/mips/lib/Makefile | 1 + arch/mips/lib/memcpy.S | 56 +-------------------------------- arch/mips/lib/memmove.c | 39 +++++++++++++++++++++++ 4 files changed, 42 insertions(+), 104 deletions(-) create mode 100644 arch/mips/lib/memmove.c diff --git a/arch/mips/cavium-octeon/octeon-memcpy.S b/arch/mips/cavium-octeon/octeon-memcpy.S index 7d96d9c..4336316 100644 --- a/arch/mips/cavium-octeon/octeon-memcpy.S +++ b/arch/mips/cavium-octeon/octeon-memcpy.S @@ -3,7 +3,7 @@ * License. See the file "COPYING" in the main directory of this archive * for more details. * - * Unified implementation of memcpy, memmove and the __copy_user backend. + * Unified implementation of memcpy and the __copy_user backend. * * Copyright (C) 1998, 99, 2000, 01, 2002 Ralf Baechle (ralf@xxxxxxx) * Copyright (C) 1999, 2000, 01, 2002 Silicon Graphics, Inc. @@ -66,9 +66,6 @@ * * The exception handlers for stores adjust len (if necessary) and return. * These handlers do not need to overwrite any data. - * - * For __rmemcpy and memmove an exception is always a kernel bug, therefore - * they're not protected. */ #define EXC(inst_reg,addr,handler) \ @@ -460,48 +457,3 @@ s_exc_p1: s_exc: jr ra nop - - .align 5 -LEAF(memmove) -EXPORT_SYMBOL(memmove) - ADD t0, a0, a2 - ADD t1, a1, a2 - sltu t0, a1, t0 # dst + len <= src -> memcpy - sltu t1, a0, t1 # dst >= src + len -> memcpy - and t0, t1 - beqz t0, __memcpy - move v0, a0 /* return value */ - beqz a2, r_out - END(memmove) - - /* fall through to __rmemcpy */ -LEAF(__rmemcpy) /* a0=dst a1=src a2=len */ - sltu t0, a1, a0 - beqz t0, r_end_bytes_up # src >= dst - nop - ADD a0, a2 # dst = dst + len - ADD a1, a2 # src = src + len - -r_end_bytes: - lb t0, -1(a1) - SUB a2, a2, 0x1 - sb t0, -1(a0) - SUB a1, a1, 0x1 - bnez a2, r_end_bytes - SUB a0, a0, 0x1 - -r_out: - jr ra - move a2, zero - -r_end_bytes_up: - lb t0, (a1) - SUB a2, a2, 0x1 - sb t0, (a0) - ADD a1, a1, 0x1 - bnez a2, r_end_bytes_up - ADD a0, a0, 0x1 - - jr ra - move a2, zero - END(__rmemcpy) diff --git a/arch/mips/lib/Makefile b/arch/mips/lib/Makefile index c0f0d1d..0040bad 100644 --- a/arch/mips/lib/Makefile +++ b/arch/mips/lib/Makefile @@ -6,6 +6,7 @@ lib-y += bitops.o lib-y += csum_partial.o lib-y += delay.o lib-y += memcpy.o +lib-y += memmove.o lib-y += memset.o lib-y += mips-atomic.o lib-y += strlen_user.o diff --git a/arch/mips/lib/memcpy.S b/arch/mips/lib/memcpy.S index c3031f1..b8d34d9 100644 --- a/arch/mips/lib/memcpy.S +++ b/arch/mips/lib/memcpy.S @@ -3,7 +3,7 @@ * License. See the file "COPYING" in the main directory of this archive * for more details. * - * Unified implementation of memcpy, memmove and the __copy_user backend. + * Unified implementation of memcpy and the __copy_user backend. * * Copyright (C) 1998, 99, 2000, 01, 2002 Ralf Baechle (ralf@xxxxxxx) * Copyright (C) 1999, 2000, 01, 2002 Silicon Graphics, Inc. @@ -82,9 +82,6 @@ * * The exception handlers for stores adjust len (if necessary) and return. * These handlers do not need to overwrite any data. - * - * For __rmemcpy and memmove an exception is always a kernel bug, therefore - * they're not protected. */ /* Instruction type */ @@ -621,57 +618,6 @@ SEXC(1) nop .endm - .align 5 -LEAF(memmove) -EXPORT_SYMBOL(memmove) - ADD t0, a0, a2 - ADD t1, a1, a2 - sltu t0, a1, t0 # dst + len <= src -> memcpy - sltu t1, a0, t1 # dst >= src + len -> memcpy - and t0, t1 - beqz t0, .L__memcpy - move v0, a0 /* return value */ - beqz a2, .Lr_out - END(memmove) - - /* fall through to __rmemcpy */ -LEAF(__rmemcpy) /* a0=dst a1=src a2=len */ - sltu t0, a1, a0 - beqz t0, .Lr_end_bytes_up # src >= dst - nop - ADD a0, a2 # dst = dst + len - ADD a1, a2 # src = src + len - -.Lr_end_bytes: - R10KCBARRIER(0(ra)) - lb t0, -1(a1) - SUB a2, a2, 0x1 - sb t0, -1(a0) - SUB a1, a1, 0x1 - .set reorder /* DADDI_WAR */ - SUB a0, a0, 0x1 - bnez a2, .Lr_end_bytes - .set noreorder - -.Lr_out: - jr ra - move a2, zero - -.Lr_end_bytes_up: - R10KCBARRIER(0(ra)) - lb t0, (a1) - SUB a2, a2, 0x1 - sb t0, (a0) - ADD a1, a1, 0x1 - .set reorder /* DADDI_WAR */ - ADD a0, a0, 0x1 - bnez a2, .Lr_end_bytes_up - .set noreorder - - jr ra - move a2, zero - END(__rmemcpy) - /* * t6 is used as a flag to note inatomic mode. */ diff --git a/arch/mips/lib/memmove.c b/arch/mips/lib/memmove.c new file mode 100644 index 0000000..4e902c6 --- /dev/null +++ b/arch/mips/lib/memmove.c @@ -0,0 +1,39 @@ +/* + * Copyright (C) 2016 Imagination Technologies + * Author: Paul Burton <paul.burton@xxxxxxxxxx> + * + * 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; either version 2 of the License, or (at your + * option) any later version. + */ + +#include <linux/export.h> +#include <linux/string.h> + +extern void *memmove(void *dest, const void *src, size_t count) +{ + const char *s = src; + const char *s_end = s + count; + char *d = dest; + char *d_end = dest + count; + + /* Use optimised memcpy when there's no overlap */ + if ((d_end <= s) || (s_end <= d)) + return memcpy(dest, src, count); + + if (d <= s) { + /* Incrementing copy loop */ + while (count--) + *d++ = *s++; + } else { + /* Decrementing copy loop */ + d = d_end; + s = s_end; + while (count--) + *--d = *--s; + } + + return dest; +} +EXPORT_SYMBOL(memmove); -- 2.10.2