misc spelling fixes
[ffmpeg.git] / libswscale / rgb2rgb_template.c
1 /*
2  *  rgb2rgb.c, Software RGB to RGB convertor
3  *  pluralize by Software PAL8 to RGB convertor
4  *               Software YUV to YUV convertor
5  *               Software YUV to RGB convertor
6  *  Written by Nick Kurshev.
7  *  palette & YUV & runtime CPU stuff by Michael (michaelni@gmx.at)
8  *  lot of big-endian byteorder 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 St, 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 too
28  */
29
30 #include <stddef.h>
31 #include <inttypes.h> /* for __WORDSIZE */
32
33 #ifndef __WORDSIZE
34 // #warning You have misconfigured system and probably will lose performance!
35 #define __WORDSIZE MP_WORDSIZE
36 #endif
37
38 #undef PREFETCH
39 #undef MOVNTQ
40 #undef EMMS
41 #undef SFENCE
42 #undef MMREG_SIZE
43 #undef PREFETCHW
44 #undef PAVGB
45
46 #ifdef HAVE_SSE2
47 #define MMREG_SIZE 16
48 #else
49 #define MMREG_SIZE 8
50 #endif
51
52 #ifdef HAVE_3DNOW
53 #define PREFETCH  "prefetch"
54 #define PREFETCHW "prefetchw"
55 #define PAVGB     "pavgusb"
56 #elif defined ( HAVE_MMX2 )
57 #define PREFETCH "prefetchnta"
58 #define PREFETCHW "prefetcht0"
59 #define PAVGB     "pavgb"
60 #else
61 #ifdef __APPLE__
62 #define PREFETCH "#"
63 #define PREFETCHW "#"
64 #else
65 #define PREFETCH  " # nop"
66 #define PREFETCHW " # nop"
67 #endif
68 #endif
69
70 #ifdef HAVE_3DNOW
71 /* On K6 femms is faster of emms. On K7 femms is directly mapped on emms. */
72 #define EMMS     "femms"
73 #else
74 #define EMMS     "emms"
75 #endif
76
77 #ifdef HAVE_MMX2
78 #define MOVNTQ "movntq"
79 #define SFENCE "sfence"
80 #else
81 #define MOVNTQ "movq"
82 #define SFENCE " # nop"
83 #endif
84
85 static inline void RENAME(rgb24to32)(const uint8_t *src,uint8_t *dst,long src_size)
86 {
87     uint8_t *dest = dst;
88     const uint8_t *s = src;
89     const uint8_t *end;
90     #ifdef HAVE_MMX
91         const uint8_t *mm_end;
92     #endif
93     end = s + src_size;
94     #ifdef HAVE_MMX
95         __asm __volatile(PREFETCH"    %0"::"m"(*s):"memory");
96         mm_end = end - 23;
97         __asm __volatile("movq        %0, %%mm7"::"m"(mask32):"memory");
98         while (s < mm_end)
99         {
100             __asm __volatile(
101             PREFETCH"    32%1           \n\t"
102             "movd          %1, %%mm0    \n\t"
103             "punpckldq    3%1, %%mm0    \n\t"
104             "movd         6%1, %%mm1    \n\t"
105             "punpckldq    9%1, %%mm1    \n\t"
106             "movd        12%1, %%mm2    \n\t"
107             "punpckldq   15%1, %%mm2    \n\t"
108             "movd        18%1, %%mm3    \n\t"
109             "punpckldq   21%1, %%mm3    \n\t"
110             "pand       %%mm7, %%mm0    \n\t"
111             "pand       %%mm7, %%mm1    \n\t"
112             "pand       %%mm7, %%mm2    \n\t"
113             "pand       %%mm7, %%mm3    \n\t"
114             MOVNTQ"     %%mm0,   %0     \n\t"
115             MOVNTQ"     %%mm1,  8%0     \n\t"
116             MOVNTQ"     %%mm2, 16%0     \n\t"
117             MOVNTQ"     %%mm3, 24%0"
118             :"=m"(*dest)
119             :"m"(*s)
120             :"memory");
121             dest += 32;
122             s += 24;
123         }
124         __asm __volatile(SFENCE:::"memory");
125         __asm __volatile(EMMS:::"memory");
126     #endif
127     while (s < end)
128     {
129     #ifdef WORDS_BIGENDIAN
130         /* RGB24 (= R,G,B) -> RGB32 (= A,B,G,R) */
131         *dest++ = 0;
132         *dest++ = s[2];
133         *dest++ = s[1];
134         *dest++ = s[0];
135         s+=3;
136     #else
137         *dest++ = *s++;
138         *dest++ = *s++;
139         *dest++ = *s++;
140         *dest++ = 0;
141     #endif
142     }
143 }
144
145 static inline void RENAME(rgb32to24)(const uint8_t *src,uint8_t *dst,long src_size)
146 {
147     uint8_t *dest = dst;
148     const uint8_t *s = src;
149     const uint8_t *end;
150 #ifdef HAVE_MMX
151     const uint8_t *mm_end;
152 #endif
153     end = s + src_size;
154 #ifdef HAVE_MMX
155     __asm __volatile(PREFETCH"    %0"::"m"(*s):"memory");
156     mm_end = end - 31;
157     while (s < mm_end)
158     {
159         __asm __volatile(
160         PREFETCH"    32%1           \n\t"
161         "movq          %1, %%mm0    \n\t"
162         "movq         8%1, %%mm1    \n\t"
163         "movq        16%1, %%mm4    \n\t"
164         "movq        24%1, %%mm5    \n\t"
165         "movq       %%mm0, %%mm2    \n\t"
166         "movq       %%mm1, %%mm3    \n\t"
167         "movq       %%mm4, %%mm6    \n\t"
168         "movq       %%mm5, %%mm7    \n\t"
169         "psrlq         $8, %%mm2    \n\t"
170         "psrlq         $8, %%mm3    \n\t"
171         "psrlq         $8, %%mm6    \n\t"
172         "psrlq         $8, %%mm7    \n\t"
173         "pand          %2, %%mm0    \n\t"
174         "pand          %2, %%mm1    \n\t"
175         "pand          %2, %%mm4    \n\t"
176         "pand          %2, %%mm5    \n\t"
177         "pand          %3, %%mm2    \n\t"
178         "pand          %3, %%mm3    \n\t"
179         "pand          %3, %%mm6    \n\t"
180         "pand          %3, %%mm7    \n\t"
181         "por        %%mm2, %%mm0    \n\t"
182         "por        %%mm3, %%mm1    \n\t"
183         "por        %%mm6, %%mm4    \n\t"
184         "por        %%mm7, %%mm5    \n\t"
185
186         "movq       %%mm1, %%mm2    \n\t"
187         "movq       %%mm4, %%mm3    \n\t"
188         "psllq        $48, %%mm2    \n\t"
189         "psllq        $32, %%mm3    \n\t"
190         "pand          %4, %%mm2    \n\t"
191         "pand          %5, %%mm3    \n\t"
192         "por        %%mm2, %%mm0    \n\t"
193         "psrlq        $16, %%mm1    \n\t"
194         "psrlq        $32, %%mm4    \n\t"
195         "psllq        $16, %%mm5    \n\t"
196         "por        %%mm3, %%mm1    \n\t"
197         "pand          %6, %%mm5    \n\t"
198         "por        %%mm5, %%mm4    \n\t"
199
200         MOVNTQ"     %%mm0,   %0     \n\t"
201         MOVNTQ"     %%mm1,  8%0     \n\t"
202         MOVNTQ"     %%mm4, 16%0"
203         :"=m"(*dest)
204         :"m"(*s),"m"(mask24l),
205          "m"(mask24h),"m"(mask24hh),"m"(mask24hhh),"m"(mask24hhhh)
206         :"memory");
207         dest += 24;
208         s += 32;
209     }
210     __asm __volatile(SFENCE:::"memory");
211     __asm __volatile(EMMS:::"memory");
212 #endif
213     while (s < end)
214     {
215 #ifdef WORDS_BIGENDIAN
216         /* RGB32 (= A,B,G,R) -> RGB24 (= R,G,B) */
217         s++;
218         dest[2] = *s++;
219         dest[1] = *s++;
220         dest[0] = *s++;
221         dest += 3;
222 #else
223         *dest++ = *s++;
224         *dest++ = *s++;
225         *dest++ = *s++;
226         s++;
227 #endif
228     }
229 }
230
231 /*
232  Original by Strepto/Astral
233  ported to gcc & bugfixed : A'rpi
234  MMX2, 3DNOW optimization by Nick Kurshev
235  32bit c version, and and&add trick by Michael Niedermayer
236 */
237 static inline void RENAME(rgb15to16)(const uint8_t *src,uint8_t *dst,long src_size)
238 {
239     register const uint8_t* s=src;
240     register uint8_t* d=dst;
241     register const uint8_t *end;
242     const uint8_t *mm_end;
243     end = s + src_size;
244 #ifdef HAVE_MMX
245     __asm __volatile(PREFETCH"    %0"::"m"(*s));
246     __asm __volatile("movq        %0, %%mm4"::"m"(mask15s));
247     mm_end = end - 15;
248     while (s<mm_end)
249     {
250         __asm __volatile(
251         PREFETCH"  32%1         \n\t"
252         "movq        %1, %%mm0  \n\t"
253         "movq       8%1, %%mm2  \n\t"
254         "movq     %%mm0, %%mm1  \n\t"
255         "movq     %%mm2, %%mm3  \n\t"
256         "pand     %%mm4, %%mm0  \n\t"
257         "pand     %%mm4, %%mm2  \n\t"
258         "paddw    %%mm1, %%mm0  \n\t"
259         "paddw    %%mm3, %%mm2  \n\t"
260         MOVNTQ"   %%mm0,  %0    \n\t"
261         MOVNTQ"   %%mm2, 8%0"
262         :"=m"(*d)
263         :"m"(*s)
264         );
265         d+=16;
266         s+=16;
267     }
268     __asm __volatile(SFENCE:::"memory");
269     __asm __volatile(EMMS:::"memory");
270 #endif
271     mm_end = end - 3;
272     while (s < mm_end)
273     {
274         register unsigned x= *((uint32_t *)s);
275         *((uint32_t *)d) = (x&0x7FFF7FFF) + (x&0x7FE07FE0);
276         d+=4;
277         s+=4;
278     }
279     if (s < end)
280     {
281         register unsigned short x= *((uint16_t *)s);
282         *((uint16_t *)d) = (x&0x7FFF) + (x&0x7FE0);
283     }
284 }
285
286 static inline void RENAME(rgb16to15)(const uint8_t *src,uint8_t *dst,long src_size)
287 {
288     register const uint8_t* s=src;
289     register uint8_t* d=dst;
290     register const uint8_t *end;
291     const uint8_t *mm_end;
292     end = s + src_size;
293 #ifdef HAVE_MMX
294     __asm __volatile(PREFETCH"    %0"::"m"(*s));
295     __asm __volatile("movq        %0, %%mm7"::"m"(mask15rg));
296     __asm __volatile("movq        %0, %%mm6"::"m"(mask15b));
297     mm_end = end - 15;
298     while (s<mm_end)
299     {
300         __asm __volatile(
301         PREFETCH"  32%1         \n\t"
302         "movq        %1, %%mm0  \n\t"
303         "movq       8%1, %%mm2  \n\t"
304         "movq     %%mm0, %%mm1  \n\t"
305         "movq     %%mm2, %%mm3  \n\t"
306         "psrlq       $1, %%mm0  \n\t"
307         "psrlq       $1, %%mm2  \n\t"
308         "pand     %%mm7, %%mm0  \n\t"
309         "pand     %%mm7, %%mm2  \n\t"
310         "pand     %%mm6, %%mm1  \n\t"
311         "pand     %%mm6, %%mm3  \n\t"
312         "por      %%mm1, %%mm0  \n\t"
313         "por      %%mm3, %%mm2  \n\t"
314         MOVNTQ"   %%mm0,  %0    \n\t"
315         MOVNTQ"   %%mm2, 8%0"
316         :"=m"(*d)
317         :"m"(*s)
318         );
319         d+=16;
320         s+=16;
321     }
322     __asm __volatile(SFENCE:::"memory");
323     __asm __volatile(EMMS:::"memory");
324 #endif
325     mm_end = end - 3;
326     while (s < mm_end)
327     {
328         register uint32_t x= *((uint32_t *)s);
329         *((uint32_t *)d) = ((x>>1)&0x7FE07FE0) | (x&0x001F001F);
330         s+=4;
331         d+=4;
332     }
333     if (s < end)
334     {
335         register uint16_t x= *((uint16_t *)s);
336         *((uint16_t *)d) = ((x>>1)&0x7FE0) | (x&0x001F);
337         s+=2;
338         d+=2;
339     }
340 }
341
342 static inline void RENAME(rgb32to16)(const uint8_t *src, uint8_t *dst, long src_size)
343 {
344     const uint8_t *s = src;
345     const uint8_t *end;
346 #ifdef HAVE_MMX
347     const uint8_t *mm_end;
348 #endif
349     uint16_t *d = (uint16_t *)dst;
350     end = s + src_size;
351 #ifdef HAVE_MMX
352     mm_end = end - 15;
353 #if 1 //is faster only if multiplies are reasonable fast (FIXME figure out on which CPUs this is faster, on Athlon it is slightly faster)
354     asm volatile(
355     "movq           %3, %%mm5   \n\t"
356     "movq           %4, %%mm6   \n\t"
357     "movq           %5, %%mm7   \n\t"
358     "jmp 2f                     \n\t"
359     ASMALIGN(4)
360     "1:                         \n\t"
361     PREFETCH"   32(%1)          \n\t"
362     "movd         (%1), %%mm0   \n\t"
363     "movd        4(%1), %%mm3   \n\t"
364     "punpckldq   8(%1), %%mm0   \n\t"
365     "punpckldq  12(%1), %%mm3   \n\t"
366     "movq        %%mm0, %%mm1   \n\t"
367     "movq        %%mm3, %%mm4   \n\t"
368     "pand        %%mm6, %%mm0   \n\t"
369     "pand        %%mm6, %%mm3   \n\t"
370     "pmaddwd     %%mm7, %%mm0   \n\t"
371     "pmaddwd     %%mm7, %%mm3   \n\t"
372     "pand        %%mm5, %%mm1   \n\t"
373     "pand        %%mm5, %%mm4   \n\t"
374     "por         %%mm1, %%mm0   \n\t"
375     "por         %%mm4, %%mm3   \n\t"
376     "psrld          $5, %%mm0   \n\t"
377     "pslld         $11, %%mm3   \n\t"
378     "por         %%mm3, %%mm0   \n\t"
379     MOVNTQ"      %%mm0, (%0)    \n\t"
380     "add           $16,  %1     \n\t"
381     "add            $8,  %0     \n\t"
382     "2:                         \n\t"
383     "cmp            %2,  %1     \n\t"
384     " jb            1b          \n\t"
385     : "+r" (d), "+r"(s)
386     : "r" (mm_end), "m" (mask3216g), "m" (mask3216br), "m" (mul3216)
387     );
388 #else
389     __asm __volatile(PREFETCH"    %0"::"m"(*src):"memory");
390     __asm __volatile(
391         "movq    %0, %%mm7    \n\t"
392         "movq    %1, %%mm6    \n\t"
393         ::"m"(red_16mask),"m"(green_16mask));
394     while (s < mm_end)
395     {
396         __asm __volatile(
397         PREFETCH"    32%1           \n\t"
398         "movd          %1, %%mm0    \n\t"
399         "movd         4%1, %%mm3    \n\t"
400         "punpckldq    8%1, %%mm0    \n\t"
401         "punpckldq   12%1, %%mm3    \n\t"
402         "movq       %%mm0, %%mm1    \n\t"
403         "movq       %%mm0, %%mm2    \n\t"
404         "movq       %%mm3, %%mm4    \n\t"
405         "movq       %%mm3, %%mm5    \n\t"
406         "psrlq         $3, %%mm0    \n\t"
407         "psrlq         $3, %%mm3    \n\t"
408         "pand          %2, %%mm0    \n\t"
409         "pand          %2, %%mm3    \n\t"
410         "psrlq         $5, %%mm1    \n\t"
411         "psrlq         $5, %%mm4    \n\t"
412         "pand       %%mm6, %%mm1    \n\t"
413         "pand       %%mm6, %%mm4    \n\t"
414         "psrlq         $8, %%mm2    \n\t"
415         "psrlq         $8, %%mm5    \n\t"
416         "pand       %%mm7, %%mm2    \n\t"
417         "pand       %%mm7, %%mm5    \n\t"
418         "por        %%mm1, %%mm0    \n\t"
419         "por        %%mm4, %%mm3    \n\t"
420         "por        %%mm2, %%mm0    \n\t"
421         "por        %%mm5, %%mm3    \n\t"
422         "psllq        $16, %%mm3    \n\t"
423         "por        %%mm3, %%mm0    \n\t"
424         MOVNTQ"     %%mm0, %0       \n\t"
425         :"=m"(*d):"m"(*s),"m"(blue_16mask):"memory");
426         d += 4;
427         s += 16;
428     }
429 #endif
430     __asm __volatile(SFENCE:::"memory");
431     __asm __volatile(EMMS:::"memory");
432 #endif
433     while (s < end)
434     {
435         register int rgb = *(uint32_t*)s; s += 4;
436         *d++ = ((rgb&0xFF)>>3) + ((rgb&0xFC00)>>5) + ((rgb&0xF80000)>>8);
437     }
438 }
439
440 static inline void RENAME(rgb32tobgr16)(const uint8_t *src, uint8_t *dst, long src_size)
441 {
442     const uint8_t *s = src;
443     const uint8_t *end;
444 #ifdef HAVE_MMX
445     const uint8_t *mm_end;
446 #endif
447     uint16_t *d = (uint16_t *)dst;
448     end = s + src_size;
449 #ifdef HAVE_MMX
450     __asm __volatile(PREFETCH"    %0"::"m"(*src):"memory");
451     __asm __volatile(
452         "movq          %0, %%mm7    \n\t"
453         "movq          %1, %%mm6    \n\t"
454         ::"m"(red_16mask),"m"(green_16mask));
455     mm_end = end - 15;
456     while (s < mm_end)
457     {
458         __asm __volatile(
459         PREFETCH"    32%1           \n\t"
460         "movd          %1, %%mm0    \n\t"
461         "movd         4%1, %%mm3    \n\t"
462         "punpckldq    8%1, %%mm0    \n\t"
463         "punpckldq   12%1, %%mm3    \n\t"
464         "movq       %%mm0, %%mm1    \n\t"
465         "movq       %%mm0, %%mm2    \n\t"
466         "movq       %%mm3, %%mm4    \n\t"
467         "movq       %%mm3, %%mm5    \n\t"
468         "psllq         $8, %%mm0    \n\t"
469         "psllq         $8, %%mm3    \n\t"
470         "pand       %%mm7, %%mm0    \n\t"
471         "pand       %%mm7, %%mm3    \n\t"
472         "psrlq         $5, %%mm1    \n\t"
473         "psrlq         $5, %%mm4    \n\t"
474         "pand       %%mm6, %%mm1    \n\t"
475         "pand       %%mm6, %%mm4    \n\t"
476         "psrlq        $19, %%mm2    \n\t"
477         "psrlq        $19, %%mm5    \n\t"
478         "pand          %2, %%mm2    \n\t"
479         "pand          %2, %%mm5    \n\t"
480         "por        %%mm1, %%mm0    \n\t"
481         "por        %%mm4, %%mm3    \n\t"
482         "por        %%mm2, %%mm0    \n\t"
483         "por        %%mm5, %%mm3    \n\t"
484         "psllq        $16, %%mm3    \n\t"
485         "por        %%mm3, %%mm0    \n\t"
486         MOVNTQ"     %%mm0, %0       \n\t"
487         :"=m"(*d):"m"(*s),"m"(blue_16mask):"memory");
488         d += 4;
489         s += 16;
490     }
491     __asm __volatile(SFENCE:::"memory");
492     __asm __volatile(EMMS:::"memory");
493 #endif
494     while (s < end)
495     {
496         register int rgb = *(uint32_t*)s; s += 4;
497         *d++ = ((rgb&0xF8)<<8) + ((rgb&0xFC00)>>5) + ((rgb&0xF80000)>>19);
498     }
499 }
500
501 static inline void RENAME(rgb32to15)(const uint8_t *src, uint8_t *dst, long src_size)
502 {
503     const uint8_t *s = src;
504     const uint8_t *end;
505 #ifdef HAVE_MMX
506     const uint8_t *mm_end;
507 #endif
508     uint16_t *d = (uint16_t *)dst;
509     end = s + src_size;
510 #ifdef HAVE_MMX
511     mm_end = end - 15;
512 #if 1 //is faster only if multiplies are reasonable fast (FIXME figure out on which CPUs this is faster, on Athlon it is slightly faster)
513     asm volatile(
514     "movq           %3, %%mm5   \n\t"
515     "movq           %4, %%mm6   \n\t"
516     "movq           %5, %%mm7   \n\t"
517     "jmp            2f          \n\t"
518     ASMALIGN(4)
519     "1:                         \n\t"
520     PREFETCH"   32(%1)          \n\t"
521     "movd         (%1), %%mm0   \n\t"
522     "movd        4(%1), %%mm3   \n\t"
523     "punpckldq   8(%1), %%mm0   \n\t"
524     "punpckldq  12(%1), %%mm3   \n\t"
525     "movq        %%mm0, %%mm1   \n\t"
526     "movq        %%mm3, %%mm4   \n\t"
527     "pand        %%mm6, %%mm0   \n\t"
528     "pand        %%mm6, %%mm3   \n\t"
529     "pmaddwd     %%mm7, %%mm0   \n\t"
530     "pmaddwd     %%mm7, %%mm3   \n\t"
531     "pand        %%mm5, %%mm1   \n\t"
532     "pand        %%mm5, %%mm4   \n\t"
533     "por         %%mm1, %%mm0   \n\t"
534     "por         %%mm4, %%mm3   \n\t"
535     "psrld          $6, %%mm0   \n\t"
536     "pslld         $10, %%mm3   \n\t"
537     "por         %%mm3, %%mm0   \n\t"
538     MOVNTQ"      %%mm0, (%0)    \n\t"
539     "add           $16,  %1     \n\t"
540     "add            $8,  %0     \n\t"
541     "2:                         \n\t"
542     "cmp            %2,  %1     \n\t"
543     " jb            1b          \n\t"
544     : "+r" (d), "+r"(s)
545     : "r" (mm_end), "m" (mask3215g), "m" (mask3216br), "m" (mul3215)
546     );
547 #else
548     __asm __volatile(PREFETCH"    %0"::"m"(*src):"memory");
549     __asm __volatile(
550         "movq          %0, %%mm7    \n\t"
551         "movq          %1, %%mm6    \n\t"
552         ::"m"(red_15mask),"m"(green_15mask));
553     while (s < mm_end)
554     {
555         __asm __volatile(
556         PREFETCH"    32%1           \n\t"
557         "movd          %1, %%mm0    \n\t"
558         "movd         4%1, %%mm3    \n\t"
559         "punpckldq    8%1, %%mm0    \n\t"
560         "punpckldq   12%1, %%mm3    \n\t"
561         "movq       %%mm0, %%mm1    \n\t"
562         "movq       %%mm0, %%mm2    \n\t"
563         "movq       %%mm3, %%mm4    \n\t"
564         "movq       %%mm3, %%mm5    \n\t"
565         "psrlq         $3, %%mm0    \n\t"
566         "psrlq         $3, %%mm3    \n\t"
567         "pand          %2, %%mm0    \n\t"
568         "pand          %2, %%mm3    \n\t"
569         "psrlq         $6, %%mm1    \n\t"
570         "psrlq         $6, %%mm4    \n\t"
571         "pand       %%mm6, %%mm1    \n\t"
572         "pand       %%mm6, %%mm4    \n\t"
573         "psrlq         $9, %%mm2    \n\t"
574         "psrlq         $9, %%mm5    \n\t"
575         "pand       %%mm7, %%mm2    \n\t"
576         "pand       %%mm7, %%mm5    \n\t"
577         "por        %%mm1, %%mm0    \n\t"
578         "por        %%mm4, %%mm3    \n\t"
579         "por        %%mm2, %%mm0    \n\t"
580         "por        %%mm5, %%mm3    \n\t"
581         "psllq        $16, %%mm3    \n\t"
582         "por        %%mm3, %%mm0    \n\t"
583         MOVNTQ"     %%mm0, %0       \n\t"
584         :"=m"(*d):"m"(*s),"m"(blue_15mask):"memory");
585         d += 4;
586         s += 16;
587     }
588 #endif
589     __asm __volatile(SFENCE:::"memory");
590     __asm __volatile(EMMS:::"memory");
591 #endif
592     while (s < end)
593     {
594         register int rgb = *(uint32_t*)s; s += 4;
595         *d++ = ((rgb&0xFF)>>3) + ((rgb&0xF800)>>6) + ((rgb&0xF80000)>>9);
596     }
597 }
598
599 static inline void RENAME(rgb32tobgr15)(const uint8_t *src, uint8_t *dst, long src_size)
600 {
601     const uint8_t *s = src;
602     const uint8_t *end;
603 #ifdef HAVE_MMX
604     const uint8_t *mm_end;
605 #endif
606     uint16_t *d = (uint16_t *)dst;
607     end = s + src_size;
608 #ifdef HAVE_MMX
609     __asm __volatile(PREFETCH"    %0"::"m"(*src):"memory");
610     __asm __volatile(
611         "movq          %0, %%mm7    \n\t"
612         "movq          %1, %%mm6    \n\t"
613         ::"m"(red_15mask),"m"(green_15mask));
614     mm_end = end - 15;
615     while (s < mm_end)
616     {
617         __asm __volatile(
618         PREFETCH"    32%1           \n\t"
619         "movd          %1, %%mm0    \n\t"
620         "movd         4%1, %%mm3    \n\t"
621         "punpckldq    8%1, %%mm0    \n\t"
622         "punpckldq   12%1, %%mm3    \n\t"
623         "movq       %%mm0, %%mm1    \n\t"
624         "movq       %%mm0, %%mm2    \n\t"
625         "movq       %%mm3, %%mm4    \n\t"
626         "movq       %%mm3, %%mm5    \n\t"
627         "psllq         $7, %%mm0    \n\t"
628         "psllq         $7, %%mm3    \n\t"
629         "pand       %%mm7, %%mm0    \n\t"
630         "pand       %%mm7, %%mm3    \n\t"
631         "psrlq         $6, %%mm1    \n\t"
632         "psrlq         $6, %%mm4    \n\t"
633         "pand       %%mm6, %%mm1    \n\t"
634         "pand       %%mm6, %%mm4    \n\t"
635         "psrlq        $19, %%mm2    \n\t"
636         "psrlq        $19, %%mm5    \n\t"
637         "pand          %2, %%mm2    \n\t"
638         "pand          %2, %%mm5    \n\t"
639         "por        %%mm1, %%mm0    \n\t"
640         "por        %%mm4, %%mm3    \n\t"
641         "por        %%mm2, %%mm0    \n\t"
642         "por        %%mm5, %%mm3    \n\t"
643         "psllq        $16, %%mm3    \n\t"
644         "por        %%mm3, %%mm0    \n\t"
645         MOVNTQ"     %%mm0, %0       \n\t"
646         :"=m"(*d):"m"(*s),"m"(blue_15mask):"memory");
647         d += 4;
648         s += 16;
649     }
650     __asm __volatile(SFENCE:::"memory");
651     __asm __volatile(EMMS:::"memory");
652 #endif
653     while (s < end)
654     {
655         register int rgb = *(uint32_t*)s; s += 4;
656         *d++ = ((rgb&0xF8)<<7) + ((rgb&0xF800)>>6) + ((rgb&0xF80000)>>19);
657     }
658 }
659
660 static inline void RENAME(rgb24to16)(const uint8_t *src, uint8_t *dst, long src_size)
661 {
662     const uint8_t *s = src;
663     const uint8_t *end;
664 #ifdef HAVE_MMX
665     const uint8_t *mm_end;
666 #endif
667     uint16_t *d = (uint16_t *)dst;
668     end = s + src_size;
669 #ifdef HAVE_MMX
670     __asm __volatile(PREFETCH"    %0"::"m"(*src):"memory");
671     __asm __volatile(
672         "movq         %0, %%mm7     \n\t"
673         "movq         %1, %%mm6     \n\t"
674         ::"m"(red_16mask),"m"(green_16mask));
675     mm_end = end - 11;
676     while (s < mm_end)
677     {
678         __asm __volatile(
679         PREFETCH"    32%1           \n\t"
680         "movd          %1, %%mm0    \n\t"
681         "movd         3%1, %%mm3    \n\t"
682         "punpckldq    6%1, %%mm0    \n\t"
683         "punpckldq    9%1, %%mm3    \n\t"
684         "movq       %%mm0, %%mm1    \n\t"
685         "movq       %%mm0, %%mm2    \n\t"
686         "movq       %%mm3, %%mm4    \n\t"
687         "movq       %%mm3, %%mm5    \n\t"
688         "psrlq         $3, %%mm0    \n\t"
689         "psrlq         $3, %%mm3    \n\t"
690         "pand          %2, %%mm0    \n\t"
691         "pand          %2, %%mm3    \n\t"
692         "psrlq         $5, %%mm1    \n\t"
693         "psrlq         $5, %%mm4    \n\t"
694         "pand       %%mm6, %%mm1    \n\t"
695         "pand       %%mm6, %%mm4    \n\t"
696         "psrlq         $8, %%mm2    \n\t"
697         "psrlq         $8, %%mm5    \n\t"
698         "pand       %%mm7, %%mm2    \n\t"
699         "pand       %%mm7, %%mm5    \n\t"
700         "por        %%mm1, %%mm0    \n\t"
701         "por        %%mm4, %%mm3    \n\t"
702         "por        %%mm2, %%mm0    \n\t"
703         "por        %%mm5, %%mm3    \n\t"
704         "psllq        $16, %%mm3    \n\t"
705         "por        %%mm3, %%mm0    \n\t"
706         MOVNTQ"     %%mm0, %0       \n\t"
707         :"=m"(*d):"m"(*s),"m"(blue_16mask):"memory");
708         d += 4;
709         s += 12;
710     }
711     __asm __volatile(SFENCE:::"memory");
712     __asm __volatile(EMMS:::"memory");
713 #endif
714     while (s < end)
715     {
716         const int b = *s++;
717         const int g = *s++;
718         const int r = *s++;
719         *d++ = (b>>3) | ((g&0xFC)<<3) | ((r&0xF8)<<8);
720     }
721 }
722
723 static inline void RENAME(rgb24tobgr16)(const uint8_t *src, uint8_t *dst, long src_size)
724 {
725     const uint8_t *s = src;
726     const uint8_t *end;
727 #ifdef HAVE_MMX
728     const uint8_t *mm_end;
729 #endif
730     uint16_t *d = (uint16_t *)dst;
731     end = s + src_size;
732 #ifdef HAVE_MMX
733     __asm __volatile(PREFETCH"    %0"::"m"(*src):"memory");
734     __asm __volatile(
735         "movq         %0, %%mm7     \n\t"
736         "movq         %1, %%mm6     \n\t"
737         ::"m"(red_16mask),"m"(green_16mask));
738     mm_end = end - 15;
739     while (s < mm_end)
740     {
741         __asm __volatile(
742         PREFETCH"    32%1           \n\t"
743         "movd          %1, %%mm0    \n\t"
744         "movd         3%1, %%mm3    \n\t"
745         "punpckldq    6%1, %%mm0    \n\t"
746         "punpckldq    9%1, %%mm3    \n\t"
747         "movq       %%mm0, %%mm1    \n\t"
748         "movq       %%mm0, %%mm2    \n\t"
749         "movq       %%mm3, %%mm4    \n\t"
750         "movq       %%mm3, %%mm5    \n\t"
751         "psllq         $8, %%mm0    \n\t"
752         "psllq         $8, %%mm3    \n\t"
753         "pand       %%mm7, %%mm0    \n\t"
754         "pand       %%mm7, %%mm3    \n\t"
755         "psrlq         $5, %%mm1    \n\t"
756         "psrlq         $5, %%mm4    \n\t"
757         "pand       %%mm6, %%mm1    \n\t"
758         "pand       %%mm6, %%mm4    \n\t"
759         "psrlq        $19, %%mm2    \n\t"
760         "psrlq        $19, %%mm5    \n\t"
761         "pand          %2, %%mm2    \n\t"
762         "pand          %2, %%mm5    \n\t"
763         "por        %%mm1, %%mm0    \n\t"
764         "por        %%mm4, %%mm3    \n\t"
765         "por        %%mm2, %%mm0    \n\t"
766         "por        %%mm5, %%mm3    \n\t"
767         "psllq        $16, %%mm3    \n\t"
768         "por        %%mm3, %%mm0    \n\t"
769         MOVNTQ"     %%mm0, %0       \n\t"
770         :"=m"(*d):"m"(*s),"m"(blue_16mask):"memory");
771         d += 4;
772         s += 12;
773     }
774     __asm __volatile(SFENCE:::"memory");
775     __asm __volatile(EMMS:::"memory");
776 #endif
777     while (s < end)
778     {
779         const int r = *s++;
780         const int g = *s++;
781         const int b = *s++;
782         *d++ = (b>>3) | ((g&0xFC)<<3) | ((r&0xF8)<<8);
783     }
784 }
785
786 static inline void RENAME(rgb24to15)(const uint8_t *src, uint8_t *dst, long src_size)
787 {
788     const uint8_t *s = src;
789     const uint8_t *end;
790 #ifdef HAVE_MMX
791     const uint8_t *mm_end;
792 #endif
793     uint16_t *d = (uint16_t *)dst;
794     end = s + src_size;
795 #ifdef HAVE_MMX
796     __asm __volatile(PREFETCH"    %0"::"m"(*src):"memory");
797     __asm __volatile(
798         "movq          %0, %%mm7    \n\t"
799         "movq          %1, %%mm6    \n\t"
800         ::"m"(red_15mask),"m"(green_15mask));
801     mm_end = end - 11;
802     while (s < mm_end)
803     {
804         __asm __volatile(
805         PREFETCH"    32%1           \n\t"
806         "movd          %1, %%mm0    \n\t"
807         "movd         3%1, %%mm3    \n\t"
808         "punpckldq    6%1, %%mm0    \n\t"
809         "punpckldq    9%1, %%mm3    \n\t"
810         "movq       %%mm0, %%mm1    \n\t"
811         "movq       %%mm0, %%mm2    \n\t"
812         "movq       %%mm3, %%mm4    \n\t"
813         "movq       %%mm3, %%mm5    \n\t"
814         "psrlq         $3, %%mm0    \n\t"
815         "psrlq         $3, %%mm3    \n\t"
816         "pand          %2, %%mm0    \n\t"
817         "pand          %2, %%mm3    \n\t"
818         "psrlq         $6, %%mm1    \n\t"
819         "psrlq         $6, %%mm4    \n\t"
820         "pand       %%mm6, %%mm1    \n\t"
821         "pand       %%mm6, %%mm4    \n\t"
822         "psrlq         $9, %%mm2    \n\t"
823         "psrlq         $9, %%mm5    \n\t"
824         "pand       %%mm7, %%mm2    \n\t"
825         "pand       %%mm7, %%mm5    \n\t"
826         "por        %%mm1, %%mm0    \n\t"
827         "por        %%mm4, %%mm3    \n\t"
828         "por        %%mm2, %%mm0    \n\t"
829         "por        %%mm5, %%mm3    \n\t"
830         "psllq        $16, %%mm3    \n\t"
831         "por        %%mm3, %%mm0    \n\t"
832         MOVNTQ"     %%mm0, %0       \n\t"
833         :"=m"(*d):"m"(*s),"m"(blue_15mask):"memory");
834         d += 4;
835         s += 12;
836     }
837     __asm __volatile(SFENCE:::"memory");
838     __asm __volatile(EMMS:::"memory");
839 #endif
840     while (s < end)
841     {
842         const int b = *s++;
843         const int g = *s++;
844         const int r = *s++;
845         *d++ = (b>>3) | ((g&0xF8)<<2) | ((r&0xF8)<<7);
846     }
847 }
848
849 static inline void RENAME(rgb24tobgr15)(const uint8_t *src, uint8_t *dst, long src_size)
850 {
851     const uint8_t *s = src;
852     const uint8_t *end;
853 #ifdef HAVE_MMX
854     const uint8_t *mm_end;
855 #endif
856     uint16_t *d = (uint16_t *)dst;
857     end = s + src_size;
858 #ifdef HAVE_MMX
859     __asm __volatile(PREFETCH"    %0"::"m"(*src):"memory");
860     __asm __volatile(
861         "movq         %0, %%mm7     \n\t"
862         "movq         %1, %%mm6     \n\t"
863         ::"m"(red_15mask),"m"(green_15mask));
864     mm_end = end - 15;
865     while (s < mm_end)
866     {
867         __asm __volatile(
868         PREFETCH"   32%1            \n\t"
869         "movd         %1, %%mm0     \n\t"
870         "movd        3%1, %%mm3     \n\t"
871         "punpckldq   6%1, %%mm0     \n\t"
872         "punpckldq   9%1, %%mm3     \n\t"
873         "movq      %%mm0, %%mm1     \n\t"
874         "movq      %%mm0, %%mm2     \n\t"
875         "movq      %%mm3, %%mm4     \n\t"
876         "movq      %%mm3, %%mm5     \n\t"
877         "psllq        $7, %%mm0     \n\t"
878         "psllq        $7, %%mm3     \n\t"
879         "pand      %%mm7, %%mm0     \n\t"
880         "pand      %%mm7, %%mm3     \n\t"
881         "psrlq        $6, %%mm1     \n\t"
882         "psrlq        $6, %%mm4     \n\t"
883         "pand      %%mm6, %%mm1     \n\t"
884         "pand      %%mm6, %%mm4     \n\t"
885         "psrlq       $19, %%mm2     \n\t"
886         "psrlq       $19, %%mm5     \n\t"
887         "pand         %2, %%mm2     \n\t"
888         "pand         %2, %%mm5     \n\t"
889         "por       %%mm1, %%mm0     \n\t"
890         "por       %%mm4, %%mm3     \n\t"
891         "por       %%mm2, %%mm0     \n\t"
892         "por       %%mm5, %%mm3     \n\t"
893         "psllq       $16, %%mm3     \n\t"
894         "por       %%mm3, %%mm0     \n\t"
895         MOVNTQ"    %%mm0, %0        \n\t"
896         :"=m"(*d):"m"(*s),"m"(blue_15mask):"memory");
897         d += 4;
898         s += 12;
899     }
900     __asm __volatile(SFENCE:::"memory");
901     __asm __volatile(EMMS:::"memory");
902 #endif
903     while (s < end)
904     {
905         const int r = *s++;
906         const int g = *s++;
907         const int b = *s++;
908         *d++ = (b>>3) | ((g&0xF8)<<2) | ((r&0xF8)<<7);
909     }
910 }
911
912 /*
913   I use here less accurate approximation by simply
914  left-shifting the input
915   value and filling the low order bits with
916  zeroes. This method improves png's
917   compression but this scheme cannot reproduce white exactly, since it does not
918   generate an all-ones maximum value; the net effect is to darken the
919   image slightly.
920
921   The better method should be "left bit replication":
922
923    4 3 2 1 0
924    ---------
925    1 1 0 1 1
926
927    7 6 5 4 3  2 1 0
928    ----------------
929    1 1 0 1 1  1 1 0
930    |=======|  |===|
931        |      Leftmost Bits Repeated to Fill Open Bits
932        |
933    Original Bits
934 */
935 static inline void RENAME(rgb15to24)(const uint8_t *src, uint8_t *dst, long src_size)
936 {
937     const uint16_t *end;
938 #ifdef HAVE_MMX
939     const uint16_t *mm_end;
940 #endif
941     uint8_t *d = (uint8_t *)dst;
942     const uint16_t *s = (uint16_t *)src;
943     end = s + src_size/2;
944 #ifdef HAVE_MMX
945     __asm __volatile(PREFETCH"    %0"::"m"(*s):"memory");
946     mm_end = end - 7;
947     while (s < mm_end)
948     {
949         __asm __volatile(
950         PREFETCH"    32%1           \n\t"
951         "movq          %1, %%mm0    \n\t"
952         "movq          %1, %%mm1    \n\t"
953         "movq          %1, %%mm2    \n\t"
954         "pand          %2, %%mm0    \n\t"
955         "pand          %3, %%mm1    \n\t"
956         "pand          %4, %%mm2    \n\t"
957         "psllq         $3, %%mm0    \n\t"
958         "psrlq         $2, %%mm1    \n\t"
959         "psrlq         $7, %%mm2    \n\t"
960         "movq       %%mm0, %%mm3    \n\t"
961         "movq       %%mm1, %%mm4    \n\t"
962         "movq       %%mm2, %%mm5    \n\t"
963         "punpcklwd     %5, %%mm0    \n\t"
964         "punpcklwd     %5, %%mm1    \n\t"
965         "punpcklwd     %5, %%mm2    \n\t"
966         "punpckhwd     %5, %%mm3    \n\t"
967         "punpckhwd     %5, %%mm4    \n\t"
968         "punpckhwd     %5, %%mm5    \n\t"
969         "psllq         $8, %%mm1    \n\t"
970         "psllq        $16, %%mm2    \n\t"
971         "por        %%mm1, %%mm0    \n\t"
972         "por        %%mm2, %%mm0    \n\t"
973         "psllq         $8, %%mm4    \n\t"
974         "psllq        $16, %%mm5    \n\t"
975         "por        %%mm4, %%mm3    \n\t"
976         "por        %%mm5, %%mm3    \n\t"
977
978         "movq       %%mm0, %%mm6    \n\t"
979         "movq       %%mm3, %%mm7    \n\t"
980
981         "movq         8%1, %%mm0    \n\t"
982         "movq         8%1, %%mm1    \n\t"
983         "movq         8%1, %%mm2    \n\t"
984         "pand          %2, %%mm0    \n\t"
985         "pand          %3, %%mm1    \n\t"
986         "pand          %4, %%mm2    \n\t"
987         "psllq         $3, %%mm0    \n\t"
988         "psrlq         $2, %%mm1    \n\t"
989         "psrlq         $7, %%mm2    \n\t"
990         "movq       %%mm0, %%mm3    \n\t"
991         "movq       %%mm1, %%mm4    \n\t"
992         "movq       %%mm2, %%mm5    \n\t"
993         "punpcklwd     %5, %%mm0    \n\t"
994         "punpcklwd     %5, %%mm1    \n\t"
995         "punpcklwd     %5, %%mm2    \n\t"
996         "punpckhwd     %5, %%mm3    \n\t"
997         "punpckhwd     %5, %%mm4    \n\t"
998         "punpckhwd     %5, %%mm5    \n\t"
999         "psllq         $8, %%mm1    \n\t"
1000         "psllq        $16, %%mm2    \n\t"
1001         "por        %%mm1, %%mm0    \n\t"
1002         "por        %%mm2, %%mm0    \n\t"
1003         "psllq         $8, %%mm4    \n\t"
1004         "psllq        $16, %%mm5    \n\t"
1005         "por        %%mm4, %%mm3    \n\t"
1006         "por        %%mm5, %%mm3    \n\t"
1007
1008         :"=m"(*d)
1009         :"m"(*s),"m"(mask15b),"m"(mask15g),"m"(mask15r), "m"(mmx_null)
1010         :"memory");
1011         /* Borrowed 32 to 24 */
1012         __asm __volatile(
1013         "movq       %%mm0, %%mm4    \n\t"
1014         "movq       %%mm3, %%mm5    \n\t"
1015         "movq       %%mm6, %%mm0    \n\t"
1016         "movq       %%mm7, %%mm1    \n\t"
1017
1018         "movq       %%mm4, %%mm6    \n\t"
1019         "movq       %%mm5, %%mm7    \n\t"
1020         "movq       %%mm0, %%mm2    \n\t"
1021         "movq       %%mm1, %%mm3    \n\t"
1022
1023         "psrlq         $8, %%mm2    \n\t"
1024         "psrlq         $8, %%mm3    \n\t"
1025         "psrlq         $8, %%mm6    \n\t"
1026         "psrlq         $8, %%mm7    \n\t"
1027         "pand          %2, %%mm0    \n\t"
1028         "pand          %2, %%mm1    \n\t"
1029         "pand          %2, %%mm4    \n\t"
1030         "pand          %2, %%mm5    \n\t"
1031         "pand          %3, %%mm2    \n\t"
1032         "pand          %3, %%mm3    \n\t"
1033         "pand          %3, %%mm6    \n\t"
1034         "pand          %3, %%mm7    \n\t"
1035         "por        %%mm2, %%mm0    \n\t"
1036         "por        %%mm3, %%mm1    \n\t"
1037         "por        %%mm6, %%mm4    \n\t"
1038         "por        %%mm7, %%mm5    \n\t"
1039
1040         "movq       %%mm1, %%mm2    \n\t"
1041         "movq       %%mm4, %%mm3    \n\t"
1042         "psllq        $48, %%mm2    \n\t"
1043         "psllq        $32, %%mm3    \n\t"
1044         "pand          %4, %%mm2    \n\t"
1045         "pand          %5, %%mm3    \n\t"
1046         "por        %%mm2, %%mm0    \n\t"
1047         "psrlq        $16, %%mm1    \n\t"
1048         "psrlq        $32, %%mm4    \n\t"
1049         "psllq        $16, %%mm5    \n\t"
1050         "por        %%mm3, %%mm1    \n\t"
1051         "pand          %6, %%mm5    \n\t"
1052         "por        %%mm5, %%mm4    \n\t"
1053
1054         MOVNTQ"     %%mm0,   %0     \n\t"
1055         MOVNTQ"     %%mm1,  8%0     \n\t"
1056         MOVNTQ"     %%mm4, 16%0"
1057
1058         :"=m"(*d)
1059         :"m"(*s),"m"(mask24l),"m"(mask24h),"m"(mask24hh),"m"(mask24hhh),"m"(mask24hhhh)
1060         :"memory");
1061         d += 24;
1062         s += 8;
1063     }
1064     __asm __volatile(SFENCE:::"memory");
1065     __asm __volatile(EMMS:::"memory");
1066 #endif
1067     while (s < end)
1068     {
1069         register uint16_t bgr;
1070         bgr = *s++;
1071         *d++ = (bgr&0x1F)<<3;
1072         *d++ = (bgr&0x3E0)>>2;
1073         *d++ = (bgr&0x7C00)>>7;
1074     }
1075 }
1076
1077 static inline void RENAME(rgb16to24)(const uint8_t *src, uint8_t *dst, long src_size)
1078 {
1079     const uint16_t *end;
1080 #ifdef HAVE_MMX
1081     const uint16_t *mm_end;
1082 #endif
1083     uint8_t *d = (uint8_t *)dst;
1084     const uint16_t *s = (const uint16_t *)src;
1085     end = s + src_size/2;
1086 #ifdef HAVE_MMX
1087     __asm __volatile(PREFETCH"    %0"::"m"(*s):"memory");
1088     mm_end = end - 7;
1089     while (s < mm_end)
1090     {
1091         __asm __volatile(
1092         PREFETCH"    32%1           \n\t"
1093         "movq          %1, %%mm0    \n\t"
1094         "movq          %1, %%mm1    \n\t"
1095         "movq          %1, %%mm2    \n\t"
1096         "pand          %2, %%mm0    \n\t"
1097         "pand          %3, %%mm1    \n\t"
1098         "pand          %4, %%mm2    \n\t"
1099         "psllq         $3, %%mm0    \n\t"
1100         "psrlq         $3, %%mm1    \n\t"
1101         "psrlq         $8, %%mm2    \n\t"
1102         "movq       %%mm0, %%mm3    \n\t"
1103         "movq       %%mm1, %%mm4    \n\t"
1104         "movq       %%mm2, %%mm5    \n\t"
1105         "punpcklwd     %5, %%mm0    \n\t"
1106         "punpcklwd     %5, %%mm1    \n\t"
1107         "punpcklwd     %5, %%mm2    \n\t"
1108         "punpckhwd     %5, %%mm3    \n\t"
1109         "punpckhwd     %5, %%mm4    \n\t"
1110         "punpckhwd     %5, %%mm5    \n\t"
1111         "psllq         $8, %%mm1    \n\t"
1112         "psllq        $16, %%mm2    \n\t"
1113         "por        %%mm1, %%mm0    \n\t"
1114         "por        %%mm2, %%mm0    \n\t"
1115         "psllq         $8, %%mm4    \n\t"
1116         "psllq        $16, %%mm5    \n\t"
1117         "por        %%mm4, %%mm3    \n\t"
1118         "por        %%mm5, %%mm3    \n\t"
1119
1120         "movq       %%mm0, %%mm6    \n\t"
1121         "movq       %%mm3, %%mm7    \n\t"
1122
1123         "movq         8%1, %%mm0    \n\t"
1124         "movq         8%1, %%mm1    \n\t"
1125         "movq         8%1, %%mm2    \n\t"
1126         "pand          %2, %%mm0    \n\t"
1127         "pand          %3, %%mm1    \n\t"
1128         "pand          %4, %%mm2    \n\t"
1129         "psllq         $3, %%mm0    \n\t"
1130         "psrlq         $3, %%mm1    \n\t"
1131         "psrlq         $8, %%mm2    \n\t"
1132         "movq       %%mm0, %%mm3    \n\t"
1133         "movq       %%mm1, %%mm4    \n\t"
1134         "movq       %%mm2, %%mm5    \n\t"
1135         "punpcklwd     %5, %%mm0    \n\t"
1136         "punpcklwd     %5, %%mm1    \n\t"
1137         "punpcklwd     %5, %%mm2    \n\t"
1138         "punpckhwd     %5, %%mm3    \n\t"
1139         "punpckhwd     %5, %%mm4    \n\t"
1140         "punpckhwd     %5, %%mm5    \n\t"
1141         "psllq         $8, %%mm1    \n\t"
1142         "psllq        $16, %%mm2    \n\t"
1143         "por        %%mm1, %%mm0    \n\t"
1144         "por        %%mm2, %%mm0    \n\t"
1145         "psllq         $8, %%mm4    \n\t"
1146         "psllq        $16, %%mm5    \n\t"
1147         "por        %%mm4, %%mm3    \n\t"
1148         "por        %%mm5, %%mm3    \n\t"
1149         :"=m"(*d)
1150         :"m"(*s),"m"(mask16b),"m"(mask16g),"m"(mask16r),"m"(mmx_null)
1151         :"memory");
1152         /* Borrowed 32 to 24 */
1153         __asm __volatile(
1154         "movq       %%mm0, %%mm4    \n\t"
1155         "movq       %%mm3, %%mm5    \n\t"
1156         "movq       %%mm6, %%mm0    \n\t"
1157         "movq       %%mm7, %%mm1    \n\t"
1158
1159         "movq       %%mm4, %%mm6    \n\t"
1160         "movq       %%mm5, %%mm7    \n\t"
1161         "movq       %%mm0, %%mm2    \n\t"
1162         "movq       %%mm1, %%mm3    \n\t"
1163
1164         "psrlq         $8, %%mm2    \n\t"
1165         "psrlq         $8, %%mm3    \n\t"
1166         "psrlq         $8, %%mm6    \n\t"
1167         "psrlq         $8, %%mm7    \n\t"
1168         "pand          %2, %%mm0    \n\t"
1169         "pand          %2, %%mm1    \n\t"
1170         "pand          %2, %%mm4    \n\t"
1171         "pand          %2, %%mm5    \n\t"
1172         "pand          %3, %%mm2    \n\t"
1173         "pand          %3, %%mm3    \n\t"
1174         "pand          %3, %%mm6    \n\t"
1175         "pand          %3, %%mm7    \n\t"
1176         "por        %%mm2, %%mm0    \n\t"
1177         "por        %%mm3, %%mm1    \n\t"
1178         "por        %%mm6, %%mm4    \n\t"
1179         "por        %%mm7, %%mm5    \n\t"
1180
1181         "movq       %%mm1, %%mm2    \n\t"
1182         "movq       %%mm4, %%mm3    \n\t"
1183         "psllq        $48, %%mm2    \n\t"
1184         "psllq        $32, %%mm3    \n\t"
1185         "pand          %4, %%mm2    \n\t"
1186         "pand          %5, %%mm3    \n\t"
1187         "por        %%mm2, %%mm0    \n\t"
1188         "psrlq        $16, %%mm1    \n\t"
1189         "psrlq        $32, %%mm4    \n\t"
1190         "psllq        $16, %%mm5    \n\t"
1191         "por        %%mm3, %%mm1    \n\t"
1192         "pand          %6, %%mm5    \n\t"
1193         "por        %%mm5, %%mm4    \n\t"
1194
1195         MOVNTQ"     %%mm0,   %0     \n\t"
1196         MOVNTQ"     %%mm1,  8%0     \n\t"
1197         MOVNTQ"     %%mm4, 16%0"
1198
1199         :"=m"(*d)
1200         :"m"(*s),"m"(mask24l),"m"(mask24h),"m"(mask24hh),"m"(mask24hhh),"m"(mask24hhhh)
1201         :"memory");
1202         d += 24;
1203         s += 8;
1204     }
1205     __asm __volatile(SFENCE:::"memory");
1206     __asm __volatile(EMMS:::"memory");
1207 #endif
1208     while (s < end)
1209     {
1210         register uint16_t bgr;
1211         bgr = *s++;
1212         *d++ = (bgr&0x1F)<<3;
1213         *d++ = (bgr&0x7E0)>>3;
1214         *d++ = (bgr&0xF800)>>8;
1215     }
1216 }
1217
1218 static inline void RENAME(rgb15to32)(const uint8_t *src, uint8_t *dst, long src_size)
1219 {
1220     const uint16_t *end;
1221 #ifdef HAVE_MMX
1222     const uint16_t *mm_end;
1223 #endif
1224     uint8_t *d = (uint8_t *)dst;
1225     const uint16_t *s = (const uint16_t *)src;
1226     end = s + src_size/2;
1227 #ifdef HAVE_MMX
1228     __asm __volatile(PREFETCH"    %0"::"m"(*s):"memory");
1229     __asm __volatile("pxor    %%mm7,%%mm7    \n\t":::"memory");
1230     mm_end = end - 3;
1231     while (s < mm_end)
1232     {
1233         __asm __volatile(
1234         PREFETCH"    32%1           \n\t"
1235         "movq          %1, %%mm0    \n\t"
1236         "movq          %1, %%mm1    \n\t"
1237         "movq          %1, %%mm2    \n\t"
1238         "pand          %2, %%mm0    \n\t"
1239         "pand          %3, %%mm1    \n\t"
1240         "pand          %4, %%mm2    \n\t"
1241         "psllq         $3, %%mm0    \n\t"
1242         "psrlq         $2, %%mm1    \n\t"
1243         "psrlq         $7, %%mm2    \n\t"
1244         "movq       %%mm0, %%mm3    \n\t"
1245         "movq       %%mm1, %%mm4    \n\t"
1246         "movq       %%mm2, %%mm5    \n\t"
1247         "punpcklwd  %%mm7, %%mm0    \n\t"
1248         "punpcklwd  %%mm7, %%mm1    \n\t"
1249         "punpcklwd  %%mm7, %%mm2    \n\t"
1250         "punpckhwd  %%mm7, %%mm3    \n\t"
1251         "punpckhwd  %%mm7, %%mm4    \n\t"
1252         "punpckhwd  %%mm7, %%mm5    \n\t"
1253         "psllq         $8, %%mm1    \n\t"
1254         "psllq        $16, %%mm2    \n\t"
1255         "por        %%mm1, %%mm0    \n\t"
1256         "por        %%mm2, %%mm0    \n\t"
1257         "psllq         $8, %%mm4    \n\t"
1258         "psllq        $16, %%mm5    \n\t"
1259         "por        %%mm4, %%mm3    \n\t"
1260         "por        %%mm5, %%mm3    \n\t"
1261         MOVNTQ"     %%mm0,  %0      \n\t"
1262         MOVNTQ"     %%mm3, 8%0      \n\t"
1263         :"=m"(*d)
1264         :"m"(*s),"m"(mask15b),"m"(mask15g),"m"(mask15r)
1265         :"memory");
1266         d += 16;
1267         s += 4;
1268     }
1269     __asm __volatile(SFENCE:::"memory");
1270     __asm __volatile(EMMS:::"memory");
1271 #endif
1272     while (s < end)
1273     {
1274 #if 0 //slightly slower on athlon
1275         int bgr= *s++;
1276         *((uint32_t*)d)++ = ((bgr&0x1F)<<3) + ((bgr&0x3E0)<<6) + ((bgr&0x7C00)<<9);
1277 #else
1278         register uint16_t bgr;
1279         bgr = *s++;
1280 #ifdef WORDS_BIGENDIAN
1281         *d++ = 0;
1282         *d++ = (bgr&0x7C00)>>7;
1283         *d++ = (bgr&0x3E0)>>2;
1284         *d++ = (bgr&0x1F)<<3;
1285 #else
1286         *d++ = (bgr&0x1F)<<3;
1287         *d++ = (bgr&0x3E0)>>2;
1288         *d++ = (bgr&0x7C00)>>7;
1289         *d++ = 0;
1290 #endif
1291
1292 #endif
1293     }
1294 }
1295
1296 static inline void RENAME(rgb16to32)(const uint8_t *src, uint8_t *dst, long src_size)
1297 {
1298     const uint16_t *end;
1299 #ifdef HAVE_MMX
1300     const uint16_t *mm_end;
1301 #endif
1302     uint8_t *d = (uint8_t *)dst;
1303     const uint16_t *s = (uint16_t *)src;
1304     end = s + src_size/2;
1305 #ifdef HAVE_MMX
1306     __asm __volatile(PREFETCH"    %0"::"m"(*s):"memory");
1307     __asm __volatile("pxor    %%mm7,%%mm7    \n\t":::"memory");
1308     mm_end = end - 3;
1309     while (s < mm_end)
1310     {
1311         __asm __volatile(
1312         PREFETCH"    32%1           \n\t"
1313         "movq          %1, %%mm0    \n\t"
1314         "movq          %1, %%mm1    \n\t"
1315         "movq          %1, %%mm2    \n\t"
1316         "pand          %2, %%mm0    \n\t"
1317         "pand          %3, %%mm1    \n\t"
1318         "pand          %4, %%mm2    \n\t"
1319         "psllq         $3, %%mm0    \n\t"
1320         "psrlq         $3, %%mm1    \n\t"
1321         "psrlq         $8, %%mm2    \n\t"
1322         "movq       %%mm0, %%mm3    \n\t"
1323         "movq       %%mm1, %%mm4    \n\t"
1324         "movq       %%mm2, %%mm5    \n\t"
1325         "punpcklwd  %%mm7, %%mm0    \n\t"
1326         "punpcklwd  %%mm7, %%mm1    \n\t"
1327         "punpcklwd  %%mm7, %%mm2    \n\t"
1328         "punpckhwd  %%mm7, %%mm3    \n\t"
1329         "punpckhwd  %%mm7, %%mm4    \n\t"
1330         "punpckhwd  %%mm7, %%mm5    \n\t"
1331         "psllq         $8, %%mm1    \n\t"
1332         "psllq        $16, %%mm2    \n\t"
1333         "por        %%mm1, %%mm0    \n\t"
1334         "por        %%mm2, %%mm0    \n\t"
1335         "psllq         $8, %%mm4    \n\t"
1336         "psllq        $16, %%mm5    \n\t"
1337         "por        %%mm4, %%mm3    \n\t"
1338         "por        %%mm5, %%mm3    \n\t"
1339         MOVNTQ"     %%mm0, %0       \n\t"
1340         MOVNTQ"     %%mm3, 8%0      \n\t"
1341         :"=m"(*d)
1342         :"m"(*s),"m"(mask16b),"m"(mask16g),"m"(mask16r)
1343         :"memory");
1344         d += 16;
1345         s += 4;
1346     }
1347     __asm __volatile(SFENCE:::"memory");
1348     __asm __volatile(EMMS:::"memory");
1349 #endif
1350     while (s < end)
1351     {
1352         register uint16_t bgr;
1353         bgr = *s++;
1354 #ifdef WORDS_BIGENDIAN
1355         *d++ = 0;
1356         *d++ = (bgr&0xF800)>>8;
1357         *d++ = (bgr&0x7E0)>>3;
1358         *d++ = (bgr&0x1F)<<3;
1359 #else
1360         *d++ = (bgr&0x1F)<<3;
1361         *d++ = (bgr&0x7E0)>>3;
1362         *d++ = (bgr&0xF800)>>8;
1363         *d++ = 0;
1364 #endif
1365     }
1366 }
1367
1368 static inline void RENAME(rgb32tobgr32)(const uint8_t *src, uint8_t *dst, long src_size)
1369 {
1370     long idx = 15 - src_size;
1371     uint8_t *s = (uint8_t *) src-idx, *d = dst-idx;
1372 #ifdef HAVE_MMX
1373     __asm __volatile(
1374     "test          %0, %0           \n\t"
1375     "jns           2f               \n\t"
1376     PREFETCH"       (%1, %0)        \n\t"
1377     "movq          %3, %%mm7        \n\t"
1378     "pxor          %4, %%mm7        \n\t"
1379     "movq       %%mm7, %%mm6        \n\t"
1380     "pxor          %5, %%mm7        \n\t"
1381     ASMALIGN(4)
1382     "1:                             \n\t"
1383     PREFETCH"     32(%1, %0)        \n\t"
1384     "movq           (%1, %0), %%mm0 \n\t"
1385     "movq          8(%1, %0), %%mm1 \n\t"
1386 # ifdef HAVE_MMX2
1387     "pshufw      $177, %%mm0, %%mm3 \n\t"
1388     "pshufw      $177, %%mm1, %%mm5 \n\t"
1389     "pand       %%mm7, %%mm0        \n\t"
1390     "pand       %%mm6, %%mm3        \n\t"
1391     "pand       %%mm7, %%mm1        \n\t"
1392     "pand       %%mm6, %%mm5        \n\t"
1393     "por        %%mm3, %%mm0        \n\t"
1394     "por        %%mm5, %%mm1        \n\t"
1395 # else
1396     "movq       %%mm0, %%mm2        \n\t"
1397     "movq       %%mm1, %%mm4        \n\t"
1398     "pand       %%mm7, %%mm0        \n\t"
1399     "pand       %%mm6, %%mm2        \n\t"
1400     "pand       %%mm7, %%mm1        \n\t"
1401     "pand       %%mm6, %%mm4        \n\t"
1402     "movq       %%mm2, %%mm3        \n\t"
1403     "movq       %%mm4, %%mm5        \n\t"
1404     "pslld        $16, %%mm2        \n\t"
1405     "psrld        $16, %%mm3        \n\t"
1406     "pslld        $16, %%mm4        \n\t"
1407     "psrld        $16, %%mm5        \n\t"
1408     "por        %%mm2, %%mm0        \n\t"
1409     "por        %%mm4, %%mm1        \n\t"
1410     "por        %%mm3, %%mm0        \n\t"
1411     "por        %%mm5, %%mm1        \n\t"
1412 # endif
1413     MOVNTQ"     %%mm0,  (%2, %0)    \n\t"
1414     MOVNTQ"     %%mm1, 8(%2, %0)    \n\t"
1415     "add          $16, %0           \n\t"
1416     "js            1b               \n\t"
1417     SFENCE"                         \n\t"
1418     EMMS"                           \n\t"
1419     "2:                             \n\t"
1420     : "+&r"(idx)
1421     : "r" (s), "r" (d), "m" (mask32b), "m" (mask32r), "m" (mmx_one)
1422     : "memory");
1423 #endif
1424     for (; idx<15; idx+=4) {
1425         register int v = *(uint32_t *)&s[idx], g = v & 0xff00ff00;
1426         v &= 0xff00ff;
1427         *(uint32_t *)&d[idx] = (v>>16) + g + (v<<16);
1428     }
1429 }
1430
1431 static inline void RENAME(rgb24tobgr24)(const uint8_t *src, uint8_t *dst, long src_size)
1432 {
1433     unsigned i;
1434 #ifdef HAVE_MMX
1435     long mmx_size= 23 - src_size;
1436     asm volatile (
1437     "test             %%"REG_a", %%"REG_a"          \n\t"
1438     "jns                     2f                     \n\t"
1439     "movq     "MANGLE(mask24r)", %%mm5              \n\t"
1440     "movq     "MANGLE(mask24g)", %%mm6              \n\t"
1441     "movq     "MANGLE(mask24b)", %%mm7              \n\t"
1442     ASMALIGN(4)
1443     "1:                                             \n\t"
1444     PREFETCH" 32(%1, %%"REG_a")                     \n\t"
1445     "movq       (%1, %%"REG_a"), %%mm0              \n\t" // BGR BGR BG
1446     "movq       (%1, %%"REG_a"), %%mm1              \n\t" // BGR BGR BG
1447     "movq      2(%1, %%"REG_a"), %%mm2              \n\t" // R BGR BGR B
1448     "psllq                  $16, %%mm0              \n\t" // 00 BGR BGR
1449     "pand                 %%mm5, %%mm0              \n\t"
1450     "pand                 %%mm6, %%mm1              \n\t"
1451     "pand                 %%mm7, %%mm2              \n\t"
1452     "por                  %%mm0, %%mm1              \n\t"
1453     "por                  %%mm2, %%mm1              \n\t"
1454     "movq      6(%1, %%"REG_a"), %%mm0              \n\t" // BGR BGR BG
1455     MOVNTQ"               %%mm1,   (%2, %%"REG_a")  \n\t" // RGB RGB RG
1456     "movq      8(%1, %%"REG_a"), %%mm1              \n\t" // R BGR BGR B
1457     "movq     10(%1, %%"REG_a"), %%mm2              \n\t" // GR BGR BGR
1458     "pand                 %%mm7, %%mm0              \n\t"
1459     "pand                 %%mm5, %%mm1              \n\t"
1460     "pand                 %%mm6, %%mm2              \n\t"
1461     "por                  %%mm0, %%mm1              \n\t"
1462     "por                  %%mm2, %%mm1              \n\t"
1463     "movq     14(%1, %%"REG_a"), %%mm0              \n\t" // R BGR BGR B
1464     MOVNTQ"               %%mm1,  8(%2, %%"REG_a")  \n\t" // B RGB RGB R
1465     "movq     16(%1, %%"REG_a"), %%mm1              \n\t" // GR BGR BGR
1466     "movq     18(%1, %%"REG_a"), %%mm2              \n\t" // BGR BGR BG
1467     "pand                 %%mm6, %%mm0              \n\t"
1468     "pand                 %%mm7, %%mm1              \n\t"
1469     "pand                 %%mm5, %%mm2              \n\t"
1470     "por                  %%mm0, %%mm1              \n\t"
1471     "por                  %%mm2, %%mm1              \n\t"
1472     MOVNTQ"               %%mm1, 16(%2, %%"REG_a")  \n\t"
1473     "add                    $24, %%"REG_a"          \n\t"
1474     " js                     1b                     \n\t"
1475     "2:                                             \n\t"
1476     : "+a" (mmx_size)
1477     : "r" (src-mmx_size), "r"(dst-mmx_size)
1478     );
1479
1480     __asm __volatile(SFENCE:::"memory");
1481     __asm __volatile(EMMS:::"memory");
1482
1483     if (mmx_size==23) return; //finihsed, was multiple of 8
1484
1485     src+= src_size;
1486     dst+= src_size;
1487     src_size= 23-mmx_size;
1488     src-= src_size;
1489     dst-= src_size;
1490 #endif
1491     for (i=0; i<src_size; i+=3)
1492     {
1493         register uint8_t x;
1494         x          = src[i + 2];
1495         dst[i + 1] = src[i + 1];
1496         dst[i + 2] = src[i + 0];
1497         dst[i + 0] = x;
1498     }
1499 }
1500
1501 static inline void RENAME(yuvPlanartoyuy2)(const uint8_t *ysrc, const uint8_t *usrc, const uint8_t *vsrc, uint8_t *dst,
1502                                            long width, long height,
1503                                            long lumStride, long chromStride, long dstStride, long vertLumPerChroma)
1504 {
1505     long y;
1506     const long chromWidth= width>>1;
1507     for (y=0; y<height; y++)
1508     {
1509 #ifdef HAVE_MMX
1510 //FIXME handle 2 lines a once (fewer prefetch, reuse some chrom, but very likely limited by mem anyway)
1511         asm volatile(
1512         "xor                 %%"REG_a", %%"REG_a"   \n\t"
1513         ASMALIGN(4)
1514         "1:                                         \n\t"
1515         PREFETCH"    32(%1, %%"REG_a", 2)           \n\t"
1516         PREFETCH"    32(%2, %%"REG_a")              \n\t"
1517         PREFETCH"    32(%3, %%"REG_a")              \n\t"
1518         "movq          (%2, %%"REG_a"), %%mm0       \n\t" // U(0)
1519         "movq                    %%mm0, %%mm2       \n\t" // U(0)
1520         "movq          (%3, %%"REG_a"), %%mm1       \n\t" // V(0)
1521         "punpcklbw               %%mm1, %%mm0       \n\t" // UVUV UVUV(0)
1522         "punpckhbw               %%mm1, %%mm2       \n\t" // UVUV UVUV(8)
1523
1524         "movq        (%1, %%"REG_a",2), %%mm3       \n\t" // Y(0)
1525         "movq       8(%1, %%"REG_a",2), %%mm5       \n\t" // Y(8)
1526         "movq                    %%mm3, %%mm4       \n\t" // Y(0)
1527         "movq                    %%mm5, %%mm6       \n\t" // Y(8)
1528         "punpcklbw               %%mm0, %%mm3       \n\t" // YUYV YUYV(0)
1529         "punpckhbw               %%mm0, %%mm4       \n\t" // YUYV YUYV(4)
1530         "punpcklbw               %%mm2, %%mm5       \n\t" // YUYV YUYV(8)
1531         "punpckhbw               %%mm2, %%mm6       \n\t" // YUYV YUYV(12)
1532
1533         MOVNTQ"                  %%mm3,   (%0, %%"REG_a", 4)    \n\t"
1534         MOVNTQ"                  %%mm4,  8(%0, %%"REG_a", 4)    \n\t"
1535         MOVNTQ"                  %%mm5, 16(%0, %%"REG_a", 4)    \n\t"
1536         MOVNTQ"                  %%mm6, 24(%0, %%"REG_a", 4)    \n\t"
1537
1538         "add                        $8, %%"REG_a"   \n\t"
1539         "cmp                        %4, %%"REG_a"   \n\t"
1540         " jb                        1b              \n\t"
1541         ::"r"(dst), "r"(ysrc), "r"(usrc), "r"(vsrc), "g" (chromWidth)
1542         : "%"REG_a
1543         );
1544 #else
1545
1546 #if defined ARCH_ALPHA && defined HAVE_MVI
1547 #define pl2yuy2(n)                  \
1548     y1 = yc[n];                     \
1549     y2 = yc2[n];                    \
1550     u = uc[n];                      \
1551     v = vc[n];                      \
1552     asm("unpkbw %1, %0" : "=r"(y1) : "r"(y1));  \
1553     asm("unpkbw %1, %0" : "=r"(y2) : "r"(y2));  \
1554     asm("unpkbl %1, %0" : "=r"(u) : "r"(u));    \
1555     asm("unpkbl %1, %0" : "=r"(v) : "r"(v));    \
1556     yuv1 = (u << 8) + (v << 24);                \
1557     yuv2 = yuv1 + y2;               \
1558     yuv1 += y1;                     \
1559     qdst[n]  = yuv1;                \
1560     qdst2[n] = yuv2;
1561
1562         int i;
1563         uint64_t *qdst = (uint64_t *) dst;
1564         uint64_t *qdst2 = (uint64_t *) (dst + dstStride);
1565         const uint32_t *yc = (uint32_t *) ysrc;
1566         const uint32_t *yc2 = (uint32_t *) (ysrc + lumStride);
1567         const uint16_t *uc = (uint16_t*) usrc, *vc = (uint16_t*) vsrc;
1568         for (i = 0; i < chromWidth; i += 8){
1569             uint64_t y1, y2, yuv1, yuv2;
1570             uint64_t u, v;
1571             /* Prefetch */
1572             asm("ldq $31,64(%0)" :: "r"(yc));
1573             asm("ldq $31,64(%0)" :: "r"(yc2));
1574             asm("ldq $31,64(%0)" :: "r"(uc));
1575             asm("ldq $31,64(%0)" :: "r"(vc));
1576
1577             pl2yuy2(0);
1578             pl2yuy2(1);
1579             pl2yuy2(2);
1580             pl2yuy2(3);
1581
1582             yc    += 4;
1583             yc2   += 4;
1584             uc    += 4;
1585             vc    += 4;
1586             qdst  += 4;
1587             qdst2 += 4;
1588         }
1589         y++;
1590         ysrc += lumStride;
1591         dst += dstStride;
1592
1593 #elif __WORDSIZE >= 64
1594         int i;
1595         uint64_t *ldst = (uint64_t *) dst;
1596         const uint8_t *yc = ysrc, *uc = usrc, *vc = vsrc;
1597         for (i = 0; i < chromWidth; i += 2){
1598             uint64_t k, l;
1599             k = yc[0] + (uc[0] << 8) +
1600                 (yc[1] << 16) + (vc[0] << 24);
1601             l = yc[2] + (uc[1] << 8) +
1602                 (yc[3] << 16) + (vc[1] << 24);
1603             *ldst++ = k + (l << 32);
1604             yc += 4;
1605             uc += 2;
1606             vc += 2;
1607         }
1608
1609 #else
1610         int i, *idst = (int32_t *) dst;
1611         const uint8_t *yc = ysrc, *uc = usrc, *vc = vsrc;
1612         for (i = 0; i < chromWidth; i++){
1613 #ifdef WORDS_BIGENDIAN
1614             *idst++ = (yc[0] << 24)+ (uc[0] << 16) +
1615                 (yc[1] << 8) + (vc[0] << 0);
1616 #else
1617             *idst++ = yc[0] + (uc[0] << 8) +
1618                 (yc[1] << 16) + (vc[0] << 24);
1619 #endif
1620             yc += 2;
1621             uc++;
1622             vc++;
1623         }
1624 #endif
1625 #endif
1626         if ((y&(vertLumPerChroma-1))==(vertLumPerChroma-1) )
1627         {
1628             usrc += chromStride;
1629             vsrc += chromStride;
1630         }
1631         ysrc += lumStride;
1632         dst  += dstStride;
1633     }
1634 #ifdef HAVE_MMX
1635 asm(    EMMS"       \n\t"
1636         SFENCE"     \n\t"
1637         :::"memory");
1638 #endif
1639 }
1640
1641 /**
1642  *
1643  * height should be a multiple of 2 and width should be a multiple of 16 (if this is a
1644  * problem for anyone then tell me, and ill fix it)
1645  */
1646 static inline void RENAME(yv12toyuy2)(const uint8_t *ysrc, const uint8_t *usrc, const uint8_t *vsrc, uint8_t *dst,
1647                                       long width, long height,
1648                                       long lumStride, long chromStride, long dstStride)
1649 {
1650     //FIXME interpolate chroma
1651     RENAME(yuvPlanartoyuy2)(ysrc, usrc, vsrc, dst, width, height, lumStride, chromStride, dstStride, 2);
1652 }
1653
1654 static inline void RENAME(yuvPlanartouyvy)(const uint8_t *ysrc, const uint8_t *usrc, const uint8_t *vsrc, uint8_t *dst,
1655                                            long width, long height,
1656                                            long lumStride, long chromStride, long dstStride, long vertLumPerChroma)
1657 {
1658     long y;
1659     const long chromWidth= width>>1;
1660     for (y=0; y<height; y++)
1661     {
1662 #ifdef HAVE_MMX
1663 //FIXME handle 2 lines a once (fewer prefetch, reuse some chrom, but very likely limited by mem anyway)
1664         asm volatile(
1665         "xor                %%"REG_a", %%"REG_a"    \n\t"
1666         ASMALIGN(4)
1667         "1:                                         \n\t"
1668         PREFETCH"   32(%1, %%"REG_a", 2)            \n\t"
1669         PREFETCH"   32(%2, %%"REG_a")               \n\t"
1670         PREFETCH"   32(%3, %%"REG_a")               \n\t"
1671         "movq         (%2, %%"REG_a"), %%mm0        \n\t" // U(0)
1672         "movq                   %%mm0, %%mm2        \n\t" // U(0)
1673         "movq         (%3, %%"REG_a"), %%mm1        \n\t" // V(0)
1674         "punpcklbw              %%mm1, %%mm0        \n\t" // UVUV UVUV(0)
1675         "punpckhbw              %%mm1, %%mm2        \n\t" // UVUV UVUV(8)
1676
1677         "movq       (%1, %%"REG_a",2), %%mm3        \n\t" // Y(0)
1678         "movq      8(%1, %%"REG_a",2), %%mm5        \n\t" // Y(8)
1679         "movq                   %%mm0, %%mm4        \n\t" // Y(0)
1680         "movq                   %%mm2, %%mm6        \n\t" // Y(8)
1681         "punpcklbw              %%mm3, %%mm0        \n\t" // YUYV YUYV(0)
1682         "punpckhbw              %%mm3, %%mm4        \n\t" // YUYV YUYV(4)
1683         "punpcklbw              %%mm5, %%mm2        \n\t" // YUYV YUYV(8)
1684         "punpckhbw              %%mm5, %%mm6        \n\t" // YUYV YUYV(12)
1685
1686         MOVNTQ"                 %%mm0,   (%0, %%"REG_a", 4)     \n\t"
1687         MOVNTQ"                 %%mm4,  8(%0, %%"REG_a", 4)     \n\t"
1688         MOVNTQ"                 %%mm2, 16(%0, %%"REG_a", 4)     \n\t"
1689         MOVNTQ"                 %%mm6, 24(%0, %%"REG_a", 4)     \n\t"
1690
1691         "add                       $8, %%"REG_a"    \n\t"
1692         "cmp                       %4, %%"REG_a"    \n\t"
1693         " jb                       1b               \n\t"
1694         ::"r"(dst), "r"(ysrc), "r"(usrc), "r"(vsrc), "g" (chromWidth)
1695         : "%"REG_a
1696         );
1697 #else
1698 //FIXME adapt the alpha asm code from yv12->yuy2
1699
1700 #if __WORDSIZE >= 64
1701         int i;
1702         uint64_t *ldst = (uint64_t *) dst;
1703         const uint8_t *yc = ysrc, *uc = usrc, *vc = vsrc;
1704         for (i = 0; i < chromWidth; i += 2){
1705             uint64_t k, l;
1706             k = uc[0] + (yc[0] << 8) +
1707                 (vc[0] << 16) + (yc[1] << 24);
1708             l = uc[1] + (yc[2] << 8) +
1709                 (vc[1] << 16) + (yc[3] << 24);
1710             *ldst++ = k + (l << 32);
1711             yc += 4;
1712             uc += 2;
1713             vc += 2;
1714         }
1715
1716 #else
1717         int i, *idst = (int32_t *) dst;
1718         const uint8_t *yc = ysrc, *uc = usrc, *vc = vsrc;
1719         for (i = 0; i < chromWidth; i++){
1720 #ifdef WORDS_BIGENDIAN
1721             *idst++ = (uc[0] << 24)+ (yc[0] << 16) +
1722                 (vc[0] << 8) + (yc[1] << 0);
1723 #else
1724             *idst++ = uc[0] + (yc[0] << 8) +
1725                 (vc[0] << 16) + (yc[1] << 24);
1726 #endif
1727             yc += 2;
1728             uc++;
1729             vc++;
1730         }
1731 #endif
1732 #endif
1733         if ((y&(vertLumPerChroma-1))==(vertLumPerChroma-1) )
1734         {
1735             usrc += chromStride;
1736             vsrc += chromStride;
1737         }
1738         ysrc += lumStride;
1739         dst += dstStride;
1740     }
1741 #ifdef HAVE_MMX
1742 asm(    EMMS"       \n\t"
1743         SFENCE"     \n\t"
1744         :::"memory");
1745 #endif
1746 }
1747
1748 /**
1749  *
1750  * height should be a multiple of 2 and width should be a multiple of 16 (if this is a
1751  * problem for anyone then tell me, and ill fix it)
1752  */
1753 static inline void RENAME(yv12touyvy)(const uint8_t *ysrc, const uint8_t *usrc, const uint8_t *vsrc, uint8_t *dst,
1754                                       long width, long height,
1755                                       long lumStride, long chromStride, long dstStride)
1756 {
1757     //FIXME interpolate chroma
1758     RENAME(yuvPlanartouyvy)(ysrc, usrc, vsrc, dst, width, height, lumStride, chromStride, dstStride, 2);
1759 }
1760
1761 /**
1762  *
1763  * width should be a multiple of 16
1764  */
1765 static inline void RENAME(yuv422ptoyuy2)(const uint8_t *ysrc, const uint8_t *usrc, const uint8_t *vsrc, uint8_t *dst,
1766                                          long width, long height,
1767                                          long lumStride, long chromStride, long dstStride)
1768 {
1769     RENAME(yuvPlanartoyuy2)(ysrc, usrc, vsrc, dst, width, height, lumStride, chromStride, dstStride, 1);
1770 }
1771
1772 /**
1773  *
1774  * height should be a multiple of 2 and width should be a multiple of 16 (if this is a
1775  * problem for anyone then tell me, and ill fix it)
1776  */
1777 static inline void RENAME(yuy2toyv12)(const uint8_t *src, uint8_t *ydst, uint8_t *udst, uint8_t *vdst,
1778                                       long width, long height,
1779                                       long lumStride, long chromStride, long srcStride)
1780 {
1781     long y;
1782     const long chromWidth= width>>1;
1783     for (y=0; y<height; y+=2)
1784     {
1785 #ifdef HAVE_MMX
1786         asm volatile(
1787         "xor                 %%"REG_a", %%"REG_a"   \n\t"
1788         "pcmpeqw                 %%mm7, %%mm7       \n\t"
1789         "psrlw                      $8, %%mm7       \n\t" // FF,00,FF,00...
1790         ASMALIGN(4)
1791         "1:                \n\t"
1792         PREFETCH" 64(%0, %%"REG_a", 4)              \n\t"
1793         "movq       (%0, %%"REG_a", 4), %%mm0       \n\t" // YUYV YUYV(0)
1794         "movq      8(%0, %%"REG_a", 4), %%mm1       \n\t" // YUYV YUYV(4)
1795         "movq                    %%mm0, %%mm2       \n\t" // YUYV YUYV(0)
1796         "movq                    %%mm1, %%mm3       \n\t" // YUYV YUYV(4)
1797         "psrlw                      $8, %%mm0       \n\t" // U0V0 U0V0(0)
1798         "psrlw                      $8, %%mm1       \n\t" // U0V0 U0V0(4)
1799         "pand                    %%mm7, %%mm2       \n\t" // Y0Y0 Y0Y0(0)
1800         "pand                    %%mm7, %%mm3       \n\t" // Y0Y0 Y0Y0(4)
1801         "packuswb                %%mm1, %%mm0       \n\t" // UVUV UVUV(0)
1802         "packuswb                %%mm3, %%mm2       \n\t" // YYYY YYYY(0)
1803
1804         MOVNTQ"                  %%mm2, (%1, %%"REG_a", 2)  \n\t"
1805
1806         "movq     16(%0, %%"REG_a", 4), %%mm1       \n\t" // YUYV YUYV(8)
1807         "movq     24(%0, %%"REG_a", 4), %%mm2       \n\t" // YUYV YUYV(12)
1808         "movq                    %%mm1, %%mm3       \n\t" // YUYV YUYV(8)
1809         "movq                    %%mm2, %%mm4       \n\t" // YUYV YUYV(12)
1810         "psrlw                      $8, %%mm1       \n\t" // U0V0 U0V0(8)
1811         "psrlw                      $8, %%mm2       \n\t" // U0V0 U0V0(12)
1812         "pand                    %%mm7, %%mm3       \n\t" // Y0Y0 Y0Y0(8)
1813         "pand                    %%mm7, %%mm4       \n\t" // Y0Y0 Y0Y0(12)
1814         "packuswb                %%mm2, %%mm1       \n\t" // UVUV UVUV(8)
1815         "packuswb                %%mm4, %%mm3       \n\t" // YYYY YYYY(8)
1816
1817         MOVNTQ"                  %%mm3, 8(%1, %%"REG_a", 2) \n\t"
1818
1819         "movq                    %%mm0, %%mm2       \n\t" // UVUV UVUV(0)
1820         "movq                    %%mm1, %%mm3       \n\t" // UVUV UVUV(8)
1821         "psrlw                      $8, %%mm0       \n\t" // V0V0 V0V0(0)
1822         "psrlw                      $8, %%mm1       \n\t" // V0V0 V0V0(8)
1823         "pand                    %%mm7, %%mm2       \n\t" // U0U0 U0U0(0)
1824         "pand                    %%mm7, %%mm3       \n\t" // U0U0 U0U0(8)
1825         "packuswb                %%mm1, %%mm0       \n\t" // VVVV VVVV(0)
1826         "packuswb                %%mm3, %%mm2       \n\t" // UUUU UUUU(0)
1827
1828         MOVNTQ"                  %%mm0, (%3, %%"REG_a")     \n\t"
1829         MOVNTQ"                  %%mm2, (%2, %%"REG_a")     \n\t"
1830
1831         "add                        $8, %%"REG_a"   \n\t"
1832         "cmp                        %4, %%"REG_a"   \n\t"
1833         " jb                        1b              \n\t"
1834         ::"r"(src), "r"(ydst), "r"(udst), "r"(vdst), "g" (chromWidth)
1835         : "memory", "%"REG_a
1836         );
1837
1838         ydst += lumStride;
1839         src  += srcStride;
1840
1841         asm volatile(
1842         "xor                 %%"REG_a", %%"REG_a"   \n\t"
1843         ASMALIGN(4)
1844         "1:                                         \n\t"
1845         PREFETCH" 64(%0, %%"REG_a", 4)              \n\t"
1846         "movq       (%0, %%"REG_a", 4), %%mm0       \n\t" // YUYV YUYV(0)
1847         "movq      8(%0, %%"REG_a", 4), %%mm1       \n\t" // YUYV YUYV(4)
1848         "movq     16(%0, %%"REG_a", 4), %%mm2       \n\t" // YUYV YUYV(8)
1849         "movq     24(%0, %%"REG_a", 4), %%mm3       \n\t" // YUYV YUYV(12)
1850         "pand                    %%mm7, %%mm0       \n\t" // Y0Y0 Y0Y0(0)
1851         "pand                    %%mm7, %%mm1       \n\t" // Y0Y0 Y0Y0(4)
1852         "pand                    %%mm7, %%mm2       \n\t" // Y0Y0 Y0Y0(8)
1853         "pand                    %%mm7, %%mm3       \n\t" // Y0Y0 Y0Y0(12)
1854         "packuswb                %%mm1, %%mm0       \n\t" // YYYY YYYY(0)
1855         "packuswb                %%mm3, %%mm2       \n\t" // YYYY YYYY(8)
1856
1857         MOVNTQ"                  %%mm0,  (%1, %%"REG_a", 2) \n\t"
1858         MOVNTQ"                  %%mm2, 8(%1, %%"REG_a", 2) \n\t"
1859
1860         "add                        $8, %%"REG_a"   \n\t"
1861         "cmp                        %4, %%"REG_a"   \n\t"
1862         " jb                        1b              \n\t"
1863
1864         ::"r"(src), "r"(ydst), "r"(udst), "r"(vdst), "g" (chromWidth)
1865         : "memory", "%"REG_a
1866         );
1867 #else
1868         long i;
1869         for (i=0; i<chromWidth; i++)
1870         {
1871             ydst[2*i+0]     = src[4*i+0];
1872             udst[i]     = src[4*i+1];
1873             ydst[2*i+1]     = src[4*i+2];
1874             vdst[i]     = src[4*i+3];
1875         }
1876         ydst += lumStride;
1877         src  += srcStride;
1878
1879         for (i=0; i<chromWidth; i++)
1880         {
1881             ydst[2*i+0]     = src[4*i+0];
1882             ydst[2*i+1]     = src[4*i+2];
1883         }
1884 #endif
1885         udst += chromStride;
1886         vdst += chromStride;
1887         ydst += lumStride;
1888         src  += srcStride;
1889     }
1890 #ifdef HAVE_MMX
1891 asm volatile(   EMMS"       \n\t"
1892                 SFENCE"     \n\t"
1893                 :::"memory");
1894 #endif
1895 }
1896
1897 static inline void RENAME(yvu9toyv12)(const uint8_t *ysrc, const uint8_t *usrc, const uint8_t *vsrc,
1898                                       uint8_t *ydst, uint8_t *udst, uint8_t *vdst,
1899                                       long width, long height, long lumStride, long chromStride)
1900 {
1901     /* Y Plane */
1902     memcpy(ydst, ysrc, width*height);
1903
1904     /* XXX: implement upscaling for U,V */
1905 }
1906
1907 static inline void RENAME(planar2x)(const uint8_t *src, uint8_t *dst, long srcWidth, long srcHeight, long srcStride, long dstStride)
1908 {
1909     long x,y;
1910
1911     dst[0]= src[0];
1912
1913     // first line
1914     for (x=0; x<srcWidth-1; x++){
1915         dst[2*x+1]= (3*src[x] +   src[x+1])>>2;
1916         dst[2*x+2]= (  src[x] + 3*src[x+1])>>2;
1917     }
1918     dst[2*srcWidth-1]= src[srcWidth-1];
1919
1920         dst+= dstStride;
1921
1922     for (y=1; y<srcHeight; y++){
1923 #if defined (HAVE_MMX2) || defined (HAVE_3DNOW)
1924         const long mmxSize= srcWidth&~15;
1925         asm volatile(
1926         "mov           %4, %%"REG_a"            \n\t"
1927         "1:                                     \n\t"
1928         "movq         (%0, %%"REG_a"), %%mm0    \n\t"
1929         "movq         (%1, %%"REG_a"), %%mm1    \n\t"
1930         "movq        1(%0, %%"REG_a"), %%mm2    \n\t"
1931         "movq        1(%1, %%"REG_a"), %%mm3    \n\t"
1932         "movq       -1(%0, %%"REG_a"), %%mm4    \n\t"
1933         "movq       -1(%1, %%"REG_a"), %%mm5    \n\t"
1934         PAVGB"                  %%mm0, %%mm5    \n\t"
1935         PAVGB"                  %%mm0, %%mm3    \n\t"
1936         PAVGB"                  %%mm0, %%mm5    \n\t"
1937         PAVGB"                  %%mm0, %%mm3    \n\t"
1938         PAVGB"                  %%mm1, %%mm4    \n\t"
1939         PAVGB"                  %%mm1, %%mm2    \n\t"
1940         PAVGB"                  %%mm1, %%mm4    \n\t"
1941         PAVGB"                  %%mm1, %%mm2    \n\t"
1942         "movq                   %%mm5, %%mm7    \n\t"
1943         "movq                   %%mm4, %%mm6    \n\t"
1944         "punpcklbw              %%mm3, %%mm5    \n\t"
1945         "punpckhbw              %%mm3, %%mm7    \n\t"
1946         "punpcklbw              %%mm2, %%mm4    \n\t"
1947         "punpckhbw              %%mm2, %%mm6    \n\t"
1948 #if 1
1949         MOVNTQ"                 %%mm5,  (%2, %%"REG_a", 2)  \n\t"
1950         MOVNTQ"                 %%mm7, 8(%2, %%"REG_a", 2)  \n\t"
1951         MOVNTQ"                 %%mm4,  (%3, %%"REG_a", 2)  \n\t"
1952         MOVNTQ"                 %%mm6, 8(%3, %%"REG_a", 2)  \n\t"
1953 #else
1954         "movq                   %%mm5,  (%2, %%"REG_a", 2)  \n\t"
1955         "movq                   %%mm7, 8(%2, %%"REG_a", 2)  \n\t"
1956         "movq                   %%mm4,  (%3, %%"REG_a", 2)  \n\t"
1957         "movq                   %%mm6, 8(%3, %%"REG_a", 2)  \n\t"
1958 #endif
1959         "add                       $8, %%"REG_a"            \n\t"
1960         " js                       1b                       \n\t"
1961         :: "r" (src + mmxSize  ), "r" (src + srcStride + mmxSize  ),
1962            "r" (dst + mmxSize*2), "r" (dst + dstStride + mmxSize*2),
1963            "g" (-mmxSize)
1964         : "%"REG_a
1965
1966         );
1967 #else
1968         const long mmxSize=1;
1969 #endif
1970         dst[0        ]= (3*src[0] +   src[srcStride])>>2;
1971         dst[dstStride]= (  src[0] + 3*src[srcStride])>>2;
1972
1973         for (x=mmxSize-1; x<srcWidth-1; x++){
1974             dst[2*x          +1]= (3*src[x+0] +   src[x+srcStride+1])>>2;
1975             dst[2*x+dstStride+2]= (  src[x+0] + 3*src[x+srcStride+1])>>2;
1976             dst[2*x+dstStride+1]= (  src[x+1] + 3*src[x+srcStride  ])>>2;
1977             dst[2*x          +2]= (3*src[x+1] +   src[x+srcStride  ])>>2;
1978         }
1979         dst[srcWidth*2 -1            ]= (3*src[srcWidth-1] +   src[srcWidth-1 + srcStride])>>2;
1980         dst[srcWidth*2 -1 + dstStride]= (  src[srcWidth-1] + 3*src[srcWidth-1 + srcStride])>>2;
1981
1982         dst+=dstStride*2;
1983         src+=srcStride;
1984     }
1985
1986     // last line
1987 #if 1
1988     dst[0]= src[0];
1989
1990     for (x=0; x<srcWidth-1; x++){
1991         dst[2*x+1]= (3*src[x] +   src[x+1])>>2;
1992         dst[2*x+2]= (  src[x] + 3*src[x+1])>>2;
1993     }
1994     dst[2*srcWidth-1]= src[srcWidth-1];
1995 #else
1996     for (x=0; x<srcWidth; x++){
1997         dst[2*x+0]=
1998         dst[2*x+1]= src[x];
1999     }
2000 #endif
2001
2002 #ifdef HAVE_MMX
2003 asm volatile(   EMMS"       \n\t"
2004                 SFENCE"     \n\t"
2005                 :::"memory");
2006 #endif
2007 }
2008
2009 /**
2010  *
2011  * height should be a multiple of 2 and width should be a multiple of 16 (if this is a
2012  * problem for anyone then tell me, and ill fix it)
2013  * chrominance data is only taken from every secound line others are ignored FIXME write HQ version
2014  */
2015 static inline void RENAME(uyvytoyv12)(const uint8_t *src, uint8_t *ydst, uint8_t *udst, uint8_t *vdst,
2016                                       long width, long height,
2017                                       long lumStride, long chromStride, long srcStride)
2018 {
2019     long y;
2020     const long chromWidth= width>>1;
2021     for (y=0; y<height; y+=2)
2022     {
2023 #ifdef HAVE_MMX
2024         asm volatile(
2025         "xorl                %%eax, %%eax   \n\t"
2026         "pcmpeqw             %%mm7, %%mm7   \n\t"
2027         "psrlw                  $8, %%mm7   \n\t" // FF,00,FF,00...
2028         ASMALIGN(4)
2029         "1:                                 \n\t"
2030         PREFETCH" 64(%0, %%eax, 4)          \n\t"
2031         "movq       (%0, %%eax, 4), %%mm0   \n\t" // UYVY UYVY(0)
2032         "movq      8(%0, %%eax, 4), %%mm1   \n\t" // UYVY UYVY(4)
2033         "movq                %%mm0, %%mm2   \n\t" // UYVY UYVY(0)
2034         "movq                %%mm1, %%mm3   \n\t" // UYVY UYVY(4)
2035         "pand                %%mm7, %%mm0   \n\t" // U0V0 U0V0(0)
2036         "pand                %%mm7, %%mm1   \n\t" // U0V0 U0V0(4)
2037         "psrlw                  $8, %%mm2   \n\t" // Y0Y0 Y0Y0(0)
2038         "psrlw                  $8, %%mm3   \n\t" // Y0Y0 Y0Y0(4)
2039         "packuswb            %%mm1, %%mm0   \n\t" // UVUV UVUV(0)
2040         "packuswb            %%mm3, %%mm2   \n\t" // YYYY YYYY(0)
2041
2042         MOVNTQ"              %%mm2,  (%1, %%eax, 2) \n\t"
2043
2044         "movq     16(%0, %%eax, 4), %%mm1   \n\t" // UYVY UYVY(8)
2045         "movq     24(%0, %%eax, 4), %%mm2   \n\t" // UYVY UYVY(12)
2046         "movq                %%mm1, %%mm3   \n\t" // UYVY UYVY(8)
2047         "movq                %%mm2, %%mm4   \n\t" // UYVY UYVY(12)
2048         "pand                %%mm7, %%mm1   \n\t" // U0V0 U0V0(8)
2049         "pand                %%mm7, %%mm2   \n\t" // U0V0 U0V0(12)
2050         "psrlw                  $8, %%mm3   \n\t" // Y0Y0 Y0Y0(8)
2051         "psrlw                  $8, %%mm4   \n\t" // Y0Y0 Y0Y0(12)
2052         "packuswb            %%mm2, %%mm1   \n\t" // UVUV UVUV(8)
2053         "packuswb            %%mm4, %%mm3   \n\t" // YYYY YYYY(8)
2054
2055         MOVNTQ"              %%mm3, 8(%1, %%eax, 2) \n\t"
2056
2057         "movq                %%mm0, %%mm2   \n\t" // UVUV UVUV(0)
2058         "movq                %%mm1, %%mm3   \n\t" // UVUV UVUV(8)
2059         "psrlw                  $8, %%mm0   \n\t" // V0V0 V0V0(0)
2060         "psrlw                  $8, %%mm1   \n\t" // V0V0 V0V0(8)
2061         "pand                %%mm7, %%mm2   \n\t" // U0U0 U0U0(0)
2062         "pand                %%mm7, %%mm3   \n\t" // U0U0 U0U0(8)
2063         "packuswb            %%mm1, %%mm0   \n\t" // VVVV VVVV(0)
2064         "packuswb            %%mm3, %%mm2   \n\t" // UUUU UUUU(0)
2065
2066         MOVNTQ"              %%mm0, (%3, %%eax) \n\t"
2067         MOVNTQ"              %%mm2, (%2, %%eax) \n\t"
2068
2069         "addl                   $8, %%eax   \n\t"
2070         "cmpl                   %4, %%eax   \n\t"
2071         " jb                    1b          \n\t"
2072         ::"r"(src), "r"(ydst), "r"(udst), "r"(vdst), "g" (chromWidth)
2073         : "memory", "%eax"
2074         );
2075
2076         ydst += lumStride;
2077         src  += srcStride;
2078
2079         asm volatile(
2080         "xorl                %%eax, %%eax   \n\t"
2081         ASMALIGN(4)
2082         "1:                                 \n\t"
2083         PREFETCH" 64(%0, %%eax, 4)          \n\t"
2084         "movq       (%0, %%eax, 4), %%mm0   \n\t" // YUYV YUYV(0)
2085         "movq      8(%0, %%eax, 4), %%mm1   \n\t" // YUYV YUYV(4)
2086         "movq     16(%0, %%eax, 4), %%mm2   \n\t" // YUYV YUYV(8)
2087         "movq     24(%0, %%eax, 4), %%mm3   \n\t" // YUYV YUYV(12)
2088         "psrlw                  $8, %%mm0   \n\t" // Y0Y0 Y0Y0(0)
2089         "psrlw                  $8, %%mm1   \n\t" // Y0Y0 Y0Y0(4)
2090         "psrlw                  $8, %%mm2   \n\t" // Y0Y0 Y0Y0(8)
2091         "psrlw                  $8, %%mm3   \n\t" // Y0Y0 Y0Y0(12)
2092         "packuswb            %%mm1, %%mm0   \n\t" // YYYY YYYY(0)
2093         "packuswb            %%mm3, %%mm2   \n\t" // YYYY YYYY(8)
2094
2095         MOVNTQ"              %%mm0,  (%1, %%eax, 2) \n\t"
2096         MOVNTQ"              %%mm2, 8(%1, %%eax, 2) \n\t"
2097
2098         "addl                   $8, %%eax   \n\t"
2099         "cmpl                   %4, %%eax   \n\t"
2100         " jb                    1b          \n\t"
2101
2102         ::"r"(src), "r"(ydst), "r"(udst), "r"(vdst), "g" (chromWidth)
2103         : "memory", "%eax"
2104         );
2105 #else
2106         long i;
2107         for (i=0; i<chromWidth; i++)
2108         {
2109             udst[i]     = src[4*i+0];
2110             ydst[2*i+0] = src[4*i+1];
2111             vdst[i]     = src[4*i+2];
2112             ydst[2*i+1] = src[4*i+3];
2113         }
2114         ydst += lumStride;
2115         src  += srcStride;
2116
2117         for (i=0; i<chromWidth; i++)
2118         {
2119             ydst[2*i+0] = src[4*i+1];
2120             ydst[2*i+1] = src[4*i+3];
2121         }
2122 #endif
2123         udst += chromStride;
2124         vdst += chromStride;
2125         ydst += lumStride;
2126         src  += srcStride;
2127     }
2128 #ifdef HAVE_MMX
2129 asm volatile(   EMMS"       \n\t"
2130                 SFENCE"     \n\t"
2131                 :::"memory");
2132 #endif
2133 }
2134
2135 /**
2136  *
2137  * height should be a multiple of 2 and width should be a multiple of 2 (if this is a
2138  * problem for anyone then tell me, and ill fix it)
2139  * chrominance data is only taken from every secound line others are ignored in the C version FIXME write HQ version
2140  */
2141 static inline void RENAME(rgb24toyv12)(const uint8_t *src, uint8_t *ydst, uint8_t *udst, uint8_t *vdst,
2142                                        long width, long height,
2143                                        long lumStride, long chromStride, long srcStride)
2144 {
2145     long y;
2146     const long chromWidth= width>>1;
2147 #ifdef HAVE_MMX
2148     for (y=0; y<height-2; y+=2)
2149     {
2150         long i;
2151         for (i=0; i<2; i++)
2152         {
2153             asm volatile(
2154             "mov                        %2, %%"REG_a"   \n\t"
2155             "movq     "MANGLE(bgr2YCoeff)", %%mm6       \n\t"
2156             "movq          "MANGLE(w1111)", %%mm5       \n\t"
2157             "pxor                    %%mm7, %%mm7       \n\t"
2158             "lea (%%"REG_a", %%"REG_a", 2), %%"REG_d"   \n\t"
2159             ASMALIGN(4)
2160             "1:                                         \n\t"
2161             PREFETCH"    64(%0, %%"REG_d")              \n\t"
2162             "movd          (%0, %%"REG_d"), %%mm0       \n\t"
2163             "movd         3(%0, %%"REG_d"), %%mm1       \n\t"
2164             "punpcklbw               %%mm7, %%mm0       \n\t"
2165             "punpcklbw               %%mm7, %%mm1       \n\t"
2166             "movd         6(%0, %%"REG_d"), %%mm2       \n\t"
2167             "movd         9(%0, %%"REG_d"), %%mm3       \n\t"
2168             "punpcklbw               %%mm7, %%mm2       \n\t"
2169             "punpcklbw               %%mm7, %%mm3       \n\t"
2170             "pmaddwd                 %%mm6, %%mm0       \n\t"
2171             "pmaddwd                 %%mm6, %%mm1       \n\t"
2172             "pmaddwd                 %%mm6, %%mm2       \n\t"
2173             "pmaddwd                 %%mm6, %%mm3       \n\t"
2174 #ifndef FAST_BGR2YV12
2175             "psrad                      $8, %%mm0       \n\t"
2176             "psrad                      $8, %%mm1       \n\t"
2177             "psrad                      $8, %%mm2       \n\t"
2178             "psrad                      $8, %%mm3       \n\t"
2179 #endif
2180             "packssdw                %%mm1, %%mm0       \n\t"
2181             "packssdw                %%mm3, %%mm2       \n\t"
2182             "pmaddwd                 %%mm5, %%mm0       \n\t"
2183             "pmaddwd                 %%mm5, %%mm2       \n\t"
2184             "packssdw                %%mm2, %%mm0       \n\t"
2185             "psraw                      $7, %%mm0       \n\t"
2186
2187             "movd        12(%0, %%"REG_d"), %%mm4       \n\t"
2188             "movd        15(%0, %%"REG_d"), %%mm1       \n\t"
2189             "punpcklbw               %%mm7, %%mm4       \n\t"
2190             "punpcklbw               %%mm7, %%mm1       \n\t"
2191             "movd        18(%0, %%"REG_d"), %%mm2       \n\t"
2192             "movd        21(%0, %%"REG_d"), %%mm3       \n\t"
2193             "punpcklbw               %%mm7, %%mm2       \n\t"
2194             "punpcklbw               %%mm7, %%mm3       \n\t"
2195             "pmaddwd                 %%mm6, %%mm4       \n\t"
2196             "pmaddwd                 %%mm6, %%mm1       \n\t"
2197             "pmaddwd                 %%mm6, %%mm2       \n\t"
2198             "pmaddwd                 %%mm6, %%mm3       \n\t"
2199 #ifndef FAST_BGR2YV12
2200             "psrad                      $8, %%mm4       \n\t"
2201             "psrad                      $8, %%mm1       \n\t"
2202             "psrad                      $8, %%mm2       \n\t"
2203             "psrad                      $8, %%mm3       \n\t"
2204 #endif
2205             "packssdw                %%mm1, %%mm4       \n\t"
2206             "packssdw                %%mm3, %%mm2       \n\t"
2207             "pmaddwd                 %%mm5, %%mm4       \n\t"
2208             "pmaddwd                 %%mm5, %%mm2       \n\t"
2209             "add                       $24, %%"REG_d"   \n\t"
2210             "packssdw                %%mm2, %%mm4       \n\t"
2211             "psraw                      $7, %%mm4       \n\t"
2212
2213             "packuswb                %%mm4, %%mm0       \n\t"
2214             "paddusb "MANGLE(bgr2YOffset)", %%mm0       \n\t"
2215
2216             MOVNTQ"                  %%mm0, (%1, %%"REG_a") \n\t"
2217             "add                        $8,      %%"REG_a"  \n\t"
2218             " js                        1b                  \n\t"
2219             : : "r" (src+width*3), "r" (ydst+width), "g" (-width)
2220             : "%"REG_a, "%"REG_d
2221             );
2222             ydst += lumStride;
2223             src  += srcStride;
2224         }
2225         src -= srcStride*2;
2226         asm volatile(
2227         "mov                        %4, %%"REG_a"   \n\t"
2228         "movq          "MANGLE(w1111)", %%mm5       \n\t"
2229         "movq     "MANGLE(bgr2UCoeff)", %%mm6       \n\t"
2230         "pxor                    %%mm7, %%mm7       \n\t"
2231         "lea (%%"REG_a", %%"REG_a", 2), %%"REG_d"   \n\t"
2232         "add                 %%"REG_d", %%"REG_d"   \n\t"
2233         ASMALIGN(4)
2234         "1:                                         \n\t"
2235         PREFETCH"    64(%0, %%"REG_d")              \n\t"
2236         PREFETCH"    64(%1, %%"REG_d")              \n\t"
2237 #if defined (HAVE_MMX2) || defined (HAVE_3DNOW)
2238         "movq          (%0, %%"REG_d"), %%mm0       \n\t"
2239         "movq          (%1, %%"REG_d"), %%mm1       \n\t"
2240         "movq         6(%0, %%"REG_d"), %%mm2       \n\t"
2241         "movq         6(%1, %%"REG_d"), %%mm3       \n\t"
2242         PAVGB"                   %%mm1, %%mm0       \n\t"
2243         PAVGB"                   %%mm3, %%mm2       \n\t"
2244         "movq                    %%mm0, %%mm1       \n\t"
2245         "movq                    %%mm2, %%mm3       \n\t"
2246         "psrlq                     $24, %%mm0       \n\t"
2247         "psrlq                     $24, %%mm2       \n\t"
2248         PAVGB"                   %%mm1, %%mm0       \n\t"
2249         PAVGB"                   %%mm3, %%mm2       \n\t"
2250         "punpcklbw               %%mm7, %%mm0       \n\t"
2251         "punpcklbw               %%mm7, %%mm2       \n\t"
2252 #else
2253         "movd          (%0, %%"REG_d"), %%mm0       \n\t"
2254         "movd          (%1, %%"REG_d"), %%mm1       \n\t"
2255         "movd         3(%0, %%"REG_d"), %%mm2       \n\t"
2256         "movd         3(%1, %%"REG_d"), %%mm3       \n\t"
2257         "punpcklbw               %%mm7, %%mm0       \n\t"
2258         "punpcklbw               %%mm7, %%mm1       \n\t"
2259         "punpcklbw               %%mm7, %%mm2       \n\t"
2260         "punpcklbw               %%mm7, %%mm3       \n\t"
2261         "paddw                   %%mm1, %%mm0       \n\t"
2262         "paddw                   %%mm3, %%mm2       \n\t"
2263         "paddw                   %%mm2, %%mm0       \n\t"
2264         "movd         6(%0, %%"REG_d"), %%mm4       \n\t"
2265         "movd         6(%1, %%"REG_d"), %%mm1       \n\t"
2266         "movd         9(%0, %%"REG_d"), %%mm2       \n\t"
2267         "movd         9(%1, %%"REG_d"), %%mm3       \n\t"
2268         "punpcklbw               %%mm7, %%mm4       \n\t"
2269         "punpcklbw               %%mm7, %%mm1       \n\t"
2270         "punpcklbw               %%mm7, %%mm2       \n\t"
2271         "punpcklbw               %%mm7, %%mm3       \n\t"
2272         "paddw                   %%mm1, %%mm4       \n\t"
2273         "paddw                   %%mm3, %%mm2       \n\t"
2274         "paddw                   %%mm4, %%mm2       \n\t"
2275         "psrlw                      $2, %%mm0       \n\t"
2276         "psrlw                      $2, %%mm2       \n\t"
2277 #endif
2278         "movq     "MANGLE(bgr2VCoeff)", %%mm1       \n\t"
2279         "movq     "MANGLE(bgr2VCoeff)", %%mm3       \n\t"
2280
2281         "pmaddwd                 %%mm0, %%mm1       \n\t"
2282         "pmaddwd                 %%mm2, %%mm3       \n\t"
2283         "pmaddwd                 %%mm6, %%mm0       \n\t"
2284         "pmaddwd                 %%mm6, %%mm2       \n\t"
2285 #ifndef FAST_BGR2YV12
2286         "psrad                      $8, %%mm0       \n\t"
2287         "psrad                      $8, %%mm1       \n\t"
2288         "psrad                      $8, %%mm2       \n\t"
2289         "psrad                      $8, %%mm3       \n\t"
2290 #endif
2291         "packssdw                %%mm2, %%mm0       \n\t"
2292         "packssdw                %%mm3, %%mm1       \n\t"
2293         "pmaddwd                 %%mm5, %%mm0       \n\t"
2294         "pmaddwd                 %%mm5, %%mm1       \n\t"
2295         "packssdw                %%mm1, %%mm0       \n\t" // V1 V0 U1 U0
2296         "psraw                      $7, %%mm0       \n\t"
2297
2298 #if defined (HAVE_MMX2) || defined (HAVE_3DNOW)
2299         "movq        12(%0, %%"REG_d"), %%mm4       \n\t"
2300         "movq        12(%1, %%"REG_d"), %%mm1       \n\t"
2301         "movq        18(%0, %%"REG_d"), %%mm2       \n\t"
2302         "movq        18(%1, %%"REG_d"), %%mm3       \n\t"
2303         PAVGB"                   %%mm1, %%mm4       \n\t"
2304         PAVGB"                   %%mm3, %%mm2       \n\t"
2305         "movq                    %%mm4, %%mm1       \n\t"
2306         "movq                    %%mm2, %%mm3       \n\t"
2307         "psrlq                     $24, %%mm4       \n\t"
2308         "psrlq                     $24, %%mm2       \n\t"
2309         PAVGB"                   %%mm1, %%mm4       \n\t"
2310         PAVGB"                   %%mm3, %%mm2       \n\t"
2311         "punpcklbw               %%mm7, %%mm4       \n\t"
2312         "punpcklbw               %%mm7, %%mm2       \n\t"
2313 #else
2314         "movd        12(%0, %%"REG_d"), %%mm4       \n\t"
2315         "movd        12(%1, %%"REG_d"), %%mm1       \n\t"
2316         "movd        15(%0, %%"REG_d"), %%mm2       \n\t"
2317         "movd        15(%1, %%"REG_d"), %%mm3       \n\t"
2318         "punpcklbw               %%mm7, %%mm4       \n\t"
2319         "punpcklbw               %%mm7, %%mm1       \n\t"
2320         "punpcklbw               %%mm7, %%mm2       \n\t"
2321         "punpcklbw               %%mm7, %%mm3       \n\t"
2322         "paddw                   %%mm1, %%mm4       \n\t"
2323         "paddw                   %%mm3, %%mm2       \n\t"
2324         "paddw                   %%mm2, %%mm4       \n\t"
2325         "movd        18(%0, %%"REG_d"), %%mm5       \n\t"
2326         "movd        18(%1, %%"REG_d"), %%mm1       \n\t"
2327         "movd        21(%0, %%"REG_d"), %%mm2       \n\t"
2328         "movd        21(%1, %%"REG_d"), %%mm3       \n\t"
2329         "punpcklbw               %%mm7, %%mm5       \n\t"
2330         "punpcklbw               %%mm7, %%mm1       \n\t"
2331         "punpcklbw               %%mm7, %%mm2       \n\t"
2332         "punpcklbw               %%mm7, %%mm3       \n\t"
2333         "paddw                   %%mm1, %%mm5       \n\t"
2334         "paddw                   %%mm3, %%mm2       \n\t"
2335         "paddw                   %%mm5, %%mm2       \n\t"
2336         "movq          "MANGLE(w1111)", %%mm5       \n\t"
2337         "psrlw                      $2, %%mm4       \n\t"
2338         "psrlw                      $2, %%mm2       \n\t"
2339 #endif
2340         "movq     "MANGLE(bgr2VCoeff)", %%mm1       \n\t"
2341         "movq     "MANGLE(bgr2VCoeff)", %%mm3       \n\t"
2342
2343         "pmaddwd                 %%mm4, %%mm1       \n\t"
2344         "pmaddwd                 %%mm2, %%mm3       \n\t"
2345         "pmaddwd                 %%mm6, %%mm4       \n\t"
2346         "pmaddwd                 %%mm6, %%mm2       \n\t"
2347 #ifndef FAST_BGR2YV12
2348         "psrad                      $8, %%mm4       \n\t"
2349         "psrad                      $8, %%mm1       \n\t"
2350         "psrad                      $8, %%mm2       \n\t"
2351         "psrad                      $8, %%mm3       \n\t"
2352 #endif
2353         "packssdw                %%mm2, %%mm4       \n\t"
2354         "packssdw                %%mm3, %%mm1       \n\t"
2355         "pmaddwd                 %%mm5, %%mm4       \n\t"
2356         "pmaddwd                 %%mm5, %%mm1       \n\t"
2357         "add                       $24, %%"REG_d"   \n\t"
2358         "packssdw                %%mm1, %%mm4       \n\t" // V3 V2 U3 U2
2359         "psraw                      $7, %%mm4       \n\t"
2360
2361         "movq                    %%mm0, %%mm1           \n\t"
2362         "punpckldq               %%mm4, %%mm0           \n\t"
2363         "punpckhdq               %%mm4, %%mm1           \n\t"
2364         "packsswb                %%mm1, %%mm0           \n\t"
2365         "paddb  "MANGLE(bgr2UVOffset)", %%mm0           \n\t"
2366         "movd                    %%mm0, (%2, %%"REG_a") \n\t"
2367         "punpckhdq               %%mm0, %%mm0           \n\t"
2368         "movd                    %%mm0, (%3, %%"REG_a") \n\t"
2369         "add                        $4, %%"REG_a"       \n\t"
2370         " js                        1b                  \n\t"
2371         : : "r" (src+chromWidth*6), "r" (src+srcStride+chromWidth*6), "r" (udst+chromWidth), "r" (vdst+chromWidth), "g" (-chromWidth)
2372         : "%"REG_a, "%"REG_d
2373         );
2374
2375         udst += chromStride;
2376         vdst += chromStride;
2377         src  += srcStride*2;
2378     }
2379
2380     asm volatile(   EMMS"       \n\t"
2381                     SFENCE"     \n\t"
2382                     :::"memory");
2383 #else
2384     y=0;
2385 #endif
2386     for (; y<height; y+=2)
2387     {
2388         long i;
2389         for (i=0; i<chromWidth; i++)
2390         {
2391             unsigned int b = src[6*i+0];
2392             unsigned int g = src[6*i+1];
2393             unsigned int r = src[6*i+2];
2394
2395             unsigned int Y  =  ((RY*r + GY*g + BY*b)>>RGB2YUV_SHIFT) + 16;
2396             unsigned int V  =  ((RV*r + GV*g + BV*b)>>RGB2YUV_SHIFT) + 128;
2397             unsigned int U  =  ((RU*r + GU*g + BU*b)>>RGB2YUV_SHIFT) + 128;
2398
2399             udst[i]     = U;
2400             vdst[i]     = V;
2401             ydst[2*i]   = Y;
2402
2403             b = src[6*i+3];
2404             g = src[6*i+4];
2405             r = src[6*i+5];
2406
2407             Y  =  ((RY*r + GY*g + BY*b)>>RGB2YUV_SHIFT) + 16;
2408             ydst[2*i+1]     = Y;
2409         }
2410         ydst += lumStride;
2411         src  += srcStride;
2412
2413         for (i=0; i<chromWidth; i++)
2414         {
2415             unsigned int b = src[6*i+0];
2416             unsigned int g = src[6*i+1];
2417             unsigned int r = src[6*i+2];
2418
2419             unsigned int Y  =  ((RY*r + GY*g + BY*b)>>RGB2YUV_SHIFT) + 16;
2420
2421             ydst[2*i]     = Y;
2422
2423             b = src[6*i+3];
2424             g = src[6*i+4];
2425             r = src[6*i+5];
2426
2427             Y  =  ((RY*r + GY*g + BY*b)>>RGB2YUV_SHIFT) + 16;
2428             ydst[2*i+1]     = Y;
2429         }
2430         udst += chromStride;
2431         vdst += chromStride;
2432         ydst += lumStride;
2433         src  += srcStride;
2434     }
2435 }
2436
2437 void RENAME(interleaveBytes)(uint8_t *src1, uint8_t *src2, uint8_t *dest,
2438                              long width, long height, long src1Stride,
2439                              long src2Stride, long dstStride){
2440     long h;
2441
2442     for (h=0; h < height; h++)
2443     {
2444         long w;
2445
2446 #ifdef HAVE_MMX
2447 #ifdef HAVE_SSE2
2448         asm(
2449         "xor              %%"REG_a", %%"REG_a"  \n\t"
2450         "1:                                     \n\t"
2451         PREFETCH" 64(%1, %%"REG_a")             \n\t"
2452         PREFETCH" 64(%2, %%"REG_a")             \n\t"
2453         "movdqa     (%1, %%"REG_a"), %%xmm0     \n\t"
2454         "movdqa     (%1, %%"REG_a"), %%xmm1     \n\t"
2455         "movdqa     (%2, %%"REG_a"), %%xmm2     \n\t"
2456         "punpcklbw           %%xmm2, %%xmm0     \n\t"
2457         "punpckhbw           %%xmm2, %%xmm1     \n\t"
2458         "movntdq             %%xmm0,   (%0, %%"REG_a", 2)   \n\t"
2459         "movntdq             %%xmm1, 16(%0, %%"REG_a", 2)   \n\t"
2460         "add                    $16, %%"REG_a"  \n\t"
2461         "cmp                     %3, %%"REG_a"  \n\t"
2462         " jb                     1b             \n\t"
2463         ::"r"(dest), "r"(src1), "r"(src2), "r" (width-15)
2464         : "memory", "%"REG_a""
2465         );
2466 #else
2467         asm(
2468         "xor %%"REG_a", %%"REG_a"               \n\t"
2469         "1:                                     \n\t"
2470         PREFETCH" 64(%1, %%"REG_a")             \n\t"
2471         PREFETCH" 64(%2, %%"REG_a")             \n\t"
2472         "movq       (%1, %%"REG_a"), %%mm0      \n\t"
2473         "movq      8(%1, %%"REG_a"), %%mm2      \n\t"
2474         "movq                 %%mm0, %%mm1      \n\t"
2475         "movq                 %%mm2, %%mm3      \n\t"
2476         "movq       (%2, %%"REG_a"), %%mm4      \n\t"
2477         "movq      8(%2, %%"REG_a"), %%mm5      \n\t"
2478         "punpcklbw            %%mm4, %%mm0      \n\t"
2479         "punpckhbw            %%mm4, %%mm1      \n\t"
2480         "punpcklbw            %%mm5, %%mm2      \n\t"
2481         "punpckhbw            %%mm5, %%mm3      \n\t"
2482         MOVNTQ"               %%mm0,   (%0, %%"REG_a", 2)   \n\t"
2483         MOVNTQ"               %%mm1,  8(%0, %%"REG_a", 2)   \n\t"
2484         MOVNTQ"               %%mm2, 16(%0, %%"REG_a", 2)   \n\t"
2485         MOVNTQ"               %%mm3, 24(%0, %%"REG_a", 2)   \n\t"
2486         "add                    $16, %%"REG_a"  \n\t"
2487         "cmp                     %3, %%"REG_a"  \n\t"
2488         " jb                     1b             \n\t"
2489         ::"r"(dest), "r"(src1), "r"(src2), "r" (width-15)
2490         : "memory", "%"REG_a
2491         );
2492 #endif
2493         for (w= (width&(~15)); w < width; w++)
2494         {
2495             dest[2*w+0] = src1[w];
2496             dest[2*w+1] = src2[w];
2497         }
2498 #else
2499         for (w=0; w < width; w++)
2500         {
2501             dest[2*w+0] = src1[w];
2502             dest[2*w+1] = src2[w];
2503         }
2504 #endif
2505         dest += dstStride;
2506                 src1 += src1Stride;
2507                 src2 += src2Stride;
2508     }
2509 #ifdef HAVE_MMX
2510     asm(
2511         EMMS"       \n\t"
2512         SFENCE"     \n\t"
2513         ::: "memory"
2514         );
2515 #endif
2516 }
2517
2518 static inline void RENAME(vu9_to_vu12)(const uint8_t *src1, const uint8_t *src2,
2519                                        uint8_t *dst1, uint8_t *dst2,
2520                                        long width, long height,
2521                                        long srcStride1, long srcStride2,
2522                                        long dstStride1, long dstStride2)
2523 {
2524     long y,x,w,h;
2525     w=width/2; h=height/2;
2526 #ifdef HAVE_MMX
2527     asm volatile(
2528     PREFETCH" %0    \n\t"
2529     PREFETCH" %1    \n\t"
2530     ::"m"(*(src1+srcStride1)),"m"(*(src2+srcStride2)):"memory");
2531 #endif
2532     for (y=0;y<h;y++){
2533     const uint8_t* s1=src1+srcStride1*(y>>1);
2534     uint8_t* d=dst1+dstStride1*y;
2535     x=0;
2536 #ifdef HAVE_MMX
2537     for (;x<w-31;x+=32)
2538     {
2539         asm volatile(
2540         PREFETCH"   32%1        \n\t"
2541         "movq         %1, %%mm0 \n\t"
2542         "movq        8%1, %%mm2 \n\t"
2543         "movq       16%1, %%mm4 \n\t"
2544         "movq       24%1, %%mm6 \n\t"
2545         "movq      %%mm0, %%mm1 \n\t"
2546         "movq      %%mm2, %%mm3 \n\t"
2547         "movq      %%mm4, %%mm5 \n\t"
2548         "movq      %%mm6, %%mm7 \n\t"
2549         "punpcklbw %%mm0, %%mm0 \n\t"
2550         "punpckhbw %%mm1, %%mm1 \n\t"
2551         "punpcklbw %%mm2, %%mm2 \n\t"
2552         "punpckhbw %%mm3, %%mm3 \n\t"
2553         "punpcklbw %%mm4, %%mm4 \n\t"
2554         "punpckhbw %%mm5, %%mm5 \n\t"
2555         "punpcklbw %%mm6, %%mm6 \n\t"
2556         "punpckhbw %%mm7, %%mm7 \n\t"
2557         MOVNTQ"    %%mm0,   %0  \n\t"
2558         MOVNTQ"    %%mm1,  8%0  \n\t"
2559         MOVNTQ"    %%mm2, 16%0  \n\t"
2560         MOVNTQ"    %%mm3, 24%0  \n\t"
2561         MOVNTQ"    %%mm4, 32%0  \n\t"
2562         MOVNTQ"    %%mm5, 40%0  \n\t"
2563         MOVNTQ"    %%mm6, 48%0  \n\t"
2564         MOVNTQ"    %%mm7, 56%0"
2565         :"=m"(d[2*x])
2566         :"m"(s1[x])
2567         :"memory");
2568     }
2569 #endif
2570     for (;x<w;x++) d[2*x]=d[2*x+1]=s1[x];
2571     }
2572     for (y=0;y<h;y++){
2573     const uint8_t* s2=src2+srcStride2*(y>>1);
2574     uint8_t* d=dst2+dstStride2*y;
2575     x=0;
2576 #ifdef HAVE_MMX
2577     for (;x<w-31;x+=32)
2578     {
2579         asm volatile(
2580         PREFETCH"   32%1        \n\t"
2581         "movq         %1, %%mm0 \n\t"
2582         "movq        8%1, %%mm2 \n\t"
2583         "movq       16%1, %%mm4 \n\t"
2584         "movq       24%1, %%mm6 \n\t"
2585         "movq      %%mm0, %%mm1 \n\t"
2586         "movq      %%mm2, %%mm3 \n\t"
2587         "movq      %%mm4, %%mm5 \n\t"
2588         "movq      %%mm6, %%mm7 \n\t"
2589         "punpcklbw %%mm0, %%mm0 \n\t"
2590         "punpckhbw %%mm1, %%mm1 \n\t"
2591         "punpcklbw %%mm2, %%mm2 \n\t"
2592         "punpckhbw %%mm3, %%mm3 \n\t"
2593         "punpcklbw %%mm4, %%mm4 \n\t"
2594         "punpckhbw %%mm5, %%mm5 \n\t"
2595         "punpcklbw %%mm6, %%mm6 \n\t"
2596         "punpckhbw %%mm7, %%mm7 \n\t"
2597         MOVNTQ"    %%mm0,   %0  \n\t"
2598         MOVNTQ"    %%mm1,  8%0  \n\t"
2599         MOVNTQ"    %%mm2, 16%0  \n\t"
2600         MOVNTQ"    %%mm3, 24%0  \n\t"
2601         MOVNTQ"    %%mm4, 32%0  \n\t"
2602         MOVNTQ"    %%mm5, 40%0  \n\t"
2603         MOVNTQ"    %%mm6, 48%0  \n\t"
2604         MOVNTQ"    %%mm7, 56%0"
2605         :"=m"(d[2*x])
2606         :"m"(s2[x])
2607         :"memory");
2608     }
2609 #endif
2610     for (;x<w;x++) d[2*x]=d[2*x+1]=s2[x];
2611     }
2612 #ifdef HAVE_MMX
2613     asm(
2614         EMMS"       \n\t"
2615         SFENCE"     \n\t"
2616         ::: "memory"
2617         );
2618 #endif
2619 }
2620
2621 static inline void RENAME(yvu9_to_yuy2)(const uint8_t *src1, const uint8_t *src2, const uint8_t *src3,
2622                                         uint8_t *dst,
2623                                         long width, long height,
2624                                         long srcStride1, long srcStride2,
2625                                         long srcStride3, long dstStride)
2626 {
2627     long y,x,w,h;
2628     w=width/2; h=height;
2629     for (y=0;y<h;y++){
2630     const uint8_t* yp=src1+srcStride1*y;
2631     const uint8_t* up=src2+srcStride2*(y>>2);
2632     const uint8_t* vp=src3+srcStride3*(y>>2);
2633     uint8_t* d=dst+dstStride*y;
2634     x=0;
2635 #ifdef HAVE_MMX
2636     for (;x<w-7;x+=8)
2637     {
2638         asm volatile(
2639         PREFETCH"   32(%1, %0)          \n\t"
2640         PREFETCH"   32(%2, %0)          \n\t"
2641         PREFETCH"   32(%3, %0)          \n\t"
2642         "movq      (%1, %0, 4), %%mm0   \n\t" /* Y0Y1Y2Y3Y4Y5Y6Y7 */
2643         "movq         (%2, %0), %%mm1   \n\t" /* U0U1U2U3U4U5U6U7 */
2644         "movq         (%3, %0), %%mm2   \n\t" /* V0V1V2V3V4V5V6V7 */
2645         "movq            %%mm0, %%mm3   \n\t" /* Y0Y1Y2Y3Y4Y5Y6Y7 */
2646         "movq            %%mm1, %%mm4   \n\t" /* U0U1U2U3U4U5U6U7 */
2647         "movq            %%mm2, %%mm5   \n\t" /* V0V1V2V3V4V5V6V7 */
2648         "punpcklbw       %%mm1, %%mm1   \n\t" /* U0U0 U1U1 U2U2 U3U3 */
2649         "punpcklbw       %%mm2, %%mm2   \n\t" /* V0V0 V1V1 V2V2 V3V3 */
2650         "punpckhbw       %%mm4, %%mm4   \n\t" /* U4U4 U5U5 U6U6 U7U7 */
2651         "punpckhbw       %%mm5, %%mm5   \n\t" /* V4V4 V5V5 V6V6 V7V7 */
2652
2653         "movq            %%mm1, %%mm6   \n\t"
2654         "punpcklbw       %%mm2, %%mm1   \n\t" /* U0V0 U0V0 U1V1 U1V1*/
2655         "punpcklbw       %%mm1, %%mm0   \n\t" /* Y0U0 Y1V0 Y2U0 Y3V0*/
2656         "punpckhbw       %%mm1, %%mm3   \n\t" /* Y4U1 Y5V1 Y6U1 Y7V1*/
2657         MOVNTQ"          %%mm0,  (%4, %0, 8)    \n\t"
2658         MOVNTQ"          %%mm3, 8(%4, %0, 8)    \n\t"
2659
2660         "punpckhbw       %%mm2, %%mm6   \n\t" /* U2V2 U2V2 U3V3 U3V3*/
2661         "movq     8(%1, %0, 4), %%mm0   \n\t"
2662         "movq            %%mm0, %%mm3   \n\t"
2663         "punpcklbw       %%mm6, %%mm0   \n\t" /* Y U2 Y V2 Y U2 Y V2*/
2664         "punpckhbw       %%mm6, %%mm3   \n\t" /* Y U3 Y V3 Y U3 Y V3*/
2665         MOVNTQ"          %%mm0, 16(%4, %0, 8)   \n\t"
2666         MOVNTQ"          %%mm3, 24(%4, %0, 8)   \n\t"
2667
2668         "movq            %%mm4, %%mm6   \n\t"
2669         "movq    16(%1, %0, 4), %%mm0   \n\t"
2670         "movq            %%mm0, %%mm3   \n\t"
2671         "punpcklbw       %%mm5, %%mm4   \n\t"
2672         "punpcklbw       %%mm4, %%mm0   \n\t" /* Y U4 Y V4 Y U4 Y V4*/
2673         "punpckhbw       %%mm4, %%mm3   \n\t" /* Y U5 Y V5 Y U5 Y V5*/
2674         MOVNTQ"          %%mm0, 32(%4, %0, 8)   \n\t"
2675         MOVNTQ"          %%mm3, 40(%4, %0, 8)   \n\t"
2676
2677         "punpckhbw       %%mm5, %%mm6   \n\t"
2678         "movq    24(%1, %0, 4), %%mm0   \n\t"
2679         "movq            %%mm0, %%mm3   \n\t"
2680         "punpcklbw       %%mm6, %%mm0   \n\t" /* Y U6 Y V6 Y U6 Y V6*/
2681         "punpckhbw       %%mm6, %%mm3   \n\t" /* Y U7 Y V7 Y U7 Y V7*/
2682         MOVNTQ"          %%mm0, 48(%4, %0, 8)   \n\t"
2683         MOVNTQ"          %%mm3, 56(%4, %0, 8)   \n\t"
2684
2685         : "+r" (x)
2686         : "r"(yp), "r" (up), "r"(vp), "r"(d)
2687         :"memory");
2688     }
2689 #endif
2690     for (; x<w; x++)
2691     {
2692         const long x2 = x<<2;
2693         d[8*x+0] = yp[x2];
2694         d[8*x+1] = up[x];
2695         d[8*x+2] = yp[x2+1];
2696         d[8*x+3] = vp[x];
2697         d[8*x+4] = yp[x2+2];
2698         d[8*x+5] = up[x];
2699         d[8*x+6] = yp[x2+3];
2700         d[8*x+7] = vp[x];
2701     }
2702     }
2703 #ifdef HAVE_MMX
2704     asm(
2705         EMMS"       \n\t"
2706         SFENCE"     \n\t"
2707         ::: "memory"
2708         );
2709 #endif
2710 }
2711
2712 static inline void RENAME(rgb2rgb_init)(void){
2713     rgb15to16       = RENAME(rgb15to16);
2714     rgb15to24       = RENAME(rgb15to24);
2715     rgb15to32       = RENAME(rgb15to32);
2716     rgb16to24       = RENAME(rgb16to24);
2717     rgb16to32       = RENAME(rgb16to32);
2718     rgb16to15       = RENAME(rgb16to15);
2719     rgb24to16       = RENAME(rgb24to16);
2720     rgb24to15       = RENAME(rgb24to15);
2721     rgb24to32       = RENAME(rgb24to32);
2722     rgb32to16       = RENAME(rgb32to16);
2723     rgb32to15       = RENAME(rgb32to15);
2724     rgb32to24       = RENAME(rgb32to24);
2725     rgb24tobgr15    = RENAME(rgb24tobgr15);
2726     rgb24tobgr16    = RENAME(rgb24tobgr16);
2727     rgb24tobgr24    = RENAME(rgb24tobgr24);
2728     rgb32tobgr32    = RENAME(rgb32tobgr32);
2729     rgb32tobgr16    = RENAME(rgb32tobgr16);
2730     rgb32tobgr15    = RENAME(rgb32tobgr15);
2731     yv12toyuy2      = RENAME(yv12toyuy2);
2732     yv12touyvy      = RENAME(yv12touyvy);
2733     yuv422ptoyuy2   = RENAME(yuv422ptoyuy2);
2734     yuy2toyv12      = RENAME(yuy2toyv12);
2735 //    uyvytoyv12      = RENAME(uyvytoyv12);
2736 //    yvu9toyv12      = RENAME(yvu9toyv12);
2737     planar2x        = RENAME(planar2x);
2738     rgb24toyv12     = RENAME(rgb24toyv12);
2739     interleaveBytes = RENAME(interleaveBytes);
2740     vu9_to_vu12     = RENAME(vu9_to_vu12);
2741     yvu9_to_yuy2    = RENAME(yvu9_to_yuy2);
2742 }