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