]> git.sesse.net Git - ffmpeg/blob - libpostproc/postprocess_template.c
Merge remote-tracking branch 'qatar/master'
[ffmpeg] / libpostproc / postprocess_template.c
1 /*
2  * Copyright (C) 2001-2002 Michael Niedermayer (michaelni@gmx.at)
3  *
4  * This file is part of FFmpeg.
5  *
6  * FFmpeg is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * FFmpeg 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
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with FFmpeg; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19  */
20
21 /**
22  * @file
23  * mmx/mmx2/3dnow postprocess code.
24  */
25
26 #include "libavutil/x86/asm.h"
27
28 /* A single TEMPLATE_PP_* should be defined (to 1) when this template is
29  * included. The following macros will define its dependencies to 1 as well
30  * (like MMX2 depending on MMX), and will define to 0 all the others. Every
31  * TEMPLATE_PP_* need to be undef at the end. */
32
33 #ifdef TEMPLATE_PP_C
34 #   define RENAME(a) a ## _C
35 #else
36 #   define TEMPLATE_PP_C 0
37 #endif
38
39 #ifdef TEMPLATE_PP_ALTIVEC
40 #   define RENAME(a) a ## _altivec
41 #else
42 #   define TEMPLATE_PP_ALTIVEC 0
43 #endif
44
45 #ifdef TEMPLATE_PP_MMX
46 #   define RENAME(a) a ## _MMX
47 #else
48 #   define TEMPLATE_PP_MMX 0
49 #endif
50
51 #ifdef TEMPLATE_PP_MMXEXT
52 #   undef  TEMPLATE_PP_MMX
53 #   define TEMPLATE_PP_MMX 1
54 #   define RENAME(a) a ## _MMX2
55 #else
56 #   define TEMPLATE_PP_MMXEXT 0
57 #endif
58
59 #ifdef TEMPLATE_PP_3DNOW
60 #   undef  TEMPLATE_PP_MMX
61 #   define TEMPLATE_PP_MMX 1
62 #   define RENAME(a) a ## _3DNow
63 #else
64 #   define TEMPLATE_PP_3DNOW 0
65 #endif
66
67 #ifdef TEMPLATE_PP_SSE2
68 #   undef  TEMPLATE_PP_MMX
69 #   define TEMPLATE_PP_MMX 1
70 #   undef  TEMPLATE_PP_MMXEXT
71 #   define TEMPLATE_PP_MMXEXT 1
72 #   define RENAME(a) a ## _SSE2
73 #else
74 #   define TEMPLATE_PP_SSE2 0
75 #endif
76
77 #undef REAL_PAVGB
78 #undef PAVGB
79 #undef PMINUB
80 #undef PMAXUB
81
82 #if   TEMPLATE_PP_MMXEXT
83 #define REAL_PAVGB(a,b) "pavgb " #a ", " #b " \n\t"
84 #elif TEMPLATE_PP_3DNOW
85 #define REAL_PAVGB(a,b) "pavgusb " #a ", " #b " \n\t"
86 #endif
87 #define PAVGB(a,b)  REAL_PAVGB(a,b)
88
89 #if   TEMPLATE_PP_MMXEXT
90 #define PMINUB(a,b,t) "pminub " #a ", " #b " \n\t"
91 #elif TEMPLATE_PP_MMX
92 #define PMINUB(b,a,t) \
93     "movq " #a ", " #t " \n\t"\
94     "psubusb " #b ", " #t " \n\t"\
95     "psubb " #t ", " #a " \n\t"
96 #endif
97
98 #if   TEMPLATE_PP_MMXEXT
99 #define PMAXUB(a,b) "pmaxub " #a ", " #b " \n\t"
100 #elif TEMPLATE_PP_MMX
101 #define PMAXUB(a,b) \
102     "psubusb " #a ", " #b " \n\t"\
103     "paddb " #a ", " #b " \n\t"
104 #endif
105
106 //FIXME? |255-0| = 1 (should not be a problem ...)
107 #if TEMPLATE_PP_MMX
108 /**
109  * Check if the middle 8x8 Block in the given 8x16 block is flat
110  */
111 static inline int RENAME(vertClassify)(uint8_t src[], int stride, PPContext *c){
112     int numEq= 0, dcOk;
113     src+= stride*4; // src points to begin of the 8x8 Block
114     __asm__ volatile(
115         "movq %0, %%mm7                         \n\t"
116         "movq %1, %%mm6                         \n\t"
117         : : "m" (c->mmxDcOffset[c->nonBQP]),  "m" (c->mmxDcThreshold[c->nonBQP])
118         );
119
120     __asm__ volatile(
121         "lea (%2, %3), %%"REG_a"                \n\t"
122 //      0       1       2       3       4       5       6       7       8       9
123 //      %1      eax     eax+%2  eax+2%2 %1+4%2  ecx     ecx+%2  ecx+2%2 %1+8%2  ecx+4%2
124
125         "movq (%2), %%mm0                       \n\t"
126         "movq (%%"REG_a"), %%mm1                \n\t"
127         "movq %%mm0, %%mm3                      \n\t"
128         "movq %%mm0, %%mm4                      \n\t"
129         PMAXUB(%%mm1, %%mm4)
130         PMINUB(%%mm1, %%mm3, %%mm5)
131         "psubb %%mm1, %%mm0                     \n\t" // mm0 = differnece
132         "paddb %%mm7, %%mm0                     \n\t"
133         "pcmpgtb %%mm6, %%mm0                   \n\t"
134
135         "movq (%%"REG_a",%3), %%mm2             \n\t"
136         PMAXUB(%%mm2, %%mm4)
137         PMINUB(%%mm2, %%mm3, %%mm5)
138         "psubb %%mm2, %%mm1                     \n\t"
139         "paddb %%mm7, %%mm1                     \n\t"
140         "pcmpgtb %%mm6, %%mm1                   \n\t"
141         "paddb %%mm1, %%mm0                     \n\t"
142
143         "movq (%%"REG_a", %3, 2), %%mm1         \n\t"
144         PMAXUB(%%mm1, %%mm4)
145         PMINUB(%%mm1, %%mm3, %%mm5)
146         "psubb %%mm1, %%mm2                     \n\t"
147         "paddb %%mm7, %%mm2                     \n\t"
148         "pcmpgtb %%mm6, %%mm2                   \n\t"
149         "paddb %%mm2, %%mm0                     \n\t"
150
151         "lea (%%"REG_a", %3, 4), %%"REG_a"      \n\t"
152
153         "movq (%2, %3, 4), %%mm2                \n\t"
154         PMAXUB(%%mm2, %%mm4)
155         PMINUB(%%mm2, %%mm3, %%mm5)
156         "psubb %%mm2, %%mm1                     \n\t"
157         "paddb %%mm7, %%mm1                     \n\t"
158         "pcmpgtb %%mm6, %%mm1                   \n\t"
159         "paddb %%mm1, %%mm0                     \n\t"
160
161         "movq (%%"REG_a"), %%mm1                \n\t"
162         PMAXUB(%%mm1, %%mm4)
163         PMINUB(%%mm1, %%mm3, %%mm5)
164         "psubb %%mm1, %%mm2                     \n\t"
165         "paddb %%mm7, %%mm2                     \n\t"
166         "pcmpgtb %%mm6, %%mm2                   \n\t"
167         "paddb %%mm2, %%mm0                     \n\t"
168
169         "movq (%%"REG_a", %3), %%mm2            \n\t"
170         PMAXUB(%%mm2, %%mm4)
171         PMINUB(%%mm2, %%mm3, %%mm5)
172         "psubb %%mm2, %%mm1                     \n\t"
173         "paddb %%mm7, %%mm1                     \n\t"
174         "pcmpgtb %%mm6, %%mm1                   \n\t"
175         "paddb %%mm1, %%mm0                     \n\t"
176
177         "movq (%%"REG_a", %3, 2), %%mm1         \n\t"
178         PMAXUB(%%mm1, %%mm4)
179         PMINUB(%%mm1, %%mm3, %%mm5)
180         "psubb %%mm1, %%mm2                     \n\t"
181         "paddb %%mm7, %%mm2                     \n\t"
182         "pcmpgtb %%mm6, %%mm2                   \n\t"
183         "paddb %%mm2, %%mm0                     \n\t"
184         "psubusb %%mm3, %%mm4                   \n\t"
185
186         "                                       \n\t"
187 #if TEMPLATE_PP_MMXEXT
188         "pxor %%mm7, %%mm7                      \n\t"
189         "psadbw %%mm7, %%mm0                    \n\t"
190 #else
191         "movq %%mm0, %%mm1                      \n\t"
192         "psrlw $8, %%mm0                        \n\t"
193         "paddb %%mm1, %%mm0                     \n\t"
194         "movq %%mm0, %%mm1                      \n\t"
195         "psrlq $16, %%mm0                       \n\t"
196         "paddb %%mm1, %%mm0                     \n\t"
197         "movq %%mm0, %%mm1                      \n\t"
198         "psrlq $32, %%mm0                       \n\t"
199         "paddb %%mm1, %%mm0                     \n\t"
200 #endif
201         "movq %4, %%mm7                         \n\t" // QP,..., QP
202         "paddusb %%mm7, %%mm7                   \n\t" // 2QP ... 2QP
203         "psubusb %%mm7, %%mm4                   \n\t" // Diff <= 2QP -> 0
204         "packssdw %%mm4, %%mm4                  \n\t"
205         "movd %%mm0, %0                         \n\t"
206         "movd %%mm4, %1                         \n\t"
207
208         : "=r" (numEq), "=r" (dcOk)
209         : "r" (src), "r" ((x86_reg)stride), "m" (c->pQPb)
210         : "%"REG_a
211         );
212
213     numEq= (-numEq) &0xFF;
214     if(numEq > c->ppMode.flatnessThreshold){
215         if(dcOk) return 0;
216         else     return 1;
217     }else{
218         return 2;
219     }
220 }
221 #endif //TEMPLATE_PP_MMX
222
223 /**
224  * Do a vertical low pass filter on the 8x16 block (only write to the 8x8 block in the middle)
225  * using the 9-Tap Filter (1,1,2,2,4,2,2,1,1)/16
226  */
227 #if !TEMPLATE_PP_ALTIVEC
228 static inline void RENAME(doVertLowPass)(uint8_t *src, int stride, PPContext *c)
229 {
230 #if TEMPLATE_PP_MMXEXT || TEMPLATE_PP_3DNOW
231     src+= stride*3;
232     __asm__ volatile(        //"movv %0 %1 %2\n\t"
233         "movq %2, %%mm0                         \n\t"  // QP,..., QP
234         "pxor %%mm4, %%mm4                      \n\t"
235
236         "movq (%0), %%mm6                       \n\t"
237         "movq (%0, %1), %%mm5                   \n\t"
238         "movq %%mm5, %%mm1                      \n\t"
239         "movq %%mm6, %%mm2                      \n\t"
240         "psubusb %%mm6, %%mm5                   \n\t"
241         "psubusb %%mm1, %%mm2                   \n\t"
242         "por %%mm5, %%mm2                       \n\t" // ABS Diff of lines
243         "psubusb %%mm0, %%mm2                   \n\t" // diff <= QP -> 0
244         "pcmpeqb %%mm4, %%mm2                   \n\t" // diff <= QP -> FF
245
246         "pand %%mm2, %%mm6                      \n\t"
247         "pandn %%mm1, %%mm2                     \n\t"
248         "por %%mm2, %%mm6                       \n\t"// First Line to Filter
249
250         "movq (%0, %1, 8), %%mm5                \n\t"
251         "lea (%0, %1, 4), %%"REG_a"             \n\t"
252         "lea (%0, %1, 8), %%"REG_c"             \n\t"
253         "sub %1, %%"REG_c"                      \n\t"
254         "add %1, %0                             \n\t" // %0 points to line 1 not 0
255         "movq (%0, %1, 8), %%mm7                \n\t"
256         "movq %%mm5, %%mm1                      \n\t"
257         "movq %%mm7, %%mm2                      \n\t"
258         "psubusb %%mm7, %%mm5                   \n\t"
259         "psubusb %%mm1, %%mm2                   \n\t"
260         "por %%mm5, %%mm2                       \n\t" // ABS Diff of lines
261         "psubusb %%mm0, %%mm2                   \n\t" // diff <= QP -> 0
262         "pcmpeqb %%mm4, %%mm2                   \n\t" // diff <= QP -> FF
263
264         "pand %%mm2, %%mm7                      \n\t"
265         "pandn %%mm1, %%mm2                     \n\t"
266         "por %%mm2, %%mm7                       \n\t" // First Line to Filter
267
268
269         //      1       2       3       4       5       6       7       8
270         //      %0      %0+%1   %0+2%1  eax     %0+4%1  eax+2%1 ecx     eax+4%1
271         // 6 4 2 2 1 1
272         // 6 4 4 2
273         // 6 8 2
274
275         "movq (%0, %1), %%mm0                   \n\t" //  1
276         "movq %%mm0, %%mm1                      \n\t" //  1
277         PAVGB(%%mm6, %%mm0)                           //1 1        /2
278         PAVGB(%%mm6, %%mm0)                           //3 1        /4
279
280         "movq (%0, %1, 4), %%mm2                \n\t" //     1
281         "movq %%mm2, %%mm5                      \n\t" //     1
282         PAVGB((%%REGa), %%mm2)                        //    11        /2
283         PAVGB((%0, %1, 2), %%mm2)                     //   211        /4
284         "movq %%mm2, %%mm3                      \n\t" //   211        /4
285         "movq (%0), %%mm4                       \n\t" // 1
286         PAVGB(%%mm4, %%mm3)                           // 4 211        /8
287         PAVGB(%%mm0, %%mm3)                           //642211        /16
288         "movq %%mm3, (%0)                       \n\t" // X
289         // mm1=2 mm2=3(211) mm4=1 mm5=5 mm6=0 mm7=9
290         "movq %%mm1, %%mm0                      \n\t" //  1
291         PAVGB(%%mm6, %%mm0)                           //1 1        /2
292         "movq %%mm4, %%mm3                      \n\t" // 1
293         PAVGB((%0,%1,2), %%mm3)                       // 1 1        /2
294         PAVGB((%%REGa,%1,2), %%mm5)                   //     11        /2
295         PAVGB((%%REGa), %%mm5)                        //    211 /4
296         PAVGB(%%mm5, %%mm3)                           // 2 2211 /8
297         PAVGB(%%mm0, %%mm3)                           //4242211 /16
298         "movq %%mm3, (%0,%1)                    \n\t" //  X
299         // mm1=2 mm2=3(211) mm4=1 mm5=4(211) mm6=0 mm7=9
300         PAVGB(%%mm4, %%mm6)                                   //11        /2
301         "movq (%%"REG_c"), %%mm0                \n\t" //       1
302         PAVGB((%%REGa, %1, 2), %%mm0)                 //      11/2
303         "movq %%mm0, %%mm3                      \n\t" //      11/2
304         PAVGB(%%mm1, %%mm0)                           //  2   11/4
305         PAVGB(%%mm6, %%mm0)                           //222   11/8
306         PAVGB(%%mm2, %%mm0)                           //22242211/16
307         "movq (%0, %1, 2), %%mm2                \n\t" //   1
308         "movq %%mm0, (%0, %1, 2)                \n\t" //   X
309         // mm1=2 mm2=3 mm3=6(11) mm4=1 mm5=4(211) mm6=0(11) mm7=9
310         "movq (%%"REG_a", %1, 4), %%mm0         \n\t" //        1
311         PAVGB((%%REGc), %%mm0)                        //       11        /2
312         PAVGB(%%mm0, %%mm6)                           //11     11        /4
313         PAVGB(%%mm1, %%mm4)                           // 11                /2
314         PAVGB(%%mm2, %%mm1)                           //  11                /2
315         PAVGB(%%mm1, %%mm6)                           //1122   11        /8
316         PAVGB(%%mm5, %%mm6)                           //112242211        /16
317         "movq (%%"REG_a"), %%mm5                \n\t" //    1
318         "movq %%mm6, (%%"REG_a")                \n\t" //    X
319         // mm0=7(11) mm1=2(11) mm2=3 mm3=6(11) mm4=1(11) mm5=4 mm7=9
320         "movq (%%"REG_a", %1, 4), %%mm6         \n\t" //        1
321         PAVGB(%%mm7, %%mm6)                           //        11        /2
322         PAVGB(%%mm4, %%mm6)                           // 11     11        /4
323         PAVGB(%%mm3, %%mm6)                           // 11   2211        /8
324         PAVGB(%%mm5, %%mm2)                           //   11                /2
325         "movq (%0, %1, 4), %%mm4                \n\t" //     1
326         PAVGB(%%mm4, %%mm2)                           //   112                /4
327         PAVGB(%%mm2, %%mm6)                           // 112242211        /16
328         "movq %%mm6, (%0, %1, 4)                \n\t" //     X
329         // mm0=7(11) mm1=2(11) mm2=3(112) mm3=6(11) mm4=5 mm5=4 mm7=9
330         PAVGB(%%mm7, %%mm1)                           //  11     2        /4
331         PAVGB(%%mm4, %%mm5)                           //    11                /2
332         PAVGB(%%mm5, %%mm0)                           //    11 11        /4
333         "movq (%%"REG_a", %1, 2), %%mm6         \n\t" //      1
334         PAVGB(%%mm6, %%mm1)                           //  11  4  2        /8
335         PAVGB(%%mm0, %%mm1)                           //  11224222        /16
336         "movq %%mm1, (%%"REG_a", %1, 2)         \n\t" //      X
337         // mm2=3(112) mm3=6(11) mm4=5 mm5=4(11) mm6=6 mm7=9
338         PAVGB((%%REGc), %%mm2)                        //   112 4        /8
339         "movq (%%"REG_a", %1, 4), %%mm0         \n\t" //        1
340         PAVGB(%%mm0, %%mm6)                           //      1 1        /2
341         PAVGB(%%mm7, %%mm6)                           //      1 12        /4
342         PAVGB(%%mm2, %%mm6)                           //   1122424        /4
343         "movq %%mm6, (%%"REG_c")                \n\t" //       X
344         // mm0=8 mm3=6(11) mm4=5 mm5=4(11) mm7=9
345         PAVGB(%%mm7, %%mm5)                           //    11   2        /4
346         PAVGB(%%mm7, %%mm5)                           //    11   6        /8
347
348         PAVGB(%%mm3, %%mm0)                           //      112        /4
349         PAVGB(%%mm0, %%mm5)                           //    112246        /16
350         "movq %%mm5, (%%"REG_a", %1, 4)         \n\t" //        X
351         "sub %1, %0                             \n\t"
352
353         :
354         : "r" (src), "r" ((x86_reg)stride), "m" (c->pQPb)
355         : "%"REG_a, "%"REG_c
356     );
357 #else //TEMPLATE_PP_MMXEXT || TEMPLATE_PP_3DNOW
358     const int l1= stride;
359     const int l2= stride + l1;
360     const int l3= stride + l2;
361     const int l4= stride + l3;
362     const int l5= stride + l4;
363     const int l6= stride + l5;
364     const int l7= stride + l6;
365     const int l8= stride + l7;
366     const int l9= stride + l8;
367     int x;
368     src+= stride*3;
369     for(x=0; x<BLOCK_SIZE; x++){
370         const int first= FFABS(src[0] - src[l1]) < c->QP ? src[0] : src[l1];
371         const int last= FFABS(src[l8] - src[l9]) < c->QP ? src[l9] : src[l8];
372
373         int sums[10];
374         sums[0] = 4*first + src[l1] + src[l2] + src[l3] + 4;
375         sums[1] = sums[0] - first  + src[l4];
376         sums[2] = sums[1] - first  + src[l5];
377         sums[3] = sums[2] - first  + src[l6];
378         sums[4] = sums[3] - first  + src[l7];
379         sums[5] = sums[4] - src[l1] + src[l8];
380         sums[6] = sums[5] - src[l2] + last;
381         sums[7] = sums[6] - src[l3] + last;
382         sums[8] = sums[7] - src[l4] + last;
383         sums[9] = sums[8] - src[l5] + last;
384
385         src[l1]= (sums[0] + sums[2] + 2*src[l1])>>4;
386         src[l2]= (sums[1] + sums[3] + 2*src[l2])>>4;
387         src[l3]= (sums[2] + sums[4] + 2*src[l3])>>4;
388         src[l4]= (sums[3] + sums[5] + 2*src[l4])>>4;
389         src[l5]= (sums[4] + sums[6] + 2*src[l5])>>4;
390         src[l6]= (sums[5] + sums[7] + 2*src[l6])>>4;
391         src[l7]= (sums[6] + sums[8] + 2*src[l7])>>4;
392         src[l8]= (sums[7] + sums[9] + 2*src[l8])>>4;
393
394         src++;
395     }
396 #endif //TEMPLATE_PP_MMXEXT || TEMPLATE_PP_3DNOW
397 }
398 #endif //TEMPLATE_PP_ALTIVEC
399
400 /**
401  * Experimental Filter 1
402  * will not damage linear gradients
403  * Flat blocks should look like they were passed through the (1,1,2,2,4,2,2,1,1) 9-Tap filter
404  * can only smooth blocks at the expected locations (it cannot smooth them if they did move)
405  * MMX2 version does correct clipping C version does not
406  */
407 static inline void RENAME(vertX1Filter)(uint8_t *src, int stride, PPContext *co)
408 {
409 #if TEMPLATE_PP_MMXEXT || TEMPLATE_PP_3DNOW
410     src+= stride*3;
411
412     __asm__ volatile(
413         "pxor %%mm7, %%mm7                      \n\t" // 0
414         "lea (%0, %1), %%"REG_a"                \n\t"
415         "lea (%%"REG_a", %1, 4), %%"REG_c"      \n\t"
416 //      0       1       2       3       4       5       6       7       8       9
417 //      %0      eax     eax+%1  eax+2%1 %0+4%1  ecx     ecx+%1  ecx+2%1 %0+8%1  ecx+4%1
418         "movq (%%"REG_a", %1, 2), %%mm0         \n\t" // line 3
419         "movq (%0, %1, 4), %%mm1                \n\t" // line 4
420         "movq %%mm1, %%mm2                      \n\t" // line 4
421         "psubusb %%mm0, %%mm1                   \n\t"
422         "psubusb %%mm2, %%mm0                   \n\t"
423         "por %%mm1, %%mm0                       \n\t" // |l2 - l3|
424         "movq (%%"REG_c"), %%mm3                \n\t" // line 5
425         "movq (%%"REG_c", %1), %%mm4            \n\t" // line 6
426         "movq %%mm3, %%mm5                      \n\t" // line 5
427         "psubusb %%mm4, %%mm3                   \n\t"
428         "psubusb %%mm5, %%mm4                   \n\t"
429         "por %%mm4, %%mm3                       \n\t" // |l5 - l6|
430         PAVGB(%%mm3, %%mm0)                           // (|l2 - l3| + |l5 - l6|)/2
431         "movq %%mm2, %%mm1                      \n\t" // line 4
432         "psubusb %%mm5, %%mm2                   \n\t"
433         "movq %%mm2, %%mm4                      \n\t"
434         "pcmpeqb %%mm7, %%mm2                   \n\t" // (l4 - l5) <= 0 ? -1 : 0
435         "psubusb %%mm1, %%mm5                   \n\t"
436         "por %%mm5, %%mm4                       \n\t" // |l4 - l5|
437         "psubusb %%mm0, %%mm4                   \n\t" //d = MAX(0, |l4-l5| - (|l2-l3| + |l5-l6|)/2)
438         "movq %%mm4, %%mm3                      \n\t" // d
439         "movq %2, %%mm0                         \n\t"
440         "paddusb %%mm0, %%mm0                   \n\t"
441         "psubusb %%mm0, %%mm4                   \n\t"
442         "pcmpeqb %%mm7, %%mm4                   \n\t" // d <= QP ? -1 : 0
443         "psubusb "MANGLE(b01)", %%mm3           \n\t"
444         "pand %%mm4, %%mm3                      \n\t" // d <= QP ? d : 0
445
446         PAVGB(%%mm7, %%mm3)                           // d/2
447         "movq %%mm3, %%mm1                      \n\t" // d/2
448         PAVGB(%%mm7, %%mm3)                           // d/4
449         PAVGB(%%mm1, %%mm3)                           // 3*d/8
450
451         "movq (%0, %1, 4), %%mm0                \n\t" // line 4
452         "pxor %%mm2, %%mm0                      \n\t" //(l4 - l5) <= 0 ? -l4-1 : l4
453         "psubusb %%mm3, %%mm0                   \n\t"
454         "pxor %%mm2, %%mm0                      \n\t"
455         "movq %%mm0, (%0, %1, 4)                \n\t" // line 4
456
457         "movq (%%"REG_c"), %%mm0                \n\t" // line 5
458         "pxor %%mm2, %%mm0                      \n\t" //(l4 - l5) <= 0 ? -l5-1 : l5
459         "paddusb %%mm3, %%mm0                   \n\t"
460         "pxor %%mm2, %%mm0                      \n\t"
461         "movq %%mm0, (%%"REG_c")                \n\t" // line 5
462
463         PAVGB(%%mm7, %%mm1)                           // d/4
464
465         "movq (%%"REG_a", %1, 2), %%mm0         \n\t" // line 3
466         "pxor %%mm2, %%mm0                      \n\t" //(l4 - l5) <= 0 ? -l4-1 : l4
467         "psubusb %%mm1, %%mm0                   \n\t"
468         "pxor %%mm2, %%mm0                      \n\t"
469         "movq %%mm0, (%%"REG_a", %1, 2)         \n\t" // line 3
470
471         "movq (%%"REG_c", %1), %%mm0            \n\t" // line 6
472         "pxor %%mm2, %%mm0                      \n\t" //(l4 - l5) <= 0 ? -l5-1 : l5
473         "paddusb %%mm1, %%mm0                   \n\t"
474         "pxor %%mm2, %%mm0                      \n\t"
475         "movq %%mm0, (%%"REG_c", %1)            \n\t" // line 6
476
477         PAVGB(%%mm7, %%mm1)                           // d/8
478
479         "movq (%%"REG_a", %1), %%mm0            \n\t" // line 2
480         "pxor %%mm2, %%mm0                      \n\t" //(l4 - l5) <= 0 ? -l2-1 : l2
481         "psubusb %%mm1, %%mm0                   \n\t"
482         "pxor %%mm2, %%mm0                      \n\t"
483         "movq %%mm0, (%%"REG_a", %1)            \n\t" // line 2
484
485         "movq (%%"REG_c", %1, 2), %%mm0         \n\t" // line 7
486         "pxor %%mm2, %%mm0                      \n\t" //(l4 - l5) <= 0 ? -l7-1 : l7
487         "paddusb %%mm1, %%mm0                   \n\t"
488         "pxor %%mm2, %%mm0                      \n\t"
489         "movq %%mm0, (%%"REG_c", %1, 2)         \n\t" // line 7
490
491         :
492         : "r" (src), "r" ((x86_reg)stride), "m" (co->pQPb)
493         : "%"REG_a, "%"REG_c
494     );
495 #else //TEMPLATE_PP_MMXEXT || TEMPLATE_PP_3DNOW
496
497     const int l1= stride;
498     const int l2= stride + l1;
499     const int l3= stride + l2;
500     const int l4= stride + l3;
501     const int l5= stride + l4;
502     const int l6= stride + l5;
503     const int l7= stride + l6;
504 //    const int l8= stride + l7;
505 //    const int l9= stride + l8;
506     int x;
507
508     src+= stride*3;
509     for(x=0; x<BLOCK_SIZE; x++){
510         int a= src[l3] - src[l4];
511         int b= src[l4] - src[l5];
512         int c= src[l5] - src[l6];
513
514         int d= FFABS(b) - ((FFABS(a) + FFABS(c))>>1);
515         d= FFMAX(d, 0);
516
517         if(d < co->QP*2){
518             int v = d * FFSIGN(-b);
519
520             src[l2] +=v>>3;
521             src[l3] +=v>>2;
522             src[l4] +=(3*v)>>3;
523             src[l5] -=(3*v)>>3;
524             src[l6] -=v>>2;
525             src[l7] -=v>>3;
526         }
527         src++;
528     }
529 #endif //TEMPLATE_PP_MMXEXT || TEMPLATE_PP_3DNOW
530 }
531
532 #if !TEMPLATE_PP_ALTIVEC
533 static inline void RENAME(doVertDefFilter)(uint8_t src[], int stride, PPContext *c)
534 {
535 #if TEMPLATE_PP_MMXEXT || TEMPLATE_PP_3DNOW
536 /*
537     uint8_t tmp[16];
538     const int l1= stride;
539     const int l2= stride + l1;
540     const int l3= stride + l2;
541     const int l4= (int)tmp - (int)src - stride*3;
542     const int l5= (int)tmp - (int)src - stride*3 + 8;
543     const int l6= stride*3 + l3;
544     const int l7= stride + l6;
545     const int l8= stride + l7;
546
547     memcpy(tmp, src+stride*7, 8);
548     memcpy(tmp+8, src+stride*8, 8);
549 */
550     src+= stride*4;
551     __asm__ volatile(
552
553 #if 0 //slightly more accurate and slightly slower
554         "pxor %%mm7, %%mm7                      \n\t" // 0
555         "lea (%0, %1), %%"REG_a"                \n\t"
556         "lea (%%"REG_a", %1, 4), %%"REG_c"      \n\t"
557 //      0       1       2       3       4       5       6       7
558 //      %0      %0+%1   %0+2%1  eax+2%1 %0+4%1  eax+4%1 ecx+%1  ecx+2%1
559 //      %0      eax     eax+%1  eax+2%1 %0+4%1  ecx     ecx+%1  ecx+2%1
560
561
562         "movq (%0, %1, 2), %%mm0                \n\t" // l2
563         "movq (%0), %%mm1                       \n\t" // l0
564         "movq %%mm0, %%mm2                      \n\t" // l2
565         PAVGB(%%mm7, %%mm0)                           // ~l2/2
566         PAVGB(%%mm1, %%mm0)                           // ~(l2 + 2l0)/4
567         PAVGB(%%mm2, %%mm0)                           // ~(5l2 + 2l0)/8
568
569         "movq (%%"REG_a"), %%mm1                \n\t" // l1
570         "movq (%%"REG_a", %1, 2), %%mm3         \n\t" // l3
571         "movq %%mm1, %%mm4                      \n\t" // l1
572         PAVGB(%%mm7, %%mm1)                           // ~l1/2
573         PAVGB(%%mm3, %%mm1)                           // ~(l1 + 2l3)/4
574         PAVGB(%%mm4, %%mm1)                           // ~(5l1 + 2l3)/8
575
576         "movq %%mm0, %%mm4                      \n\t" // ~(5l2 + 2l0)/8
577         "psubusb %%mm1, %%mm0                   \n\t"
578         "psubusb %%mm4, %%mm1                   \n\t"
579         "por %%mm0, %%mm1                       \n\t" // ~|2l0 - 5l1 + 5l2 - 2l3|/8
580 // mm1= |lenergy|, mm2= l2, mm3= l3, mm7=0
581
582         "movq (%0, %1, 4), %%mm0                \n\t" // l4
583         "movq %%mm0, %%mm4                      \n\t" // l4
584         PAVGB(%%mm7, %%mm0)                           // ~l4/2
585         PAVGB(%%mm2, %%mm0)                           // ~(l4 + 2l2)/4
586         PAVGB(%%mm4, %%mm0)                           // ~(5l4 + 2l2)/8
587
588         "movq (%%"REG_c"), %%mm2                \n\t" // l5
589         "movq %%mm3, %%mm5                      \n\t" // l3
590         PAVGB(%%mm7, %%mm3)                           // ~l3/2
591         PAVGB(%%mm2, %%mm3)                           // ~(l3 + 2l5)/4
592         PAVGB(%%mm5, %%mm3)                           // ~(5l3 + 2l5)/8
593
594         "movq %%mm0, %%mm6                      \n\t" // ~(5l4 + 2l2)/8
595         "psubusb %%mm3, %%mm0                   \n\t"
596         "psubusb %%mm6, %%mm3                   \n\t"
597         "por %%mm0, %%mm3                       \n\t" // ~|2l2 - 5l3 + 5l4 - 2l5|/8
598         "pcmpeqb %%mm7, %%mm0                   \n\t" // SIGN(2l2 - 5l3 + 5l4 - 2l5)
599 // mm0= SIGN(menergy), mm1= |lenergy|, mm2= l5, mm3= |menergy|, mm4=l4, mm5= l3, mm7=0
600
601         "movq (%%"REG_c", %1), %%mm6            \n\t" // l6
602         "movq %%mm6, %%mm5                      \n\t" // l6
603         PAVGB(%%mm7, %%mm6)                           // ~l6/2
604         PAVGB(%%mm4, %%mm6)                           // ~(l6 + 2l4)/4
605         PAVGB(%%mm5, %%mm6)                           // ~(5l6 + 2l4)/8
606
607         "movq (%%"REG_c", %1, 2), %%mm5         \n\t" // l7
608         "movq %%mm2, %%mm4                      \n\t" // l5
609         PAVGB(%%mm7, %%mm2)                           // ~l5/2
610         PAVGB(%%mm5, %%mm2)                           // ~(l5 + 2l7)/4
611         PAVGB(%%mm4, %%mm2)                           // ~(5l5 + 2l7)/8
612
613         "movq %%mm6, %%mm4                      \n\t" // ~(5l6 + 2l4)/8
614         "psubusb %%mm2, %%mm6                   \n\t"
615         "psubusb %%mm4, %%mm2                   \n\t"
616         "por %%mm6, %%mm2                       \n\t" // ~|2l4 - 5l5 + 5l6 - 2l7|/8
617 // mm0= SIGN(menergy), mm1= |lenergy|/8, mm2= |renergy|/8, mm3= |menergy|/8, mm7=0
618
619
620         PMINUB(%%mm2, %%mm1, %%mm4)                   // MIN(|lenergy|,|renergy|)/8
621         "movq %2, %%mm4                         \n\t" // QP //FIXME QP+1 ?
622         "paddusb "MANGLE(b01)", %%mm4           \n\t"
623         "pcmpgtb %%mm3, %%mm4                   \n\t" // |menergy|/8 < QP
624         "psubusb %%mm1, %%mm3                   \n\t" // d=|menergy|/8-MIN(|lenergy|,|renergy|)/8
625         "pand %%mm4, %%mm3                      \n\t"
626
627         "movq %%mm3, %%mm1                      \n\t"
628 //        "psubusb "MANGLE(b01)", %%mm3           \n\t"
629         PAVGB(%%mm7, %%mm3)
630         PAVGB(%%mm7, %%mm3)
631         "paddusb %%mm1, %%mm3                   \n\t"
632 //        "paddusb "MANGLE(b01)", %%mm3           \n\t"
633
634         "movq (%%"REG_a", %1, 2), %%mm6         \n\t" //l3
635         "movq (%0, %1, 4), %%mm5                \n\t" //l4
636         "movq (%0, %1, 4), %%mm4                \n\t" //l4
637         "psubusb %%mm6, %%mm5                   \n\t"
638         "psubusb %%mm4, %%mm6                   \n\t"
639         "por %%mm6, %%mm5                       \n\t" // |l3-l4|
640         "pcmpeqb %%mm7, %%mm6                   \n\t" // SIGN(l3-l4)
641         "pxor %%mm6, %%mm0                      \n\t"
642         "pand %%mm0, %%mm3                      \n\t"
643         PMINUB(%%mm5, %%mm3, %%mm0)
644
645         "psubusb "MANGLE(b01)", %%mm3           \n\t"
646         PAVGB(%%mm7, %%mm3)
647
648         "movq (%%"REG_a", %1, 2), %%mm0         \n\t"
649         "movq (%0, %1, 4), %%mm2                \n\t"
650         "pxor %%mm6, %%mm0                      \n\t"
651         "pxor %%mm6, %%mm2                      \n\t"
652         "psubb %%mm3, %%mm0                     \n\t"
653         "paddb %%mm3, %%mm2                     \n\t"
654         "pxor %%mm6, %%mm0                      \n\t"
655         "pxor %%mm6, %%mm2                      \n\t"
656         "movq %%mm0, (%%"REG_a", %1, 2)         \n\t"
657         "movq %%mm2, (%0, %1, 4)                \n\t"
658 #endif //0
659
660         "lea (%0, %1), %%"REG_a"                \n\t"
661         "pcmpeqb %%mm6, %%mm6                   \n\t" // -1
662 //      0       1       2       3       4       5       6       7
663 //      %0      %0+%1   %0+2%1  eax+2%1 %0+4%1  eax+4%1 ecx+%1  ecx+2%1
664 //      %0      eax     eax+%1  eax+2%1 %0+4%1  ecx     ecx+%1  ecx+2%1
665
666
667         "movq (%%"REG_a", %1, 2), %%mm1         \n\t" // l3
668         "movq (%0, %1, 4), %%mm0                \n\t" // l4
669         "pxor %%mm6, %%mm1                      \n\t" // -l3-1
670         PAVGB(%%mm1, %%mm0)                           // -q+128 = (l4-l3+256)/2
671 // mm1=-l3-1, mm0=128-q
672
673         "movq (%%"REG_a", %1, 4), %%mm2         \n\t" // l5
674         "movq (%%"REG_a", %1), %%mm3            \n\t" // l2
675         "pxor %%mm6, %%mm2                      \n\t" // -l5-1
676         "movq %%mm2, %%mm5                      \n\t" // -l5-1
677         "movq "MANGLE(b80)", %%mm4              \n\t" // 128
678         "lea (%%"REG_a", %1, 4), %%"REG_c"      \n\t"
679         PAVGB(%%mm3, %%mm2)                           // (l2-l5+256)/2
680         PAVGB(%%mm0, %%mm4)                           // ~(l4-l3)/4 + 128
681         PAVGB(%%mm2, %%mm4)                           // ~(l2-l5)/4 +(l4-l3)/8 + 128
682         PAVGB(%%mm0, %%mm4)                           // ~(l2-l5)/8 +5(l4-l3)/16 + 128
683 // mm1=-l3-1, mm0=128-q, mm3=l2, mm4=menergy/16 + 128, mm5= -l5-1
684
685         "movq (%%"REG_a"), %%mm2                \n\t" // l1
686         "pxor %%mm6, %%mm2                      \n\t" // -l1-1
687         PAVGB(%%mm3, %%mm2)                           // (l2-l1+256)/2
688         PAVGB((%0), %%mm1)                            // (l0-l3+256)/2
689         "movq "MANGLE(b80)", %%mm3              \n\t" // 128
690         PAVGB(%%mm2, %%mm3)                           // ~(l2-l1)/4 + 128
691         PAVGB(%%mm1, %%mm3)                           // ~(l0-l3)/4 +(l2-l1)/8 + 128
692         PAVGB(%%mm2, %%mm3)                           // ~(l0-l3)/8 +5(l2-l1)/16 + 128
693 // mm0=128-q, mm3=lenergy/16 + 128, mm4= menergy/16 + 128, mm5= -l5-1
694
695         PAVGB((%%REGc, %1), %%mm5)                    // (l6-l5+256)/2
696         "movq (%%"REG_c", %1, 2), %%mm1         \n\t" // l7
697         "pxor %%mm6, %%mm1                      \n\t" // -l7-1
698         PAVGB((%0, %1, 4), %%mm1)                     // (l4-l7+256)/2
699         "movq "MANGLE(b80)", %%mm2              \n\t" // 128
700         PAVGB(%%mm5, %%mm2)                           // ~(l6-l5)/4 + 128
701         PAVGB(%%mm1, %%mm2)                           // ~(l4-l7)/4 +(l6-l5)/8 + 128
702         PAVGB(%%mm5, %%mm2)                           // ~(l4-l7)/8 +5(l6-l5)/16 + 128
703 // mm0=128-q, mm2=renergy/16 + 128, mm3=lenergy/16 + 128, mm4= menergy/16 + 128
704
705         "movq "MANGLE(b00)", %%mm1              \n\t" // 0
706         "movq "MANGLE(b00)", %%mm5              \n\t" // 0
707         "psubb %%mm2, %%mm1                     \n\t" // 128 - renergy/16
708         "psubb %%mm3, %%mm5                     \n\t" // 128 - lenergy/16
709         PMAXUB(%%mm1, %%mm2)                          // 128 + |renergy/16|
710         PMAXUB(%%mm5, %%mm3)                          // 128 + |lenergy/16|
711         PMINUB(%%mm2, %%mm3, %%mm1)                   // 128 + MIN(|lenergy|,|renergy|)/16
712
713 // mm0=128-q, mm3=128 + MIN(|lenergy|,|renergy|)/16, mm4= menergy/16 + 128
714
715         "movq "MANGLE(b00)", %%mm7              \n\t" // 0
716         "movq %2, %%mm2                         \n\t" // QP
717         PAVGB(%%mm6, %%mm2)                           // 128 + QP/2
718         "psubb %%mm6, %%mm2                     \n\t"
719
720         "movq %%mm4, %%mm1                      \n\t"
721         "pcmpgtb %%mm7, %%mm1                   \n\t" // SIGN(menergy)
722         "pxor %%mm1, %%mm4                      \n\t"
723         "psubb %%mm1, %%mm4                     \n\t" // 128 + |menergy|/16
724         "pcmpgtb %%mm4, %%mm2                   \n\t" // |menergy|/16 < QP/2
725         "psubusb %%mm3, %%mm4                   \n\t" //d=|menergy|/16 - MIN(|lenergy|,|renergy|)/16
726 // mm0=128-q, mm1= SIGN(menergy), mm2= |menergy|/16 < QP/2, mm4= d/16
727
728         "movq %%mm4, %%mm3                      \n\t" // d
729         "psubusb "MANGLE(b01)", %%mm4           \n\t"
730         PAVGB(%%mm7, %%mm4)                           // d/32
731         PAVGB(%%mm7, %%mm4)                           // (d + 32)/64
732         "paddb %%mm3, %%mm4                     \n\t" // 5d/64
733         "pand %%mm2, %%mm4                      \n\t"
734
735         "movq "MANGLE(b80)", %%mm5              \n\t" // 128
736         "psubb %%mm0, %%mm5                     \n\t" // q
737         "paddsb %%mm6, %%mm5                    \n\t" // fix bad rounding
738         "pcmpgtb %%mm5, %%mm7                   \n\t" // SIGN(q)
739         "pxor %%mm7, %%mm5                      \n\t"
740
741         PMINUB(%%mm5, %%mm4, %%mm3)                   // MIN(|q|, 5d/64)
742         "pxor %%mm1, %%mm7                      \n\t" // SIGN(d*q)
743
744         "pand %%mm7, %%mm4                      \n\t"
745         "movq (%%"REG_a", %1, 2), %%mm0         \n\t"
746         "movq (%0, %1, 4), %%mm2                \n\t"
747         "pxor %%mm1, %%mm0                      \n\t"
748         "pxor %%mm1, %%mm2                      \n\t"
749         "paddb %%mm4, %%mm0                     \n\t"
750         "psubb %%mm4, %%mm2                     \n\t"
751         "pxor %%mm1, %%mm0                      \n\t"
752         "pxor %%mm1, %%mm2                      \n\t"
753         "movq %%mm0, (%%"REG_a", %1, 2)         \n\t"
754         "movq %%mm2, (%0, %1, 4)                \n\t"
755
756         :
757         : "r" (src), "r" ((x86_reg)stride), "m" (c->pQPb)
758         : "%"REG_a, "%"REG_c
759     );
760
761 /*
762     {
763     int x;
764     src-= stride;
765     for(x=0; x<BLOCK_SIZE; x++){
766         const int middleEnergy= 5*(src[l5] - src[l4]) + 2*(src[l3] - src[l6]);
767         if(FFABS(middleEnergy)< 8*QP){
768             const int q=(src[l4] - src[l5])/2;
769             const int leftEnergy=  5*(src[l3] - src[l2]) + 2*(src[l1] - src[l4]);
770             const int rightEnergy= 5*(src[l7] - src[l6]) + 2*(src[l5] - src[l8]);
771
772             int d= FFABS(middleEnergy) - FFMIN( FFABS(leftEnergy), FFABS(rightEnergy) );
773             d= FFMAX(d, 0);
774
775             d= (5*d + 32) >> 6;
776             d*= FFSIGN(-middleEnergy);
777
778             if(q>0){
779                 d= d<0 ? 0 : d;
780                 d= d>q ? q : d;
781             }else{
782                 d= d>0 ? 0 : d;
783                 d= d<q ? q : d;
784             }
785
786             src[l4]-= d;
787             src[l5]+= d;
788         }
789         src++;
790     }
791     src-=8;
792     for(x=0; x<8; x++){
793         int y;
794         for(y=4; y<6; y++){
795             int d= src[x+y*stride] - tmp[x+(y-4)*8];
796             int ad= FFABS(d);
797             static int max=0;
798             static int sum=0;
799             static int num=0;
800             static int bias=0;
801
802             if(max<ad) max=ad;
803             sum+= ad>3 ? 1 : 0;
804             if(ad>3){
805                 src[0] = src[7] = src[stride*7] = src[(stride+1)*7]=255;
806             }
807             if(y==4) bias+=d;
808             num++;
809             if(num%1000000 == 0){
810                 av_log(c, AV_LOG_INFO, " %d %d %d %d\n", num, sum, max, bias);
811             }
812         }
813     }
814 }
815 */
816 #elif TEMPLATE_PP_MMX
817     DECLARE_ALIGNED(8, uint64_t, tmp)[4]; // make space for 4 8-byte vars
818     src+= stride*4;
819     __asm__ volatile(
820         "pxor %%mm7, %%mm7                      \n\t"
821 //      0       1       2       3       4       5       6       7
822 //      %0      %0+%1   %0+2%1  eax+2%1 %0+4%1  eax+4%1 edx+%1  edx+2%1
823 //      %0      eax     eax+%1  eax+2%1 %0+4%1  edx     edx+%1  edx+2%1
824
825         "movq (%0), %%mm0                       \n\t"
826         "movq %%mm0, %%mm1                      \n\t"
827         "punpcklbw %%mm7, %%mm0                 \n\t" // low part of line 0
828         "punpckhbw %%mm7, %%mm1                 \n\t" // high part of line 0
829
830         "movq (%0, %1), %%mm2                   \n\t"
831         "lea (%0, %1, 2), %%"REG_a"             \n\t"
832         "movq %%mm2, %%mm3                      \n\t"
833         "punpcklbw %%mm7, %%mm2                 \n\t" // low part of line 1
834         "punpckhbw %%mm7, %%mm3                 \n\t" // high part of line 1
835
836         "movq (%%"REG_a"), %%mm4                \n\t"
837         "movq %%mm4, %%mm5                      \n\t"
838         "punpcklbw %%mm7, %%mm4                 \n\t" // low part of line 2
839         "punpckhbw %%mm7, %%mm5                 \n\t" // high part of line 2
840
841         "paddw %%mm0, %%mm0                     \n\t" // 2L0
842         "paddw %%mm1, %%mm1                     \n\t" // 2H0
843         "psubw %%mm4, %%mm2                     \n\t" // L1 - L2
844         "psubw %%mm5, %%mm3                     \n\t" // H1 - H2
845         "psubw %%mm2, %%mm0                     \n\t" // 2L0 - L1 + L2
846         "psubw %%mm3, %%mm1                     \n\t" // 2H0 - H1 + H2
847
848         "psllw $2, %%mm2                        \n\t" // 4L1 - 4L2
849         "psllw $2, %%mm3                        \n\t" // 4H1 - 4H2
850         "psubw %%mm2, %%mm0                     \n\t" // 2L0 - 5L1 + 5L2
851         "psubw %%mm3, %%mm1                     \n\t" // 2H0 - 5H1 + 5H2
852
853         "movq (%%"REG_a", %1), %%mm2            \n\t"
854         "movq %%mm2, %%mm3                      \n\t"
855         "punpcklbw %%mm7, %%mm2                 \n\t" // L3
856         "punpckhbw %%mm7, %%mm3                 \n\t" // H3
857
858         "psubw %%mm2, %%mm0                     \n\t" // 2L0 - 5L1 + 5L2 - L3
859         "psubw %%mm3, %%mm1                     \n\t" // 2H0 - 5H1 + 5H2 - H3
860         "psubw %%mm2, %%mm0                     \n\t" // 2L0 - 5L1 + 5L2 - 2L3
861         "psubw %%mm3, %%mm1                     \n\t" // 2H0 - 5H1 + 5H2 - 2H3
862         "movq %%mm0, (%3)                       \n\t" // 2L0 - 5L1 + 5L2 - 2L3
863         "movq %%mm1, 8(%3)                      \n\t" // 2H0 - 5H1 + 5H2 - 2H3
864
865         "movq (%%"REG_a", %1, 2), %%mm0         \n\t"
866         "movq %%mm0, %%mm1                      \n\t"
867         "punpcklbw %%mm7, %%mm0                 \n\t" // L4
868         "punpckhbw %%mm7, %%mm1                 \n\t" // H4
869
870         "psubw %%mm0, %%mm2                     \n\t" // L3 - L4
871         "psubw %%mm1, %%mm3                     \n\t" // H3 - H4
872         "movq %%mm2, 16(%3)                     \n\t" // L3 - L4
873         "movq %%mm3, 24(%3)                     \n\t" // H3 - H4
874         "paddw %%mm4, %%mm4                     \n\t" // 2L2
875         "paddw %%mm5, %%mm5                     \n\t" // 2H2
876         "psubw %%mm2, %%mm4                     \n\t" // 2L2 - L3 + L4
877         "psubw %%mm3, %%mm5                     \n\t" // 2H2 - H3 + H4
878
879         "lea (%%"REG_a", %1), %0                \n\t"
880         "psllw $2, %%mm2                        \n\t" // 4L3 - 4L4
881         "psllw $2, %%mm3                        \n\t" // 4H3 - 4H4
882         "psubw %%mm2, %%mm4                     \n\t" // 2L2 - 5L3 + 5L4
883         "psubw %%mm3, %%mm5                     \n\t" // 2H2 - 5H3 + 5H4
884 //50 opcodes so far
885         "movq (%0, %1, 2), %%mm2                \n\t"
886         "movq %%mm2, %%mm3                      \n\t"
887         "punpcklbw %%mm7, %%mm2                 \n\t" // L5
888         "punpckhbw %%mm7, %%mm3                 \n\t" // H5
889         "psubw %%mm2, %%mm4                     \n\t" // 2L2 - 5L3 + 5L4 - L5
890         "psubw %%mm3, %%mm5                     \n\t" // 2H2 - 5H3 + 5H4 - H5
891         "psubw %%mm2, %%mm4                     \n\t" // 2L2 - 5L3 + 5L4 - 2L5
892         "psubw %%mm3, %%mm5                     \n\t" // 2H2 - 5H3 + 5H4 - 2H5
893
894         "movq (%%"REG_a", %1, 4), %%mm6         \n\t"
895         "punpcklbw %%mm7, %%mm6                 \n\t" // L6
896         "psubw %%mm6, %%mm2                     \n\t" // L5 - L6
897         "movq (%%"REG_a", %1, 4), %%mm6         \n\t"
898         "punpckhbw %%mm7, %%mm6                 \n\t" // H6
899         "psubw %%mm6, %%mm3                     \n\t" // H5 - H6
900
901         "paddw %%mm0, %%mm0                     \n\t" // 2L4
902         "paddw %%mm1, %%mm1                     \n\t" // 2H4
903         "psubw %%mm2, %%mm0                     \n\t" // 2L4 - L5 + L6
904         "psubw %%mm3, %%mm1                     \n\t" // 2H4 - H5 + H6
905
906         "psllw $2, %%mm2                        \n\t" // 4L5 - 4L6
907         "psllw $2, %%mm3                        \n\t" // 4H5 - 4H6
908         "psubw %%mm2, %%mm0                     \n\t" // 2L4 - 5L5 + 5L6
909         "psubw %%mm3, %%mm1                     \n\t" // 2H4 - 5H5 + 5H6
910
911         "movq (%0, %1, 4), %%mm2                \n\t"
912         "movq %%mm2, %%mm3                      \n\t"
913         "punpcklbw %%mm7, %%mm2                 \n\t" // L7
914         "punpckhbw %%mm7, %%mm3                 \n\t" // H7
915
916         "paddw %%mm2, %%mm2                     \n\t" // 2L7
917         "paddw %%mm3, %%mm3                     \n\t" // 2H7
918         "psubw %%mm2, %%mm0                     \n\t" // 2L4 - 5L5 + 5L6 - 2L7
919         "psubw %%mm3, %%mm1                     \n\t" // 2H4 - 5H5 + 5H6 - 2H7
920
921         "movq (%3), %%mm2                       \n\t" // 2L0 - 5L1 + 5L2 - 2L3
922         "movq 8(%3), %%mm3                      \n\t" // 2H0 - 5H1 + 5H2 - 2H3
923
924 #if TEMPLATE_PP_MMXEXT
925         "movq %%mm7, %%mm6                      \n\t" // 0
926         "psubw %%mm0, %%mm6                     \n\t"
927         "pmaxsw %%mm6, %%mm0                    \n\t" // |2L4 - 5L5 + 5L6 - 2L7|
928         "movq %%mm7, %%mm6                      \n\t" // 0
929         "psubw %%mm1, %%mm6                     \n\t"
930         "pmaxsw %%mm6, %%mm1                    \n\t" // |2H4 - 5H5 + 5H6 - 2H7|
931         "movq %%mm7, %%mm6                      \n\t" // 0
932         "psubw %%mm2, %%mm6                     \n\t"
933         "pmaxsw %%mm6, %%mm2                    \n\t" // |2L0 - 5L1 + 5L2 - 2L3|
934         "movq %%mm7, %%mm6                      \n\t" // 0
935         "psubw %%mm3, %%mm6                     \n\t"
936         "pmaxsw %%mm6, %%mm3                    \n\t" // |2H0 - 5H1 + 5H2 - 2H3|
937 #else
938         "movq %%mm7, %%mm6                      \n\t" // 0
939         "pcmpgtw %%mm0, %%mm6                   \n\t"
940         "pxor %%mm6, %%mm0                      \n\t"
941         "psubw %%mm6, %%mm0                     \n\t" // |2L4 - 5L5 + 5L6 - 2L7|
942         "movq %%mm7, %%mm6                      \n\t" // 0
943         "pcmpgtw %%mm1, %%mm6                   \n\t"
944         "pxor %%mm6, %%mm1                      \n\t"
945         "psubw %%mm6, %%mm1                     \n\t" // |2H4 - 5H5 + 5H6 - 2H7|
946         "movq %%mm7, %%mm6                      \n\t" // 0
947         "pcmpgtw %%mm2, %%mm6                   \n\t"
948         "pxor %%mm6, %%mm2                      \n\t"
949         "psubw %%mm6, %%mm2                     \n\t" // |2L0 - 5L1 + 5L2 - 2L3|
950         "movq %%mm7, %%mm6                      \n\t" // 0
951         "pcmpgtw %%mm3, %%mm6                   \n\t"
952         "pxor %%mm6, %%mm3                      \n\t"
953         "psubw %%mm6, %%mm3                     \n\t" // |2H0 - 5H1 + 5H2 - 2H3|
954 #endif
955
956 #if TEMPLATE_PP_MMXEXT
957         "pminsw %%mm2, %%mm0                    \n\t"
958         "pminsw %%mm3, %%mm1                    \n\t"
959 #else
960         "movq %%mm0, %%mm6                      \n\t"
961         "psubusw %%mm2, %%mm6                   \n\t"
962         "psubw %%mm6, %%mm0                     \n\t"
963         "movq %%mm1, %%mm6                      \n\t"
964         "psubusw %%mm3, %%mm6                   \n\t"
965         "psubw %%mm6, %%mm1                     \n\t"
966 #endif
967
968         "movd %2, %%mm2                         \n\t" // QP
969         "punpcklbw %%mm7, %%mm2                 \n\t"
970
971         "movq %%mm7, %%mm6                      \n\t" // 0
972         "pcmpgtw %%mm4, %%mm6                   \n\t" // sign(2L2 - 5L3 + 5L4 - 2L5)
973         "pxor %%mm6, %%mm4                      \n\t"
974         "psubw %%mm6, %%mm4                     \n\t" // |2L2 - 5L3 + 5L4 - 2L5|
975         "pcmpgtw %%mm5, %%mm7                   \n\t" // sign(2H2 - 5H3 + 5H4 - 2H5)
976         "pxor %%mm7, %%mm5                      \n\t"
977         "psubw %%mm7, %%mm5                     \n\t" // |2H2 - 5H3 + 5H4 - 2H5|
978 // 100 opcodes
979         "psllw $3, %%mm2                        \n\t" // 8QP
980         "movq %%mm2, %%mm3                      \n\t" // 8QP
981         "pcmpgtw %%mm4, %%mm2                   \n\t"
982         "pcmpgtw %%mm5, %%mm3                   \n\t"
983         "pand %%mm2, %%mm4                      \n\t"
984         "pand %%mm3, %%mm5                      \n\t"
985
986
987         "psubusw %%mm0, %%mm4                   \n\t" // hd
988         "psubusw %%mm1, %%mm5                   \n\t" // ld
989
990
991         "movq "MANGLE(w05)", %%mm2              \n\t" // 5
992         "pmullw %%mm2, %%mm4                    \n\t"
993         "pmullw %%mm2, %%mm5                    \n\t"
994         "movq "MANGLE(w20)", %%mm2              \n\t" // 32
995         "paddw %%mm2, %%mm4                     \n\t"
996         "paddw %%mm2, %%mm5                     \n\t"
997         "psrlw $6, %%mm4                        \n\t"
998         "psrlw $6, %%mm5                        \n\t"
999
1000         "movq 16(%3), %%mm0                     \n\t" // L3 - L4
1001         "movq 24(%3), %%mm1                     \n\t" // H3 - H4
1002
1003         "pxor %%mm2, %%mm2                      \n\t"
1004         "pxor %%mm3, %%mm3                      \n\t"
1005
1006         "pcmpgtw %%mm0, %%mm2                   \n\t" // sign (L3-L4)
1007         "pcmpgtw %%mm1, %%mm3                   \n\t" // sign (H3-H4)
1008         "pxor %%mm2, %%mm0                      \n\t"
1009         "pxor %%mm3, %%mm1                      \n\t"
1010         "psubw %%mm2, %%mm0                     \n\t" // |L3-L4|
1011         "psubw %%mm3, %%mm1                     \n\t" // |H3-H4|
1012         "psrlw $1, %%mm0                        \n\t" // |L3 - L4|/2
1013         "psrlw $1, %%mm1                        \n\t" // |H3 - H4|/2
1014
1015         "pxor %%mm6, %%mm2                      \n\t"
1016         "pxor %%mm7, %%mm3                      \n\t"
1017         "pand %%mm2, %%mm4                      \n\t"
1018         "pand %%mm3, %%mm5                      \n\t"
1019
1020 #if TEMPLATE_PP_MMXEXT
1021         "pminsw %%mm0, %%mm4                    \n\t"
1022         "pminsw %%mm1, %%mm5                    \n\t"
1023 #else
1024         "movq %%mm4, %%mm2                      \n\t"
1025         "psubusw %%mm0, %%mm2                   \n\t"
1026         "psubw %%mm2, %%mm4                     \n\t"
1027         "movq %%mm5, %%mm2                      \n\t"
1028         "psubusw %%mm1, %%mm2                   \n\t"
1029         "psubw %%mm2, %%mm5                     \n\t"
1030 #endif
1031         "pxor %%mm6, %%mm4                      \n\t"
1032         "pxor %%mm7, %%mm5                      \n\t"
1033         "psubw %%mm6, %%mm4                     \n\t"
1034         "psubw %%mm7, %%mm5                     \n\t"
1035         "packsswb %%mm5, %%mm4                  \n\t"
1036         "movq (%0), %%mm0                       \n\t"
1037         "paddb   %%mm4, %%mm0                   \n\t"
1038         "movq %%mm0, (%0)                       \n\t"
1039         "movq (%0, %1), %%mm0                   \n\t"
1040         "psubb %%mm4, %%mm0                     \n\t"
1041         "movq %%mm0, (%0, %1)                   \n\t"
1042
1043         : "+r" (src)
1044         : "r" ((x86_reg)stride), "m" (c->pQPb), "r"(tmp)
1045         : "%"REG_a
1046     );
1047 #else //TEMPLATE_PP_MMXEXT || TEMPLATE_PP_3DNOW
1048     const int l1= stride;
1049     const int l2= stride + l1;
1050     const int l3= stride + l2;
1051     const int l4= stride + l3;
1052     const int l5= stride + l4;
1053     const int l6= stride + l5;
1054     const int l7= stride + l6;
1055     const int l8= stride + l7;
1056 //    const int l9= stride + l8;
1057     int x;
1058     src+= stride*3;
1059     for(x=0; x<BLOCK_SIZE; x++){
1060         const int middleEnergy= 5*(src[l5] - src[l4]) + 2*(src[l3] - src[l6]);
1061         if(FFABS(middleEnergy) < 8*c->QP){
1062             const int q=(src[l4] - src[l5])/2;
1063             const int leftEnergy=  5*(src[l3] - src[l2]) + 2*(src[l1] - src[l4]);
1064             const int rightEnergy= 5*(src[l7] - src[l6]) + 2*(src[l5] - src[l8]);
1065
1066             int d= FFABS(middleEnergy) - FFMIN( FFABS(leftEnergy), FFABS(rightEnergy) );
1067             d= FFMAX(d, 0);
1068
1069             d= (5*d + 32) >> 6;
1070             d*= FFSIGN(-middleEnergy);
1071
1072             if(q>0){
1073                 d= d<0 ? 0 : d;
1074                 d= d>q ? q : d;
1075             }else{
1076                 d= d>0 ? 0 : d;
1077                 d= d<q ? q : d;
1078             }
1079
1080             src[l4]-= d;
1081             src[l5]+= d;
1082         }
1083         src++;
1084     }
1085 #endif //TEMPLATE_PP_MMXEXT || TEMPLATE_PP_3DNOW
1086 }
1087 #endif //TEMPLATE_PP_ALTIVEC
1088
1089 #if !TEMPLATE_PP_ALTIVEC
1090 static inline void RENAME(dering)(uint8_t src[], int stride, PPContext *c)
1091 {
1092 #if TEMPLATE_PP_MMXEXT || TEMPLATE_PP_3DNOW
1093     DECLARE_ALIGNED(8, uint64_t, tmp)[3];
1094     __asm__ volatile(
1095         "pxor %%mm6, %%mm6                      \n\t"
1096         "pcmpeqb %%mm7, %%mm7                   \n\t"
1097         "movq %2, %%mm0                         \n\t"
1098         "punpcklbw %%mm6, %%mm0                 \n\t"
1099         "psrlw $1, %%mm0                        \n\t"
1100         "psubw %%mm7, %%mm0                     \n\t"
1101         "packuswb %%mm0, %%mm0                  \n\t"
1102         "movq %%mm0, %3                         \n\t"
1103
1104         "lea (%0, %1), %%"REG_a"                \n\t"
1105         "lea (%%"REG_a", %1, 4), %%"REG_d"      \n\t"
1106
1107 //        0        1        2        3        4        5        6        7        8        9
1108 //        %0        eax        eax+%1        eax+2%1        %0+4%1        edx        edx+%1        edx+2%1        %0+8%1        edx+4%1
1109
1110 #undef REAL_FIND_MIN_MAX
1111 #undef FIND_MIN_MAX
1112 #if TEMPLATE_PP_MMXEXT
1113 #define REAL_FIND_MIN_MAX(addr)\
1114         "movq " #addr ", %%mm0                  \n\t"\
1115         "pminub %%mm0, %%mm7                    \n\t"\
1116         "pmaxub %%mm0, %%mm6                    \n\t"
1117 #else
1118 #define REAL_FIND_MIN_MAX(addr)\
1119         "movq " #addr ", %%mm0                  \n\t"\
1120         "movq %%mm7, %%mm1                      \n\t"\
1121         "psubusb %%mm0, %%mm6                   \n\t"\
1122         "paddb %%mm0, %%mm6                     \n\t"\
1123         "psubusb %%mm0, %%mm1                   \n\t"\
1124         "psubb %%mm1, %%mm7                     \n\t"
1125 #endif
1126 #define FIND_MIN_MAX(addr)  REAL_FIND_MIN_MAX(addr)
1127
1128 FIND_MIN_MAX((%%REGa))
1129 FIND_MIN_MAX((%%REGa, %1))
1130 FIND_MIN_MAX((%%REGa, %1, 2))
1131 FIND_MIN_MAX((%0, %1, 4))
1132 FIND_MIN_MAX((%%REGd))
1133 FIND_MIN_MAX((%%REGd, %1))
1134 FIND_MIN_MAX((%%REGd, %1, 2))
1135 FIND_MIN_MAX((%0, %1, 8))
1136
1137         "movq %%mm7, %%mm4                      \n\t"
1138         "psrlq $8, %%mm7                        \n\t"
1139 #if TEMPLATE_PP_MMXEXT
1140         "pminub %%mm4, %%mm7                    \n\t" // min of pixels
1141         "pshufw $0xF9, %%mm7, %%mm4             \n\t"
1142         "pminub %%mm4, %%mm7                    \n\t" // min of pixels
1143         "pshufw $0xFE, %%mm7, %%mm4             \n\t"
1144         "pminub %%mm4, %%mm7                    \n\t"
1145 #else
1146         "movq %%mm7, %%mm1                      \n\t"
1147         "psubusb %%mm4, %%mm1                   \n\t"
1148         "psubb %%mm1, %%mm7                     \n\t"
1149         "movq %%mm7, %%mm4                      \n\t"
1150         "psrlq $16, %%mm7                       \n\t"
1151         "movq %%mm7, %%mm1                      \n\t"
1152         "psubusb %%mm4, %%mm1                   \n\t"
1153         "psubb %%mm1, %%mm7                     \n\t"
1154         "movq %%mm7, %%mm4                      \n\t"
1155         "psrlq $32, %%mm7                       \n\t"
1156         "movq %%mm7, %%mm1                      \n\t"
1157         "psubusb %%mm4, %%mm1                   \n\t"
1158         "psubb %%mm1, %%mm7                     \n\t"
1159 #endif
1160
1161
1162         "movq %%mm6, %%mm4                      \n\t"
1163         "psrlq $8, %%mm6                        \n\t"
1164 #if TEMPLATE_PP_MMXEXT
1165         "pmaxub %%mm4, %%mm6                    \n\t" // max of pixels
1166         "pshufw $0xF9, %%mm6, %%mm4             \n\t"
1167         "pmaxub %%mm4, %%mm6                    \n\t"
1168         "pshufw $0xFE, %%mm6, %%mm4             \n\t"
1169         "pmaxub %%mm4, %%mm6                    \n\t"
1170 #else
1171         "psubusb %%mm4, %%mm6                   \n\t"
1172         "paddb %%mm4, %%mm6                     \n\t"
1173         "movq %%mm6, %%mm4                      \n\t"
1174         "psrlq $16, %%mm6                       \n\t"
1175         "psubusb %%mm4, %%mm6                   \n\t"
1176         "paddb %%mm4, %%mm6                     \n\t"
1177         "movq %%mm6, %%mm4                      \n\t"
1178         "psrlq $32, %%mm6                       \n\t"
1179         "psubusb %%mm4, %%mm6                   \n\t"
1180         "paddb %%mm4, %%mm6                     \n\t"
1181 #endif
1182         "movq %%mm6, %%mm0                      \n\t" // max
1183         "psubb %%mm7, %%mm6                     \n\t" // max - min
1184         "push %4                              \n\t"
1185         "movd %%mm6, %k4                        \n\t"
1186         "cmpb "MANGLE(deringThreshold)", %b4    \n\t"
1187         "pop %4                               \n\t"
1188         " jb 1f                                 \n\t"
1189         PAVGB(%%mm0, %%mm7)                           // a=(max + min)/2
1190         "punpcklbw %%mm7, %%mm7                 \n\t"
1191         "punpcklbw %%mm7, %%mm7                 \n\t"
1192         "punpcklbw %%mm7, %%mm7                 \n\t"
1193         "movq %%mm7, (%4)                       \n\t"
1194
1195         "movq (%0), %%mm0                       \n\t" // L10
1196         "movq %%mm0, %%mm1                      \n\t" // L10
1197         "movq %%mm0, %%mm2                      \n\t" // L10
1198         "psllq $8, %%mm1                        \n\t"
1199         "psrlq $8, %%mm2                        \n\t"
1200         "movd -4(%0), %%mm3                     \n\t"
1201         "movd 8(%0), %%mm4                      \n\t"
1202         "psrlq $24, %%mm3                       \n\t"
1203         "psllq $56, %%mm4                       \n\t"
1204         "por %%mm3, %%mm1                       \n\t" // L00
1205         "por %%mm4, %%mm2                       \n\t" // L20
1206         "movq %%mm1, %%mm3                      \n\t" // L00
1207         PAVGB(%%mm2, %%mm1)                           // (L20 + L00)/2
1208         PAVGB(%%mm0, %%mm1)                           // (L20 + L00 + 2L10)/4
1209         "psubusb %%mm7, %%mm0                   \n\t"
1210         "psubusb %%mm7, %%mm2                   \n\t"
1211         "psubusb %%mm7, %%mm3                   \n\t"
1212         "pcmpeqb "MANGLE(b00)", %%mm0           \n\t" // L10 > a ? 0 : -1
1213         "pcmpeqb "MANGLE(b00)", %%mm2           \n\t" // L20 > a ? 0 : -1
1214         "pcmpeqb "MANGLE(b00)", %%mm3           \n\t" // L00 > a ? 0 : -1
1215         "paddb %%mm2, %%mm0                     \n\t"
1216         "paddb %%mm3, %%mm0                     \n\t"
1217
1218         "movq (%%"REG_a"), %%mm2                \n\t" // L11
1219         "movq %%mm2, %%mm3                      \n\t" // L11
1220         "movq %%mm2, %%mm4                      \n\t" // L11
1221         "psllq $8, %%mm3                        \n\t"
1222         "psrlq $8, %%mm4                        \n\t"
1223         "movd -4(%%"REG_a"), %%mm5              \n\t"
1224         "movd 8(%%"REG_a"), %%mm6               \n\t"
1225         "psrlq $24, %%mm5                       \n\t"
1226         "psllq $56, %%mm6                       \n\t"
1227         "por %%mm5, %%mm3                       \n\t" // L01
1228         "por %%mm6, %%mm4                       \n\t" // L21
1229         "movq %%mm3, %%mm5                      \n\t" // L01
1230         PAVGB(%%mm4, %%mm3)                           // (L21 + L01)/2
1231         PAVGB(%%mm2, %%mm3)                           // (L21 + L01 + 2L11)/4
1232         "psubusb %%mm7, %%mm2                   \n\t"
1233         "psubusb %%mm7, %%mm4                   \n\t"
1234         "psubusb %%mm7, %%mm5                   \n\t"
1235         "pcmpeqb "MANGLE(b00)", %%mm2           \n\t" // L11 > a ? 0 : -1
1236         "pcmpeqb "MANGLE(b00)", %%mm4           \n\t" // L21 > a ? 0 : -1
1237         "pcmpeqb "MANGLE(b00)", %%mm5           \n\t" // L01 > a ? 0 : -1
1238         "paddb %%mm4, %%mm2                     \n\t"
1239         "paddb %%mm5, %%mm2                     \n\t"
1240 // 0, 2, 3, 1
1241 #define REAL_DERING_CORE(dst,src,ppsx,psx,sx,pplx,plx,lx,t0,t1) \
1242         "movq " #src ", " #sx "                 \n\t" /* src[0] */\
1243         "movq " #sx ", " #lx "                  \n\t" /* src[0] */\
1244         "movq " #sx ", " #t0 "                  \n\t" /* src[0] */\
1245         "psllq $8, " #lx "                      \n\t"\
1246         "psrlq $8, " #t0 "                      \n\t"\
1247         "movd -4" #src ", " #t1 "               \n\t"\
1248         "psrlq $24, " #t1 "                     \n\t"\
1249         "por " #t1 ", " #lx "                   \n\t" /* src[-1] */\
1250         "movd 8" #src ", " #t1 "                \n\t"\
1251         "psllq $56, " #t1 "                     \n\t"\
1252         "por " #t1 ", " #t0 "                   \n\t" /* src[+1] */\
1253         "movq " #lx ", " #t1 "                  \n\t" /* src[-1] */\
1254         PAVGB(t0, lx)                                 /* (src[-1] + src[+1])/2 */\
1255         PAVGB(sx, lx)                                 /* (src[-1] + 2src[0] + src[+1])/4 */\
1256         PAVGB(lx, pplx)                                     \
1257         "movq " #lx ", 8(%4)                    \n\t"\
1258         "movq (%4), " #lx "                     \n\t"\
1259         "psubusb " #lx ", " #t1 "               \n\t"\
1260         "psubusb " #lx ", " #t0 "               \n\t"\
1261         "psubusb " #lx ", " #sx "               \n\t"\
1262         "movq "MANGLE(b00)", " #lx "            \n\t"\
1263         "pcmpeqb " #lx ", " #t1 "               \n\t" /* src[-1] > a ? 0 : -1*/\
1264         "pcmpeqb " #lx ", " #t0 "               \n\t" /* src[+1] > a ? 0 : -1*/\
1265         "pcmpeqb " #lx ", " #sx "               \n\t" /* src[0]  > a ? 0 : -1*/\
1266         "paddb " #t1 ", " #t0 "                 \n\t"\
1267         "paddb " #t0 ", " #sx "                 \n\t"\
1268 \
1269         PAVGB(plx, pplx)                              /* filtered */\
1270         "movq " #dst ", " #t0 "                 \n\t" /* dst */\
1271         "movq " #t0 ", " #t1 "                  \n\t" /* dst */\
1272         "psubusb %3, " #t0 "                    \n\t"\
1273         "paddusb %3, " #t1 "                    \n\t"\
1274         PMAXUB(t0, pplx)\
1275         PMINUB(t1, pplx, t0)\
1276         "paddb " #sx ", " #ppsx "               \n\t"\
1277         "paddb " #psx ", " #ppsx "              \n\t"\
1278         "#paddb "MANGLE(b02)", " #ppsx "        \n\t"\
1279         "pand "MANGLE(b08)", " #ppsx "          \n\t"\
1280         "pcmpeqb " #lx ", " #ppsx "             \n\t"\
1281         "pand " #ppsx ", " #pplx "              \n\t"\
1282         "pandn " #dst ", " #ppsx "              \n\t"\
1283         "por " #pplx ", " #ppsx "               \n\t"\
1284         "movq " #ppsx ", " #dst "               \n\t"\
1285         "movq 8(%4), " #lx "                    \n\t"
1286
1287 #define DERING_CORE(dst,src,ppsx,psx,sx,pplx,plx,lx,t0,t1) \
1288    REAL_DERING_CORE(dst,src,ppsx,psx,sx,pplx,plx,lx,t0,t1)
1289 /*
1290 0000000
1291 1111111
1292
1293 1111110
1294 1111101
1295 1111100
1296 1111011
1297 1111010
1298 1111001
1299
1300 1111000
1301 1110111
1302
1303 */
1304 //DERING_CORE(dst          ,src            ,ppsx ,psx  ,sx   ,pplx ,plx  ,lx   ,t0   ,t1)
1305 DERING_CORE((%%REGa)       ,(%%REGa, %1)   ,%%mm0,%%mm2,%%mm4,%%mm1,%%mm3,%%mm5,%%mm6,%%mm7)
1306 DERING_CORE((%%REGa, %1)   ,(%%REGa, %1, 2),%%mm2,%%mm4,%%mm0,%%mm3,%%mm5,%%mm1,%%mm6,%%mm7)
1307 DERING_CORE((%%REGa, %1, 2),(%0, %1, 4)    ,%%mm4,%%mm0,%%mm2,%%mm5,%%mm1,%%mm3,%%mm6,%%mm7)
1308 DERING_CORE((%0, %1, 4)    ,(%%REGd)       ,%%mm0,%%mm2,%%mm4,%%mm1,%%mm3,%%mm5,%%mm6,%%mm7)
1309 DERING_CORE((%%REGd)       ,(%%REGd, %1)   ,%%mm2,%%mm4,%%mm0,%%mm3,%%mm5,%%mm1,%%mm6,%%mm7)
1310 DERING_CORE((%%REGd, %1)   ,(%%REGd, %1, 2),%%mm4,%%mm0,%%mm2,%%mm5,%%mm1,%%mm3,%%mm6,%%mm7)
1311 DERING_CORE((%%REGd, %1, 2),(%0, %1, 8)    ,%%mm0,%%mm2,%%mm4,%%mm1,%%mm3,%%mm5,%%mm6,%%mm7)
1312 DERING_CORE((%0, %1, 8)    ,(%%REGd, %1, 4),%%mm2,%%mm4,%%mm0,%%mm3,%%mm5,%%mm1,%%mm6,%%mm7)
1313
1314         "1:                        \n\t"
1315         : : "r" (src), "r" ((x86_reg)stride), "m" (c->pQPb), "m"(c->pQPb2), "q"(tmp)
1316         : "%"REG_a, "%"REG_d
1317     );
1318 #else //TEMPLATE_PP_MMXEXT || TEMPLATE_PP_3DNOW
1319     int y;
1320     int min=255;
1321     int max=0;
1322     int avg;
1323     uint8_t *p;
1324     int s[10];
1325     const int QP2= c->QP/2 + 1;
1326
1327     for(y=1; y<9; y++){
1328         int x;
1329         p= src + stride*y;
1330         for(x=1; x<9; x++){
1331             p++;
1332             if(*p > max) max= *p;
1333             if(*p < min) min= *p;
1334         }
1335     }
1336     avg= (min + max + 1)>>1;
1337
1338     if(max - min <deringThreshold) return;
1339
1340     for(y=0; y<10; y++){
1341         int t = 0;
1342
1343         if(src[stride*y + 0] > avg) t+= 1;
1344         if(src[stride*y + 1] > avg) t+= 2;
1345         if(src[stride*y + 2] > avg) t+= 4;
1346         if(src[stride*y + 3] > avg) t+= 8;
1347         if(src[stride*y + 4] > avg) t+= 16;
1348         if(src[stride*y + 5] > avg) t+= 32;
1349         if(src[stride*y + 6] > avg) t+= 64;
1350         if(src[stride*y + 7] > avg) t+= 128;
1351         if(src[stride*y + 8] > avg) t+= 256;
1352         if(src[stride*y + 9] > avg) t+= 512;
1353
1354         t |= (~t)<<16;
1355         t &= (t<<1) & (t>>1);
1356         s[y] = t;
1357     }
1358
1359     for(y=1; y<9; y++){
1360         int t = s[y-1] & s[y] & s[y+1];
1361         t|= t>>16;
1362         s[y-1]= t;
1363     }
1364
1365     for(y=1; y<9; y++){
1366         int x;
1367         int t = s[y-1];
1368
1369         p= src + stride*y;
1370         for(x=1; x<9; x++){
1371             p++;
1372             if(t & (1<<x)){
1373                 int f= (*(p-stride-1)) + 2*(*(p-stride)) + (*(p-stride+1))
1374                       +2*(*(p     -1)) + 4*(*p         ) + 2*(*(p     +1))
1375                       +(*(p+stride-1)) + 2*(*(p+stride)) + (*(p+stride+1));
1376                 f= (f + 8)>>4;
1377
1378 #ifdef DEBUG_DERING_THRESHOLD
1379                     __asm__ volatile("emms\n\t":);
1380                     {
1381                     static long long numPixels=0;
1382                     if(x!=1 && x!=8 && y!=1 && y!=8) numPixels++;
1383 //                    if((max-min)<20 || (max-min)*QP<200)
1384 //                    if((max-min)*QP < 500)
1385 //                    if(max-min<QP/2)
1386                     if(max-min < 20){
1387                         static int numSkipped=0;
1388                         static int errorSum=0;
1389                         static int worstQP=0;
1390                         static int worstRange=0;
1391                         static int worstDiff=0;
1392                         int diff= (f - *p);
1393                         int absDiff= FFABS(diff);
1394                         int error= diff*diff;
1395
1396                         if(x==1 || x==8 || y==1 || y==8) continue;
1397
1398                         numSkipped++;
1399                         if(absDiff > worstDiff){
1400                             worstDiff= absDiff;
1401                             worstQP= QP;
1402                             worstRange= max-min;
1403                         }
1404                         errorSum+= error;
1405
1406                         if(1024LL*1024LL*1024LL % numSkipped == 0){
1407                             av_log(c, AV_LOG_INFO, "sum:%1.3f, skip:%d, wQP:%d, "
1408                                    "wRange:%d, wDiff:%d, relSkip:%1.3f\n",
1409                                    (float)errorSum/numSkipped, numSkipped, worstQP, worstRange,
1410                                    worstDiff, (float)numSkipped/numPixels);
1411                         }
1412                     }
1413                     }
1414 #endif
1415                     if     (*p + QP2 < f) *p= *p + QP2;
1416                     else if(*p - QP2 > f) *p= *p - QP2;
1417                     else *p=f;
1418             }
1419         }
1420     }
1421 #ifdef DEBUG_DERING_THRESHOLD
1422     if(max-min < 20){
1423         for(y=1; y<9; y++){
1424             int x;
1425             int t = 0;
1426             p= src + stride*y;
1427             for(x=1; x<9; x++){
1428                 p++;
1429                 *p = FFMIN(*p + 20, 255);
1430             }
1431         }
1432 //        src[0] = src[7]=src[stride*7]=src[stride*7 + 7]=255;
1433     }
1434 #endif
1435 #endif //TEMPLATE_PP_MMXEXT || TEMPLATE_PP_3DNOW
1436 }
1437 #endif //TEMPLATE_PP_ALTIVEC
1438
1439 /**
1440  * Deinterlace the given block by linearly interpolating every second line.
1441  * will be called for every 8x8 block and can read & write from line 4-15
1442  * lines 0-3 have been passed through the deblock / dering filters already, but can be read, too.
1443  * lines 4-12 will be read into the deblocking filter and should be deinterlaced
1444  */
1445 static inline void RENAME(deInterlaceInterpolateLinear)(uint8_t src[], int stride)
1446 {
1447 #if TEMPLATE_PP_MMXEXT || TEMPLATE_PP_3DNOW
1448     src+= 4*stride;
1449     __asm__ volatile(
1450         "lea (%0, %1), %%"REG_a"                \n\t"
1451         "lea (%%"REG_a", %1, 4), %%"REG_c"      \n\t"
1452 //      0       1       2       3       4       5       6       7       8       9
1453 //      %0      eax     eax+%1  eax+2%1 %0+4%1  ecx     ecx+%1  ecx+2%1 %0+8%1  ecx+4%1
1454
1455         "movq (%0), %%mm0                       \n\t"
1456         "movq (%%"REG_a", %1), %%mm1            \n\t"
1457         PAVGB(%%mm1, %%mm0)
1458         "movq %%mm0, (%%"REG_a")                \n\t"
1459         "movq (%0, %1, 4), %%mm0                \n\t"
1460         PAVGB(%%mm0, %%mm1)
1461         "movq %%mm1, (%%"REG_a", %1, 2)         \n\t"
1462         "movq (%%"REG_c", %1), %%mm1            \n\t"
1463         PAVGB(%%mm1, %%mm0)
1464         "movq %%mm0, (%%"REG_c")                \n\t"
1465         "movq (%0, %1, 8), %%mm0                \n\t"
1466         PAVGB(%%mm0, %%mm1)
1467         "movq %%mm1, (%%"REG_c", %1, 2)         \n\t"
1468
1469         : : "r" (src), "r" ((x86_reg)stride)
1470         : "%"REG_a, "%"REG_c
1471     );
1472 #else
1473     int a, b, x;
1474     src+= 4*stride;
1475
1476     for(x=0; x<2; x++){
1477         a= *(uint32_t*)&src[stride*0];
1478         b= *(uint32_t*)&src[stride*2];
1479         *(uint32_t*)&src[stride*1]= (a|b) - (((a^b)&0xFEFEFEFEUL)>>1);
1480         a= *(uint32_t*)&src[stride*4];
1481         *(uint32_t*)&src[stride*3]= (a|b) - (((a^b)&0xFEFEFEFEUL)>>1);
1482         b= *(uint32_t*)&src[stride*6];
1483         *(uint32_t*)&src[stride*5]= (a|b) - (((a^b)&0xFEFEFEFEUL)>>1);
1484         a= *(uint32_t*)&src[stride*8];
1485         *(uint32_t*)&src[stride*7]= (a|b) - (((a^b)&0xFEFEFEFEUL)>>1);
1486         src += 4;
1487     }
1488 #endif
1489 }
1490
1491 /**
1492  * Deinterlace the given block by cubic interpolating every second line.
1493  * will be called for every 8x8 block and can read & write from line 4-15
1494  * lines 0-3 have been passed through the deblock / dering filters already, but can be read, too.
1495  * lines 4-12 will be read into the deblocking filter and should be deinterlaced
1496  * this filter will read lines 3-15 and write 7-13
1497  */
1498 static inline void RENAME(deInterlaceInterpolateCubic)(uint8_t src[], int stride)
1499 {
1500 #if TEMPLATE_PP_SSE2 || TEMPLATE_PP_MMXEXT || TEMPLATE_PP_3DNOW
1501     src+= stride*3;
1502     __asm__ volatile(
1503         "lea (%0, %1), %%"REG_a"                \n\t"
1504         "lea (%%"REG_a", %1, 4), %%"REG_d"      \n\t"
1505         "lea (%%"REG_d", %1, 4), %%"REG_c"      \n\t"
1506         "add %1, %%"REG_c"                      \n\t"
1507 #if TEMPLATE_PP_SSE2
1508         "pxor %%xmm7, %%xmm7                    \n\t"
1509 #define REAL_DEINT_CUBIC(a,b,c,d,e)\
1510         "movq " #a ", %%xmm0                    \n\t"\
1511         "movq " #b ", %%xmm1                    \n\t"\
1512         "movq " #d ", %%xmm2                    \n\t"\
1513         "movq " #e ", %%xmm3                    \n\t"\
1514         "pavgb %%xmm2, %%xmm1                   \n\t"\
1515         "pavgb %%xmm3, %%xmm0                   \n\t"\
1516         "punpcklbw %%xmm7, %%xmm0               \n\t"\
1517         "punpcklbw %%xmm7, %%xmm1               \n\t"\
1518         "psubw %%xmm1, %%xmm0                   \n\t"\
1519         "psraw $3, %%xmm0                       \n\t"\
1520         "psubw %%xmm0, %%xmm1                   \n\t"\
1521         "packuswb %%xmm1, %%xmm1                \n\t"\
1522         "movlps %%xmm1, " #c "                  \n\t"
1523 #else //TEMPLATE_PP_SSE2
1524         "pxor %%mm7, %%mm7                      \n\t"
1525 //      0       1       2       3       4       5       6       7       8       9       10
1526 //      %0      eax     eax+%1  eax+2%1 %0+4%1  edx     edx+%1  edx+2%1 %0+8%1  edx+4%1 ecx
1527
1528 #define REAL_DEINT_CUBIC(a,b,c,d,e)\
1529         "movq " #a ", %%mm0                     \n\t"\
1530         "movq " #b ", %%mm1                     \n\t"\
1531         "movq " #d ", %%mm2                     \n\t"\
1532         "movq " #e ", %%mm3                     \n\t"\
1533         PAVGB(%%mm2, %%mm1)                             /* (b+d) /2 */\
1534         PAVGB(%%mm3, %%mm0)                             /* (a+e) /2 */\
1535         "movq %%mm0, %%mm2                      \n\t"\
1536         "punpcklbw %%mm7, %%mm0                 \n\t"\
1537         "punpckhbw %%mm7, %%mm2                 \n\t"\
1538         "movq %%mm1, %%mm3                      \n\t"\
1539         "punpcklbw %%mm7, %%mm1                 \n\t"\
1540         "punpckhbw %%mm7, %%mm3                 \n\t"\
1541         "psubw %%mm1, %%mm0                     \n\t"   /* L(a+e - (b+d))/2 */\
1542         "psubw %%mm3, %%mm2                     \n\t"   /* H(a+e - (b+d))/2 */\
1543         "psraw $3, %%mm0                        \n\t"   /* L(a+e - (b+d))/16 */\
1544         "psraw $3, %%mm2                        \n\t"   /* H(a+e - (b+d))/16 */\
1545         "psubw %%mm0, %%mm1                     \n\t"   /* L(9b + 9d - a - e)/16 */\
1546         "psubw %%mm2, %%mm3                     \n\t"   /* H(9b + 9d - a - e)/16 */\
1547         "packuswb %%mm3, %%mm1                  \n\t"\
1548         "movq %%mm1, " #c "                     \n\t"
1549 #endif //TEMPLATE_PP_SSE2
1550 #define DEINT_CUBIC(a,b,c,d,e)  REAL_DEINT_CUBIC(a,b,c,d,e)
1551
1552 DEINT_CUBIC((%0)        , (%%REGa, %1), (%%REGa, %1, 2), (%0, %1, 4) , (%%REGd, %1))
1553 DEINT_CUBIC((%%REGa, %1), (%0, %1, 4) , (%%REGd)       , (%%REGd, %1), (%0, %1, 8))
1554 DEINT_CUBIC((%0, %1, 4) , (%%REGd, %1), (%%REGd, %1, 2), (%0, %1, 8) , (%%REGc))
1555 DEINT_CUBIC((%%REGd, %1), (%0, %1, 8) , (%%REGd, %1, 4), (%%REGc)    , (%%REGc, %1, 2))
1556
1557         : : "r" (src), "r" ((x86_reg)stride)
1558         :
1559 #if TEMPLATE_PP_SSE2
1560         XMM_CLOBBERS("%xmm0", "%xmm1", "%xmm2", "%xmm3", "%xmm7",)
1561 #endif
1562         "%"REG_a, "%"REG_d, "%"REG_c
1563     );
1564 #undef REAL_DEINT_CUBIC
1565 #else //TEMPLATE_PP_SSE2 || TEMPLATE_PP_MMXEXT || TEMPLATE_PP_3DNOW
1566     int x;
1567     src+= stride*3;
1568     for(x=0; x<8; x++){
1569         src[stride*3] = CLIP((-src[0]        + 9*src[stride*2] + 9*src[stride*4] - src[stride*6])>>4);
1570         src[stride*5] = CLIP((-src[stride*2] + 9*src[stride*4] + 9*src[stride*6] - src[stride*8])>>4);
1571         src[stride*7] = CLIP((-src[stride*4] + 9*src[stride*6] + 9*src[stride*8] - src[stride*10])>>4);
1572         src[stride*9] = CLIP((-src[stride*6] + 9*src[stride*8] + 9*src[stride*10] - src[stride*12])>>4);
1573         src++;
1574     }
1575 #endif //TEMPLATE_PP_SSE2 || TEMPLATE_PP_MMXEXT || TEMPLATE_PP_3DNOW
1576 }
1577
1578 /**
1579  * Deinterlace the given block by filtering every second line with a (-1 4 2 4 -1) filter.
1580  * will be called for every 8x8 block and can read & write from line 4-15
1581  * lines 0-3 have been passed through the deblock / dering filters already, but can be read, too.
1582  * lines 4-12 will be read into the deblocking filter and should be deinterlaced
1583  * this filter will read lines 4-13 and write 5-11
1584  */
1585 static inline void RENAME(deInterlaceFF)(uint8_t src[], int stride, uint8_t *tmp)
1586 {
1587 #if TEMPLATE_PP_MMXEXT || TEMPLATE_PP_3DNOW
1588     src+= stride*4;
1589     __asm__ volatile(
1590         "lea (%0, %1), %%"REG_a"                \n\t"
1591         "lea (%%"REG_a", %1, 4), %%"REG_d"      \n\t"
1592         "pxor %%mm7, %%mm7                      \n\t"
1593         "movq (%2), %%mm0                       \n\t"
1594 //      0       1       2       3       4       5       6       7       8       9       10
1595 //      %0      eax     eax+%1  eax+2%1 %0+4%1  edx     edx+%1  edx+2%1 %0+8%1  edx+4%1 ecx
1596
1597 #define REAL_DEINT_FF(a,b,c,d)\
1598         "movq " #a ", %%mm1                     \n\t"\
1599         "movq " #b ", %%mm2                     \n\t"\
1600         "movq " #c ", %%mm3                     \n\t"\
1601         "movq " #d ", %%mm4                     \n\t"\
1602         PAVGB(%%mm3, %%mm1)                          \
1603         PAVGB(%%mm4, %%mm0)                          \
1604         "movq %%mm0, %%mm3                      \n\t"\
1605         "punpcklbw %%mm7, %%mm0                 \n\t"\
1606         "punpckhbw %%mm7, %%mm3                 \n\t"\
1607         "movq %%mm1, %%mm4                      \n\t"\
1608         "punpcklbw %%mm7, %%mm1                 \n\t"\
1609         "punpckhbw %%mm7, %%mm4                 \n\t"\
1610         "psllw $2, %%mm1                        \n\t"\
1611         "psllw $2, %%mm4                        \n\t"\
1612         "psubw %%mm0, %%mm1                     \n\t"\
1613         "psubw %%mm3, %%mm4                     \n\t"\
1614         "movq %%mm2, %%mm5                      \n\t"\
1615         "movq %%mm2, %%mm0                      \n\t"\
1616         "punpcklbw %%mm7, %%mm2                 \n\t"\
1617         "punpckhbw %%mm7, %%mm5                 \n\t"\
1618         "paddw %%mm2, %%mm1                     \n\t"\
1619         "paddw %%mm5, %%mm4                     \n\t"\
1620         "psraw $2, %%mm1                        \n\t"\
1621         "psraw $2, %%mm4                        \n\t"\
1622         "packuswb %%mm4, %%mm1                  \n\t"\
1623         "movq %%mm1, " #b "                     \n\t"\
1624
1625 #define DEINT_FF(a,b,c,d)  REAL_DEINT_FF(a,b,c,d)
1626
1627 DEINT_FF((%0)        , (%%REGa)       , (%%REGa, %1), (%%REGa, %1, 2))
1628 DEINT_FF((%%REGa, %1), (%%REGa, %1, 2), (%0, %1, 4) , (%%REGd)       )
1629 DEINT_FF((%0, %1, 4) , (%%REGd)       , (%%REGd, %1), (%%REGd, %1, 2))
1630 DEINT_FF((%%REGd, %1), (%%REGd, %1, 2), (%0, %1, 8) , (%%REGd, %1, 4))
1631
1632         "movq %%mm0, (%2)                       \n\t"
1633         : : "r" (src), "r" ((x86_reg)stride), "r"(tmp)
1634         : "%"REG_a, "%"REG_d
1635     );
1636 #else //TEMPLATE_PP_MMXEXT || TEMPLATE_PP_3DNOW
1637     int x;
1638     src+= stride*4;
1639     for(x=0; x<8; x++){
1640         int t1= tmp[x];
1641         int t2= src[stride*1];
1642
1643         src[stride*1]= CLIP((-t1 + 4*src[stride*0] + 2*t2 + 4*src[stride*2] - src[stride*3] + 4)>>3);
1644         t1= src[stride*4];
1645         src[stride*3]= CLIP((-t2 + 4*src[stride*2] + 2*t1 + 4*src[stride*4] - src[stride*5] + 4)>>3);
1646         t2= src[stride*6];
1647         src[stride*5]= CLIP((-t1 + 4*src[stride*4] + 2*t2 + 4*src[stride*6] - src[stride*7] + 4)>>3);
1648         t1= src[stride*8];
1649         src[stride*7]= CLIP((-t2 + 4*src[stride*6] + 2*t1 + 4*src[stride*8] - src[stride*9] + 4)>>3);
1650         tmp[x]= t1;
1651
1652         src++;
1653     }
1654 #endif //TEMPLATE_PP_MMXEXT || TEMPLATE_PP_3DNOW
1655 }
1656
1657 /**
1658  * Deinterlace the given block by filtering every line with a (-1 2 6 2 -1) filter.
1659  * will be called for every 8x8 block and can read & write from line 4-15
1660  * lines 0-3 have been passed through the deblock / dering filters already, but can be read, too.
1661  * lines 4-12 will be read into the deblocking filter and should be deinterlaced
1662  * this filter will read lines 4-13 and write 4-11
1663  */
1664 static inline void RENAME(deInterlaceL5)(uint8_t src[], int stride, uint8_t *tmp, uint8_t *tmp2)
1665 {
1666 #if TEMPLATE_PP_MMXEXT || TEMPLATE_PP_3DNOW
1667     src+= stride*4;
1668     __asm__ volatile(
1669         "lea (%0, %1), %%"REG_a"                \n\t"
1670         "lea (%%"REG_a", %1, 4), %%"REG_d"      \n\t"
1671         "pxor %%mm7, %%mm7                      \n\t"
1672         "movq (%2), %%mm0                       \n\t"
1673         "movq (%3), %%mm1                       \n\t"
1674 //      0       1       2       3       4       5       6       7       8       9       10
1675 //      %0      eax     eax+%1  eax+2%1 %0+4%1  edx     edx+%1  edx+2%1 %0+8%1  edx+4%1 ecx
1676
1677 #define REAL_DEINT_L5(t1,t2,a,b,c)\
1678         "movq " #a ", %%mm2                     \n\t"\
1679         "movq " #b ", %%mm3                     \n\t"\
1680         "movq " #c ", %%mm4                     \n\t"\
1681         PAVGB(t2, %%mm3)                             \
1682         PAVGB(t1, %%mm4)                             \
1683         "movq %%mm2, %%mm5                      \n\t"\
1684         "movq %%mm2, " #t1 "                    \n\t"\
1685         "punpcklbw %%mm7, %%mm2                 \n\t"\
1686         "punpckhbw %%mm7, %%mm5                 \n\t"\
1687         "movq %%mm2, %%mm6                      \n\t"\
1688         "paddw %%mm2, %%mm2                     \n\t"\
1689         "paddw %%mm6, %%mm2                     \n\t"\
1690         "movq %%mm5, %%mm6                      \n\t"\
1691         "paddw %%mm5, %%mm5                     \n\t"\
1692         "paddw %%mm6, %%mm5                     \n\t"\
1693         "movq %%mm3, %%mm6                      \n\t"\
1694         "punpcklbw %%mm7, %%mm3                 \n\t"\
1695         "punpckhbw %%mm7, %%mm6                 \n\t"\
1696         "paddw %%mm3, %%mm3                     \n\t"\
1697         "paddw %%mm6, %%mm6                     \n\t"\
1698         "paddw %%mm3, %%mm2                     \n\t"\
1699         "paddw %%mm6, %%mm5                     \n\t"\
1700         "movq %%mm4, %%mm6                      \n\t"\
1701         "punpcklbw %%mm7, %%mm4                 \n\t"\
1702         "punpckhbw %%mm7, %%mm6                 \n\t"\
1703         "psubw %%mm4, %%mm2                     \n\t"\
1704         "psubw %%mm6, %%mm5                     \n\t"\
1705         "psraw $2, %%mm2                        \n\t"\
1706         "psraw $2, %%mm5                        \n\t"\
1707         "packuswb %%mm5, %%mm2                  \n\t"\
1708         "movq %%mm2, " #a "                     \n\t"\
1709
1710 #define DEINT_L5(t1,t2,a,b,c)  REAL_DEINT_L5(t1,t2,a,b,c)
1711
1712 DEINT_L5(%%mm0, %%mm1, (%0)           , (%%REGa)       , (%%REGa, %1)   )
1713 DEINT_L5(%%mm1, %%mm0, (%%REGa)       , (%%REGa, %1)   , (%%REGa, %1, 2))
1714 DEINT_L5(%%mm0, %%mm1, (%%REGa, %1)   , (%%REGa, %1, 2), (%0, %1, 4)   )
1715 DEINT_L5(%%mm1, %%mm0, (%%REGa, %1, 2), (%0, %1, 4)    , (%%REGd)       )
1716 DEINT_L5(%%mm0, %%mm1, (%0, %1, 4)    , (%%REGd)       , (%%REGd, %1)   )
1717 DEINT_L5(%%mm1, %%mm0, (%%REGd)       , (%%REGd, %1)   , (%%REGd, %1, 2))
1718 DEINT_L5(%%mm0, %%mm1, (%%REGd, %1)   , (%%REGd, %1, 2), (%0, %1, 8)   )
1719 DEINT_L5(%%mm1, %%mm0, (%%REGd, %1, 2), (%0, %1, 8)    , (%%REGd, %1, 4))
1720
1721         "movq %%mm0, (%2)                       \n\t"
1722         "movq %%mm1, (%3)                       \n\t"
1723         : : "r" (src), "r" ((x86_reg)stride), "r"(tmp), "r"(tmp2)
1724         : "%"REG_a, "%"REG_d
1725     );
1726 #else //TEMPLATE_PP_MMXEXT || TEMPLATE_PP_3DNOW
1727     int x;
1728     src+= stride*4;
1729     for(x=0; x<8; x++){
1730         int t1= tmp[x];
1731         int t2= tmp2[x];
1732         int t3= src[0];
1733
1734         src[stride*0]= CLIP((-(t1 + src[stride*2]) + 2*(t2 + src[stride*1]) + 6*t3 + 4)>>3);
1735         t1= src[stride*1];
1736         src[stride*1]= CLIP((-(t2 + src[stride*3]) + 2*(t3 + src[stride*2]) + 6*t1 + 4)>>3);
1737         t2= src[stride*2];
1738         src[stride*2]= CLIP((-(t3 + src[stride*4]) + 2*(t1 + src[stride*3]) + 6*t2 + 4)>>3);
1739         t3= src[stride*3];
1740         src[stride*3]= CLIP((-(t1 + src[stride*5]) + 2*(t2 + src[stride*4]) + 6*t3 + 4)>>3);
1741         t1= src[stride*4];
1742         src[stride*4]= CLIP((-(t2 + src[stride*6]) + 2*(t3 + src[stride*5]) + 6*t1 + 4)>>3);
1743         t2= src[stride*5];
1744         src[stride*5]= CLIP((-(t3 + src[stride*7]) + 2*(t1 + src[stride*6]) + 6*t2 + 4)>>3);
1745         t3= src[stride*6];
1746         src[stride*6]= CLIP((-(t1 + src[stride*8]) + 2*(t2 + src[stride*7]) + 6*t3 + 4)>>3);
1747         t1= src[stride*7];
1748         src[stride*7]= CLIP((-(t2 + src[stride*9]) + 2*(t3 + src[stride*8]) + 6*t1 + 4)>>3);
1749
1750         tmp[x]= t3;
1751         tmp2[x]= t1;
1752
1753         src++;
1754     }
1755 #endif //TEMPLATE_PP_MMXEXT || TEMPLATE_PP_3DNOW
1756 }
1757
1758 /**
1759  * Deinterlace the given block by filtering all lines with a (1 2 1) filter.
1760  * will be called for every 8x8 block and can read & write from line 4-15
1761  * lines 0-3 have been passed through the deblock / dering filters already, but can be read, too.
1762  * lines 4-12 will be read into the deblocking filter and should be deinterlaced
1763  * this filter will read lines 4-13 and write 4-11
1764  */
1765 static inline void RENAME(deInterlaceBlendLinear)(uint8_t src[], int stride, uint8_t *tmp)
1766 {
1767 #if TEMPLATE_PP_MMXEXT || TEMPLATE_PP_3DNOW
1768     src+= 4*stride;
1769     __asm__ volatile(
1770         "lea (%0, %1), %%"REG_a"                \n\t"
1771         "lea (%%"REG_a", %1, 4), %%"REG_d"      \n\t"
1772 //      0       1       2       3       4       5       6       7       8       9
1773 //      %0      eax     eax+%1  eax+2%1 %0+4%1  edx     edx+%1  edx+2%1 %0+8%1  edx+4%1
1774
1775         "movq (%2), %%mm0                       \n\t" // L0
1776         "movq (%%"REG_a"), %%mm1                \n\t" // L2
1777         PAVGB(%%mm1, %%mm0)                           // L0+L2
1778         "movq (%0), %%mm2                       \n\t" // L1
1779         PAVGB(%%mm2, %%mm0)
1780         "movq %%mm0, (%0)                       \n\t"
1781         "movq (%%"REG_a", %1), %%mm0            \n\t" // L3
1782         PAVGB(%%mm0, %%mm2)                           // L1+L3
1783         PAVGB(%%mm1, %%mm2)                           // 2L2 + L1 + L3
1784         "movq %%mm2, (%%"REG_a")                \n\t"
1785         "movq (%%"REG_a", %1, 2), %%mm2         \n\t" // L4
1786         PAVGB(%%mm2, %%mm1)                           // L2+L4
1787         PAVGB(%%mm0, %%mm1)                           // 2L3 + L2 + L4
1788         "movq %%mm1, (%%"REG_a", %1)            \n\t"
1789         "movq (%0, %1, 4), %%mm1                \n\t" // L5
1790         PAVGB(%%mm1, %%mm0)                           // L3+L5
1791         PAVGB(%%mm2, %%mm0)                           // 2L4 + L3 + L5
1792         "movq %%mm0, (%%"REG_a", %1, 2)         \n\t"
1793         "movq (%%"REG_d"), %%mm0                \n\t" // L6
1794         PAVGB(%%mm0, %%mm2)                           // L4+L6
1795         PAVGB(%%mm1, %%mm2)                           // 2L5 + L4 + L6
1796         "movq %%mm2, (%0, %1, 4)                \n\t"
1797         "movq (%%"REG_d", %1), %%mm2            \n\t" // L7
1798         PAVGB(%%mm2, %%mm1)                           // L5+L7
1799         PAVGB(%%mm0, %%mm1)                           // 2L6 + L5 + L7
1800         "movq %%mm1, (%%"REG_d")                \n\t"
1801         "movq (%%"REG_d", %1, 2), %%mm1         \n\t" // L8
1802         PAVGB(%%mm1, %%mm0)                           // L6+L8
1803         PAVGB(%%mm2, %%mm0)                           // 2L7 + L6 + L8
1804         "movq %%mm0, (%%"REG_d", %1)            \n\t"
1805         "movq (%0, %1, 8), %%mm0                \n\t" // L9
1806         PAVGB(%%mm0, %%mm2)                           // L7+L9
1807         PAVGB(%%mm1, %%mm2)                           // 2L8 + L7 + L9
1808         "movq %%mm2, (%%"REG_d", %1, 2)         \n\t"
1809         "movq %%mm1, (%2)                       \n\t"
1810
1811         : : "r" (src), "r" ((x86_reg)stride), "r" (tmp)
1812         : "%"REG_a, "%"REG_d
1813     );
1814 #else //TEMPLATE_PP_MMXEXT || TEMPLATE_PP_3DNOW
1815     int a, b, c, x;
1816     src+= 4*stride;
1817
1818     for(x=0; x<2; x++){
1819         a= *(uint32_t*)&tmp[stride*0];
1820         b= *(uint32_t*)&src[stride*0];
1821         c= *(uint32_t*)&src[stride*1];
1822         a= (a&c) + (((a^c)&0xFEFEFEFEUL)>>1);
1823         *(uint32_t*)&src[stride*0]= (a|b) - (((a^b)&0xFEFEFEFEUL)>>1);
1824
1825         a= *(uint32_t*)&src[stride*2];
1826         b= (a&b) + (((a^b)&0xFEFEFEFEUL)>>1);
1827         *(uint32_t*)&src[stride*1]= (c|b) - (((c^b)&0xFEFEFEFEUL)>>1);
1828
1829         b= *(uint32_t*)&src[stride*3];
1830         c= (b&c) + (((b^c)&0xFEFEFEFEUL)>>1);
1831         *(uint32_t*)&src[stride*2]= (c|a) - (((c^a)&0xFEFEFEFEUL)>>1);
1832
1833         c= *(uint32_t*)&src[stride*4];
1834         a= (a&c) + (((a^c)&0xFEFEFEFEUL)>>1);
1835         *(uint32_t*)&src[stride*3]= (a|b) - (((a^b)&0xFEFEFEFEUL)>>1);
1836
1837         a= *(uint32_t*)&src[stride*5];
1838         b= (a&b) + (((a^b)&0xFEFEFEFEUL)>>1);
1839         *(uint32_t*)&src[stride*4]= (c|b) - (((c^b)&0xFEFEFEFEUL)>>1);
1840
1841         b= *(uint32_t*)&src[stride*6];
1842         c= (b&c) + (((b^c)&0xFEFEFEFEUL)>>1);
1843         *(uint32_t*)&src[stride*5]= (c|a) - (((c^a)&0xFEFEFEFEUL)>>1);
1844
1845         c= *(uint32_t*)&src[stride*7];
1846         a= (a&c) + (((a^c)&0xFEFEFEFEUL)>>1);
1847         *(uint32_t*)&src[stride*6]= (a|b) - (((a^b)&0xFEFEFEFEUL)>>1);
1848
1849         a= *(uint32_t*)&src[stride*8];
1850         b= (a&b) + (((a^b)&0xFEFEFEFEUL)>>1);
1851         *(uint32_t*)&src[stride*7]= (c|b) - (((c^b)&0xFEFEFEFEUL)>>1);
1852
1853         *(uint32_t*)&tmp[stride*0]= c;
1854         src += 4;
1855         tmp += 4;
1856     }
1857 #endif //TEMPLATE_PP_MMXEXT || TEMPLATE_PP_3DNOW
1858 }
1859
1860 /**
1861  * Deinterlace the given block by applying a median filter to every second line.
1862  * will be called for every 8x8 block and can read & write from line 4-15,
1863  * lines 0-3 have been passed through the deblock / dering filters already, but can be read, too.
1864  * lines 4-12 will be read into the deblocking filter and should be deinterlaced
1865  */
1866 static inline void RENAME(deInterlaceMedian)(uint8_t src[], int stride)
1867 {
1868 #if TEMPLATE_PP_MMX
1869     src+= 4*stride;
1870 #if TEMPLATE_PP_MMXEXT
1871     __asm__ volatile(
1872         "lea (%0, %1), %%"REG_a"                \n\t"
1873         "lea (%%"REG_a", %1, 4), %%"REG_d"      \n\t"
1874 //      0       1       2       3       4       5       6       7       8       9
1875 //      %0      eax     eax+%1  eax+2%1 %0+4%1  edx     edx+%1  edx+2%1 %0+8%1  edx+4%1
1876
1877         "movq (%0), %%mm0                       \n\t" //
1878         "movq (%%"REG_a", %1), %%mm2            \n\t" //
1879         "movq (%%"REG_a"), %%mm1                \n\t" //
1880         "movq %%mm0, %%mm3                      \n\t"
1881         "pmaxub %%mm1, %%mm0                    \n\t" //
1882         "pminub %%mm3, %%mm1                    \n\t" //
1883         "pmaxub %%mm2, %%mm1                    \n\t" //
1884         "pminub %%mm1, %%mm0                    \n\t"
1885         "movq %%mm0, (%%"REG_a")                \n\t"
1886
1887         "movq (%0, %1, 4), %%mm0                \n\t" //
1888         "movq (%%"REG_a", %1, 2), %%mm1         \n\t" //
1889         "movq %%mm2, %%mm3                      \n\t"
1890         "pmaxub %%mm1, %%mm2                    \n\t" //
1891         "pminub %%mm3, %%mm1                    \n\t" //
1892         "pmaxub %%mm0, %%mm1                    \n\t" //
1893         "pminub %%mm1, %%mm2                    \n\t"
1894         "movq %%mm2, (%%"REG_a", %1, 2)         \n\t"
1895
1896         "movq (%%"REG_d"), %%mm2                \n\t" //
1897         "movq (%%"REG_d", %1), %%mm1            \n\t" //
1898         "movq %%mm2, %%mm3                      \n\t"
1899         "pmaxub %%mm0, %%mm2                    \n\t" //
1900         "pminub %%mm3, %%mm0                    \n\t" //
1901         "pmaxub %%mm1, %%mm0                    \n\t" //
1902         "pminub %%mm0, %%mm2                    \n\t"
1903         "movq %%mm2, (%%"REG_d")                \n\t"
1904
1905         "movq (%%"REG_d", %1, 2), %%mm2         \n\t" //
1906         "movq (%0, %1, 8), %%mm0                \n\t" //
1907         "movq %%mm2, %%mm3                      \n\t"
1908         "pmaxub %%mm0, %%mm2                    \n\t" //
1909         "pminub %%mm3, %%mm0                    \n\t" //
1910         "pmaxub %%mm1, %%mm0                    \n\t" //
1911         "pminub %%mm0, %%mm2                    \n\t"
1912         "movq %%mm2, (%%"REG_d", %1, 2)         \n\t"
1913
1914
1915         : : "r" (src), "r" ((x86_reg)stride)
1916         : "%"REG_a, "%"REG_d
1917     );
1918
1919 #else // MMX without MMX2
1920     __asm__ volatile(
1921         "lea (%0, %1), %%"REG_a"                \n\t"
1922         "lea (%%"REG_a", %1, 4), %%"REG_d"      \n\t"
1923 //      0       1       2       3       4       5       6       7       8       9
1924 //      %0      eax     eax+%1  eax+2%1 %0+4%1  edx     edx+%1  edx+2%1 %0+8%1  edx+4%1
1925         "pxor %%mm7, %%mm7                      \n\t"
1926
1927 #define REAL_MEDIAN(a,b,c)\
1928         "movq " #a ", %%mm0                     \n\t"\
1929         "movq " #b ", %%mm2                     \n\t"\
1930         "movq " #c ", %%mm1                     \n\t"\
1931         "movq %%mm0, %%mm3                      \n\t"\
1932         "movq %%mm1, %%mm4                      \n\t"\
1933         "movq %%mm2, %%mm5                      \n\t"\
1934         "psubusb %%mm1, %%mm3                   \n\t"\
1935         "psubusb %%mm2, %%mm4                   \n\t"\
1936         "psubusb %%mm0, %%mm5                   \n\t"\
1937         "pcmpeqb %%mm7, %%mm3                   \n\t"\
1938         "pcmpeqb %%mm7, %%mm4                   \n\t"\
1939         "pcmpeqb %%mm7, %%mm5                   \n\t"\
1940         "movq %%mm3, %%mm6                      \n\t"\
1941         "pxor %%mm4, %%mm3                      \n\t"\
1942         "pxor %%mm5, %%mm4                      \n\t"\
1943         "pxor %%mm6, %%mm5                      \n\t"\
1944         "por %%mm3, %%mm1                       \n\t"\
1945         "por %%mm4, %%mm2                       \n\t"\
1946         "por %%mm5, %%mm0                       \n\t"\
1947         "pand %%mm2, %%mm0                      \n\t"\
1948         "pand %%mm1, %%mm0                      \n\t"\
1949         "movq %%mm0, " #b "                     \n\t"
1950 #define MEDIAN(a,b,c)  REAL_MEDIAN(a,b,c)
1951
1952 MEDIAN((%0)        , (%%REGa)       , (%%REGa, %1))
1953 MEDIAN((%%REGa, %1), (%%REGa, %1, 2), (%0, %1, 4))
1954 MEDIAN((%0, %1, 4) , (%%REGd)       , (%%REGd, %1))
1955 MEDIAN((%%REGd, %1), (%%REGd, %1, 2), (%0, %1, 8))
1956
1957         : : "r" (src), "r" ((x86_reg)stride)
1958         : "%"REG_a, "%"REG_d
1959     );
1960 #endif //TEMPLATE_PP_MMXEXT
1961 #else //TEMPLATE_PP_MMX
1962     int x, y;
1963     src+= 4*stride;
1964     // FIXME - there should be a way to do a few columns in parallel like w/mmx
1965     for(x=0; x<8; x++){
1966         uint8_t *colsrc = src;
1967         for (y=0; y<4; y++){
1968             int a, b, c, d, e, f;
1969             a = colsrc[0       ];
1970             b = colsrc[stride  ];
1971             c = colsrc[stride*2];
1972             d = (a-b)>>31;
1973             e = (b-c)>>31;
1974             f = (c-a)>>31;
1975             colsrc[stride  ] = (a|(d^f)) & (b|(d^e)) & (c|(e^f));
1976             colsrc += stride*2;
1977         }
1978         src++;
1979     }
1980 #endif //TEMPLATE_PP_MMX
1981 }
1982
1983 #if TEMPLATE_PP_MMX
1984 /**
1985  * Transpose and shift the given 8x8 Block into dst1 and dst2.
1986  */
1987 static inline void RENAME(transpose1)(uint8_t *dst1, uint8_t *dst2, uint8_t *src, int srcStride)
1988 {
1989     __asm__(
1990         "lea (%0, %1), %%"REG_a"                \n\t"
1991 //      0       1       2       3       4       5       6       7       8       9
1992 //      %0      eax     eax+%1  eax+2%1 %0+4%1  edx     edx+%1  edx+2%1 %0+8%1  edx+4%1
1993         "movq (%0), %%mm0                       \n\t" // 12345678
1994         "movq (%%"REG_a"), %%mm1                \n\t" // abcdefgh
1995         "movq %%mm0, %%mm2                      \n\t" // 12345678
1996         "punpcklbw %%mm1, %%mm0                 \n\t" // 1a2b3c4d
1997         "punpckhbw %%mm1, %%mm2                 \n\t" // 5e6f7g8h
1998
1999         "movq (%%"REG_a", %1), %%mm1            \n\t"
2000         "movq (%%"REG_a", %1, 2), %%mm3         \n\t"
2001         "movq %%mm1, %%mm4                      \n\t"
2002         "punpcklbw %%mm3, %%mm1                 \n\t"
2003         "punpckhbw %%mm3, %%mm4                 \n\t"
2004
2005         "movq %%mm0, %%mm3                      \n\t"
2006         "punpcklwd %%mm1, %%mm0                 \n\t"
2007         "punpckhwd %%mm1, %%mm3                 \n\t"
2008         "movq %%mm2, %%mm1                      \n\t"
2009         "punpcklwd %%mm4, %%mm2                 \n\t"
2010         "punpckhwd %%mm4, %%mm1                 \n\t"
2011
2012         "movd %%mm0, 128(%2)                    \n\t"
2013         "psrlq $32, %%mm0                       \n\t"
2014         "movd %%mm0, 144(%2)                    \n\t"
2015         "movd %%mm3, 160(%2)                    \n\t"
2016         "psrlq $32, %%mm3                       \n\t"
2017         "movd %%mm3, 176(%2)                    \n\t"
2018         "movd %%mm3, 48(%3)                     \n\t"
2019         "movd %%mm2, 192(%2)                    \n\t"
2020         "movd %%mm2, 64(%3)                     \n\t"
2021         "psrlq $32, %%mm2                       \n\t"
2022         "movd %%mm2, 80(%3)                     \n\t"
2023         "movd %%mm1, 96(%3)                     \n\t"
2024         "psrlq $32, %%mm1                       \n\t"
2025         "movd %%mm1, 112(%3)                    \n\t"
2026
2027         "lea (%%"REG_a", %1, 4), %%"REG_a"      \n\t"
2028
2029         "movq (%0, %1, 4), %%mm0                \n\t" // 12345678
2030         "movq (%%"REG_a"), %%mm1                \n\t" // abcdefgh
2031         "movq %%mm0, %%mm2                      \n\t" // 12345678
2032         "punpcklbw %%mm1, %%mm0                 \n\t" // 1a2b3c4d
2033         "punpckhbw %%mm1, %%mm2                 \n\t" // 5e6f7g8h
2034
2035         "movq (%%"REG_a", %1), %%mm1            \n\t"
2036         "movq (%%"REG_a", %1, 2), %%mm3         \n\t"
2037         "movq %%mm1, %%mm4                      \n\t"
2038         "punpcklbw %%mm3, %%mm1                 \n\t"
2039         "punpckhbw %%mm3, %%mm4                 \n\t"
2040
2041         "movq %%mm0, %%mm3                      \n\t"
2042         "punpcklwd %%mm1, %%mm0                 \n\t"
2043         "punpckhwd %%mm1, %%mm3                 \n\t"
2044         "movq %%mm2, %%mm1                      \n\t"
2045         "punpcklwd %%mm4, %%mm2                 \n\t"
2046         "punpckhwd %%mm4, %%mm1                 \n\t"
2047
2048         "movd %%mm0, 132(%2)                    \n\t"
2049         "psrlq $32, %%mm0                       \n\t"
2050         "movd %%mm0, 148(%2)                    \n\t"
2051         "movd %%mm3, 164(%2)                    \n\t"
2052         "psrlq $32, %%mm3                       \n\t"
2053         "movd %%mm3, 180(%2)                    \n\t"
2054         "movd %%mm3, 52(%3)                     \n\t"
2055         "movd %%mm2, 196(%2)                    \n\t"
2056         "movd %%mm2, 68(%3)                     \n\t"
2057         "psrlq $32, %%mm2                       \n\t"
2058         "movd %%mm2, 84(%3)                     \n\t"
2059         "movd %%mm1, 100(%3)                    \n\t"
2060         "psrlq $32, %%mm1                       \n\t"
2061         "movd %%mm1, 116(%3)                    \n\t"
2062
2063
2064         :: "r" (src), "r" ((x86_reg)srcStride), "r" (dst1), "r" (dst2)
2065         : "%"REG_a
2066     );
2067 }
2068
2069 /**
2070  * Transpose the given 8x8 block.
2071  */
2072 static inline void RENAME(transpose2)(uint8_t *dst, int dstStride, uint8_t *src)
2073 {
2074     __asm__(
2075         "lea (%0, %1), %%"REG_a"                \n\t"
2076         "lea (%%"REG_a",%1,4), %%"REG_d"        \n\t"
2077 //      0       1       2       3       4       5       6       7       8       9
2078 //      %0      eax     eax+%1  eax+2%1 %0+4%1  edx     edx+%1  edx+2%1 %0+8%1  edx+4%1
2079         "movq (%2), %%mm0                       \n\t" // 12345678
2080         "movq 16(%2), %%mm1                     \n\t" // abcdefgh
2081         "movq %%mm0, %%mm2                      \n\t" // 12345678
2082         "punpcklbw %%mm1, %%mm0                 \n\t" // 1a2b3c4d
2083         "punpckhbw %%mm1, %%mm2                 \n\t" // 5e6f7g8h
2084
2085         "movq 32(%2), %%mm1                     \n\t"
2086         "movq 48(%2), %%mm3                     \n\t"
2087         "movq %%mm1, %%mm4                      \n\t"
2088         "punpcklbw %%mm3, %%mm1                 \n\t"
2089         "punpckhbw %%mm3, %%mm4                 \n\t"
2090
2091         "movq %%mm0, %%mm3                      \n\t"
2092         "punpcklwd %%mm1, %%mm0                 \n\t"
2093         "punpckhwd %%mm1, %%mm3                 \n\t"
2094         "movq %%mm2, %%mm1                      \n\t"
2095         "punpcklwd %%mm4, %%mm2                 \n\t"
2096         "punpckhwd %%mm4, %%mm1                 \n\t"
2097
2098         "movd %%mm0, (%0)                       \n\t"
2099         "psrlq $32, %%mm0                       \n\t"
2100         "movd %%mm0, (%%"REG_a")                \n\t"
2101         "movd %%mm3, (%%"REG_a", %1)            \n\t"
2102         "psrlq $32, %%mm3                       \n\t"
2103         "movd %%mm3, (%%"REG_a", %1, 2)         \n\t"
2104         "movd %%mm2, (%0, %1, 4)                \n\t"
2105         "psrlq $32, %%mm2                       \n\t"
2106         "movd %%mm2, (%%"REG_d")                \n\t"
2107         "movd %%mm1, (%%"REG_d", %1)            \n\t"
2108         "psrlq $32, %%mm1                       \n\t"
2109         "movd %%mm1, (%%"REG_d", %1, 2)         \n\t"
2110
2111
2112         "movq 64(%2), %%mm0                     \n\t" // 12345678
2113         "movq 80(%2), %%mm1                     \n\t" // abcdefgh
2114         "movq %%mm0, %%mm2                      \n\t" // 12345678
2115         "punpcklbw %%mm1, %%mm0                 \n\t" // 1a2b3c4d
2116         "punpckhbw %%mm1, %%mm2                 \n\t" // 5e6f7g8h
2117
2118         "movq 96(%2), %%mm1                     \n\t"
2119         "movq 112(%2), %%mm3                    \n\t"
2120         "movq %%mm1, %%mm4                      \n\t"
2121         "punpcklbw %%mm3, %%mm1                 \n\t"
2122         "punpckhbw %%mm3, %%mm4                 \n\t"
2123
2124         "movq %%mm0, %%mm3                      \n\t"
2125         "punpcklwd %%mm1, %%mm0                 \n\t"
2126         "punpckhwd %%mm1, %%mm3                 \n\t"
2127         "movq %%mm2, %%mm1                      \n\t"
2128         "punpcklwd %%mm4, %%mm2                 \n\t"
2129         "punpckhwd %%mm4, %%mm1                 \n\t"
2130
2131         "movd %%mm0, 4(%0)                      \n\t"
2132         "psrlq $32, %%mm0                       \n\t"
2133         "movd %%mm0, 4(%%"REG_a")               \n\t"
2134         "movd %%mm3, 4(%%"REG_a", %1)           \n\t"
2135         "psrlq $32, %%mm3                       \n\t"
2136         "movd %%mm3, 4(%%"REG_a", %1, 2)        \n\t"
2137         "movd %%mm2, 4(%0, %1, 4)               \n\t"
2138         "psrlq $32, %%mm2                       \n\t"
2139         "movd %%mm2, 4(%%"REG_d")               \n\t"
2140         "movd %%mm1, 4(%%"REG_d", %1)           \n\t"
2141         "psrlq $32, %%mm1                       \n\t"
2142         "movd %%mm1, 4(%%"REG_d", %1, 2)        \n\t"
2143
2144         :: "r" (dst), "r" ((x86_reg)dstStride), "r" (src)
2145         : "%"REG_a, "%"REG_d
2146     );
2147 }
2148 #endif //TEMPLATE_PP_MMX
2149 //static long test=0;
2150
2151 #if !TEMPLATE_PP_ALTIVEC
2152 static inline void RENAME(tempNoiseReducer)(uint8_t *src, int stride,
2153                                     uint8_t *tempBlurred, uint32_t *tempBlurredPast, int *maxNoise)
2154 {
2155     // to save a register (FIXME do this outside of the loops)
2156     tempBlurredPast[127]= maxNoise[0];
2157     tempBlurredPast[128]= maxNoise[1];
2158     tempBlurredPast[129]= maxNoise[2];
2159
2160 #define FAST_L2_DIFF
2161 //#define L1_DIFF //u should change the thresholds too if u try that one
2162 #if TEMPLATE_PP_MMXEXT || TEMPLATE_PP_3DNOW
2163     __asm__ volatile(
2164         "lea (%2, %2, 2), %%"REG_a"             \n\t" // 3*stride
2165         "lea (%2, %2, 4), %%"REG_d"             \n\t" // 5*stride
2166         "lea (%%"REG_d", %2, 2), %%"REG_c"      \n\t" // 7*stride
2167 //      0       1       2       3       4       5       6       7       8       9
2168 //      %x      %x+%2   %x+2%2  %x+eax  %x+4%2  %x+edx  %x+2eax %x+ecx  %x+8%2
2169 //FIXME reorder?
2170 #ifdef L1_DIFF //needs mmx2
2171         "movq (%0), %%mm0                       \n\t" // L0
2172         "psadbw (%1), %%mm0                     \n\t" // |L0-R0|
2173         "movq (%0, %2), %%mm1                   \n\t" // L1
2174         "psadbw (%1, %2), %%mm1                 \n\t" // |L1-R1|
2175         "movq (%0, %2, 2), %%mm2                \n\t" // L2
2176         "psadbw (%1, %2, 2), %%mm2              \n\t" // |L2-R2|
2177         "movq (%0, %%"REG_a"), %%mm3            \n\t" // L3
2178         "psadbw (%1, %%"REG_a"), %%mm3          \n\t" // |L3-R3|
2179
2180         "movq (%0, %2, 4), %%mm4                \n\t" // L4
2181         "paddw %%mm1, %%mm0                     \n\t"
2182         "psadbw (%1, %2, 4), %%mm4              \n\t" // |L4-R4|
2183         "movq (%0, %%"REG_d"), %%mm5            \n\t" // L5
2184         "paddw %%mm2, %%mm0                     \n\t"
2185         "psadbw (%1, %%"REG_d"), %%mm5          \n\t" // |L5-R5|
2186         "movq (%0, %%"REG_a", 2), %%mm6         \n\t" // L6
2187         "paddw %%mm3, %%mm0                     \n\t"
2188         "psadbw (%1, %%"REG_a", 2), %%mm6       \n\t" // |L6-R6|
2189         "movq (%0, %%"REG_c"), %%mm7            \n\t" // L7
2190         "paddw %%mm4, %%mm0                     \n\t"
2191         "psadbw (%1, %%"REG_c"), %%mm7          \n\t" // |L7-R7|
2192         "paddw %%mm5, %%mm6                     \n\t"
2193         "paddw %%mm7, %%mm6                     \n\t"
2194         "paddw %%mm6, %%mm0                     \n\t"
2195 #else //L1_DIFF
2196 #if defined (FAST_L2_DIFF)
2197         "pcmpeqb %%mm7, %%mm7                   \n\t"
2198         "movq "MANGLE(b80)", %%mm6              \n\t"
2199         "pxor %%mm0, %%mm0                      \n\t"
2200 #define REAL_L2_DIFF_CORE(a, b)\
2201         "movq " #a ", %%mm5                     \n\t"\
2202         "movq " #b ", %%mm2                     \n\t"\
2203         "pxor %%mm7, %%mm2                      \n\t"\
2204         PAVGB(%%mm2, %%mm5)\
2205         "paddb %%mm6, %%mm5                     \n\t"\
2206         "movq %%mm5, %%mm2                      \n\t"\
2207         "psllw $8, %%mm5                        \n\t"\
2208         "pmaddwd %%mm5, %%mm5                   \n\t"\
2209         "pmaddwd %%mm2, %%mm2                   \n\t"\
2210         "paddd %%mm2, %%mm5                     \n\t"\
2211         "psrld $14, %%mm5                       \n\t"\
2212         "paddd %%mm5, %%mm0                     \n\t"
2213
2214 #else //defined (FAST_L2_DIFF)
2215         "pxor %%mm7, %%mm7                      \n\t"
2216         "pxor %%mm0, %%mm0                      \n\t"
2217 #define REAL_L2_DIFF_CORE(a, b)\
2218         "movq " #a ", %%mm5                     \n\t"\
2219         "movq " #b ", %%mm2                     \n\t"\
2220         "movq %%mm5, %%mm1                      \n\t"\
2221         "movq %%mm2, %%mm3                      \n\t"\
2222         "punpcklbw %%mm7, %%mm5                 \n\t"\
2223         "punpckhbw %%mm7, %%mm1                 \n\t"\
2224         "punpcklbw %%mm7, %%mm2                 \n\t"\
2225         "punpckhbw %%mm7, %%mm3                 \n\t"\
2226         "psubw %%mm2, %%mm5                     \n\t"\
2227         "psubw %%mm3, %%mm1                     \n\t"\
2228         "pmaddwd %%mm5, %%mm5                   \n\t"\
2229         "pmaddwd %%mm1, %%mm1                   \n\t"\
2230         "paddd %%mm1, %%mm5                     \n\t"\
2231         "paddd %%mm5, %%mm0                     \n\t"
2232
2233 #endif //defined (FAST_L2_DIFF)
2234
2235 #define L2_DIFF_CORE(a, b)  REAL_L2_DIFF_CORE(a, b)
2236
2237 L2_DIFF_CORE((%0)          , (%1))
2238 L2_DIFF_CORE((%0, %2)      , (%1, %2))
2239 L2_DIFF_CORE((%0, %2, 2)   , (%1, %2, 2))
2240 L2_DIFF_CORE((%0, %%REGa)  , (%1, %%REGa))
2241 L2_DIFF_CORE((%0, %2, 4)   , (%1, %2, 4))
2242 L2_DIFF_CORE((%0, %%REGd)  , (%1, %%REGd))
2243 L2_DIFF_CORE((%0, %%REGa,2), (%1, %%REGa,2))
2244 L2_DIFF_CORE((%0, %%REGc)  , (%1, %%REGc))
2245
2246 #endif //L1_DIFF
2247
2248         "movq %%mm0, %%mm4                      \n\t"
2249         "psrlq $32, %%mm0                       \n\t"
2250         "paddd %%mm0, %%mm4                     \n\t"
2251         "movd %%mm4, %%ecx                      \n\t"
2252         "shll $2, %%ecx                         \n\t"
2253         "mov %3, %%"REG_d"                      \n\t"
2254         "addl -4(%%"REG_d"), %%ecx              \n\t"
2255         "addl 4(%%"REG_d"), %%ecx               \n\t"
2256         "addl -1024(%%"REG_d"), %%ecx           \n\t"
2257         "addl $4, %%ecx                         \n\t"
2258         "addl 1024(%%"REG_d"), %%ecx            \n\t"
2259         "shrl $3, %%ecx                         \n\t"
2260         "movl %%ecx, (%%"REG_d")                \n\t"
2261
2262 //        "mov %3, %%"REG_c"                      \n\t"
2263 //        "mov %%"REG_c", test                    \n\t"
2264 //        "jmp 4f                                 \n\t"
2265         "cmpl 512(%%"REG_d"), %%ecx             \n\t"
2266         " jb 2f                                 \n\t"
2267         "cmpl 516(%%"REG_d"), %%ecx             \n\t"
2268         " jb 1f                                 \n\t"
2269
2270         "lea (%%"REG_a", %2, 2), %%"REG_d"      \n\t" // 5*stride
2271         "lea (%%"REG_d", %2, 2), %%"REG_c"      \n\t" // 7*stride
2272         "movq (%0), %%mm0                       \n\t" // L0
2273         "movq (%0, %2), %%mm1                   \n\t" // L1
2274         "movq (%0, %2, 2), %%mm2                \n\t" // L2
2275         "movq (%0, %%"REG_a"), %%mm3            \n\t" // L3
2276         "movq (%0, %2, 4), %%mm4                \n\t" // L4
2277         "movq (%0, %%"REG_d"), %%mm5            \n\t" // L5
2278         "movq (%0, %%"REG_a", 2), %%mm6         \n\t" // L6
2279         "movq (%0, %%"REG_c"), %%mm7            \n\t" // L7
2280         "movq %%mm0, (%1)                       \n\t" // L0
2281         "movq %%mm1, (%1, %2)                   \n\t" // L1
2282         "movq %%mm2, (%1, %2, 2)                \n\t" // L2
2283         "movq %%mm3, (%1, %%"REG_a")            \n\t" // L3
2284         "movq %%mm4, (%1, %2, 4)                \n\t" // L4
2285         "movq %%mm5, (%1, %%"REG_d")            \n\t" // L5
2286         "movq %%mm6, (%1, %%"REG_a", 2)         \n\t" // L6
2287         "movq %%mm7, (%1, %%"REG_c")            \n\t" // L7
2288         "jmp 4f                                 \n\t"
2289
2290         "1:                                     \n\t"
2291         "lea (%%"REG_a", %2, 2), %%"REG_d"      \n\t" // 5*stride
2292         "lea (%%"REG_d", %2, 2), %%"REG_c"      \n\t" // 7*stride
2293         "movq (%0), %%mm0                       \n\t" // L0
2294         PAVGB((%1), %%mm0)                            // L0
2295         "movq (%0, %2), %%mm1                   \n\t" // L1
2296         PAVGB((%1, %2), %%mm1)                        // L1
2297         "movq (%0, %2, 2), %%mm2                \n\t" // L2
2298         PAVGB((%1, %2, 2), %%mm2)                     // L2
2299         "movq (%0, %%"REG_a"), %%mm3            \n\t" // L3
2300         PAVGB((%1, %%REGa), %%mm3)                    // L3
2301         "movq (%0, %2, 4), %%mm4                \n\t" // L4
2302         PAVGB((%1, %2, 4), %%mm4)                     // L4
2303         "movq (%0, %%"REG_d"), %%mm5            \n\t" // L5
2304         PAVGB((%1, %%REGd), %%mm5)                    // L5
2305         "movq (%0, %%"REG_a", 2), %%mm6         \n\t" // L6
2306         PAVGB((%1, %%REGa, 2), %%mm6)                 // L6
2307         "movq (%0, %%"REG_c"), %%mm7            \n\t" // L7
2308         PAVGB((%1, %%REGc), %%mm7)                    // L7
2309         "movq %%mm0, (%1)                       \n\t" // R0
2310         "movq %%mm1, (%1, %2)                   \n\t" // R1
2311         "movq %%mm2, (%1, %2, 2)                \n\t" // R2
2312         "movq %%mm3, (%1, %%"REG_a")            \n\t" // R3
2313         "movq %%mm4, (%1, %2, 4)                \n\t" // R4
2314         "movq %%mm5, (%1, %%"REG_d")            \n\t" // R5
2315         "movq %%mm6, (%1, %%"REG_a", 2)         \n\t" // R6
2316         "movq %%mm7, (%1, %%"REG_c")            \n\t" // R7
2317         "movq %%mm0, (%0)                       \n\t" // L0
2318         "movq %%mm1, (%0, %2)                   \n\t" // L1
2319         "movq %%mm2, (%0, %2, 2)                \n\t" // L2
2320         "movq %%mm3, (%0, %%"REG_a")            \n\t" // L3
2321         "movq %%mm4, (%0, %2, 4)                \n\t" // L4
2322         "movq %%mm5, (%0, %%"REG_d")            \n\t" // L5
2323         "movq %%mm6, (%0, %%"REG_a", 2)         \n\t" // L6
2324         "movq %%mm7, (%0, %%"REG_c")            \n\t" // L7
2325         "jmp 4f                                 \n\t"
2326
2327         "2:                                     \n\t"
2328         "cmpl 508(%%"REG_d"), %%ecx             \n\t"
2329         " jb 3f                                 \n\t"
2330
2331         "lea (%%"REG_a", %2, 2), %%"REG_d"      \n\t" // 5*stride
2332         "lea (%%"REG_d", %2, 2), %%"REG_c"      \n\t" // 7*stride
2333         "movq (%0), %%mm0                       \n\t" // L0
2334         "movq (%0, %2), %%mm1                   \n\t" // L1
2335         "movq (%0, %2, 2), %%mm2                \n\t" // L2
2336         "movq (%0, %%"REG_a"), %%mm3            \n\t" // L3
2337         "movq (%1), %%mm4                       \n\t" // R0
2338         "movq (%1, %2), %%mm5                   \n\t" // R1
2339         "movq (%1, %2, 2), %%mm6                \n\t" // R2
2340         "movq (%1, %%"REG_a"), %%mm7            \n\t" // R3
2341         PAVGB(%%mm4, %%mm0)
2342         PAVGB(%%mm5, %%mm1)
2343         PAVGB(%%mm6, %%mm2)
2344         PAVGB(%%mm7, %%mm3)
2345         PAVGB(%%mm4, %%mm0)
2346         PAVGB(%%mm5, %%mm1)
2347         PAVGB(%%mm6, %%mm2)
2348         PAVGB(%%mm7, %%mm3)
2349         "movq %%mm0, (%1)                       \n\t" // R0
2350         "movq %%mm1, (%1, %2)                   \n\t" // R1
2351         "movq %%mm2, (%1, %2, 2)                \n\t" // R2
2352         "movq %%mm3, (%1, %%"REG_a")            \n\t" // R3
2353         "movq %%mm0, (%0)                       \n\t" // L0
2354         "movq %%mm1, (%0, %2)                   \n\t" // L1
2355         "movq %%mm2, (%0, %2, 2)                \n\t" // L2
2356         "movq %%mm3, (%0, %%"REG_a")            \n\t" // L3
2357
2358         "movq (%0, %2, 4), %%mm0                \n\t" // L4
2359         "movq (%0, %%"REG_d"), %%mm1            \n\t" // L5
2360         "movq (%0, %%"REG_a", 2), %%mm2         \n\t" // L6
2361         "movq (%0, %%"REG_c"), %%mm3            \n\t" // L7
2362         "movq (%1, %2, 4), %%mm4                \n\t" // R4
2363         "movq (%1, %%"REG_d"), %%mm5            \n\t" // R5
2364         "movq (%1, %%"REG_a", 2), %%mm6         \n\t" // R6
2365         "movq (%1, %%"REG_c"), %%mm7            \n\t" // R7
2366         PAVGB(%%mm4, %%mm0)
2367         PAVGB(%%mm5, %%mm1)
2368         PAVGB(%%mm6, %%mm2)
2369         PAVGB(%%mm7, %%mm3)
2370         PAVGB(%%mm4, %%mm0)
2371         PAVGB(%%mm5, %%mm1)
2372         PAVGB(%%mm6, %%mm2)
2373         PAVGB(%%mm7, %%mm3)
2374         "movq %%mm0, (%1, %2, 4)                \n\t" // R4
2375         "movq %%mm1, (%1, %%"REG_d")            \n\t" // R5
2376         "movq %%mm2, (%1, %%"REG_a", 2)         \n\t" // R6
2377         "movq %%mm3, (%1, %%"REG_c")            \n\t" // R7
2378         "movq %%mm0, (%0, %2, 4)                \n\t" // L4
2379         "movq %%mm1, (%0, %%"REG_d")            \n\t" // L5
2380         "movq %%mm2, (%0, %%"REG_a", 2)         \n\t" // L6
2381         "movq %%mm3, (%0, %%"REG_c")            \n\t" // L7
2382         "jmp 4f                                 \n\t"
2383
2384         "3:                                     \n\t"
2385         "lea (%%"REG_a", %2, 2), %%"REG_d"      \n\t" // 5*stride
2386         "lea (%%"REG_d", %2, 2), %%"REG_c"      \n\t" // 7*stride
2387         "movq (%0), %%mm0                       \n\t" // L0
2388         "movq (%0, %2), %%mm1                   \n\t" // L1
2389         "movq (%0, %2, 2), %%mm2                \n\t" // L2
2390         "movq (%0, %%"REG_a"), %%mm3            \n\t" // L3
2391         "movq (%1), %%mm4                       \n\t" // R0
2392         "movq (%1, %2), %%mm5                   \n\t" // R1
2393         "movq (%1, %2, 2), %%mm6                \n\t" // R2
2394         "movq (%1, %%"REG_a"), %%mm7            \n\t" // R3
2395         PAVGB(%%mm4, %%mm0)
2396         PAVGB(%%mm5, %%mm1)
2397         PAVGB(%%mm6, %%mm2)
2398         PAVGB(%%mm7, %%mm3)
2399         PAVGB(%%mm4, %%mm0)
2400         PAVGB(%%mm5, %%mm1)
2401         PAVGB(%%mm6, %%mm2)
2402         PAVGB(%%mm7, %%mm3)
2403         PAVGB(%%mm4, %%mm0)
2404         PAVGB(%%mm5, %%mm1)
2405         PAVGB(%%mm6, %%mm2)
2406         PAVGB(%%mm7, %%mm3)
2407         "movq %%mm0, (%1)                       \n\t" // R0
2408         "movq %%mm1, (%1, %2)                   \n\t" // R1
2409         "movq %%mm2, (%1, %2, 2)                \n\t" // R2
2410         "movq %%mm3, (%1, %%"REG_a")            \n\t" // R3
2411         "movq %%mm0, (%0)                       \n\t" // L0
2412         "movq %%mm1, (%0, %2)                   \n\t" // L1
2413         "movq %%mm2, (%0, %2, 2)                \n\t" // L2
2414         "movq %%mm3, (%0, %%"REG_a")            \n\t" // L3
2415
2416         "movq (%0, %2, 4), %%mm0                \n\t" // L4
2417         "movq (%0, %%"REG_d"), %%mm1            \n\t" // L5
2418         "movq (%0, %%"REG_a", 2), %%mm2         \n\t" // L6
2419         "movq (%0, %%"REG_c"), %%mm3            \n\t" // L7
2420         "movq (%1, %2, 4), %%mm4                \n\t" // R4
2421         "movq (%1, %%"REG_d"), %%mm5            \n\t" // R5
2422         "movq (%1, %%"REG_a", 2), %%mm6         \n\t" // R6
2423         "movq (%1, %%"REG_c"), %%mm7            \n\t" // R7
2424         PAVGB(%%mm4, %%mm0)
2425         PAVGB(%%mm5, %%mm1)
2426         PAVGB(%%mm6, %%mm2)
2427         PAVGB(%%mm7, %%mm3)
2428         PAVGB(%%mm4, %%mm0)
2429         PAVGB(%%mm5, %%mm1)
2430         PAVGB(%%mm6, %%mm2)
2431         PAVGB(%%mm7, %%mm3)
2432         PAVGB(%%mm4, %%mm0)
2433         PAVGB(%%mm5, %%mm1)
2434         PAVGB(%%mm6, %%mm2)
2435         PAVGB(%%mm7, %%mm3)
2436         "movq %%mm0, (%1, %2, 4)                \n\t" // R4
2437         "movq %%mm1, (%1, %%"REG_d")            \n\t" // R5
2438         "movq %%mm2, (%1, %%"REG_a", 2)         \n\t" // R6
2439         "movq %%mm3, (%1, %%"REG_c")            \n\t" // R7
2440         "movq %%mm0, (%0, %2, 4)                \n\t" // L4
2441         "movq %%mm1, (%0, %%"REG_d")            \n\t" // L5
2442         "movq %%mm2, (%0, %%"REG_a", 2)         \n\t" // L6
2443         "movq %%mm3, (%0, %%"REG_c")            \n\t" // L7
2444
2445         "4:                                     \n\t"
2446
2447         :: "r" (src), "r" (tempBlurred), "r"((x86_reg)stride), "m" (tempBlurredPast)
2448         : "%"REG_a, "%"REG_d, "%"REG_c, "memory"
2449     );
2450 #else //TEMPLATE_PP_MMXEXT || TEMPLATE_PP_3DNOW
2451 {
2452     int y;
2453     int d=0;
2454 //    int sysd=0;
2455     int i;
2456
2457     for(y=0; y<8; y++){
2458         int x;
2459         for(x=0; x<8; x++){
2460             int ref= tempBlurred[ x + y*stride ];
2461             int cur= src[ x + y*stride ];
2462             int d1=ref - cur;
2463 //            if(x==0 || x==7) d1+= d1>>1;
2464 //            if(y==0 || y==7) d1+= d1>>1;
2465 //            d+= FFABS(d1);
2466             d+= d1*d1;
2467 //            sysd+= d1;
2468         }
2469     }
2470     i=d;
2471     d=  (
2472         4*d
2473         +(*(tempBlurredPast-256))
2474         +(*(tempBlurredPast-1))+ (*(tempBlurredPast+1))
2475         +(*(tempBlurredPast+256))
2476         +4)>>3;
2477     *tempBlurredPast=i;
2478 //    ((*tempBlurredPast)*3 + d + 2)>>2;
2479
2480 /*
2481 Switch between
2482  1  0  0  0  0  0  0  (0)
2483 64 32 16  8  4  2  1  (1)
2484 64 48 36 27 20 15 11 (33) (approx)
2485 64 56 49 43 37 33 29 (200) (approx)
2486 */
2487     if(d > maxNoise[1]){
2488         if(d < maxNoise[2]){
2489             for(y=0; y<8; y++){
2490                 int x;
2491                 for(x=0; x<8; x++){
2492                     int ref= tempBlurred[ x + y*stride ];
2493                     int cur= src[ x + y*stride ];
2494                     tempBlurred[ x + y*stride ]=
2495                     src[ x + y*stride ]=
2496                         (ref + cur + 1)>>1;
2497                 }
2498             }
2499         }else{
2500             for(y=0; y<8; y++){
2501                 int x;
2502                 for(x=0; x<8; x++){
2503                     tempBlurred[ x + y*stride ]= src[ x + y*stride ];
2504                 }
2505             }
2506         }
2507     }else{
2508         if(d < maxNoise[0]){
2509             for(y=0; y<8; y++){
2510                 int x;
2511                 for(x=0; x<8; x++){
2512                     int ref= tempBlurred[ x + y*stride ];
2513                     int cur= src[ x + y*stride ];
2514                     tempBlurred[ x + y*stride ]=
2515                     src[ x + y*stride ]=
2516                         (ref*7 + cur + 4)>>3;
2517                 }
2518             }
2519         }else{
2520             for(y=0; y<8; y++){
2521                 int x;
2522                 for(x=0; x<8; x++){
2523                     int ref= tempBlurred[ x + y*stride ];
2524                     int cur= src[ x + y*stride ];
2525                     tempBlurred[ x + y*stride ]=
2526                     src[ x + y*stride ]=
2527                         (ref*3 + cur + 2)>>2;
2528                 }
2529             }
2530         }
2531     }
2532 }
2533 #endif //TEMPLATE_PP_MMXEXT || TEMPLATE_PP_3DNOW
2534 }
2535 #endif //TEMPLATE_PP_ALTIVEC
2536
2537 #if TEMPLATE_PP_MMX
2538 /**
2539  * accurate deblock filter
2540  */
2541 static av_always_inline void RENAME(do_a_deblock)(uint8_t *src, int step, int stride, PPContext *c){
2542     int64_t dc_mask, eq_mask, both_masks;
2543     int64_t sums[10*8*2];
2544     src+= step*3; // src points to begin of the 8x8 Block
2545     //{ START_TIMER
2546     __asm__ volatile(
2547         "movq %0, %%mm7                         \n\t"
2548         "movq %1, %%mm6                         \n\t"
2549         : : "m" (c->mmxDcOffset[c->nonBQP]),  "m" (c->mmxDcThreshold[c->nonBQP])
2550         );
2551
2552     __asm__ volatile(
2553         "lea (%2, %3), %%"REG_a"                \n\t"
2554 //      0       1       2       3       4       5       6       7       8       9
2555 //      %1      eax     eax+%2  eax+2%2 %1+4%2  ecx     ecx+%2  ecx+2%2 %1+8%2  ecx+4%2
2556
2557         "movq (%2), %%mm0                       \n\t"
2558         "movq (%%"REG_a"), %%mm1                \n\t"
2559         "movq %%mm1, %%mm3                      \n\t"
2560         "movq %%mm1, %%mm4                      \n\t"
2561         "psubb %%mm1, %%mm0                     \n\t" // mm0 = differnece
2562         "paddb %%mm7, %%mm0                     \n\t"
2563         "pcmpgtb %%mm6, %%mm0                   \n\t"
2564
2565         "movq (%%"REG_a",%3), %%mm2             \n\t"
2566         PMAXUB(%%mm2, %%mm4)
2567         PMINUB(%%mm2, %%mm3, %%mm5)
2568         "psubb %%mm2, %%mm1                     \n\t"
2569         "paddb %%mm7, %%mm1                     \n\t"
2570         "pcmpgtb %%mm6, %%mm1                   \n\t"
2571         "paddb %%mm1, %%mm0                     \n\t"
2572
2573         "movq (%%"REG_a", %3, 2), %%mm1         \n\t"
2574         PMAXUB(%%mm1, %%mm4)
2575         PMINUB(%%mm1, %%mm3, %%mm5)
2576         "psubb %%mm1, %%mm2                     \n\t"
2577         "paddb %%mm7, %%mm2                     \n\t"
2578         "pcmpgtb %%mm6, %%mm2                   \n\t"
2579         "paddb %%mm2, %%mm0                     \n\t"
2580
2581         "lea (%%"REG_a", %3, 4), %%"REG_a"      \n\t"
2582
2583         "movq (%2, %3, 4), %%mm2                \n\t"
2584         PMAXUB(%%mm2, %%mm4)
2585         PMINUB(%%mm2, %%mm3, %%mm5)
2586         "psubb %%mm2, %%mm1                     \n\t"
2587         "paddb %%mm7, %%mm1                     \n\t"
2588         "pcmpgtb %%mm6, %%mm1                   \n\t"
2589         "paddb %%mm1, %%mm0                     \n\t"
2590
2591         "movq (%%"REG_a"), %%mm1                \n\t"
2592         PMAXUB(%%mm1, %%mm4)
2593         PMINUB(%%mm1, %%mm3, %%mm5)
2594         "psubb %%mm1, %%mm2                     \n\t"
2595         "paddb %%mm7, %%mm2                     \n\t"
2596         "pcmpgtb %%mm6, %%mm2                   \n\t"
2597         "paddb %%mm2, %%mm0                     \n\t"
2598
2599         "movq (%%"REG_a", %3), %%mm2            \n\t"
2600         PMAXUB(%%mm2, %%mm4)
2601         PMINUB(%%mm2, %%mm3, %%mm5)
2602         "psubb %%mm2, %%mm1                     \n\t"
2603         "paddb %%mm7, %%mm1                     \n\t"
2604         "pcmpgtb %%mm6, %%mm1                   \n\t"
2605         "paddb %%mm1, %%mm0                     \n\t"
2606
2607         "movq (%%"REG_a", %3, 2), %%mm1         \n\t"
2608         PMAXUB(%%mm1, %%mm4)
2609         PMINUB(%%mm1, %%mm3, %%mm5)
2610         "psubb %%mm1, %%mm2                     \n\t"
2611         "paddb %%mm7, %%mm2                     \n\t"
2612         "pcmpgtb %%mm6, %%mm2                   \n\t"
2613         "paddb %%mm2, %%mm0                     \n\t"
2614
2615         "movq (%2, %3, 8), %%mm2                \n\t"
2616         PMAXUB(%%mm2, %%mm4)
2617         PMINUB(%%mm2, %%mm3, %%mm5)
2618         "psubb %%mm2, %%mm1                     \n\t"
2619         "paddb %%mm7, %%mm1                     \n\t"
2620         "pcmpgtb %%mm6, %%mm1                   \n\t"
2621         "paddb %%mm1, %%mm0                     \n\t"
2622
2623         "movq (%%"REG_a", %3, 4), %%mm1         \n\t"
2624         "psubb %%mm1, %%mm2                     \n\t"
2625         "paddb %%mm7, %%mm2                     \n\t"
2626         "pcmpgtb %%mm6, %%mm2                   \n\t"
2627         "paddb %%mm2, %%mm0                     \n\t"
2628         "psubusb %%mm3, %%mm4                   \n\t"
2629
2630         "pxor %%mm6, %%mm6                      \n\t"
2631         "movq %4, %%mm7                         \n\t" // QP,..., QP
2632         "paddusb %%mm7, %%mm7                   \n\t" // 2QP ... 2QP
2633         "psubusb %%mm4, %%mm7                   \n\t" // Diff >=2QP -> 0
2634         "pcmpeqb %%mm6, %%mm7                   \n\t" // Diff < 2QP -> 0
2635         "pcmpeqb %%mm6, %%mm7                   \n\t" // Diff < 2QP -> 0
2636         "movq %%mm7, %1                         \n\t"
2637
2638         "movq %5, %%mm7                         \n\t"
2639         "punpcklbw %%mm7, %%mm7                 \n\t"
2640         "punpcklbw %%mm7, %%mm7                 \n\t"
2641         "punpcklbw %%mm7, %%mm7                 \n\t"
2642         "psubb %%mm0, %%mm6                     \n\t"
2643         "pcmpgtb %%mm7, %%mm6                   \n\t"
2644         "movq %%mm6, %0                         \n\t"
2645
2646         : "=m" (eq_mask), "=m" (dc_mask)
2647         : "r" (src), "r" ((x86_reg)step), "m" (c->pQPb), "m"(c->ppMode.flatnessThreshold)
2648         : "%"REG_a
2649     );
2650
2651     both_masks = dc_mask & eq_mask;
2652
2653     if(both_masks){
2654         x86_reg offset= -8*step;
2655         int64_t *temp_sums= sums;
2656
2657         __asm__ volatile(
2658             "movq %2, %%mm0                         \n\t"  // QP,..., QP
2659             "pxor %%mm4, %%mm4                      \n\t"
2660
2661             "movq (%0), %%mm6                       \n\t"
2662             "movq (%0, %1), %%mm5                   \n\t"
2663             "movq %%mm5, %%mm1                      \n\t"
2664             "movq %%mm6, %%mm2                      \n\t"
2665             "psubusb %%mm6, %%mm5                   \n\t"
2666             "psubusb %%mm1, %%mm2                   \n\t"
2667             "por %%mm5, %%mm2                       \n\t" // ABS Diff of lines
2668             "psubusb %%mm2, %%mm0                   \n\t" // diff >= QP -> 0
2669             "pcmpeqb %%mm4, %%mm0                   \n\t" // diff >= QP -> FF
2670
2671             "pxor %%mm6, %%mm1                      \n\t"
2672             "pand %%mm0, %%mm1                      \n\t"
2673             "pxor %%mm1, %%mm6                      \n\t"
2674             // 0:QP  6:First
2675
2676             "movq (%0, %1, 8), %%mm5                \n\t"
2677             "add %1, %0                             \n\t" // %0 points to line 1 not 0
2678             "movq (%0, %1, 8), %%mm7                \n\t"
2679             "movq %%mm5, %%mm1                      \n\t"
2680             "movq %%mm7, %%mm2                      \n\t"
2681             "psubusb %%mm7, %%mm5                   \n\t"
2682             "psubusb %%mm1, %%mm2                   \n\t"
2683             "por %%mm5, %%mm2                       \n\t" // ABS Diff of lines
2684             "movq %2, %%mm0                         \n\t"  // QP,..., QP
2685             "psubusb %%mm2, %%mm0                   \n\t" // diff >= QP -> 0
2686             "pcmpeqb %%mm4, %%mm0                   \n\t" // diff >= QP -> FF
2687
2688             "pxor %%mm7, %%mm1                      \n\t"
2689             "pand %%mm0, %%mm1                      \n\t"
2690             "pxor %%mm1, %%mm7                      \n\t"
2691
2692             "movq %%mm6, %%mm5                      \n\t"
2693             "punpckhbw %%mm4, %%mm6                 \n\t"
2694             "punpcklbw %%mm4, %%mm5                 \n\t"
2695             // 4:0 5/6:First 7:Last
2696
2697             "movq %%mm5, %%mm0                      \n\t"
2698             "movq %%mm6, %%mm1                      \n\t"
2699             "psllw $2, %%mm0                        \n\t"
2700             "psllw $2, %%mm1                        \n\t"
2701             "paddw "MANGLE(w04)", %%mm0             \n\t"
2702             "paddw "MANGLE(w04)", %%mm1             \n\t"
2703
2704 #define NEXT\
2705             "movq (%0), %%mm2                       \n\t"\
2706             "movq (%0), %%mm3                       \n\t"\
2707             "add %1, %0                             \n\t"\
2708             "punpcklbw %%mm4, %%mm2                 \n\t"\
2709             "punpckhbw %%mm4, %%mm3                 \n\t"\
2710             "paddw %%mm2, %%mm0                     \n\t"\
2711             "paddw %%mm3, %%mm1                     \n\t"
2712
2713 #define PREV\
2714             "movq (%0), %%mm2                       \n\t"\
2715             "movq (%0), %%mm3                       \n\t"\
2716             "add %1, %0                             \n\t"\
2717             "punpcklbw %%mm4, %%mm2                 \n\t"\
2718             "punpckhbw %%mm4, %%mm3                 \n\t"\
2719             "psubw %%mm2, %%mm0                     \n\t"\
2720             "psubw %%mm3, %%mm1                     \n\t"
2721
2722
2723             NEXT //0
2724             NEXT //1
2725             NEXT //2
2726             "movq %%mm0, (%3)                       \n\t"
2727             "movq %%mm1, 8(%3)                      \n\t"
2728
2729             NEXT //3
2730             "psubw %%mm5, %%mm0                     \n\t"
2731             "psubw %%mm6, %%mm1                     \n\t"
2732             "movq %%mm0, 16(%3)                     \n\t"
2733             "movq %%mm1, 24(%3)                     \n\t"
2734
2735             NEXT //4
2736             "psubw %%mm5, %%mm0                     \n\t"
2737             "psubw %%mm6, %%mm1                     \n\t"
2738             "movq %%mm0, 32(%3)                     \n\t"
2739             "movq %%mm1, 40(%3)                     \n\t"
2740
2741             NEXT //5
2742             "psubw %%mm5, %%mm0                     \n\t"
2743             "psubw %%mm6, %%mm1                     \n\t"
2744             "movq %%mm0, 48(%3)                     \n\t"
2745             "movq %%mm1, 56(%3)                     \n\t"
2746
2747             NEXT //6
2748             "psubw %%mm5, %%mm0                     \n\t"
2749             "psubw %%mm6, %%mm1                     \n\t"
2750             "movq %%mm0, 64(%3)                     \n\t"
2751             "movq %%mm1, 72(%3)                     \n\t"
2752
2753             "movq %%mm7, %%mm6                      \n\t"
2754             "punpckhbw %%mm4, %%mm7                 \n\t"
2755             "punpcklbw %%mm4, %%mm6                 \n\t"
2756
2757             NEXT //7
2758             "mov %4, %0                             \n\t"
2759             "add %1, %0                             \n\t"
2760             PREV //0
2761             "movq %%mm0, 80(%3)                     \n\t"
2762             "movq %%mm1, 88(%3)                     \n\t"
2763
2764             PREV //1
2765             "paddw %%mm6, %%mm0                     \n\t"
2766             "paddw %%mm7, %%mm1                     \n\t"
2767             "movq %%mm0, 96(%3)                     \n\t"
2768             "movq %%mm1, 104(%3)                    \n\t"
2769
2770             PREV //2
2771             "paddw %%mm6, %%mm0                     \n\t"
2772             "paddw %%mm7, %%mm1                     \n\t"
2773             "movq %%mm0, 112(%3)                    \n\t"
2774             "movq %%mm1, 120(%3)                    \n\t"
2775
2776             PREV //3
2777             "paddw %%mm6, %%mm0                     \n\t"
2778             "paddw %%mm7, %%mm1                     \n\t"
2779             "movq %%mm0, 128(%3)                    \n\t"
2780             "movq %%mm1, 136(%3)                    \n\t"
2781
2782             PREV //4
2783             "paddw %%mm6, %%mm0                     \n\t"
2784             "paddw %%mm7, %%mm1                     \n\t"
2785             "movq %%mm0, 144(%3)                    \n\t"
2786             "movq %%mm1, 152(%3)                    \n\t"
2787
2788             "mov %4, %0                             \n\t" //FIXME
2789
2790             : "+&r"(src)
2791             : "r" ((x86_reg)step), "m" (c->pQPb), "r"(sums), "g"(src)
2792         );
2793
2794         src+= step; // src points to begin of the 8x8 Block
2795
2796         __asm__ volatile(
2797             "movq %4, %%mm6                         \n\t"
2798             "pcmpeqb %%mm5, %%mm5                   \n\t"
2799             "pxor %%mm6, %%mm5                      \n\t"
2800             "pxor %%mm7, %%mm7                      \n\t"
2801
2802             "1:                                     \n\t"
2803             "movq (%1), %%mm0                       \n\t"
2804             "movq 8(%1), %%mm1                      \n\t"
2805             "paddw 32(%1), %%mm0                    \n\t"
2806             "paddw 40(%1), %%mm1                    \n\t"
2807             "movq (%0, %3), %%mm2                   \n\t"
2808             "movq %%mm2, %%mm3                      \n\t"
2809             "movq %%mm2, %%mm4                      \n\t"
2810             "punpcklbw %%mm7, %%mm2                 \n\t"
2811             "punpckhbw %%mm7, %%mm3                 \n\t"
2812             "paddw %%mm2, %%mm0                     \n\t"
2813             "paddw %%mm3, %%mm1                     \n\t"
2814             "paddw %%mm2, %%mm0                     \n\t"
2815             "paddw %%mm3, %%mm1                     \n\t"
2816             "psrlw $4, %%mm0                        \n\t"
2817             "psrlw $4, %%mm1                        \n\t"
2818             "packuswb %%mm1, %%mm0                  \n\t"
2819             "pand %%mm6, %%mm0                      \n\t"
2820             "pand %%mm5, %%mm4                      \n\t"
2821             "por %%mm4, %%mm0                       \n\t"
2822             "movq %%mm0, (%0, %3)                   \n\t"
2823             "add $16, %1                            \n\t"
2824             "add %2, %0                             \n\t"
2825             " js 1b                                 \n\t"
2826
2827             : "+r"(offset), "+r"(temp_sums)
2828             : "r" ((x86_reg)step), "r"(src - offset), "m"(both_masks)
2829         );
2830     }else
2831         src+= step; // src points to begin of the 8x8 Block
2832
2833     if(eq_mask != -1LL){
2834         uint8_t *temp_src= src;
2835         DECLARE_ALIGNED(8, uint64_t, tmp)[4]; // make space for 4 8-byte vars
2836         __asm__ volatile(
2837             "pxor %%mm7, %%mm7                      \n\t"
2838 //      0       1       2       3       4       5       6       7       8       9
2839 //      %0      eax     eax+%1  eax+2%1 %0+4%1  ecx     ecx+%1  ecx+2%1 %1+8%1  ecx+4%1
2840
2841             "movq (%0), %%mm0                       \n\t"
2842             "movq %%mm0, %%mm1                      \n\t"
2843             "punpcklbw %%mm7, %%mm0                 \n\t" // low part of line 0
2844             "punpckhbw %%mm7, %%mm1                 \n\t" // high part of line 0
2845
2846             "movq (%0, %1), %%mm2                   \n\t"
2847             "lea (%0, %1, 2), %%"REG_a"             \n\t"
2848             "movq %%mm2, %%mm3                      \n\t"
2849             "punpcklbw %%mm7, %%mm2                 \n\t" // low part of line 1
2850             "punpckhbw %%mm7, %%mm3                 \n\t" // high part of line 1
2851
2852             "movq (%%"REG_a"), %%mm4                \n\t"
2853             "movq %%mm4, %%mm5                      \n\t"
2854             "punpcklbw %%mm7, %%mm4                 \n\t" // low part of line 2
2855             "punpckhbw %%mm7, %%mm5                 \n\t" // high part of line 2
2856
2857             "paddw %%mm0, %%mm0                     \n\t" // 2L0
2858             "paddw %%mm1, %%mm1                     \n\t" // 2H0
2859             "psubw %%mm4, %%mm2                     \n\t" // L1 - L2
2860             "psubw %%mm5, %%mm3                     \n\t" // H1 - H2
2861             "psubw %%mm2, %%mm0                     \n\t" // 2L0 - L1 + L2
2862             "psubw %%mm3, %%mm1                     \n\t" // 2H0 - H1 + H2
2863
2864             "psllw $2, %%mm2                        \n\t" // 4L1 - 4L2
2865             "psllw $2, %%mm3                        \n\t" // 4H1 - 4H2
2866             "psubw %%mm2, %%mm0                     \n\t" // 2L0 - 5L1 + 5L2
2867             "psubw %%mm3, %%mm1                     \n\t" // 2H0 - 5H1 + 5H2
2868
2869             "movq (%%"REG_a", %1), %%mm2            \n\t"
2870             "movq %%mm2, %%mm3                      \n\t"
2871             "punpcklbw %%mm7, %%mm2                 \n\t" // L3
2872             "punpckhbw %%mm7, %%mm3                 \n\t" // H3
2873
2874             "psubw %%mm2, %%mm0                     \n\t" // 2L0 - 5L1 + 5L2 - L3
2875             "psubw %%mm3, %%mm1                     \n\t" // 2H0 - 5H1 + 5H2 - H3
2876             "psubw %%mm2, %%mm0                     \n\t" // 2L0 - 5L1 + 5L2 - 2L3
2877             "psubw %%mm3, %%mm1                     \n\t" // 2H0 - 5H1 + 5H2 - 2H3
2878             "movq %%mm0, (%4)                       \n\t" // 2L0 - 5L1 + 5L2 - 2L3
2879             "movq %%mm1, 8(%4)                      \n\t" // 2H0 - 5H1 + 5H2 - 2H3
2880
2881             "movq (%%"REG_a", %1, 2), %%mm0         \n\t"
2882             "movq %%mm0, %%mm1                      \n\t"
2883             "punpcklbw %%mm7, %%mm0                 \n\t" // L4
2884             "punpckhbw %%mm7, %%mm1                 \n\t" // H4
2885
2886             "psubw %%mm0, %%mm2                     \n\t" // L3 - L4
2887             "psubw %%mm1, %%mm3                     \n\t" // H3 - H4
2888             "movq %%mm2, 16(%4)                     \n\t" // L3 - L4
2889             "movq %%mm3, 24(%4)                     \n\t" // H3 - H4
2890             "paddw %%mm4, %%mm4                     \n\t" // 2L2
2891             "paddw %%mm5, %%mm5                     \n\t" // 2H2
2892             "psubw %%mm2, %%mm4                     \n\t" // 2L2 - L3 + L4
2893             "psubw %%mm3, %%mm5                     \n\t" // 2H2 - H3 + H4
2894
2895             "lea (%%"REG_a", %1), %0                \n\t"
2896             "psllw $2, %%mm2                        \n\t" // 4L3 - 4L4
2897             "psllw $2, %%mm3                        \n\t" // 4H3 - 4H4
2898             "psubw %%mm2, %%mm4                     \n\t" // 2L2 - 5L3 + 5L4
2899             "psubw %%mm3, %%mm5                     \n\t" // 2H2 - 5H3 + 5H4
2900 //50 opcodes so far
2901             "movq (%0, %1, 2), %%mm2                \n\t"
2902             "movq %%mm2, %%mm3                      \n\t"
2903             "punpcklbw %%mm7, %%mm2                 \n\t" // L5
2904             "punpckhbw %%mm7, %%mm3                 \n\t" // H5
2905             "psubw %%mm2, %%mm4                     \n\t" // 2L2 - 5L3 + 5L4 - L5
2906             "psubw %%mm3, %%mm5                     \n\t" // 2H2 - 5H3 + 5H4 - H5
2907             "psubw %%mm2, %%mm4                     \n\t" // 2L2 - 5L3 + 5L4 - 2L5
2908             "psubw %%mm3, %%mm5                     \n\t" // 2H2 - 5H3 + 5H4 - 2H5
2909
2910             "movq (%%"REG_a", %1, 4), %%mm6         \n\t"
2911             "punpcklbw %%mm7, %%mm6                 \n\t" // L6
2912             "psubw %%mm6, %%mm2                     \n\t" // L5 - L6
2913             "movq (%%"REG_a", %1, 4), %%mm6         \n\t"
2914             "punpckhbw %%mm7, %%mm6                 \n\t" // H6
2915             "psubw %%mm6, %%mm3                     \n\t" // H5 - H6
2916
2917             "paddw %%mm0, %%mm0                     \n\t" // 2L4
2918             "paddw %%mm1, %%mm1                     \n\t" // 2H4
2919             "psubw %%mm2, %%mm0                     \n\t" // 2L4 - L5 + L6
2920             "psubw %%mm3, %%mm1                     \n\t" // 2H4 - H5 + H6
2921
2922             "psllw $2, %%mm2                        \n\t" // 4L5 - 4L6
2923             "psllw $2, %%mm3                        \n\t" // 4H5 - 4H6
2924             "psubw %%mm2, %%mm0                     \n\t" // 2L4 - 5L5 + 5L6
2925             "psubw %%mm3, %%mm1                     \n\t" // 2H4 - 5H5 + 5H6
2926
2927             "movq (%0, %1, 4), %%mm2                \n\t"
2928             "movq %%mm2, %%mm3                      \n\t"
2929             "punpcklbw %%mm7, %%mm2                 \n\t" // L7
2930             "punpckhbw %%mm7, %%mm3                 \n\t" // H7
2931
2932             "paddw %%mm2, %%mm2                     \n\t" // 2L7
2933             "paddw %%mm3, %%mm3                     \n\t" // 2H7
2934             "psubw %%mm2, %%mm0                     \n\t" // 2L4 - 5L5 + 5L6 - 2L7
2935             "psubw %%mm3, %%mm1                     \n\t" // 2H4 - 5H5 + 5H6 - 2H7
2936
2937             "movq (%4), %%mm2                       \n\t" // 2L0 - 5L1 + 5L2 - 2L3
2938             "movq 8(%4), %%mm3                      \n\t" // 2H0 - 5H1 + 5H2 - 2H3
2939
2940 #if TEMPLATE_PP_MMXEXT
2941             "movq %%mm7, %%mm6                      \n\t" // 0
2942             "psubw %%mm0, %%mm6                     \n\t"
2943             "pmaxsw %%mm6, %%mm0                    \n\t" // |2L4 - 5L5 + 5L6 - 2L7|
2944             "movq %%mm7, %%mm6                      \n\t" // 0
2945             "psubw %%mm1, %%mm6                     \n\t"
2946             "pmaxsw %%mm6, %%mm1                    \n\t" // |2H4 - 5H5 + 5H6 - 2H7|
2947             "movq %%mm7, %%mm6                      \n\t" // 0
2948             "psubw %%mm2, %%mm6                     \n\t"
2949             "pmaxsw %%mm6, %%mm2                    \n\t" // |2L0 - 5L1 + 5L2 - 2L3|
2950             "movq %%mm7, %%mm6                      \n\t" // 0
2951             "psubw %%mm3, %%mm6                     \n\t"
2952             "pmaxsw %%mm6, %%mm3                    \n\t" // |2H0 - 5H1 + 5H2 - 2H3|
2953 #else
2954             "movq %%mm7, %%mm6                      \n\t" // 0
2955             "pcmpgtw %%mm0, %%mm6                   \n\t"
2956             "pxor %%mm6, %%mm0                      \n\t"
2957             "psubw %%mm6, %%mm0                     \n\t" // |2L4 - 5L5 + 5L6 - 2L7|
2958             "movq %%mm7, %%mm6                      \n\t" // 0
2959             "pcmpgtw %%mm1, %%mm6                   \n\t"
2960             "pxor %%mm6, %%mm1                      \n\t"
2961             "psubw %%mm6, %%mm1                     \n\t" // |2H4 - 5H5 + 5H6 - 2H7|
2962             "movq %%mm7, %%mm6                      \n\t" // 0
2963             "pcmpgtw %%mm2, %%mm6                   \n\t"
2964             "pxor %%mm6, %%mm2                      \n\t"
2965             "psubw %%mm6, %%mm2                     \n\t" // |2L0 - 5L1 + 5L2 - 2L3|
2966             "movq %%mm7, %%mm6                      \n\t" // 0
2967             "pcmpgtw %%mm3, %%mm6                   \n\t"
2968             "pxor %%mm6, %%mm3                      \n\t"
2969             "psubw %%mm6, %%mm3                     \n\t" // |2H0 - 5H1 + 5H2 - 2H3|
2970 #endif
2971
2972 #if TEMPLATE_PP_MMXEXT
2973             "pminsw %%mm2, %%mm0                    \n\t"
2974             "pminsw %%mm3, %%mm1                    \n\t"
2975 #else
2976             "movq %%mm0, %%mm6                      \n\t"
2977             "psubusw %%mm2, %%mm6                   \n\t"
2978             "psubw %%mm6, %%mm0                     \n\t"
2979             "movq %%mm1, %%mm6                      \n\t"
2980             "psubusw %%mm3, %%mm6                   \n\t"
2981             "psubw %%mm6, %%mm1                     \n\t"
2982 #endif
2983
2984             "movd %2, %%mm2                         \n\t" // QP
2985             "punpcklbw %%mm7, %%mm2                 \n\t"
2986
2987             "movq %%mm7, %%mm6                      \n\t" // 0
2988             "pcmpgtw %%mm4, %%mm6                   \n\t" // sign(2L2 - 5L3 + 5L4 - 2L5)
2989             "pxor %%mm6, %%mm4                      \n\t"
2990             "psubw %%mm6, %%mm4                     \n\t" // |2L2 - 5L3 + 5L4 - 2L5|
2991             "pcmpgtw %%mm5, %%mm7                   \n\t" // sign(2H2 - 5H3 + 5H4 - 2H5)
2992             "pxor %%mm7, %%mm5                      \n\t"
2993             "psubw %%mm7, %%mm5                     \n\t" // |2H2 - 5H3 + 5H4 - 2H5|
2994 // 100 opcodes
2995             "psllw $3, %%mm2                        \n\t" // 8QP
2996             "movq %%mm2, %%mm3                      \n\t" // 8QP
2997             "pcmpgtw %%mm4, %%mm2                   \n\t"
2998             "pcmpgtw %%mm5, %%mm3                   \n\t"
2999             "pand %%mm2, %%mm4                      \n\t"
3000             "pand %%mm3, %%mm5                      \n\t"
3001
3002
3003             "psubusw %%mm0, %%mm4                   \n\t" // hd
3004             "psubusw %%mm1, %%mm5                   \n\t" // ld
3005
3006
3007             "movq "MANGLE(w05)", %%mm2              \n\t" // 5
3008             "pmullw %%mm2, %%mm4                    \n\t"
3009             "pmullw %%mm2, %%mm5                    \n\t"
3010             "movq "MANGLE(w20)", %%mm2              \n\t" // 32
3011             "paddw %%mm2, %%mm4                     \n\t"
3012             "paddw %%mm2, %%mm5                     \n\t"
3013             "psrlw $6, %%mm4                        \n\t"
3014             "psrlw $6, %%mm5                        \n\t"
3015
3016             "movq 16(%4), %%mm0                     \n\t" // L3 - L4
3017             "movq 24(%4), %%mm1                     \n\t" // H3 - H4
3018
3019             "pxor %%mm2, %%mm2                      \n\t"
3020             "pxor %%mm3, %%mm3                      \n\t"
3021
3022             "pcmpgtw %%mm0, %%mm2                   \n\t" // sign (L3-L4)
3023             "pcmpgtw %%mm1, %%mm3                   \n\t" // sign (H3-H4)
3024             "pxor %%mm2, %%mm0                      \n\t"
3025             "pxor %%mm3, %%mm1                      \n\t"
3026             "psubw %%mm2, %%mm0                     \n\t" // |L3-L4|
3027             "psubw %%mm3, %%mm1                     \n\t" // |H3-H4|
3028             "psrlw $1, %%mm0                        \n\t" // |L3 - L4|/2
3029             "psrlw $1, %%mm1                        \n\t" // |H3 - H4|/2
3030
3031             "pxor %%mm6, %%mm2                      \n\t"
3032             "pxor %%mm7, %%mm3                      \n\t"
3033             "pand %%mm2, %%mm4                      \n\t"
3034             "pand %%mm3, %%mm5                      \n\t"
3035
3036 #if TEMPLATE_PP_MMXEXT
3037             "pminsw %%mm0, %%mm4                    \n\t"
3038             "pminsw %%mm1, %%mm5                    \n\t"
3039 #else
3040             "movq %%mm4, %%mm2                      \n\t"
3041             "psubusw %%mm0, %%mm2                   \n\t"
3042             "psubw %%mm2, %%mm4                     \n\t"
3043             "movq %%mm5, %%mm2                      \n\t"
3044             "psubusw %%mm1, %%mm2                   \n\t"
3045             "psubw %%mm2, %%mm5                     \n\t"
3046 #endif
3047             "pxor %%mm6, %%mm4                      \n\t"
3048             "pxor %%mm7, %%mm5                      \n\t"
3049             "psubw %%mm6, %%mm4                     \n\t"
3050             "psubw %%mm7, %%mm5                     \n\t"
3051             "packsswb %%mm5, %%mm4                  \n\t"
3052             "movq %3, %%mm1                         \n\t"
3053             "pandn %%mm4, %%mm1                     \n\t"
3054             "movq (%0), %%mm0                       \n\t"
3055             "paddb   %%mm1, %%mm0                   \n\t"
3056             "movq %%mm0, (%0)                       \n\t"
3057             "movq (%0, %1), %%mm0                   \n\t"
3058             "psubb %%mm1, %%mm0                     \n\t"
3059             "movq %%mm0, (%0, %1)                   \n\t"
3060
3061             : "+r" (temp_src)
3062             : "r" ((x86_reg)step), "m" (c->pQPb), "m"(eq_mask), "r"(tmp)
3063             : "%"REG_a
3064         );
3065     }
3066 /*if(step==16){
3067     STOP_TIMER("step16")
3068 }else{
3069     STOP_TIMER("stepX")
3070 }
3071     } */
3072 }
3073 #endif //TEMPLATE_PP_MMX
3074
3075 static void RENAME(postProcess)(const uint8_t src[], int srcStride, uint8_t dst[], int dstStride, int width, int height,
3076                                 const QP_STORE_T QPs[], int QPStride, int isColor, PPContext *c);
3077
3078 /**
3079  * Copy a block from src to dst and fixes the blacklevel.
3080  * levelFix == 0 -> do not touch the brighness & contrast
3081  */
3082 #undef REAL_SCALED_CPY
3083 #undef SCALED_CPY
3084
3085 static inline void RENAME(blockCopy)(uint8_t dst[], int dstStride, const uint8_t src[], int srcStride,
3086                                      int levelFix, int64_t *packedOffsetAndScale)
3087 {
3088 #if !TEMPLATE_PP_MMX
3089     int i;
3090 #endif
3091     if(levelFix){
3092 #if TEMPLATE_PP_MMX
3093     __asm__ volatile(
3094         "movq (%%"REG_a"), %%mm2        \n\t" // packedYOffset
3095         "movq 8(%%"REG_a"), %%mm3       \n\t" // packedYScale
3096         "lea (%2,%4), %%"REG_a"         \n\t"
3097         "lea (%3,%5), %%"REG_d"         \n\t"
3098         "pxor %%mm4, %%mm4              \n\t"
3099 #if TEMPLATE_PP_MMXEXT
3100 #define REAL_SCALED_CPY(src1, src2, dst1, dst2)                                                \
3101         "movq " #src1 ", %%mm0          \n\t"\
3102         "movq " #src1 ", %%mm5          \n\t"\
3103         "movq " #src2 ", %%mm1          \n\t"\
3104         "movq " #src2 ", %%mm6          \n\t"\
3105         "punpcklbw %%mm0, %%mm0         \n\t"\
3106         "punpckhbw %%mm5, %%mm5         \n\t"\
3107         "punpcklbw %%mm1, %%mm1         \n\t"\
3108         "punpckhbw %%mm6, %%mm6         \n\t"\
3109         "pmulhuw %%mm3, %%mm0           \n\t"\
3110         "pmulhuw %%mm3, %%mm5           \n\t"\
3111         "pmulhuw %%mm3, %%mm1           \n\t"\
3112         "pmulhuw %%mm3, %%mm6           \n\t"\
3113         "psubw %%mm2, %%mm0             \n\t"\
3114         "psubw %%mm2, %%mm5             \n\t"\
3115         "psubw %%mm2, %%mm1             \n\t"\
3116         "psubw %%mm2, %%mm6             \n\t"\
3117         "packuswb %%mm5, %%mm0          \n\t"\
3118         "packuswb %%mm6, %%mm1          \n\t"\
3119         "movq %%mm0, " #dst1 "          \n\t"\
3120         "movq %%mm1, " #dst2 "          \n\t"\
3121
3122 #else //TEMPLATE_PP_MMXEXT
3123 #define REAL_SCALED_CPY(src1, src2, dst1, dst2)                                        \
3124         "movq " #src1 ", %%mm0          \n\t"\
3125         "movq " #src1 ", %%mm5          \n\t"\
3126         "punpcklbw %%mm4, %%mm0         \n\t"\
3127         "punpckhbw %%mm4, %%mm5         \n\t"\
3128         "psubw %%mm2, %%mm0             \n\t"\
3129         "psubw %%mm2, %%mm5             \n\t"\
3130         "movq " #src2 ", %%mm1          \n\t"\
3131         "psllw $6, %%mm0                \n\t"\
3132         "psllw $6, %%mm5                \n\t"\
3133         "pmulhw %%mm3, %%mm0            \n\t"\
3134         "movq " #src2 ", %%mm6          \n\t"\
3135         "pmulhw %%mm3, %%mm5            \n\t"\
3136         "punpcklbw %%mm4, %%mm1         \n\t"\
3137         "punpckhbw %%mm4, %%mm6         \n\t"\
3138         "psubw %%mm2, %%mm1             \n\t"\
3139         "psubw %%mm2, %%mm6             \n\t"\
3140         "psllw $6, %%mm1                \n\t"\
3141         "psllw $6, %%mm6                \n\t"\
3142         "pmulhw %%mm3, %%mm1            \n\t"\
3143         "pmulhw %%mm3, %%mm6            \n\t"\
3144         "packuswb %%mm5, %%mm0          \n\t"\
3145         "packuswb %%mm6, %%mm1          \n\t"\
3146         "movq %%mm0, " #dst1 "          \n\t"\
3147         "movq %%mm1, " #dst2 "          \n\t"\
3148
3149 #endif //TEMPLATE_PP_MMXEXT
3150 #define SCALED_CPY(src1, src2, dst1, dst2)\
3151    REAL_SCALED_CPY(src1, src2, dst1, dst2)
3152
3153 SCALED_CPY((%2)       , (%2, %4)      , (%3)       , (%3, %5))
3154 SCALED_CPY((%2, %4, 2), (%%REGa, %4, 2), (%3, %5, 2), (%%REGd, %5, 2))
3155 SCALED_CPY((%2, %4, 4), (%%REGa, %4, 4), (%3, %5, 4), (%%REGd, %5, 4))
3156         "lea (%%"REG_a",%4,4), %%"REG_a"        \n\t"
3157         "lea (%%"REG_d",%5,4), %%"REG_d"        \n\t"
3158 SCALED_CPY((%%REGa, %4), (%%REGa, %4, 2), (%%REGd, %5), (%%REGd, %5, 2))
3159
3160
3161         : "=&a" (packedOffsetAndScale)
3162         : "0" (packedOffsetAndScale),
3163         "r"(src),
3164         "r"(dst),
3165         "r" ((x86_reg)srcStride),
3166         "r" ((x86_reg)dstStride)
3167         : "%"REG_d
3168     );
3169 #else //TEMPLATE_PP_MMX
3170     for(i=0; i<8; i++)
3171         memcpy( &(dst[dstStride*i]),
3172                 &(src[srcStride*i]), BLOCK_SIZE);
3173 #endif //TEMPLATE_PP_MMX
3174     }else{
3175 #if TEMPLATE_PP_MMX
3176     __asm__ volatile(
3177         "lea (%0,%2), %%"REG_a"                 \n\t"
3178         "lea (%1,%3), %%"REG_d"                 \n\t"
3179
3180 #define REAL_SIMPLE_CPY(src1, src2, dst1, dst2)                              \
3181         "movq " #src1 ", %%mm0          \n\t"\
3182         "movq " #src2 ", %%mm1          \n\t"\
3183         "movq %%mm0, " #dst1 "          \n\t"\
3184         "movq %%mm1, " #dst2 "          \n\t"\
3185
3186 #define SIMPLE_CPY(src1, src2, dst1, dst2)\
3187    REAL_SIMPLE_CPY(src1, src2, dst1, dst2)
3188
3189 SIMPLE_CPY((%0)       , (%0, %2)       , (%1)       , (%1, %3))
3190 SIMPLE_CPY((%0, %2, 2), (%%REGa, %2, 2), (%1, %3, 2), (%%REGd, %3, 2))
3191 SIMPLE_CPY((%0, %2, 4), (%%REGa, %2, 4), (%1, %3, 4), (%%REGd, %3, 4))
3192         "lea (%%"REG_a",%2,4), %%"REG_a"        \n\t"
3193         "lea (%%"REG_d",%3,4), %%"REG_d"        \n\t"
3194 SIMPLE_CPY((%%REGa, %2), (%%REGa, %2, 2), (%%REGd, %3), (%%REGd, %3, 2))
3195
3196         : : "r" (src),
3197         "r" (dst),
3198         "r" ((x86_reg)srcStride),
3199         "r" ((x86_reg)dstStride)
3200         : "%"REG_a, "%"REG_d
3201     );
3202 #else //TEMPLATE_PP_MMX
3203     for(i=0; i<8; i++)
3204         memcpy( &(dst[dstStride*i]),
3205                 &(src[srcStride*i]), BLOCK_SIZE);
3206 #endif //TEMPLATE_PP_MMX
3207     }
3208 }
3209
3210 /**
3211  * Duplicate the given 8 src pixels ? times upward
3212  */
3213 static inline void RENAME(duplicate)(uint8_t src[], int stride)
3214 {
3215 #if TEMPLATE_PP_MMX
3216     __asm__ volatile(
3217         "movq (%0), %%mm0               \n\t"
3218         "add %1, %0                     \n\t"
3219         "movq %%mm0, (%0)               \n\t"
3220         "movq %%mm0, (%0, %1)           \n\t"
3221         "movq %%mm0, (%0, %1, 2)        \n\t"
3222         : "+r" (src)
3223         : "r" ((x86_reg)-stride)
3224     );
3225 #else
3226     int i;
3227     uint8_t *p=src;
3228     for(i=0; i<3; i++){
3229         p-= stride;
3230         memcpy(p, src, 8);
3231     }
3232 #endif
3233 }
3234
3235 /**
3236  * Filter array of bytes (Y or U or V values)
3237  */
3238 static void RENAME(postProcess)(const uint8_t src[], int srcStride, uint8_t dst[], int dstStride, int width, int height,
3239                                 const QP_STORE_T QPs[], int QPStride, int isColor, PPContext *c2)
3240 {
3241     DECLARE_ALIGNED(8, PPContext, c)= *c2; //copy to stack for faster access
3242     int x,y;
3243 #ifdef TEMPLATE_PP_TIME_MODE
3244     const int mode= TEMPLATE_PP_TIME_MODE;
3245 #else
3246     const int mode= isColor ? c.ppMode.chromMode : c.ppMode.lumMode;
3247 #endif
3248     int black=0, white=255; // blackest black and whitest white in the picture
3249     int QPCorrecture= 256*256;
3250
3251     int copyAhead;
3252 #if TEMPLATE_PP_MMX
3253     int i;
3254 #endif
3255
3256     const int qpHShift= isColor ? 4-c.hChromaSubSample : 4;
3257     const int qpVShift= isColor ? 4-c.vChromaSubSample : 4;
3258
3259     //FIXME remove
3260     uint64_t * const yHistogram= c.yHistogram;
3261     uint8_t * const tempSrc= srcStride > 0 ? c.tempSrc : c.tempSrc - 23*srcStride;
3262     uint8_t * const tempDst= dstStride > 0 ? c.tempDst : c.tempDst - 23*dstStride;
3263     //const int mbWidth= isColor ? (width+7)>>3 : (width+15)>>4;
3264
3265 #if TEMPLATE_PP_MMX
3266     for(i=0; i<57; i++){
3267         int offset= ((i*c.ppMode.baseDcDiff)>>8) + 1;
3268         int threshold= offset*2 + 1;
3269         c.mmxDcOffset[i]= 0x7F - offset;
3270         c.mmxDcThreshold[i]= 0x7F - threshold;
3271         c.mmxDcOffset[i]*= 0x0101010101010101LL;
3272         c.mmxDcThreshold[i]*= 0x0101010101010101LL;
3273     }
3274 #endif
3275
3276     if(mode & CUBIC_IPOL_DEINT_FILTER) copyAhead=16;
3277     else if(   (mode & LINEAR_BLEND_DEINT_FILTER)
3278             || (mode & FFMPEG_DEINT_FILTER)
3279             || (mode & LOWPASS5_DEINT_FILTER)) copyAhead=14;
3280     else if(   (mode & V_DEBLOCK)
3281             || (mode & LINEAR_IPOL_DEINT_FILTER)
3282             || (mode & MEDIAN_DEINT_FILTER)
3283             || (mode & V_A_DEBLOCK)) copyAhead=13;
3284     else if(mode & V_X1_FILTER) copyAhead=11;
3285 //    else if(mode & V_RK1_FILTER) copyAhead=10;
3286     else if(mode & DERING) copyAhead=9;
3287     else copyAhead=8;
3288
3289     copyAhead-= 8;
3290
3291     if(!isColor){
3292         uint64_t sum= 0;
3293         int i;
3294         uint64_t maxClipped;
3295         uint64_t clipped;
3296         double scale;
3297
3298         c.frameNum++;
3299         // first frame is fscked so we ignore it
3300         if(c.frameNum == 1) yHistogram[0]= width*(uint64_t)height/64*15/256;
3301
3302         for(i=0; i<256; i++){
3303             sum+= yHistogram[i];
3304         }
3305
3306         /* We always get a completely black picture first. */
3307         maxClipped= (uint64_t)(sum * c.ppMode.maxClippedThreshold);
3308
3309         clipped= sum;
3310         for(black=255; black>0; black--){
3311             if(clipped < maxClipped) break;
3312             clipped-= yHistogram[black];
3313         }
3314
3315         clipped= sum;
3316         for(white=0; white<256; white++){
3317             if(clipped < maxClipped) break;
3318             clipped-= yHistogram[white];
3319         }
3320
3321         scale= (double)(c.ppMode.maxAllowedY - c.ppMode.minAllowedY) / (double)(white-black);
3322
3323 #if TEMPLATE_PP_MMXEXT
3324         c.packedYScale= (uint16_t)(scale*256.0 + 0.5);
3325         c.packedYOffset= (((black*c.packedYScale)>>8) - c.ppMode.minAllowedY) & 0xFFFF;
3326 #else
3327         c.packedYScale= (uint16_t)(scale*1024.0 + 0.5);
3328         c.packedYOffset= (black - c.ppMode.minAllowedY) & 0xFFFF;
3329 #endif
3330
3331         c.packedYOffset|= c.packedYOffset<<32;
3332         c.packedYOffset|= c.packedYOffset<<16;
3333
3334         c.packedYScale|= c.packedYScale<<32;
3335         c.packedYScale|= c.packedYScale<<16;
3336
3337         if(mode & LEVEL_FIX)        QPCorrecture= (int)(scale*256*256 + 0.5);
3338         else                        QPCorrecture= 256*256;
3339     }else{
3340         c.packedYScale= 0x0100010001000100LL;
3341         c.packedYOffset= 0;
3342         QPCorrecture= 256*256;
3343     }
3344
3345     /* copy & deinterlace first row of blocks */
3346     y=-BLOCK_SIZE;
3347     {
3348         const uint8_t *srcBlock= &(src[y*srcStride]);
3349         uint8_t *dstBlock= tempDst + dstStride;
3350
3351         // From this point on it is guaranteed that we can read and write 16 lines downward
3352         // finish 1 block before the next otherwise we might have a problem
3353         // with the L1 Cache of the P4 ... or only a few blocks at a time or soemthing
3354         for(x=0; x<width; x+=BLOCK_SIZE){
3355
3356 #if TEMPLATE_PP_MMXEXT
3357 /*
3358             prefetchnta(srcBlock + (((x>>2)&6) + 5)*srcStride + 32);
3359             prefetchnta(srcBlock + (((x>>2)&6) + 6)*srcStride + 32);
3360             prefetcht0(dstBlock + (((x>>2)&6) + 5)*dstStride + 32);
3361             prefetcht0(dstBlock + (((x>>2)&6) + 6)*dstStride + 32);
3362 */
3363
3364             __asm__(
3365                 "mov %4, %%"REG_a"              \n\t"
3366                 "shr $2, %%"REG_a"              \n\t"
3367                 "and $6, %%"REG_a"              \n\t"
3368                 "add %5, %%"REG_a"              \n\t"
3369                 "mov %%"REG_a", %%"REG_d"       \n\t"
3370                 "imul %1, %%"REG_a"             \n\t"
3371                 "imul %3, %%"REG_d"             \n\t"
3372                 "prefetchnta 32(%%"REG_a", %0)  \n\t"
3373                 "prefetcht0 32(%%"REG_d", %2)   \n\t"
3374                 "add %1, %%"REG_a"              \n\t"
3375                 "add %3, %%"REG_d"              \n\t"
3376                 "prefetchnta 32(%%"REG_a", %0)  \n\t"
3377                 "prefetcht0 32(%%"REG_d", %2)   \n\t"
3378                 :: "r" (srcBlock), "r" ((x86_reg)srcStride), "r" (dstBlock), "r" ((x86_reg)dstStride),
3379                 "g" ((x86_reg)x), "g" ((x86_reg)copyAhead)
3380                 : "%"REG_a, "%"REG_d
3381             );
3382
3383 #elif TEMPLATE_PP_3DNOW
3384 //FIXME check if this is faster on an 3dnow chip or if it is faster without the prefetch or ...
3385 /*          prefetch(srcBlock + (((x>>3)&3) + 5)*srcStride + 32);
3386             prefetch(srcBlock + (((x>>3)&3) + 9)*srcStride + 32);
3387             prefetchw(dstBlock + (((x>>3)&3) + 5)*dstStride + 32);
3388             prefetchw(dstBlock + (((x>>3)&3) + 9)*dstStride + 32);
3389 */
3390 #endif
3391
3392             RENAME(blockCopy)(dstBlock + dstStride*8, dstStride,
3393                               srcBlock + srcStride*8, srcStride, mode & LEVEL_FIX, &c.packedYOffset);
3394
3395             RENAME(duplicate)(dstBlock + dstStride*8, dstStride);
3396
3397             if(mode & LINEAR_IPOL_DEINT_FILTER)
3398                 RENAME(deInterlaceInterpolateLinear)(dstBlock, dstStride);
3399             else if(mode & LINEAR_BLEND_DEINT_FILTER)
3400                 RENAME(deInterlaceBlendLinear)(dstBlock, dstStride, c.deintTemp + x);
3401             else if(mode & MEDIAN_DEINT_FILTER)
3402                 RENAME(deInterlaceMedian)(dstBlock, dstStride);
3403             else if(mode & CUBIC_IPOL_DEINT_FILTER)
3404                 RENAME(deInterlaceInterpolateCubic)(dstBlock, dstStride);
3405             else if(mode & FFMPEG_DEINT_FILTER)
3406                 RENAME(deInterlaceFF)(dstBlock, dstStride, c.deintTemp + x);
3407             else if(mode & LOWPASS5_DEINT_FILTER)
3408                 RENAME(deInterlaceL5)(dstBlock, dstStride, c.deintTemp + x, c.deintTemp + width + x);
3409 /*          else if(mode & CUBIC_BLEND_DEINT_FILTER)
3410                 RENAME(deInterlaceBlendCubic)(dstBlock, dstStride);
3411 */
3412             dstBlock+=8;
3413             srcBlock+=8;
3414         }
3415         if(width==FFABS(dstStride))
3416             linecpy(dst, tempDst + 9*dstStride, copyAhead, dstStride);
3417         else{
3418             int i;
3419             for(i=0; i<copyAhead; i++){
3420                 memcpy(dst + i*dstStride, tempDst + (9+i)*dstStride, width);
3421             }
3422         }
3423     }
3424
3425     for(y=0; y<height; y+=BLOCK_SIZE){
3426         //1% speedup if these are here instead of the inner loop
3427         const uint8_t *srcBlock= &(src[y*srcStride]);
3428         uint8_t *dstBlock= &(dst[y*dstStride]);
3429 #if TEMPLATE_PP_MMX
3430         uint8_t *tempBlock1= c.tempBlocks;
3431         uint8_t *tempBlock2= c.tempBlocks + 8;
3432 #endif
3433         const int8_t *QPptr= &QPs[(y>>qpVShift)*QPStride];
3434         int8_t *nonBQPptr= &c.nonBQPTable[(y>>qpVShift)*FFABS(QPStride)];
3435         int QP=0;
3436         /* can we mess with a 8x16 block from srcBlock/dstBlock downwards and 1 line upwards
3437            if not than use a temporary buffer */
3438         if(y+15 >= height){
3439             int i;
3440             /* copy from line (copyAhead) to (copyAhead+7) of src, these will be copied with
3441                blockcopy to dst later */
3442             linecpy(tempSrc + srcStride*copyAhead, srcBlock + srcStride*copyAhead,
3443                     FFMAX(height-y-copyAhead, 0), srcStride);
3444
3445             /* duplicate last line of src to fill the void up to line (copyAhead+7) */
3446             for(i=FFMAX(height-y, 8); i<copyAhead+8; i++)
3447                     memcpy(tempSrc + srcStride*i, src + srcStride*(height-1), FFABS(srcStride));
3448
3449             /* copy up to (copyAhead+1) lines of dst (line -1 to (copyAhead-1))*/
3450             linecpy(tempDst, dstBlock - dstStride, FFMIN(height-y+1, copyAhead+1), dstStride);
3451
3452             /* duplicate last line of dst to fill the void up to line (copyAhead) */
3453             for(i=height-y+1; i<=copyAhead; i++)
3454                     memcpy(tempDst + dstStride*i, dst + dstStride*(height-1), FFABS(dstStride));
3455
3456             dstBlock= tempDst + dstStride;
3457             srcBlock= tempSrc;
3458         }
3459
3460         // From this point on it is guaranteed that we can read and write 16 lines downward
3461         // finish 1 block before the next otherwise we might have a problem
3462         // with the L1 Cache of the P4 ... or only a few blocks at a time or soemthing
3463         for(x=0; x<width; x+=BLOCK_SIZE){
3464             const int stride= dstStride;
3465 #if TEMPLATE_PP_MMX
3466             uint8_t *tmpXchg;
3467 #endif
3468             if(isColor){
3469                 QP= QPptr[x>>qpHShift];
3470                 c.nonBQP= nonBQPptr[x>>qpHShift];
3471             }else{
3472                 QP= QPptr[x>>4];
3473                 QP= (QP* QPCorrecture + 256*128)>>16;
3474                 c.nonBQP= nonBQPptr[x>>4];
3475                 c.nonBQP= (c.nonBQP* QPCorrecture + 256*128)>>16;
3476                 yHistogram[ srcBlock[srcStride*12 + 4] ]++;
3477             }
3478             c.QP= QP;
3479 #if TEMPLATE_PP_MMX
3480             __asm__ volatile(
3481                 "movd %1, %%mm7         \n\t"
3482                 "packuswb %%mm7, %%mm7  \n\t" // 0, 0, 0, QP, 0, 0, 0, QP
3483                 "packuswb %%mm7, %%mm7  \n\t" // 0,QP, 0, QP, 0,QP, 0, QP
3484                 "packuswb %%mm7, %%mm7  \n\t" // QP,..., QP
3485                 "movq %%mm7, %0         \n\t"
3486                 : "=m" (c.pQPb)
3487                 : "r" (QP)
3488             );
3489 #endif
3490
3491
3492 #if TEMPLATE_PP_MMXEXT
3493 /*
3494             prefetchnta(srcBlock + (((x>>2)&6) + 5)*srcStride + 32);
3495             prefetchnta(srcBlock + (((x>>2)&6) + 6)*srcStride + 32);
3496             prefetcht0(dstBlock + (((x>>2)&6) + 5)*dstStride + 32);
3497             prefetcht0(dstBlock + (((x>>2)&6) + 6)*dstStride + 32);
3498 */
3499
3500             __asm__(
3501                 "mov %4, %%"REG_a"              \n\t"
3502                 "shr $2, %%"REG_a"              \n\t"
3503                 "and $6, %%"REG_a"              \n\t"
3504                 "add %5, %%"REG_a"              \n\t"
3505                 "mov %%"REG_a", %%"REG_d"       \n\t"
3506                 "imul %1, %%"REG_a"             \n\t"
3507                 "imul %3, %%"REG_d"             \n\t"
3508                 "prefetchnta 32(%%"REG_a", %0)  \n\t"
3509                 "prefetcht0 32(%%"REG_d", %2)   \n\t"
3510                 "add %1, %%"REG_a"              \n\t"
3511                 "add %3, %%"REG_d"              \n\t"
3512                 "prefetchnta 32(%%"REG_a", %0)  \n\t"
3513                 "prefetcht0 32(%%"REG_d", %2)   \n\t"
3514                 :: "r" (srcBlock), "r" ((x86_reg)srcStride), "r" (dstBlock), "r" ((x86_reg)dstStride),
3515                 "g" ((x86_reg)x), "g" ((x86_reg)copyAhead)
3516                 : "%"REG_a, "%"REG_d
3517             );
3518
3519 #elif TEMPLATE_PP_3DNOW
3520 //FIXME check if this is faster on an 3dnow chip or if it is faster without the prefetch or ...
3521 /*          prefetch(srcBlock + (((x>>3)&3) + 5)*srcStride + 32);
3522             prefetch(srcBlock + (((x>>3)&3) + 9)*srcStride + 32);
3523             prefetchw(dstBlock + (((x>>3)&3) + 5)*dstStride + 32);
3524             prefetchw(dstBlock + (((x>>3)&3) + 9)*dstStride + 32);
3525 */
3526 #endif
3527
3528             RENAME(blockCopy)(dstBlock + dstStride*copyAhead, dstStride,
3529                               srcBlock + srcStride*copyAhead, srcStride, mode & LEVEL_FIX, &c.packedYOffset);
3530
3531             if(mode & LINEAR_IPOL_DEINT_FILTER)
3532                 RENAME(deInterlaceInterpolateLinear)(dstBlock, dstStride);
3533             else if(mode & LINEAR_BLEND_DEINT_FILTER)
3534                 RENAME(deInterlaceBlendLinear)(dstBlock, dstStride, c.deintTemp + x);
3535             else if(mode & MEDIAN_DEINT_FILTER)
3536                 RENAME(deInterlaceMedian)(dstBlock, dstStride);
3537             else if(mode & CUBIC_IPOL_DEINT_FILTER)
3538                 RENAME(deInterlaceInterpolateCubic)(dstBlock, dstStride);
3539             else if(mode & FFMPEG_DEINT_FILTER)
3540                 RENAME(deInterlaceFF)(dstBlock, dstStride, c.deintTemp + x);
3541             else if(mode & LOWPASS5_DEINT_FILTER)
3542                 RENAME(deInterlaceL5)(dstBlock, dstStride, c.deintTemp + x, c.deintTemp + width + x);
3543 /*          else if(mode & CUBIC_BLEND_DEINT_FILTER)
3544                 RENAME(deInterlaceBlendCubic)(dstBlock, dstStride);
3545 */
3546
3547             /* only deblock if we have 2 blocks */
3548             if(y + 8 < height){
3549                 if(mode & V_X1_FILTER)
3550                     RENAME(vertX1Filter)(dstBlock, stride, &c);
3551                 else if(mode & V_DEBLOCK){
3552                     const int t= RENAME(vertClassify)(dstBlock, stride, &c);
3553
3554                     if(t==1)
3555                         RENAME(doVertLowPass)(dstBlock, stride, &c);
3556                     else if(t==2)
3557                         RENAME(doVertDefFilter)(dstBlock, stride, &c);
3558                 }else if(mode & V_A_DEBLOCK){
3559                     RENAME(do_a_deblock)(dstBlock, stride, 1, &c);
3560                 }
3561             }
3562
3563 #if TEMPLATE_PP_MMX
3564             RENAME(transpose1)(tempBlock1, tempBlock2, dstBlock, dstStride);
3565 #endif
3566             /* check if we have a previous block to deblock it with dstBlock */
3567             if(x - 8 >= 0){
3568 #if TEMPLATE_PP_MMX
3569                 if(mode & H_X1_FILTER)
3570                         RENAME(vertX1Filter)(tempBlock1, 16, &c);
3571                 else if(mode & H_DEBLOCK){
3572 //START_TIMER
3573                     const int t= RENAME(vertClassify)(tempBlock1, 16, &c);
3574 //STOP_TIMER("dc & minmax")
3575                     if(t==1)
3576                         RENAME(doVertLowPass)(tempBlock1, 16, &c);
3577                     else if(t==2)
3578                         RENAME(doVertDefFilter)(tempBlock1, 16, &c);
3579                 }else if(mode & H_A_DEBLOCK){
3580                         RENAME(do_a_deblock)(tempBlock1, 16, 1, &c);
3581                 }
3582
3583                 RENAME(transpose2)(dstBlock-4, dstStride, tempBlock1 + 4*16);
3584
3585 #else
3586                 if(mode & H_X1_FILTER)
3587                     horizX1Filter(dstBlock-4, stride, QP);
3588                 else if(mode & H_DEBLOCK){
3589 #if TEMPLATE_PP_ALTIVEC
3590                     DECLARE_ALIGNED(16, unsigned char, tempBlock)[272];
3591                     int t;
3592                     transpose_16x8_char_toPackedAlign_altivec(tempBlock, dstBlock - (4 + 1), stride);
3593
3594                     t = vertClassify_altivec(tempBlock-48, 16, &c);
3595                     if(t==1) {
3596                         doVertLowPass_altivec(tempBlock-48, 16, &c);
3597                         transpose_8x16_char_fromPackedAlign_altivec(dstBlock - (4 + 1), tempBlock, stride);
3598                     }
3599                     else if(t==2) {
3600                         doVertDefFilter_altivec(tempBlock-48, 16, &c);
3601                         transpose_8x16_char_fromPackedAlign_altivec(dstBlock - (4 + 1), tempBlock, stride);
3602                     }
3603 #else
3604                     const int t= RENAME(horizClassify)(dstBlock-4, stride, &c);
3605
3606                     if(t==1)
3607                         RENAME(doHorizLowPass)(dstBlock-4, stride, &c);
3608                     else if(t==2)
3609                         RENAME(doHorizDefFilter)(dstBlock-4, stride, &c);
3610 #endif
3611                 }else if(mode & H_A_DEBLOCK){
3612                     RENAME(do_a_deblock)(dstBlock-8, 1, stride, &c);
3613                 }
3614 #endif //TEMPLATE_PP_MMX
3615                 if(mode & DERING){
3616                 //FIXME filter first line
3617                     if(y>0) RENAME(dering)(dstBlock - stride - 8, stride, &c);
3618                 }
3619
3620                 if(mode & TEMP_NOISE_FILTER)
3621                 {
3622                     RENAME(tempNoiseReducer)(dstBlock-8, stride,
3623                             c.tempBlurred[isColor] + y*dstStride + x,
3624                             c.tempBlurredPast[isColor] + (y>>3)*256 + (x>>3) + 256,
3625                             c.ppMode.maxTmpNoise);
3626                 }
3627             }
3628
3629             dstBlock+=8;
3630             srcBlock+=8;
3631
3632 #if TEMPLATE_PP_MMX
3633             tmpXchg= tempBlock1;
3634             tempBlock1= tempBlock2;
3635             tempBlock2 = tmpXchg;
3636 #endif
3637         }
3638
3639         if(mode & DERING){
3640             if(y > 0) RENAME(dering)(dstBlock - dstStride - 8, dstStride, &c);
3641         }
3642
3643         if((mode & TEMP_NOISE_FILTER)){
3644             RENAME(tempNoiseReducer)(dstBlock-8, dstStride,
3645                     c.tempBlurred[isColor] + y*dstStride + x,
3646                     c.tempBlurredPast[isColor] + (y>>3)*256 + (x>>3) + 256,
3647                     c.ppMode.maxTmpNoise);
3648         }
3649
3650         /* did we use a tmp buffer for the last lines*/
3651         if(y+15 >= height){
3652             uint8_t *dstBlock= &(dst[y*dstStride]);
3653             if(width==FFABS(dstStride))
3654                 linecpy(dstBlock, tempDst + dstStride, height-y, dstStride);
3655             else{
3656                 int i;
3657                 for(i=0; i<height-y; i++){
3658                     memcpy(dstBlock + i*dstStride, tempDst + (i+1)*dstStride, width);
3659                 }
3660             }
3661         }
3662 /*
3663         for(x=0; x<width; x+=32){
3664             volatile int i;
3665             i+=   dstBlock[x + 7*dstStride] + dstBlock[x + 8*dstStride]
3666                 + dstBlock[x + 9*dstStride] + dstBlock[x +10*dstStride]
3667                 + dstBlock[x +11*dstStride] + dstBlock[x +12*dstStride];
3668                 + dstBlock[x +13*dstStride]
3669                 + dstBlock[x +14*dstStride] + dstBlock[x +15*dstStride];
3670         }*/
3671     }
3672 #if   TEMPLATE_PP_3DNOW
3673     __asm__ volatile("femms");
3674 #elif TEMPLATE_PP_MMX
3675     __asm__ volatile("emms");
3676 #endif
3677
3678 #ifdef DEBUG_BRIGHTNESS
3679     if(!isColor){
3680         int max=1;
3681         int i;
3682         for(i=0; i<256; i++)
3683             if(yHistogram[i] > max) max=yHistogram[i];
3684
3685         for(i=1; i<256; i++){
3686             int x;
3687             int start=yHistogram[i-1]/(max/256+1);
3688             int end=yHistogram[i]/(max/256+1);
3689             int inc= end > start ? 1 : -1;
3690             for(x=start; x!=end+inc; x+=inc)
3691                 dst[ i*dstStride + x]+=128;
3692         }
3693
3694         for(i=0; i<100; i+=2){
3695             dst[ (white)*dstStride + i]+=128;
3696             dst[ (black)*dstStride + i]+=128;
3697         }
3698     }
3699 #endif
3700
3701     *c2= c; //copy local context back
3702
3703 }
3704
3705 #undef RENAME
3706 #undef TEMPLATE_PP_C
3707 #undef TEMPLATE_PP_ALTIVEC
3708 #undef TEMPLATE_PP_MMX
3709 #undef TEMPLATE_PP_MMXEXT
3710 #undef TEMPLATE_PP_3DNOW
3711 #undef TEMPLATE_PP_SSE2