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