update
[ffmpeg.git] / postproc / postprocess_template.c
1 /*
2     Copyright (C) 2001-2002 Michael Niedermayer (michaelni@gmx.at)
3
4     This program is free software; you can redistribute it and/or modify
5     it under the terms of the GNU General Public License as published by
6     the Free Software Foundation; either version 2 of the License, or
7     (at your option) any later version.
8
9     This program is distributed in the hope that it will be useful,
10     but WITHOUT ANY WARRANTY; without even the implied warranty of
11     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12     GNU General Public License for more details.
13
14     You should have received a copy of the GNU General Public License
15     along with this program; if not, write to the Free Software
16     Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
17 */
18
19 #undef PAVGB
20 #undef PMINUB
21 #undef PMAXUB
22
23 #ifdef HAVE_MMX2
24 #define PAVGB(a,b) "pavgb " #a ", " #b " \n\t"
25 #elif defined (HAVE_3DNOW)
26 #define PAVGB(a,b) "pavgusb " #a ", " #b " \n\t"
27 #endif
28
29 #ifdef HAVE_MMX2
30 #define PMINUB(a,b,t) "pminub " #a ", " #b " \n\t"
31 #elif defined (HAVE_MMX)
32 #define PMINUB(b,a,t) \
33         "movq " #a ", " #t " \n\t"\
34         "psubusb " #b ", " #t " \n\t"\
35         "psubb " #t ", " #a " \n\t"
36 #endif
37
38 #ifdef HAVE_MMX2
39 #define PMAXUB(a,b) "pmaxub " #a ", " #b " \n\t"
40 #elif defined (HAVE_MMX)
41 #define PMAXUB(a,b) \
42         "psubusb " #a ", " #b " \n\t"\
43         "paddb " #a ", " #b " \n\t"
44 #endif
45
46
47 //FIXME? |255-0| = 1 (shouldnt be a problem ...)
48 #ifdef HAVE_MMX
49 /**
50  * Check if the middle 8x8 Block in the given 8x16 block is flat
51  */
52 static inline int RENAME(isVertDC)(uint8_t src[], int stride, PPContext *c){
53         int numEq= 0;
54         src+= stride*4; // src points to begin of the 8x8 Block
55 asm volatile(
56                 "leal (%1, %2), %%eax                           \n\t"
57 //      0       1       2       3       4       5       6       7       8       9
58 //      %1      eax     eax+%2  eax+2%2 %1+4%2  ecx     ecx+%2  ecx+2%2 %1+8%2  ecx+4%2
59                 "movq %3, %%mm7                                 \n\t" 
60                 "movq %4, %%mm6                                 \n\t" 
61
62                 "movq (%1), %%mm0                               \n\t"
63                 "movq (%%eax), %%mm1                            \n\t"
64                 "psubb %%mm1, %%mm0                             \n\t" // mm0 = differnece
65                 "paddb %%mm7, %%mm0                             \n\t"
66                 "pcmpgtb %%mm6, %%mm0                           \n\t"
67
68                 "movq (%%eax,%2), %%mm2                         \n\t"
69                 "psubb %%mm2, %%mm1                             \n\t"
70                 "paddb %%mm7, %%mm1                             \n\t"
71                 "pcmpgtb %%mm6, %%mm1                           \n\t"
72                 "paddb %%mm1, %%mm0                             \n\t"
73
74                 "movq (%%eax, %2, 2), %%mm1                     \n\t"
75                 "psubb %%mm1, %%mm2                             \n\t"
76                 "paddb %%mm7, %%mm2                             \n\t"
77                 "pcmpgtb %%mm6, %%mm2                           \n\t"
78                 "paddb %%mm2, %%mm0                             \n\t"
79                 
80                 "leal (%%eax, %2, 4), %%eax                     \n\t"
81
82                 "movq (%1, %2, 4), %%mm2                        \n\t"
83                 "psubb %%mm2, %%mm1                             \n\t"
84                 "paddb %%mm7, %%mm1                             \n\t"
85                 "pcmpgtb %%mm6, %%mm1                           \n\t"
86                 "paddb %%mm1, %%mm0                             \n\t"
87
88                 "movq (%%eax), %%mm1                            \n\t"
89                 "psubb %%mm1, %%mm2                             \n\t"
90                 "paddb %%mm7, %%mm2                             \n\t"
91                 "pcmpgtb %%mm6, %%mm2                           \n\t"
92                 "paddb %%mm2, %%mm0                             \n\t"
93
94                 "movq (%%eax, %2), %%mm2                        \n\t"
95                 "psubb %%mm2, %%mm1                             \n\t"
96                 "paddb %%mm7, %%mm1                             \n\t"
97                 "pcmpgtb %%mm6, %%mm1                           \n\t"
98                 "paddb %%mm1, %%mm0                             \n\t"
99
100                 "movq (%%eax, %2, 2), %%mm1                     \n\t"
101                 "psubb %%mm1, %%mm2                             \n\t"
102                 "paddb %%mm7, %%mm2                             \n\t"
103                 "pcmpgtb %%mm6, %%mm2                           \n\t"
104                 "paddb %%mm2, %%mm0                             \n\t"
105
106                 "                                               \n\t"
107 #ifdef HAVE_MMX2
108                 "pxor %%mm7, %%mm7                              \n\t"
109                 "psadbw %%mm7, %%mm0                            \n\t"
110 #else
111                 "movq %%mm0, %%mm1                              \n\t"
112                 "psrlw $8, %%mm0                                \n\t"
113                 "paddb %%mm1, %%mm0                             \n\t"
114                 "movq %%mm0, %%mm1                              \n\t"
115                 "psrlq $16, %%mm0                               \n\t"
116                 "paddb %%mm1, %%mm0                             \n\t"
117                 "movq %%mm0, %%mm1                              \n\t"
118                 "psrlq $32, %%mm0                               \n\t"
119                 "paddb %%mm1, %%mm0                             \n\t"
120 #endif
121                 "movd %%mm0, %0                                 \n\t"
122                 : "=r" (numEq)
123                 : "r" (src), "r" (stride), "m" (c->mmxDcOffset[c->nonBQP]),  "m" (c->mmxDcThreshold[c->nonBQP])
124                 : "%eax"
125                 );
126         numEq= (-numEq) &0xFF;
127         return numEq > c->ppMode.flatnessThreshold;
128 }
129 #endif
130
131 static inline int RENAME(isVertMinMaxOk)(uint8_t src[], int stride, PPContext *c)
132 {
133 #ifdef HAVE_MMX
134         int isOk;
135         src+= stride*3;
136         asm volatile(
137                 "movq (%1, %2), %%mm0                           \n\t"
138                 "movq (%1, %2, 8), %%mm1                        \n\t"
139                 "movq %%mm0, %%mm2                              \n\t"
140                 "psubusb %%mm1, %%mm0                           \n\t"
141                 "psubusb %%mm2, %%mm1                           \n\t"
142                 "por %%mm1, %%mm0                               \n\t" // ABS Diff
143
144                 "movq %3, %%mm7                                 \n\t" // QP,..., QP
145                 "paddusb %%mm7, %%mm7                           \n\t" // 2QP ... 2QP
146                 "psubusb %%mm7, %%mm0                           \n\t" // Diff <= 2QP -> 0
147                 "packssdw %%mm0, %%mm0                          \n\t"
148                 "movd %%mm0, %0                                 \n\t"
149                 : "=r" (isOk)
150                 : "r" (src), "r" (stride), "m" (c->pQPb)
151                 );
152         return isOk==0;
153 #else
154 #if 1
155         int x;
156         const int QP= c->QP;
157         src+= stride*3;
158         for(x=0; x<BLOCK_SIZE; x++)
159         {
160                 if((unsigned)(src[x + stride] - src[x + (stride<<3)] + 2*QP) > 4*QP) return 0;
161         }
162
163         return 1;
164 #else
165         int x;
166         const int QP= c->QP;
167         src+= stride*4;
168         for(x=0; x<BLOCK_SIZE; x++)
169         {
170                 int min=255;
171                 int max=0;
172                 int y;
173                 for(y=0; y<8; y++){
174                         int v= src[x + y*stride];
175                         if(v>max) max=v;
176                         if(v<min) min=v;
177                 }
178                 if(max-min > 2*QP) return 0;
179         }
180         return 1;
181 #endif
182 #endif
183 }
184
185 /**
186  * Do a vertical low pass filter on the 8x16 block (only write to the 8x8 block in the middle)
187  * using the 9-Tap Filter (1,1,2,2,4,2,2,1,1)/16
188  */
189 static inline void RENAME(doVertLowPass)(uint8_t *src, int stride, PPContext *c)
190 {
191 #if defined (HAVE_MMX2) || defined (HAVE_3DNOW)
192         src+= stride*3;
193         asm volatile(   //"movv %0 %1 %2\n\t"
194                 "movq %2, %%mm0                 \n\t"  // QP,..., QP
195                 "pxor %%mm4, %%mm4                              \n\t"
196
197                 "movq (%0), %%mm6                               \n\t"
198                 "movq (%0, %1), %%mm5                           \n\t"
199                 "movq %%mm5, %%mm1                              \n\t"
200                 "movq %%mm6, %%mm2                              \n\t"
201                 "psubusb %%mm6, %%mm5                           \n\t"
202                 "psubusb %%mm1, %%mm2                           \n\t"
203                 "por %%mm5, %%mm2                               \n\t" // ABS Diff of lines
204                 "psubusb %%mm0, %%mm2                           \n\t" // diff <= QP -> 0
205                 "pcmpeqb %%mm4, %%mm2                   \n\t" // diff <= QP -> FF
206
207                 "pand %%mm2, %%mm6                              \n\t"
208                 "pandn %%mm1, %%mm2                             \n\t"
209                 "por %%mm2, %%mm6                               \n\t"// First Line to Filter
210
211                 "movq (%0, %1, 8), %%mm5                        \n\t"
212                 "leal (%0, %1, 4), %%eax                        \n\t"
213                 "leal (%0, %1, 8), %%ecx                        \n\t"
214                 "subl %1, %%ecx                                 \n\t"
215                 "addl %1, %0                                    \n\t" // %0 points to line 1 not 0
216                 "movq (%0, %1, 8), %%mm7                        \n\t"
217                 "movq %%mm5, %%mm1                              \n\t"
218                 "movq %%mm7, %%mm2                              \n\t"
219                 "psubusb %%mm7, %%mm5                           \n\t"
220                 "psubusb %%mm1, %%mm2                           \n\t"
221                 "por %%mm5, %%mm2                               \n\t" // ABS Diff of lines
222                 "psubusb %%mm0, %%mm2                           \n\t" // diff <= QP -> 0
223                 "pcmpeqb %%mm4, %%mm2                   \n\t" // diff <= QP -> FF
224
225                 "pand %%mm2, %%mm7                              \n\t"
226                 "pandn %%mm1, %%mm2                             \n\t"
227                 "por %%mm2, %%mm7                               \n\t" // First Line to Filter
228
229
230                 //      1       2       3       4       5       6       7       8
231                 //      %0      %0+%1   %0+2%1  eax     %0+4%1  eax+2%1 ecx     eax+4%1
232                 // 6 4 2 2 1 1
233                 // 6 4 4 2
234                 // 6 8 2
235
236                 "movq (%0, %1), %%mm0                           \n\t" //  1
237                 "movq %%mm0, %%mm1                              \n\t" //  1
238                 PAVGB(%%mm6, %%mm0)                                   //1 1     /2
239                 PAVGB(%%mm6, %%mm0)                                   //3 1     /4
240
241                 "movq (%0, %1, 4), %%mm2                        \n\t" //     1
242                 "movq %%mm2, %%mm5                              \n\t" //     1
243                 PAVGB((%%eax), %%mm2)                                 //    11  /2
244                 PAVGB((%0, %1, 2), %%mm2)                             //   211  /4
245                 "movq %%mm2, %%mm3                              \n\t" //   211  /4
246                 "movq (%0), %%mm4                               \n\t" // 1
247                 PAVGB(%%mm4, %%mm3)                                   // 4 211  /8
248                 PAVGB(%%mm0, %%mm3)                                   //642211  /16
249                 "movq %%mm3, (%0)                               \n\t" // X
250                 // mm1=2 mm2=3(211) mm4=1 mm5=5 mm6=0 mm7=9
251                 "movq %%mm1, %%mm0                              \n\t" //  1
252                 PAVGB(%%mm6, %%mm0)                                   //1 1     /2
253                 "movq %%mm4, %%mm3                              \n\t" // 1
254                 PAVGB((%0,%1,2), %%mm3)                               // 1 1    /2
255                 PAVGB((%%eax,%1,2), %%mm5)                            //     11 /2
256                 PAVGB((%%eax), %%mm5)                                 //    211 /4
257                 PAVGB(%%mm5, %%mm3)                                   // 2 2211 /8
258                 PAVGB(%%mm0, %%mm3)                                   //4242211 /16
259                 "movq %%mm3, (%0,%1)                            \n\t" //  X
260                 // mm1=2 mm2=3(211) mm4=1 mm5=4(211) mm6=0 mm7=9
261                 PAVGB(%%mm4, %%mm6)                                   //11      /2
262                 "movq (%%ecx), %%mm0                            \n\t" //       1
263                 PAVGB((%%eax, %1, 2), %%mm0)                          //      11/2
264                 "movq %%mm0, %%mm3                              \n\t" //      11/2
265                 PAVGB(%%mm1, %%mm0)                                   //  2   11/4
266                 PAVGB(%%mm6, %%mm0)                                   //222   11/8
267                 PAVGB(%%mm2, %%mm0)                                   //22242211/16
268                 "movq (%0, %1, 2), %%mm2                        \n\t" //   1
269                 "movq %%mm0, (%0, %1, 2)                        \n\t" //   X
270                 // mm1=2 mm2=3 mm3=6(11) mm4=1 mm5=4(211) mm6=0(11) mm7=9
271                 "movq (%%eax, %1, 4), %%mm0                     \n\t" //        1
272                 PAVGB((%%ecx), %%mm0)                                 //       11       /2
273                 PAVGB(%%mm0, %%mm6)                                   //11     11       /4
274                 PAVGB(%%mm1, %%mm4)                                   // 11             /2
275                 PAVGB(%%mm2, %%mm1)                                   //  11            /2
276                 PAVGB(%%mm1, %%mm6)                                   //1122   11       /8
277                 PAVGB(%%mm5, %%mm6)                                   //112242211       /16
278                 "movq (%%eax), %%mm5                            \n\t" //    1
279                 "movq %%mm6, (%%eax)                            \n\t" //    X
280                 // mm0=7(11) mm1=2(11) mm2=3 mm3=6(11) mm4=1(11) mm5=4 mm7=9
281                 "movq (%%eax, %1, 4), %%mm6                     \n\t" //        1
282                 PAVGB(%%mm7, %%mm6)                                   //        11      /2
283                 PAVGB(%%mm4, %%mm6)                                   // 11     11      /4
284                 PAVGB(%%mm3, %%mm6)                                   // 11   2211      /8
285                 PAVGB(%%mm5, %%mm2)                                   //   11           /2
286                 "movq (%0, %1, 4), %%mm4                        \n\t" //     1
287                 PAVGB(%%mm4, %%mm2)                                   //   112          /4
288                 PAVGB(%%mm2, %%mm6)                                   // 112242211      /16
289                 "movq %%mm6, (%0, %1, 4)                        \n\t" //     X
290                 // mm0=7(11) mm1=2(11) mm2=3(112) mm3=6(11) mm4=5 mm5=4 mm7=9
291                 PAVGB(%%mm7, %%mm1)                                   //  11     2      /4
292                 PAVGB(%%mm4, %%mm5)                                   //    11          /2
293                 PAVGB(%%mm5, %%mm0)                                   //    11 11       /4
294                 "movq (%%eax, %1, 2), %%mm6                     \n\t" //      1
295                 PAVGB(%%mm6, %%mm1)                                   //  11  4  2      /8
296                 PAVGB(%%mm0, %%mm1)                                   //  11224222      /16
297                 "movq %%mm1, (%%eax, %1, 2)                     \n\t" //      X
298                 // mm2=3(112) mm3=6(11) mm4=5 mm5=4(11) mm6=6 mm7=9
299                 PAVGB((%%ecx), %%mm2)                                 //   112 4        /8
300                 "movq (%%eax, %1, 4), %%mm0                     \n\t" //        1
301                 PAVGB(%%mm0, %%mm6)                                   //      1 1       /2
302                 PAVGB(%%mm7, %%mm6)                                   //      1 12      /4
303                 PAVGB(%%mm2, %%mm6)                                   //   1122424      /4
304                 "movq %%mm6, (%%ecx)                            \n\t" //       X
305                 // mm0=8 mm3=6(11) mm4=5 mm5=4(11) mm7=9
306                 PAVGB(%%mm7, %%mm5)                                   //    11   2      /4
307                 PAVGB(%%mm7, %%mm5)                                   //    11   6      /8
308
309                 PAVGB(%%mm3, %%mm0)                                   //      112       /4
310                 PAVGB(%%mm0, %%mm5)                                   //    112246      /16
311                 "movq %%mm5, (%%eax, %1, 4)                     \n\t" //        X
312                 "subl %1, %0                                    \n\t"
313
314                 :
315                 : "r" (src), "r" (stride), "m" (c->pQPb)
316                 : "%eax", "%ecx"
317         );
318 #else
319         const int l1= stride;
320         const int l2= stride + l1;
321         const int l3= stride + l2;
322         const int l4= stride + l3;
323         const int l5= stride + l4;
324         const int l6= stride + l5;
325         const int l7= stride + l6;
326         const int l8= stride + l7;
327         const int l9= stride + l8;
328         int x;
329         src+= stride*3;
330         for(x=0; x<BLOCK_SIZE; x++)
331         {
332                 const int first= ABS(src[0] - src[l1]) < c->QP ? src[0] : src[l1];
333                 const int last= ABS(src[l8] - src[l9]) < c->QP ? src[l9] : src[l8];
334
335                 int sums[9];
336                 sums[0] = first + src[l1];
337                 sums[1] = src[l1] + src[l2];
338                 sums[2] = src[l2] + src[l3];
339                 sums[3] = src[l3] + src[l4];
340                 sums[4] = src[l4] + src[l5];
341                 sums[5] = src[l5] + src[l6];
342                 sums[6] = src[l6] + src[l7];
343                 sums[7] = src[l7] + src[l8];
344                 sums[8] = src[l8] + last;
345
346                 src[l1]= ((sums[0]<<2) + ((first + sums[2])<<1) + sums[4] + 8)>>4;
347                 src[l2]= ((src[l2]<<2) + ((first + sums[0] + sums[3])<<1) + sums[5] + 8)>>4;
348                 src[l3]= ((src[l3]<<2) + ((first + sums[1] + sums[4])<<1) + sums[6] + 8)>>4;
349                 src[l4]= ((src[l4]<<2) + ((sums[2] + sums[5])<<1) + sums[0] + sums[7] + 8)>>4;
350                 src[l5]= ((src[l5]<<2) + ((sums[3] + sums[6])<<1) + sums[1] + sums[8] + 8)>>4;
351                 src[l6]= ((src[l6]<<2) + ((last + sums[7] + sums[4])<<1) + sums[2] + 8)>>4;
352                 src[l7]= (((last + src[l7])<<2) + ((src[l8] + sums[5])<<1) + sums[3] + 8)>>4;
353                 src[l8]= ((sums[8]<<2) + ((last + sums[6])<<1) + sums[4] + 8)>>4;
354
355                 src++;
356         }
357 #endif
358 }
359
360 #if 0
361 /**
362  * Experimental implementation of the filter (Algorithm 1) described in a paper from Ramkishor & Karandikar
363  * values are correctly clipped (MMX2)
364  * values are wraparound (C)
365  * conclusion: its fast, but introduces ugly horizontal patterns if there is a continious gradient
366         0 8 16 24
367         x = 8
368         x/2 = 4
369         x/8 = 1
370         1 12 12 23
371  */
372 static inline void RENAME(vertRK1Filter)(uint8_t *src, int stride, int QP)
373 {
374 #if defined (HAVE_MMX2) || defined (HAVE_3DNOW)
375         src+= stride*3;
376 // FIXME rounding
377         asm volatile(
378                 "pxor %%mm7, %%mm7                              \n\t" // 0
379                 "movq "MANGLE(b80)", %%mm6                      \n\t" // MIN_SIGNED_BYTE
380                 "leal (%0, %1), %%eax                           \n\t"
381                 "leal (%%eax, %1, 4), %%ecx                     \n\t"
382 //      0       1       2       3       4       5       6       7       8       9
383 //      %0      eax     eax+%1  eax+2%1 %0+4%1  ecx     ecx+%1  ecx+2%1 %0+8%1  ecx+4%1
384                 "movq "MANGLE(pQPb)", %%mm0                     \n\t" // QP,..., QP
385                 "movq %%mm0, %%mm1                              \n\t" // QP,..., QP
386                 "paddusb "MANGLE(b02)", %%mm0                   \n\t"
387                 "psrlw $2, %%mm0                                \n\t"
388                 "pand "MANGLE(b3F)", %%mm0                      \n\t" // QP/4,..., QP/4
389                 "paddusb %%mm1, %%mm0                           \n\t" // QP*1.25 ...
390                 "movq (%0, %1, 4), %%mm2                        \n\t" // line 4
391                 "movq (%%ecx), %%mm3                            \n\t" // line 5
392                 "movq %%mm2, %%mm4                              \n\t" // line 4
393                 "pcmpeqb %%mm5, %%mm5                           \n\t" // -1
394                 "pxor %%mm2, %%mm5                              \n\t" // -line 4 - 1
395                 PAVGB(%%mm3, %%mm5)
396                 "paddb %%mm6, %%mm5                             \n\t" // (l5-l4)/2
397                 "psubusb %%mm3, %%mm4                           \n\t"
398                 "psubusb %%mm2, %%mm3                           \n\t"
399                 "por %%mm3, %%mm4                               \n\t" // |l4 - l5|
400                 "psubusb %%mm0, %%mm4                           \n\t"
401                 "pcmpeqb %%mm7, %%mm4                           \n\t"
402                 "pand %%mm4, %%mm5                              \n\t" // d/2
403
404 //              "paddb %%mm6, %%mm2                             \n\t" // line 4 + 0x80
405                 "paddb %%mm5, %%mm2                             \n\t"
406 //              "psubb %%mm6, %%mm2                             \n\t"
407                 "movq %%mm2, (%0,%1, 4)                         \n\t"
408
409                 "movq (%%ecx), %%mm2                            \n\t"
410 //              "paddb %%mm6, %%mm2                             \n\t" // line 5 + 0x80
411                 "psubb %%mm5, %%mm2                             \n\t"
412 //              "psubb %%mm6, %%mm2                             \n\t"
413                 "movq %%mm2, (%%ecx)                            \n\t"
414
415                 "paddb %%mm6, %%mm5                             \n\t"
416                 "psrlw $2, %%mm5                                \n\t"
417                 "pand "MANGLE(b3F)", %%mm5                      \n\t"
418                 "psubb "MANGLE(b20)", %%mm5                     \n\t" // (l5-l4)/8
419
420                 "movq (%%eax, %1, 2), %%mm2                     \n\t"
421                 "paddb %%mm6, %%mm2                             \n\t" // line 3 + 0x80
422                 "paddsb %%mm5, %%mm2                            \n\t"
423                 "psubb %%mm6, %%mm2                             \n\t"
424                 "movq %%mm2, (%%eax, %1, 2)                     \n\t"
425
426                 "movq (%%ecx, %1), %%mm2                        \n\t"
427                 "paddb %%mm6, %%mm2                             \n\t" // line 6 + 0x80
428                 "psubsb %%mm5, %%mm2                            \n\t"
429                 "psubb %%mm6, %%mm2                             \n\t"
430                 "movq %%mm2, (%%ecx, %1)                        \n\t"
431
432                 :
433                 : "r" (src), "r" (stride)
434                 : "%eax", "%ecx"
435         );
436 #else
437         const int l1= stride;
438         const int l2= stride + l1;
439         const int l3= stride + l2;
440         const int l4= stride + l3;
441         const int l5= stride + l4;
442         const int l6= stride + l5;
443 //      const int l7= stride + l6;
444 //      const int l8= stride + l7;
445 //      const int l9= stride + l8;
446         int x;
447         const int QP15= QP + (QP>>2);
448         src+= stride*3;
449         for(x=0; x<BLOCK_SIZE; x++)
450         {
451                 const int v = (src[x+l5] - src[x+l4]);
452                 if(ABS(v) < QP15)
453                 {
454                         src[x+l3] +=v>>3;
455                         src[x+l4] +=v>>1;
456                         src[x+l5] -=v>>1;
457                         src[x+l6] -=v>>3;
458
459                 }
460         }
461
462 #endif
463 }
464 #endif
465
466 /**
467  * Experimental Filter 1
468  * will not damage linear gradients
469  * Flat blocks should look like they where passed through the (1,1,2,2,4,2,2,1,1) 9-Tap filter
470  * can only smooth blocks at the expected locations (it cant smooth them if they did move)
471  * MMX2 version does correct clipping C version doesnt
472  */
473 static inline void RENAME(vertX1Filter)(uint8_t *src, int stride, PPContext *co)
474 {
475 #if defined (HAVE_MMX2) || defined (HAVE_3DNOW)
476         src+= stride*3;
477
478         asm volatile(
479                 "pxor %%mm7, %%mm7                              \n\t" // 0
480                 "leal (%0, %1), %%eax                           \n\t"
481                 "leal (%%eax, %1, 4), %%ecx                     \n\t"
482 //      0       1       2       3       4       5       6       7       8       9
483 //      %0      eax     eax+%1  eax+2%1 %0+4%1  ecx     ecx+%1  ecx+2%1 %0+8%1  ecx+4%1
484                 "movq (%%eax, %1, 2), %%mm0                     \n\t" // line 3
485                 "movq (%0, %1, 4), %%mm1                        \n\t" // line 4
486                 "movq %%mm1, %%mm2                              \n\t" // line 4
487                 "psubusb %%mm0, %%mm1                           \n\t"
488                 "psubusb %%mm2, %%mm0                           \n\t"
489                 "por %%mm1, %%mm0                               \n\t" // |l2 - l3|
490                 "movq (%%ecx), %%mm3                            \n\t" // line 5
491                 "movq (%%ecx, %1), %%mm4                        \n\t" // line 6
492                 "movq %%mm3, %%mm5                              \n\t" // line 5
493                 "psubusb %%mm4, %%mm3                           \n\t"
494                 "psubusb %%mm5, %%mm4                           \n\t"
495                 "por %%mm4, %%mm3                               \n\t" // |l5 - l6|
496                 PAVGB(%%mm3, %%mm0)                                   // (|l2 - l3| + |l5 - l6|)/2
497                 "movq %%mm2, %%mm1                              \n\t" // line 4
498                 "psubusb %%mm5, %%mm2                           \n\t"
499                 "movq %%mm2, %%mm4                              \n\t"
500                 "pcmpeqb %%mm7, %%mm2                           \n\t" // (l4 - l5) <= 0 ? -1 : 0
501                 "psubusb %%mm1, %%mm5                           \n\t"
502                 "por %%mm5, %%mm4                               \n\t" // |l4 - l5|
503                 "psubusb %%mm0, %%mm4           \n\t" //d = MAX(0, |l4-l5| - (|l2-l3| + |l5-l6|)/2)
504                 "movq %%mm4, %%mm3                              \n\t" // d
505                 "movq %2, %%mm0                 \n\t"
506                 "paddusb %%mm0, %%mm0                           \n\t"
507                 "psubusb %%mm0, %%mm4                           \n\t"
508                 "pcmpeqb %%mm7, %%mm4                           \n\t" // d <= QP ? -1 : 0
509                 "psubusb "MANGLE(b01)", %%mm3                   \n\t"
510                 "pand %%mm4, %%mm3                              \n\t" // d <= QP ? d : 0
511
512                 PAVGB(%%mm7, %%mm3)                                   // d/2
513                 "movq %%mm3, %%mm1                              \n\t" // d/2
514                 PAVGB(%%mm7, %%mm3)                                   // d/4
515                 PAVGB(%%mm1, %%mm3)                                   // 3*d/8
516
517                 "movq (%0, %1, 4), %%mm0                        \n\t" // line 4
518                 "pxor %%mm2, %%mm0                              \n\t" //(l4 - l5) <= 0 ? -l4-1 : l4
519                 "psubusb %%mm3, %%mm0                           \n\t"
520                 "pxor %%mm2, %%mm0                              \n\t"
521                 "movq %%mm0, (%0, %1, 4)                        \n\t" // line 4
522
523                 "movq (%%ecx), %%mm0                            \n\t" // line 5
524                 "pxor %%mm2, %%mm0                              \n\t" //(l4 - l5) <= 0 ? -l5-1 : l5
525                 "paddusb %%mm3, %%mm0                           \n\t"
526                 "pxor %%mm2, %%mm0                              \n\t"
527                 "movq %%mm0, (%%ecx)                            \n\t" // line 5
528
529                 PAVGB(%%mm7, %%mm1)                                   // d/4
530
531                 "movq (%%eax, %1, 2), %%mm0                     \n\t" // line 3
532                 "pxor %%mm2, %%mm0                              \n\t" //(l4 - l5) <= 0 ? -l4-1 : l4
533                 "psubusb %%mm1, %%mm0                           \n\t"
534                 "pxor %%mm2, %%mm0                              \n\t"
535                 "movq %%mm0, (%%eax, %1, 2)                     \n\t" // line 3
536
537                 "movq (%%ecx, %1), %%mm0                        \n\t" // line 6
538                 "pxor %%mm2, %%mm0                              \n\t" //(l4 - l5) <= 0 ? -l5-1 : l5
539                 "paddusb %%mm1, %%mm0                           \n\t"
540                 "pxor %%mm2, %%mm0                              \n\t"
541                 "movq %%mm0, (%%ecx, %1)                        \n\t" // line 6
542
543                 PAVGB(%%mm7, %%mm1)                                   // d/8
544
545                 "movq (%%eax, %1), %%mm0                        \n\t" // line 2
546                 "pxor %%mm2, %%mm0                              \n\t" //(l4 - l5) <= 0 ? -l2-1 : l2
547                 "psubusb %%mm1, %%mm0                           \n\t"
548                 "pxor %%mm2, %%mm0                              \n\t"
549                 "movq %%mm0, (%%eax, %1)                        \n\t" // line 2
550
551                 "movq (%%ecx, %1, 2), %%mm0                     \n\t" // line 7
552                 "pxor %%mm2, %%mm0                              \n\t" //(l4 - l5) <= 0 ? -l7-1 : l7
553                 "paddusb %%mm1, %%mm0                           \n\t"
554                 "pxor %%mm2, %%mm0                              \n\t"
555                 "movq %%mm0, (%%ecx, %1, 2)                     \n\t" // line 7
556
557                 :
558                 : "r" (src), "r" (stride), "m" (co->pQPb)
559                 : "%eax", "%ecx"
560         );
561 #else
562
563         const int l1= stride;
564         const int l2= stride + l1;
565         const int l3= stride + l2;
566         const int l4= stride + l3;
567         const int l5= stride + l4;
568         const int l6= stride + l5;
569         const int l7= stride + l6;
570 //      const int l8= stride + l7;
571 //      const int l9= stride + l8;
572         int x;
573
574         src+= stride*3;
575         for(x=0; x<BLOCK_SIZE; x++)
576         {
577                 int a= src[l3] - src[l4];
578                 int b= src[l4] - src[l5];
579                 int c= src[l5] - src[l6];
580
581                 int d= ABS(b) - ((ABS(a) + ABS(c))>>1);
582                 d= MAX(d, 0);
583
584                 if(d < co->QP*2)
585                 {
586                         int v = d * SIGN(-b);
587
588                         src[l2] +=v>>3;
589                         src[l3] +=v>>2;
590                         src[l4] +=(3*v)>>3;
591                         src[l5] -=(3*v)>>3;
592                         src[l6] -=v>>2;
593                         src[l7] -=v>>3;
594
595                 }
596                 src++;
597         }
598 #endif
599 }
600
601 static inline void RENAME(doVertDefFilter)(uint8_t src[], int stride, PPContext *c)
602 {
603 #if defined (HAVE_MMX2) || defined (HAVE_3DNOW)
604 /*
605         uint8_t tmp[16];
606         const int l1= stride;
607         const int l2= stride + l1;
608         const int l3= stride + l2;
609         const int l4= (int)tmp - (int)src - stride*3;
610         const int l5= (int)tmp - (int)src - stride*3 + 8;
611         const int l6= stride*3 + l3;
612         const int l7= stride + l6;
613         const int l8= stride + l7;
614
615         memcpy(tmp, src+stride*7, 8);
616         memcpy(tmp+8, src+stride*8, 8);
617 */
618         src+= stride*4;
619         asm volatile(
620
621 #if 0 //sligtly more accurate and slightly slower
622                 "pxor %%mm7, %%mm7                              \n\t" // 0
623                 "leal (%0, %1), %%eax                           \n\t"
624                 "leal (%%eax, %1, 4), %%ecx                     \n\t"
625 //      0       1       2       3       4       5       6       7
626 //      %0      %0+%1   %0+2%1  eax+2%1 %0+4%1  eax+4%1 ecx+%1  ecx+2%1
627 //      %0      eax     eax+%1  eax+2%1 %0+4%1  ecx     ecx+%1  ecx+2%1
628
629
630                 "movq (%0, %1, 2), %%mm0                        \n\t" // l2
631                 "movq (%0), %%mm1                               \n\t" // l0
632                 "movq %%mm0, %%mm2                              \n\t" // l2
633                 PAVGB(%%mm7, %%mm0)                                   // ~l2/2
634                 PAVGB(%%mm1, %%mm0)                                   // ~(l2 + 2l0)/4
635                 PAVGB(%%mm2, %%mm0)                                   // ~(5l2 + 2l0)/8
636
637                 "movq (%%eax), %%mm1                            \n\t" // l1
638                 "movq (%%eax, %1, 2), %%mm3                     \n\t" // l3
639                 "movq %%mm1, %%mm4                              \n\t" // l1
640                 PAVGB(%%mm7, %%mm1)                                   // ~l1/2
641                 PAVGB(%%mm3, %%mm1)                                   // ~(l1 + 2l3)/4
642                 PAVGB(%%mm4, %%mm1)                                   // ~(5l1 + 2l3)/8
643
644                 "movq %%mm0, %%mm4                              \n\t" // ~(5l2 + 2l0)/8
645                 "psubusb %%mm1, %%mm0                           \n\t"
646                 "psubusb %%mm4, %%mm1                           \n\t"
647                 "por %%mm0, %%mm1                               \n\t" // ~|2l0 - 5l1 + 5l2 - 2l3|/8
648 // mm1= |lenergy|, mm2= l2, mm3= l3, mm7=0
649
650                 "movq (%0, %1, 4), %%mm0                        \n\t" // l4
651                 "movq %%mm0, %%mm4                              \n\t" // l4
652                 PAVGB(%%mm7, %%mm0)                                   // ~l4/2
653                 PAVGB(%%mm2, %%mm0)                                   // ~(l4 + 2l2)/4
654                 PAVGB(%%mm4, %%mm0)                                   // ~(5l4 + 2l2)/8
655
656                 "movq (%%ecx), %%mm2                            \n\t" // l5
657                 "movq %%mm3, %%mm5                              \n\t" // l3
658                 PAVGB(%%mm7, %%mm3)                                   // ~l3/2
659                 PAVGB(%%mm2, %%mm3)                                   // ~(l3 + 2l5)/4
660                 PAVGB(%%mm5, %%mm3)                                   // ~(5l3 + 2l5)/8
661
662                 "movq %%mm0, %%mm6                              \n\t" // ~(5l4 + 2l2)/8
663                 "psubusb %%mm3, %%mm0                           \n\t"
664                 "psubusb %%mm6, %%mm3                           \n\t"
665                 "por %%mm0, %%mm3                               \n\t" // ~|2l2 - 5l3 + 5l4 - 2l5|/8
666                 "pcmpeqb %%mm7, %%mm0                           \n\t" // SIGN(2l2 - 5l3 + 5l4 - 2l5)
667 // mm0= SIGN(menergy), mm1= |lenergy|, mm2= l5, mm3= |menergy|, mm4=l4, mm5= l3, mm7=0
668
669                 "movq (%%ecx, %1), %%mm6                        \n\t" // l6
670                 "movq %%mm6, %%mm5                              \n\t" // l6
671                 PAVGB(%%mm7, %%mm6)                                   // ~l6/2
672                 PAVGB(%%mm4, %%mm6)                                   // ~(l6 + 2l4)/4
673                 PAVGB(%%mm5, %%mm6)                                   // ~(5l6 + 2l4)/8
674
675                 "movq (%%ecx, %1, 2), %%mm5                     \n\t" // l7
676                 "movq %%mm2, %%mm4                              \n\t" // l5
677                 PAVGB(%%mm7, %%mm2)                                   // ~l5/2
678                 PAVGB(%%mm5, %%mm2)                                   // ~(l5 + 2l7)/4
679                 PAVGB(%%mm4, %%mm2)                                   // ~(5l5 + 2l7)/8
680
681                 "movq %%mm6, %%mm4                              \n\t" // ~(5l6 + 2l4)/8
682                 "psubusb %%mm2, %%mm6                           \n\t"
683                 "psubusb %%mm4, %%mm2                           \n\t"
684                 "por %%mm6, %%mm2                               \n\t" // ~|2l4 - 5l5 + 5l6 - 2l7|/8
685 // mm0= SIGN(menergy), mm1= |lenergy|/8, mm2= |renergy|/8, mm3= |menergy|/8, mm7=0
686
687
688                 PMINUB(%%mm2, %%mm1, %%mm4)                           // MIN(|lenergy|,|renergy|)/8
689                 "movq %2, %%mm4                                 \n\t" // QP //FIXME QP+1 ?
690                 "paddusb "MANGLE(b01)", %%mm4                   \n\t"
691                 "pcmpgtb %%mm3, %%mm4                           \n\t" // |menergy|/8 < QP
692                 "psubusb %%mm1, %%mm3                           \n\t" // d=|menergy|/8-MIN(|lenergy|,|renergy|)/8
693                 "pand %%mm4, %%mm3                              \n\t"
694
695                 "movq %%mm3, %%mm1                              \n\t"
696 //              "psubusb "MANGLE(b01)", %%mm3                   \n\t"
697                 PAVGB(%%mm7, %%mm3)
698                 PAVGB(%%mm7, %%mm3)
699                 "paddusb %%mm1, %%mm3                           \n\t"
700 //              "paddusb "MANGLE(b01)", %%mm3                   \n\t"
701
702                 "movq (%%eax, %1, 2), %%mm6                     \n\t" //l3
703                 "movq (%0, %1, 4), %%mm5                        \n\t" //l4
704                 "movq (%0, %1, 4), %%mm4                        \n\t" //l4
705                 "psubusb %%mm6, %%mm5                           \n\t"
706                 "psubusb %%mm4, %%mm6                           \n\t"
707                 "por %%mm6, %%mm5                               \n\t" // |l3-l4|
708                 "pcmpeqb %%mm7, %%mm6                           \n\t" // SIGN(l3-l4)
709                 "pxor %%mm6, %%mm0                              \n\t"
710                 "pand %%mm0, %%mm3                              \n\t"
711                 PMINUB(%%mm5, %%mm3, %%mm0)
712
713                 "psubusb "MANGLE(b01)", %%mm3                   \n\t"
714                 PAVGB(%%mm7, %%mm3)
715
716                 "movq (%%eax, %1, 2), %%mm0                     \n\t"
717                 "movq (%0, %1, 4), %%mm2                        \n\t"
718                 "pxor %%mm6, %%mm0                              \n\t"
719                 "pxor %%mm6, %%mm2                              \n\t"
720                 "psubb %%mm3, %%mm0                             \n\t"
721                 "paddb %%mm3, %%mm2                             \n\t"
722                 "pxor %%mm6, %%mm0                              \n\t"
723                 "pxor %%mm6, %%mm2                              \n\t"
724                 "movq %%mm0, (%%eax, %1, 2)                     \n\t"
725                 "movq %%mm2, (%0, %1, 4)                        \n\t"
726 #endif
727
728                 "leal (%0, %1), %%eax                           \n\t"
729                 "pcmpeqb %%mm6, %%mm6                           \n\t" // -1
730 //      0       1       2       3       4       5       6       7
731 //      %0      %0+%1   %0+2%1  eax+2%1 %0+4%1  eax+4%1 ecx+%1  ecx+2%1
732 //      %0      eax     eax+%1  eax+2%1 %0+4%1  ecx     ecx+%1  ecx+2%1
733
734
735                 "movq (%%eax, %1, 2), %%mm1                     \n\t" // l3
736                 "movq (%0, %1, 4), %%mm0                        \n\t" // l4
737                 "pxor %%mm6, %%mm1                              \n\t" // -l3-1
738                 PAVGB(%%mm1, %%mm0)                                   // -q+128 = (l4-l3+256)/2
739 // mm1=-l3-1, mm0=128-q
740
741                 "movq (%%eax, %1, 4), %%mm2                     \n\t" // l5
742                 "movq (%%eax, %1), %%mm3                        \n\t" // l2
743                 "pxor %%mm6, %%mm2                              \n\t" // -l5-1
744                 "movq %%mm2, %%mm5                              \n\t" // -l5-1
745                 "movq "MANGLE(b80)", %%mm4                      \n\t" // 128
746                 "leal (%%eax, %1, 4), %%ecx                     \n\t"
747                 PAVGB(%%mm3, %%mm2)                                   // (l2-l5+256)/2
748                 PAVGB(%%mm0, %%mm4)                                   // ~(l4-l3)/4 + 128
749                 PAVGB(%%mm2, %%mm4)                                   // ~(l2-l5)/4 +(l4-l3)/8 + 128
750                 PAVGB(%%mm0, %%mm4)                                   // ~(l2-l5)/8 +5(l4-l3)/16 + 128
751 // mm1=-l3-1, mm0=128-q, mm3=l2, mm4=menergy/16 + 128, mm5= -l5-1
752
753                 "movq (%%eax), %%mm2                            \n\t" // l1
754                 "pxor %%mm6, %%mm2                              \n\t" // -l1-1
755                 PAVGB(%%mm3, %%mm2)                                   // (l2-l1+256)/2
756                 PAVGB((%0), %%mm1)                                    // (l0-l3+256)/2
757                 "movq "MANGLE(b80)", %%mm3                      \n\t" // 128
758                 PAVGB(%%mm2, %%mm3)                                   // ~(l2-l1)/4 + 128
759                 PAVGB(%%mm1, %%mm3)                                   // ~(l0-l3)/4 +(l2-l1)/8 + 128
760                 PAVGB(%%mm2, %%mm3)                                   // ~(l0-l3)/8 +5(l2-l1)/16 + 128
761 // mm0=128-q, mm3=lenergy/16 + 128, mm4= menergy/16 + 128, mm5= -l5-1
762
763                 PAVGB((%%ecx, %1), %%mm5)                             // (l6-l5+256)/2
764                 "movq (%%ecx, %1, 2), %%mm1                     \n\t" // l7
765                 "pxor %%mm6, %%mm1                              \n\t" // -l7-1
766                 PAVGB((%0, %1, 4), %%mm1)                             // (l4-l7+256)/2
767                 "movq "MANGLE(b80)", %%mm2                      \n\t" // 128
768                 PAVGB(%%mm5, %%mm2)                                   // ~(l6-l5)/4 + 128
769                 PAVGB(%%mm1, %%mm2)                                   // ~(l4-l7)/4 +(l6-l5)/8 + 128
770                 PAVGB(%%mm5, %%mm2)                                   // ~(l4-l7)/8 +5(l6-l5)/16 + 128
771 // mm0=128-q, mm2=renergy/16 + 128, mm3=lenergy/16 + 128, mm4= menergy/16 + 128
772
773                 "movq "MANGLE(b00)", %%mm1                      \n\t" // 0
774                 "movq "MANGLE(b00)", %%mm5                      \n\t" // 0
775                 "psubb %%mm2, %%mm1                             \n\t" // 128 - renergy/16
776                 "psubb %%mm3, %%mm5                             \n\t" // 128 - lenergy/16
777                 PMAXUB(%%mm1, %%mm2)                                  // 128 + |renergy/16|
778                 PMAXUB(%%mm5, %%mm3)                                  // 128 + |lenergy/16|
779                 PMINUB(%%mm2, %%mm3, %%mm1)                           // 128 + MIN(|lenergy|,|renergy|)/16
780
781 // mm0=128-q, mm3=128 + MIN(|lenergy|,|renergy|)/16, mm4= menergy/16 + 128
782
783                 "movq "MANGLE(b00)", %%mm7                      \n\t" // 0
784                 "movq %2, %%mm2                                 \n\t" // QP
785                 PAVGB(%%mm6, %%mm2)                                   // 128 + QP/2
786                 "psubb %%mm6, %%mm2                             \n\t"
787
788                 "movq %%mm4, %%mm1                              \n\t"
789                 "pcmpgtb %%mm7, %%mm1                           \n\t" // SIGN(menergy)
790                 "pxor %%mm1, %%mm4                              \n\t"
791                 "psubb %%mm1, %%mm4                             \n\t" // 128 + |menergy|/16
792                 "pcmpgtb %%mm4, %%mm2                           \n\t" // |menergy|/16 < QP/2
793                 "psubusb %%mm3, %%mm4                           \n\t" //d=|menergy|/16 - MIN(|lenergy|,|renergy|)/16
794 // mm0=128-q, mm1= SIGN(menergy), mm2= |menergy|/16 < QP/2, mm4= d/16
795
796                 "movq %%mm4, %%mm3                              \n\t" // d
797                 "psubusb "MANGLE(b01)", %%mm4                   \n\t"
798                 PAVGB(%%mm7, %%mm4)                                   // d/32
799                 PAVGB(%%mm7, %%mm4)                                   // (d + 32)/64
800                 "paddb %%mm3, %%mm4                             \n\t" // 5d/64
801                 "pand %%mm2, %%mm4                              \n\t"
802
803                 "movq "MANGLE(b80)", %%mm5                      \n\t" // 128
804                 "psubb %%mm0, %%mm5                             \n\t" // q
805                 "paddsb %%mm6, %%mm5                            \n\t" // fix bad rounding
806                 "pcmpgtb %%mm5, %%mm7                           \n\t" // SIGN(q)
807                 "pxor %%mm7, %%mm5                              \n\t"
808
809                 PMINUB(%%mm5, %%mm4, %%mm3)                           // MIN(|q|, 5d/64)
810                 "pxor %%mm1, %%mm7                              \n\t" // SIGN(d*q)
811
812                 "pand %%mm7, %%mm4                              \n\t"
813                 "movq (%%eax, %1, 2), %%mm0                     \n\t"
814                 "movq (%0, %1, 4), %%mm2                        \n\t"
815                 "pxor %%mm1, %%mm0                              \n\t"
816                 "pxor %%mm1, %%mm2                              \n\t"
817                 "paddb %%mm4, %%mm0                             \n\t"
818                 "psubb %%mm4, %%mm2                             \n\t"
819                 "pxor %%mm1, %%mm0                              \n\t"
820                 "pxor %%mm1, %%mm2                              \n\t"
821                 "movq %%mm0, (%%eax, %1, 2)                     \n\t"
822                 "movq %%mm2, (%0, %1, 4)                        \n\t"
823
824                 :
825                 : "r" (src), "r" (stride), "m" (c->pQPb)
826                 : "%eax", "%ecx"
827         );
828
829 /*
830         {
831         int x;
832         src-= stride;
833         for(x=0; x<BLOCK_SIZE; x++)
834         {
835                 const int middleEnergy= 5*(src[l5] - src[l4]) + 2*(src[l3] - src[l6]);
836                 if(ABS(middleEnergy)< 8*QP)
837                 {
838                         const int q=(src[l4] - src[l5])/2;
839                         const int leftEnergy=  5*(src[l3] - src[l2]) + 2*(src[l1] - src[l4]);
840                         const int rightEnergy= 5*(src[l7] - src[l6]) + 2*(src[l5] - src[l8]);
841
842                         int d= ABS(middleEnergy) - MIN( ABS(leftEnergy), ABS(rightEnergy) );
843                         d= MAX(d, 0);
844
845                         d= (5*d + 32) >> 6;
846                         d*= SIGN(-middleEnergy);
847
848                         if(q>0)
849                         {
850                                 d= d<0 ? 0 : d;
851                                 d= d>q ? q : d;
852                         }
853                         else
854                         {
855                                 d= d>0 ? 0 : d;
856                                 d= d<q ? q : d;
857                         }
858
859                         src[l4]-= d;
860                         src[l5]+= d;
861                 }
862                 src++;
863         }
864 src-=8;
865         for(x=0; x<8; x++)
866         {
867                 int y;
868                 for(y=4; y<6; y++)
869                 {
870                         int d= src[x+y*stride] - tmp[x+(y-4)*8];
871                         int ad= ABS(d);
872                         static int max=0;
873                         static int sum=0;
874                         static int num=0;
875                         static int bias=0;
876
877                         if(max<ad) max=ad;
878                         sum+= ad>3 ? 1 : 0;
879                         if(ad>3)
880                         {
881                                 src[0] = src[7] = src[stride*7] = src[(stride+1)*7]=255;
882                         }
883                         if(y==4) bias+=d;
884                         num++;
885                         if(num%1000000 == 0)
886                         {
887                                 printf(" %d %d %d %d\n", num, sum, max, bias);
888                         }
889                 }
890         }
891 }
892 */
893 #elif defined (HAVE_MMX)
894         src+= stride*4;
895         asm volatile(
896                 "pxor %%mm7, %%mm7                              \n\t"
897                 "leal -40(%%esp), %%ecx                         \n\t" // make space for 4 8-byte vars
898                 "andl $0xFFFFFFF8, %%ecx                        \n\t" // align
899 //      0       1       2       3       4       5       6       7
900 //      %0      %0+%1   %0+2%1  eax+2%1 %0+4%1  eax+4%1 edx+%1  edx+2%1
901 //      %0      eax     eax+%1  eax+2%1 %0+4%1  edx     edx+%1  edx+2%1
902
903                 "movq (%0), %%mm0                               \n\t"
904                 "movq %%mm0, %%mm1                              \n\t"
905                 "punpcklbw %%mm7, %%mm0                         \n\t" // low part of line 0
906                 "punpckhbw %%mm7, %%mm1                         \n\t" // high part of line 0
907
908                 "movq (%0, %1), %%mm2                           \n\t"
909                 "leal (%0, %1, 2), %%eax                        \n\t"
910                 "movq %%mm2, %%mm3                              \n\t"
911                 "punpcklbw %%mm7, %%mm2                         \n\t" // low part of line 1
912                 "punpckhbw %%mm7, %%mm3                         \n\t" // high part of line 1
913
914                 "movq (%%eax), %%mm4                            \n\t"
915                 "movq %%mm4, %%mm5                              \n\t"
916                 "punpcklbw %%mm7, %%mm4                         \n\t" // low part of line 2
917                 "punpckhbw %%mm7, %%mm5                         \n\t" // high part of line 2
918
919                 "paddw %%mm0, %%mm0                             \n\t" // 2L0
920                 "paddw %%mm1, %%mm1                             \n\t" // 2H0
921                 "psubw %%mm4, %%mm2                             \n\t" // L1 - L2
922                 "psubw %%mm5, %%mm3                             \n\t" // H1 - H2
923                 "psubw %%mm2, %%mm0                             \n\t" // 2L0 - L1 + L2
924                 "psubw %%mm3, %%mm1                             \n\t" // 2H0 - H1 + H2
925
926                 "psllw $2, %%mm2                                \n\t" // 4L1 - 4L2
927                 "psllw $2, %%mm3                                \n\t" // 4H1 - 4H2
928                 "psubw %%mm2, %%mm0                             \n\t" // 2L0 - 5L1 + 5L2
929                 "psubw %%mm3, %%mm1                             \n\t" // 2H0 - 5H1 + 5H2
930
931                 "movq (%%eax, %1), %%mm2                        \n\t"
932                 "movq %%mm2, %%mm3                              \n\t"
933                 "punpcklbw %%mm7, %%mm2                         \n\t" // L3
934                 "punpckhbw %%mm7, %%mm3                         \n\t" // H3
935
936                 "psubw %%mm2, %%mm0                             \n\t" // 2L0 - 5L1 + 5L2 - L3
937                 "psubw %%mm3, %%mm1                             \n\t" // 2H0 - 5H1 + 5H2 - H3
938                 "psubw %%mm2, %%mm0                             \n\t" // 2L0 - 5L1 + 5L2 - 2L3
939                 "psubw %%mm3, %%mm1                             \n\t" // 2H0 - 5H1 + 5H2 - 2H3
940                 "movq %%mm0, (%%ecx)                            \n\t" // 2L0 - 5L1 + 5L2 - 2L3
941                 "movq %%mm1, 8(%%ecx)                           \n\t" // 2H0 - 5H1 + 5H2 - 2H3
942
943                 "movq (%%eax, %1, 2), %%mm0                     \n\t"
944                 "movq %%mm0, %%mm1                              \n\t"
945                 "punpcklbw %%mm7, %%mm0                         \n\t" // L4
946                 "punpckhbw %%mm7, %%mm1                         \n\t" // H4
947
948                 "psubw %%mm0, %%mm2                             \n\t" // L3 - L4
949                 "psubw %%mm1, %%mm3                             \n\t" // H3 - H4
950                 "movq %%mm2, 16(%%ecx)                          \n\t" // L3 - L4
951                 "movq %%mm3, 24(%%ecx)                          \n\t" // H3 - H4
952                 "paddw %%mm4, %%mm4                             \n\t" // 2L2
953                 "paddw %%mm5, %%mm5                             \n\t" // 2H2
954                 "psubw %%mm2, %%mm4                             \n\t" // 2L2 - L3 + L4
955                 "psubw %%mm3, %%mm5                             \n\t" // 2H2 - H3 + H4
956
957                 "leal (%%eax, %1), %0                           \n\t"
958                 "psllw $2, %%mm2                                \n\t" // 4L3 - 4L4
959                 "psllw $2, %%mm3                                \n\t" // 4H3 - 4H4
960                 "psubw %%mm2, %%mm4                             \n\t" // 2L2 - 5L3 + 5L4
961                 "psubw %%mm3, %%mm5                             \n\t" // 2H2 - 5H3 + 5H4
962 //50 opcodes so far
963                 "movq (%0, %1, 2), %%mm2                        \n\t"
964                 "movq %%mm2, %%mm3                              \n\t"
965                 "punpcklbw %%mm7, %%mm2                         \n\t" // L5
966                 "punpckhbw %%mm7, %%mm3                         \n\t" // H5
967                 "psubw %%mm2, %%mm4                             \n\t" // 2L2 - 5L3 + 5L4 - L5
968                 "psubw %%mm3, %%mm5                             \n\t" // 2H2 - 5H3 + 5H4 - H5
969                 "psubw %%mm2, %%mm4                             \n\t" // 2L2 - 5L3 + 5L4 - 2L5
970                 "psubw %%mm3, %%mm5                             \n\t" // 2H2 - 5H3 + 5H4 - 2H5
971
972                 "movq (%%eax, %1, 4), %%mm6                     \n\t"
973                 "punpcklbw %%mm7, %%mm6                         \n\t" // L6
974                 "psubw %%mm6, %%mm2                             \n\t" // L5 - L6
975                 "movq (%%eax, %1, 4), %%mm6                     \n\t"
976                 "punpckhbw %%mm7, %%mm6                         \n\t" // H6
977                 "psubw %%mm6, %%mm3                             \n\t" // H5 - H6
978
979                 "paddw %%mm0, %%mm0                             \n\t" // 2L4
980                 "paddw %%mm1, %%mm1                             \n\t" // 2H4
981                 "psubw %%mm2, %%mm0                             \n\t" // 2L4 - L5 + L6
982                 "psubw %%mm3, %%mm1                             \n\t" // 2H4 - H5 + H6
983
984                 "psllw $2, %%mm2                                \n\t" // 4L5 - 4L6
985                 "psllw $2, %%mm3                                \n\t" // 4H5 - 4H6
986                 "psubw %%mm2, %%mm0                             \n\t" // 2L4 - 5L5 + 5L6
987                 "psubw %%mm3, %%mm1                             \n\t" // 2H4 - 5H5 + 5H6
988
989                 "movq (%0, %1, 4), %%mm2                        \n\t"
990                 "movq %%mm2, %%mm3                              \n\t"
991                 "punpcklbw %%mm7, %%mm2                         \n\t" // L7
992                 "punpckhbw %%mm7, %%mm3                         \n\t" // H7
993
994                 "paddw %%mm2, %%mm2                             \n\t" // 2L7
995                 "paddw %%mm3, %%mm3                             \n\t" // 2H7
996                 "psubw %%mm2, %%mm0                             \n\t" // 2L4 - 5L5 + 5L6 - 2L7
997                 "psubw %%mm3, %%mm1                             \n\t" // 2H4 - 5H5 + 5H6 - 2H7
998
999                 "movq (%%ecx), %%mm2                            \n\t" // 2L0 - 5L1 + 5L2 - 2L3
1000                 "movq 8(%%ecx), %%mm3                           \n\t" // 2H0 - 5H1 + 5H2 - 2H3
1001
1002 #ifdef HAVE_MMX2
1003                 "movq %%mm7, %%mm6                              \n\t" // 0
1004                 "psubw %%mm0, %%mm6                             \n\t"
1005                 "pmaxsw %%mm6, %%mm0                            \n\t" // |2L4 - 5L5 + 5L6 - 2L7|
1006                 "movq %%mm7, %%mm6                              \n\t" // 0
1007                 "psubw %%mm1, %%mm6                             \n\t"
1008                 "pmaxsw %%mm6, %%mm1                            \n\t" // |2H4 - 5H5 + 5H6 - 2H7|
1009                 "movq %%mm7, %%mm6                              \n\t" // 0
1010                 "psubw %%mm2, %%mm6                             \n\t"
1011                 "pmaxsw %%mm6, %%mm2                            \n\t" // |2L0 - 5L1 + 5L2 - 2L3|
1012                 "movq %%mm7, %%mm6                              \n\t" // 0
1013                 "psubw %%mm3, %%mm6                             \n\t"
1014                 "pmaxsw %%mm6, %%mm3                            \n\t" // |2H0 - 5H1 + 5H2 - 2H3|
1015 #else
1016                 "movq %%mm7, %%mm6                              \n\t" // 0
1017                 "pcmpgtw %%mm0, %%mm6                           \n\t"
1018                 "pxor %%mm6, %%mm0                              \n\t"
1019                 "psubw %%mm6, %%mm0                             \n\t" // |2L4 - 5L5 + 5L6 - 2L7|
1020                 "movq %%mm7, %%mm6                              \n\t" // 0
1021                 "pcmpgtw %%mm1, %%mm6                           \n\t"
1022                 "pxor %%mm6, %%mm1                              \n\t"
1023                 "psubw %%mm6, %%mm1                             \n\t" // |2H4 - 5H5 + 5H6 - 2H7|
1024                 "movq %%mm7, %%mm6                              \n\t" // 0
1025                 "pcmpgtw %%mm2, %%mm6                           \n\t"
1026                 "pxor %%mm6, %%mm2                              \n\t"
1027                 "psubw %%mm6, %%mm2                             \n\t" // |2L0 - 5L1 + 5L2 - 2L3|
1028                 "movq %%mm7, %%mm6                              \n\t" // 0
1029                 "pcmpgtw %%mm3, %%mm6                           \n\t"
1030                 "pxor %%mm6, %%mm3                              \n\t"
1031                 "psubw %%mm6, %%mm3                             \n\t" // |2H0 - 5H1 + 5H2 - 2H3|
1032 #endif
1033
1034 #ifdef HAVE_MMX2
1035                 "pminsw %%mm2, %%mm0                            \n\t"
1036                 "pminsw %%mm3, %%mm1                            \n\t"
1037 #else
1038                 "movq %%mm0, %%mm6                              \n\t"
1039                 "psubusw %%mm2, %%mm6                           \n\t"
1040                 "psubw %%mm6, %%mm0                             \n\t"
1041                 "movq %%mm1, %%mm6                              \n\t"
1042                 "psubusw %%mm3, %%mm6                           \n\t"
1043                 "psubw %%mm6, %%mm1                             \n\t"
1044 #endif
1045
1046                 "movq %%mm7, %%mm6                              \n\t" // 0
1047                 "pcmpgtw %%mm4, %%mm6                           \n\t" // sign(2L2 - 5L3 + 5L4 - 2L5)
1048                 "pxor %%mm6, %%mm4                              \n\t"
1049                 "psubw %%mm6, %%mm4                             \n\t" // |2L2 - 5L3 + 5L4 - 2L5|
1050                 "pcmpgtw %%mm5, %%mm7                           \n\t" // sign(2H2 - 5H3 + 5H4 - 2H5)
1051                 "pxor %%mm7, %%mm5                              \n\t"
1052                 "psubw %%mm7, %%mm5                             \n\t" // |2H2 - 5H3 + 5H4 - 2H5|
1053 // 100 opcodes
1054                 "movd %2, %%mm2                                 \n\t" // QP
1055                 "psllw $3, %%mm2                                \n\t" // 8QP
1056                 "movq %%mm2, %%mm3                              \n\t" // 8QP
1057                 "pcmpgtw %%mm4, %%mm2                           \n\t"
1058                 "pcmpgtw %%mm5, %%mm3                           \n\t"
1059                 "pand %%mm2, %%mm4                              \n\t"
1060                 "pand %%mm3, %%mm5                              \n\t"
1061
1062
1063                 "psubusw %%mm0, %%mm4                           \n\t" // hd
1064                 "psubusw %%mm1, %%mm5                           \n\t" // ld
1065
1066
1067                 "movq "MANGLE(w05)", %%mm2                      \n\t" // 5
1068                 "pmullw %%mm2, %%mm4                            \n\t"
1069                 "pmullw %%mm2, %%mm5                            \n\t"
1070                 "movq "MANGLE(w20)", %%mm2                      \n\t" // 32
1071                 "paddw %%mm2, %%mm4                             \n\t"
1072                 "paddw %%mm2, %%mm5                             \n\t"
1073                 "psrlw $6, %%mm4                                \n\t"
1074                 "psrlw $6, %%mm5                                \n\t"
1075
1076                 "movq 16(%%ecx), %%mm0                          \n\t" // L3 - L4
1077                 "movq 24(%%ecx), %%mm1                          \n\t" // H3 - H4
1078
1079                 "pxor %%mm2, %%mm2                              \n\t"
1080                 "pxor %%mm3, %%mm3                              \n\t"
1081
1082                 "pcmpgtw %%mm0, %%mm2                           \n\t" // sign (L3-L4)
1083                 "pcmpgtw %%mm1, %%mm3                           \n\t" // sign (H3-H4)
1084                 "pxor %%mm2, %%mm0                              \n\t"
1085                 "pxor %%mm3, %%mm1                              \n\t"
1086                 "psubw %%mm2, %%mm0                             \n\t" // |L3-L4|
1087                 "psubw %%mm3, %%mm1                             \n\t" // |H3-H4|
1088                 "psrlw $1, %%mm0                                \n\t" // |L3 - L4|/2
1089                 "psrlw $1, %%mm1                                \n\t" // |H3 - H4|/2
1090
1091                 "pxor %%mm6, %%mm2                              \n\t"
1092                 "pxor %%mm7, %%mm3                              \n\t"
1093                 "pand %%mm2, %%mm4                              \n\t"
1094                 "pand %%mm3, %%mm5                              \n\t"
1095
1096 #ifdef HAVE_MMX2
1097                 "pminsw %%mm0, %%mm4                            \n\t"
1098                 "pminsw %%mm1, %%mm5                            \n\t"
1099 #else
1100                 "movq %%mm4, %%mm2                              \n\t"
1101                 "psubusw %%mm0, %%mm2                           \n\t"
1102                 "psubw %%mm2, %%mm4                             \n\t"
1103                 "movq %%mm5, %%mm2                              \n\t"
1104                 "psubusw %%mm1, %%mm2                           \n\t"
1105                 "psubw %%mm2, %%mm5                             \n\t"
1106 #endif
1107                 "pxor %%mm6, %%mm4                              \n\t"
1108                 "pxor %%mm7, %%mm5                              \n\t"
1109                 "psubw %%mm6, %%mm4                             \n\t"
1110                 "psubw %%mm7, %%mm5                             \n\t"
1111                 "packsswb %%mm5, %%mm4                          \n\t"
1112                 "movq (%0), %%mm0                               \n\t"
1113                 "paddb   %%mm4, %%mm0                           \n\t"
1114                 "movq %%mm0, (%0)                               \n\t"
1115                 "movq (%0, %1), %%mm0                           \n\t"
1116                 "psubb %%mm4, %%mm0                             \n\t"
1117                 "movq %%mm0, (%0, %1)                           \n\t"
1118
1119                 : "+r" (src)
1120                 : "r" (stride), "m" (c->pQPb)
1121                 : "%eax", "%ecx"
1122         );
1123 #else
1124         const int l1= stride;
1125         const int l2= stride + l1;
1126         const int l3= stride + l2;
1127         const int l4= stride + l3;
1128         const int l5= stride + l4;
1129         const int l6= stride + l5;
1130         const int l7= stride + l6;
1131         const int l8= stride + l7;
1132 //      const int l9= stride + l8;
1133         int x;
1134         src+= stride*3;
1135         for(x=0; x<BLOCK_SIZE; x++)
1136         {
1137                 const int middleEnergy= 5*(src[l5] - src[l4]) + 2*(src[l3] - src[l6]);
1138                 if(ABS(middleEnergy) < 8*c->QP)
1139                 {
1140                         const int q=(src[l4] - src[l5])/2;
1141                         const int leftEnergy=  5*(src[l3] - src[l2]) + 2*(src[l1] - src[l4]);
1142                         const int rightEnergy= 5*(src[l7] - src[l6]) + 2*(src[l5] - src[l8]);
1143
1144                         int d= ABS(middleEnergy) - MIN( ABS(leftEnergy), ABS(rightEnergy) );
1145                         d= MAX(d, 0);
1146
1147                         d= (5*d + 32) >> 6;
1148                         d*= SIGN(-middleEnergy);
1149
1150                         if(q>0)
1151                         {
1152                                 d= d<0 ? 0 : d;
1153                                 d= d>q ? q : d;
1154                         }
1155                         else
1156                         {
1157                                 d= d>0 ? 0 : d;
1158                                 d= d<q ? q : d;
1159                         }
1160
1161                         src[l4]-= d;
1162                         src[l5]+= d;
1163                 }
1164                 src++;
1165         }
1166 #endif
1167 }
1168
1169 static inline void RENAME(dering)(uint8_t src[], int stride, PPContext *c)
1170 {
1171 #if defined (HAVE_MMX2) || defined (HAVE_3DNOW)
1172         asm volatile(
1173                 "pxor %%mm6, %%mm6                              \n\t"
1174                 "pcmpeqb %%mm7, %%mm7                           \n\t"
1175                 "movq %2, %%mm0                                 \n\t"
1176                 "punpcklbw %%mm6, %%mm0                         \n\t"
1177                 "psrlw $1, %%mm0                                \n\t"
1178                 "psubw %%mm7, %%mm0                             \n\t"
1179                 "packuswb %%mm0, %%mm0                          \n\t"
1180                 "movq %%mm0, %3                                 \n\t"
1181
1182                 "leal (%0, %1), %%eax                           \n\t"
1183                 "leal (%%eax, %1, 4), %%edx                     \n\t"
1184                 
1185 //      0       1       2       3       4       5       6       7       8       9
1186 //      %0      eax     eax+%1  eax+2%1 %0+4%1  edx     edx+%1  edx+2%1 %0+8%1  edx+4%1
1187
1188 #undef FIND_MIN_MAX
1189 #ifdef HAVE_MMX2
1190 #define FIND_MIN_MAX(addr)\
1191                 "movq " #addr ", %%mm0                          \n\t"\
1192                 "pminub %%mm0, %%mm7                            \n\t"\
1193                 "pmaxub %%mm0, %%mm6                            \n\t"
1194 #else
1195 #define FIND_MIN_MAX(addr)\
1196                 "movq " #addr ", %%mm0                          \n\t"\
1197                 "movq %%mm7, %%mm1                              \n\t"\
1198                 "psubusb %%mm0, %%mm6                           \n\t"\
1199                 "paddb %%mm0, %%mm6                             \n\t"\
1200                 "psubusb %%mm0, %%mm1                           \n\t"\
1201                 "psubb %%mm1, %%mm7                             \n\t"
1202 #endif
1203
1204 FIND_MIN_MAX((%%eax))
1205 FIND_MIN_MAX((%%eax, %1))
1206 FIND_MIN_MAX((%%eax, %1, 2))
1207 FIND_MIN_MAX((%0, %1, 4))
1208 FIND_MIN_MAX((%%edx))
1209 FIND_MIN_MAX((%%edx, %1))
1210 FIND_MIN_MAX((%%edx, %1, 2))
1211 FIND_MIN_MAX((%0, %1, 8))
1212
1213                 "movq %%mm7, %%mm4                              \n\t"
1214                 "psrlq $8, %%mm7                                \n\t"
1215 #ifdef HAVE_MMX2
1216                 "pminub %%mm4, %%mm7                            \n\t" // min of pixels
1217                 "pshufw $0xF9, %%mm7, %%mm4                     \n\t"
1218                 "pminub %%mm4, %%mm7                            \n\t" // min of pixels
1219                 "pshufw $0xFE, %%mm7, %%mm4                     \n\t"
1220                 "pminub %%mm4, %%mm7                            \n\t"
1221 #else
1222                 "movq %%mm7, %%mm1                              \n\t"
1223                 "psubusb %%mm4, %%mm1                           \n\t"
1224                 "psubb %%mm1, %%mm7                             \n\t"
1225                 "movq %%mm7, %%mm4                              \n\t"
1226                 "psrlq $16, %%mm7                               \n\t"
1227                 "movq %%mm7, %%mm1                              \n\t"
1228                 "psubusb %%mm4, %%mm1                           \n\t"
1229                 "psubb %%mm1, %%mm7                             \n\t"
1230                 "movq %%mm7, %%mm4                              \n\t"
1231                 "psrlq $32, %%mm7                               \n\t"
1232                 "movq %%mm7, %%mm1                              \n\t"
1233                 "psubusb %%mm4, %%mm1                           \n\t"
1234                 "psubb %%mm1, %%mm7                             \n\t"
1235 #endif
1236
1237
1238                 "movq %%mm6, %%mm4                              \n\t"
1239                 "psrlq $8, %%mm6                                \n\t"
1240 #ifdef HAVE_MMX2
1241                 "pmaxub %%mm4, %%mm6                            \n\t" // max of pixels
1242                 "pshufw $0xF9, %%mm6, %%mm4                     \n\t"
1243                 "pmaxub %%mm4, %%mm6                            \n\t"
1244                 "pshufw $0xFE, %%mm6, %%mm4                     \n\t"
1245                 "pmaxub %%mm4, %%mm6                            \n\t"
1246 #else
1247                 "psubusb %%mm4, %%mm6                           \n\t"
1248                 "paddb %%mm4, %%mm6                             \n\t"
1249                 "movq %%mm6, %%mm4                              \n\t"
1250                 "psrlq $16, %%mm6                               \n\t"
1251                 "psubusb %%mm4, %%mm6                           \n\t"
1252                 "paddb %%mm4, %%mm6                             \n\t"
1253                 "movq %%mm6, %%mm4                              \n\t"
1254                 "psrlq $32, %%mm6                               \n\t"
1255                 "psubusb %%mm4, %%mm6                           \n\t"
1256                 "paddb %%mm4, %%mm6                             \n\t"
1257 #endif
1258                 "movq %%mm6, %%mm0                              \n\t" // max
1259                 "psubb %%mm7, %%mm6                             \n\t" // max - min
1260                 "movd %%mm6, %%ecx                              \n\t"
1261                 "cmpb "MANGLE(deringThreshold)", %%cl           \n\t"
1262                 " jb 1f                                         \n\t"
1263                 "leal -24(%%esp), %%ecx                         \n\t"
1264                 "andl $0xFFFFFFF8, %%ecx                        \n\t" 
1265                 PAVGB(%%mm0, %%mm7)                                   // a=(max + min)/2
1266                 "punpcklbw %%mm7, %%mm7                         \n\t"
1267                 "punpcklbw %%mm7, %%mm7                         \n\t"
1268                 "punpcklbw %%mm7, %%mm7                         \n\t"
1269                 "movq %%mm7, (%%ecx)                            \n\t"
1270
1271                 "movq (%0), %%mm0                               \n\t" // L10
1272                 "movq %%mm0, %%mm1                              \n\t" // L10
1273                 "movq %%mm0, %%mm2                              \n\t" // L10
1274                 "psllq $8, %%mm1                                \n\t"
1275                 "psrlq $8, %%mm2                                \n\t"
1276                 "movd -4(%0), %%mm3                             \n\t"
1277                 "movd 8(%0), %%mm4                              \n\t"
1278                 "psrlq $24, %%mm3                               \n\t"
1279                 "psllq $56, %%mm4                               \n\t"
1280                 "por %%mm3, %%mm1                               \n\t" // L00
1281                 "por %%mm4, %%mm2                               \n\t" // L20
1282                 "movq %%mm1, %%mm3                              \n\t" // L00
1283                 PAVGB(%%mm2, %%mm1)                                   // (L20 + L00)/2
1284                 PAVGB(%%mm0, %%mm1)                                   // (L20 + L00 + 2L10)/4
1285                 "psubusb %%mm7, %%mm0                           \n\t"
1286                 "psubusb %%mm7, %%mm2                           \n\t"
1287                 "psubusb %%mm7, %%mm3                           \n\t"
1288                 "pcmpeqb "MANGLE(b00)", %%mm0                   \n\t" // L10 > a ? 0 : -1
1289                 "pcmpeqb "MANGLE(b00)", %%mm2                   \n\t" // L20 > a ? 0 : -1
1290                 "pcmpeqb "MANGLE(b00)", %%mm3                   \n\t" // L00 > a ? 0 : -1
1291                 "paddb %%mm2, %%mm0                             \n\t"
1292                 "paddb %%mm3, %%mm0                             \n\t"
1293
1294                 "movq (%%eax), %%mm2                            \n\t" // L11
1295                 "movq %%mm2, %%mm3                              \n\t" // L11
1296                 "movq %%mm2, %%mm4                              \n\t" // L11
1297                 "psllq $8, %%mm3                                \n\t"
1298                 "psrlq $8, %%mm4                                \n\t"
1299                 "movd -4(%%eax), %%mm5                          \n\t"
1300                 "movd 8(%%eax), %%mm6                           \n\t"
1301                 "psrlq $24, %%mm5                               \n\t"
1302                 "psllq $56, %%mm6                               \n\t"
1303                 "por %%mm5, %%mm3                               \n\t" // L01
1304                 "por %%mm6, %%mm4                               \n\t" // L21
1305                 "movq %%mm3, %%mm5                              \n\t" // L01
1306                 PAVGB(%%mm4, %%mm3)                                   // (L21 + L01)/2
1307                 PAVGB(%%mm2, %%mm3)                                   // (L21 + L01 + 2L11)/4
1308                 "psubusb %%mm7, %%mm2                           \n\t"
1309                 "psubusb %%mm7, %%mm4                           \n\t"
1310                 "psubusb %%mm7, %%mm5                           \n\t"
1311                 "pcmpeqb "MANGLE(b00)", %%mm2                   \n\t" // L11 > a ? 0 : -1
1312                 "pcmpeqb "MANGLE(b00)", %%mm4                   \n\t" // L21 > a ? 0 : -1
1313                 "pcmpeqb "MANGLE(b00)", %%mm5                   \n\t" // L01 > a ? 0 : -1
1314                 "paddb %%mm4, %%mm2                             \n\t"
1315                 "paddb %%mm5, %%mm2                             \n\t"
1316 // 0, 2, 3, 1
1317 #define DERING_CORE(dst,src,ppsx,psx,sx,pplx,plx,lx,t0,t1) \
1318                 "movq " #src ", " #sx "                         \n\t" /* src[0] */\
1319                 "movq " #sx ", " #lx "                          \n\t" /* src[0] */\
1320                 "movq " #sx ", " #t0 "                          \n\t" /* src[0] */\
1321                 "psllq $8, " #lx "                              \n\t"\
1322                 "psrlq $8, " #t0 "                              \n\t"\
1323                 "movd -4" #src ", " #t1 "                       \n\t"\
1324                 "psrlq $24, " #t1 "                             \n\t"\
1325                 "por " #t1 ", " #lx "                           \n\t" /* src[-1] */\
1326                 "movd 8" #src ", " #t1 "                        \n\t"\
1327                 "psllq $56, " #t1 "                             \n\t"\
1328                 "por " #t1 ", " #t0 "                           \n\t" /* src[+1] */\
1329                 "movq " #lx ", " #t1 "                          \n\t" /* src[-1] */\
1330                 PAVGB(t0, lx)                                         /* (src[-1] + src[+1])/2 */\
1331                 PAVGB(sx, lx)                                 /* (src[-1] + 2src[0] + src[+1])/4 */\
1332                 PAVGB(lx, pplx)                                      \
1333                 "movq " #lx ", 8(%%ecx)                         \n\t"\
1334                 "movq (%%ecx), " #lx "                          \n\t"\
1335                 "psubusb " #lx ", " #t1 "                       \n\t"\
1336                 "psubusb " #lx ", " #t0 "                       \n\t"\
1337                 "psubusb " #lx ", " #sx "                       \n\t"\
1338                 "movq "MANGLE(b00)", " #lx "                    \n\t"\
1339                 "pcmpeqb " #lx ", " #t1 "                       \n\t" /* src[-1] > a ? 0 : -1*/\
1340                 "pcmpeqb " #lx ", " #t0 "                       \n\t" /* src[+1] > a ? 0 : -1*/\
1341                 "pcmpeqb " #lx ", " #sx "                       \n\t" /* src[0]  > a ? 0 : -1*/\
1342                 "paddb " #t1 ", " #t0 "                         \n\t"\
1343                 "paddb " #t0 ", " #sx "                         \n\t"\
1344 \
1345                 PAVGB(plx, pplx)                                      /* filtered */\
1346                 "movq " #dst ", " #t0 "                         \n\t" /* dst */\
1347                 "movq " #t0 ", " #t1 "                          \n\t" /* dst */\
1348                 "psubusb %3, " #t0 "                            \n\t"\
1349                 "paddusb %3, " #t1 "                            \n\t"\
1350                 PMAXUB(t0, pplx)\
1351                 PMINUB(t1, pplx, t0)\
1352                 "paddb " #sx ", " #ppsx "                       \n\t"\
1353                 "paddb " #psx ", " #ppsx "                      \n\t"\
1354                 "#paddb "MANGLE(b02)", " #ppsx "                \n\t"\
1355                 "pand "MANGLE(b08)", " #ppsx "                  \n\t"\
1356                 "pcmpeqb " #lx ", " #ppsx "                     \n\t"\
1357                 "pand " #ppsx ", " #pplx "                      \n\t"\
1358                 "pandn " #dst ", " #ppsx "                      \n\t"\
1359                 "por " #pplx ", " #ppsx "                       \n\t"\
1360                 "movq " #ppsx ", " #dst "                       \n\t"\
1361                 "movq 8(%%ecx), " #lx "                         \n\t"
1362
1363 /*
1364 0000000
1365 1111111
1366
1367 1111110
1368 1111101
1369 1111100
1370 1111011
1371 1111010
1372 1111001
1373
1374 1111000
1375 1110111
1376
1377 */
1378 //DERING_CORE(dst,src                  ,ppsx ,psx  ,sx   ,pplx ,plx  ,lx   ,t0   ,t1)
1379 DERING_CORE((%%eax),(%%eax, %1)        ,%%mm0,%%mm2,%%mm4,%%mm1,%%mm3,%%mm5,%%mm6,%%mm7)
1380 DERING_CORE((%%eax, %1),(%%eax, %1, 2) ,%%mm2,%%mm4,%%mm0,%%mm3,%%mm5,%%mm1,%%mm6,%%mm7)
1381 DERING_CORE((%%eax, %1, 2),(%0, %1, 4) ,%%mm4,%%mm0,%%mm2,%%mm5,%%mm1,%%mm3,%%mm6,%%mm7)
1382 DERING_CORE((%0, %1, 4),(%%edx)        ,%%mm0,%%mm2,%%mm4,%%mm1,%%mm3,%%mm5,%%mm6,%%mm7)
1383 DERING_CORE((%%edx),(%%edx, %1)        ,%%mm2,%%mm4,%%mm0,%%mm3,%%mm5,%%mm1,%%mm6,%%mm7)
1384 DERING_CORE((%%edx, %1), (%%edx, %1, 2),%%mm4,%%mm0,%%mm2,%%mm5,%%mm1,%%mm3,%%mm6,%%mm7)
1385 DERING_CORE((%%edx, %1, 2),(%0, %1, 8) ,%%mm0,%%mm2,%%mm4,%%mm1,%%mm3,%%mm5,%%mm6,%%mm7)
1386 DERING_CORE((%0, %1, 8),(%%edx, %1, 4) ,%%mm2,%%mm4,%%mm0,%%mm3,%%mm5,%%mm1,%%mm6,%%mm7)
1387
1388                 "1:                     \n\t"
1389                 : : "r" (src), "r" (stride), "m" (c->pQPb), "m"(c->pQPb2)
1390                 : "%eax", "%edx", "%ecx"
1391         );
1392 #else
1393         int y;
1394         int min=255;
1395         int max=0;
1396         int avg;
1397         uint8_t *p;
1398         int s[10];
1399         const int QP2= c->QP/2 + 1;
1400
1401         for(y=1; y<9; y++)
1402         {
1403                 int x;
1404                 p= src + stride*y;
1405                 for(x=1; x<9; x++)
1406                 {
1407                         p++;
1408                         if(*p > max) max= *p;
1409                         if(*p < min) min= *p;
1410                 }
1411         }
1412         avg= (min + max + 1)>>1;
1413
1414         if(max - min <deringThreshold) return;
1415
1416         for(y=0; y<10; y++)
1417         {
1418                 int t = 0;
1419
1420                 if(src[stride*y + 0] > avg) t+= 1;
1421                 if(src[stride*y + 1] > avg) t+= 2;
1422                 if(src[stride*y + 2] > avg) t+= 4;
1423                 if(src[stride*y + 3] > avg) t+= 8;
1424                 if(src[stride*y + 4] > avg) t+= 16;
1425                 if(src[stride*y + 5] > avg) t+= 32;
1426                 if(src[stride*y + 6] > avg) t+= 64;
1427                 if(src[stride*y + 7] > avg) t+= 128;
1428                 if(src[stride*y + 8] > avg) t+= 256;
1429                 if(src[stride*y + 9] > avg) t+= 512;
1430                 
1431                 t |= (~t)<<16;
1432                 t &= (t<<1) & (t>>1);
1433                 s[y] = t;
1434         }
1435         
1436         for(y=1; y<9; y++)
1437         {
1438                 int t = s[y-1] & s[y] & s[y+1];
1439                 t|= t>>16;
1440                 s[y-1]= t;
1441         }
1442
1443         for(y=1; y<9; y++)
1444         {
1445                 int x;
1446                 int t = s[y-1];
1447
1448                 p= src + stride*y;
1449                 for(x=1; x<9; x++)
1450                 {
1451                         p++;
1452                         if(t & (1<<x))
1453                         {
1454                                 int f= (*(p-stride-1)) + 2*(*(p-stride)) + (*(p-stride+1))
1455                                       +2*(*(p     -1)) + 4*(*p         ) + 2*(*(p     +1))
1456                                       +(*(p+stride-1)) + 2*(*(p+stride)) + (*(p+stride+1));
1457                                 f= (f + 8)>>4;
1458
1459 #ifdef DEBUG_DERING_THRESHOLD
1460                                 asm volatile("emms\n\t":);
1461                                 {
1462                                 static long long numPixels=0;
1463                                 if(x!=1 && x!=8 && y!=1 && y!=8) numPixels++;
1464 //                              if((max-min)<20 || (max-min)*QP<200)
1465 //                              if((max-min)*QP < 500)
1466 //                              if(max-min<QP/2)
1467                                 if(max-min < 20)
1468                                 {
1469                                         static int numSkiped=0;
1470                                         static int errorSum=0;
1471                                         static int worstQP=0;
1472                                         static int worstRange=0;
1473                                         static int worstDiff=0;
1474                                         int diff= (f - *p);
1475                                         int absDiff= ABS(diff);
1476                                         int error= diff*diff;
1477
1478                                         if(x==1 || x==8 || y==1 || y==8) continue;
1479
1480                                         numSkiped++;
1481                                         if(absDiff > worstDiff)
1482                                         {
1483                                                 worstDiff= absDiff;
1484                                                 worstQP= QP;
1485                                                 worstRange= max-min;
1486                                         }
1487                                         errorSum+= error;
1488
1489                                         if(1024LL*1024LL*1024LL % numSkiped == 0)
1490                                         {
1491                                                 printf( "sum:%1.3f, skip:%d, wQP:%d, "
1492                                                         "wRange:%d, wDiff:%d, relSkip:%1.3f\n",
1493                                                         (float)errorSum/numSkiped, numSkiped, worstQP, worstRange,
1494                                                         worstDiff, (float)numSkiped/numPixels);
1495                                         }
1496                                 }
1497                                 }
1498 #endif
1499                                 if     (*p + QP2 < f) *p= *p + QP2;
1500                                 else if(*p - QP2 > f) *p= *p - QP2;
1501                                 else *p=f;
1502                         }
1503                 }
1504         }
1505 #ifdef DEBUG_DERING_THRESHOLD
1506         if(max-min < 20)
1507         {
1508                 for(y=1; y<9; y++)
1509                 {
1510                         int x;
1511                         int t = 0;
1512                         p= src + stride*y;
1513                         for(x=1; x<9; x++)
1514                         {
1515                                 p++;
1516                                 *p = MIN(*p + 20, 255);
1517                         }
1518                 }
1519 //              src[0] = src[7]=src[stride*7]=src[stride*7 + 7]=255;
1520         }
1521 #endif
1522 #endif
1523 }
1524
1525 /**
1526  * Deinterlaces the given block
1527  * will be called for every 8x8 block and can read & write from line 4-15
1528  * lines 0-3 have been passed through the deblock / dering filters allready, but can be read too
1529  * lines 4-12 will be read into the deblocking filter and should be deinterlaced
1530  */
1531 static inline void RENAME(deInterlaceInterpolateLinear)(uint8_t src[], int stride)
1532 {
1533 #if defined (HAVE_MMX2) || defined (HAVE_3DNOW)
1534         src+= 4*stride;
1535         asm volatile(
1536                 "leal (%0, %1), %%eax                           \n\t"
1537                 "leal (%%eax, %1, 4), %%ecx                     \n\t"
1538 //      0       1       2       3       4       5       6       7       8       9
1539 //      %0      eax     eax+%1  eax+2%1 %0+4%1  ecx     ecx+%1  ecx+2%1 %0+8%1  ecx+4%1
1540
1541                 "movq (%0), %%mm0                               \n\t"
1542                 "movq (%%eax, %1), %%mm1                        \n\t"
1543                 PAVGB(%%mm1, %%mm0)
1544                 "movq %%mm0, (%%eax)                            \n\t"
1545                 "movq (%0, %1, 4), %%mm0                        \n\t"
1546                 PAVGB(%%mm0, %%mm1)
1547                 "movq %%mm1, (%%eax, %1, 2)                     \n\t"
1548                 "movq (%%ecx, %1), %%mm1                        \n\t"
1549                 PAVGB(%%mm1, %%mm0)
1550                 "movq %%mm0, (%%ecx)                            \n\t"
1551                 "movq (%0, %1, 8), %%mm0                        \n\t"
1552                 PAVGB(%%mm0, %%mm1)
1553                 "movq %%mm1, (%%ecx, %1, 2)                     \n\t"
1554
1555                 : : "r" (src), "r" (stride)
1556                 : "%eax", "%ecx"
1557         );
1558 #else
1559         int x;
1560         src+= 4*stride;
1561         for(x=0; x<8; x++)
1562         {
1563                 src[stride]   = (src[0]        + src[stride*2])>>1;
1564                 src[stride*3] = (src[stride*2] + src[stride*4])>>1;
1565                 src[stride*5] = (src[stride*4] + src[stride*6])>>1;
1566                 src[stride*7] = (src[stride*6] + src[stride*8])>>1;
1567                 src++;
1568         }
1569 #endif
1570 }
1571
1572 /**
1573  * Deinterlaces the given block
1574  * will be called for every 8x8 block and can read & write from line 4-15
1575  * lines 0-3 have been passed through the deblock / dering filters allready, but can be read too
1576  * lines 4-12 will be read into the deblocking filter and should be deinterlaced
1577  * this filter will read lines 3-15 and write 7-13
1578  * no cliping in C version
1579  */
1580 static inline void RENAME(deInterlaceInterpolateCubic)(uint8_t src[], int stride)
1581 {
1582 #if defined (HAVE_MMX2) || defined (HAVE_3DNOW)
1583         src+= stride*3;
1584         asm volatile(
1585                 "leal (%0, %1), %%eax                           \n\t"
1586                 "leal (%%eax, %1, 4), %%edx                     \n\t"
1587                 "leal (%%edx, %1, 4), %%ecx                     \n\t"
1588                 "addl %1, %%ecx                                 \n\t"
1589                 "pxor %%mm7, %%mm7                              \n\t"
1590 //      0       1       2       3       4       5       6       7       8       9       10
1591 //      %0      eax     eax+%1  eax+2%1 %0+4%1  edx     edx+%1  edx+2%1 %0+8%1  edx+4%1 ecx
1592
1593 #define DEINT_CUBIC(a,b,c,d,e)\
1594                 "movq " #a ", %%mm0                             \n\t"\
1595                 "movq " #b ", %%mm1                             \n\t"\
1596                 "movq " #d ", %%mm2                             \n\t"\
1597                 "movq " #e ", %%mm3                             \n\t"\
1598                 PAVGB(%%mm2, %%mm1)                                     /* (b+d) /2 */\
1599                 PAVGB(%%mm3, %%mm0)                                     /* a(a+e) /2 */\
1600                 "movq %%mm0, %%mm2                              \n\t"\
1601                 "punpcklbw %%mm7, %%mm0                         \n\t"\
1602                 "punpckhbw %%mm7, %%mm2                         \n\t"\
1603                 "movq %%mm1, %%mm3                              \n\t"\
1604                 "punpcklbw %%mm7, %%mm1                         \n\t"\
1605                 "punpckhbw %%mm7, %%mm3                         \n\t"\
1606                 "psubw %%mm1, %%mm0                             \n\t"   /* L(a+e - (b+d))/2 */\
1607                 "psubw %%mm3, %%mm2                             \n\t"   /* H(a+e - (b+d))/2 */\
1608                 "psraw $3, %%mm0                                \n\t"   /* L(a+e - (b+d))/16 */\
1609                 "psraw $3, %%mm2                                \n\t"   /* H(a+e - (b+d))/16 */\
1610                 "psubw %%mm0, %%mm1                             \n\t"   /* L(9b + 9d - a - e)/16 */\
1611                 "psubw %%mm2, %%mm3                             \n\t"   /* H(9b + 9d - a - e)/16 */\
1612                 "packuswb %%mm3, %%mm1                          \n\t"\
1613                 "movq %%mm1, " #c "                             \n\t"
1614
1615 DEINT_CUBIC((%0), (%%eax, %1), (%%eax, %1, 2), (%0, %1, 4), (%%edx, %1))
1616 DEINT_CUBIC((%%eax, %1), (%0, %1, 4), (%%edx), (%%edx, %1), (%0, %1, 8))
1617 DEINT_CUBIC((%0, %1, 4), (%%edx, %1), (%%edx, %1, 2), (%0, %1, 8), (%%ecx))
1618 DEINT_CUBIC((%%edx, %1), (%0, %1, 8), (%%edx, %1, 4), (%%ecx), (%%ecx, %1, 2))
1619
1620                 : : "r" (src), "r" (stride)
1621                 : "%eax", "%edx", "ecx"
1622         );
1623 #else
1624         int x;
1625         src+= stride*3;
1626         for(x=0; x<8; x++)
1627         {
1628                 src[stride*3] = (-src[0]        + 9*src[stride*2] + 9*src[stride*4] - src[stride*6])>>4;
1629                 src[stride*5] = (-src[stride*2] + 9*src[stride*4] + 9*src[stride*6] - src[stride*8])>>4;
1630                 src[stride*7] = (-src[stride*4] + 9*src[stride*6] + 9*src[stride*8] - src[stride*10])>>4;
1631                 src[stride*9] = (-src[stride*6] + 9*src[stride*8] + 9*src[stride*10] - src[stride*12])>>4;
1632                 src++;
1633         }
1634 #endif
1635 }
1636
1637 /**
1638  * Deinterlaces the given block
1639  * will be called for every 8x8 block and can read & write from line 4-15
1640  * lines 0-3 have been passed through the deblock / dering filters allready, but can be read too
1641  * lines 4-12 will be read into the deblocking filter and should be deinterlaced
1642  * this filter will read lines 4-13 and write 5-11
1643  * no cliping in C version
1644  */
1645 static inline void RENAME(deInterlaceFF)(uint8_t src[], int stride, uint8_t *tmp)
1646 {
1647 #if defined (HAVE_MMX2) || defined (HAVE_3DNOW)
1648         src+= stride*4;
1649         asm volatile(
1650                 "leal (%0, %1), %%eax                           \n\t"
1651                 "leal (%%eax, %1, 4), %%edx                     \n\t"
1652                 "pxor %%mm7, %%mm7                              \n\t"
1653                 "movq (%2), %%mm0                               \n\t"
1654 //      0       1       2       3       4       5       6       7       8       9       10
1655 //      %0      eax     eax+%1  eax+2%1 %0+4%1  edx     edx+%1  edx+2%1 %0+8%1  edx+4%1 ecx
1656
1657 #define DEINT_FF(a,b,c,d)\
1658                 "movq " #a ", %%mm1                             \n\t"\
1659                 "movq " #b ", %%mm2                             \n\t"\
1660                 "movq " #c ", %%mm3                             \n\t"\
1661                 "movq " #d ", %%mm4                             \n\t"\
1662                 PAVGB(%%mm3, %%mm1)                                     \
1663                 PAVGB(%%mm4, %%mm0)                                     \
1664                 "movq %%mm0, %%mm3                              \n\t"\
1665                 "punpcklbw %%mm7, %%mm0                         \n\t"\
1666                 "punpckhbw %%mm7, %%mm3                         \n\t"\
1667                 "movq %%mm1, %%mm4                              \n\t"\
1668                 "punpcklbw %%mm7, %%mm1                         \n\t"\
1669                 "punpckhbw %%mm7, %%mm4                         \n\t"\
1670                 "psllw $2, %%mm1                                \n\t"\
1671                 "psllw $2, %%mm4                                \n\t"\
1672                 "psubw %%mm0, %%mm1                             \n\t"\
1673                 "psubw %%mm3, %%mm4                             \n\t"\
1674                 "movq %%mm2, %%mm5                              \n\t"\
1675                 "movq %%mm2, %%mm0                              \n\t"\
1676                 "punpcklbw %%mm7, %%mm2                         \n\t"\
1677                 "punpckhbw %%mm7, %%mm5                         \n\t"\
1678                 "paddw %%mm2, %%mm1                             \n\t"\
1679                 "paddw %%mm5, %%mm4                             \n\t"\
1680                 "psraw $2, %%mm1                                \n\t"\
1681                 "psraw $2, %%mm4                                \n\t"\
1682                 "packuswb %%mm4, %%mm1                          \n\t"\
1683                 "movq %%mm1, " #b "                             \n\t"\
1684
1685 DEINT_FF((%0)       , (%%eax)       , (%%eax, %1), (%%eax, %1, 2))
1686 DEINT_FF((%%eax, %1), (%%eax, %1, 2), (%0, %1, 4), (%%edx)       )
1687 DEINT_FF((%0, %1, 4), (%%edx)       , (%%edx, %1), (%%edx, %1, 2))
1688 DEINT_FF((%%edx, %1), (%%edx, %1, 2), (%0, %1, 8), (%%edx, %1, 4))
1689
1690                 "movq %%mm0, (%2)                               \n\t"
1691                 : : "r" (src), "r" (stride), "r"(tmp)
1692                 : "%eax", "%edx"
1693         );
1694 #else
1695         int x;
1696         src+= stride*4;
1697         for(x=0; x<8; x++)
1698         {
1699                 int t1= tmp[x];
1700                 int t2= src[stride*1];
1701
1702                 src[stride*1]= (-t1 + 4*src[stride*0] + 2*t2 + 4*src[stride*2] - src[stride*3] + 4)>>3;
1703                 t1= src[stride*4];
1704                 src[stride*3]= (-t2 + 4*src[stride*2] + 2*t1 + 4*src[stride*4] - src[stride*5] + 4)>>3;
1705                 t2= src[stride*6];
1706                 src[stride*5]= (-t1 + 4*src[stride*4] + 2*t2 + 4*src[stride*6] - src[stride*7] + 4)>>3;
1707                 t1= src[stride*8];
1708                 src[stride*7]= (-t2 + 4*src[stride*6] + 2*t1 + 4*src[stride*8] - src[stride*9] + 4)>>3;
1709                 tmp[x]= t1;
1710
1711                 src++;
1712         }
1713 #endif
1714 }
1715
1716 /**
1717  * Deinterlaces the given block
1718  * will be called for every 8x8 block and can read & write from line 4-15
1719  * lines 0-3 have been passed through the deblock / dering filters allready, but can be read too
1720  * lines 4-12 will be read into the deblocking filter and should be deinterlaced
1721  * will shift the image up by 1 line (FIXME if this is a problem)
1722  * this filter will read lines 4-13 and write 4-11
1723  */
1724 static inline void RENAME(deInterlaceBlendLinear)(uint8_t src[], int stride)
1725 {
1726 #if defined (HAVE_MMX2) || defined (HAVE_3DNOW)
1727         src+= 4*stride;
1728         asm volatile(
1729                 "leal (%0, %1), %%eax                           \n\t"
1730                 "leal (%%eax, %1, 4), %%edx                     \n\t"
1731 //      0       1       2       3       4       5       6       7       8       9
1732 //      %0      eax     eax+%1  eax+2%1 %0+4%1  edx     edx+%1  edx+2%1 %0+8%1  edx+4%1
1733
1734                 "movq (%0), %%mm0                               \n\t" // L0
1735                 "movq (%%eax, %1), %%mm1                        \n\t" // L2
1736                 PAVGB(%%mm1, %%mm0)                                   // L0+L2
1737                 "movq (%%eax), %%mm2                            \n\t" // L1
1738                 PAVGB(%%mm2, %%mm0)
1739                 "movq %%mm0, (%0)                               \n\t"
1740                 "movq (%%eax, %1, 2), %%mm0                     \n\t" // L3
1741                 PAVGB(%%mm0, %%mm2)                                   // L1+L3
1742                 PAVGB(%%mm1, %%mm2)                                   // 2L2 + L1 + L3
1743                 "movq %%mm2, (%%eax)                            \n\t"
1744                 "movq (%0, %1, 4), %%mm2                        \n\t" // L4
1745                 PAVGB(%%mm2, %%mm1)                                   // L2+L4
1746                 PAVGB(%%mm0, %%mm1)                                   // 2L3 + L2 + L4
1747                 "movq %%mm1, (%%eax, %1)                        \n\t"
1748                 "movq (%%edx), %%mm1                            \n\t" // L5
1749                 PAVGB(%%mm1, %%mm0)                                   // L3+L5
1750                 PAVGB(%%mm2, %%mm0)                                   // 2L4 + L3 + L5
1751                 "movq %%mm0, (%%eax, %1, 2)                     \n\t"
1752                 "movq (%%edx, %1), %%mm0                        \n\t" // L6
1753                 PAVGB(%%mm0, %%mm2)                                   // L4+L6
1754                 PAVGB(%%mm1, %%mm2)                                   // 2L5 + L4 + L6
1755                 "movq %%mm2, (%0, %1, 4)                        \n\t"
1756                 "movq (%%edx, %1, 2), %%mm2                     \n\t" // L7
1757                 PAVGB(%%mm2, %%mm1)                                   // L5+L7
1758                 PAVGB(%%mm0, %%mm1)                                   // 2L6 + L5 + L7
1759                 "movq %%mm1, (%%edx)                            \n\t"
1760                 "movq (%0, %1, 8), %%mm1                        \n\t" // L8
1761                 PAVGB(%%mm1, %%mm0)                                   // L6+L8
1762                 PAVGB(%%mm2, %%mm0)                                   // 2L7 + L6 + L8
1763                 "movq %%mm0, (%%edx, %1)                        \n\t"
1764                 "movq (%%edx, %1, 4), %%mm0                     \n\t" // L9
1765                 PAVGB(%%mm0, %%mm2)                                   // L7+L9
1766                 PAVGB(%%mm1, %%mm2)                                   // 2L8 + L7 + L9
1767                 "movq %%mm2, (%%edx, %1, 2)                     \n\t"
1768
1769
1770                 : : "r" (src), "r" (stride)
1771                 : "%eax", "%edx"
1772         );
1773 #else
1774         int x;
1775         src+= 4*stride;
1776         for(x=0; x<8; x++)
1777         {
1778                 src[0       ] = (src[0       ] + 2*src[stride  ] + src[stride*2])>>2;
1779                 src[stride  ] = (src[stride  ] + 2*src[stride*2] + src[stride*3])>>2;
1780                 src[stride*2] = (src[stride*2] + 2*src[stride*3] + src[stride*4])>>2;
1781                 src[stride*3] = (src[stride*3] + 2*src[stride*4] + src[stride*5])>>2;
1782                 src[stride*4] = (src[stride*4] + 2*src[stride*5] + src[stride*6])>>2;
1783                 src[stride*5] = (src[stride*5] + 2*src[stride*6] + src[stride*7])>>2;
1784                 src[stride*6] = (src[stride*6] + 2*src[stride*7] + src[stride*8])>>2;
1785                 src[stride*7] = (src[stride*7] + 2*src[stride*8] + src[stride*9])>>2;
1786                 src++;
1787         }
1788 #endif
1789 }
1790
1791 /**
1792  * Deinterlaces the given block
1793  * will be called for every 8x8 block and can read & write from line 4-15,
1794  * lines 0-3 have been passed through the deblock / dering filters allready, but can be read too
1795  * lines 4-12 will be read into the deblocking filter and should be deinterlaced
1796  */
1797 static inline void RENAME(deInterlaceMedian)(uint8_t src[], int stride)
1798 {
1799 #ifdef HAVE_MMX
1800         src+= 4*stride;
1801 #ifdef HAVE_MMX2
1802         asm volatile(
1803                 "leal (%0, %1), %%eax                           \n\t"
1804                 "leal (%%eax, %1, 4), %%edx                     \n\t"
1805 //      0       1       2       3       4       5       6       7       8       9
1806 //      %0      eax     eax+%1  eax+2%1 %0+4%1  edx     edx+%1  edx+2%1 %0+8%1  edx+4%1
1807
1808                 "movq (%0), %%mm0                               \n\t" //
1809                 "movq (%%eax, %1), %%mm2                        \n\t" //
1810                 "movq (%%eax), %%mm1                            \n\t" //
1811                 "movq %%mm0, %%mm3                              \n\t"
1812                 "pmaxub %%mm1, %%mm0                            \n\t" //
1813                 "pminub %%mm3, %%mm1                            \n\t" //
1814                 "pmaxub %%mm2, %%mm1                            \n\t" //
1815                 "pminub %%mm1, %%mm0                            \n\t"
1816                 "movq %%mm0, (%%eax)                            \n\t"
1817
1818                 "movq (%0, %1, 4), %%mm0                        \n\t" //
1819                 "movq (%%eax, %1, 2), %%mm1                     \n\t" //
1820                 "movq %%mm2, %%mm3                              \n\t"
1821                 "pmaxub %%mm1, %%mm2                            \n\t" //
1822                 "pminub %%mm3, %%mm1                            \n\t" //
1823                 "pmaxub %%mm0, %%mm1                            \n\t" //
1824                 "pminub %%mm1, %%mm2                            \n\t"
1825                 "movq %%mm2, (%%eax, %1, 2)                     \n\t"
1826
1827                 "movq (%%edx), %%mm2                            \n\t" //
1828                 "movq (%%edx, %1), %%mm1                        \n\t" //
1829                 "movq %%mm2, %%mm3                              \n\t"
1830                 "pmaxub %%mm0, %%mm2                            \n\t" //
1831                 "pminub %%mm3, %%mm0                            \n\t" //
1832                 "pmaxub %%mm1, %%mm0                            \n\t" //
1833                 "pminub %%mm0, %%mm2                            \n\t"
1834                 "movq %%mm2, (%%edx)                            \n\t"
1835
1836                 "movq (%%edx, %1, 2), %%mm2                     \n\t" //
1837                 "movq (%0, %1, 8), %%mm0                        \n\t" //
1838                 "movq %%mm2, %%mm3                              \n\t"
1839                 "pmaxub %%mm0, %%mm2                            \n\t" //
1840                 "pminub %%mm3, %%mm0                            \n\t" //
1841                 "pmaxub %%mm1, %%mm0                            \n\t" //
1842                 "pminub %%mm0, %%mm2                            \n\t"
1843                 "movq %%mm2, (%%edx, %1, 2)                     \n\t"
1844
1845
1846                 : : "r" (src), "r" (stride)
1847                 : "%eax", "%edx"
1848         );
1849
1850 #else // MMX without MMX2
1851         asm volatile(
1852                 "leal (%0, %1), %%eax                           \n\t"
1853                 "leal (%%eax, %1, 4), %%edx                     \n\t"
1854 //      0       1       2       3       4       5       6       7       8       9
1855 //      %0      eax     eax+%1  eax+2%1 %0+4%1  edx     edx+%1  edx+2%1 %0+8%1  edx+4%1
1856                 "pxor %%mm7, %%mm7                              \n\t"
1857
1858 #define MEDIAN(a,b,c)\
1859                 "movq " #a ", %%mm0                             \n\t"\
1860                 "movq " #b ", %%mm2                             \n\t"\
1861                 "movq " #c ", %%mm1                             \n\t"\
1862                 "movq %%mm0, %%mm3                              \n\t"\
1863                 "movq %%mm1, %%mm4                              \n\t"\
1864                 "movq %%mm2, %%mm5                              \n\t"\
1865                 "psubusb %%mm1, %%mm3                           \n\t"\
1866                 "psubusb %%mm2, %%mm4                           \n\t"\
1867                 "psubusb %%mm0, %%mm5                           \n\t"\
1868                 "pcmpeqb %%mm7, %%mm3                           \n\t"\
1869                 "pcmpeqb %%mm7, %%mm4                           \n\t"\
1870                 "pcmpeqb %%mm7, %%mm5                           \n\t"\
1871                 "movq %%mm3, %%mm6                              \n\t"\
1872                 "pxor %%mm4, %%mm3                              \n\t"\
1873                 "pxor %%mm5, %%mm4                              \n\t"\
1874                 "pxor %%mm6, %%mm5                              \n\t"\
1875                 "por %%mm3, %%mm1                               \n\t"\
1876                 "por %%mm4, %%mm2                               \n\t"\
1877                 "por %%mm5, %%mm0                               \n\t"\
1878                 "pand %%mm2, %%mm0                              \n\t"\
1879                 "pand %%mm1, %%mm0                              \n\t"\
1880                 "movq %%mm0, " #b "                             \n\t"
1881
1882 MEDIAN((%0), (%%eax), (%%eax, %1))
1883 MEDIAN((%%eax, %1), (%%eax, %1, 2), (%0, %1, 4))
1884 MEDIAN((%0, %1, 4), (%%edx), (%%edx, %1))
1885 MEDIAN((%%edx, %1), (%%edx, %1, 2), (%0, %1, 8))
1886
1887                 : : "r" (src), "r" (stride)
1888                 : "%eax", "%edx"
1889         );
1890 #endif // MMX
1891 #else
1892         //FIXME
1893         int x;
1894         src+= 4*stride;
1895         for(x=0; x<8; x++)
1896         {
1897                 src[0       ] = (src[0       ] + 2*src[stride  ] + src[stride*2])>>2;
1898                 src[stride  ] = (src[stride  ] + 2*src[stride*2] + src[stride*3])>>2;
1899                 src[stride*2] = (src[stride*2] + 2*src[stride*3] + src[stride*4])>>2;
1900                 src[stride*3] = (src[stride*3] + 2*src[stride*4] + src[stride*5])>>2;
1901                 src[stride*4] = (src[stride*4] + 2*src[stride*5] + src[stride*6])>>2;
1902                 src[stride*5] = (src[stride*5] + 2*src[stride*6] + src[stride*7])>>2;
1903                 src[stride*6] = (src[stride*6] + 2*src[stride*7] + src[stride*8])>>2;
1904                 src[stride*7] = (src[stride*7] + 2*src[stride*8] + src[stride*9])>>2;
1905                 src++;
1906         }
1907 #endif
1908 }
1909
1910 #ifdef HAVE_MMX
1911 /**
1912  * transposes and shift the given 8x8 Block into dst1 and dst2
1913  */
1914 static inline void RENAME(transpose1)(uint8_t *dst1, uint8_t *dst2, uint8_t *src, int srcStride)
1915 {
1916         asm(
1917                 "leal (%0, %1), %%eax                           \n\t"
1918 //      0       1       2       3       4       5       6       7       8       9
1919 //      %0      eax     eax+%1  eax+2%1 %0+4%1  edx     edx+%1  edx+2%1 %0+8%1  edx+4%1
1920                 "movq (%0), %%mm0               \n\t" // 12345678
1921                 "movq (%%eax), %%mm1            \n\t" // abcdefgh
1922                 "movq %%mm0, %%mm2              \n\t" // 12345678
1923                 "punpcklbw %%mm1, %%mm0         \n\t" // 1a2b3c4d
1924                 "punpckhbw %%mm1, %%mm2         \n\t" // 5e6f7g8h
1925
1926                 "movq (%%eax, %1), %%mm1        \n\t"
1927                 "movq (%%eax, %1, 2), %%mm3     \n\t"
1928                 "movq %%mm1, %%mm4              \n\t"
1929                 "punpcklbw %%mm3, %%mm1         \n\t"
1930                 "punpckhbw %%mm3, %%mm4         \n\t"
1931
1932                 "movq %%mm0, %%mm3              \n\t"
1933                 "punpcklwd %%mm1, %%mm0         \n\t"
1934                 "punpckhwd %%mm1, %%mm3         \n\t"
1935                 "movq %%mm2, %%mm1              \n\t"
1936                 "punpcklwd %%mm4, %%mm2         \n\t"
1937                 "punpckhwd %%mm4, %%mm1         \n\t"
1938
1939                 "movd %%mm0, 128(%2)            \n\t"
1940                 "psrlq $32, %%mm0               \n\t"
1941                 "movd %%mm0, 144(%2)            \n\t"
1942                 "movd %%mm3, 160(%2)            \n\t"
1943                 "psrlq $32, %%mm3               \n\t"
1944                 "movd %%mm3, 176(%2)            \n\t"
1945                 "movd %%mm3, 48(%3)             \n\t"
1946                 "movd %%mm2, 192(%2)            \n\t"
1947                 "movd %%mm2, 64(%3)             \n\t"
1948                 "psrlq $32, %%mm2               \n\t"
1949                 "movd %%mm2, 80(%3)             \n\t"
1950                 "movd %%mm1, 96(%3)             \n\t"
1951                 "psrlq $32, %%mm1               \n\t"
1952                 "movd %%mm1, 112(%3)            \n\t"
1953
1954                 "leal (%%eax, %1, 4), %%eax     \n\t"
1955                 
1956                 "movq (%0, %1, 4), %%mm0        \n\t" // 12345678
1957                 "movq (%%eax), %%mm1            \n\t" // abcdefgh
1958                 "movq %%mm0, %%mm2              \n\t" // 12345678
1959                 "punpcklbw %%mm1, %%mm0         \n\t" // 1a2b3c4d
1960                 "punpckhbw %%mm1, %%mm2         \n\t" // 5e6f7g8h
1961
1962                 "movq (%%eax, %1), %%mm1        \n\t"
1963                 "movq (%%eax, %1, 2), %%mm3     \n\t"
1964                 "movq %%mm1, %%mm4              \n\t"
1965                 "punpcklbw %%mm3, %%mm1         \n\t"
1966                 "punpckhbw %%mm3, %%mm4         \n\t"
1967
1968                 "movq %%mm0, %%mm3              \n\t"
1969                 "punpcklwd %%mm1, %%mm0         \n\t"
1970                 "punpckhwd %%mm1, %%mm3         \n\t"
1971                 "movq %%mm2, %%mm1              \n\t"
1972                 "punpcklwd %%mm4, %%mm2         \n\t"
1973                 "punpckhwd %%mm4, %%mm1         \n\t"
1974
1975                 "movd %%mm0, 132(%2)            \n\t"
1976                 "psrlq $32, %%mm0               \n\t"
1977                 "movd %%mm0, 148(%2)            \n\t"
1978                 "movd %%mm3, 164(%2)            \n\t"
1979                 "psrlq $32, %%mm3               \n\t"
1980                 "movd %%mm3, 180(%2)            \n\t"
1981                 "movd %%mm3, 52(%3)             \n\t"
1982                 "movd %%mm2, 196(%2)            \n\t"
1983                 "movd %%mm2, 68(%3)             \n\t"
1984                 "psrlq $32, %%mm2               \n\t"
1985                 "movd %%mm2, 84(%3)             \n\t"
1986                 "movd %%mm1, 100(%3)            \n\t"
1987                 "psrlq $32, %%mm1               \n\t"
1988                 "movd %%mm1, 116(%3)            \n\t"
1989
1990
1991         :: "r" (src), "r" (srcStride), "r" (dst1), "r" (dst2)
1992         : "%eax"
1993         );
1994 }
1995
1996 /**
1997  * transposes the given 8x8 block
1998  */
1999 static inline void RENAME(transpose2)(uint8_t *dst, int dstStride, uint8_t *src)
2000 {
2001         asm(
2002                 "leal (%0, %1), %%eax                           \n\t"
2003                 "leal (%%eax, %1, 4), %%edx                     \n\t"
2004 //      0       1       2       3       4       5       6       7       8       9
2005 //      %0      eax     eax+%1  eax+2%1 %0+4%1  edx     edx+%1  edx+2%1 %0+8%1  edx+4%1
2006                 "movq (%2), %%mm0               \n\t" // 12345678
2007                 "movq 16(%2), %%mm1             \n\t" // abcdefgh
2008                 "movq %%mm0, %%mm2              \n\t" // 12345678
2009                 "punpcklbw %%mm1, %%mm0         \n\t" // 1a2b3c4d
2010                 "punpckhbw %%mm1, %%mm2         \n\t" // 5e6f7g8h
2011
2012                 "movq 32(%2), %%mm1             \n\t"
2013                 "movq 48(%2), %%mm3             \n\t"
2014                 "movq %%mm1, %%mm4              \n\t"
2015                 "punpcklbw %%mm3, %%mm1         \n\t"
2016                 "punpckhbw %%mm3, %%mm4         \n\t"
2017
2018                 "movq %%mm0, %%mm3              \n\t"
2019                 "punpcklwd %%mm1, %%mm0         \n\t"
2020                 "punpckhwd %%mm1, %%mm3         \n\t"
2021                 "movq %%mm2, %%mm1              \n\t"
2022                 "punpcklwd %%mm4, %%mm2         \n\t"
2023                 "punpckhwd %%mm4, %%mm1         \n\t"
2024
2025                 "movd %%mm0, (%0)               \n\t"
2026                 "psrlq $32, %%mm0               \n\t"
2027                 "movd %%mm0, (%%eax)            \n\t"
2028                 "movd %%mm3, (%%eax, %1)        \n\t"
2029                 "psrlq $32, %%mm3               \n\t"
2030                 "movd %%mm3, (%%eax, %1, 2)     \n\t"
2031                 "movd %%mm2, (%0, %1, 4)        \n\t"
2032                 "psrlq $32, %%mm2               \n\t"
2033                 "movd %%mm2, (%%edx)            \n\t"
2034                 "movd %%mm1, (%%edx, %1)        \n\t"
2035                 "psrlq $32, %%mm1               \n\t"
2036                 "movd %%mm1, (%%edx, %1, 2)     \n\t"
2037
2038
2039                 "movq 64(%2), %%mm0             \n\t" // 12345678
2040                 "movq 80(%2), %%mm1             \n\t" // abcdefgh
2041                 "movq %%mm0, %%mm2              \n\t" // 12345678
2042                 "punpcklbw %%mm1, %%mm0         \n\t" // 1a2b3c4d
2043                 "punpckhbw %%mm1, %%mm2         \n\t" // 5e6f7g8h
2044
2045                 "movq 96(%2), %%mm1             \n\t"
2046                 "movq 112(%2), %%mm3            \n\t"
2047                 "movq %%mm1, %%mm4              \n\t"
2048                 "punpcklbw %%mm3, %%mm1         \n\t"
2049                 "punpckhbw %%mm3, %%mm4         \n\t"
2050
2051                 "movq %%mm0, %%mm3              \n\t"
2052                 "punpcklwd %%mm1, %%mm0         \n\t"
2053                 "punpckhwd %%mm1, %%mm3         \n\t"
2054                 "movq %%mm2, %%mm1              \n\t"
2055                 "punpcklwd %%mm4, %%mm2         \n\t"
2056                 "punpckhwd %%mm4, %%mm1         \n\t"
2057
2058                 "movd %%mm0, 4(%0)              \n\t"
2059                 "psrlq $32, %%mm0               \n\t"
2060                 "movd %%mm0, 4(%%eax)           \n\t"
2061                 "movd %%mm3, 4(%%eax, %1)       \n\t"
2062                 "psrlq $32, %%mm3               \n\t"
2063                 "movd %%mm3, 4(%%eax, %1, 2)    \n\t"
2064                 "movd %%mm2, 4(%0, %1, 4)       \n\t"
2065                 "psrlq $32, %%mm2               \n\t"
2066                 "movd %%mm2, 4(%%edx)           \n\t"
2067                 "movd %%mm1, 4(%%edx, %1)       \n\t"
2068                 "psrlq $32, %%mm1               \n\t"
2069                 "movd %%mm1, 4(%%edx, %1, 2)    \n\t"
2070
2071         :: "r" (dst), "r" (dstStride), "r" (src)
2072         : "%eax", "%edx"
2073         );
2074 }
2075 #endif
2076 //static int test=0;
2077
2078 static void inline RENAME(tempNoiseReducer)(uint8_t *src, int stride,
2079                                     uint8_t *tempBlured, uint32_t *tempBluredPast, int *maxNoise)
2080 {
2081         // to save a register (FIXME do this outside of the loops)
2082         tempBluredPast[127]= maxNoise[0];
2083         tempBluredPast[128]= maxNoise[1];
2084         tempBluredPast[129]= maxNoise[2];
2085         
2086 #define FAST_L2_DIFF
2087 //#define L1_DIFF //u should change the thresholds too if u try that one
2088 #if defined (HAVE_MMX2) || defined (HAVE_3DNOW)
2089         asm volatile(
2090                 "leal (%2, %2, 2), %%eax                        \n\t" // 3*stride
2091                 "leal (%2, %2, 4), %%edx                        \n\t" // 5*stride
2092                 "leal (%%edx, %2, 2), %%ecx                     \n\t" // 7*stride
2093 //      0       1       2       3       4       5       6       7       8       9
2094 //      %x      %x+%2   %x+2%2  %x+eax  %x+4%2  %x+edx  %x+2eax %x+ecx  %x+8%2
2095 //FIXME reorder?
2096 #ifdef L1_DIFF //needs mmx2
2097                 "movq (%0), %%mm0                               \n\t" // L0
2098                 "psadbw (%1), %%mm0                             \n\t" // |L0-R0|
2099                 "movq (%0, %2), %%mm1                           \n\t" // L1
2100                 "psadbw (%1, %2), %%mm1                         \n\t" // |L1-R1|
2101                 "movq (%0, %2, 2), %%mm2                        \n\t" // L2
2102                 "psadbw (%1, %2, 2), %%mm2                      \n\t" // |L2-R2|
2103                 "movq (%0, %%eax), %%mm3                        \n\t" // L3
2104                 "psadbw (%1, %%eax), %%mm3                      \n\t" // |L3-R3|
2105
2106                 "movq (%0, %2, 4), %%mm4                        \n\t" // L4
2107                 "paddw %%mm1, %%mm0                             \n\t"
2108                 "psadbw (%1, %2, 4), %%mm4                      \n\t" // |L4-R4|
2109                 "movq (%0, %%edx), %%mm5                        \n\t" // L5
2110                 "paddw %%mm2, %%mm0                             \n\t"
2111                 "psadbw (%1, %%edx), %%mm5                      \n\t" // |L5-R5|
2112                 "movq (%0, %%eax, 2), %%mm6                     \n\t" // L6
2113                 "paddw %%mm3, %%mm0                             \n\t"
2114                 "psadbw (%1, %%eax, 2), %%mm6                   \n\t" // |L6-R6|
2115                 "movq (%0, %%ecx), %%mm7                        \n\t" // L7
2116                 "paddw %%mm4, %%mm0                             \n\t"
2117                 "psadbw (%1, %%ecx), %%mm7                      \n\t" // |L7-R7|
2118                 "paddw %%mm5, %%mm6                             \n\t"
2119                 "paddw %%mm7, %%mm6                             \n\t"
2120                 "paddw %%mm6, %%mm0                             \n\t"
2121 #elif defined (FAST_L2_DIFF)
2122                 "pcmpeqb %%mm7, %%mm7                           \n\t"
2123                 "movq "MANGLE(b80)", %%mm6                      \n\t"
2124                 "pxor %%mm0, %%mm0                              \n\t"
2125 #define L2_DIFF_CORE(a, b)\
2126                 "movq " #a ", %%mm5                             \n\t"\
2127                 "movq " #b ", %%mm2                             \n\t"\
2128                 "pxor %%mm7, %%mm2                              \n\t"\
2129                 PAVGB(%%mm2, %%mm5)\
2130                 "paddb %%mm6, %%mm5                             \n\t"\
2131                 "movq %%mm5, %%mm2                              \n\t"\
2132                 "psllw $8, %%mm5                                \n\t"\
2133                 "pmaddwd %%mm5, %%mm5                           \n\t"\
2134                 "pmaddwd %%mm2, %%mm2                           \n\t"\
2135                 "paddd %%mm2, %%mm5                             \n\t"\
2136                 "psrld $14, %%mm5                               \n\t"\
2137                 "paddd %%mm5, %%mm0                             \n\t"
2138
2139 L2_DIFF_CORE((%0), (%1))
2140 L2_DIFF_CORE((%0, %2), (%1, %2))
2141 L2_DIFF_CORE((%0, %2, 2), (%1, %2, 2))
2142 L2_DIFF_CORE((%0, %%eax), (%1, %%eax))
2143 L2_DIFF_CORE((%0, %2, 4), (%1, %2, 4))
2144 L2_DIFF_CORE((%0, %%edx), (%1, %%edx))
2145 L2_DIFF_CORE((%0, %%eax,2), (%1, %%eax,2))
2146 L2_DIFF_CORE((%0, %%ecx), (%1, %%ecx))
2147
2148 #else
2149                 "pxor %%mm7, %%mm7                              \n\t"
2150                 "pxor %%mm0, %%mm0                              \n\t"
2151 #define L2_DIFF_CORE(a, b)\
2152                 "movq " #a ", %%mm5                             \n\t"\
2153                 "movq " #b ", %%mm2                             \n\t"\
2154                 "movq %%mm5, %%mm1                              \n\t"\
2155                 "movq %%mm2, %%mm3                              \n\t"\
2156                 "punpcklbw %%mm7, %%mm5                         \n\t"\
2157                 "punpckhbw %%mm7, %%mm1                         \n\t"\
2158                 "punpcklbw %%mm7, %%mm2                         \n\t"\
2159                 "punpckhbw %%mm7, %%mm3                         \n\t"\
2160                 "psubw %%mm2, %%mm5                             \n\t"\
2161                 "psubw %%mm3, %%mm1                             \n\t"\
2162                 "pmaddwd %%mm5, %%mm5                           \n\t"\
2163                 "pmaddwd %%mm1, %%mm1                           \n\t"\
2164                 "paddd %%mm1, %%mm5                             \n\t"\
2165                 "paddd %%mm5, %%mm0                             \n\t"
2166
2167 L2_DIFF_CORE((%0), (%1))
2168 L2_DIFF_CORE((%0, %2), (%1, %2))
2169 L2_DIFF_CORE((%0, %2, 2), (%1, %2, 2))
2170 L2_DIFF_CORE((%0, %%eax), (%1, %%eax))
2171 L2_DIFF_CORE((%0, %2, 4), (%1, %2, 4))
2172 L2_DIFF_CORE((%0, %%edx), (%1, %%edx))
2173 L2_DIFF_CORE((%0, %%eax,2), (%1, %%eax,2))
2174 L2_DIFF_CORE((%0, %%ecx), (%1, %%ecx))
2175
2176 #endif
2177
2178                 "movq %%mm0, %%mm4                              \n\t"
2179                 "psrlq $32, %%mm0                               \n\t"
2180                 "paddd %%mm0, %%mm4                             \n\t"
2181                 "movd %%mm4, %%ecx                              \n\t"
2182                 "shll $2, %%ecx                                 \n\t"
2183                 "movl %3, %%edx                                 \n\t"
2184                 "addl -4(%%edx), %%ecx                          \n\t"
2185                 "addl 4(%%edx), %%ecx                           \n\t"
2186                 "addl -1024(%%edx), %%ecx                       \n\t"
2187                 "addl $4, %%ecx                                 \n\t"
2188                 "addl 1024(%%edx), %%ecx                        \n\t"
2189                 "shrl $3, %%ecx                                 \n\t"
2190                 "movl %%ecx, (%%edx)                            \n\t"
2191
2192 //              "movl %3, %%ecx                                 \n\t"
2193 //              "movl %%ecx, test                               \n\t"
2194 //              "jmp 4f \n\t"
2195                 "cmpl 512(%%edx), %%ecx                         \n\t"
2196                 " jb 2f                                         \n\t"
2197                 "cmpl 516(%%edx), %%ecx                         \n\t"
2198                 " jb 1f                                         \n\t"
2199
2200                 "leal (%%eax, %2, 2), %%edx                     \n\t" // 5*stride
2201                 "leal (%%edx, %2, 2), %%ecx                     \n\t" // 7*stride
2202                 "movq (%0), %%mm0                               \n\t" // L0
2203                 "movq (%0, %2), %%mm1                           \n\t" // L1
2204                 "movq (%0, %2, 2), %%mm2                        \n\t" // L2
2205                 "movq (%0, %%eax), %%mm3                        \n\t" // L3
2206                 "movq (%0, %2, 4), %%mm4                        \n\t" // L4
2207                 "movq (%0, %%edx), %%mm5                        \n\t" // L5
2208                 "movq (%0, %%eax, 2), %%mm6                     \n\t" // L6
2209                 "movq (%0, %%ecx), %%mm7                        \n\t" // L7
2210                 "movq %%mm0, (%1)                               \n\t" // L0
2211                 "movq %%mm1, (%1, %2)                           \n\t" // L1
2212                 "movq %%mm2, (%1, %2, 2)                        \n\t" // L2
2213                 "movq %%mm3, (%1, %%eax)                        \n\t" // L3
2214                 "movq %%mm4, (%1, %2, 4)                        \n\t" // L4
2215                 "movq %%mm5, (%1, %%edx)                        \n\t" // L5
2216                 "movq %%mm6, (%1, %%eax, 2)                     \n\t" // L6
2217                 "movq %%mm7, (%1, %%ecx)                        \n\t" // L7
2218                 "jmp 4f                                         \n\t"
2219
2220                 "1:                                             \n\t"
2221                 "leal (%%eax, %2, 2), %%edx                     \n\t" // 5*stride
2222                 "leal (%%edx, %2, 2), %%ecx                     \n\t" // 7*stride
2223                 "movq (%0), %%mm0                               \n\t" // L0
2224                 PAVGB((%1), %%mm0)                                    // L0
2225                 "movq (%0, %2), %%mm1                           \n\t" // L1
2226                 PAVGB((%1, %2), %%mm1)                                // L1
2227                 "movq (%0, %2, 2), %%mm2                        \n\t" // L2
2228                 PAVGB((%1, %2, 2), %%mm2)                             // L2
2229                 "movq (%0, %%eax), %%mm3                        \n\t" // L3
2230                 PAVGB((%1, %%eax), %%mm3)                             // L3
2231                 "movq (%0, %2, 4), %%mm4                        \n\t" // L4
2232                 PAVGB((%1, %2, 4), %%mm4)                             // L4
2233                 "movq (%0, %%edx), %%mm5                        \n\t" // L5
2234                 PAVGB((%1, %%edx), %%mm5)                             // L5
2235                 "movq (%0, %%eax, 2), %%mm6                     \n\t" // L6
2236                 PAVGB((%1, %%eax, 2), %%mm6)                          // L6
2237                 "movq (%0, %%ecx), %%mm7                        \n\t" // L7
2238                 PAVGB((%1, %%ecx), %%mm7)                             // L7
2239                 "movq %%mm0, (%1)                               \n\t" // R0
2240                 "movq %%mm1, (%1, %2)                           \n\t" // R1
2241                 "movq %%mm2, (%1, %2, 2)                        \n\t" // R2
2242                 "movq %%mm3, (%1, %%eax)                        \n\t" // R3
2243                 "movq %%mm4, (%1, %2, 4)                        \n\t" // R4
2244                 "movq %%mm5, (%1, %%edx)                        \n\t" // R5
2245                 "movq %%mm6, (%1, %%eax, 2)                     \n\t" // R6
2246                 "movq %%mm7, (%1, %%ecx)                        \n\t" // R7
2247                 "movq %%mm0, (%0)                               \n\t" // L0
2248                 "movq %%mm1, (%0, %2)                           \n\t" // L1
2249                 "movq %%mm2, (%0, %2, 2)                        \n\t" // L2
2250                 "movq %%mm3, (%0, %%eax)                        \n\t" // L3
2251                 "movq %%mm4, (%0, %2, 4)                        \n\t" // L4
2252                 "movq %%mm5, (%0, %%edx)                        \n\t" // L5
2253                 "movq %%mm6, (%0, %%eax, 2)                     \n\t" // L6
2254                 "movq %%mm7, (%0, %%ecx)                        \n\t" // L7
2255                 "jmp 4f                                         \n\t"
2256
2257                 "2:                                             \n\t"
2258                 "cmpl 508(%%edx), %%ecx                         \n\t"
2259                 " jb 3f                                         \n\t"
2260
2261                 "leal (%%eax, %2, 2), %%edx                     \n\t" // 5*stride
2262                 "leal (%%edx, %2, 2), %%ecx                     \n\t" // 7*stride
2263                 "movq (%0), %%mm0                               \n\t" // L0
2264                 "movq (%0, %2), %%mm1                           \n\t" // L1
2265                 "movq (%0, %2, 2), %%mm2                        \n\t" // L2
2266                 "movq (%0, %%eax), %%mm3                        \n\t" // L3
2267                 "movq (%1), %%mm4                               \n\t" // R0
2268                 "movq (%1, %2), %%mm5                           \n\t" // R1
2269                 "movq (%1, %2, 2), %%mm6                        \n\t" // R2
2270                 "movq (%1, %%eax), %%mm7                        \n\t" // R3
2271                 PAVGB(%%mm4, %%mm0)
2272                 PAVGB(%%mm5, %%mm1)
2273                 PAVGB(%%mm6, %%mm2)
2274                 PAVGB(%%mm7, %%mm3)
2275                 PAVGB(%%mm4, %%mm0)
2276                 PAVGB(%%mm5, %%mm1)
2277                 PAVGB(%%mm6, %%mm2)
2278                 PAVGB(%%mm7, %%mm3)
2279                 "movq %%mm0, (%1)                               \n\t" // R0
2280                 "movq %%mm1, (%1, %2)                           \n\t" // R1
2281                 "movq %%mm2, (%1, %2, 2)                        \n\t" // R2
2282                 "movq %%mm3, (%1, %%eax)                        \n\t" // R3
2283                 "movq %%mm0, (%0)                               \n\t" // L0
2284                 "movq %%mm1, (%0, %2)                           \n\t" // L1
2285                 "movq %%mm2, (%0, %2, 2)                        \n\t" // L2
2286                 "movq %%mm3, (%0, %%eax)                        \n\t" // L3
2287
2288                 "movq (%0, %2, 4), %%mm0                        \n\t" // L4
2289                 "movq (%0, %%edx), %%mm1                        \n\t" // L5
2290                 "movq (%0, %%eax, 2), %%mm2                     \n\t" // L6
2291                 "movq (%0, %%ecx), %%mm3                        \n\t" // L7
2292                 "movq (%1, %2, 4), %%mm4                        \n\t" // R4
2293                 "movq (%1, %%edx), %%mm5                        \n\t" // R5
2294                 "movq (%1, %%eax, 2), %%mm6                     \n\t" // R6
2295                 "movq (%1, %%ecx), %%mm7                        \n\t" // R7
2296                 PAVGB(%%mm4, %%mm0)
2297                 PAVGB(%%mm5, %%mm1)
2298                 PAVGB(%%mm6, %%mm2)
2299                 PAVGB(%%mm7, %%mm3)
2300                 PAVGB(%%mm4, %%mm0)
2301                 PAVGB(%%mm5, %%mm1)
2302                 PAVGB(%%mm6, %%mm2)
2303                 PAVGB(%%mm7, %%mm3)
2304                 "movq %%mm0, (%1, %2, 4)                        \n\t" // R4
2305                 "movq %%mm1, (%1, %%edx)                        \n\t" // R5
2306                 "movq %%mm2, (%1, %%eax, 2)                     \n\t" // R6
2307                 "movq %%mm3, (%1, %%ecx)                        \n\t" // R7
2308                 "movq %%mm0, (%0, %2, 4)                        \n\t" // L4
2309                 "movq %%mm1, (%0, %%edx)                        \n\t" // L5
2310                 "movq %%mm2, (%0, %%eax, 2)                     \n\t" // L6
2311                 "movq %%mm3, (%0, %%ecx)                        \n\t" // L7
2312                 "jmp 4f                                         \n\t"
2313
2314                 "3:                                             \n\t"
2315                 "leal (%%eax, %2, 2), %%edx                     \n\t" // 5*stride
2316                 "leal (%%edx, %2, 2), %%ecx                     \n\t" // 7*stride
2317                 "movq (%0), %%mm0                               \n\t" // L0
2318                 "movq (%0, %2), %%mm1                           \n\t" // L1
2319                 "movq (%0, %2, 2), %%mm2                        \n\t" // L2
2320                 "movq (%0, %%eax), %%mm3                        \n\t" // L3
2321                 "movq (%1), %%mm4                               \n\t" // R0
2322                 "movq (%1, %2), %%mm5                           \n\t" // R1
2323                 "movq (%1, %2, 2), %%mm6                        \n\t" // R2
2324                 "movq (%1, %%eax), %%mm7                        \n\t" // R3
2325                 PAVGB(%%mm4, %%mm0)
2326                 PAVGB(%%mm5, %%mm1)
2327                 PAVGB(%%mm6, %%mm2)
2328                 PAVGB(%%mm7, %%mm3)
2329                 PAVGB(%%mm4, %%mm0)
2330                 PAVGB(%%mm5, %%mm1)
2331                 PAVGB(%%mm6, %%mm2)
2332                 PAVGB(%%mm7, %%mm3)
2333                 PAVGB(%%mm4, %%mm0)
2334                 PAVGB(%%mm5, %%mm1)
2335                 PAVGB(%%mm6, %%mm2)
2336                 PAVGB(%%mm7, %%mm3)
2337                 "movq %%mm0, (%1)                               \n\t" // R0
2338                 "movq %%mm1, (%1, %2)                           \n\t" // R1
2339                 "movq %%mm2, (%1, %2, 2)                        \n\t" // R2
2340                 "movq %%mm3, (%1, %%eax)                        \n\t" // R3
2341                 "movq %%mm0, (%0)                               \n\t" // L0
2342                 "movq %%mm1, (%0, %2)                           \n\t" // L1
2343                 "movq %%mm2, (%0, %2, 2)                        \n\t" // L2
2344                 "movq %%mm3, (%0, %%eax)                        \n\t" // L3
2345
2346                 "movq (%0, %2, 4), %%mm0                        \n\t" // L4
2347                 "movq (%0, %%edx), %%mm1                        \n\t" // L5
2348                 "movq (%0, %%eax, 2), %%mm2                     \n\t" // L6
2349                 "movq (%0, %%ecx), %%mm3                        \n\t" // L7
2350                 "movq (%1, %2, 4), %%mm4                        \n\t" // R4
2351                 "movq (%1, %%edx), %%mm5                        \n\t" // R5
2352                 "movq (%1, %%eax, 2), %%mm6                     \n\t" // R6
2353                 "movq (%1, %%ecx), %%mm7                        \n\t" // R7
2354                 PAVGB(%%mm4, %%mm0)
2355                 PAVGB(%%mm5, %%mm1)
2356                 PAVGB(%%mm6, %%mm2)
2357                 PAVGB(%%mm7, %%mm3)
2358                 PAVGB(%%mm4, %%mm0)
2359                 PAVGB(%%mm5, %%mm1)
2360                 PAVGB(%%mm6, %%mm2)
2361                 PAVGB(%%mm7, %%mm3)
2362                 PAVGB(%%mm4, %%mm0)
2363                 PAVGB(%%mm5, %%mm1)
2364                 PAVGB(%%mm6, %%mm2)
2365                 PAVGB(%%mm7, %%mm3)
2366                 "movq %%mm0, (%1, %2, 4)                        \n\t" // R4
2367                 "movq %%mm1, (%1, %%edx)                        \n\t" // R5
2368                 "movq %%mm2, (%1, %%eax, 2)                     \n\t" // R6
2369                 "movq %%mm3, (%1, %%ecx)                        \n\t" // R7
2370                 "movq %%mm0, (%0, %2, 4)                        \n\t" // L4
2371                 "movq %%mm1, (%0, %%edx)                        \n\t" // L5
2372                 "movq %%mm2, (%0, %%eax, 2)                     \n\t" // L6
2373                 "movq %%mm3, (%0, %%ecx)                        \n\t" // L7
2374
2375                 "4:                                             \n\t"
2376
2377                 :: "r" (src), "r" (tempBlured), "r"(stride), "m" (tempBluredPast)
2378                 : "%eax", "%edx", "%ecx", "memory"
2379                 );
2380 //printf("%d\n", test);
2381 #else
2382 {
2383         int y;
2384         int d=0;
2385         int sysd=0;
2386         int i;
2387
2388         for(y=0; y<8; y++)
2389         {
2390                 int x;
2391                 for(x=0; x<8; x++)
2392                 {
2393                         int ref= tempBlured[ x + y*stride ];
2394                         int cur= src[ x + y*stride ];
2395                         int d1=ref - cur;
2396 //                      if(x==0 || x==7) d1+= d1>>1;
2397 //                      if(y==0 || y==7) d1+= d1>>1;
2398 //                      d+= ABS(d1);
2399                         d+= d1*d1;
2400                         sysd+= d1;
2401                 }
2402         }
2403         i=d;
2404         d=      (
2405                 4*d
2406                 +(*(tempBluredPast-256))
2407                 +(*(tempBluredPast-1))+ (*(tempBluredPast+1))
2408                 +(*(tempBluredPast+256))
2409                 +4)>>3;
2410         *tempBluredPast=i;
2411 //      ((*tempBluredPast)*3 + d + 2)>>2;
2412
2413 //printf("%d %d %d\n", maxNoise[0], maxNoise[1], maxNoise[2]);
2414 /*
2415 Switch between
2416  1  0  0  0  0  0  0  (0)
2417 64 32 16  8  4  2  1  (1)
2418 64 48 36 27 20 15 11 (33) (approx)
2419 64 56 49 43 37 33 29 (200) (approx)
2420 */
2421         if(d > maxNoise[1])
2422         {
2423                 if(d < maxNoise[2])
2424                 {
2425                         for(y=0; y<8; y++)
2426                         {
2427                                 int x;
2428                                 for(x=0; x<8; x++)
2429                                 {
2430                                         int ref= tempBlured[ x + y*stride ];
2431                                         int cur= src[ x + y*stride ];
2432                                         tempBlured[ x + y*stride ]=
2433                                         src[ x + y*stride ]=
2434                                                 (ref + cur + 1)>>1;
2435                                 }
2436                         }
2437                 }
2438                 else
2439                 {
2440                         for(y=0; y<8; y++)
2441                         {
2442                                 int x;
2443                                 for(x=0; x<8; x++)
2444                                 {
2445                                         tempBlured[ x + y*stride ]= src[ x + y*stride ];
2446                                 }
2447                         }
2448                 }
2449         }
2450         else
2451         {
2452                 if(d < maxNoise[0])
2453                 {
2454                         for(y=0; y<8; y++)
2455                         {
2456                                 int x;
2457                                 for(x=0; x<8; x++)
2458                                 {
2459                                         int ref= tempBlured[ x + y*stride ];
2460                                         int cur= src[ x + y*stride ];
2461                                         tempBlured[ x + y*stride ]=
2462                                         src[ x + y*stride ]=