diff options
Diffstat (limited to 'arch/x86/lib')
-rw-r--r-- | arch/x86/lib/memcpy_32.c | 38 | ||||
-rw-r--r-- | arch/x86/lib/memmove_64.c | 46 |
2 files changed, 68 insertions, 16 deletions
diff --git a/arch/x86/lib/memcpy_32.c b/arch/x86/lib/memcpy_32.c index 5415a9d06f53..be424dfcf365 100644 --- a/arch/x86/lib/memcpy_32.c +++ b/arch/x86/lib/memcpy_32.c | |||
@@ -25,19 +25,35 @@ void *memmove(void *dest, const void *src, size_t n) | |||
25 | int d0, d1, d2; | 25 | int d0, d1, d2; |
26 | 26 | ||
27 | if (dest < src) { | 27 | if (dest < src) { |
28 | memcpy(dest, src, n); | 28 | if ((dest + n) < src) |
29 | return memcpy(dest, src, n); | ||
30 | else | ||
31 | __asm__ __volatile__( | ||
32 | "rep\n\t" | ||
33 | "movsb\n\t" | ||
34 | : "=&c" (d0), "=&S" (d1), "=&D" (d2) | ||
35 | :"0" (n), | ||
36 | "1" (src), | ||
37 | "2" (dest) | ||
38 | :"memory"); | ||
39 | |||
29 | } else { | 40 | } else { |
30 | __asm__ __volatile__( | 41 | |
31 | "std\n\t" | 42 | if((src + count) < dest) |
32 | "rep\n\t" | 43 | return memcpy(dest, src, count); |
33 | "movsb\n\t" | 44 | else |
34 | "cld" | 45 | __asm__ __volatile__( |
35 | : "=&c" (d0), "=&S" (d1), "=&D" (d2) | 46 | "std\n\t" |
36 | :"0" (n), | 47 | "rep\n\t" |
37 | "1" (n-1+src), | 48 | "movsb\n\t" |
38 | "2" (n-1+dest) | 49 | "cld" |
39 | :"memory"); | 50 | : "=&c" (d0), "=&S" (d1), "=&D" (d2) |
51 | :"0" (n), | ||
52 | "1" (n-1+src), | ||
53 | "2" (n-1+dest) | ||
54 | :"memory"); | ||
40 | } | 55 | } |
56 | |||
41 | return dest; | 57 | return dest; |
42 | } | 58 | } |
43 | EXPORT_SYMBOL(memmove); | 59 | EXPORT_SYMBOL(memmove); |
diff --git a/arch/x86/lib/memmove_64.c b/arch/x86/lib/memmove_64.c index 0a33909bf122..ecacc4b3d9e5 100644 --- a/arch/x86/lib/memmove_64.c +++ b/arch/x86/lib/memmove_64.c | |||
@@ -8,13 +8,49 @@ | |||
8 | #undef memmove | 8 | #undef memmove |
9 | void *memmove(void *dest, const void *src, size_t count) | 9 | void *memmove(void *dest, const void *src, size_t count) |
10 | { | 10 | { |
11 | unsigned long d0, d1, d2, d3; | ||
11 | if (dest < src) { | 12 | if (dest < src) { |
12 | return memcpy(dest, src, count); | 13 | if ((dest + count) < src) |
14 | return memcpy(dest, src, count); | ||
15 | else | ||
16 | __asm__ __volatile__( | ||
17 | "movq %0, %3\n\t" | ||
18 | "shr $3, %0\n\t" | ||
19 | "andq $7, %3\n\t" | ||
20 | "rep\n\t" | ||
21 | "movsq\n\t" | ||
22 | "movq %3, %0\n\t" | ||
23 | "rep\n\t" | ||
24 | "movsb" | ||
25 | : "=&c" (d0), "=&S" (d1), "=&D" (d2), "=r" (d3) | ||
26 | :"0" (count), | ||
27 | "1" (src), | ||
28 | "2" (dest) | ||
29 | :"memory"); | ||
13 | } else { | 30 | } else { |
14 | char *p = dest + count; | 31 | if((src + count) < dest) |
15 | const char *s = src + count; | 32 | return memcpy(dest, src, count); |
16 | while (count--) | 33 | else |
17 | *--p = *--s; | 34 | __asm__ __volatile__( |
35 | "movq %0, %3\n\t" | ||
36 | "lea -8(%1, %0), %1\n\t" | ||
37 | "lea -8(%2, %0), %2\n\t" | ||
38 | "shr $3, %0\n\t" | ||
39 | "andq $7, %3\n\t" | ||
40 | "std\n\t" | ||
41 | "rep\n\t" | ||
42 | "movsq\n\t" | ||
43 | "lea 7(%1), %1\n\t" | ||
44 | "lea 7(%2), %2\n\t" | ||
45 | "movq %3, %0\n\t" | ||
46 | "rep\n\t" | ||
47 | "movsb\n\t" | ||
48 | "cld" | ||
49 | : "=&c" (d0), "=&S" (d1), "=&D" (d2), "=r" (d3) | ||
50 | :"0" (count), | ||
51 | "1" (src), | ||
52 | "2" (dest) | ||
53 | :"memory"); | ||
18 | } | 54 | } |
19 | return dest; | 55 | return dest; |
20 | } | 56 | } |