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