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