aboutsummaryrefslogtreecommitdiff
path: root/arch/x86/lib/memmove_64.S
diff options
context:
space:
mode:
Diffstat (limited to 'arch/x86/lib/memmove_64.S')
-rw-r--r--arch/x86/lib/memmove_64.S34
1 files changed, 30 insertions, 4 deletions
diff --git a/arch/x86/lib/memmove_64.S b/arch/x86/lib/memmove_64.S
index 0ecb8433e5a..65268a6104f 100644
--- a/arch/x86/lib/memmove_64.S
+++ b/arch/x86/lib/memmove_64.S
@@ -8,6 +8,8 @@
#define _STRING_C
#include <linux/linkage.h>
#include <asm/dwarf2.h>
+#include <asm/cpufeature.h>
+#include <asm/alternative-asm.h>
#undef memmove
@@ -24,15 +26,21 @@
*/
ENTRY(memmove)
CFI_STARTPROC
- /* Handle more 32bytes in loop */
+
+ /* Handle more 32 bytes in loop */
mov %rdi, %rax
cmp $0x20, %rdx
jb 1f
/* Decide forward/backward copy mode */
cmp %rdi, %rsi
- jb 2f
+ jge .Lmemmove_begin_forward
+ mov %rsi, %r8
+ add %rdx, %r8
+ cmp %rdi, %r8
+ jg 2f
+.Lmemmove_begin_forward:
/*
* movsq instruction have many startup latency
* so we handle small size by general register.
@@ -48,7 +56,7 @@ ENTRY(memmove)
3:
sub $0x20, %rdx
/*
- * We gobble 32byts forward in each loop.
+ * We gobble 32 bytes forward in each loop.
*/
5:
sub $0x20, %rdx
@@ -78,6 +86,8 @@ ENTRY(memmove)
rep movsq
movq %r11, (%r10)
jmp 13f
+.Lmemmove_end_forward:
+
/*
* Handle data backward by movsq.
*/
@@ -112,7 +122,7 @@ ENTRY(memmove)
addq %rdx, %rdi
subq $0x20, %rdx
/*
- * We gobble 32byts backward in each loop.
+ * We gobble 32 bytes backward in each loop.
*/
8:
subq $0x20, %rdx
@@ -194,4 +204,20 @@ ENTRY(memmove)
13:
retq
CFI_ENDPROC
+
+ .section .altinstr_replacement,"ax"
+.Lmemmove_begin_forward_efs:
+ /* Forward moving data. */
+ movq %rdx, %rcx
+ rep movsb
+ retq
+.Lmemmove_end_forward_efs:
+ .previous
+
+ .section .altinstructions,"a"
+ altinstruction_entry .Lmemmove_begin_forward, \
+ .Lmemmove_begin_forward_efs,X86_FEATURE_ERMS, \
+ .Lmemmove_end_forward-.Lmemmove_begin_forward, \
+ .Lmemmove_end_forward_efs-.Lmemmove_begin_forward_efs
+ .previous
ENDPROC(memmove)