477
|
1
|
|
2 #ifndef __MPLAYER_MEMCPY
|
|
3 #define __MPLAYER_MEMCPY
|
|
4
|
358
|
5 /*
|
|
6 This part of code was taken by from Linux-2.4.3 and slightly modified
|
|
7 for MMX2 instruction set. I have done it since linux uses page aligned
|
|
8 blocks but mplayer uses weakly ordered data and original sources can not
|
376
|
9 speedup their. Only using prefetchnta and movntq together have effect!
|
358
|
10 If you have questions please contact with me: Nick Kurshev: nickols_k@mail.ru.
|
|
11 */
|
477
|
12
|
|
13 // 3dnow memcpy support from kernel 2.4.2
|
|
14 // by Pontscho/fresh!mindworkz
|
|
15
|
|
16 #if defined( HAVE_MMX2 ) || defined( HAVE_3DNOW )
|
|
17
|
376
|
18 /* for small memory blocks (<256 bytes) this version is faster */
|
|
19 #define small_memcpy(to,from,n)\
|
|
20 {\
|
|
21 __asm__ __volatile__(\
|
|
22 "rep ; movsb\n"\
|
|
23 ::"D" (to), "S" (from),"c" (n)\
|
|
24 : "memory");\
|
|
25 }
|
358
|
26
|
370
|
27 inline static void * fast_memcpy(void * to, const void * from, unsigned len)
|
358
|
28 {
|
|
29 void *p;
|
|
30 int i;
|
|
31
|
567
|
32
|
|
33 #ifdef HAVE_SSE /* Only P3 (may be Cyrix3) */
|
|
34 // printf("fastmemcpy_pre(0x%X,0x%X,0x%X)\n",to,from,len);
|
|
35 // Align dest to 16-byte boundary:
|
|
36 if((unsigned int)to&15){
|
|
37 int len2=16-((unsigned int)to&15);
|
|
38 if(len>len2){
|
|
39 len-=len2;
|
|
40 __asm__ __volatile__(
|
|
41 "rep ; movsb\n"
|
|
42 :"=D" (to), "=S" (from)
|
|
43 : "D" (to), "S" (from),"c" (len2)
|
|
44 : "memory");
|
|
45 }
|
|
46 }
|
|
47 // printf("fastmemcpy(0x%X,0x%X,0x%X)\n",to,from,len);
|
|
48 #endif
|
|
49
|
|
50
|
358
|
51 if(len >= 0x200) /* 512-byte blocks */
|
|
52 {
|
|
53 p = to;
|
|
54 i = len >> 6; /* len/64 */
|
376
|
55 len&=63;
|
|
56
|
358
|
57 __asm__ __volatile__ (
|
477
|
58 #if defined( HAVE_3DNOW ) && !defined( HAVE_MMX2 )
|
|
59 "prefetch (%0)\n"
|
|
60 "prefetch 64(%0)\n"
|
|
61 "prefetch 128(%0)\n"
|
|
62 "prefetch 192(%0)\n"
|
|
63 "prefetch 256(%0)\n"
|
|
64 #else
|
409
|
65 "prefetchnta (%0)\n"
|
|
66 "prefetchnta 64(%0)\n"
|
|
67 "prefetchnta 128(%0)\n"
|
|
68 "prefetchnta 192(%0)\n"
|
|
69 "prefetchnta 256(%0)\n"
|
477
|
70 #endif
|
358
|
71 : : "r" (from) );
|
409
|
72 /*
|
|
73 This algorithm is top effective when the code consequently
|
|
74 reads and writes blocks which have size of cache line.
|
|
75 Size of cache line is processor-dependent.
|
|
76 It will, however, be a minimum of 32 bytes on any processors.
|
|
77 It would be better to have a number of instructions which
|
|
78 perform reading and writing to be multiple to a number of
|
|
79 processor's decoders, but it's not always possible.
|
|
80 */
|
358
|
81 for(; i>0; i--)
|
|
82 {
|
|
83 __asm__ __volatile__ (
|
477
|
84 #if defined( HAVE_3DNOW ) && !defined( HAVE_MMX2 )
|
|
85 "prefetch 320(%0)\n"
|
|
86 #else
|
409
|
87 "prefetchnta 320(%0)\n"
|
477
|
88 #endif
|
409
|
89 #ifdef HAVE_SSE /* Only P3 (may be Cyrix3) */
|
|
90 "movups (%0), %%xmm0\n"
|
|
91 "movups 16(%0), %%xmm1\n"
|
|
92 "movntps %%xmm0, (%1)\n"
|
|
93 "movntps %%xmm1, 16(%1)\n"
|
|
94 "movups 32(%0), %%xmm0\n"
|
|
95 "movups 48(%0), %%xmm1\n"
|
|
96 "movntps %%xmm0, 32(%1)\n"
|
|
97 "movntps %%xmm1, 48(%1)\n"
|
|
98 #else /* Only K7 (may be other) */
|
477
|
99 #if defined( HAVE_3DNOW ) && !defined( HAVE_MMX2 )
|
|
100 "movq (%0), %%mm0\n"
|
|
101 "movq 8(%0), %%mm1\n"
|
|
102 "movq 16(%0), %%mm2\n"
|
|
103 "movq 24(%0), %%mm3\n"
|
|
104 "movq %%mm0, (%1)\n"
|
|
105 "movq %%mm1, 8(%1)\n"
|
|
106 "movq %%mm2, 16(%1)\n"
|
|
107 "movq %%mm3, 24(%1)\n"
|
|
108 "movq 32(%0), %%mm0\n"
|
|
109 "movq 40(%0), %%mm1\n"
|
|
110 "movq 48(%0), %%mm2\n"
|
|
111 "movq 56(%0), %%mm3\n"
|
|
112 "movq %%mm0, 32(%1)\n"
|
|
113 "movq %%mm1, 40(%1)\n"
|
|
114 "movq %%mm2, 48(%1)\n"
|
|
115 "movq %%mm3, 56(%1)\n"
|
|
116 #else
|
409
|
117 "movq (%0), %%mm0\n"
|
|
118 "movq 8(%0), %%mm1\n"
|
|
119 "movq 16(%0), %%mm2\n"
|
|
120 "movq 24(%0), %%mm3\n"
|
|
121 "movntq %%mm0, (%1)\n"
|
|
122 "movntq %%mm1, 8(%1)\n"
|
|
123 "movntq %%mm2, 16(%1)\n"
|
|
124 "movntq %%mm3, 24(%1)\n"
|
|
125 "movq 32(%0), %%mm0\n"
|
|
126 "movq 40(%0), %%mm1\n"
|
|
127 "movq 48(%0), %%mm2\n"
|
|
128 "movq 56(%0), %%mm3\n"
|
|
129 "movntq %%mm0, 32(%1)\n"
|
|
130 "movntq %%mm1, 40(%1)\n"
|
|
131 "movntq %%mm2, 48(%1)\n"
|
|
132 "movntq %%mm3, 56(%1)\n"
|
|
133 #endif
|
477
|
134 #endif
|
409
|
135 :: "r" (from), "r" (to) : "memory");
|
358
|
136 from+=64;
|
|
137 to+=64;
|
|
138 }
|
477
|
139 #if defined( HAVE_3DNOW ) && !defined( HAVE_MMX2 )
|
|
140 __asm__ __volatile__ ("femms":::"memory");
|
|
141 #else
|
409
|
142 __asm__ __volatile__ ("emms":::"memory");
|
477
|
143 #endif
|
358
|
144 }
|
|
145 /*
|
|
146 * Now do the tail of the block
|
|
147 */
|
376
|
148 small_memcpy(to, from, len);
|
358
|
149 return p;
|
|
150 }
|
376
|
151 #define memcpy(a,b,c) fast_memcpy(a,b,c)
|
477
|
152
|
513
|
153 #undef small_memcpy
|
|
154
|
358
|
155 #endif
|
|
156
|
478
|
157 #endif
|