Initial revision
[ffmpeg.git] / libavcodec / i386 / dsputil_mmx.c
1 /*
2  * MMX optimized DSP utils
3  * Copyright (c) 2000, 2001 Gerard Lantau.
4  *
5  * This program is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License as published by
7  * the Free Software Foundation; either version 2 of the License, or
8  * (at your option) any later version.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program; if not, write to the Free Software
17  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18  *
19  * MMX optimization by Nick Kurshev <nickols_k@mail.ru>
20  */
21
22 #include "../dsputil.h"
23
24 int pix_abs16x16_mmx(UINT8 *blk1, UINT8 *blk2, int lx, int h);
25 int pix_abs16x16_sse(UINT8 *blk1, UINT8 *blk2, int lx, int h);
26 int pix_abs16x16_x2_mmx(UINT8 *blk1, UINT8 *blk2, int lx, int h);
27 int pix_abs16x16_y2_mmx(UINT8 *blk1, UINT8 *blk2, int lx, int h);
28 int pix_abs16x16_xy2_mmx(UINT8 *blk1, UINT8 *blk2, int lx, int h);
29
30 /* pixel operations */
31 static const unsigned short mm_wone[4] __attribute__ ((aligned(8))) = { 0x1, 0x1, 0x1, 0x1 };
32 static const unsigned short mm_wtwo[4] __attribute__ ((aligned(8))) = { 0x2, 0x2, 0x2, 0x2 };
33
34 /***********************************/
35 /* 3Dnow specific */
36
37 #define DEF(x) x ## _3dnow
38 /* for Athlons PAVGUSB is prefered */
39 #define PAVGB "pavgusb"
40
41 #include "dsputil_mmx_avg.h"
42
43 #undef DEF
44 #undef PAVGB
45
46 /***********************************/
47 /* MMX2 specific */
48
49 #define DEF(x) x ## _sse
50
51 /* Introduced only in MMX2 set */
52 #define PAVGB "pavgb"
53
54 #include "dsputil_mmx_avg.h"
55
56 #undef DEF
57 #undef PAVGB
58
59 /***********************************/
60 /* standard MMX */
61
62 static void get_pixels_mmx(DCTELEM *block, const UINT8 *pixels, int line_size)
63 {
64     DCTELEM *p;
65     const UINT8 *pix;
66     int i;
67
68     /* read the pixels */
69     p = block;
70     pix = pixels;
71     __asm __volatile("pxor %%mm7, %%mm7":::"memory");
72     for(i=0;i<4;i++) {
73         __asm __volatile(
74                 "movq   %1, %%mm0\n\t"
75                 "movq   %2, %%mm1\n\t"
76                 "movq   %%mm0, %%mm2\n\t"
77                 "movq   %%mm1, %%mm3\n\t"
78                 "punpcklbw %%mm7, %%mm0\n\t"
79                 "punpckhbw %%mm7, %%mm2\n\t"
80                 "punpcklbw %%mm7, %%mm1\n\t"
81                 "punpckhbw %%mm7, %%mm3\n\t"
82                 "movq   %%mm0, %0\n\t"
83                 "movq   %%mm2, 8%0\n\t"
84                 "movq   %%mm1, 16%0\n\t"
85                 "movq   %%mm3, 24%0\n\t"
86                 :"=m"(*p)
87                 :"m"(*pix), "m"(*(pix+line_size))
88                 :"memory");
89         pix += line_size*2;
90         p += 16;
91     }
92     emms();
93 }
94
95 static void put_pixels_clamped_mmx(const DCTELEM *block, UINT8 *pixels, int line_size)
96 {
97     const DCTELEM *p;
98     UINT8 *pix;
99     int i;
100
101     /* read the pixels */
102     p = block;
103     pix = pixels;
104     for(i=0;i<2;i++) {
105         __asm __volatile(
106                 "movq   %4, %%mm0\n\t"
107                 "movq   8%4, %%mm1\n\t"
108                 "movq   16%4, %%mm2\n\t"
109                 "movq   24%4, %%mm3\n\t"
110                 "movq   32%4, %%mm4\n\t"
111                 "movq   40%4, %%mm5\n\t"
112                 "movq   48%4, %%mm6\n\t"
113                 "movq   56%4, %%mm7\n\t"
114                 "packuswb %%mm1, %%mm0\n\t"
115                 "packuswb %%mm3, %%mm2\n\t"
116                 "packuswb %%mm5, %%mm4\n\t"
117                 "packuswb %%mm7, %%mm6\n\t"
118                 "movq   %%mm0, %0\n\t"
119                 "movq   %%mm2, %1\n\t"
120                 "movq   %%mm4, %2\n\t"
121                 "movq   %%mm6, %3\n\t"
122                 :"=m"(*pix), "=m"(*(pix+line_size))
123                 ,"=m"(*(pix+line_size*2)), "=m"(*(pix+line_size*3))
124                 :"m"(*p)
125                 :"memory");
126         pix += line_size*4;
127         p += 32;
128     }
129     emms();
130 }
131
132 static void add_pixels_clamped_mmx(const DCTELEM *block, UINT8 *pixels, int line_size)
133 {
134     const DCTELEM *p;
135     UINT8 *pix;
136     int i;
137
138     /* read the pixels */
139     p = block;
140     pix = pixels;
141         __asm __volatile("pxor  %%mm7, %%mm7":::"memory");
142     for(i=0;i<4;i++) {
143         __asm __volatile(
144                 "movq   %2, %%mm0\n\t"
145                 "movq   8%2, %%mm1\n\t"
146                 "movq   16%2, %%mm2\n\t"
147                 "movq   24%2, %%mm3\n\t"
148                 "movq   %0, %%mm4\n\t"
149                 "movq   %1, %%mm6\n\t"
150                 "movq   %%mm4, %%mm5\n\t"
151                 "punpcklbw %%mm7, %%mm4\n\t"
152                 "punpckhbw %%mm7, %%mm5\n\t"
153                 "paddsw %%mm4, %%mm0\n\t"
154                 "paddsw %%mm5, %%mm1\n\t"
155                 "movq   %%mm6, %%mm5\n\t"
156                 "punpcklbw %%mm7, %%mm6\n\t"
157                 "punpckhbw %%mm7, %%mm5\n\t"
158                 "paddsw %%mm6, %%mm2\n\t"
159                 "paddsw %%mm5, %%mm3\n\t"
160                 "packuswb %%mm1, %%mm0\n\t"
161                 "packuswb %%mm3, %%mm2\n\t"
162                 "movq   %%mm0, %0\n\t"
163                 "movq   %%mm2, %1\n\t"
164                 :"=m"(*pix), "=m"(*(pix+line_size))
165                 :"m"(*p)
166                 :"memory");
167         pix += line_size*2;
168         p += 16;
169     }
170     emms();
171 }
172
173 static void put_pixels_mmx(UINT8 *block, const UINT8 *pixels, int line_size, int h)
174 {
175     int dh, hh;
176     UINT8 *p;
177     const UINT8 *pix;
178     p   = block;
179     pix = pixels;
180     hh=h>>2;
181     dh=h&3;
182     while(hh--) {
183     __asm __volatile(
184         "movq   %4, %%mm0\n\t"
185         "movq   %5, %%mm1\n\t"
186         "movq   %6, %%mm2\n\t"
187         "movq   %7, %%mm3\n\t"
188         "movq   %%mm0, %0\n\t"
189         "movq   %%mm1, %1\n\t"
190         "movq   %%mm2, %2\n\t"
191         "movq   %%mm3, %3\n\t"
192         :"=m"(*p), "=m"(*(p+line_size)), "=m"(*(p+line_size*2)), "=m"(*(p+line_size*3))
193         :"m"(*pix), "m"(*(pix+line_size)), "m"(*(pix+line_size*2)), "m"(*(pix+line_size*3))
194         :"memory");
195         pix = pix + line_size*4;
196         p =   p   + line_size*4;
197     }
198     while(dh--) {
199      __asm __volatile(
200         "movq   %1, %%mm0\n\t"
201         "movq   %%mm0, %0\n\t"
202         :"=m"(*p)
203         :"m"(*pix)
204         :"memory");
205         pix = pix + line_size;
206         p =   p   + line_size;
207     }
208     emms();
209 }
210
211 static void put_pixels_x2_mmx(UINT8 *block, const UINT8 *pixels, int line_size, int h)
212 {
213   UINT8 *p;
214   const UINT8 *pix;
215   p = block;
216   pix = pixels;
217   __asm __volatile(
218         "pxor   %%mm7, %%mm7\n\t"
219         "movq   %0, %%mm4\n\t"
220         ::"m"(mm_wone[0]):"memory");
221   do {
222     __asm __volatile(
223         "movq   %1, %%mm0\n\t"
224         "movq   1%1, %%mm1\n\t"
225         "movq   %%mm0, %%mm2\n\t"
226         "movq   %%mm1, %%mm3\n\t"
227         "punpcklbw %%mm7, %%mm0\n\t"
228         "punpcklbw %%mm7, %%mm1\n\t"
229         "punpckhbw %%mm7, %%mm2\n\t"
230         "punpckhbw %%mm7, %%mm3\n\t"
231         "paddusw %%mm1, %%mm0\n\t"
232         "paddusw %%mm3, %%mm2\n\t"
233         "paddusw %%mm4, %%mm0\n\t"
234         "paddusw %%mm4, %%mm2\n\t"
235         "psrlw  $1, %%mm0\n\t"
236         "psrlw  $1, %%mm2\n\t"
237         "packuswb  %%mm2, %%mm0\n\t"
238         "movq   %%mm0, %0\n\t"
239         :"=m"(*p)
240         :"m"(*pix)
241         :"memory");
242    pix += line_size; p += line_size;
243   } while (--h);
244   emms();
245 }
246
247 static void put_pixels_y2_mmx(UINT8 *block, const UINT8 *pixels, int line_size, int h)
248 {
249   UINT8 *p;
250   const UINT8 *pix;
251   p = block;
252   pix = pixels;
253   __asm __volatile(
254         "pxor   %%mm7, %%mm7\n\t"
255         "movq   %0, %%mm4\n\t"
256         ::"m"(mm_wone[0]):"memory");
257   do {
258     __asm __volatile(
259         "movq   %1, %%mm0\n\t"
260         "movq   %2, %%mm1\n\t"
261         "movq   %%mm0, %%mm2\n\t"
262         "movq   %%mm1, %%mm3\n\t"
263         "punpcklbw %%mm7, %%mm0\n\t"
264         "punpcklbw %%mm7, %%mm1\n\t"
265         "punpckhbw %%mm7, %%mm2\n\t"
266         "punpckhbw %%mm7, %%mm3\n\t"
267         "paddusw %%mm1, %%mm0\n\t"
268         "paddusw %%mm3, %%mm2\n\t"
269         "paddusw %%mm4, %%mm0\n\t"
270         "paddusw %%mm4, %%mm2\n\t"
271         "psrlw  $1, %%mm0\n\t"
272         "psrlw  $1, %%mm2\n\t"
273         "packuswb  %%mm2, %%mm0\n\t"
274         "movq   %%mm0, %0\n\t"
275         :"=m"(*p)
276         :"m"(*pix),
277          "m"(*(pix+line_size))
278         :"memory");
279    pix += line_size;
280    p += line_size;
281   } while (--h);
282   emms();
283 }
284
285 static void put_pixels_xy2_mmx(UINT8 *block, const UINT8 *pixels, int line_size, int h)
286 {
287   UINT8 *p;
288   const UINT8 *pix;
289   p = block;
290   pix = pixels;
291   __asm __volatile(
292         "pxor   %%mm7, %%mm7\n\t"
293         "movq   %0, %%mm6\n\t"
294         ::"m"(mm_wtwo[0]):"memory");
295   do {
296     __asm __volatile(
297         "movq   %1, %%mm0\n\t"
298         "movq   %2, %%mm1\n\t"
299         "movq   1%1, %%mm4\n\t"
300         "movq   1%2, %%mm5\n\t"
301         "movq   %%mm0, %%mm2\n\t"
302         "movq   %%mm1, %%mm3\n\t"
303         "punpcklbw %%mm7, %%mm0\n\t"
304         "punpcklbw %%mm7, %%mm1\n\t"
305         "punpckhbw %%mm7, %%mm2\n\t"
306         "punpckhbw %%mm7, %%mm3\n\t"
307         "paddusw %%mm1, %%mm0\n\t"
308         "paddusw %%mm3, %%mm2\n\t"
309         "movq   %%mm4, %%mm1\n\t"
310         "movq   %%mm5, %%mm3\n\t"
311         "punpcklbw %%mm7, %%mm4\n\t"
312         "punpcklbw %%mm7, %%mm5\n\t"
313         "punpckhbw %%mm7, %%mm1\n\t"
314         "punpckhbw %%mm7, %%mm3\n\t"
315         "paddusw %%mm5, %%mm4\n\t"
316         "paddusw %%mm3, %%mm1\n\t"
317         "paddusw %%mm6, %%mm4\n\t"
318         "paddusw %%mm6, %%mm1\n\t"
319         "paddusw %%mm4, %%mm0\n\t"
320         "paddusw %%mm1, %%mm2\n\t"
321         "psrlw  $2, %%mm0\n\t"
322         "psrlw  $2, %%mm2\n\t"
323         "packuswb  %%mm2, %%mm0\n\t"
324         "movq   %%mm0, %0\n\t"
325         :"=m"(*p)
326         :"m"(*pix),
327          "m"(*(pix+line_size))
328         :"memory");
329    pix += line_size;
330    p += line_size;
331   } while(--h);
332   emms();
333 }
334
335 static void   put_no_rnd_pixels_x2_mmx( UINT8  *block, const UINT8 *pixels, int line_size, int h)
336 {
337   UINT8  *p;
338   const UINT8 *pix;
339   p = block;
340   pix = pixels;
341   __asm __volatile("pxor %%mm7, %%mm7\n\t":::"memory");
342   do {
343     __asm __volatile(
344         "movq   %1, %%mm0\n\t"
345         "movq   1%1, %%mm1\n\t"
346         "movq   %%mm0, %%mm2\n\t"
347         "movq   %%mm1, %%mm3\n\t"
348         "punpcklbw %%mm7, %%mm0\n\t"
349         "punpcklbw %%mm7, %%mm1\n\t"
350         "punpckhbw %%mm7, %%mm2\n\t"
351         "punpckhbw %%mm7, %%mm3\n\t"
352         "paddusw %%mm1, %%mm0\n\t"
353         "paddusw %%mm3, %%mm2\n\t"
354         "psrlw  $1, %%mm0\n\t"
355         "psrlw  $1, %%mm2\n\t"
356         "packuswb  %%mm2, %%mm0\n\t"
357         "movq   %%mm0, %0\n\t"
358         :"=m"(*p)
359         :"m"(*pix)
360         :"memory");
361    pix += line_size;
362    p +=   line_size;
363   } while (--h);
364   emms();
365 }
366
367 static void put_no_rnd_pixels_y2_mmx( UINT8  *block, const UINT8 *pixels, int line_size, int h)
368 {
369   UINT8  *p;
370   const UINT8 *pix;
371   p = block;
372   pix = pixels;
373   __asm __volatile("pxor %%mm7, %%mm7\n\t":::"memory");
374   do {
375     __asm __volatile(
376         "movq   %1, %%mm0\n\t"
377         "movq   %2, %%mm1\n\t"
378         "movq   %%mm0, %%mm2\n\t"
379         "movq   %%mm1, %%mm3\n\t"
380         "punpcklbw %%mm7, %%mm0\n\t"
381         "punpcklbw %%mm7, %%mm1\n\t"
382         "punpckhbw %%mm7, %%mm2\n\t"
383         "punpckhbw %%mm7, %%mm3\n\t"
384         "paddusw %%mm1, %%mm0\n\t"
385         "paddusw %%mm3, %%mm2\n\t"
386         "psrlw  $1, %%mm0\n\t"
387         "psrlw  $1, %%mm2\n\t"
388         "packuswb  %%mm2, %%mm0\n\t"
389         "movq   %%mm0, %0\n\t"
390         :"=m"(*p)
391         :"m"(*pix),
392          "m"(*(pix+line_size))
393         :"memory");
394    pix += line_size;
395    p +=   line_size;
396   } while(--h);
397   emms();
398 }
399
400 static void   put_no_rnd_pixels_xy2_mmx( UINT8  *block, const UINT8 *pixels, int line_size, int h)
401 {
402   UINT8  *p;
403   const UINT8 *pix;
404   p = block;
405   pix = pixels;
406   __asm __volatile(
407         "pxor   %%mm7, %%mm7\n\t"
408         "movq   %0, %%mm6\n\t"
409         ::"m"(mm_wone[0]):"memory");
410   do {
411     __asm __volatile(
412         "movq   %1, %%mm0\n\t"
413         "movq   %2, %%mm1\n\t"
414         "movq   1%1, %%mm4\n\t"
415         "movq   1%2, %%mm5\n\t"
416         "movq   %%mm0, %%mm2\n\t"
417         "movq   %%mm1, %%mm3\n\t"
418         "punpcklbw %%mm7, %%mm0\n\t"
419         "punpcklbw %%mm7, %%mm1\n\t"
420         "punpckhbw %%mm7, %%mm2\n\t"
421         "punpckhbw %%mm7, %%mm3\n\t"
422         "paddusw %%mm1, %%mm0\n\t"
423         "paddusw %%mm3, %%mm2\n\t"
424         "movq   %%mm4, %%mm1\n\t"
425         "movq   %%mm5, %%mm3\n\t"
426         "punpcklbw %%mm7, %%mm4\n\t"
427         "punpcklbw %%mm7, %%mm5\n\t"
428         "punpckhbw %%mm7, %%mm1\n\t"
429         "punpckhbw %%mm7, %%mm3\n\t"
430         "paddusw %%mm5, %%mm4\n\t"
431         "paddusw %%mm3, %%mm1\n\t"
432         "paddusw %%mm6, %%mm4\n\t"
433         "paddusw %%mm6, %%mm1\n\t"
434         "paddusw %%mm4, %%mm0\n\t"
435         "paddusw %%mm1, %%mm2\n\t"
436         "psrlw  $2, %%mm0\n\t"
437         "psrlw  $2, %%mm2\n\t"
438         "packuswb  %%mm2, %%mm0\n\t"
439         "movq   %%mm0, %0\n\t"
440         :"=m"(*p)
441         :"m"(*pix),
442          "m"(*(pix+line_size))
443         :"memory");
444    pix += line_size;
445    p +=   line_size;
446   } while(--h);
447   emms();
448 }
449
450 static void avg_pixels_mmx(UINT8 *block, const UINT8 *pixels, int line_size, int h)
451 {
452   UINT8  *p;
453   const UINT8 *pix;
454   p = block;
455   pix = pixels;
456   __asm __volatile(
457         "pxor   %%mm7, %%mm7\n\t"
458         "movq   %0, %%mm6\n\t"
459         ::"m"(mm_wone[0]):"memory");
460   do {
461     __asm __volatile(
462         "movq   %0, %%mm0\n\t"
463         "movq   %1, %%mm1\n\t"
464         "movq   %%mm0, %%mm2\n\t"
465         "movq   %%mm1, %%mm3\n\t"
466         "punpcklbw %%mm7, %%mm0\n\t"
467         "punpcklbw %%mm7, %%mm1\n\t"
468         "punpckhbw %%mm7, %%mm2\n\t"
469         "punpckhbw %%mm7, %%mm3\n\t"
470         "paddusw %%mm1, %%mm0\n\t"
471         "paddusw %%mm3, %%mm2\n\t"
472         "paddusw %%mm6, %%mm0\n\t"
473         "paddusw %%mm6, %%mm2\n\t"
474         "psrlw  $1, %%mm0\n\t"
475         "psrlw  $1, %%mm2\n\t"
476         "packuswb  %%mm2, %%mm0\n\t"
477         "movq   %%mm0, %0\n\t"
478         :"=m"(*p)
479         :"m"(*pix)
480         :"memory");
481    pix += line_size;
482    p +=   line_size;
483   }
484   while (--h);
485   emms();
486 }
487
488 static void   avg_pixels_x2_mmx( UINT8  *block, const UINT8 *pixels, int line_size, int h)
489 {
490   UINT8  *p;
491   const UINT8 *pix;
492   p = block;
493   pix = pixels;
494   __asm __volatile(
495         "pxor   %%mm7, %%mm7\n\t"
496         "movq   %0, %%mm6\n\t"
497         ::"m"(mm_wone[0]):"memory");
498   do {
499     __asm __volatile(
500         "movq   %1, %%mm1\n\t"
501         "movq   %0, %%mm0\n\t"
502         "movq   1%1, %%mm4\n\t"
503         "movq   %%mm0, %%mm2\n\t"
504         "movq   %%mm1, %%mm3\n\t"
505         "movq   %%mm4, %%mm5\n\t"
506         "punpcklbw %%mm7, %%mm1\n\t"
507         "punpckhbw %%mm7, %%mm3\n\t"
508         "punpcklbw %%mm7, %%mm4\n\t"
509         "punpckhbw %%mm7, %%mm5\n\t"
510         "punpcklbw %%mm7, %%mm0\n\t"
511         "punpckhbw %%mm7, %%mm2\n\t"
512         "paddusw %%mm4, %%mm1\n\t"
513         "paddusw %%mm5, %%mm3\n\t"
514         "paddusw %%mm6, %%mm1\n\t"
515         "paddusw %%mm6, %%mm3\n\t"
516         "psrlw  $1, %%mm1\n\t"
517         "psrlw  $1, %%mm3\n\t"
518         "paddusw %%mm6, %%mm0\n\t"
519         "paddusw %%mm6, %%mm2\n\t"
520         "paddusw %%mm1, %%mm0\n\t"
521         "paddusw %%mm3, %%mm2\n\t"
522         "psrlw  $1, %%mm0\n\t"
523         "psrlw  $1, %%mm2\n\t"
524         "packuswb  %%mm2, %%mm0\n\t"
525         "movq   %%mm0, %0\n\t"
526         :"=m"(*p)
527         :"m"(*pix)
528         :"memory");
529    pix += line_size;
530    p +=   line_size;
531   } while (--h);
532   emms();
533 }
534
535 static void   avg_pixels_y2_mmx( UINT8  *block, const UINT8 *pixels, int line_size, int h)
536 {
537   UINT8  *p;
538   const UINT8 *pix;
539   p = block;
540   pix = pixels;
541   __asm __volatile(
542         "pxor   %%mm7, %%mm7\n\t"
543         "movq   %0, %%mm6\n\t"
544         ::"m"(mm_wone[0]):"memory");
545   do {
546     __asm __volatile(
547         "movq   %1, %%mm1\n\t"
548         "movq   %0, %%mm0\n\t"
549         "movq   %2, %%mm4\n\t"
550         "movq   %%mm0, %%mm2\n\t"
551         "movq   %%mm1, %%mm3\n\t"
552         "movq   %%mm4, %%mm5\n\t"
553         "punpcklbw %%mm7, %%mm1\n\t"
554         "punpckhbw %%mm7, %%mm3\n\t"
555         "punpcklbw %%mm7, %%mm4\n\t"
556         "punpckhbw %%mm7, %%mm5\n\t"
557         "punpcklbw %%mm7, %%mm0\n\t"
558         "punpckhbw %%mm7, %%mm2\n\t"
559         "paddusw %%mm4, %%mm1\n\t"
560         "paddusw %%mm5, %%mm3\n\t"
561         "paddusw %%mm6, %%mm1\n\t"
562         "paddusw %%mm6, %%mm3\n\t"
563         "psrlw  $1, %%mm1\n\t"
564         "psrlw  $1, %%mm3\n\t"
565         "paddusw %%mm6, %%mm0\n\t"
566         "paddusw %%mm6, %%mm2\n\t"
567         "paddusw %%mm1, %%mm0\n\t"
568         "paddusw %%mm3, %%mm2\n\t"
569         "psrlw  $1, %%mm0\n\t"
570         "psrlw  $1, %%mm2\n\t"
571         "packuswb  %%mm2, %%mm0\n\t"
572         "movq   %%mm0, %0\n\t"
573         :"=m"(*p)
574         :"m"(*pix), "m"(*(pix+line_size))
575         :"memory");
576    pix += line_size;
577    p +=   line_size ;
578   } while(--h);
579   emms();
580 }
581
582 static void   avg_pixels_xy2_mmx( UINT8  *block, const UINT8 *pixels, int line_size, int h)
583 {
584   UINT8  *p;
585   const UINT8 *pix;
586   p = block;
587   pix = pixels;
588   __asm __volatile(
589         "pxor   %%mm7, %%mm7\n\t"
590         "movq   %0, %%mm6\n\t"
591         ::"m"(mm_wtwo[0]):"memory");
592   do {
593     __asm __volatile(
594         "movq   %1, %%mm0\n\t"
595         "movq   %2, %%mm1\n\t"
596         "movq   1%1, %%mm4\n\t"
597         "movq   1%2, %%mm5\n\t"
598         "movq   %%mm0, %%mm2\n\t"
599         "movq   %%mm1, %%mm3\n\t"
600         "punpcklbw %%mm7, %%mm0\n\t"
601         "punpcklbw %%mm7, %%mm1\n\t"
602         "punpckhbw %%mm7, %%mm2\n\t"
603         "punpckhbw %%mm7, %%mm3\n\t"
604         "paddusw %%mm1, %%mm0\n\t"
605         "paddusw %%mm3, %%mm2\n\t"
606         "movq   %%mm4, %%mm1\n\t"
607         "movq   %%mm5, %%mm3\n\t"
608         "punpcklbw %%mm7, %%mm4\n\t"
609         "punpcklbw %%mm7, %%mm5\n\t"
610         "punpckhbw %%mm7, %%mm1\n\t"
611         "punpckhbw %%mm7, %%mm3\n\t"
612         "paddusw %%mm5, %%mm4\n\t"
613         "paddusw %%mm3, %%mm1\n\t"
614         "paddusw %%mm6, %%mm4\n\t"
615         "paddusw %%mm6, %%mm1\n\t"
616         "paddusw %%mm4, %%mm0\n\t"
617         "paddusw %%mm1, %%mm2\n\t"
618         "movq   %3, %%mm5\n\t"
619         "psrlw  $2, %%mm0\n\t"
620         "movq   %0, %%mm1\n\t"
621         "psrlw  $2, %%mm2\n\t"
622         "movq   %%mm1, %%mm3\n\t"
623         "punpcklbw %%mm7, %%mm1\n\t"
624         "punpckhbw %%mm7, %%mm3\n\t"
625         "paddusw %%mm1, %%mm0\n\t"
626         "paddusw %%mm3, %%mm2\n\t"
627         "paddusw %%mm5, %%mm0\n\t"
628         "paddusw %%mm5, %%mm2\n\t"
629         "psrlw  $1, %%mm0\n\t"
630         "psrlw  $1, %%mm2\n\t"
631         "packuswb  %%mm2, %%mm0\n\t"
632         "movq   %%mm0, %0\n\t"
633         :"=m"(*p)
634         :"m"(*pix),
635          "m"(*(pix+line_size)), "m"(mm_wone[0])
636         :"memory");
637    pix += line_size;
638    p +=   line_size ;
639   } while(--h);
640   emms();
641 }
642
643 static void avg_no_rnd_pixels_mmx( UINT8  *block, const UINT8 *pixels, int line_size, int h)
644 {
645   UINT8  *p;
646   const UINT8 *pix;
647   p = block;
648   pix = pixels;
649   __asm __volatile("pxor %%mm7, %%mm7\n\t":::"memory");
650   do {
651     __asm __volatile(
652         "movq   %1, %%mm0\n\t"
653         "movq   %0, %%mm1\n\t"
654         "movq   %%mm0, %%mm2\n\t"
655         "movq   %%mm1, %%mm3\n\t"
656         "punpcklbw %%mm7, %%mm0\n\t"
657         "punpcklbw %%mm7, %%mm1\n\t"
658         "punpckhbw %%mm7, %%mm2\n\t"
659         "punpckhbw %%mm7, %%mm3\n\t"
660         "paddusw %%mm1, %%mm0\n\t"
661         "paddusw %%mm3, %%mm2\n\t"
662         "psrlw  $1, %%mm0\n\t"
663         "psrlw  $1, %%mm2\n\t"
664         "packuswb  %%mm2, %%mm0\n\t"
665         "movq   %%mm0, %0\n\t"
666         :"=m"(*p)
667         :"m"(*pix)
668         :"memory");
669    pix += line_size;
670    p +=   line_size ;
671   } while (--h);
672   emms();
673 }
674
675 static void   avg_no_rnd_pixels_x2_mmx( UINT8  *block, const UINT8 *pixels, int line_size, int h)
676 {
677   UINT8  *p;
678   const UINT8 *pix;
679   p = block;
680   pix = pixels;
681   __asm __volatile(
682       "pxor     %%mm7, %%mm7\n\t":::"memory");
683   do {
684     __asm __volatile(
685         "movq   %1, %%mm0\n\t"
686         "movq   1%1, %%mm1\n\t"
687         "movq   %0, %%mm4\n\t"
688         "movq   %%mm0, %%mm2\n\t"
689         "movq   %%mm1, %%mm3\n\t"
690         "movq   %%mm4, %%mm5\n\t"
691         "punpcklbw %%mm7, %%mm0\n\t"
692         "punpcklbw %%mm7, %%mm1\n\t"
693         "punpckhbw %%mm7, %%mm2\n\t"
694         "punpckhbw %%mm7, %%mm3\n\t"
695         "punpcklbw %%mm7, %%mm4\n\t"
696         "punpckhbw %%mm7, %%mm5\n\t"
697         "paddusw %%mm1, %%mm0\n\t"
698         "paddusw %%mm3, %%mm2\n\t"
699         "psrlw  $1, %%mm0\n\t"
700         "psrlw  $1, %%mm2\n\t"
701         "paddusw %%mm4, %%mm0\n\t"
702         "paddusw %%mm5, %%mm2\n\t"
703         "psrlw  $1, %%mm0\n\t"
704         "psrlw  $1, %%mm2\n\t"
705         "packuswb  %%mm2, %%mm0\n\t"
706         "movq   %%mm0, %0\n\t"
707         :"=m"(*p)
708         :"m"(*pix)
709         :"memory");
710    pix += line_size;
711    p +=   line_size;
712  } while (--h);
713  emms();
714 }
715
716 static void   avg_no_rnd_pixels_y2_mmx( UINT8  *block, const UINT8 *pixels, int line_size, int h)
717 {
718   UINT8  *p;
719   const UINT8 *pix;
720   p = block;
721   pix = pixels;
722   __asm __volatile(
723       "pxor     %%mm7, %%mm7\n\t":::"memory");
724   do {
725     __asm __volatile(
726         "movq   %1, %%mm0\n\t"
727         "movq   %2, %%mm1\n\t"
728         "movq   %0, %%mm4\n\t"
729         "movq   %%mm0, %%mm2\n\t"
730         "movq   %%mm1, %%mm3\n\t"
731         "movq   %%mm4, %%mm5\n\t"
732         "punpcklbw %%mm7, %%mm0\n\t"
733         "punpcklbw %%mm7, %%mm1\n\t"
734         "punpckhbw %%mm7, %%mm2\n\t"
735         "punpckhbw %%mm7, %%mm3\n\t"
736         "punpcklbw %%mm7, %%mm4\n\t"
737         "punpckhbw %%mm7, %%mm5\n\t"
738         "paddusw %%mm1, %%mm0\n\t"
739         "paddusw %%mm3, %%mm2\n\t"
740         "psrlw  $1, %%mm0\n\t"
741         "psrlw  $1, %%mm2\n\t"
742         "paddusw %%mm4, %%mm0\n\t"
743         "paddusw %%mm5, %%mm2\n\t"
744         "psrlw  $1, %%mm0\n\t"
745         "psrlw  $1, %%mm2\n\t"
746         "packuswb  %%mm2, %%mm0\n\t"
747         "movq   %%mm0, %0\n\t"
748         :"=m"(*p)
749         :"m"(*pix), "m"(*(pix+line_size))
750         :"memory");
751    pix += line_size;
752    p +=   line_size ;
753   } while(--h);
754   emms();
755 }
756
757 static void   avg_no_rnd_pixels_xy2_mmx( UINT8  *block, const UINT8 *pixels, int line_size, int h)
758 {
759   UINT8  *p;
760   const UINT8 *pix;
761   p = block;
762   pix = pixels;
763   __asm __volatile(
764         "pxor   %%mm7, %%mm7\n\t"
765         "movq   %0, %%mm6\n\t"
766         ::"m"(mm_wone[0]):"memory");
767   do {
768     __asm __volatile(
769         "movq   %1, %%mm0\n\t"
770         "movq   %2, %%mm1\n\t"
771         "movq   1%1, %%mm4\n\t"
772         "movq   1%2, %%mm5\n\t"
773         "movq   %%mm0, %%mm2\n\t"
774         "movq   %%mm1, %%mm3\n\t"
775         "punpcklbw %%mm7, %%mm0\n\t"
776         "punpcklbw %%mm7, %%mm1\n\t"
777         "punpckhbw %%mm7, %%mm2\n\t"
778         "punpckhbw %%mm7, %%mm3\n\t"
779         "paddusw %%mm1, %%mm0\n\t"
780         "paddusw %%mm3, %%mm2\n\t"
781         "movq   %%mm4, %%mm1\n\t"
782         "movq   %%mm5, %%mm3\n\t"
783         "punpcklbw %%mm7, %%mm4\n\t"
784         "punpcklbw %%mm7, %%mm5\n\t"
785         "punpckhbw %%mm7, %%mm1\n\t"
786         "punpckhbw %%mm7, %%mm3\n\t"
787         "paddusw %%mm5, %%mm4\n\t"
788         "paddusw %%mm3, %%mm1\n\t"
789         "paddusw %%mm6, %%mm4\n\t"
790         "paddusw %%mm6, %%mm1\n\t"
791         "paddusw %%mm4, %%mm0\n\t"
792         "paddusw %%mm1, %%mm2\n\t"
793         "movq   %0, %%mm1\n\t"
794         "psrlw  $2, %%mm0\n\t"
795         "movq   %%mm1, %%mm3\n\t"
796         "psrlw  $2, %%mm2\n\t"
797         "punpcklbw %%mm7, %%mm1\n\t"
798         "punpckhbw %%mm7, %%mm3\n\t"
799         "paddusw %%mm1, %%mm0\n\t"
800         "paddusw %%mm3, %%mm2\n\t"
801         "psrlw  $1, %%mm0\n\t"
802         "psrlw  $1, %%mm2\n\t"
803         "packuswb  %%mm2, %%mm0\n\t"
804         "movq   %%mm0, %0\n\t"
805         :"=m"(*p)
806         :"m"(*pix),
807          "m"(*(pix+line_size))
808         :"memory");
809    pix += line_size;
810    p += line_size;
811   } while(--h);
812   emms();
813 }
814
815 static void sub_pixels_mmx( DCTELEM  *block, const UINT8 *pixels, int line_size, int h)
816 {
817   DCTELEM  *p;
818   const UINT8 *pix;
819   p = block;
820   pix = pixels;
821   __asm __volatile("pxor %%mm7, %%mm7":::"memory");
822   do {
823     __asm __volatile(
824         "movq   %0, %%mm0\n\t"
825         "movq   %1, %%mm2\n\t"
826         "movq   8%0, %%mm1\n\t"
827         "movq   %%mm2, %%mm3\n\t"
828         "punpcklbw %%mm7, %%mm2\n\t"
829         "punpckhbw %%mm7, %%mm3\n\t"
830         "psubsw %%mm2, %%mm0\n\t"
831         "psubsw %%mm3, %%mm1\n\t"
832         "movq   %%mm0, %0\n\t"
833         "movq   %%mm1, 8%0\n\t"
834         :"=m"(*p)
835         :"m"(*pix)
836         :"memory");
837    pix += line_size;
838    p +=   8;
839   } while (--h);
840   emms();
841 }
842
843 static void sub_pixels_x2_mmx( DCTELEM  *block, const UINT8 *pixels, int line_size, int h)
844 {
845   DCTELEM  *p;
846   const UINT8 *pix;
847   p = block;
848   pix = pixels;
849   __asm __volatile(
850       "pxor     %%mm7, %%mm7\n\t"
851       "movq     %0, %%mm6"
852       ::"m"(mm_wone[0]):"memory");
853   do {
854     __asm __volatile(
855         "movq   %0, %%mm0\n\t"
856         "movq   %1, %%mm2\n\t"
857         "movq   8%0, %%mm1\n\t"
858         "movq   1%1, %%mm4\n\t"
859         "movq   %%mm2, %%mm3\n\t"
860         "movq   %%mm4, %%mm5\n\t"
861         "punpcklbw %%mm7, %%mm2\n\t"
862         "punpckhbw %%mm7, %%mm3\n\t"
863         "punpcklbw %%mm7, %%mm4\n\t"
864         "punpckhbw %%mm7, %%mm5\n\t"
865         "paddusw %%mm4, %%mm2\n\t"
866         "paddusw %%mm5, %%mm3\n\t"
867         "paddusw %%mm6, %%mm2\n\t"
868         "paddusw %%mm6, %%mm3\n\t"
869         "psrlw  $1, %%mm2\n\t"
870         "psrlw  $1, %%mm3\n\t"
871         "psubsw %%mm2, %%mm0\n\t"
872         "psubsw %%mm3, %%mm1\n\t"
873         "movq   %%mm0, %0\n\t"
874         "movq   %%mm1, 8%0\n\t"
875         :"=m"(*p)
876         :"m"(*pix)
877         :"memory");
878    pix += line_size;
879    p +=   8;
880  } while (--h);
881  emms();
882 }
883
884 static void sub_pixels_y2_mmx( DCTELEM  *block, const UINT8 *pixels, int line_size, int h)
885 {
886   DCTELEM  *p;
887   const UINT8 *pix;
888   p = block;
889   pix = pixels;
890   __asm __volatile(
891       "pxor     %%mm7, %%mm7\n\t"
892       "movq     %0, %%mm6"
893       ::"m"(mm_wone[0]):"memory");
894   do {
895     __asm __volatile(
896         "movq   %0, %%mm0\n\t"
897         "movq   %1, %%mm2\n\t"
898         "movq   8%0, %%mm1\n\t"
899         "movq   %2, %%mm4\n\t"
900         "movq   %%mm2, %%mm3\n\t"
901         "movq   %%mm4, %%mm5\n\t"
902         "punpcklbw %%mm7, %%mm2\n\t"
903         "punpckhbw %%mm7, %%mm3\n\t"
904         "punpcklbw %%mm7, %%mm4\n\t"
905         "punpckhbw %%mm7, %%mm5\n\t"
906         "paddusw %%mm4, %%mm2\n\t"
907         "paddusw %%mm5, %%mm3\n\t"
908         "paddusw %%mm6, %%mm2\n\t"
909         "paddusw %%mm6, %%mm3\n\t"
910         "psrlw  $1, %%mm2\n\t"
911         "psrlw  $1, %%mm3\n\t"
912         "psubsw %%mm2, %%mm0\n\t"
913         "psubsw %%mm3, %%mm1\n\t"
914         "movq   %%mm0, %0\n\t"
915         "movq   %%mm1, 8%0\n\t"
916         :"=m"(*p)
917         :"m"(*pix), "m"(*(pix+line_size))
918         :"memory");
919    pix += line_size;
920    p +=   8;
921  } while (--h);
922  emms();
923 }
924
925 static void   sub_pixels_xy2_mmx( DCTELEM  *block, const UINT8 *pixels, int line_size, int h)
926 {
927   DCTELEM  *p;
928   const UINT8 *pix;
929   p = block;
930   pix = pixels;
931   __asm __volatile(
932         "pxor   %%mm7, %%mm7\n\t"
933         "movq   %0, %%mm6\n\t"
934         ::"m"(mm_wtwo[0]):"memory");
935   do {
936     __asm __volatile(
937         "movq   %1, %%mm0\n\t"
938         "movq   %2, %%mm1\n\t"
939         "movq   1%1, %%mm4\n\t"
940         "movq   1%2, %%mm5\n\t"
941         "movq   %%mm0, %%mm2\n\t"
942         "movq   %%mm1, %%mm3\n\t"
943         "punpcklbw %%mm7, %%mm0\n\t"
944         "punpcklbw %%mm7, %%mm1\n\t"
945         "punpckhbw %%mm7, %%mm2\n\t"
946         "punpckhbw %%mm7, %%mm3\n\t"
947         "paddusw %%mm1, %%mm0\n\t"
948         "paddusw %%mm3, %%mm2\n\t"
949         "movq   %%mm4, %%mm1\n\t"
950         "movq   %%mm5, %%mm3\n\t"
951         "punpcklbw %%mm7, %%mm4\n\t"
952         "punpcklbw %%mm7, %%mm5\n\t"
953         "punpckhbw %%mm7, %%mm1\n\t"
954         "punpckhbw %%mm7, %%mm3\n\t"
955         "paddusw %%mm5, %%mm4\n\t"
956         "paddusw %%mm3, %%mm1\n\t"
957         "paddusw %%mm6, %%mm4\n\t"
958         "paddusw %%mm6, %%mm1\n\t"
959         "paddusw %%mm4, %%mm0\n\t"
960         "paddusw %%mm1, %%mm2\n\t"
961         "movq   %0, %%mm1\n\t"
962         "movq   8%0, %%mm3\n\t"
963         "psrlw  $2, %%mm0\n\t"
964         "psrlw  $2, %%mm2\n\t"
965         "psubsw %%mm0, %%mm1\n\t"
966         "psubsw %%mm2, %%mm3\n\t"
967         "movq   %%mm1, %0\n\t"
968         "movq   %%mm3, 8%0\n\t"
969         :"=m"(*p)
970         :"m"(*pix),
971          "m"(*(pix+line_size))
972         :"memory");
973    pix += line_size;
974    p +=   8 ;
975   } while(--h);
976   emms();
977 }
978
979 void dsputil_init_mmx(void)
980 {
981     mm_flags = mm_support();
982 #if 0
983     printf("CPU flags:");
984     if (mm_flags & MM_MMX)
985         printf(" mmx");
986     if (mm_flags & MM_MMXEXT)
987         printf(" mmxext");
988     if (mm_flags & MM_3DNOW)
989         printf(" 3dnow");
990     if (mm_flags & MM_SSE)
991         printf(" sse");
992     if (mm_flags & MM_SSE2)
993         printf(" sse2");
994     printf("\n");
995 #endif
996
997     if (mm_flags & MM_MMX) {
998         get_pixels = get_pixels_mmx;
999         put_pixels_clamped = put_pixels_clamped_mmx;
1000         add_pixels_clamped = add_pixels_clamped_mmx;
1001         
1002         pix_abs16x16 = pix_abs16x16_mmx;
1003         pix_abs16x16_x2 = pix_abs16x16_x2_mmx;
1004         pix_abs16x16_y2 = pix_abs16x16_y2_mmx;
1005         pix_abs16x16_xy2 = pix_abs16x16_xy2_mmx;
1006         av_fdct = fdct_mmx;
1007
1008         put_pixels_tab[0] = put_pixels_mmx;
1009         put_pixels_tab[1] = put_pixels_x2_mmx;
1010         put_pixels_tab[2] = put_pixels_y2_mmx;
1011         put_pixels_tab[3] = put_pixels_xy2_mmx;
1012
1013         put_no_rnd_pixels_tab[0] = put_pixels_mmx;
1014         put_no_rnd_pixels_tab[1] = put_no_rnd_pixels_x2_mmx;
1015         put_no_rnd_pixels_tab[2] = put_no_rnd_pixels_y2_mmx;
1016         put_no_rnd_pixels_tab[3] = put_no_rnd_pixels_xy2_mmx;
1017         
1018         avg_pixels_tab[0] = avg_pixels_mmx;
1019         avg_pixels_tab[1] = avg_pixels_x2_mmx;
1020         avg_pixels_tab[2] = avg_pixels_y2_mmx;
1021         avg_pixels_tab[3] = avg_pixels_xy2_mmx;
1022
1023         avg_no_rnd_pixels_tab[0] = avg_no_rnd_pixels_mmx;
1024         avg_no_rnd_pixels_tab[1] = avg_no_rnd_pixels_x2_mmx;
1025         avg_no_rnd_pixels_tab[2] = avg_no_rnd_pixels_y2_mmx;
1026         avg_no_rnd_pixels_tab[3] = avg_no_rnd_pixels_xy2_mmx;
1027         
1028         sub_pixels_tab[0] = sub_pixels_mmx;
1029         sub_pixels_tab[1] = sub_pixels_x2_mmx;
1030         sub_pixels_tab[2] = sub_pixels_y2_mmx;
1031         sub_pixels_tab[3] = sub_pixels_xy2_mmx;
1032
1033         if (mm_flags & MM_MMXEXT) {
1034             pix_abs16x16 = pix_abs16x16_sse;
1035         }
1036
1037         if (mm_flags & MM_SSE) {
1038             put_pixels_tab[1] = put_pixels_x2_sse;
1039             put_pixels_tab[2] = put_pixels_y2_sse;
1040             
1041             avg_pixels_tab[0] = avg_pixels_sse;
1042             avg_pixels_tab[1] = avg_pixels_x2_sse;
1043             avg_pixels_tab[2] = avg_pixels_y2_sse;
1044             avg_pixels_tab[3] = avg_pixels_xy2_sse;
1045
1046             sub_pixels_tab[1] = sub_pixels_x2_sse;
1047             sub_pixels_tab[2] = sub_pixels_y2_sse;
1048         } else if (mm_flags & MM_3DNOW) {
1049             put_pixels_tab[1] = put_pixels_x2_3dnow;
1050             put_pixels_tab[2] = put_pixels_y2_3dnow;
1051             
1052             avg_pixels_tab[0] = avg_pixels_3dnow;
1053             avg_pixels_tab[1] = avg_pixels_x2_3dnow;
1054             avg_pixels_tab[2] = avg_pixels_y2_3dnow;
1055             avg_pixels_tab[3] = avg_pixels_xy2_3dnow;
1056
1057             sub_pixels_tab[1] = sub_pixels_x2_3dnow;
1058             sub_pixels_tab[2] = sub_pixels_y2_3dnow;
1059         }
1060     }
1061 }