copyright year update of the files i touched and remembered, things look annoyingly...
[ffmpeg.git] / libavcodec / i386 / dsputil_mmx_rnd.h
1 /*
2  * DSP utils mmx functions are compiled twice for rnd/no_rnd
3  * Copyright (c) 2000, 2001 Fabrice Bellard.
4  * Copyright (c) 2003-2004 Michael Niedermayer <michaelni@gmx.at>
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this library; if not, write to the Free Software
18  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19  *
20  * MMX optimization by Nick Kurshev <nickols_k@mail.ru>
21  * mostly rewritten by Michael Niedermayer <michaelni@gmx.at>
22  * and improved by Zdenek Kabelac <kabi@users.sf.net>
23  */
24
25 // put_pixels
26 static void DEF(put, pixels8_x2)(uint8_t *block, const uint8_t *pixels, int line_size, int h)
27 {
28     MOVQ_BFE(mm6);
29     __asm __volatile(
30         "lea    (%3, %3), %%eax         \n\t"
31         ".balign 8                      \n\t"
32         "1:                             \n\t"
33         "movq   (%1), %%mm0             \n\t"
34         "movq   1(%1), %%mm1            \n\t"
35         "movq   (%1, %3), %%mm2         \n\t"
36         "movq   1(%1, %3), %%mm3        \n\t"
37         PAVGBP(%%mm0, %%mm1, %%mm4,   %%mm2, %%mm3, %%mm5)
38         "movq   %%mm4, (%2)             \n\t"
39         "movq   %%mm5, (%2, %3)         \n\t"
40         "addl   %%eax, %1               \n\t"
41         "addl   %%eax, %2               \n\t"
42         "movq   (%1), %%mm0             \n\t"
43         "movq   1(%1), %%mm1            \n\t"
44         "movq   (%1, %3), %%mm2         \n\t"
45         "movq   1(%1, %3), %%mm3        \n\t"
46         PAVGBP(%%mm0, %%mm1, %%mm4,   %%mm2, %%mm3, %%mm5)
47         "movq   %%mm4, (%2)             \n\t"
48         "movq   %%mm5, (%2, %3)         \n\t"
49         "addl   %%eax, %1               \n\t"
50         "addl   %%eax, %2               \n\t"
51         "subl   $4, %0                  \n\t"
52         "jnz    1b                      \n\t"
53         :"+g"(h), "+S"(pixels), "+D"(block)
54         :"r"(line_size)
55         :"eax", "memory");
56 }
57
58 static void DEF(put, pixels8_l2)(uint8_t *dst, uint8_t *src1, uint8_t *src2, int dstStride, int src1Stride, int h)
59 {
60     MOVQ_BFE(mm6);
61     __asm __volatile(
62         "testl $1, %0                   \n\t"
63         " jz 1f                         \n\t"
64         "movq   (%1), %%mm0             \n\t"
65         "movq   (%2), %%mm1             \n\t"
66         "addl   %4, %1                  \n\t"
67         "addl   $8, %2                  \n\t"
68         PAVGB(%%mm0, %%mm1, %%mm4, %%mm6)
69         "movq   %%mm4, (%3)             \n\t"
70         "addl   %5, %3                  \n\t"
71         "decl   %0                      \n\t"
72         ".balign 8                      \n\t"
73         "1:                             \n\t"
74         "movq   (%1), %%mm0             \n\t"
75         "movq   (%2), %%mm1             \n\t"
76         "addl   %4, %1                  \n\t"
77         "movq   (%1), %%mm2             \n\t"
78         "movq   8(%2), %%mm3            \n\t"
79         "addl   %4, %1                  \n\t"
80         PAVGBP(%%mm0, %%mm1, %%mm4,   %%mm2, %%mm3, %%mm5)
81         "movq   %%mm4, (%3)             \n\t"
82         "addl   %5, %3                  \n\t"
83         "movq   %%mm5, (%3)             \n\t"
84         "addl   %5, %3                  \n\t"
85         "movq   (%1), %%mm0             \n\t"
86         "movq   16(%2), %%mm1           \n\t"
87         "addl   %4, %1                  \n\t"
88         "movq   (%1), %%mm2             \n\t"
89         "movq   24(%2), %%mm3           \n\t"
90         "addl   %4, %1                  \n\t"
91         "addl   $32, %2                 \n\t"
92         PAVGBP(%%mm0, %%mm1, %%mm4,   %%mm2, %%mm3, %%mm5)
93         "movq   %%mm4, (%3)             \n\t"
94         "addl   %5, %3                  \n\t"
95         "movq   %%mm5, (%3)             \n\t"
96         "addl   %5, %3                  \n\t"
97         "subl   $4, %0                  \n\t"
98         "jnz    1b                      \n\t"
99 #ifdef PIC //Note "+bm" and "+mb" are buggy too (with gcc 3.2.2 at least) and cant be used
100         :"+m"(h), "+a"(src1), "+c"(src2), "+d"(dst)
101 #else
102         :"+b"(h), "+a"(src1), "+c"(src2), "+d"(dst)
103 #endif
104         :"S"(src1Stride), "D"(dstStride)
105         :"memory");
106 }
107
108 static void DEF(put, pixels16_x2)(uint8_t *block, const uint8_t *pixels, int line_size, int h)
109 {
110     MOVQ_BFE(mm6);
111     __asm __volatile(
112         "lea    (%3, %3), %%eax         \n\t"
113         ".balign 8                      \n\t"
114         "1:                             \n\t"
115         "movq   (%1), %%mm0             \n\t"
116         "movq   1(%1), %%mm1            \n\t"
117         "movq   (%1, %3), %%mm2         \n\t"
118         "movq   1(%1, %3), %%mm3        \n\t"
119         PAVGBP(%%mm0, %%mm1, %%mm4,   %%mm2, %%mm3, %%mm5)
120         "movq   %%mm4, (%2)             \n\t"
121         "movq   %%mm5, (%2, %3)         \n\t"
122         "movq   8(%1), %%mm0            \n\t"
123         "movq   9(%1), %%mm1            \n\t"
124         "movq   8(%1, %3), %%mm2        \n\t"
125         "movq   9(%1, %3), %%mm3        \n\t"
126         PAVGBP(%%mm0, %%mm1, %%mm4,   %%mm2, %%mm3, %%mm5)
127         "movq   %%mm4, 8(%2)            \n\t"
128         "movq   %%mm5, 8(%2, %3)        \n\t"
129         "addl   %%eax, %1               \n\t"
130         "addl   %%eax, %2               \n\t"
131         "movq   (%1), %%mm0             \n\t"
132         "movq   1(%1), %%mm1            \n\t"
133         "movq   (%1, %3), %%mm2         \n\t"
134         "movq   1(%1, %3), %%mm3        \n\t"
135         PAVGBP(%%mm0, %%mm1, %%mm4,   %%mm2, %%mm3, %%mm5)
136         "movq   %%mm4, (%2)             \n\t"
137         "movq   %%mm5, (%2, %3)         \n\t"
138         "movq   8(%1), %%mm0            \n\t"
139         "movq   9(%1), %%mm1            \n\t"
140         "movq   8(%1, %3), %%mm2        \n\t"
141         "movq   9(%1, %3), %%mm3        \n\t"
142         PAVGBP(%%mm0, %%mm1, %%mm4,   %%mm2, %%mm3, %%mm5)
143         "movq   %%mm4, 8(%2)            \n\t"
144         "movq   %%mm5, 8(%2, %3)        \n\t"
145         "addl   %%eax, %1               \n\t"
146         "addl   %%eax, %2               \n\t"
147         "subl   $4, %0                  \n\t"
148         "jnz    1b                      \n\t"
149         :"+g"(h), "+S"(pixels), "+D"(block)
150         :"r"(line_size)
151         :"eax", "memory");
152 }
153
154 static void DEF(put, pixels16_l2)(uint8_t *dst, uint8_t *src1, uint8_t *src2, int dstStride, int src1Stride, int h)
155 {
156     MOVQ_BFE(mm6);
157     __asm __volatile(
158         "testl $1, %0                   \n\t"
159         " jz 1f                         \n\t"
160         "movq   (%1), %%mm0             \n\t"
161         "movq   (%2), %%mm1             \n\t"
162         "movq   8(%1), %%mm2            \n\t"
163         "movq   8(%2), %%mm3            \n\t"
164         "addl   %4, %1                  \n\t"
165         "addl   $16, %2                 \n\t"
166         PAVGBP(%%mm0, %%mm1, %%mm4,   %%mm2, %%mm3, %%mm5)
167         "movq   %%mm4, (%3)             \n\t"
168         "movq   %%mm5, 8(%3)            \n\t"
169         "addl   %5, %3                  \n\t"
170         "decl   %0                      \n\t"
171         ".balign 8                      \n\t"
172         "1:                             \n\t"
173         "movq   (%1), %%mm0             \n\t"
174         "movq   (%2), %%mm1             \n\t"
175         "movq   8(%1), %%mm2            \n\t"
176         "movq   8(%2), %%mm3            \n\t"
177         "addl   %4, %1                  \n\t"
178         PAVGBP(%%mm0, %%mm1, %%mm4,   %%mm2, %%mm3, %%mm5)
179         "movq   %%mm4, (%3)             \n\t"
180         "movq   %%mm5, 8(%3)            \n\t"
181         "addl   %5, %3                  \n\t"
182         "movq   (%1), %%mm0             \n\t"
183         "movq   16(%2), %%mm1           \n\t"
184         "movq   8(%1), %%mm2            \n\t"
185         "movq   24(%2), %%mm3           \n\t"
186         "addl   %4, %1                  \n\t"
187         PAVGBP(%%mm0, %%mm1, %%mm4,   %%mm2, %%mm3, %%mm5)
188         "movq   %%mm4, (%3)             \n\t"
189         "movq   %%mm5, 8(%3)            \n\t"
190         "addl   %5, %3                  \n\t"
191         "addl   $32, %2                 \n\t"
192         "subl   $2, %0                  \n\t"
193         "jnz    1b                      \n\t"
194 #ifdef PIC //Note "+bm" and "+mb" are buggy too (with gcc 3.2.2 at least) and cant be used
195         :"+m"(h), "+a"(src1), "+c"(src2), "+d"(dst)
196 #else
197         :"+b"(h), "+a"(src1), "+c"(src2), "+d"(dst)
198 #endif
199         :"S"(src1Stride), "D"(dstStride)
200         :"memory"); 
201 }
202
203 static void DEF(put, pixels8_y2)(uint8_t *block, const uint8_t *pixels, int line_size, int h)
204 {
205     MOVQ_BFE(mm6);
206     __asm __volatile(
207         "lea (%3, %3), %%eax            \n\t"
208         "movq (%1), %%mm0               \n\t"
209         ".balign 8                      \n\t"
210         "1:                             \n\t"
211         "movq   (%1, %3), %%mm1         \n\t"
212         "movq   (%1, %%eax),%%mm2       \n\t"
213         PAVGBP(%%mm1, %%mm0, %%mm4,   %%mm2, %%mm1, %%mm5)
214         "movq   %%mm4, (%2)             \n\t"
215         "movq   %%mm5, (%2, %3)         \n\t"
216         "addl   %%eax, %1               \n\t"
217         "addl   %%eax, %2               \n\t"
218         "movq   (%1, %3), %%mm1         \n\t"
219         "movq   (%1, %%eax),%%mm0       \n\t"
220         PAVGBP(%%mm1, %%mm2, %%mm4,   %%mm0, %%mm1, %%mm5)
221         "movq   %%mm4, (%2)             \n\t"
222         "movq   %%mm5, (%2, %3)         \n\t"
223         "addl   %%eax, %1               \n\t"
224         "addl   %%eax, %2               \n\t"
225         "subl   $4, %0                  \n\t"
226         "jnz    1b                      \n\t"
227         :"+g"(h), "+S"(pixels), "+D"(block)
228         :"r"(line_size)
229         :"eax", "memory");
230 }
231
232 static void DEF(put, pixels8_xy2)(uint8_t *block, const uint8_t *pixels, int line_size, int h)
233 {
234     MOVQ_ZERO(mm7);
235     SET_RND(mm6); // =2 for rnd  and  =1 for no_rnd version
236     __asm __volatile(
237         "movq   (%1), %%mm0             \n\t"
238         "movq   1(%1), %%mm4            \n\t"
239         "movq   %%mm0, %%mm1            \n\t"
240         "movq   %%mm4, %%mm5            \n\t"
241         "punpcklbw %%mm7, %%mm0         \n\t"
242         "punpcklbw %%mm7, %%mm4         \n\t"
243         "punpckhbw %%mm7, %%mm1         \n\t"
244         "punpckhbw %%mm7, %%mm5         \n\t"
245         "paddusw %%mm0, %%mm4           \n\t"
246         "paddusw %%mm1, %%mm5           \n\t"
247         "xorl   %%eax, %%eax            \n\t"
248         "addl   %3, %1                  \n\t"
249         ".balign 8                      \n\t"
250         "1:                             \n\t"
251         "movq   (%1, %%eax), %%mm0      \n\t"
252         "movq   1(%1, %%eax), %%mm2     \n\t"
253         "movq   %%mm0, %%mm1            \n\t"
254         "movq   %%mm2, %%mm3            \n\t"
255         "punpcklbw %%mm7, %%mm0         \n\t"
256         "punpcklbw %%mm7, %%mm2         \n\t"
257         "punpckhbw %%mm7, %%mm1         \n\t"
258         "punpckhbw %%mm7, %%mm3         \n\t"
259         "paddusw %%mm2, %%mm0           \n\t"
260         "paddusw %%mm3, %%mm1           \n\t"
261         "paddusw %%mm6, %%mm4           \n\t"
262         "paddusw %%mm6, %%mm5           \n\t"
263         "paddusw %%mm0, %%mm4           \n\t"
264         "paddusw %%mm1, %%mm5           \n\t"
265         "psrlw  $2, %%mm4               \n\t"
266         "psrlw  $2, %%mm5               \n\t"
267         "packuswb  %%mm5, %%mm4         \n\t"
268         "movq   %%mm4, (%2, %%eax)      \n\t"
269         "addl   %3, %%eax               \n\t"
270
271         "movq   (%1, %%eax), %%mm2      \n\t" // 0 <-> 2   1 <-> 3
272         "movq   1(%1, %%eax), %%mm4     \n\t"
273         "movq   %%mm2, %%mm3            \n\t"
274         "movq   %%mm4, %%mm5            \n\t"
275         "punpcklbw %%mm7, %%mm2         \n\t"
276         "punpcklbw %%mm7, %%mm4         \n\t"
277         "punpckhbw %%mm7, %%mm3         \n\t"
278         "punpckhbw %%mm7, %%mm5         \n\t"
279         "paddusw %%mm2, %%mm4           \n\t"
280         "paddusw %%mm3, %%mm5           \n\t"
281         "paddusw %%mm6, %%mm0           \n\t"
282         "paddusw %%mm6, %%mm1           \n\t"
283         "paddusw %%mm4, %%mm0           \n\t"
284         "paddusw %%mm5, %%mm1           \n\t"
285         "psrlw  $2, %%mm0               \n\t"
286         "psrlw  $2, %%mm1               \n\t"
287         "packuswb  %%mm1, %%mm0         \n\t"
288         "movq   %%mm0, (%2, %%eax)      \n\t"
289         "addl   %3, %%eax               \n\t"
290
291         "subl   $2, %0                  \n\t"
292         "jnz    1b                      \n\t"
293         :"+g"(h), "+S"(pixels)
294         :"D"(block), "r"(line_size)
295         :"eax", "memory");
296 }
297
298 // avg_pixels
299 // in case more speed is needed - unroling would certainly help
300 static void DEF(avg, pixels8)(uint8_t *block, const uint8_t *pixels, int line_size, int h)
301 {
302     MOVQ_BFE(mm6);
303     JUMPALIGN();
304     do {
305         __asm __volatile(
306              "movq  %0, %%mm0           \n\t"
307              "movq  %1, %%mm1           \n\t"
308              PAVGB(%%mm0, %%mm1, %%mm2, %%mm6)
309              "movq  %%mm2, %0           \n\t"
310              :"+m"(*block)
311              :"m"(*pixels)
312              :"memory");
313         pixels += line_size;
314         block += line_size;
315     }
316     while (--h);
317 }
318
319 static void DEF(avg, pixels16)(uint8_t *block, const uint8_t *pixels, int line_size, int h)
320 {
321     MOVQ_BFE(mm6);
322     JUMPALIGN();
323     do {
324         __asm __volatile(
325              "movq  %0, %%mm0           \n\t"
326              "movq  %1, %%mm1           \n\t"
327              PAVGB(%%mm0, %%mm1, %%mm2, %%mm6)
328              "movq  %%mm2, %0           \n\t"
329              "movq  8%0, %%mm0          \n\t"
330              "movq  8%1, %%mm1          \n\t"
331              PAVGB(%%mm0, %%mm1, %%mm2, %%mm6)
332              "movq  %%mm2, 8%0          \n\t"
333              :"+m"(*block)
334              :"m"(*pixels)
335              :"memory");
336         pixels += line_size;
337         block += line_size;
338     }
339     while (--h);
340 }
341
342 static void DEF(avg, pixels8_x2)(uint8_t *block, const uint8_t *pixels, int line_size, int h)
343 {
344     MOVQ_BFE(mm6);
345     JUMPALIGN();
346     do {
347         __asm __volatile(
348             "movq  %1, %%mm0            \n\t"
349             "movq  1%1, %%mm1           \n\t"
350             "movq  %0, %%mm3            \n\t"
351             PAVGB(%%mm0, %%mm1, %%mm2, %%mm6)
352             PAVGB(%%mm3, %%mm2, %%mm0, %%mm6)
353             "movq  %%mm0, %0            \n\t"
354             :"+m"(*block)
355             :"m"(*pixels)
356             :"memory");
357         pixels += line_size;
358         block += line_size;
359     } while (--h);
360 }
361
362 static void DEF(avg, pixels8_l2)(uint8_t *dst, uint8_t *src1, uint8_t *src2, int dstStride, int src1Stride, int h)
363 {
364     MOVQ_BFE(mm6);
365     JUMPALIGN();
366     do {
367         __asm __volatile(
368             "movq  %1, %%mm0            \n\t"
369             "movq  %2, %%mm1            \n\t"
370             "movq  %0, %%mm3            \n\t"
371             PAVGB(%%mm0, %%mm1, %%mm2, %%mm6)
372             PAVGB(%%mm3, %%mm2, %%mm0, %%mm6)
373             "movq  %%mm0, %0            \n\t"
374             :"+m"(*dst)
375             :"m"(*src1), "m"(*src2)
376             :"memory");
377         dst += dstStride;
378         src1 += src1Stride;
379         src2 += 8;
380     } while (--h);
381 }
382
383 static void DEF(avg, pixels16_x2)(uint8_t *block, const uint8_t *pixels, int line_size, int h)
384 {
385     MOVQ_BFE(mm6);
386     JUMPALIGN();
387     do {
388         __asm __volatile(
389             "movq  %1, %%mm0            \n\t"
390             "movq  1%1, %%mm1           \n\t"
391             "movq  %0, %%mm3            \n\t"
392             PAVGB(%%mm0, %%mm1, %%mm2, %%mm6)
393             PAVGB(%%mm3, %%mm2, %%mm0, %%mm6)
394             "movq  %%mm0, %0            \n\t"
395             "movq  8%1, %%mm0           \n\t"
396             "movq  9%1, %%mm1           \n\t"
397             "movq  8%0, %%mm3           \n\t"
398             PAVGB(%%mm0, %%mm1, %%mm2, %%mm6)
399             PAVGB(%%mm3, %%mm2, %%mm0, %%mm6)
400             "movq  %%mm0, 8%0           \n\t"
401             :"+m"(*block)
402             :"m"(*pixels)
403             :"memory");
404         pixels += line_size;
405         block += line_size;
406     } while (--h);
407 }
408
409 static void DEF(avg, pixels16_l2)(uint8_t *dst, uint8_t *src1, uint8_t *src2, int dstStride, int src1Stride, int h)
410 {
411     MOVQ_BFE(mm6);
412     JUMPALIGN();
413     do {
414         __asm __volatile(
415             "movq  %1, %%mm0            \n\t"
416             "movq  %2, %%mm1            \n\t"
417             "movq  %0, %%mm3            \n\t"
418             PAVGB(%%mm0, %%mm1, %%mm2, %%mm6)
419             PAVGB(%%mm3, %%mm2, %%mm0, %%mm6)
420             "movq  %%mm0, %0            \n\t"
421             "movq  8%1, %%mm0           \n\t"
422             "movq  8%2, %%mm1           \n\t"
423             "movq  8%0, %%mm3           \n\t"
424             PAVGB(%%mm0, %%mm1, %%mm2, %%mm6)
425             PAVGB(%%mm3, %%mm2, %%mm0, %%mm6)
426             "movq  %%mm0, 8%0           \n\t"
427             :"+m"(*dst)
428             :"m"(*src1), "m"(*src2)
429             :"memory");
430         dst += dstStride;
431         src1 += src1Stride;
432         src2 += 16;
433     } while (--h);
434 }
435
436 static void DEF(avg, pixels8_y2)(uint8_t *block, const uint8_t *pixels, int line_size, int h)
437 {
438     MOVQ_BFE(mm6);
439     __asm __volatile(
440         "lea    (%3, %3), %%eax         \n\t"
441         "movq   (%1), %%mm0             \n\t"
442         ".balign 8                      \n\t"
443         "1:                             \n\t"
444         "movq   (%1, %3), %%mm1         \n\t"
445         "movq   (%1, %%eax), %%mm2      \n\t"
446         PAVGBP(%%mm1, %%mm0, %%mm4,   %%mm2, %%mm1, %%mm5)
447         "movq   (%2), %%mm3             \n\t"
448         PAVGB(%%mm3, %%mm4, %%mm0, %%mm6)
449         "movq   (%2, %3), %%mm3         \n\t"
450         PAVGB(%%mm3, %%mm5, %%mm1, %%mm6)
451         "movq   %%mm0, (%2)             \n\t"
452         "movq   %%mm1, (%2, %3)         \n\t"
453         "addl   %%eax, %1               \n\t"
454         "addl   %%eax, %2               \n\t"
455
456         "movq   (%1, %3), %%mm1         \n\t"
457         "movq   (%1, %%eax), %%mm0      \n\t"
458         PAVGBP(%%mm1, %%mm2, %%mm4,   %%mm0, %%mm1, %%mm5)
459         "movq   (%2), %%mm3             \n\t"
460         PAVGB(%%mm3, %%mm4, %%mm2, %%mm6)
461         "movq   (%2, %3), %%mm3         \n\t"
462         PAVGB(%%mm3, %%mm5, %%mm1, %%mm6)
463         "movq   %%mm2, (%2)             \n\t"
464         "movq   %%mm1, (%2, %3)         \n\t"
465         "addl   %%eax, %1               \n\t"
466         "addl   %%eax, %2               \n\t"
467
468         "subl   $4, %0                  \n\t"
469         "jnz    1b                      \n\t"
470         :"+g"(h), "+S"(pixels), "+D"(block)
471         :"r"(line_size)
472         :"eax", "memory");
473 }
474
475 // this routine is 'slightly' suboptimal but mostly unused
476 static void DEF(avg, pixels8_xy2)(uint8_t *block, const uint8_t *pixels, int line_size, int h)
477 {
478     MOVQ_ZERO(mm7);
479     SET_RND(mm6); // =2 for rnd  and  =1 for no_rnd version
480     __asm __volatile(
481         "movq   (%1), %%mm0             \n\t"
482         "movq   1(%1), %%mm4            \n\t"
483         "movq   %%mm0, %%mm1            \n\t"
484         "movq   %%mm4, %%mm5            \n\t"
485         "punpcklbw %%mm7, %%mm0         \n\t"
486         "punpcklbw %%mm7, %%mm4         \n\t"
487         "punpckhbw %%mm7, %%mm1         \n\t"
488         "punpckhbw %%mm7, %%mm5         \n\t"
489         "paddusw %%mm0, %%mm4           \n\t"
490         "paddusw %%mm1, %%mm5           \n\t"
491         "xorl   %%eax, %%eax            \n\t"
492         "addl   %3, %1                  \n\t"
493         ".balign 8                      \n\t"
494         "1:                             \n\t"
495         "movq   (%1, %%eax), %%mm0      \n\t"
496         "movq   1(%1, %%eax), %%mm2     \n\t"
497         "movq   %%mm0, %%mm1            \n\t"
498         "movq   %%mm2, %%mm3            \n\t"
499         "punpcklbw %%mm7, %%mm0         \n\t"
500         "punpcklbw %%mm7, %%mm2         \n\t"
501         "punpckhbw %%mm7, %%mm1         \n\t"
502         "punpckhbw %%mm7, %%mm3         \n\t"
503         "paddusw %%mm2, %%mm0           \n\t"
504         "paddusw %%mm3, %%mm1           \n\t"
505         "paddusw %%mm6, %%mm4           \n\t"
506         "paddusw %%mm6, %%mm5           \n\t"
507         "paddusw %%mm0, %%mm4           \n\t"
508         "paddusw %%mm1, %%mm5           \n\t"
509         "psrlw  $2, %%mm4               \n\t"
510         "psrlw  $2, %%mm5               \n\t"
511                 "movq   (%2, %%eax), %%mm3      \n\t"
512         "packuswb  %%mm5, %%mm4         \n\t"
513                 "pcmpeqd %%mm2, %%mm2   \n\t"
514                 "paddb %%mm2, %%mm2     \n\t"
515                 PAVGB(%%mm3, %%mm4, %%mm5, %%mm2)
516                 "movq   %%mm5, (%2, %%eax)      \n\t"
517         "addl   %3, %%eax               \n\t"
518
519         "movq   (%1, %%eax), %%mm2      \n\t" // 0 <-> 2   1 <-> 3
520         "movq   1(%1, %%eax), %%mm4     \n\t"
521         "movq   %%mm2, %%mm3            \n\t"
522         "movq   %%mm4, %%mm5            \n\t"
523         "punpcklbw %%mm7, %%mm2         \n\t"
524         "punpcklbw %%mm7, %%mm4         \n\t"
525         "punpckhbw %%mm7, %%mm3         \n\t"
526         "punpckhbw %%mm7, %%mm5         \n\t"
527         "paddusw %%mm2, %%mm4           \n\t"
528         "paddusw %%mm3, %%mm5           \n\t"
529         "paddusw %%mm6, %%mm0           \n\t"
530         "paddusw %%mm6, %%mm1           \n\t"
531         "paddusw %%mm4, %%mm0           \n\t"
532         "paddusw %%mm5, %%mm1           \n\t"
533         "psrlw  $2, %%mm0               \n\t"
534         "psrlw  $2, %%mm1               \n\t"
535                 "movq   (%2, %%eax), %%mm3      \n\t"
536         "packuswb  %%mm1, %%mm0         \n\t"
537                 "pcmpeqd %%mm2, %%mm2   \n\t"
538                 "paddb %%mm2, %%mm2     \n\t"
539                 PAVGB(%%mm3, %%mm0, %%mm1, %%mm2)
540                 "movq   %%mm1, (%2, %%eax)      \n\t"
541         "addl   %3, %%eax               \n\t"
542
543         "subl   $2, %0                  \n\t"
544         "jnz    1b                      \n\t"
545         :"+g"(h), "+S"(pixels)
546         :"D"(block), "r"(line_size)
547         :"eax", "memory");
548 }
549
550 //FIXME optimize
551 static void DEF(put, pixels16_y2)(uint8_t *block, const uint8_t *pixels, int line_size, int h){
552     DEF(put, pixels8_y2)(block  , pixels  , line_size, h);
553     DEF(put, pixels8_y2)(block+8, pixels+8, line_size, h);
554 }
555
556 static void DEF(put, pixels16_xy2)(uint8_t *block, const uint8_t *pixels, int line_size, int h){
557     DEF(put, pixels8_xy2)(block  , pixels  , line_size, h);
558     DEF(put, pixels8_xy2)(block+8, pixels+8, line_size, h);
559 }
560
561 static void DEF(avg, pixels16_y2)(uint8_t *block, const uint8_t *pixels, int line_size, int h){
562     DEF(avg, pixels8_y2)(block  , pixels  , line_size, h);
563     DEF(avg, pixels8_y2)(block+8, pixels+8, line_size, h);
564 }
565
566 static void DEF(avg, pixels16_xy2)(uint8_t *block, const uint8_t *pixels, int line_size, int h){
567     DEF(avg, pixels8_xy2)(block  , pixels  , line_size, h);
568     DEF(avg, pixels8_xy2)(block+8, pixels+8, line_size, h);
569 }
570
571