aboutsummaryrefslogtreecommitdiffstats
path: root/xen/arch/x86/copy_page.S
blob: 2fd3e533c674d62e8ea06590597cad78608e33e0 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
#include <xen/config.h>
#include <asm/page.h>

#ifdef __i386__
#define src_reg %esi
#define dst_reg %edi
#define WORD_SIZE 4
#define tmp1_reg %eax
#define tmp2_reg %edx
#define tmp3_reg %ebx
#define tmp4_reg %ebp
#else
#define src_reg %rsi
#define dst_reg %rdi
#define WORD_SIZE 8
#define tmp1_reg %r8
#define tmp2_reg %r9
#define tmp3_reg %r10
#define tmp4_reg %r11
#endif

ENTRY(copy_page_sse2)
#ifdef __i386__
        push    %ebx
        push    %ebp
        push    %esi
        push    %edi
        mov     6*4(%esp), src_reg
        mov     5*4(%esp), dst_reg
#endif
        mov     $PAGE_SIZE/(4*WORD_SIZE)-3, %ecx

        prefetchnta 2*4*WORD_SIZE(src_reg)
        mov     (src_reg), tmp1_reg
        mov     WORD_SIZE(src_reg), tmp2_reg
        mov     2*WORD_SIZE(src_reg), tmp3_reg
        mov     3*WORD_SIZE(src_reg), tmp4_reg

0:      prefetchnta 3*4*WORD_SIZE(src_reg)
1:      add     $4*WORD_SIZE, src_reg
        movnti  tmp1_reg, (dst_reg)
        mov     (src_reg), tmp1_reg
        dec     %ecx
        movnti  tmp2_reg, WORD_SIZE(dst_reg)
        mov     WORD_SIZE(src_reg), tmp2_reg
        movnti  tmp3_reg, 2*WORD_SIZE(dst_reg)
        mov     2*WORD_SIZE(src_reg), tmp3_reg
        movnti  tmp4_reg, 3*WORD_SIZE(dst_reg)
        lea     4*WORD_SIZE(dst_reg), dst_reg
        mov     3*WORD_SIZE(src_reg), tmp4_reg
        jg      0b
        jpe     1b

        movnti  tmp1_reg, (dst_reg)
        movnti  tmp2_reg, WORD_SIZE(dst_reg)
        movnti  tmp3_reg, 2*WORD_SIZE(dst_reg)
        movnti  tmp4_reg, 3*WORD_SIZE(dst_reg)

#ifdef __i386__
        pop     %edi
        pop     %esi
        pop     %ebp
        pop     %ebx
#endif
        sfence
        ret