Update to MPlayer SVN rev 29473 and FFmpeg SVN rev 19572.
[vaapi:athaifas-mplayer.git] / libswscale / .svn / text-base / rgb2rgb_template.c.svn-base
1 /*
2  * software RGB to RGB converter
3  * pluralize by software PAL8 to RGB converter
4  *              software YUV to YUV converter
5  *              software YUV to RGB converter
6  * Written by Nick Kurshev.
7  * palette & YUV & runtime CPU stuff by Michael (michaelni@gmx.at)
8  * lot of big-endian byte order fixes by Alex Beregszaszi
9  *
10  * This file is part of FFmpeg.
11  *
12  * FFmpeg is free software; you can redistribute it and/or modify
13  * it under the terms of the GNU General Public License as published by
14  * the Free Software Foundation; either version 2 of the License, or
15  * (at your option) any later version.
16  *
17  * FFmpeg is distributed in the hope that it will be useful,
18  * but WITHOUT ANY WARRANTY; without even the implied warranty of
19  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
20  * GNU General Public License for more details.
21  *
22  * You should have received a copy of the GNU General Public License
23  * along with FFmpeg; if not, write to the Free Software
24  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
25  *
26  * The C code (not assembly, MMX, ...) of this file can be used
27  * under the LGPL license.
28  */
29
30 #include <stddef.h>
31
32 #undef PREFETCH
33 #undef MOVNTQ
34 #undef EMMS
35 #undef SFENCE
36 #undef MMREG_SIZE
37 #undef PREFETCHW
38 #undef PAVGB
39
40 #if HAVE_SSE2
41 #define MMREG_SIZE 16
42 #else
43 #define MMREG_SIZE 8
44 #endif
45
46 #if HAVE_AMD3DNOW
47 #define PREFETCH  "prefetch"
48 #define PREFETCHW "prefetchw"
49 #define PAVGB     "pavgusb"
50 #elif HAVE_MMX2
51 #define PREFETCH "prefetchnta"
52 #define PREFETCHW "prefetcht0"
53 #define PAVGB     "pavgb"
54 #else
55 #define PREFETCH  " # nop"
56 #define PREFETCHW " # nop"
57 #endif
58
59 #if HAVE_AMD3DNOW
60 /* On K6 femms is faster than emms. On K7 femms is directly mapped to emms. */
61 #define EMMS     "femms"
62 #else
63 #define EMMS     "emms"
64 #endif
65
66 #if HAVE_MMX2
67 #define MOVNTQ "movntq"
68 #define SFENCE "sfence"
69 #else
70 #define MOVNTQ "movq"
71 #define SFENCE " # nop"
72 #endif
73
74 static inline void RENAME(rgb24tobgr32)(const uint8_t *src, uint8_t *dst, long src_size)
75 {
76     uint8_t *dest = dst;
77     const uint8_t *s = src;
78     const uint8_t *end;
79     #if HAVE_MMX
80         const uint8_t *mm_end;
81     #endif
82     end = s + src_size;
83     #if HAVE_MMX
84         __asm__ volatile(PREFETCH"    %0"::"m"(*s):"memory");
85         mm_end = end - 23;
86         __asm__ volatile("movq        %0, %%mm7"::"m"(mask32a):"memory");
87         while (s < mm_end)
88         {
89             __asm__ volatile(
90             PREFETCH"    32%1           \n\t"
91             "movd          %1, %%mm0    \n\t"
92             "punpckldq    3%1, %%mm0    \n\t"
93             "movd         6%1, %%mm1    \n\t"
94             "punpckldq    9%1, %%mm1    \n\t"
95             "movd        12%1, %%mm2    \n\t"
96             "punpckldq   15%1, %%mm2    \n\t"
97             "movd        18%1, %%mm3    \n\t"
98             "punpckldq   21%1, %%mm3    \n\t"
99             "por        %%mm7, %%mm0    \n\t"
100             "por        %%mm7, %%mm1    \n\t"
101             "por        %%mm7, %%mm2    \n\t"
102             "por        %%mm7, %%mm3    \n\t"
103             MOVNTQ"     %%mm0,   %0     \n\t"
104             MOVNTQ"     %%mm1,  8%0     \n\t"
105             MOVNTQ"     %%mm2, 16%0     \n\t"
106             MOVNTQ"     %%mm3, 24%0"
107             :"=m"(*dest)
108             :"m"(*s)
109             :"memory");
110             dest += 32;
111             s += 24;
112         }
113         __asm__ volatile(SFENCE:::"memory");
114         __asm__ volatile(EMMS:::"memory");
115     #endif
116     while (s < end)
117     {
118     #if HAVE_BIGENDIAN
119         /* RGB24 (= R,G,B) -> RGB32 (= A,B,G,R) */
120         *dest++ = 255;
121         *dest++ = s[2];
122         *dest++ = s[1];
123         *dest++ = s[0];
124         s+=3;
125     #else
126         *dest++ = *s++;
127         *dest++ = *s++;
128         *dest++ = *s++;
129         *dest++ = 255;
130     #endif
131     }
132 }
133
134 static inline void RENAME(rgb32tobgr24)(const uint8_t *src, uint8_t *dst, long src_size)
135 {
136     uint8_t *dest = dst;
137     const uint8_t *s = src;
138     const uint8_t *end;
139 #if HAVE_MMX
140     const uint8_t *mm_end;
141 #endif
142     end = s + src_size;
143 #if HAVE_MMX
144     __asm__ volatile(PREFETCH"    %0"::"m"(*s):"memory");
145     mm_end = end - 31;
146     while (s < mm_end)
147     {
148         __asm__ volatile(
149         PREFETCH"    32%1           \n\t"
150         "movq          %1, %%mm0    \n\t"
151         "movq         8%1, %%mm1    \n\t"
152         "movq        16%1, %%mm4    \n\t"
153         "movq        24%1, %%mm5    \n\t"
154         "movq       %%mm0, %%mm2    \n\t"
155         "movq       %%mm1, %%mm3    \n\t"
156         "movq       %%mm4, %%mm6    \n\t"
157         "movq       %%mm5, %%mm7    \n\t"
158         "psrlq         $8, %%mm2    \n\t"
159         "psrlq         $8, %%mm3    \n\t"
160         "psrlq         $8, %%mm6    \n\t"
161         "psrlq         $8, %%mm7    \n\t"
162         "pand          %2, %%mm0    \n\t"
163         "pand          %2, %%mm1    \n\t"
164         "pand          %2, %%mm4    \n\t"
165         "pand          %2, %%mm5    \n\t"
166         "pand          %3, %%mm2    \n\t"
167         "pand          %3, %%mm3    \n\t"
168         "pand          %3, %%mm6    \n\t"
169         "pand          %3, %%mm7    \n\t"
170         "por        %%mm2, %%mm0    \n\t"
171         "por        %%mm3, %%mm1    \n\t"
172         "por        %%mm6, %%mm4    \n\t"
173         "por        %%mm7, %%mm5    \n\t"
174
175         "movq       %%mm1, %%mm2    \n\t"
176         "movq       %%mm4, %%mm3    \n\t"
177         "psllq        $48, %%mm2    \n\t"
178         "psllq        $32, %%mm3    \n\t"
179         "pand          %4, %%mm2    \n\t"
180         "pand          %5, %%mm3    \n\t"
181         "por        %%mm2, %%mm0    \n\t"
182         "psrlq        $16, %%mm1    \n\t"
183         "psrlq        $32, %%mm4    \n\t"
184         "psllq        $16, %%mm5    \n\t"
185         "por        %%mm3, %%mm1    \n\t"
186         "pand          %6, %%mm5    \n\t"
187         "por        %%mm5, %%mm4    \n\t"
188
189         MOVNTQ"     %%mm0,   %0     \n\t"
190         MOVNTQ"     %%mm1,  8%0     \n\t"
191         MOVNTQ"     %%mm4, 16%0"
192         :"=m"(*dest)
193         :"m"(*s),"m"(mask24l),
194          "m"(mask24h),"m"(mask24hh),"m"(mask24hhh),"m"(mask24hhhh)
195         :"memory");
196         dest += 24;
197         s += 32;
198     }
199     __asm__ volatile(SFENCE:::"memory");
200     __asm__ volatile(EMMS:::"memory");
201 #endif
202     while (s < end)
203     {
204 #if HAVE_BIGENDIAN
205         /* RGB32 (= A,B,G,R) -> RGB24 (= R,G,B) */
206         s++;
207         dest[2] = *s++;
208         dest[1] = *s++;
209         dest[0] = *s++;
210         dest += 3;
211 #else
212         *dest++ = *s++;
213         *dest++ = *s++;
214         *dest++ = *s++;
215         s++;
216 #endif
217     }
218 }
219
220 /*
221  original by Strepto/Astral
222  ported to gcc & bugfixed: A'rpi
223  MMX2, 3DNOW optimization by Nick Kurshev
224  32-bit C version, and and&add trick by Michael Niedermayer
225 */
226 static inline void RENAME(rgb15to16)(const uint8_t *src, uint8_t *dst, long src_size)
227 {
228     register const uint8_t* s=src;
229     register uint8_t* d=dst;
230     register const uint8_t *end;
231     const uint8_t *mm_end;
232     end = s + src_size;
233 #if HAVE_MMX
234     __asm__ volatile(PREFETCH"    %0"::"m"(*s));
235     __asm__ volatile("movq        %0, %%mm4"::"m"(mask15s));
236     mm_end = end - 15;
237     while (s<mm_end)
238     {
239         __asm__ volatile(
240         PREFETCH"  32%1         \n\t"
241         "movq        %1, %%mm0  \n\t"
242         "movq       8%1, %%mm2  \n\t"
243         "movq     %%mm0, %%mm1  \n\t"
244         "movq     %%mm2, %%mm3  \n\t"
245         "pand     %%mm4, %%mm0  \n\t"
246         "pand     %%mm4, %%mm2  \n\t"
247         "paddw    %%mm1, %%mm0  \n\t"
248         "paddw    %%mm3, %%mm2  \n\t"
249         MOVNTQ"   %%mm0,  %0    \n\t"
250         MOVNTQ"   %%mm2, 8%0"
251         :"=m"(*d)
252         :"m"(*s)
253         );
254         d+=16;
255         s+=16;
256     }
257     __asm__ volatile(SFENCE:::"memory");
258     __asm__ volatile(EMMS:::"memory");
259 #endif
260     mm_end = end - 3;
261     while (s < mm_end)
262     {
263         register unsigned x= *((const uint32_t *)s);
264         *((uint32_t *)d) = (x&0x7FFF7FFF) + (x&0x7FE07FE0);
265         d+=4;
266         s+=4;
267     }
268     if (s < end)
269     {
270         register unsigned short x= *((const uint16_t *)s);
271         *((uint16_t *)d) = (x&0x7FFF) + (x&0x7FE0);
272     }
273 }
274
275 static inline void RENAME(rgb16to15)(const uint8_t *src, uint8_t *dst, long src_size)
276 {
277     register const uint8_t* s=src;
278     register uint8_t* d=dst;
279     register const uint8_t *end;
280     const uint8_t *mm_end;
281     end = s + src_size;
282 #if HAVE_MMX
283     __asm__ volatile(PREFETCH"    %0"::"m"(*s));
284     __asm__ volatile("movq        %0, %%mm7"::"m"(mask15rg));
285     __asm__ volatile("movq        %0, %%mm6"::"m"(mask15b));
286     mm_end = end - 15;
287     while (s<mm_end)
288     {
289         __asm__ volatile(
290         PREFETCH"  32%1         \n\t"
291         "movq        %1, %%mm0  \n\t"
292         "movq       8%1, %%mm2  \n\t"
293         "movq     %%mm0, %%mm1  \n\t"
294         "movq     %%mm2, %%mm3  \n\t"
295         "psrlq       $1, %%mm0  \n\t"
296         "psrlq       $1, %%mm2  \n\t"
297         "pand     %%mm7, %%mm0  \n\t"
298         "pand     %%mm7, %%mm2  \n\t"
299         "pand     %%mm6, %%mm1  \n\t"
300         "pand     %%mm6, %%mm3  \n\t"
301         "por      %%mm1, %%mm0  \n\t"
302         "por      %%mm3, %%mm2  \n\t"
303         MOVNTQ"   %%mm0,  %0    \n\t"
304         MOVNTQ"   %%mm2, 8%0"
305         :"=m"(*d)
306         :"m"(*s)
307         );
308         d+=16;
309         s+=16;
310     }
311     __asm__ volatile(SFENCE:::"memory");
312     __asm__ volatile(EMMS:::"memory");
313 #endif
314     mm_end = end - 3;
315     while (s < mm_end)
316     {
317         register uint32_t x= *((const uint32_t*)s);
318         *((uint32_t *)d) = ((x>>1)&0x7FE07FE0) | (x&0x001F001F);
319         s+=4;
320         d+=4;
321     }
322     if (s < end)
323     {
324         register uint16_t x= *((const uint16_t*)s);
325         *((uint16_t *)d) = ((x>>1)&0x7FE0) | (x&0x001F);
326     }
327 }
328
329 static inline void RENAME(rgb32to16)(const uint8_t *src, uint8_t *dst, long src_size)
330 {
331     const uint8_t *s = src;
332     const uint8_t *end;
333 #if HAVE_MMX
334     const uint8_t *mm_end;
335 #endif
336     uint16_t *d = (uint16_t *)dst;
337     end = s + src_size;
338 #if HAVE_MMX
339     mm_end = end - 15;
340 #if 1 //is faster only if multiplies are reasonably fast (FIXME figure out on which CPUs this is faster, on Athlon it is slightly faster)
341     __asm__ volatile(
342     "movq           %3, %%mm5   \n\t"
343     "movq           %4, %%mm6   \n\t"
344     "movq           %5, %%mm7   \n\t"
345     "jmp 2f                     \n\t"
346     ASMALIGN(4)
347     "1:                         \n\t"
348     PREFETCH"   32(%1)          \n\t"
349     "movd         (%1), %%mm0   \n\t"
350     "movd        4(%1), %%mm3   \n\t"
351     "punpckldq   8(%1), %%mm0   \n\t"
352     "punpckldq  12(%1), %%mm3   \n\t"
353     "movq        %%mm0, %%mm1   \n\t"
354     "movq        %%mm3, %%mm4   \n\t"
355     "pand        %%mm6, %%mm0   \n\t"
356     "pand        %%mm6, %%mm3   \n\t"
357     "pmaddwd     %%mm7, %%mm0   \n\t"
358     "pmaddwd     %%mm7, %%mm3   \n\t"
359     "pand        %%mm5, %%mm1   \n\t"
360     "pand        %%mm5, %%mm4   \n\t"
361     "por         %%mm1, %%mm0   \n\t"
362     "por         %%mm4, %%mm3   \n\t"
363     "psrld          $5, %%mm0   \n\t"
364     "pslld         $11, %%mm3   \n\t"
365     "por         %%mm3, %%mm0   \n\t"
366     MOVNTQ"      %%mm0, (%0)    \n\t"
367     "add           $16,  %1     \n\t"
368     "add            $8,  %0     \n\t"
369     "2:                         \n\t"
370     "cmp            %2,  %1     \n\t"
371     " jb            1b          \n\t"
372     : "+r" (d), "+r"(s)
373     : "r" (mm_end), "m" (mask3216g), "m" (mask3216br), "m" (mul3216)
374     );
375 #else
376     __asm__ volatile(PREFETCH"    %0"::"m"(*src):"memory");
377     __asm__ volatile(
378         "movq    %0, %%mm7    \n\t"
379         "movq    %1, %%mm6    \n\t"
380         ::"m"(red_16mask),"m"(green_16mask));
381     while (s < mm_end)
382     {
383         __asm__ volatile(
384         PREFETCH"    32%1           \n\t"
385         "movd          %1, %%mm0    \n\t"
386         "movd         4%1, %%mm3    \n\t"
387         "punpckldq    8%1, %%mm0    \n\t"
388         "punpckldq   12%1, %%mm3    \n\t"
389         "movq       %%mm0, %%mm1    \n\t"
390         "movq       %%mm0, %%mm2    \n\t"
391         "movq       %%mm3, %%mm4    \n\t"
392         "movq       %%mm3, %%mm5    \n\t"
393         "psrlq         $3, %%mm0    \n\t"
394         "psrlq         $3, %%mm3    \n\t"
395         "pand          %2, %%mm0    \n\t"
396         "pand          %2, %%mm3    \n\t"
397         "psrlq         $5, %%mm1    \n\t"
398         "psrlq         $5, %%mm4    \n\t"
399         "pand       %%mm6, %%mm1    \n\t"
400         "pand       %%mm6, %%mm4    \n\t"
401         "psrlq         $8, %%mm2    \n\t"
402         "psrlq         $8, %%mm5    \n\t"
403         "pand       %%mm7, %%mm2    \n\t"
404         "pand       %%mm7, %%mm5    \n\t"
405         "por        %%mm1, %%mm0    \n\t"
406         "por        %%mm4, %%mm3    \n\t"
407         "por        %%mm2, %%mm0    \n\t"
408         "por        %%mm5, %%mm3    \n\t"
409         "psllq        $16, %%mm3    \n\t"
410         "por        %%mm3, %%mm0    \n\t"
411         MOVNTQ"     %%mm0, %0       \n\t"
412         :"=m"(*d):"m"(*s),"m"(blue_16mask):"memory");
413         d += 4;
414         s += 16;
415     }
416 #endif
417     __asm__ volatile(SFENCE:::"memory");
418     __asm__ volatile(EMMS:::"memory");
419 #endif
420     while (s < end)
421     {
422         register int rgb = *(const uint32_t*)s; s += 4;
423         *d++ = ((rgb&0xFF)>>3) + ((rgb&0xFC00)>>5) + ((rgb&0xF80000)>>8);
424     }
425 }
426
427 static inline void RENAME(rgb32tobgr16)(const uint8_t *src, uint8_t *dst, long src_size)
428 {
429     const uint8_t *s = src;
430     const uint8_t *end;
431 #if HAVE_MMX
432     const uint8_t *mm_end;
433 #endif
434     uint16_t *d = (uint16_t *)dst;
435     end = s + src_size;
436 #if HAVE_MMX
437     __asm__ volatile(PREFETCH"    %0"::"m"(*src):"memory");
438     __asm__ volatile(
439         "movq          %0, %%mm7    \n\t"
440         "movq          %1, %%mm6    \n\t"
441         ::"m"(red_16mask),"m"(green_16mask));
442     mm_end = end - 15;
443     while (s < mm_end)
444     {
445         __asm__ volatile(
446         PREFETCH"    32%1           \n\t"
447         "movd          %1, %%mm0    \n\t"
448         "movd         4%1, %%mm3    \n\t"
449         "punpckldq    8%1, %%mm0    \n\t"
450         "punpckldq   12%1, %%mm3    \n\t"
451         "movq       %%mm0, %%mm1    \n\t"
452         "movq       %%mm0, %%mm2    \n\t"
453         "movq       %%mm3, %%mm4    \n\t"
454         "movq       %%mm3, %%mm5    \n\t"
455         "psllq         $8, %%mm0    \n\t"
456         "psllq         $8, %%mm3    \n\t"
457         "pand       %%mm7, %%mm0    \n\t"
458         "pand       %%mm7, %%mm3    \n\t"
459         "psrlq         $5, %%mm1    \n\t"
460         "psrlq         $5, %%mm4    \n\t"
461         "pand       %%mm6, %%mm1    \n\t"
462         "pand       %%mm6, %%mm4    \n\t"
463         "psrlq        $19, %%mm2    \n\t"
464         "psrlq        $19, %%mm5    \n\t"
465         "pand          %2, %%mm2    \n\t"
466         "pand          %2, %%mm5    \n\t"
467         "por        %%mm1, %%mm0    \n\t"
468         "por        %%mm4, %%mm3    \n\t"
469         "por        %%mm2, %%mm0    \n\t"
470         "por        %%mm5, %%mm3    \n\t"
471         "psllq        $16, %%mm3    \n\t"
472         "por        %%mm3, %%mm0    \n\t"
473         MOVNTQ"     %%mm0, %0       \n\t"
474         :"=m"(*d):"m"(*s),"m"(blue_16mask):"memory");
475         d += 4;
476         s += 16;
477     }
478     __asm__ volatile(SFENCE:::"memory");
479     __asm__ volatile(EMMS:::"memory");
480 #endif
481     while (s < end)
482     {
483         register int rgb = *(const uint32_t*)s; s += 4;
484         *d++ = ((rgb&0xF8)<<8) + ((rgb&0xFC00)>>5) + ((rgb&0xF80000)>>19);
485     }
486 }
487
488 static inline void RENAME(rgb32to15)(const uint8_t *src, uint8_t *dst, long src_size)
489 {
490     const uint8_t *s = src;
491     const uint8_t *end;
492 #if HAVE_MMX
493     const uint8_t *mm_end;
494 #endif
495     uint16_t *d = (uint16_t *)dst;
496     end = s + src_size;
497 #if HAVE_MMX
498     mm_end = end - 15;
499 #if 1 //is faster only if multiplies are reasonably fast (FIXME figure out on which CPUs this is faster, on Athlon it is slightly faster)
500     __asm__ volatile(
501     "movq           %3, %%mm5   \n\t"
502     "movq           %4, %%mm6   \n\t"
503     "movq           %5, %%mm7   \n\t"
504     "jmp            2f          \n\t"
505     ASMALIGN(4)
506     "1:                         \n\t"
507     PREFETCH"   32(%1)          \n\t"
508     "movd         (%1), %%mm0   \n\t"
509     "movd        4(%1), %%mm3   \n\t"
510     "punpckldq   8(%1), %%mm0   \n\t"
511     "punpckldq  12(%1), %%mm3   \n\t"
512     "movq        %%mm0, %%mm1   \n\t"
513     "movq        %%mm3, %%mm4   \n\t"
514     "pand        %%mm6, %%mm0   \n\t"
515     "pand        %%mm6, %%mm3   \n\t"
516     "pmaddwd     %%mm7, %%mm0   \n\t"
517     "pmaddwd     %%mm7, %%mm3   \n\t"
518     "pand        %%mm5, %%mm1   \n\t"
519     "pand        %%mm5, %%mm4   \n\t"
520     "por         %%mm1, %%mm0   \n\t"
521     "por         %%mm4, %%mm3   \n\t"
522     "psrld          $6, %%mm0   \n\t"
523     "pslld         $10, %%mm3   \n\t"
524     "por         %%mm3, %%mm0   \n\t"
525     MOVNTQ"      %%mm0, (%0)    \n\t"
526     "add           $16,  %1     \n\t"
527     "add            $8,  %0     \n\t"
528     "2:                         \n\t"
529     "cmp            %2,  %1     \n\t"
530     " jb            1b          \n\t"
531     : "+r" (d), "+r"(s)
532     : "r" (mm_end), "m" (mask3215g), "m" (mask3216br), "m" (mul3215)
533     );
534 #else
535     __asm__ volatile(PREFETCH"    %0"::"m"(*src):"memory");
536     __asm__ volatile(
537         "movq          %0, %%mm7    \n\t"
538         "movq          %1, %%mm6    \n\t"
539         ::"m"(red_15mask),"m"(green_15mask));
540     while (s < mm_end)
541     {
542         __asm__ volatile(
543         PREFETCH"    32%1           \n\t"
544         "movd          %1, %%mm0    \n\t"
545         "movd         4%1, %%mm3    \n\t"
546         "punpckldq    8%1, %%mm0    \n\t"
547         "punpckldq   12%1, %%mm3    \n\t"
548         "movq       %%mm0, %%mm1    \n\t"
549         "movq       %%mm0, %%mm2    \n\t"
550         "movq       %%mm3, %%mm4    \n\t"
551         "movq       %%mm3, %%mm5    \n\t"
552         "psrlq         $3, %%mm0    \n\t"
553         "psrlq         $3, %%mm3    \n\t"
554         "pand          %2, %%mm0    \n\t"
555         "pand          %2, %%mm3    \n\t"
556         "psrlq         $6, %%mm1    \n\t"
557         "psrlq         $6, %%mm4    \n\t"
558         "pand       %%mm6, %%mm1    \n\t"
559         "pand       %%mm6, %%mm4    \n\t"
560         "psrlq         $9, %%mm2    \n\t"
561         "psrlq         $9, %%mm5    \n\t"
562         "pand       %%mm7, %%mm2    \n\t"
563         "pand       %%mm7, %%mm5    \n\t"
564         "por        %%mm1, %%mm0    \n\t"
565         "por        %%mm4, %%mm3    \n\t"
566         "por        %%mm2, %%mm0    \n\t"
567         "por        %%mm5, %%mm3    \n\t"
568         "psllq        $16, %%mm3    \n\t"
569         "por        %%mm3, %%mm0    \n\t"
570         MOVNTQ"     %%mm0, %0       \n\t"
571         :"=m"(*d):"m"(*s),"m"(blue_15mask):"memory");
572         d += 4;
573         s += 16;
574     }
575 #endif
576     __asm__ volatile(SFENCE:::"memory");
577     __asm__ volatile(EMMS:::"memory");
578 #endif
579     while (s < end)
580     {
581         register int rgb = *(const uint32_t*)s; s += 4;
582         *d++ = ((rgb&0xFF)>>3) + ((rgb&0xF800)>>6) + ((rgb&0xF80000)>>9);
583     }
584 }
585
586 static inline void RENAME(rgb32tobgr15)(const uint8_t *src, uint8_t *dst, long src_size)
587 {
588     const uint8_t *s = src;
589     const uint8_t *end;
590 #if HAVE_MMX
591     const uint8_t *mm_end;
592 #endif
593     uint16_t *d = (uint16_t *)dst;
594     end = s + src_size;
595 #if HAVE_MMX
596     __asm__ volatile(PREFETCH"    %0"::"m"(*src):"memory");
597     __asm__ volatile(
598         "movq          %0, %%mm7    \n\t"
599         "movq          %1, %%mm6    \n\t"
600         ::"m"(red_15mask),"m"(green_15mask));
601     mm_end = end - 15;
602     while (s < mm_end)
603     {
604         __asm__ volatile(
605         PREFETCH"    32%1           \n\t"
606         "movd          %1, %%mm0    \n\t"
607         "movd         4%1, %%mm3    \n\t"
608         "punpckldq    8%1, %%mm0    \n\t"
609         "punpckldq   12%1, %%mm3    \n\t"
610         "movq       %%mm0, %%mm1    \n\t"
611         "movq       %%mm0, %%mm2    \n\t"
612         "movq       %%mm3, %%mm4    \n\t"
613         "movq       %%mm3, %%mm5    \n\t"
614         "psllq         $7, %%mm0    \n\t"
615         "psllq         $7, %%mm3    \n\t"
616         "pand       %%mm7, %%mm0    \n\t"
617         "pand       %%mm7, %%mm3    \n\t"
618         "psrlq         $6, %%mm1    \n\t"
619         "psrlq         $6, %%mm4    \n\t"
620         "pand       %%mm6, %%mm1    \n\t"
621         "pand       %%mm6, %%mm4    \n\t"
622         "psrlq        $19, %%mm2    \n\t"
623         "psrlq        $19, %%mm5    \n\t"
624         "pand          %2, %%mm2    \n\t"
625         "pand          %2, %%mm5    \n\t"
626         "por        %%mm1, %%mm0    \n\t"
627         "por        %%mm4, %%mm3    \n\t"
628         "por        %%mm2, %%mm0    \n\t"
629         "por        %%mm5, %%mm3    \n\t"
630         "psllq        $16, %%mm3    \n\t"
631         "por        %%mm3, %%mm0    \n\t"
632         MOVNTQ"     %%mm0, %0       \n\t"
633         :"=m"(*d):"m"(*s),"m"(blue_15mask):"memory");
634         d += 4;
635         s += 16;
636     }
637     __asm__ volatile(SFENCE:::"memory");
638     __asm__ volatile(EMMS:::"memory");
639 #endif
640     while (s < end)
641     {
642         register int rgb = *(const uint32_t*)s; s += 4;
643         *d++ = ((rgb&0xF8)<<7) + ((rgb&0xF800)>>6) + ((rgb&0xF80000)>>19);
644     }
645 }
646
647 static inline void RENAME(rgb24tobgr16)(const uint8_t *src, uint8_t *dst, long src_size)
648 {
649     const uint8_t *s = src;
650     const uint8_t *end;
651 #if HAVE_MMX
652     const uint8_t *mm_end;
653 #endif
654     uint16_t *d = (uint16_t *)dst;
655     end = s + src_size;
656 #if HAVE_MMX
657     __asm__ volatile(PREFETCH"    %0"::"m"(*src):"memory");
658     __asm__ volatile(
659         "movq         %0, %%mm7     \n\t"
660         "movq         %1, %%mm6     \n\t"
661         ::"m"(red_16mask),"m"(green_16mask));
662     mm_end = end - 11;
663     while (s < mm_end)
664     {
665         __asm__ volatile(
666         PREFETCH"    32%1           \n\t"
667         "movd          %1, %%mm0    \n\t"
668         "movd         3%1, %%mm3    \n\t"
669         "punpckldq    6%1, %%mm0    \n\t"
670         "punpckldq    9%1, %%mm3    \n\t"
671         "movq       %%mm0, %%mm1    \n\t"
672         "movq       %%mm0, %%mm2    \n\t"
673         "movq       %%mm3, %%mm4    \n\t"
674         "movq       %%mm3, %%mm5    \n\t"
675         "psrlq         $3, %%mm0    \n\t"
676         "psrlq         $3, %%mm3    \n\t"
677         "pand          %2, %%mm0    \n\t"
678         "pand          %2, %%mm3    \n\t"
679         "psrlq         $5, %%mm1    \n\t"
680         "psrlq         $5, %%mm4    \n\t"
681         "pand       %%mm6, %%mm1    \n\t"
682         "pand       %%mm6, %%mm4    \n\t"
683         "psrlq         $8, %%mm2    \n\t"
684         "psrlq         $8, %%mm5    \n\t"
685         "pand       %%mm7, %%mm2    \n\t"
686         "pand       %%mm7, %%mm5    \n\t"
687         "por        %%mm1, %%mm0    \n\t"
688         "por        %%mm4, %%mm3    \n\t"
689         "por        %%mm2, %%mm0    \n\t"
690         "por        %%mm5, %%mm3    \n\t"
691         "psllq        $16, %%mm3    \n\t"
692         "por        %%mm3, %%mm0    \n\t"
693         MOVNTQ"     %%mm0, %0       \n\t"
694         :"=m"(*d):"m"(*s),"m"(blue_16mask):"memory");
695         d += 4;
696         s += 12;
697     }
698     __asm__ volatile(SFENCE:::"memory");
699     __asm__ volatile(EMMS:::"memory");
700 #endif
701     while (s < end)
702     {
703         const int b = *s++;
704         const int g = *s++;
705         const int r = *s++;
706         *d++ = (b>>3) | ((g&0xFC)<<3) | ((r&0xF8)<<8);
707     }
708 }
709
710 static inline void RENAME(rgb24to16)(const uint8_t *src, uint8_t *dst, long src_size)
711 {
712     const uint8_t *s = src;
713     const uint8_t *end;
714 #if HAVE_MMX
715     const uint8_t *mm_end;
716 #endif
717     uint16_t *d = (uint16_t *)dst;
718     end = s + src_size;
719 #if HAVE_MMX
720     __asm__ volatile(PREFETCH"    %0"::"m"(*src):"memory");
721     __asm__ volatile(
722         "movq         %0, %%mm7     \n\t"
723         "movq         %1, %%mm6     \n\t"
724         ::"m"(red_16mask),"m"(green_16mask));
725     mm_end = end - 15;
726     while (s < mm_end)
727     {
728         __asm__ volatile(
729         PREFETCH"    32%1           \n\t"
730         "movd          %1, %%mm0    \n\t"
731         "movd         3%1, %%mm3    \n\t"
732         "punpckldq    6%1, %%mm0    \n\t"
733         "punpckldq    9%1, %%mm3    \n\t"
734         "movq       %%mm0, %%mm1    \n\t"
735         "movq       %%mm0, %%mm2    \n\t"
736         "movq       %%mm3, %%mm4    \n\t"
737         "movq       %%mm3, %%mm5    \n\t"
738         "psllq         $8, %%mm0    \n\t"
739         "psllq         $8, %%mm3    \n\t"
740         "pand       %%mm7, %%mm0    \n\t"
741         "pand       %%mm7, %%mm3    \n\t"
742         "psrlq         $5, %%mm1    \n\t"
743         "psrlq         $5, %%mm4    \n\t"
744         "pand       %%mm6, %%mm1    \n\t"
745         "pand       %%mm6, %%mm4    \n\t"
746         "psrlq        $19, %%mm2    \n\t"
747         "psrlq        $19, %%mm5    \n\t"
748         "pand          %2, %%mm2    \n\t"
749         "pand          %2, %%mm5    \n\t"
750         "por        %%mm1, %%mm0    \n\t"
751         "por        %%mm4, %%mm3    \n\t"
752         "por        %%mm2, %%mm0    \n\t"
753         "por        %%mm5, %%mm3    \n\t"
754         "psllq        $16, %%mm3    \n\t"
755         "por        %%mm3, %%mm0    \n\t"
756         MOVNTQ"     %%mm0, %0       \n\t"
757         :"=m"(*d):"m"(*s),"m"(blue_16mask):"memory");
758         d += 4;
759         s += 12;
760     }
761     __asm__ volatile(SFENCE:::"memory");
762     __asm__ volatile(EMMS:::"memory");
763 #endif
764     while (s < end)
765     {
766         const int r = *s++;
767         const int g = *s++;
768         const int b = *s++;
769         *d++ = (b>>3) | ((g&0xFC)<<3) | ((r&0xF8)<<8);
770     }
771 }
772
773 static inline void RENAME(rgb24tobgr15)(const uint8_t *src, uint8_t *dst, long src_size)
774 {
775     const uint8_t *s = src;
776     const uint8_t *end;
777 #if HAVE_MMX
778     const uint8_t *mm_end;
779 #endif
780     uint16_t *d = (uint16_t *)dst;
781     end = s + src_size;
782 #if HAVE_MMX
783     __asm__ volatile(PREFETCH"    %0"::"m"(*src):"memory");
784     __asm__ volatile(
785         "movq          %0, %%mm7    \n\t"
786         "movq          %1, %%mm6    \n\t"
787         ::"m"(red_15mask),"m"(green_15mask));
788     mm_end = end - 11;
789     while (s < mm_end)
790     {
791         __asm__ volatile(
792         PREFETCH"    32%1           \n\t"
793         "movd          %1, %%mm0    \n\t"
794         "movd         3%1, %%mm3    \n\t"
795         "punpckldq    6%1, %%mm0    \n\t"
796         "punpckldq    9%1, %%mm3    \n\t"
797         "movq       %%mm0, %%mm1    \n\t"
798         "movq       %%mm0, %%mm2    \n\t"
799         "movq       %%mm3, %%mm4    \n\t"
800         "movq       %%mm3, %%mm5    \n\t"
801         "psrlq         $3, %%mm0    \n\t"
802         "psrlq         $3, %%mm3    \n\t"
803         "pand          %2, %%mm0    \n\t"
804         "pand          %2, %%mm3    \n\t"
805         "psrlq         $6, %%mm1    \n\t"
806         "psrlq         $6, %%mm4    \n\t"
807         "pand       %%mm6, %%mm1    \n\t"
808         "pand       %%mm6, %%mm4    \n\t"
809         "psrlq         $9, %%mm2    \n\t"
810         "psrlq         $9, %%mm5    \n\t"
811         "pand       %%mm7, %%mm2    \n\t"
812         "pand       %%mm7, %%mm5    \n\t"
813         "por        %%mm1, %%mm0    \n\t"
814         "por        %%mm4, %%mm3    \n\t"
815         "por        %%mm2, %%mm0    \n\t"
816         "por        %%mm5, %%mm3    \n\t"
817         "psllq        $16, %%mm3    \n\t"
818         "por        %%mm3, %%mm0    \n\t"
819         MOVNTQ"     %%mm0, %0       \n\t"
820         :"=m"(*d):"m"(*s),"m"(blue_15mask):"memory");
821         d += 4;
822         s += 12;
823     }
824     __asm__ volatile(SFENCE:::"memory");
825     __asm__ volatile(EMMS:::"memory");
826 #endif
827     while (s < end)
828     {
829         const int b = *s++;
830         const int g = *s++;
831         const int r = *s++;
832         *d++ = (b>>3) | ((g&0xF8)<<2) | ((r&0xF8)<<7);
833     }
834 }
835
836 static inline void RENAME(rgb24to15)(const uint8_t *src, uint8_t *dst, long src_size)
837 {
838     const uint8_t *s = src;
839     const uint8_t *end;
840 #if HAVE_MMX
841     const uint8_t *mm_end;
842 #endif
843     uint16_t *d = (uint16_t *)dst;
844     end = s + src_size;
845 #if HAVE_MMX
846     __asm__ volatile(PREFETCH"    %0"::"m"(*src):"memory");
847     __asm__ volatile(
848         "movq         %0, %%mm7     \n\t"
849         "movq         %1, %%mm6     \n\t"
850         ::"m"(red_15mask),"m"(green_15mask));
851     mm_end = end - 15;
852     while (s < mm_end)
853     {
854         __asm__ volatile(
855         PREFETCH"   32%1            \n\t"
856         "movd         %1, %%mm0     \n\t"
857         "movd        3%1, %%mm3     \n\t"
858         "punpckldq   6%1, %%mm0     \n\t"
859         "punpckldq   9%1, %%mm3     \n\t"
860         "movq      %%mm0, %%mm1     \n\t"
861         "movq      %%mm0, %%mm2     \n\t"
862         "movq      %%mm3, %%mm4     \n\t"
863         "movq      %%mm3, %%mm5     \n\t"
864         "psllq        $7, %%mm0     \n\t"
865         "psllq        $7, %%mm3     \n\t"
866         "pand      %%mm7, %%mm0     \n\t"
867         "pand      %%mm7, %%mm3     \n\t"
868         "psrlq        $6, %%mm1     \n\t"
869         "psrlq        $6, %%mm4     \n\t"
870         "pand      %%mm6, %%mm1     \n\t"
871         "pand      %%mm6, %%mm4     \n\t"
872         "psrlq       $19, %%mm2     \n\t"
873         "psrlq       $19, %%mm5     \n\t"
874         "pand         %2, %%mm2     \n\t"
875         "pand         %2, %%mm5     \n\t"
876         "por       %%mm1, %%mm0     \n\t"
877         "por       %%mm4, %%mm3     \n\t"
878         "por       %%mm2, %%mm0     \n\t"
879         "por       %%mm5, %%mm3     \n\t"
880         "psllq       $16, %%mm3     \n\t"
881         "por       %%mm3, %%mm0     \n\t"
882         MOVNTQ"    %%mm0, %0        \n\t"
883         :"=m"(*d):"m"(*s),"m"(blue_15mask):"memory");
884         d += 4;
885         s += 12;
886     }
887     __asm__ volatile(SFENCE:::"memory");
888     __asm__ volatile(EMMS:::"memory");
889 #endif
890     while (s < end)
891     {
892         const int r = *s++;
893         const int g = *s++;
894         const int b = *s++;
895         *d++ = (b>>3) | ((g&0xF8)<<2) | ((r&0xF8)<<7);
896     }
897 }
898
899 /*
900   I use less accurate approximation here by simply left-shifting the input
901   value and filling the low order bits with zeroes. This method improves PNG
902   compression but this scheme cannot reproduce white exactly, since it does
903   not generate an all-ones maximum value; the net effect is to darken the
904   image slightly.
905
906   The better method should be "left bit replication":
907
908    4 3 2 1 0
909    ---------
910    1 1 0 1 1
911
912    7 6 5 4 3  2 1 0
913    ----------------
914    1 1 0 1 1  1 1 0
915    |=======|  |===|
916        |      leftmost bits repeated to fill open bits
917        |
918    original bits
919 */
920 static inline void RENAME(rgb15tobgr24)(const uint8_t *src, uint8_t *dst, long src_size)
921 {
922     const uint16_t *end;
923 #if HAVE_MMX
924     const uint16_t *mm_end;
925 #endif
926     uint8_t *d = dst;
927     const uint16_t *s = (const uint16_t*)src;
928     end = s + src_size/2;
929 #if HAVE_MMX
930     __asm__ volatile(PREFETCH"    %0"::"m"(*s):"memory");
931     mm_end = end - 7;
932     while (s < mm_end)
933     {
934         __asm__ volatile(
935         PREFETCH"    32%1           \n\t"
936         "movq          %1, %%mm0    \n\t"
937         "movq          %1, %%mm1    \n\t"
938         "movq          %1, %%mm2    \n\t"
939         "pand          %2, %%mm0    \n\t"
940         "pand          %3, %%mm1    \n\t"
941         "pand          %4, %%mm2    \n\t"
942         "psllq         $3, %%mm0    \n\t"
943         "psrlq         $2, %%mm1    \n\t"
944         "psrlq         $7, %%mm2    \n\t"
945         "movq       %%mm0, %%mm3    \n\t"
946         "movq       %%mm1, %%mm4    \n\t"
947         "movq       %%mm2, %%mm5    \n\t"
948         "punpcklwd     %5, %%mm0    \n\t"
949         "punpcklwd     %5, %%mm1    \n\t"
950         "punpcklwd     %5, %%mm2    \n\t"
951         "punpckhwd     %5, %%mm3    \n\t"
952         "punpckhwd     %5, %%mm4    \n\t"
953         "punpckhwd     %5, %%mm5    \n\t"
954         "psllq         $8, %%mm1    \n\t"
955         "psllq        $16, %%mm2    \n\t"
956         "por        %%mm1, %%mm0    \n\t"
957         "por        %%mm2, %%mm0    \n\t"
958         "psllq         $8, %%mm4    \n\t"
959         "psllq        $16, %%mm5    \n\t"
960         "por        %%mm4, %%mm3    \n\t"
961         "por        %%mm5, %%mm3    \n\t"
962
963         "movq       %%mm0, %%mm6    \n\t"
964         "movq       %%mm3, %%mm7    \n\t"
965
966         "movq         8%1, %%mm0    \n\t"
967         "movq         8%1, %%mm1    \n\t"
968         "movq         8%1, %%mm2    \n\t"
969         "pand          %2, %%mm0    \n\t"
970         "pand          %3, %%mm1    \n\t"
971         "pand          %4, %%mm2    \n\t"
972         "psllq         $3, %%mm0    \n\t"
973         "psrlq         $2, %%mm1    \n\t"
974         "psrlq         $7, %%mm2    \n\t"
975         "movq       %%mm0, %%mm3    \n\t"
976         "movq       %%mm1, %%mm4    \n\t"
977         "movq       %%mm2, %%mm5    \n\t"
978         "punpcklwd     %5, %%mm0    \n\t"
979         "punpcklwd     %5, %%mm1    \n\t"
980         "punpcklwd     %5, %%mm2    \n\t"
981         "punpckhwd     %5, %%mm3    \n\t"
982         "punpckhwd     %5, %%mm4    \n\t"
983         "punpckhwd     %5, %%mm5    \n\t"
984         "psllq         $8, %%mm1    \n\t"
985         "psllq        $16, %%mm2    \n\t"
986         "por        %%mm1, %%mm0    \n\t"
987         "por        %%mm2, %%mm0    \n\t"
988         "psllq         $8, %%mm4    \n\t"
989         "psllq        $16, %%mm5    \n\t"
990         "por        %%mm4, %%mm3    \n\t"
991         "por        %%mm5, %%mm3    \n\t"
992
993         :"=m"(*d)
994         :"m"(*s),"m"(mask15b),"m"(mask15g),"m"(mask15r), "m"(mmx_null)
995         :"memory");
996         /* borrowed 32 to 24 */
997         __asm__ volatile(
998         "movq       %%mm0, %%mm4    \n\t"
999         "movq       %%mm3, %%mm5    \n\t"
1000         "movq       %%mm6, %%mm0    \n\t"
1001         "movq       %%mm7, %%mm1    \n\t"
1002
1003         "movq       %%mm4, %%mm6    \n\t"
1004         "movq       %%mm5, %%mm7    \n\t"
1005         "movq       %%mm0, %%mm2    \n\t"
1006         "movq       %%mm1, %%mm3    \n\t"
1007
1008         "psrlq         $8, %%mm2    \n\t"
1009         "psrlq         $8, %%mm3    \n\t"
1010         "psrlq         $8, %%mm6    \n\t"
1011         "psrlq         $8, %%mm7    \n\t"
1012         "pand          %2, %%mm0    \n\t"
1013         "pand          %2, %%mm1    \n\t"
1014         "pand          %2, %%mm4    \n\t"
1015         "pand          %2, %%mm5    \n\t"
1016         "pand          %3, %%mm2    \n\t"
1017         "pand          %3, %%mm3    \n\t"
1018         "pand          %3, %%mm6    \n\t"
1019         "pand          %3, %%mm7    \n\t"
1020         "por        %%mm2, %%mm0    \n\t"
1021         "por        %%mm3, %%mm1    \n\t"
1022         "por        %%mm6, %%mm4    \n\t"
1023         "por        %%mm7, %%mm5    \n\t"
1024
1025         "movq       %%mm1, %%mm2    \n\t"
1026         "movq       %%mm4, %%mm3    \n\t"
1027         "psllq        $48, %%mm2    \n\t"
1028         "psllq        $32, %%mm3    \n\t"
1029         "pand          %4, %%mm2    \n\t"
1030         "pand          %5, %%mm3    \n\t"
1031         "por        %%mm2, %%mm0    \n\t"
1032         "psrlq        $16, %%mm1    \n\t"
1033         "psrlq        $32, %%mm4    \n\t"
1034         "psllq        $16, %%mm5    \n\t"
1035         "por        %%mm3, %%mm1    \n\t"
1036         "pand          %6, %%mm5    \n\t"
1037         "por        %%mm5, %%mm4    \n\t"
1038
1039         MOVNTQ"     %%mm0,   %0     \n\t"
1040         MOVNTQ"     %%mm1,  8%0     \n\t"
1041         MOVNTQ"     %%mm4, 16%0"
1042
1043         :"=m"(*d)
1044         :"m"(*s),"m"(mask24l),"m"(mask24h),"m"(mask24hh),"m"(mask24hhh),"m"(mask24hhhh)
1045         :"memory");
1046         d += 24;
1047         s += 8;
1048     }
1049     __asm__ volatile(SFENCE:::"memory");
1050     __asm__ volatile(EMMS:::"memory");
1051 #endif
1052     while (s < end)
1053     {
1054         register uint16_t bgr;
1055         bgr = *s++;
1056         *d++ = (bgr&0x1F)<<3;
1057         *d++ = (bgr&0x3E0)>>2;
1058         *d++ = (bgr&0x7C00)>>7;
1059     }
1060 }
1061
1062 static inline void RENAME(rgb16tobgr24)(const uint8_t *src, uint8_t *dst, long src_size)
1063 {
1064     const uint16_t *end;
1065 #if HAVE_MMX
1066     const uint16_t *mm_end;
1067 #endif
1068     uint8_t *d = (uint8_t *)dst;
1069     const uint16_t *s = (const uint16_t *)src;
1070     end = s + src_size/2;
1071 #if HAVE_MMX
1072     __asm__ volatile(PREFETCH"    %0"::"m"(*s):"memory");
1073     mm_end = end - 7;
1074     while (s < mm_end)
1075     {
1076         __asm__ volatile(
1077         PREFETCH"    32%1           \n\t"
1078         "movq          %1, %%mm0    \n\t"
1079         "movq          %1, %%mm1    \n\t"
1080         "movq          %1, %%mm2    \n\t"
1081         "pand          %2, %%mm0    \n\t"
1082         "pand          %3, %%mm1    \n\t"
1083         "pand          %4, %%mm2    \n\t"
1084         "psllq         $3, %%mm0    \n\t"
1085         "psrlq         $3, %%mm1    \n\t"
1086         "psrlq         $8, %%mm2    \n\t"
1087         "movq       %%mm0, %%mm3    \n\t"
1088         "movq       %%mm1, %%mm4    \n\t"
1089         "movq       %%mm2, %%mm5    \n\t"
1090         "punpcklwd     %5, %%mm0    \n\t"
1091         "punpcklwd     %5, %%mm1    \n\t"
1092         "punpcklwd     %5, %%mm2    \n\t"
1093         "punpckhwd     %5, %%mm3    \n\t"
1094         "punpckhwd     %5, %%mm4    \n\t"
1095         "punpckhwd     %5, %%mm5    \n\t"
1096         "psllq         $8, %%mm1    \n\t"
1097         "psllq        $16, %%mm2    \n\t"
1098         "por        %%mm1, %%mm0    \n\t"
1099         "por        %%mm2, %%mm0    \n\t"
1100         "psllq         $8, %%mm4    \n\t"
1101         "psllq        $16, %%mm5    \n\t"
1102         "por        %%mm4, %%mm3    \n\t"
1103         "por        %%mm5, %%mm3    \n\t"
1104
1105         "movq       %%mm0, %%mm6    \n\t"
1106         "movq       %%mm3, %%mm7    \n\t"
1107
1108         "movq         8%1, %%mm0    \n\t"
1109         "movq         8%1, %%mm1    \n\t"
1110         "movq         8%1, %%mm2    \n\t"
1111         "pand          %2, %%mm0    \n\t"
1112         "pand          %3, %%mm1    \n\t"
1113         "pand          %4, %%mm2    \n\t"
1114         "psllq         $3, %%mm0    \n\t"
1115         "psrlq         $3, %%mm1    \n\t"
1116         "psrlq         $8, %%mm2    \n\t"
1117         "movq       %%mm0, %%mm3    \n\t"
1118         "movq       %%mm1, %%mm4    \n\t"
1119         "movq       %%mm2, %%mm5    \n\t"
1120         "punpcklwd     %5, %%mm0    \n\t"
1121         "punpcklwd     %5, %%mm1    \n\t"
1122         "punpcklwd     %5, %%mm2    \n\t"
1123         "punpckhwd     %5, %%mm3    \n\t"
1124         "punpckhwd     %5, %%mm4    \n\t"
1125         "punpckhwd     %5, %%mm5    \n\t"
1126         "psllq         $8, %%mm1    \n\t"
1127         "psllq        $16, %%mm2    \n\t"
1128         "por        %%mm1, %%mm0    \n\t"
1129         "por        %%mm2, %%mm0    \n\t"
1130         "psllq         $8, %%mm4    \n\t"
1131         "psllq        $16, %%mm5    \n\t"
1132         "por        %%mm4, %%mm3    \n\t"
1133         "por        %%mm5, %%mm3    \n\t"
1134         :"=m"(*d)
1135         :"m"(*s),"m"(mask16b),"m"(mask16g),"m"(mask16r),"m"(mmx_null)
1136         :"memory");
1137         /* borrowed 32 to 24 */
1138         __asm__ volatile(
1139         "movq       %%mm0, %%mm4    \n\t"
1140         "movq       %%mm3, %%mm5    \n\t"
1141         "movq       %%mm6, %%mm0    \n\t"
1142         "movq       %%mm7, %%mm1    \n\t"
1143
1144         "movq       %%mm4, %%mm6    \n\t"
1145         "movq       %%mm5, %%mm7    \n\t"
1146         "movq       %%mm0, %%mm2    \n\t"
1147         "movq       %%mm1, %%mm3    \n\t"
1148
1149         "psrlq         $8, %%mm2    \n\t"
1150         "psrlq         $8, %%mm3    \n\t"
1151         "psrlq         $8, %%mm6    \n\t"
1152         "psrlq         $8, %%mm7    \n\t"
1153         "pand          %2, %%mm0    \n\t"
1154         "pand          %2, %%mm1    \n\t"
1155         "pand          %2, %%mm4    \n\t"
1156         "pand          %2, %%mm5    \n\t"
1157         "pand          %3, %%mm2    \n\t"
1158         "pand          %3, %%mm3    \n\t"
1159         "pand          %3, %%mm6    \n\t"
1160         "pand          %3, %%mm7    \n\t"
1161         "por        %%mm2, %%mm0    \n\t"
1162         "por        %%mm3, %%mm1    \n\t"
1163         "por        %%mm6, %%mm4    \n\t"
1164         "por        %%mm7, %%mm5    \n\t"
1165
1166         "movq       %%mm1, %%mm2    \n\t"
1167         "movq       %%mm4, %%mm3    \n\t"
1168         "psllq        $48, %%mm2    \n\t"
1169         "psllq        $32, %%mm3    \n\t"
1170         "pand          %4, %%mm2    \n\t"
1171         "pand          %5, %%mm3    \n\t"
1172         "por        %%mm2, %%mm0    \n\t"
1173         "psrlq        $16, %%mm1    \n\t"
1174         "psrlq        $32, %%mm4    \n\t"
1175         "psllq        $16, %%mm5    \n\t"
1176         "por        %%mm3, %%mm1    \n\t"
1177         "pand          %6, %%mm5    \n\t"
1178         "por        %%mm5, %%mm4    \n\t"
1179
1180         MOVNTQ"     %%mm0,   %0     \n\t"
1181         MOVNTQ"     %%mm1,  8%0     \n\t"
1182         MOVNTQ"     %%mm4, 16%0"
1183
1184         :"=m"(*d)
1185         :"m"(*s),"m"(mask24l),"m"(mask24h),"m"(mask24hh),"m"(mask24hhh),"m"(mask24hhhh)
1186         :"memory");
1187         d += 24;
1188         s += 8;
1189     }
1190     __asm__ volatile(SFENCE:::"memory");
1191     __asm__ volatile(EMMS:::"memory");
1192 #endif
1193     while (s < end)
1194     {
1195         register uint16_t bgr;
1196         bgr = *s++;
1197         *d++ = (bgr&0x1F)<<3;
1198         *d++ = (bgr&0x7E0)>>3;
1199         *d++ = (bgr&0xF800)>>8;
1200     }
1201 }
1202
1203 /*
1204  * mm0 = 00 B3 00 B2 00 B1 00 B0
1205  * mm1 = 00 G3 00 G2 00 G1 00 G0
1206  * mm2 = 00 R3 00 R2 00 R1 00 R0
1207  * mm6 = FF FF FF FF FF FF FF FF
1208  * mm7 = 00 00 00 00 00 00 00 00
1209  */
1210 #define PACK_RGB32 \
1211     "packuswb   %%mm7, %%mm0    \n\t" /* 00 00 00 00 B3 B2 B1 B0 */ \
1212     "packuswb   %%mm7, %%mm1    \n\t" /* 00 00 00 00 G3 G2 G1 G0 */ \
1213     "packuswb   %%mm7, %%mm2    \n\t" /* 00 00 00 00 R3 R2 R1 R0 */ \
1214     "punpcklbw  %%mm1, %%mm0    \n\t" /* G3 B3 G2 B2 G1 B1 G0 B0 */ \
1215     "punpcklbw  %%mm6, %%mm2    \n\t" /* FF R3 FF R2 FF R1 FF R0 */ \
1216     "movq       %%mm0, %%mm3    \n\t"                               \
1217     "punpcklwd  %%mm2, %%mm0    \n\t" /* FF R1 G1 B1 FF R0 G0 B0 */ \
1218     "punpckhwd  %%mm2, %%mm3    \n\t" /* FF R3 G3 B3 FF R2 G2 B2 */ \
1219     MOVNTQ"     %%mm0,  %0      \n\t"                               \
1220     MOVNTQ"     %%mm3, 8%0      \n\t"                               \
1221
1222 static inline void RENAME(rgb15to32)(const uint8_t *src, uint8_t *dst, long src_size)
1223 {
1224     const uint16_t *end;
1225 #if HAVE_MMX
1226     const uint16_t *mm_end;
1227 #endif
1228     uint8_t *d = dst;
1229     const uint16_t *s = (const uint16_t *)src;
1230     end = s + src_size/2;
1231 #if HAVE_MMX
1232     __asm__ volatile(PREFETCH"    %0"::"m"(*s):"memory");
1233     __asm__ volatile("pxor    %%mm7,%%mm7    \n\t":::"memory");
1234     __asm__ volatile("pcmpeqd %%mm6,%%mm6    \n\t":::"memory");
1235     mm_end = end - 3;
1236     while (s < mm_end)
1237     {
1238         __asm__ volatile(
1239         PREFETCH"    32%1           \n\t"
1240         "movq          %1, %%mm0    \n\t"
1241         "movq          %1, %%mm1    \n\t"
1242         "movq          %1, %%mm2    \n\t"
1243         "pand          %2, %%mm0    \n\t"
1244         "pand          %3, %%mm1    \n\t"
1245         "pand          %4, %%mm2    \n\t"
1246         "psllq         $3, %%mm0    \n\t"
1247         "psrlq         $2, %%mm1    \n\t"
1248         "psrlq         $7, %%mm2    \n\t"
1249         PACK_RGB32
1250         :"=m"(*d)
1251         :"m"(*s),"m"(mask15b),"m"(mask15g),"m"(mask15r)
1252         :"memory");
1253         d += 16;
1254         s += 4;
1255     }
1256     __asm__ volatile(SFENCE:::"memory");
1257     __asm__ volatile(EMMS:::"memory");
1258 #endif
1259     while (s < end)
1260     {
1261 #if 0 //slightly slower on Athlon
1262         int bgr= *s++;
1263         *((uint32_t*)d)++ = ((bgr&0x1F)<<3) + ((bgr&0x3E0)<<6) + ((bgr&0x7C00)<<9);
1264 #else
1265         register uint16_t bgr;
1266         bgr = *s++;
1267 #if HAVE_BIGENDIAN
1268         *d++ = 255;
1269         *d++ = (bgr&0x7C00)>>7;
1270         *d++ = (bgr&0x3E0)>>2;
1271         *d++ = (bgr&0x1F)<<3;
1272 #else
1273         *d++ = (bgr&0x1F)<<3;
1274         *d++ = (bgr&0x3E0)>>2;
1275         *d++ = (bgr&0x7C00)>>7;
1276         *d++ = 255;
1277 #endif
1278
1279 #endif
1280     }
1281 }
1282
1283 static inline void RENAME(rgb16to32)(const uint8_t *src, uint8_t *dst, long src_size)
1284 {
1285     const uint16_t *end;
1286 #if HAVE_MMX
1287     const uint16_t *mm_end;
1288 #endif
1289     uint8_t *d = dst;
1290     const uint16_t *s = (const uint16_t*)src;
1291     end = s + src_size/2;
1292 #if HAVE_MMX
1293     __asm__ volatile(PREFETCH"    %0"::"m"(*s):"memory");
1294     __asm__ volatile("pxor    %%mm7,%%mm7    \n\t":::"memory");
1295     __asm__ volatile("pcmpeqd %%mm6,%%mm6    \n\t":::"memory");
1296     mm_end = end - 3;
1297     while (s < mm_end)
1298     {
1299         __asm__ volatile(
1300         PREFETCH"    32%1           \n\t"
1301         "movq          %1, %%mm0    \n\t"
1302         "movq          %1, %%mm1    \n\t"
1303         "movq          %1, %%mm2    \n\t"
1304         "pand          %2, %%mm0    \n\t"
1305         "pand          %3, %%mm1    \n\t"
1306         "pand          %4, %%mm2    \n\t"
1307         "psllq         $3, %%mm0    \n\t"
1308         "psrlq         $3, %%mm1    \n\t"
1309         "psrlq         $8, %%mm2    \n\t"
1310         PACK_RGB32
1311         :"=m"(*d)
1312         :"m"(*s),"m"(mask16b),"m"(mask16g),"m"(mask16r)
1313         :"memory");
1314         d += 16;
1315         s += 4;
1316     }
1317     __asm__ volatile(SFENCE:::"memory");
1318     __asm__ volatile(EMMS:::"memory");
1319 #endif
1320     while (s < end)
1321     {
1322         register uint16_t bgr;
1323         bgr = *s++;
1324 #if HAVE_BIGENDIAN
1325         *d++ = 255;
1326         *d++ = (bgr&0xF800)>>8;
1327         *d++ = (bgr&0x7E0)>>3;
1328         *d++ = (bgr&0x1F)<<3;
1329 #else
1330         *d++ = (bgr&0x1F)<<3;
1331         *d++ = (bgr&0x7E0)>>3;
1332         *d++ = (bgr&0xF800)>>8;
1333         *d++ = 255;
1334 #endif
1335     }
1336 }
1337
1338 static inline void RENAME(rgb32tobgr32)(const uint8_t *src, uint8_t *dst, long src_size)
1339 {
1340     x86_reg idx = 15 - src_size;
1341     const uint8_t *s = src-idx;
1342     uint8_t *d = dst-idx;
1343 #if HAVE_MMX
1344     __asm__ volatile(
1345     "test          %0, %0           \n\t"
1346     "jns           2f               \n\t"
1347     PREFETCH"       (%1, %0)        \n\t"
1348     "movq          %3, %%mm7        \n\t"
1349     "pxor          %4, %%mm7        \n\t"
1350     "movq       %%mm7, %%mm6        \n\t"
1351     "pxor          %5, %%mm7        \n\t"
1352     ASMALIGN(4)
1353     "1:                             \n\t"
1354     PREFETCH"     32(%1, %0)        \n\t"
1355     "movq           (%1, %0), %%mm0 \n\t"
1356     "movq          8(%1, %0), %%mm1 \n\t"
1357 # if HAVE_MMX2
1358     "pshufw      $177, %%mm0, %%mm3 \n\t"
1359     "pshufw      $177, %%mm1, %%mm5 \n\t"
1360     "pand       %%mm7, %%mm0        \n\t"
1361     "pand       %%mm6, %%mm3        \n\t"
1362     "pand       %%mm7, %%mm1        \n\t"
1363     "pand       %%mm6, %%mm5        \n\t"
1364     "por        %%mm3, %%mm0        \n\t"
1365     "por        %%mm5, %%mm1        \n\t"
1366 # else
1367     "movq       %%mm0, %%mm2        \n\t"
1368     "movq       %%mm1, %%mm4        \n\t"
1369     "pand       %%mm7, %%mm0        \n\t"
1370     "pand       %%mm6, %%mm2        \n\t"
1371     "pand       %%mm7, %%mm1        \n\t"
1372     "pand       %%mm6, %%mm4        \n\t"
1373     "movq       %%mm2, %%mm3        \n\t"
1374     "movq       %%mm4, %%mm5        \n\t"
1375     "pslld        $16, %%mm2        \n\t"
1376     "psrld        $16, %%mm3        \n\t"
1377     "pslld        $16, %%mm4        \n\t"
1378     "psrld        $16, %%mm5        \n\t"
1379     "por        %%mm2, %%mm0        \n\t"
1380     "por        %%mm4, %%mm1        \n\t"
1381     "por        %%mm3, %%mm0        \n\t"
1382     "por        %%mm5, %%mm1        \n\t"
1383 # endif
1384     MOVNTQ"     %%mm0,  (%2, %0)    \n\t"
1385     MOVNTQ"     %%mm1, 8(%2, %0)    \n\t"
1386     "add          $16, %0           \n\t"
1387     "js            1b               \n\t"
1388     SFENCE"                         \n\t"
1389     EMMS"                           \n\t"
1390     "2:                             \n\t"
1391     : "+&r"(idx)
1392     : "r" (s), "r" (d), "m" (mask32b), "m" (mask32r), "m" (mmx_one)
1393     : "memory");
1394 #endif
1395     for (; idx<15; idx+=4) {
1396         register int v = *(const uint32_t *)&s[idx], g = v & 0xff00ff00;
1397         v &= 0xff00ff;
1398         *(uint32_t *)&d[idx] = (v>>16) + g + (v<<16);
1399     }
1400 }
1401
1402 static inline void RENAME(rgb24tobgr24)(const uint8_t *src, uint8_t *dst, long src_size)
1403 {
1404     unsigned i;
1405 #if HAVE_MMX
1406     x86_reg mmx_size= 23 - src_size;
1407     __asm__ volatile (
1408     "test             %%"REG_a", %%"REG_a"          \n\t"
1409     "jns                     2f                     \n\t"
1410     "movq     "MANGLE(mask24r)", %%mm5              \n\t"
1411     "movq     "MANGLE(mask24g)", %%mm6              \n\t"
1412     "movq     "MANGLE(mask24b)", %%mm7              \n\t"
1413     ASMALIGN(4)
1414     "1:                                             \n\t"
1415     PREFETCH" 32(%1, %%"REG_a")                     \n\t"
1416     "movq       (%1, %%"REG_a"), %%mm0              \n\t" // BGR BGR BG
1417     "movq       (%1, %%"REG_a"), %%mm1              \n\t" // BGR BGR BG
1418     "movq      2(%1, %%"REG_a"), %%mm2              \n\t" // R BGR BGR B
1419     "psllq                  $16, %%mm0              \n\t" // 00 BGR BGR
1420     "pand                 %%mm5, %%mm0              \n\t"
1421     "pand                 %%mm6, %%mm1              \n\t"
1422     "pand                 %%mm7, %%mm2              \n\t"
1423     "por                  %%mm0, %%mm1              \n\t"
1424     "por                  %%mm2, %%mm1              \n\t"
1425     "movq      6(%1, %%"REG_a"), %%mm0              \n\t" // BGR BGR BG
1426     MOVNTQ"               %%mm1,   (%2, %%"REG_a")  \n\t" // RGB RGB RG
1427     "movq      8(%1, %%"REG_a"), %%mm1              \n\t" // R BGR BGR B
1428     "movq     10(%1, %%"REG_a"), %%mm2              \n\t" // GR BGR BGR
1429     "pand                 %%mm7, %%mm0              \n\t"
1430     "pand                 %%mm5, %%mm1              \n\t"
1431     "pand                 %%mm6, %%mm2              \n\t"
1432     "por                  %%mm0, %%mm1              \n\t"
1433     "por                  %%mm2, %%mm1              \n\t"
1434     "movq     14(%1, %%"REG_a"), %%mm0              \n\t" // R BGR BGR B
1435     MOVNTQ"               %%mm1,  8(%2, %%"REG_a")  \n\t" // B RGB RGB R
1436     "movq     16(%1, %%"REG_a"), %%mm1              \n\t" // GR BGR BGR
1437     "movq     18(%1, %%"REG_a"), %%mm2              \n\t" // BGR BGR BG
1438     "pand                 %%mm6, %%mm0              \n\t"
1439     "pand                 %%mm7, %%mm1              \n\t"
1440     "pand                 %%mm5, %%mm2              \n\t"
1441     "por                  %%mm0, %%mm1              \n\t"
1442     "por                  %%mm2, %%mm1              \n\t"
1443     MOVNTQ"               %%mm1, 16(%2, %%"REG_a")  \n\t"
1444     "add                    $24, %%"REG_a"          \n\t"
1445     " js                     1b                     \n\t"
1446     "2:                                             \n\t"
1447     : "+a" (mmx_size)
1448     : "r" (src-mmx_size), "r"(dst-mmx_size)
1449     );
1450
1451     __asm__ volatile(SFENCE:::"memory");
1452     __asm__ volatile(EMMS:::"memory");
1453
1454     if (mmx_size==23) return; //finished, was multiple of 8
1455
1456     src+= src_size;
1457     dst+= src_size;
1458     src_size= 23-mmx_size;
1459     src-= src_size;
1460     dst-= src_size;
1461 #endif
1462     for (i=0; i<src_size; i+=3)
1463     {
1464         register uint8_t x;
1465         x          = src[i + 2];
1466         dst[i + 1] = src[i + 1];
1467         dst[i + 2] = src[i + 0];
1468         dst[i + 0] = x;
1469     }
1470 }
1471
1472 static inline void RENAME(yuvPlanartoyuy2)(const uint8_t *ysrc, const uint8_t *usrc, const uint8_t *vsrc, uint8_t *dst,
1473                                            long width, long height,
1474                                            long lumStride, long chromStride, long dstStride, long vertLumPerChroma)
1475 {
1476     long y;
1477     const x86_reg chromWidth= width>>1;
1478     for (y=0; y<height; y++)
1479     {
1480 #if HAVE_MMX
1481 //FIXME handle 2 lines at once (fewer prefetches, reuse some chroma, but very likely memory-limited anyway)
1482         __asm__ volatile(
1483         "xor                 %%"REG_a", %%"REG_a"   \n\t"
1484         ASMALIGN(4)
1485         "1:                                         \n\t"
1486         PREFETCH"    32(%1, %%"REG_a", 2)           \n\t"
1487         PREFETCH"    32(%2, %%"REG_a")              \n\t"
1488         PREFETCH"    32(%3, %%"REG_a")              \n\t"
1489         "movq          (%2, %%"REG_a"), %%mm0       \n\t" // U(0)
1490         "movq                    %%mm0, %%mm2       \n\t" // U(0)
1491         "movq          (%3, %%"REG_a"), %%mm1       \n\t" // V(0)
1492         "punpcklbw               %%mm1, %%mm0       \n\t" // UVUV UVUV(0)
1493         "punpckhbw               %%mm1, %%mm2       \n\t" // UVUV UVUV(8)
1494
1495         "movq        (%1, %%"REG_a",2), %%mm3       \n\t" // Y(0)
1496         "movq       8(%1, %%"REG_a",2), %%mm5       \n\t" // Y(8)
1497         "movq                    %%mm3, %%mm4       \n\t" // Y(0)
1498         "movq                    %%mm5, %%mm6       \n\t" // Y(8)
1499         "punpcklbw               %%mm0, %%mm3       \n\t" // YUYV YUYV(0)
1500         "punpckhbw               %%mm0, %%mm4       \n\t" // YUYV YUYV(4)
1501         "punpcklbw               %%mm2, %%mm5       \n\t" // YUYV YUYV(8)
1502         "punpckhbw               %%mm2, %%mm6       \n\t" // YUYV YUYV(12)
1503
1504         MOVNTQ"                  %%mm3,   (%0, %%"REG_a", 4)    \n\t"
1505         MOVNTQ"                  %%mm4,  8(%0, %%"REG_a", 4)    \n\t"
1506         MOVNTQ"                  %%mm5, 16(%0, %%"REG_a", 4)    \n\t"
1507         MOVNTQ"                  %%mm6, 24(%0, %%"REG_a", 4)    \n\t"
1508
1509         "add                        $8, %%"REG_a"   \n\t"
1510         "cmp                        %4, %%"REG_a"   \n\t"
1511         " jb                        1b              \n\t"
1512         ::"r"(dst), "r"(ysrc), "r"(usrc), "r"(vsrc), "g" (chromWidth)
1513         : "%"REG_a
1514         );
1515 #else
1516
1517 #if ARCH_ALPHA && HAVE_MVI
1518 #define pl2yuy2(n)                  \
1519     y1 = yc[n];                     \
1520     y2 = yc2[n];                    \
1521     u = uc[n];                      \
1522     v = vc[n];                      \
1523     __asm__("unpkbw %1, %0" : "=r"(y1) : "r"(y1));  \
1524     __asm__("unpkbw %1, %0" : "=r"(y2) : "r"(y2));  \
1525     __asm__("unpkbl %1, %0" : "=r"(u) : "r"(u));    \
1526     __asm__("unpkbl %1, %0" : "=r"(v) : "r"(v));    \
1527     yuv1 = (u << 8) + (v << 24);                \
1528     yuv2 = yuv1 + y2;               \
1529     yuv1 += y1;                     \
1530     qdst[n]  = yuv1;                \
1531     qdst2[n] = yuv2;
1532
1533         int i;
1534         uint64_t *qdst = (uint64_t *) dst;
1535         uint64_t *qdst2 = (uint64_t *) (dst + dstStride);
1536         const uint32_t *yc = (uint32_t *) ysrc;
1537         const uint32_t *yc2 = (uint32_t *) (ysrc + lumStride);
1538         const uint16_t *uc = (uint16_t*) usrc, *vc = (uint16_t*) vsrc;
1539         for (i = 0; i < chromWidth; i += 8){
1540             uint64_t y1, y2, yuv1, yuv2;
1541             uint64_t u, v;
1542             /* Prefetch */
1543             __asm__("ldq $31,64(%0)" :: "r"(yc));
1544             __asm__("ldq $31,64(%0)" :: "r"(yc2));
1545             __asm__("ldq $31,64(%0)" :: "r"(uc));
1546             __asm__("ldq $31,64(%0)" :: "r"(vc));
1547
1548             pl2yuy2(0);
1549             pl2yuy2(1);
1550             pl2yuy2(2);
1551             pl2yuy2(3);
1552
1553             yc    += 4;
1554             yc2   += 4;
1555             uc    += 4;
1556             vc    += 4;
1557             qdst  += 4;
1558             qdst2 += 4;
1559         }
1560         y++;
1561         ysrc += lumStride;
1562         dst += dstStride;
1563
1564 #elif HAVE_FAST_64BIT
1565         int i;
1566         uint64_t *ldst = (uint64_t *) dst;
1567         const uint8_t *yc = ysrc, *uc = usrc, *vc = vsrc;
1568         for (i = 0; i < chromWidth; i += 2){
1569             uint64_t k, l;
1570             k = yc[0] + (uc[0] << 8) +
1571                 (yc[1] << 16) + (vc[0] << 24);
1572             l = yc[2] + (uc[1] << 8) +
1573                 (yc[3] << 16) + (vc[1] << 24);
1574             *ldst++ = k + (l << 32);
1575             yc += 4;
1576             uc += 2;
1577             vc += 2;
1578         }
1579
1580 #else
1581         int i, *idst = (int32_t *) dst;
1582         const uint8_t *yc = ysrc, *uc = usrc, *vc = vsrc;
1583         for (i = 0; i < chromWidth; i++){
1584 #if HAVE_BIGENDIAN
1585             *idst++ = (yc[0] << 24)+ (uc[0] << 16) +
1586                 (yc[1] << 8) + (vc[0] << 0);
1587 #else
1588             *idst++ = yc[0] + (uc[0] << 8) +
1589                 (yc[1] << 16) + (vc[0] << 24);
1590 #endif
1591             yc += 2;
1592             uc++;
1593             vc++;
1594         }
1595 #endif
1596 #endif
1597         if ((y&(vertLumPerChroma-1)) == vertLumPerChroma-1)
1598         {
1599             usrc += chromStride;
1600             vsrc += chromStride;
1601         }
1602         ysrc += lumStride;
1603         dst  += dstStride;
1604     }
1605 #if HAVE_MMX
1606 __asm__(    EMMS"       \n\t"
1607         SFENCE"     \n\t"
1608         :::"memory");
1609 #endif
1610 }
1611
1612 /**
1613  * Height should be a multiple of 2 and width should be a multiple of 16.
1614  * (If this is a problem for anyone then tell me, and I will fix it.)
1615  */
1616 static inline void RENAME(yv12toyuy2)(const uint8_t *ysrc, const uint8_t *usrc, const uint8_t *vsrc, uint8_t *dst,
1617                                       long width, long height,
1618                                       long lumStride, long chromStride, long dstStride)
1619 {
1620     //FIXME interpolate chroma
1621     RENAME(yuvPlanartoyuy2)(ysrc, usrc, vsrc, dst, width, height, lumStride, chromStride, dstStride, 2);
1622 }
1623
1624 static inline void RENAME(yuvPlanartouyvy)(const uint8_t *ysrc, const uint8_t *usrc, const uint8_t *vsrc, uint8_t *dst,
1625                                            long width, long height,
1626                                            long lumStride, long chromStride, long dstStride, long vertLumPerChroma)
1627 {
1628     long y;
1629     const x86_reg chromWidth= width>>1;
1630     for (y=0; y<height; y++)
1631     {
1632 #if HAVE_MMX
1633 //FIXME handle 2 lines at once (fewer prefetches, reuse some chroma, but very likely memory-limited anyway)
1634         __asm__ volatile(
1635         "xor                %%"REG_a", %%"REG_a"    \n\t"
1636         ASMALIGN(4)
1637         "1:                                         \n\t"
1638         PREFETCH"   32(%1, %%"REG_a", 2)            \n\t"
1639         PREFETCH"   32(%2, %%"REG_a")               \n\t"
1640         PREFETCH"   32(%3, %%"REG_a")               \n\t"
1641         "movq         (%2, %%"REG_a"), %%mm0        \n\t" // U(0)
1642         "movq                   %%mm0, %%mm2        \n\t" // U(0)
1643         "movq         (%3, %%"REG_a"), %%mm1        \n\t" // V(0)
1644         "punpcklbw              %%mm1, %%mm0        \n\t" // UVUV UVUV(0)
1645         "punpckhbw              %%mm1, %%mm2        \n\t" // UVUV UVUV(8)
1646
1647         "movq       (%1, %%"REG_a",2), %%mm3        \n\t" // Y(0)
1648         "movq      8(%1, %%"REG_a",2), %%mm5        \n\t" // Y(8)
1649         "movq                   %%mm0, %%mm4        \n\t" // Y(0)
1650         "movq                   %%mm2, %%mm6        \n\t" // Y(8)
1651         "punpcklbw              %%mm3, %%mm0        \n\t" // YUYV YUYV(0)
1652         "punpckhbw              %%mm3, %%mm4        \n\t" // YUYV YUYV(4)
1653         "punpcklbw              %%mm5, %%mm2        \n\t" // YUYV YUYV(8)
1654         "punpckhbw              %%mm5, %%mm6        \n\t" // YUYV YUYV(12)
1655
1656         MOVNTQ"                 %%mm0,   (%0, %%"REG_a", 4)     \n\t"
1657         MOVNTQ"                 %%mm4,  8(%0, %%"REG_a", 4)     \n\t"
1658         MOVNTQ"                 %%mm2, 16(%0, %%"REG_a", 4)     \n\t"
1659         MOVNTQ"                 %%mm6, 24(%0, %%"REG_a", 4)     \n\t"
1660
1661         "add                       $8, %%"REG_a"    \n\t"
1662         "cmp                       %4, %%"REG_a"    \n\t"
1663         " jb                       1b               \n\t"
1664         ::"r"(dst), "r"(ysrc), "r"(usrc), "r"(vsrc), "g" (chromWidth)
1665         : "%"REG_a
1666         );
1667 #else
1668 //FIXME adapt the Alpha ASM code from yv12->yuy2
1669
1670 #if HAVE_FAST_64BIT
1671         int i;
1672         uint64_t *ldst = (uint64_t *) dst;
1673         const uint8_t *yc = ysrc, *uc = usrc, *vc = vsrc;
1674         for (i = 0; i < chromWidth; i += 2){
1675             uint64_t k, l;
1676             k = uc[0] + (yc[0] << 8) +
1677                 (vc[0] << 16) + (yc[1] << 24);
1678             l = uc[1] + (yc[2] << 8) +
1679                 (vc[1] << 16) + (yc[3] << 24);
1680             *ldst++ = k + (l << 32);
1681             yc += 4;
1682             uc += 2;
1683             vc += 2;
1684         }
1685
1686 #else
1687         int i, *idst = (int32_t *) dst;
1688         const uint8_t *yc = ysrc, *uc = usrc, *vc = vsrc;
1689         for (i = 0; i < chromWidth; i++){
1690 #if HAVE_BIGENDIAN
1691             *idst++ = (uc[0] << 24)+ (yc[0] << 16) +
1692                 (vc[0] << 8) + (yc[1] << 0);
1693 #else
1694             *idst++ = uc[0] + (yc[0] << 8) +
1695                (vc[0] << 16) + (yc[1] << 24);
1696 #endif
1697             yc += 2;
1698             uc++;
1699             vc++;
1700         }
1701 #endif
1702 #endif
1703         if ((y&(vertLumPerChroma-1)) == vertLumPerChroma-1)
1704         {
1705             usrc += chromStride;
1706             vsrc += chromStride;
1707         }
1708         ysrc += lumStride;
1709         dst += dstStride;
1710     }
1711 #if HAVE_MMX
1712 __asm__(    EMMS"       \n\t"
1713         SFENCE"     \n\t"
1714         :::"memory");
1715 #endif
1716 }
1717
1718 /**
1719  * Height should be a multiple of 2 and width should be a multiple of 16
1720  * (If this is a problem for anyone then tell me, and I will fix it.)
1721  */
1722 static inline void RENAME(yv12touyvy)(const uint8_t *ysrc, const uint8_t *usrc, const uint8_t *vsrc, uint8_t *dst,
1723                                       long width, long height,
1724                                       long lumStride, long chromStride, long dstStride)
1725 {
1726     //FIXME interpolate chroma
1727     RENAME(yuvPlanartouyvy)(ysrc, usrc, vsrc, dst, width, height, lumStride, chromStride, dstStride, 2);
1728 }
1729
1730 /**
1731  * Width should be a multiple of 16.
1732  */
1733 static inline void RENAME(yuv422ptouyvy)(const uint8_t *ysrc, const uint8_t *usrc, const uint8_t *vsrc, uint8_t *dst,
1734                                          long width, long height,
1735                                          long lumStride, long chromStride, long dstStride)
1736 {
1737     RENAME(yuvPlanartouyvy)(ysrc, usrc, vsrc, dst, width, height, lumStride, chromStride, dstStride, 1);
1738 }
1739
1740 /**
1741  * Width should be a multiple of 16.
1742  */
1743 static inline void RENAME(yuv422ptoyuy2)(const uint8_t *ysrc, const uint8_t *usrc, const uint8_t *vsrc, uint8_t *dst,
1744                                          long width, long height,
1745                                          long lumStride, long chromStride, long dstStride)
1746 {
1747     RENAME(yuvPlanartoyuy2)(ysrc, usrc, vsrc, dst, width, height, lumStride, chromStride, dstStride, 1);
1748 }
1749
1750 /**
1751  * Height should be a multiple of 2 and width should be a multiple of 16.
1752  * (If this is a problem for anyone then tell me, and I will fix it.)
1753  */
1754 static inline void RENAME(yuy2toyv12)(const uint8_t *src, uint8_t *ydst, uint8_t *udst, uint8_t *vdst,
1755                                       long width, long height,
1756                                       long lumStride, long chromStride, long srcStride)
1757 {
1758     long y;
1759     const x86_reg chromWidth= width>>1;
1760     for (y=0; y<height; y+=2)
1761     {
1762 #if HAVE_MMX
1763         __asm__ volatile(
1764         "xor                 %%"REG_a", %%"REG_a"   \n\t"
1765         "pcmpeqw                 %%mm7, %%mm7       \n\t"
1766         "psrlw                      $8, %%mm7       \n\t" // FF,00,FF,00...
1767         ASMALIGN(4)
1768         "1:                \n\t"
1769         PREFETCH" 64(%0, %%"REG_a", 4)              \n\t"
1770         "movq       (%0, %%"REG_a", 4), %%mm0       \n\t" // YUYV YUYV(0)
1771         "movq      8(%0, %%"REG_a", 4), %%mm1       \n\t" // YUYV YUYV(4)
1772         "movq                    %%mm0, %%mm2       \n\t" // YUYV YUYV(0)
1773         "movq                    %%mm1, %%mm3       \n\t" // YUYV YUYV(4)
1774         "psrlw                      $8, %%mm0       \n\t" // U0V0 U0V0(0)
1775         "psrlw                      $8, %%mm1       \n\t" // U0V0 U0V0(4)
1776         "pand                    %%mm7, %%mm2       \n\t" // Y0Y0 Y0Y0(0)
1777         "pand                    %%mm7, %%mm3       \n\t" // Y0Y0 Y0Y0(4)
1778         "packuswb                %%mm1, %%mm0       \n\t" // UVUV UVUV(0)
1779         "packuswb                %%mm3, %%mm2       \n\t" // YYYY YYYY(0)
1780
1781         MOVNTQ"                  %%mm2, (%1, %%"REG_a", 2)  \n\t"
1782
1783         "movq     16(%0, %%"REG_a", 4), %%mm1       \n\t" // YUYV YUYV(8)
1784         "movq     24(%0, %%"REG_a", 4), %%mm2       \n\t" // YUYV YUYV(12)
1785         "movq                    %%mm1, %%mm3       \n\t" // YUYV YUYV(8)
1786         "movq                    %%mm2, %%mm4       \n\t" // YUYV YUYV(12)
1787         "psrlw                      $8, %%mm1       \n\t" // U0V0 U0V0(8)
1788         "psrlw                      $8, %%mm2       \n\t" // U0V0 U0V0(12)
1789         "pand                    %%mm7, %%mm3       \n\t" // Y0Y0 Y0Y0(8)
1790         "pand                    %%mm7, %%mm4       \n\t" // Y0Y0 Y0Y0(12)
1791         "packuswb                %%mm2, %%mm1       \n\t" // UVUV UVUV(8)
1792         "packuswb                %%mm4, %%mm3       \n\t" // YYYY YYYY(8)
1793
1794         MOVNTQ"                  %%mm3, 8(%1, %%"REG_a", 2) \n\t"
1795
1796         "movq                    %%mm0, %%mm2       \n\t" // UVUV UVUV(0)
1797         "movq                    %%mm1, %%mm3       \n\t" // UVUV UVUV(8)
1798         "psrlw                      $8, %%mm0       \n\t" // V0V0 V0V0(0)
1799         "psrlw                      $8, %%mm1       \n\t" // V0V0 V0V0(8)
1800         "pand                    %%mm7, %%mm2       \n\t" // U0U0 U0U0(0)
1801         "pand                    %%mm7, %%mm3       \n\t" // U0U0 U0U0(8)
1802         "packuswb                %%mm1, %%mm0       \n\t" // VVVV VVVV(0)
1803         "packuswb                %%mm3, %%mm2       \n\t" // UUUU UUUU(0)
1804
1805         MOVNTQ"                  %%mm0, (%3, %%"REG_a")     \n\t"
1806         MOVNTQ"                  %%mm2, (%2, %%"REG_a")     \n\t"
1807
1808         "add                        $8, %%"REG_a"   \n\t"
1809         "cmp                        %4, %%"REG_a"   \n\t"
1810         " jb                        1b              \n\t"
1811         ::"r"(src), "r"(ydst), "r"(udst), "r"(vdst), "g" (chromWidth)
1812         : "memory", "%"REG_a
1813         );
1814
1815         ydst += lumStride;
1816         src  += srcStride;
1817
1818         __asm__ volatile(
1819         "xor                 %%"REG_a", %%"REG_a"   \n\t"
1820         ASMALIGN(4)
1821         "1:                                         \n\t"
1822         PREFETCH" 64(%0, %%"REG_a", 4)              \n\t"
1823         "movq       (%0, %%"REG_a", 4), %%mm0       \n\t" // YUYV YUYV(0)
1824         "movq      8(%0, %%"REG_a", 4), %%mm1       \n\t" // YUYV YUYV(4)
1825         "movq     16(%0, %%"REG_a", 4), %%mm2       \n\t" // YUYV YUYV(8)
1826         "movq     24(%0, %%"REG_a", 4), %%mm3       \n\t" // YUYV YUYV(12)
1827         "pand                    %%mm7, %%mm0       \n\t" // Y0Y0 Y0Y0(0)
1828         "pand                    %%mm7, %%mm1       \n\t" // Y0Y0 Y0Y0(4)
1829         "pand                    %%mm7, %%mm2       \n\t" // Y0Y0 Y0Y0(8)
1830         "pand                    %%mm7, %%mm3       \n\t" // Y0Y0 Y0Y0(12)
1831         "packuswb                %%mm1, %%mm0       \n\t" // YYYY YYYY(0)
1832         "packuswb                %%mm3, %%mm2       \n\t" // YYYY YYYY(8)
1833
1834         MOVNTQ"                  %%mm0,  (%1, %%"REG_a", 2) \n\t"
1835         MOVNTQ"                  %%mm2, 8(%1, %%"REG_a", 2) \n\t"
1836
1837         "add                        $8, %%"REG_a"   \n\t"
1838         "cmp                        %4, %%"REG_a"   \n\t"
1839         " jb                        1b              \n\t"
1840
1841         ::"r"(src), "r"(ydst), "r"(udst), "r"(vdst), "g" (chromWidth)
1842         : "memory", "%"REG_a
1843         );
1844 #else
1845         long i;
1846         for (i=0; i<chromWidth; i++)
1847         {
1848             ydst[2*i+0]     = src[4*i+0];
1849             udst[i]     = src[4*i+1];
1850             ydst[2*i+1]     = src[4*i+2];
1851             vdst[i]     = src[4*i+3];
1852         }
1853         ydst += lumStride;
1854         src  += srcStride;
1855
1856         for (i=0; i<chromWidth; i++)
1857         {
1858             ydst[2*i+0]     = src[4*i+0];
1859             ydst[2*i+1]     = src[4*i+2];
1860         }
1861 #endif
1862         udst += chromStride;
1863         vdst += chromStride;
1864         ydst += lumStride;
1865         src  += srcStride;
1866     }
1867 #if HAVE_MMX
1868 __asm__ volatile(   EMMS"       \n\t"
1869                 SFENCE"     \n\t"
1870                 :::"memory");
1871 #endif
1872 }
1873
1874 static inline void RENAME(yvu9toyv12)(const uint8_t *ysrc, const uint8_t *usrc, const uint8_t *vsrc,
1875                                       uint8_t *ydst, uint8_t *udst, uint8_t *vdst,
1876                                       long width, long height, long lumStride, long chromStride)
1877 {
1878     /* Y Plane */
1879     memcpy(ydst, ysrc, width*height);
1880
1881     /* XXX: implement upscaling for U,V */
1882 }
1883
1884 static inline void RENAME(planar2x)(const uint8_t *src, uint8_t *dst, long srcWidth, long srcHeight, long srcStride, long dstStride)
1885 {
1886     long x,y;
1887
1888     dst[0]= src[0];
1889
1890     // first line
1891     for (x=0; x<srcWidth-1; x++){
1892         dst[2*x+1]= (3*src[x] +   src[x+1])>>2;
1893         dst[2*x+2]= (  src[x] + 3*src[x+1])>>2;
1894     }
1895     dst[2*srcWidth-1]= src[srcWidth-1];
1896
1897         dst+= dstStride;
1898
1899     for (y=1; y<srcHeight; y++){
1900 #if HAVE_MMX2 || HAVE_AMD3DNOW
1901         const x86_reg mmxSize= srcWidth&~15;
1902         __asm__ volatile(
1903         "mov           %4, %%"REG_a"            \n\t"
1904         "1:                                     \n\t"
1905         "movq         (%0, %%"REG_a"), %%mm0    \n\t"
1906         "movq         (%1, %%"REG_a"), %%mm1    \n\t"
1907         "movq        1(%0, %%"REG_a"), %%mm2    \n\t"
1908         "movq        1(%1, %%"REG_a"), %%mm3    \n\t"
1909         "movq       -1(%0, %%"REG_a"), %%mm4    \n\t"
1910         "movq       -1(%1, %%"REG_a"), %%mm5    \n\t"
1911         PAVGB"                  %%mm0, %%mm5    \n\t"
1912         PAVGB"                  %%mm0, %%mm3    \n\t"
1913         PAVGB"                  %%mm0, %%mm5    \n\t"
1914         PAVGB"                  %%mm0, %%mm3    \n\t"
1915         PAVGB"                  %%mm1, %%mm4    \n\t"
1916         PAVGB"                  %%mm1, %%mm2    \n\t"
1917         PAVGB"                  %%mm1, %%mm4    \n\t"
1918         PAVGB"                  %%mm1, %%mm2    \n\t"
1919         "movq                   %%mm5, %%mm7    \n\t"
1920         "movq                   %%mm4, %%mm6    \n\t"
1921         "punpcklbw              %%mm3, %%mm5    \n\t"
1922         "punpckhbw              %%mm3, %%mm7    \n\t"
1923         "punpcklbw              %%mm2, %%mm4    \n\t"
1924         "punpckhbw              %%mm2, %%mm6    \n\t"
1925 #if 1
1926         MOVNTQ"                 %%mm5,  (%2, %%"REG_a", 2)  \n\t"
1927         MOVNTQ"                 %%mm7, 8(%2, %%"REG_a", 2)  \n\t"
1928         MOVNTQ"                 %%mm4,  (%3, %%"REG_a", 2)  \n\t"
1929         MOVNTQ"                 %%mm6, 8(%3, %%"REG_a", 2)  \n\t"
1930 #else
1931         "movq                   %%mm5,  (%2, %%"REG_a", 2)  \n\t"
1932         "movq                   %%mm7, 8(%2, %%"REG_a", 2)  \n\t"
1933         "movq                   %%mm4,  (%3, %%"REG_a", 2)  \n\t"
1934         "movq                   %%mm6, 8(%3, %%"REG_a", 2)  \n\t"
1935 #endif
1936         "add                       $8, %%"REG_a"            \n\t"
1937         " js                       1b                       \n\t"
1938         :: "r" (src + mmxSize  ), "r" (src + srcStride + mmxSize  ),
1939            "r" (dst + mmxSize*2), "r" (dst + dstStride + mmxSize*2),
1940            "g" (-mmxSize)
1941         : "%"REG_a
1942
1943         );
1944 #else
1945         const x86_reg mmxSize=1;
1946 #endif
1947         dst[0        ]= (3*src[0] +   src[srcStride])>>2;
1948         dst[dstStride]= (  src[0] + 3*src[srcStride])>>2;
1949
1950         for (x=mmxSize-1; x<srcWidth-1; x++){
1951             dst[2*x          +1]= (3*src[x+0] +   src[x+srcStride+1])>>2;
1952             dst[2*x+dstStride+2]= (  src[x+0] + 3*src[x+srcStride+1])>>2;
1953             dst[2*x+dstStride+1]= (  src[x+1] + 3*src[x+srcStride  ])>>2;
1954             dst[2*x          +2]= (3*src[x+1] +   src[x+srcStride  ])>>2;
1955         }
1956         dst[srcWidth*2 -1            ]= (3*src[srcWidth-1] +   src[srcWidth-1 + srcStride])>>2;
1957         dst[srcWidth*2 -1 + dstStride]= (  src[srcWidth-1] + 3*src[srcWidth-1 + srcStride])>>2;
1958
1959         dst+=dstStride*2;
1960         src+=srcStride;
1961     }
1962
1963     // last line
1964 #if 1
1965     dst[0]= src[0];
1966
1967     for (x=0; x<srcWidth-1; x++){
1968         dst[2*x+1]= (3*src[x] +   src[x+1])>>2;
1969         dst[2*x+2]= (  src[x] + 3*src[x+1])>>2;
1970     }
1971     dst[2*srcWidth-1]= src[srcWidth-1];
1972 #else
1973     for (x=0; x<srcWidth; x++){
1974         dst[2*x+0]=
1975         dst[2*x+1]= src[x];
1976     }
1977 #endif
1978
1979 #if HAVE_MMX
1980 __asm__ volatile(   EMMS"       \n\t"
1981                 SFENCE"     \n\t"
1982                 :::"memory");
1983 #endif
1984 }
1985
1986 /**
1987  * Height should be a multiple of 2 and width should be a multiple of 16.
1988  * (If this is a problem for anyone then tell me, and I will fix it.)
1989  * Chrominance data is only taken from every second line, others are ignored.
1990  * FIXME: Write HQ version.
1991  */
1992 static inline void RENAME(uyvytoyv12)(const uint8_t *src, uint8_t *ydst, uint8_t *udst, uint8_t *vdst,
1993                                       long width, long height,
1994                                       long lumStride, long chromStride, long srcStride)
1995 {
1996     long y;
1997     const x86_reg chromWidth= width>>1;
1998     for (y=0; y<height; y+=2)
1999     {
2000 #if HAVE_MMX
2001         __asm__ volatile(
2002         "xor                 %%"REG_a", %%"REG_a"   \n\t"
2003         "pcmpeqw             %%mm7, %%mm7   \n\t"
2004         "psrlw                  $8, %%mm7   \n\t" // FF,00,FF,00...
2005         ASMALIGN(4)
2006         "1:                                 \n\t"
2007         PREFETCH" 64(%0, %%"REG_a", 4)          \n\t"
2008         "movq       (%0, %%"REG_a", 4), %%mm0   \n\t" // UYVY UYVY(0)
2009         "movq      8(%0, %%"REG_a", 4), %%mm1   \n\t" // UYVY UYVY(4)
2010         "movq                %%mm0, %%mm2   \n\t" // UYVY UYVY(0)
2011         "movq                %%mm1, %%mm3   \n\t" // UYVY UYVY(4)
2012         "pand                %%mm7, %%mm0   \n\t" // U0V0 U0V0(0)
2013         "pand                %%mm7, %%mm1   \n\t" // U0V0 U0V0(4)
2014         "psrlw                  $8, %%mm2   \n\t" // Y0Y0 Y0Y0(0)
2015         "psrlw                  $8, %%mm3   \n\t" // Y0Y0 Y0Y0(4)
2016         "packuswb            %%mm1, %%mm0   \n\t" // UVUV UVUV(0)
2017         "packuswb            %%mm3, %%mm2   \n\t" // YYYY YYYY(0)
2018
2019         MOVNTQ"              %%mm2,  (%1, %%"REG_a", 2) \n\t"
2020
2021         "movq     16(%0, %%"REG_a", 4), %%mm1   \n\t" // UYVY UYVY(8)
2022         "movq     24(%0, %%"REG_a", 4), %%mm2   \n\t" // UYVY UYVY(12)
2023         "movq                %%mm1, %%mm3   \n\t" // UYVY UYVY(8)
2024         "movq                %%mm2, %%mm4   \n\t" // UYVY UYVY(12)
2025         "pand                %%mm7, %%mm1   \n\t" // U0V0 U0V0(8)
2026         "pand                %%mm7, %%mm2   \n\t" // U0V0 U0V0(12)
2027         "psrlw                  $8, %%mm3   \n\t" // Y0Y0 Y0Y0(8)
2028         "psrlw                  $8, %%mm4   \n\t" // Y0Y0 Y0Y0(12)
2029         "packuswb            %%mm2, %%mm1   \n\t" // UVUV UVUV(8)
2030         "packuswb            %%mm4, %%mm3   \n\t" // YYYY YYYY(8)
2031
2032         MOVNTQ"              %%mm3, 8(%1, %%"REG_a", 2) \n\t"
2033
2034         "movq                %%mm0, %%mm2   \n\t" // UVUV UVUV(0)
2035         "movq                %%mm1, %%mm3   \n\t" // UVUV UVUV(8)
2036         "psrlw                  $8, %%mm0   \n\t" // V0V0 V0V0(0)
2037         "psrlw                  $8, %%mm1   \n\t" // V0V0 V0V0(8)
2038         "pand                %%mm7, %%mm2   \n\t" // U0U0 U0U0(0)
2039         "pand                %%mm7, %%mm3   \n\t" // U0U0 U0U0(8)
2040         "packuswb            %%mm1, %%mm0   \n\t" // VVVV VVVV(0)
2041         "packuswb            %%mm3, %%mm2   \n\t" // UUUU UUUU(0)
2042
2043         MOVNTQ"              %%mm0, (%3, %%"REG_a") \n\t"
2044         MOVNTQ"              %%mm2, (%2, %%"REG_a") \n\t"
2045
2046         "add                    $8, %%"REG_a"   \n\t"
2047         "cmp                    %4, %%"REG_a"   \n\t"
2048         " jb                    1b          \n\t"
2049         ::"r"(src), "r"(ydst), "r"(udst), "r"(vdst), "g" (chromWidth)
2050         : "memory", "%"REG_a
2051         );
2052
2053         ydst += lumStride;
2054         src  += srcStride;
2055
2056         __asm__ volatile(
2057         "xor                 %%"REG_a", %%"REG_a"   \n\t"
2058         ASMALIGN(4)
2059         "1:                                 \n\t"
2060         PREFETCH" 64(%0, %%"REG_a", 4)          \n\t"
2061         "movq       (%0, %%"REG_a", 4), %%mm0   \n\t" // YUYV YUYV(0)
2062         "movq      8(%0, %%"REG_a", 4), %%mm1   \n\t" // YUYV YUYV(4)
2063         "movq     16(%0, %%"REG_a", 4), %%mm2   \n\t" // YUYV YUYV(8)
2064         "movq     24(%0, %%"REG_a", 4), %%mm3   \n\t" // YUYV YUYV(12)
2065         "psrlw                  $8, %%mm0   \n\t" // Y0Y0 Y0Y0(0)
2066         "psrlw                  $8, %%mm1   \n\t" // Y0Y0 Y0Y0(4)
2067         "psrlw                  $8, %%mm2   \n\t" // Y0Y0 Y0Y0(8)
2068         "psrlw                  $8, %%mm3   \n\t" // Y0Y0 Y0Y0(12)
2069         "packuswb            %%mm1, %%mm0   \n\t" // YYYY YYYY(0)
2070         "packuswb            %%mm3, %%mm2   \n\t" // YYYY YYYY(8)
2071
2072         MOVNTQ"              %%mm0,  (%1, %%"REG_a", 2) \n\t"
2073         MOVNTQ"              %%mm2, 8(%1, %%"REG_a", 2) \n\t"
2074
2075         "add                    $8, %%"REG_a"   \n\t"
2076         "cmp                    %4, %%"REG_a"   \n\t"
2077         " jb                    1b          \n\t"
2078
2079         ::"r"(src), "r"(ydst), "r"(udst), "r"(vdst), "g" (chromWidth)
2080         : "memory", "%"REG_a
2081         );
2082 #else
2083         long i;
2084         for (i=0; i<chromWidth; i++)
2085         {
2086             udst[i]     = src[4*i+0];
2087             ydst[2*i+0] = src[4*i+1];
2088             vdst[i]     = src[4*i+2];
2089             ydst[2*i+1] = src[4*i+3];
2090         }
2091         ydst += lumStride;
2092         src  += srcStride;
2093
2094         for (i=0; i<chromWidth; i++)
2095         {
2096             ydst[2*i+0] = src[4*i+1];
2097             ydst[2*i+1] = src[4*i+3];
2098         }
2099 #endif
2100         udst += chromStride;
2101         vdst += chromStride;
2102         ydst += lumStride;
2103         src  += srcStride;
2104     }
2105 #if HAVE_MMX
2106 __asm__ volatile(   EMMS"       \n\t"
2107                 SFENCE"     \n\t"
2108                 :::"memory");
2109 #endif
2110 }
2111
2112 /**
2113  * Height should be a multiple of 2 and width should be a multiple of 2.
2114  * (If this is a problem for anyone then tell me, and I will fix it.)
2115  * Chrominance data is only taken from every second line,
2116  * others are ignored in the C version.
2117  * FIXME: Write HQ version.
2118  */
2119 static inline void RENAME(rgb24toyv12)(const uint8_t *src, uint8_t *ydst, uint8_t *udst, uint8_t *vdst,
2120                                        long width, long height,
2121                                        long lumStride, long chromStride, long srcStride)
2122 {
2123     long y;
2124     const x86_reg chromWidth= width>>1;
2125 #if HAVE_MMX
2126     for (y=0; y<height-2; y+=2)
2127     {
2128         long i;
2129         for (i=0; i<2; i++)
2130         {
2131             __asm__ volatile(
2132             "mov                        %2, %%"REG_a"   \n\t"
2133             "movq  "MANGLE(ff_bgr2YCoeff)", %%mm6       \n\t"
2134             "movq       "MANGLE(ff_w1111)", %%mm5       \n\t"
2135             "pxor                    %%mm7, %%mm7       \n\t"
2136             "lea (%%"REG_a", %%"REG_a", 2), %%"REG_d"   \n\t"
2137             ASMALIGN(4)
2138             "1:                                         \n\t"
2139             PREFETCH"    64(%0, %%"REG_d")              \n\t"
2140             "movd          (%0, %%"REG_d"), %%mm0       \n\t"
2141             "movd         3(%0, %%"REG_d"), %%mm1       \n\t"
2142             "punpcklbw               %%mm7, %%mm0       \n\t"
2143             "punpcklbw               %%mm7, %%mm1       \n\t"
2144             "movd         6(%0, %%"REG_d"), %%mm2       \n\t"
2145             "movd         9(%0, %%"REG_d"), %%mm3       \n\t"
2146             "punpcklbw               %%mm7, %%mm2       \n\t"
2147             "punpcklbw               %%mm7, %%mm3       \n\t"
2148             "pmaddwd                 %%mm6, %%mm0       \n\t"
2149             "pmaddwd                 %%mm6, %%mm1       \n\t"
2150             "pmaddwd                 %%mm6, %%mm2       \n\t"
2151             "pmaddwd                 %%mm6, %%mm3       \n\t"
2152 #ifndef FAST_BGR2YV12
2153             "psrad                      $8, %%mm0       \n\t"
2154             "psrad                      $8, %%mm1       \n\t"
2155             "psrad                      $8, %%mm2       \n\t"
2156             "psrad                      $8, %%mm3       \n\t"
2157 #endif
2158             "packssdw                %%mm1, %%mm0       \n\t"
2159             "packssdw                %%mm3, %%mm2       \n\t"
2160             "pmaddwd                 %%mm5, %%mm0       \n\t"
2161             "pmaddwd                 %%mm5, %%mm2       \n\t"
2162             "packssdw                %%mm2, %%mm0       \n\t"
2163             "psraw                      $7, %%mm0       \n\t"
2164
2165             "movd        12(%0, %%"REG_d"), %%mm4       \n\t"
2166             "movd        15(%0, %%"REG_d"), %%mm1       \n\t"
2167             "punpcklbw               %%mm7, %%mm4       \n\t"
2168             "punpcklbw               %%mm7, %%mm1       \n\t"
2169             "movd        18(%0, %%"REG_d"), %%mm2       \n\t"
2170             "movd        21(%0, %%"REG_d"), %%mm3       \n\t"
2171             "punpcklbw               %%mm7, %%mm2       \n\t"
2172             "punpcklbw               %%mm7, %%mm3       \n\t"
2173             "pmaddwd                 %%mm6, %%mm4       \n\t"
2174             "pmaddwd                 %%mm6, %%mm1       \n\t"
2175             "pmaddwd                 %%mm6, %%mm2       \n\t"
2176             "pmaddwd                 %%mm6, %%mm3       \n\t"
2177 #ifndef FAST_BGR2YV12
2178             "psrad                      $8, %%mm4       \n\t"
2179             "psrad                      $8, %%mm1       \n\t"
2180             "psrad                      $8, %%mm2       \n\t"
2181             "psrad                      $8, %%mm3       \n\t"
2182 #endif
2183             "packssdw                %%mm1, %%mm4       \n\t"
2184             "packssdw                %%mm3, %%mm2       \n\t"
2185             "pmaddwd                 %%mm5, %%mm4       \n\t"
2186             "pmaddwd                 %%mm5, %%mm2       \n\t"
2187             "add                       $24, %%"REG_d"   \n\t"
2188             "packssdw                %%mm2, %%mm4       \n\t"
2189             "psraw                      $7, %%mm4       \n\t"
2190
2191             "packuswb                %%mm4, %%mm0       \n\t"
2192             "paddusb "MANGLE(ff_bgr2YOffset)", %%mm0    \n\t"
2193
2194             MOVNTQ"                  %%mm0, (%1, %%"REG_a") \n\t"
2195             "add                        $8,      %%"REG_a"  \n\t"
2196             " js                        1b                  \n\t"
2197             : : "r" (src+width*3), "r" (ydst+width), "g" ((x86_reg)-width)
2198             : "%"REG_a, "%"REG_d
2199             );
2200             ydst += lumStride;
2201             src  += srcStride;
2202         }
2203         src -= srcStride*2;
2204         __asm__ volatile(
2205         "mov                        %4, %%"REG_a"   \n\t"
2206         "movq       "MANGLE(ff_w1111)", %%mm5       \n\t"
2207         "movq  "MANGLE(ff_bgr2UCoeff)", %%mm6       \n\t"
2208         "pxor                    %%mm7, %%mm7       \n\t"
2209         "lea (%%"REG_a", %%"REG_a", 2), %%"REG_d"   \n\t"
2210         "add                 %%"REG_d", %%"REG_d"   \n\t"
2211         ASMALIGN(4)
2212         "1:                                         \n\t"
2213         PREFETCH"    64(%0, %%"REG_d")              \n\t"
2214         PREFETCH"    64(%1, %%"REG_d")              \n\t"
2215 #if HAVE_MMX2 || HAVE_AMD3DNOW
2216         "movq          (%0, %%"REG_d"), %%mm0       \n\t"
2217         "movq          (%1, %%"REG_d"), %%mm1       \n\t"
2218         "movq         6(%0, %%"REG_d"), %%mm2       \n\t"
2219         "movq         6(%1, %%"REG_d"), %%mm3       \n\t"
2220         PAVGB"                   %%mm1, %%mm0       \n\t"
2221         PAVGB"                   %%mm3, %%mm2       \n\t"
2222         "movq                    %%mm0, %%mm1       \n\t"
2223         "movq                    %%mm2, %%mm3       \n\t"
2224         "psrlq                     $24, %%mm0       \n\t"
2225         "psrlq                     $24, %%mm2       \n\t"
2226         PAVGB"                   %%mm1, %%mm0       \n\t"
2227         PAVGB"                   %%mm3, %%mm2       \n\t"
2228         "punpcklbw               %%mm7, %%mm0       \n\t"
2229         "punpcklbw               %%mm7, %%mm2       \n\t"
2230 #else
2231         "movd          (%0, %%"REG_d"), %%mm0       \n\t"
2232         "movd          (%1, %%"REG_d"), %%mm1       \n\t"
2233         "movd         3(%0, %%"REG_d"), %%mm2       \n\t"
2234         "movd         3(%1, %%"REG_d"), %%mm3       \n\t"
2235         "punpcklbw               %%mm7, %%mm0       \n\t"
2236         "punpcklbw               %%mm7, %%mm1       \n\t"
2237         "punpcklbw               %%mm7, %%mm2       \n\t"
2238         "punpcklbw               %%mm7, %%mm3       \n\t"
2239         "paddw                   %%mm1, %%mm0       \n\t"
2240         "paddw                   %%mm3, %%mm2       \n\t"
2241         "paddw                   %%mm2, %%mm0       \n\t"
2242         "movd         6(%0, %%"REG_d"), %%mm4       \n\t"
2243         "movd         6(%1, %%"REG_d"), %%mm1       \n\t"
2244         "movd         9(%0, %%"REG_d"), %%mm2       \n\t"
2245         "movd         9(%1, %%"REG_d"), %%mm3       \n\t"
2246         "punpcklbw               %%mm7, %%mm4       \n\t"
2247         "punpcklbw               %%mm7, %%mm1       \n\t"
2248         "punpcklbw               %%mm7, %%mm2       \n\t"
2249         "punpcklbw               %%mm7, %%mm3       \n\t"
2250         "paddw                   %%mm1, %%mm4       \n\t"
2251         "paddw                   %%mm3, %%mm2       \n\t"
2252         "paddw                   %%mm4, %%mm2       \n\t"
2253         "psrlw                      $2, %%mm0       \n\t"
2254         "psrlw                      $2, %%mm2       \n\t"
2255 #endif
2256         "movq  "MANGLE(ff_bgr2VCoeff)", %%mm1       \n\t"
2257         "movq  "MANGLE(ff_bgr2VCoeff)", %%mm3       \n\t"
2258
2259         "pmaddwd                 %%mm0, %%mm1       \n\t"
2260         "pmaddwd                 %%mm2, %%mm3       \n\t"
2261         "pmaddwd                 %%mm6, %%mm0       \n\t"
2262         "pmaddwd                 %%mm6, %%mm2       \n\t"
2263 #ifndef FAST_BGR2YV12
2264         "psrad                      $8, %%mm0       \n\t"
2265         "psrad                      $8, %%mm1       \n\t"
2266         "psrad                      $8, %%mm2       \n\t"
2267         "psrad                      $8, %%mm3       \n\t"
2268 #endif
2269         "packssdw                %%mm2, %%mm0       \n\t"
2270         "packssdw                %%mm3, %%mm1       \n\t"
2271         "pmaddwd                 %%mm5, %%mm0       \n\t"
2272         "pmaddwd                 %%mm5, %%mm1       \n\t"
2273         "packssdw                %%mm1, %%mm0       \n\t" // V1 V0 U1 U0
2274         "psraw                      $7, %%mm0       \n\t"
2275
2276 #if HAVE_MMX2 || HAVE_AMD3DNOW
2277         "movq        12(%0, %%"REG_d"), %%mm4       \n\t"
2278         "movq        12(%1, %%"REG_d"), %%mm1       \n\t"
2279         "movq        18(%0, %%"REG_d"), %%mm2       \n\t"
2280         "movq        18(%1, %%"REG_d"), %%mm3       \n\t"
2281         PAVGB"                   %%mm1, %%mm4       \n\t"
2282         PAVGB"                   %%mm3, %%mm2       \n\t"
2283         "movq                    %%mm4, %%mm1       \n\t"
2284         "movq                    %%mm2, %%mm3       \n\t"
2285         "psrlq                     $24, %%mm4       \n\t"
2286         "psrlq                     $24, %%mm2       \n\t"
2287         PAVGB"                   %%mm1, %%mm4       \n\t"
2288         PAVGB"                   %%mm3, %%mm2       \n\t"
2289         "punpcklbw               %%mm7, %%mm4       \n\t"
2290         "punpcklbw               %%mm7, %%mm2       \n\t"
2291 #else
2292         "movd        12(%0, %%"REG_d"), %%mm4       \n\t"
2293         "movd        12(%1, %%"REG_d"), %%mm1       \n\t"
2294         "movd        15(%0, %%"REG_d"), %%mm2       \n\t"
2295         "movd        15(%1, %%"REG_d"), %%mm3       \n\t"
2296         "punpcklbw               %%mm7, %%mm4       \n\t"
2297         "punpcklbw               %%mm7, %%mm1       \n\t"
2298         "punpcklbw               %%mm7, %%mm2       \n\t"
2299         "punpcklbw               %%mm7, %%mm3       \n\t"
2300         "paddw                   %%mm1, %%mm4       \n\t"
2301         "paddw                   %%mm3, %%mm2       \n\t"
2302         "paddw                   %%mm2, %%mm4       \n\t"
2303         "movd        18(%0, %%"REG_d"), %%mm5       \n\t"
2304         "movd        18(%1, %%"REG_d"), %%mm1       \n\t"
2305         "movd        21(%0, %%"REG_d"), %%mm2       \n\t"
2306         "movd        21(%1, %%"REG_d"), %%mm3       \n\t"
2307         "punpcklbw               %%mm7, %%mm5       \n\t"
2308         "punpcklbw               %%mm7, %%mm1       \n\t"
2309         "punpcklbw               %%mm7, %%mm2       \n\t"
2310         "punpcklbw               %%mm7, %%mm3       \n\t"
2311         "paddw                   %%mm1, %%mm5       \n\t"
2312         "paddw                   %%mm3, %%mm2       \n\t"
2313         "paddw                   %%mm5, %%mm2       \n\t"
2314         "movq       "MANGLE(ff_w1111)", %%mm5       \n\t"
2315         "psrlw                      $2, %%mm4       \n\t"
2316         "psrlw                      $2, %%mm2       \n\t"
2317 #endif
2318         "movq  "MANGLE(ff_bgr2VCoeff)", %%mm1       \n\t"
2319         "movq  "MANGLE(ff_bgr2VCoeff)", %%mm3       \n\t"
2320
2321         "pmaddwd                 %%mm4, %%mm1       \n\t"
2322         "pmaddwd                 %%mm2, %%mm3       \n\t"
2323         "pmaddwd                 %%mm6, %%mm4       \n\t"
2324         "pmaddwd                 %%mm6, %%mm2       \n\t"
2325 #ifndef FAST_BGR2YV12
2326         "psrad                      $8, %%mm4       \n\t"