Fix SPLATB_REG mess. Used to be a if/elseif/elseif/elseif spaghetti, so this
[ffmpeg.git] / libavcodec / x86 / vp8dsp.asm
1 ;******************************************************************************
2 ;* VP8 MMXEXT optimizations
3 ;* Copyright (c) 2010 Ronald S. Bultje <rsbultje@gmail.com>
4 ;* Copyright (c) 2010 Jason Garrett-Glaser <darkshikari@gmail.com>
5 ;*
6 ;* This file is part of FFmpeg.
7 ;*
8 ;* FFmpeg is free software; you can redistribute it and/or
9 ;* modify it under the terms of the GNU Lesser General Public
10 ;* License as published by the Free Software Foundation; either
11 ;* version 2.1 of the License, or (at your option) any later version.
12 ;*
13 ;* FFmpeg is distributed in the hope that it will be useful,
14 ;* but WITHOUT ANY WARRANTY; without even the implied warranty of
15 ;* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16 ;* Lesser General Public License for more details.
17 ;*
18 ;* You should have received a copy of the GNU Lesser General Public
19 ;* License along with FFmpeg; if not, write to the Free Software
20 ;* 51, Inc., Foundation Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
21 ;******************************************************************************
22
23 %include "x86inc.asm"
24 %include "x86util.asm"
25
26 SECTION_RODATA
27
28 fourtap_filter_hw_m: times 4 dw  -6, 123
29                      times 4 dw  12,  -1
30                      times 4 dw  -9,  93
31                      times 4 dw  50,  -6
32                      times 4 dw  -6,  50
33                      times 4 dw  93,  -9
34                      times 4 dw  -1,  12
35                      times 4 dw 123,  -6
36
37 sixtap_filter_hw_m:  times 4 dw   2, -11
38                      times 4 dw 108,  36
39                      times 4 dw  -8,   1
40                      times 4 dw   3, -16
41                      times 4 dw  77,  77
42                      times 4 dw -16,   3
43                      times 4 dw   1,  -8
44                      times 4 dw  36, 108
45                      times 4 dw -11,   2
46
47 fourtap_filter_hb_m: times 8 db  -6, 123
48                      times 8 db  12,  -1
49                      times 8 db  -9,  93
50                      times 8 db  50,  -6
51                      times 8 db  -6,  50
52                      times 8 db  93,  -9
53                      times 8 db  -1,  12
54                      times 8 db 123,  -6
55
56 sixtap_filter_hb_m:  times 8 db   2,   1
57                      times 8 db -11, 108
58                      times 8 db  36,  -8
59                      times 8 db   3,   3
60                      times 8 db -16,  77
61                      times 8 db  77, -16
62                      times 8 db   1,   2
63                      times 8 db  -8,  36
64                      times 8 db 108, -11
65
66 fourtap_filter_v_m:  times 8 dw  -6
67                      times 8 dw 123
68                      times 8 dw  12
69                      times 8 dw  -1
70                      times 8 dw  -9
71                      times 8 dw  93
72                      times 8 dw  50
73                      times 8 dw  -6
74                      times 8 dw  -6
75                      times 8 dw  50
76                      times 8 dw  93
77                      times 8 dw  -9
78                      times 8 dw  -1
79                      times 8 dw  12
80                      times 8 dw 123
81                      times 8 dw  -6
82
83 sixtap_filter_v_m:   times 8 dw   2
84                      times 8 dw -11
85                      times 8 dw 108
86                      times 8 dw  36
87                      times 8 dw  -8
88                      times 8 dw   1
89                      times 8 dw   3
90                      times 8 dw -16
91                      times 8 dw  77
92                      times 8 dw  77
93                      times 8 dw -16
94                      times 8 dw   3
95                      times 8 dw   1
96                      times 8 dw  -8
97                      times 8 dw  36
98                      times 8 dw 108
99                      times 8 dw -11
100                      times 8 dw   2
101
102 bilinear_filter_vw_m: times 8 dw 1
103                       times 8 dw 2
104                       times 8 dw 3
105                       times 8 dw 4
106                       times 8 dw 5
107                       times 8 dw 6
108                       times 8 dw 7
109
110 bilinear_filter_vb_m: times 8 db 7, 1
111                       times 8 db 6, 2
112                       times 8 db 5, 3
113                       times 8 db 4, 4
114                       times 8 db 3, 5
115                       times 8 db 2, 6
116                       times 8 db 1, 7
117
118 %ifdef PIC
119 %define fourtap_filter_hw    r11
120 %define sixtap_filter_hw     r11
121 %define fourtap_filter_hb    r11
122 %define sixtap_filter_hb     r11
123 %define fourtap_filter_v     r11
124 %define sixtap_filter_v      r11
125 %define bilinear_filter_vw   r11
126 %define bilinear_filter_vb   r11
127 %else
128 %define fourtap_filter_hw fourtap_filter_hw_m
129 %define sixtap_filter_hw  sixtap_filter_hw_m
130 %define fourtap_filter_hb fourtap_filter_hb_m
131 %define sixtap_filter_hb  sixtap_filter_hb_m
132 %define fourtap_filter_v  fourtap_filter_v_m
133 %define sixtap_filter_v   sixtap_filter_v_m
134 %define bilinear_filter_vw bilinear_filter_vw_m
135 %define bilinear_filter_vb bilinear_filter_vb_m
136 %endif
137
138 filter_h2_shuf:  db 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5,  6, 6,  7,  7,  8
139 filter_h4_shuf:  db 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7,  8, 8,  9,  9, 10
140
141 filter_h6_shuf1: db 0, 5, 1, 6, 2, 7, 3, 8, 4, 9, 5, 10, 6, 11,  7, 12
142 filter_h6_shuf2: db 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6,  7, 7,  8,  8,  9
143 filter_h6_shuf3: db 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 8,  9, 9, 10, 10, 11
144
145 pw_20091: times 4 dw 20091
146 pw_17734: times 4 dw 17734
147
148 cextern pb_1
149 cextern pw_3
150 cextern pb_3
151 cextern pw_4
152 cextern pb_4
153 cextern pw_9
154 cextern pw_18
155 cextern pw_27
156 cextern pw_63
157 cextern pw_64
158 cextern pb_80
159 cextern pb_F8
160 cextern pb_FE
161
162 SECTION .text
163
164 ;-----------------------------------------------------------------------------
165 ; subpel MC functions:
166 ;
167 ; void put_vp8_epel<size>_h<htap>v<vtap>_<opt>(uint8_t *dst, int deststride,
168 ;                                              uint8_t *src, int srcstride,
169 ;                                              int height,   int mx, int my);
170 ;-----------------------------------------------------------------------------
171
172 %macro FILTER_SSSE3 3
173 cglobal put_vp8_epel%1_h6_ssse3, 6, 6, %2
174     lea      r5d, [r5*3]
175     mova      m3, [filter_h6_shuf2]
176     mova      m4, [filter_h6_shuf3]
177 %ifdef PIC
178     lea      r11, [sixtap_filter_hb_m]
179 %endif
180     mova      m5, [sixtap_filter_hb+r5*8-48] ; set up 6tap filter in bytes
181     mova      m6, [sixtap_filter_hb+r5*8-32]
182     mova      m7, [sixtap_filter_hb+r5*8-16]
183
184 .nextrow
185     movu      m0, [r2-2]
186     mova      m1, m0
187     mova      m2, m0
188 %ifidn %1, 4
189 ; For epel4, we need 9 bytes, but only 8 get loaded; to compensate, do the
190 ; shuffle with a memory operand
191     punpcklbw m0, [r2+3]
192 %else
193     pshufb    m0, [filter_h6_shuf1]
194 %endif
195     pshufb    m1, m3
196     pshufb    m2, m4
197     pmaddubsw m0, m5
198     pmaddubsw m1, m6
199     pmaddubsw m2, m7
200     paddsw    m0, m1
201     paddsw    m0, m2
202     paddsw    m0, [pw_64]
203     psraw     m0, 7
204     packuswb  m0, m0
205     movh    [r0], m0        ; store
206
207     ; go to next line
208     add       r0, r1
209     add       r2, r3
210     dec       r4            ; next row
211     jg .nextrow
212     REP_RET
213
214 cglobal put_vp8_epel%1_h4_ssse3, 6, 6, %3
215     shl      r5d, 4
216     mova      m2, [pw_64]
217     mova      m3, [filter_h2_shuf]
218     mova      m4, [filter_h4_shuf]
219 %ifdef PIC
220     lea      r11, [fourtap_filter_hb_m]
221 %endif
222     mova      m5, [fourtap_filter_hb+r5-16] ; set up 4tap filter in bytes
223     mova      m6, [fourtap_filter_hb+r5]
224
225 .nextrow
226     movu      m0, [r2-1]
227     mova      m1, m0
228     pshufb    m0, m3
229     pshufb    m1, m4
230     pmaddubsw m0, m5
231     pmaddubsw m1, m6
232     paddsw    m0, m2
233     paddsw    m0, m1
234     psraw     m0, 7
235     packuswb  m0, m0
236     movh    [r0], m0        ; store
237
238     ; go to next line
239     add       r0, r1
240     add       r2, r3
241     dec       r4            ; next row
242     jg .nextrow
243     REP_RET
244
245 cglobal put_vp8_epel%1_v4_ssse3, 7, 7, %2
246     shl      r6d, 4
247 %ifdef PIC
248     lea      r11, [fourtap_filter_hb_m]
249 %endif
250     mova      m5, [fourtap_filter_hb+r6-16]
251     mova      m6, [fourtap_filter_hb+r6]
252     mova      m7, [pw_64]
253
254     ; read 3 lines
255     sub       r2, r3
256     movh      m0, [r2]
257     movh      m1, [r2+  r3]
258     movh      m2, [r2+2*r3]
259     add       r2, r3
260
261 .nextrow
262     movh      m3, [r2+2*r3]                ; read new row
263     mova      m4, m0
264     mova      m0, m1
265     punpcklbw m4, m1
266     mova      m1, m2
267     punpcklbw m2, m3
268     pmaddubsw m4, m5
269     pmaddubsw m2, m6
270     paddsw    m4, m2
271     mova      m2, m3
272     paddsw    m4, m7
273     psraw     m4, 7
274     packuswb  m4, m4
275     movh    [r0], m4
276
277     ; go to next line
278     add        r0, r1
279     add        r2, r3
280     dec        r4                          ; next row
281     jg .nextrow
282     REP_RET
283
284 cglobal put_vp8_epel%1_v6_ssse3, 7, 7, %2
285     lea      r6d, [r6*3]
286 %ifdef PIC
287     lea      r11, [sixtap_filter_hb_m]
288 %endif
289     lea       r6, [sixtap_filter_hb+r6*8]
290
291     ; read 5 lines
292     sub       r2, r3
293     sub       r2, r3
294     movh      m0, [r2]
295     movh      m1, [r2+r3]
296     movh      m2, [r2+r3*2]
297     lea       r2, [r2+r3*2]
298     add       r2, r3
299     movh      m3, [r2]
300     movh      m4, [r2+r3]
301
302 .nextrow
303     movh      m5, [r2+2*r3]                ; read new row
304     mova      m6, m0
305     punpcklbw m6, m5
306     mova      m0, m1
307     punpcklbw m1, m2
308     mova      m7, m3
309     punpcklbw m7, m4
310     pmaddubsw m6, [r6-48]
311     pmaddubsw m1, [r6-32]
312     pmaddubsw m7, [r6-16]
313     paddsw    m6, m1
314     paddsw    m6, m7
315     mova      m1, m2
316     paddsw    m6, [pw_64]
317     mova      m2, m3
318     psraw     m6, 7
319     mova      m3, m4
320     packuswb  m6, m6
321     mova      m4, m5
322     movh    [r0], m6
323
324     ; go to next line
325     add        r0, r1
326     add        r2, r3
327     dec        r4                          ; next row
328     jg .nextrow
329     REP_RET
330 %endmacro
331
332 INIT_MMX
333 FILTER_SSSE3 4, 0, 0
334 INIT_XMM
335 FILTER_SSSE3 8, 8, 7
336
337 ; 4x4 block, H-only 4-tap filter
338 cglobal put_vp8_epel4_h4_mmxext, 6, 6
339     shl       r5d, 4
340 %ifdef PIC
341     lea       r11, [fourtap_filter_hw_m]
342 %endif
343     movq      mm4, [fourtap_filter_hw+r5-16] ; set up 4tap filter in words
344     movq      mm5, [fourtap_filter_hw+r5]
345     movq      mm7, [pw_64]
346     pxor      mm6, mm6
347
348 .nextrow
349     movq      mm1, [r2-1]                  ; (ABCDEFGH) load 8 horizontal pixels
350
351     ; first set of 2 pixels
352     movq      mm2, mm1                     ; byte ABCD..
353     punpcklbw mm1, mm6                     ; byte->word ABCD
354     pshufw    mm0, mm2, 9                  ; byte CDEF..
355     punpcklbw mm0, mm6                     ; byte->word CDEF
356     pshufw    mm3, mm1, 0x94               ; word ABBC
357     pshufw    mm1, mm0, 0x94               ; word CDDE
358     pmaddwd   mm3, mm4                     ; multiply 2px with F0/F1
359     movq      mm0, mm1                     ; backup for second set of pixels
360     pmaddwd   mm1, mm5                     ; multiply 2px with F2/F3
361     paddd     mm3, mm1                     ; finish 1st 2px
362
363     ; second set of 2 pixels, use backup of above
364     punpckhbw mm2, mm6                     ; byte->word EFGH
365     pmaddwd   mm0, mm4                     ; multiply backed up 2px with F0/F1
366     pshufw    mm1, mm2, 0x94               ; word EFFG
367     pmaddwd   mm1, mm5                     ; multiply 2px with F2/F3
368     paddd     mm0, mm1                     ; finish 2nd 2px
369
370     ; merge two sets of 2 pixels into one set of 4, round/clip/store
371     packssdw  mm3, mm0                     ; merge dword->word (4px)
372     paddsw    mm3, mm7                     ; rounding
373     psraw     mm3, 7
374     packuswb  mm3, mm6                     ; clip and word->bytes
375     movd     [r0], mm3                     ; store
376
377     ; go to next line
378     add        r0, r1
379     add        r2, r3
380     dec        r4                          ; next row
381     jg .nextrow
382     REP_RET
383
384 ; 4x4 block, H-only 6-tap filter
385 cglobal put_vp8_epel4_h6_mmxext, 6, 6
386     lea       r5d, [r5*3]
387 %ifdef PIC
388     lea       r11, [sixtap_filter_hw_m]
389 %endif
390     movq      mm4, [sixtap_filter_hw+r5*8-48] ; set up 4tap filter in words
391     movq      mm5, [sixtap_filter_hw+r5*8-32]
392     movq      mm6, [sixtap_filter_hw+r5*8-16]
393     movq      mm7, [pw_64]
394     pxor      mm3, mm3
395
396 .nextrow
397     movq      mm1, [r2-2]                  ; (ABCDEFGH) load 8 horizontal pixels
398
399     ; first set of 2 pixels
400     movq      mm2, mm1                     ; byte ABCD..
401     punpcklbw mm1, mm3                     ; byte->word ABCD
402     pshufw    mm0, mm2, 0x9                ; byte CDEF..
403     punpckhbw mm2, mm3                     ; byte->word EFGH
404     punpcklbw mm0, mm3                     ; byte->word CDEF
405     pshufw    mm1, mm1, 0x94               ; word ABBC
406     pshufw    mm2, mm2, 0x94               ; word EFFG
407     pmaddwd   mm1, mm4                     ; multiply 2px with F0/F1
408     pshufw    mm3, mm0, 0x94               ; word CDDE
409     movq      mm0, mm3                     ; backup for second set of pixels
410     pmaddwd   mm3, mm5                     ; multiply 2px with F2/F3
411     paddd     mm1, mm3                     ; add to 1st 2px cache
412     movq      mm3, mm2                     ; backup for second set of pixels
413     pmaddwd   mm2, mm6                     ; multiply 2px with F4/F5
414     paddd     mm1, mm2                     ; finish 1st 2px
415
416     ; second set of 2 pixels, use backup of above
417     movd      mm2, [r2+3]                  ; byte FGHI (prevent overreads)
418     pmaddwd   mm0, mm4                     ; multiply 1st backed up 2px with F0/F1
419     pmaddwd   mm3, mm5                     ; multiply 2nd backed up 2px with F2/F3
420     paddd     mm0, mm3                     ; add to 2nd 2px cache
421     pxor      mm3, mm3
422     punpcklbw mm2, mm3                     ; byte->word FGHI
423     pshufw    mm2, mm2, 0xE9               ; word GHHI
424     pmaddwd   mm2, mm6                     ; multiply 2px with F4/F5
425     paddd     mm0, mm2                     ; finish 2nd 2px
426
427     ; merge two sets of 2 pixels into one set of 4, round/clip/store
428     packssdw  mm1, mm0                     ; merge dword->word (4px)
429     paddsw    mm1, mm7                     ; rounding
430     psraw     mm1, 7
431     packuswb  mm1, mm3                     ; clip and word->bytes
432     movd     [r0], mm1                     ; store
433
434     ; go to next line
435     add        r0, r1
436     add        r2, r3
437     dec        r4                          ; next row
438     jg .nextrow
439     REP_RET
440
441 ; 4x4 block, H-only 4-tap filter
442 INIT_XMM
443 cglobal put_vp8_epel8_h4_sse2, 6, 6, 8
444     shl      r5d, 4
445 %ifdef PIC
446     lea      r11, [fourtap_filter_hw_m]
447 %endif
448     mova      m5, [fourtap_filter_hw+r5-16] ; set up 4tap filter in words
449     mova      m6, [fourtap_filter_hw+r5]
450     pxor      m7, m7
451
452 .nextrow
453     movh      m0, [r2-1]
454     punpcklbw m0, m7        ; ABCDEFGH
455     mova      m1, m0
456     mova      m2, m0
457     mova      m3, m0
458     psrldq    m1, 2         ; BCDEFGH
459     psrldq    m2, 4         ; CDEFGH
460     psrldq    m3, 6         ; DEFGH
461     punpcklwd m0, m1        ; ABBCCDDE
462     punpcklwd m2, m3        ; CDDEEFFG
463     pmaddwd   m0, m5
464     pmaddwd   m2, m6
465     paddd     m0, m2
466
467     movh      m1, [r2+3]
468     punpcklbw m1, m7        ; ABCDEFGH
469     mova      m2, m1
470     mova      m3, m1
471     mova      m4, m1
472     psrldq    m2, 2         ; BCDEFGH
473     psrldq    m3, 4         ; CDEFGH
474     psrldq    m4, 6         ; DEFGH
475     punpcklwd m1, m2        ; ABBCCDDE
476     punpcklwd m3, m4        ; CDDEEFFG
477     pmaddwd   m1, m5
478     pmaddwd   m3, m6
479     paddd     m1, m3
480
481     packssdw  m0, m1
482     paddsw    m0, [pw_64]
483     psraw     m0, 7
484     packuswb  m0, m7
485     movh    [r0], m0        ; store
486
487     ; go to next line
488     add       r0, r1
489     add       r2, r3
490     dec       r4            ; next row
491     jg .nextrow
492     REP_RET
493
494 cglobal put_vp8_epel8_h6_sse2, 6, 6, 8
495     lea      r5d, [r5*3]
496 %ifdef PIC
497     lea      r11, [sixtap_filter_hw_m]
498 %endif
499     lea       r5, [sixtap_filter_hw+r5*8]
500     pxor      m7, m7
501
502 .nextrow
503     movu      m0, [r2-2]
504     mova      m6, m0
505     mova      m4, m0
506     punpcklbw m0, m7        ; ABCDEFGHI
507     mova      m1, m0
508     mova      m2, m0
509     mova      m3, m0
510     psrldq    m1, 2         ; BCDEFGH
511     psrldq    m2, 4         ; CDEFGH
512     psrldq    m3, 6         ; DEFGH
513     psrldq    m4, 4
514     punpcklbw m4, m7        ; EFGH
515     mova      m5, m4
516     psrldq    m5, 2         ; FGH
517     punpcklwd m0, m1        ; ABBCCDDE
518     punpcklwd m2, m3        ; CDDEEFFG
519     punpcklwd m4, m5        ; EFFGGHHI
520     pmaddwd   m0, [r5-48]
521     pmaddwd   m2, [r5-32]
522     pmaddwd   m4, [r5-16]
523     paddd     m0, m2
524     paddd     m0, m4
525
526     psrldq    m6, 4
527     mova      m4, m6
528     punpcklbw m6, m7        ; ABCDEFGHI
529     mova      m1, m6
530     mova      m2, m6
531     mova      m3, m6
532     psrldq    m1, 2         ; BCDEFGH
533     psrldq    m2, 4         ; CDEFGH
534     psrldq    m3, 6         ; DEFGH
535     psrldq    m4, 4
536     punpcklbw m4, m7        ; EFGH
537     mova      m5, m4
538     psrldq    m5, 2         ; FGH
539     punpcklwd m6, m1        ; ABBCCDDE
540     punpcklwd m2, m3        ; CDDEEFFG
541     punpcklwd m4, m5        ; EFFGGHHI
542     pmaddwd   m6, [r5-48]
543     pmaddwd   m2, [r5-32]
544     pmaddwd   m4, [r5-16]
545     paddd     m6, m2
546     paddd     m6, m4
547
548     packssdw  m0, m6
549     paddsw    m0, [pw_64]
550     psraw     m0, 7
551     packuswb  m0, m7
552     movh    [r0], m0        ; store
553
554     ; go to next line
555     add       r0, r1
556     add       r2, r3
557     dec       r4            ; next row
558     jg .nextrow
559     REP_RET
560
561 %macro FILTER_V 3
562 ; 4x4 block, V-only 4-tap filter
563 cglobal put_vp8_epel%2_v4_%1, 7, 7, %3
564     shl      r6d, 5
565 %ifdef PIC
566     lea      r11, [fourtap_filter_v_m]
567 %endif
568     lea       r6, [fourtap_filter_v+r6-32]
569     mova      m6, [pw_64]
570     pxor      m7, m7
571     mova      m5, [r6+48]
572
573     ; read 3 lines
574     sub       r2, r3
575     movh      m0, [r2]
576     movh      m1, [r2+  r3]
577     movh      m2, [r2+2*r3]
578     add       r2, r3
579     punpcklbw m0, m7
580     punpcklbw m1, m7
581     punpcklbw m2, m7
582
583 .nextrow
584     ; first calculate negative taps (to prevent losing positive overflows)
585     movh      m4, [r2+2*r3]                ; read new row
586     punpcklbw m4, m7
587     mova      m3, m4
588     pmullw    m0, [r6+0]
589     pmullw    m4, m5
590     paddsw    m4, m0
591
592     ; then calculate positive taps
593     mova      m0, m1
594     pmullw    m1, [r6+16]
595     paddsw    m4, m1
596     mova      m1, m2
597     pmullw    m2, [r6+32]
598     paddsw    m4, m2
599     mova      m2, m3
600
601     ; round/clip/store
602     paddsw    m4, m6
603     psraw     m4, 7
604     packuswb  m4, m7
605     movh    [r0], m4
606
607     ; go to next line
608     add       r0, r1
609     add       r2, r3
610     dec       r4                           ; next row
611     jg .nextrow
612     REP_RET
613
614
615 ; 4x4 block, V-only 6-tap filter
616 cglobal put_vp8_epel%2_v6_%1, 7, 7, %3
617     shl      r6d, 4
618     lea       r6, [r6*3]
619 %ifdef PIC
620     lea      r11, [sixtap_filter_v_m]
621 %endif
622     lea       r6, [sixtap_filter_v+r6-96]
623     pxor      m7, m7
624
625     ; read 5 lines
626     sub       r2, r3
627     sub       r2, r3
628     movh      m0, [r2]
629     movh      m1, [r2+r3]
630     movh      m2, [r2+r3*2]
631     lea       r2, [r2+r3*2]
632     add       r2, r3
633     movh      m3, [r2]
634     movh      m4, [r2+r3]
635     punpcklbw m0, m7
636     punpcklbw m1, m7
637     punpcklbw m2, m7
638     punpcklbw m3, m7
639     punpcklbw m4, m7
640
641 .nextrow
642     ; first calculate negative taps (to prevent losing positive overflows)
643     mova      m5, m1
644     pmullw    m5, [r6+16]
645     mova      m6, m4
646     pmullw    m6, [r6+64]
647     paddsw    m6, m5
648
649     ; then calculate positive taps
650     movh      m5, [r2+2*r3]                ; read new row
651     punpcklbw m5, m7
652     pmullw    m0, [r6+0]
653     paddsw    m6, m0
654     mova      m0, m1
655     mova      m1, m2
656     pmullw    m2, [r6+32]
657     paddsw    m6, m2
658     mova      m2, m3
659     pmullw    m3, [r6+48]
660     paddsw    m6, m3
661     mova      m3, m4
662     mova      m4, m5
663     pmullw    m5, [r6+80]
664     paddsw    m6, m5
665
666     ; round/clip/store
667     paddsw    m6, [pw_64]
668     psraw     m6, 7
669     packuswb  m6, m7
670     movh    [r0], m6
671
672     ; go to next line
673     add       r0, r1
674     add       r2, r3
675     dec       r4                           ; next row
676     jg .nextrow
677     REP_RET
678 %endmacro
679
680 INIT_MMX
681 FILTER_V mmxext, 4, 0
682 INIT_XMM
683 FILTER_V sse2,   8, 8
684
685 %macro FILTER_BILINEAR 3
686 cglobal put_vp8_bilinear%2_v_%1, 7,7,%3
687     mov      r5d, 8*16
688     shl      r6d, 4
689     sub      r5d, r6d
690 %ifdef PIC
691     lea      r11, [bilinear_filter_vw_m]
692 %endif
693     pxor      m6, m6
694     mova      m4, [bilinear_filter_vw+r5-16]
695     mova      m5, [bilinear_filter_vw+r6-16]
696 .nextrow
697     movh      m0, [r2+r3*0]
698     movh      m1, [r2+r3*1]
699     movh      m3, [r2+r3*2]
700     punpcklbw m0, m6
701     punpcklbw m1, m6
702     punpcklbw m3, m6
703     mova      m2, m1
704     pmullw    m0, m4
705     pmullw    m1, m5
706     pmullw    m2, m4
707     pmullw    m3, m5
708     paddsw    m0, m1
709     paddsw    m2, m3
710     psraw     m0, 2
711     psraw     m2, 2
712     pavgw     m0, m6
713     pavgw     m2, m6
714 %ifidn %1, mmxext
715     packuswb  m0, m0
716     packuswb  m2, m2
717     movh [r0+r1*0], m0
718     movh [r0+r1*1], m2
719 %else
720     packuswb  m0, m2
721     movh   [r0+r1*0], m0
722     movhps [r0+r1*1], m0
723 %endif
724
725     lea       r0, [r0+r1*2]
726     lea       r2, [r2+r3*2]
727     sub       r4, 2
728     jg .nextrow
729     REP_RET
730
731 cglobal put_vp8_bilinear%2_h_%1, 7,7,%3
732     mov      r6d, 8*16
733     shl      r5d, 4
734     sub      r6d, r5d
735 %ifdef PIC
736     lea      r11, [bilinear_filter_vw_m]
737 %endif
738     pxor      m6, m6
739     mova      m4, [bilinear_filter_vw+r6-16]
740     mova      m5, [bilinear_filter_vw+r5-16]
741 .nextrow
742     movh      m0, [r2+r3*0+0]
743     movh      m1, [r2+r3*0+1]
744     movh      m2, [r2+r3*1+0]
745     movh      m3, [r2+r3*1+1]
746     punpcklbw m0, m6
747     punpcklbw m1, m6
748     punpcklbw m2, m6
749     punpcklbw m3, m6
750     pmullw    m0, m4
751     pmullw    m1, m5
752     pmullw    m2, m4
753     pmullw    m3, m5
754     paddsw    m0, m1
755     paddsw    m2, m3
756     psraw     m0, 2
757     psraw     m2, 2
758     pavgw     m0, m6
759     pavgw     m2, m6
760 %ifidn %1, mmxext
761     packuswb  m0, m0
762     packuswb  m2, m2
763     movh [r0+r1*0], m0
764     movh [r0+r1*1], m2
765 %else
766     packuswb  m0, m2
767     movh   [r0+r1*0], m0
768     movhps [r0+r1*1], m0
769 %endif
770
771     lea       r0, [r0+r1*2]
772     lea       r2, [r2+r3*2]
773     sub       r4, 2
774     jg .nextrow
775     REP_RET
776 %endmacro
777
778 INIT_MMX
779 FILTER_BILINEAR mmxext, 4, 0
780 INIT_XMM
781 FILTER_BILINEAR   sse2, 8, 7
782
783 %macro FILTER_BILINEAR_SSSE3 1
784 cglobal put_vp8_bilinear%1_v_ssse3, 7,7
785     shl      r6d, 4
786 %ifdef PIC
787     lea      r11, [bilinear_filter_vb_m]
788 %endif
789     pxor      m4, m4
790     mova      m3, [bilinear_filter_vb+r6-16]
791 .nextrow
792     movh      m0, [r2+r3*0]
793     movh      m1, [r2+r3*1]
794     movh      m2, [r2+r3*2]
795     punpcklbw m0, m1
796     punpcklbw m1, m2
797     pmaddubsw m0, m3
798     pmaddubsw m1, m3
799     psraw     m0, 2
800     psraw     m1, 2
801     pavgw     m0, m4
802     pavgw     m1, m4
803 %if mmsize==8
804     packuswb  m0, m0
805     packuswb  m1, m1
806     movh [r0+r1*0], m0
807     movh [r0+r1*1], m1
808 %else
809     packuswb  m0, m1
810     movh   [r0+r1*0], m0
811     movhps [r0+r1*1], m0
812 %endif
813
814     lea       r0, [r0+r1*2]
815     lea       r2, [r2+r3*2]
816     sub       r4, 2
817     jg .nextrow
818     REP_RET
819
820 cglobal put_vp8_bilinear%1_h_ssse3, 7,7
821     shl      r5d, 4
822 %ifdef PIC
823     lea      r11, [bilinear_filter_vb_m]
824 %endif
825     pxor      m4, m4
826     mova      m2, [filter_h2_shuf]
827     mova      m3, [bilinear_filter_vb+r5-16]
828 .nextrow
829     movu      m0, [r2+r3*0]
830     movu      m1, [r2+r3*1]
831     pshufb    m0, m2
832     pshufb    m1, m2
833     pmaddubsw m0, m3
834     pmaddubsw m1, m3
835     psraw     m0, 2
836     psraw     m1, 2
837     pavgw     m0, m4
838     pavgw     m1, m4
839 %if mmsize==8
840     packuswb  m0, m0
841     packuswb  m1, m1
842     movh [r0+r1*0], m0
843     movh [r0+r1*1], m1
844 %else
845     packuswb  m0, m1
846     movh   [r0+r1*0], m0
847     movhps [r0+r1*1], m0
848 %endif
849
850     lea       r0, [r0+r1*2]
851     lea       r2, [r2+r3*2]
852     sub       r4, 2
853     jg .nextrow
854     REP_RET
855 %endmacro
856
857 INIT_MMX
858 FILTER_BILINEAR_SSSE3 4
859 INIT_XMM
860 FILTER_BILINEAR_SSSE3 8
861
862 cglobal put_vp8_pixels8_mmx, 5,5
863 .nextrow:
864     movq  mm0, [r2+r3*0]
865     movq  mm1, [r2+r3*1]
866     lea    r2, [r2+r3*2]
867     movq [r0+r1*0], mm0
868     movq [r0+r1*1], mm1
869     lea    r0, [r0+r1*2]
870     sub   r4d, 2
871     jg .nextrow
872     REP_RET
873
874 cglobal put_vp8_pixels16_mmx, 5,5
875 .nextrow:
876     movq  mm0, [r2+r3*0+0]
877     movq  mm1, [r2+r3*0+8]
878     movq  mm2, [r2+r3*1+0]
879     movq  mm3, [r2+r3*1+8]
880     lea    r2, [r2+r3*2]
881     movq [r0+r1*0+0], mm0
882     movq [r0+r1*0+8], mm1
883     movq [r0+r1*1+0], mm2
884     movq [r0+r1*1+8], mm3
885     lea    r0, [r0+r1*2]
886     sub   r4d, 2
887     jg .nextrow
888     REP_RET
889
890 cglobal put_vp8_pixels16_sse, 5,5,2
891 .nextrow:
892     movups xmm0, [r2+r3*0]
893     movups xmm1, [r2+r3*1]
894     lea     r2, [r2+r3*2]
895     movaps [r0+r1*0], xmm0
896     movaps [r0+r1*1], xmm1
897     lea     r0, [r0+r1*2]
898     sub    r4d, 2
899     jg .nextrow
900     REP_RET
901
902 ;-----------------------------------------------------------------------------
903 ; void vp8_idct_dc_add_<opt>(uint8_t *dst, DCTELEM block[16], int stride);
904 ;-----------------------------------------------------------------------------
905
906 %macro ADD_DC 4
907     %4        m2, [r0+%3]
908     %4        m3, [r0+r2+%3]
909     %4        m4, [r1+%3]
910     %4        m5, [r1+r2+%3]
911     paddusb   m2, %1
912     paddusb   m3, %1
913     paddusb   m4, %1
914     paddusb   m5, %1
915     psubusb   m2, %2
916     psubusb   m3, %2
917     psubusb   m4, %2
918     psubusb   m5, %2
919     %4    [r0+%3], m2
920     %4 [r0+r2+%3], m3
921     %4    [r1+%3], m4
922     %4 [r1+r2+%3], m5
923 %endmacro
924
925 INIT_MMX
926 cglobal vp8_idct_dc_add_mmx, 3, 3
927     ; load data
928     movd       m0, [r1]
929
930     ; calculate DC
931     paddw      m0, [pw_4]
932     pxor       m1, m1
933     psraw      m0, 3
934     movd      [r1], m1
935     psubw      m1, m0
936     packuswb   m0, m0
937     packuswb   m1, m1
938     punpcklbw  m0, m0
939     punpcklbw  m1, m1
940     punpcklwd  m0, m0
941     punpcklwd  m1, m1
942
943     ; add DC
944     lea        r1, [r0+r2*2]
945     ADD_DC     m0, m1, 0, movh
946     RET
947
948 INIT_XMM
949 cglobal vp8_idct_dc_add_sse4, 3, 3, 6
950     ; load data
951     movd       m0, [r1]
952     pxor       m1, m1
953
954     ; calculate DC
955     paddw      m0, [pw_4]
956     movd     [r1], m1
957     lea        r1, [r0+r2*2]
958     movd       m2, [r0]
959     movd       m3, [r0+r2]
960     movd       m4, [r1]
961     movd       m5, [r1+r2]
962     psraw      m0, 3
963     pshuflw    m0, m0, 0
964     punpcklqdq m0, m0
965     punpckldq  m2, m3
966     punpckldq  m4, m5
967     punpcklbw  m2, m1
968     punpcklbw  m4, m1
969     paddw      m2, m0
970     paddw      m4, m0
971     packuswb   m2, m4
972     movd      [r0], m2
973     pextrd [r0+r2], m2, 1
974     pextrd    [r1], m2, 2
975     pextrd [r1+r2], m2, 3
976     RET
977
978 ;-----------------------------------------------------------------------------
979 ; void vp8_idct_dc_add4y_<opt>(uint8_t *dst, DCTELEM block[4][16], int stride);
980 ;-----------------------------------------------------------------------------
981
982 INIT_MMX
983 cglobal vp8_idct_dc_add4y_mmx, 3, 3
984     ; load data
985     movd      m0, [r1+32*0] ; A
986     movd      m1, [r1+32*2] ; C
987     punpcklwd m0, [r1+32*1] ; A B
988     punpcklwd m1, [r1+32*3] ; C D
989     punpckldq m0, m1        ; A B C D
990     pxor      m6, m6
991
992     ; calculate DC
993     paddw     m0, [pw_4]
994     movd [r1+32*0], m6
995     movd [r1+32*1], m6
996     movd [r1+32*2], m6
997     movd [r1+32*3], m6
998     psraw     m0, 3
999     psubw     m6, m0
1000     packuswb  m0, m0
1001     packuswb  m6, m6
1002     punpcklbw m0, m0 ; AABBCCDD
1003     punpcklbw m6, m6 ; AABBCCDD
1004     movq      m1, m0
1005     movq      m7, m6
1006     punpcklbw m0, m0 ; AAAABBBB
1007     punpckhbw m1, m1 ; CCCCDDDD
1008     punpcklbw m6, m6 ; AAAABBBB
1009     punpckhbw m7, m7 ; CCCCDDDD
1010
1011     ; add DC
1012     lea       r1, [r0+r2*2]
1013     ADD_DC    m0, m6, 0, mova
1014     ADD_DC    m1, m7, 8, mova
1015     RET
1016
1017 INIT_XMM
1018 cglobal vp8_idct_dc_add4y_sse2, 3, 3, 6
1019     ; load data
1020     movd      m0, [r1+32*0] ; A
1021     movd      m1, [r1+32*2] ; C
1022     punpcklwd m0, [r1+32*1] ; A B
1023     punpcklwd m1, [r1+32*3] ; C D
1024     punpckldq m0, m1        ; A B C D
1025     pxor      m1, m1
1026
1027     ; calculate DC
1028     paddw     m0, [pw_4]
1029     movd [r1+32*0], m1
1030     movd [r1+32*1], m1
1031     movd [r1+32*2], m1
1032     movd [r1+32*3], m1
1033     psraw     m0, 3
1034     psubw     m1, m0
1035     packuswb  m0, m0
1036     packuswb  m1, m1
1037     punpcklbw m0, m0
1038     punpcklbw m1, m1
1039     punpcklbw m0, m0
1040     punpcklbw m1, m1
1041
1042     ; add DC
1043     lea       r1, [r0+r2*2]
1044     ADD_DC    m0, m1, 0, mova
1045     RET
1046
1047 ;-----------------------------------------------------------------------------
1048 ; void vp8_idct_dc_add4uv_<opt>(uint8_t *dst, DCTELEM block[4][16], int stride);
1049 ;-----------------------------------------------------------------------------
1050
1051 INIT_MMX
1052 cglobal vp8_idct_dc_add4uv_mmx, 3, 3
1053     ; load data
1054     movd      m0, [r1+32*0] ; A
1055     movd      m1, [r1+32*2] ; C
1056     punpcklwd m0, [r1+32*1] ; A B
1057     punpcklwd m1, [r1+32*3] ; C D
1058     punpckldq m0, m1        ; A B C D
1059     pxor      m6, m6
1060
1061     ; calculate DC
1062     paddw     m0, [pw_4]
1063     movd [r1+32*0], m6
1064     movd [r1+32*1], m6
1065     movd [r1+32*2], m6
1066     movd [r1+32*3], m6
1067     psraw     m0, 3
1068     psubw     m6, m0
1069     packuswb  m0, m0
1070     packuswb  m6, m6
1071     punpcklbw m0, m0 ; AABBCCDD
1072     punpcklbw m6, m6 ; AABBCCDD
1073     movq      m1, m0
1074     movq      m7, m6
1075     punpcklbw m0, m0 ; AAAABBBB
1076     punpckhbw m1, m1 ; CCCCDDDD
1077     punpcklbw m6, m6 ; AAAABBBB
1078     punpckhbw m7, m7 ; CCCCDDDD
1079
1080     ; add DC
1081     lea       r1, [r0+r2*2]
1082     ADD_DC    m0, m6, 0, mova
1083     lea       r0, [r0+r2*4]
1084     lea       r1, [r1+r2*4]
1085     ADD_DC    m1, m7, 0, mova
1086     RET
1087
1088 ;-----------------------------------------------------------------------------
1089 ; void vp8_idct_add_<opt>(uint8_t *dst, DCTELEM block[16], int stride);
1090 ;-----------------------------------------------------------------------------
1091
1092 ; calculate %1=mul_35468(%1)-mul_20091(%2); %2=mul_20091(%1)+mul_35468(%2)
1093 ;           this macro assumes that m6/m7 have words for 20091/17734 loaded
1094 %macro VP8_MULTIPLY_SUMSUB 4
1095     mova      %3, %1
1096     mova      %4, %2
1097     pmulhw    %3, m6 ;20091(1)
1098     pmulhw    %4, m6 ;20091(2)
1099     paddw     %3, %1
1100     paddw     %4, %2
1101     paddw     %1, %1
1102     paddw     %2, %2
1103     pmulhw    %1, m7 ;35468(1)
1104     pmulhw    %2, m7 ;35468(2)
1105     psubw     %1, %4
1106     paddw     %2, %3
1107 %endmacro
1108
1109 ; calculate x0=%1+%3; x1=%1-%3
1110 ;           x2=mul_35468(%2)-mul_20091(%4); x3=mul_20091(%2)+mul_35468(%4)
1111 ;           %1=x0+x3 (tmp0); %2=x1+x2 (tmp1); %3=x1-x2 (tmp2); %4=x0-x3 (tmp3)
1112 ;           %5/%6 are temporary registers
1113 ;           we assume m6/m7 have constant words 20091/17734 loaded in them
1114 %macro VP8_IDCT_TRANSFORM4x4_1D 6
1115     SUMSUB_BA           m%3, m%1, m%5     ;t0, t1
1116     VP8_MULTIPLY_SUMSUB m%2, m%4, m%5,m%6 ;t2, t3
1117     SUMSUB_BA           m%4, m%3, m%5     ;tmp0, tmp3
1118     SUMSUB_BA           m%2, m%1, m%5     ;tmp1, tmp2
1119     SWAP                 %4,  %1
1120     SWAP                 %4,  %3
1121 %endmacro
1122
1123 INIT_MMX
1124 %macro VP8_IDCT_ADD 1
1125 cglobal vp8_idct_add_%1, 3, 3
1126     ; load block data
1127     movq         m0, [r1+ 0]
1128     movq         m1, [r1+ 8]
1129     movq         m2, [r1+16]
1130     movq         m3, [r1+24]
1131     movq         m6, [pw_20091]
1132     movq         m7, [pw_17734]
1133 %ifidn %1, sse
1134     xorps      xmm0, xmm0
1135     movaps  [r1+ 0], xmm0
1136     movaps  [r1+16], xmm0
1137 %else
1138     pxor         m4, m4
1139     movq    [r1+ 0], m4
1140     movq    [r1+ 8], m4
1141     movq    [r1+16], m4
1142     movq    [r1+24], m4
1143 %endif
1144
1145     ; actual IDCT
1146     VP8_IDCT_TRANSFORM4x4_1D 0, 1, 2, 3, 4, 5
1147     TRANSPOSE4x4W            0, 1, 2, 3, 4
1148     paddw        m0, [pw_4]
1149     VP8_IDCT_TRANSFORM4x4_1D 0, 1, 2, 3, 4, 5
1150     TRANSPOSE4x4W            0, 1, 2, 3, 4
1151
1152     ; store
1153     pxor         m4, m4
1154     lea          r1, [r0+2*r2]
1155     STORE_DIFFx2 m0, m1, m6, m7, m4, 3, r0, r2
1156     STORE_DIFFx2 m2, m3, m6, m7, m4, 3, r1, r2
1157
1158     RET
1159 %endmacro
1160
1161 VP8_IDCT_ADD mmx
1162 VP8_IDCT_ADD sse
1163
1164 ;-----------------------------------------------------------------------------
1165 ; void vp8_luma_dc_wht_mmxext(DCTELEM block[4][4][16], DCTELEM dc[16])
1166 ;-----------------------------------------------------------------------------
1167
1168 %macro SCATTER_WHT 3
1169     movd  r1d, m%1
1170     movd  r2d, m%2
1171     mov [r0+2*16*(0+%3)], r1w
1172     mov [r0+2*16*(1+%3)], r2w
1173     shr   r1d, 16
1174     shr   r2d, 16
1175     psrlq m%1, 32
1176     psrlq m%2, 32
1177     mov [r0+2*16*(4+%3)], r1w
1178     mov [r0+2*16*(5+%3)], r2w
1179     movd  r1d, m%1
1180     movd  r2d, m%2
1181     mov [r0+2*16*(8+%3)], r1w
1182     mov [r0+2*16*(9+%3)], r2w
1183     shr   r1d, 16
1184     shr   r2d, 16
1185     mov [r0+2*16*(12+%3)], r1w
1186     mov [r0+2*16*(13+%3)], r2w
1187 %endmacro
1188
1189 %macro HADAMARD4_1D 4
1190     SUMSUB_BADC m%2, m%1, m%4, m%3
1191     SUMSUB_BADC m%4, m%2, m%3, m%1
1192     SWAP %1, %4, %3
1193 %endmacro
1194
1195 INIT_MMX
1196 cglobal vp8_luma_dc_wht_mmx, 2,3
1197     movq          m0, [r1]
1198     movq          m1, [r1+8]
1199     movq          m2, [r1+16]
1200     movq          m3, [r1+24]
1201     HADAMARD4_1D  0, 1, 2, 3
1202     TRANSPOSE4x4W 0, 1, 2, 3, 4
1203     paddw         m0, [pw_3]
1204     HADAMARD4_1D  0, 1, 2, 3
1205     psraw         m0, 3
1206     psraw         m1, 3
1207     psraw         m2, 3
1208     psraw         m3, 3
1209     SCATTER_WHT   0, 1, 0
1210     SCATTER_WHT   2, 3, 2
1211     RET
1212
1213 ;-----------------------------------------------------------------------------
1214 ; void vp8_h/v_loop_filter_simple_<opt>(uint8_t *dst, int stride, int flim);
1215 ;-----------------------------------------------------------------------------
1216
1217 ; macro called with 7 mm register indexes as argument, and 4 regular registers
1218 ;
1219 ; first 4 mm registers will carry the transposed pixel data
1220 ; the other three are scratchspace (one would be sufficient, but this allows
1221 ; for more spreading/pipelining and thus faster execution on OOE CPUs)
1222 ;
1223 ; first two regular registers are buf+4*stride and buf+5*stride
1224 ; third is -stride, fourth is +stride
1225 %macro READ_8x4_INTERLEAVED 11
1226     ; interleave 8 (A-H) rows of 4 pixels each
1227     movd          m%1, [%8+%10*4]   ; A0-3
1228     movd          m%5, [%9+%10*4]   ; B0-3
1229     movd          m%2, [%8+%10*2]   ; C0-3
1230     movd          m%6, [%8+%10]     ; D0-3
1231     movd          m%3, [%8]         ; E0-3
1232     movd          m%7, [%9]         ; F0-3
1233     movd          m%4, [%9+%11]     ; G0-3
1234     punpcklbw     m%1, m%5          ; A/B interleaved
1235     movd          m%5, [%9+%11*2]   ; H0-3
1236     punpcklbw     m%2, m%6          ; C/D interleaved
1237     punpcklbw     m%3, m%7          ; E/F interleaved
1238     punpcklbw     m%4, m%5          ; G/H interleaved
1239 %endmacro
1240
1241 ; macro called with 7 mm register indexes as argument, and 5 regular registers
1242 ; first 11 mean the same as READ_8x4_TRANSPOSED above
1243 ; fifth regular register is scratchspace to reach the bottom 8 rows, it
1244 ; will be set to second regular register + 8*stride at the end
1245 %macro READ_16x4_INTERLEAVED 12
1246     ; transpose 16 (A-P) rows of 4 pixels each
1247     lea           %12, [r0+8*r2]
1248
1249     ; read (and interleave) those addressable by %8 (=r0), A/C/D/E/I/K/L/M
1250     movd          m%1, [%8+%10*4]   ; A0-3
1251     movd          m%3, [%12+%10*4]  ; I0-3
1252     movd          m%2, [%8+%10*2]   ; C0-3
1253     movd          m%4, [%12+%10*2]  ; K0-3
1254     movd          m%6, [%8+%10]     ; D0-3
1255     movd          m%5, [%12+%10]    ; L0-3
1256     movd          m%7, [%12]        ; M0-3
1257     add           %12, %11
1258     punpcklbw     m%1, m%3          ; A/I
1259     movd          m%3, [%8]         ; E0-3
1260     punpcklbw     m%2, m%4          ; C/K
1261     punpcklbw     m%6, m%5          ; D/L
1262     punpcklbw     m%3, m%7          ; E/M
1263     punpcklbw     m%2, m%6          ; C/D/K/L interleaved
1264
1265     ; read (and interleave) those addressable by %9 (=r4), B/F/G/H/J/N/O/P
1266     movd         m%5, [%9+%10*4]   ; B0-3
1267     movd         m%4, [%12+%10*4]  ; J0-3
1268     movd         m%7, [%9]         ; F0-3
1269     movd         m%6, [%12]        ; N0-3
1270     punpcklbw    m%5, m%4          ; B/J
1271     punpcklbw    m%7, m%6          ; F/N
1272     punpcklbw    m%1, m%5          ; A/B/I/J interleaved
1273     punpcklbw    m%3, m%7          ; E/F/M/N interleaved
1274     movd         m%4, [%9+%11]     ; G0-3
1275     movd         m%6, [%12+%11]    ; O0-3
1276     movd         m%5, [%9+%11*2]   ; H0-3
1277     movd         m%7, [%12+%11*2]  ; P0-3
1278     punpcklbw    m%4, m%6          ; G/O
1279     punpcklbw    m%5, m%7          ; H/P
1280     punpcklbw    m%4, m%5          ; G/H/O/P interleaved
1281 %endmacro
1282
1283 ; write 4 mm registers of 2 dwords each
1284 ; first four arguments are mm register indexes containing source data
1285 ; last four are registers containing buf+4*stride, buf+5*stride,
1286 ; -stride and +stride
1287 %macro WRITE_4x2D 8
1288     ; write out (2 dwords per register)
1289     movd    [%5+%7*4], m%1
1290     movd    [%5+%7*2], m%2
1291     movd         [%5], m%3
1292     movd      [%6+%8], m%4
1293     punpckhdq     m%1, m%1
1294     punpckhdq     m%2, m%2
1295     punpckhdq     m%3, m%3
1296     punpckhdq     m%4, m%4
1297     movd    [%6+%7*4], m%1
1298     movd      [%5+%7], m%2
1299     movd         [%6], m%3
1300     movd    [%6+%8*2], m%4
1301 %endmacro
1302
1303 ; write 4 xmm registers of 4 dwords each
1304 ; arguments same as WRITE_2x4D, but with an extra register, so that the 5 regular
1305 ; registers contain buf+4*stride, buf+5*stride, buf+12*stride, -stride and +stride
1306 ; we add 1*stride to the third regular registry in the process
1307 ; the 10th argument is 16 if it's a Y filter (i.e. all regular registers cover the
1308 ; same memory region), or 8 if they cover two separate buffers (third one points to
1309 ; a different memory region than the first two), allowing for more optimal code for
1310 ; the 16-width case
1311 %macro WRITE_4x4D 10
1312     ; write out (4 dwords per register), start with dwords zero
1313     movd    [%5+%8*4], m%1
1314     movd         [%5], m%2
1315     movd    [%7+%8*4], m%3
1316     movd         [%7], m%4
1317
1318     ; store dwords 1
1319     psrldq        m%1, 4
1320     psrldq        m%2, 4
1321     psrldq        m%3, 4
1322     psrldq        m%4, 4
1323     movd    [%6+%8*4], m%1
1324     movd         [%6], m%2
1325 %if %10 == 16
1326     movd    [%6+%9*4], m%3
1327 %endif
1328     movd      [%7+%9], m%4
1329
1330     ; write dwords 2
1331     psrldq        m%1, 4
1332     psrldq        m%2, 4
1333 %if %10 == 8
1334     movd    [%5+%8*2], m%1
1335     movd           %5, m%3
1336 %endif
1337     psrldq        m%3, 4
1338     psrldq        m%4, 4
1339 %if %10 == 16
1340     movd    [%5+%8*2], m%1
1341 %endif
1342     movd      [%6+%9], m%2
1343     movd    [%7+%8*2], m%3
1344     movd    [%7+%9*2], m%4
1345     add            %7, %9
1346
1347     ; store dwords 3
1348     psrldq        m%1, 4
1349     psrldq        m%2, 4
1350     psrldq        m%3, 4
1351     psrldq        m%4, 4
1352 %if %10 == 8
1353     mov     [%7+%8*4], %5d
1354     movd    [%6+%8*2], m%1
1355 %else
1356     movd      [%5+%8], m%1
1357 %endif
1358     movd    [%6+%9*2], m%2
1359     movd    [%7+%8*2], m%3
1360     movd    [%7+%9*2], m%4
1361 %endmacro
1362
1363 %macro SPLATB_REG_MMX 2-3
1364     movd           %1, %2
1365     punpcklbw      %1, %1
1366     punpcklwd      %1, %1
1367     punpckldq      %1, %1
1368 %endmacro
1369
1370 %macro SPLATB_REG_MMXEXT 2-3
1371     movd           %1, %2
1372     punpcklbw      %1, %1
1373     pshufw         %1, %1, 0x0
1374 %endmacro
1375
1376 %macro SPLATB_REG_SSE2 2-3
1377     movd           %1, %2
1378     punpcklbw      %1, %1
1379     pshuflw        %1, %1, 0x0
1380     punpcklqdq     %1, %1
1381 %endmacro
1382
1383 %macro SPLATB_REG_SSSE3 3
1384     movd           %1, %2
1385     pshufb         %1, %3
1386 %endmacro
1387
1388 %macro SIMPLE_LOOPFILTER 3
1389 cglobal vp8_%2_loop_filter_simple_%1, 3, %3
1390 %ifidn %2, h
1391     mov            r5, rsp          ; backup stack pointer
1392     and           rsp, ~(mmsize-1)  ; align stack
1393 %endif
1394 %if mmsize == 8 ; mmx/mmxext
1395     mov            r3, 2
1396 %endif
1397 %ifnidn %1, sse2 && mmsize == 16
1398     pxor           m0, m0
1399 %endif
1400     SPLATB_REG     m7, r2, m0       ; splat "flim" into register
1401
1402     ; set up indexes to address 4 rows
1403     mov            r2, r1
1404     neg            r1
1405 %ifidn %2, h
1406     lea            r0, [r0+4*r2-2]
1407     sub           rsp, mmsize*2     ; (aligned) storage space for saving p1/q1
1408 %endif
1409
1410 %if mmsize == 8 ; mmx / mmxext
1411 .next8px
1412 %endif
1413 %ifidn %2, v
1414     ; read 4 half/full rows of pixels
1415     mova           m0, [r0+r1*2]    ; p1
1416     mova           m1, [r0+r1]      ; p0
1417     mova           m2, [r0]         ; q0
1418     mova           m3, [r0+r2]      ; q1
1419 %else ; h
1420     lea            r4, [r0+r2]
1421
1422 %if mmsize == 8 ; mmx/mmxext
1423     READ_8x4_INTERLEAVED  0, 1, 2, 3, 4, 5, 6, r0, r4, r1, r2
1424 %else ; sse2
1425     READ_16x4_INTERLEAVED 0, 1, 2, 3, 4, 5, 6, r0, r4, r1, r2, r3
1426 %endif
1427     TRANSPOSE4x4W         0, 1, 2, 3, 4
1428
1429     mova        [rsp], m0           ; store p1
1430     mova [rsp+mmsize], m3           ; store q1
1431 %endif
1432
1433     ; simple_limit
1434     mova           m5, m2           ; m5=backup of q0
1435     mova           m6, m1           ; m6=backup of p0
1436     psubusb        m1, m2           ; p0-q0
1437     psubusb        m2, m6           ; q0-p0
1438     por            m1, m2           ; FFABS(p0-q0)
1439     paddusb        m1, m1           ; m1=FFABS(p0-q0)*2
1440
1441     mova           m4, m3
1442     mova           m2, m0
1443     psubusb        m3, m0           ; q1-p1
1444     psubusb        m0, m4           ; p1-q1
1445     por            m3, m0           ; FFABS(p1-q1)
1446     mova           m0, [pb_80]
1447     pxor           m2, m0
1448     pxor           m4, m0
1449     psubsb         m2, m4           ; m2=p1-q1 (signed) backup for below
1450     pand           m3, [pb_FE]
1451     psrlq          m3, 1            ; m3=FFABS(p1-q1)/2, this can be used signed
1452     paddusb        m3, m1
1453     psubusb        m3, m7
1454     pxor           m1, m1
1455     pcmpeqb        m3, m1           ; abs(p0-q0)*2+abs(p1-q1)/2<=flim mask(0xff/0x0)
1456
1457     ; filter_common (use m2/p1-q1, m4=q0, m6=p0, m5/q0-p0 and m3/mask)
1458     mova           m4, m5
1459     pxor           m5, m0
1460     pxor           m0, m6
1461     psubsb         m5, m0           ; q0-p0 (signed)
1462     paddsb         m2, m5
1463     paddsb         m2, m5
1464     paddsb         m2, m5           ; a=(p1-q1) + 3*(q0-p0)
1465     pand           m2, m3           ; apply filter mask (m3)
1466
1467     mova           m3, [pb_F8]
1468     mova           m1, m2
1469     paddsb         m2, [pb_4]       ; f1<<3=a+4
1470     paddsb         m1, [pb_3]       ; f2<<3=a+3
1471     pand           m2, m3
1472     pand           m1, m3           ; cache f2<<3
1473
1474     pxor           m0, m0
1475     pxor           m3, m3
1476     pcmpgtb        m0, m2           ; which values are <0?
1477     psubb          m3, m2           ; -f1<<3
1478     psrlq          m2, 3            ; +f1
1479     psrlq          m3, 3            ; -f1
1480     pand           m3, m0
1481     pandn          m0, m2
1482     psubusb        m4, m0
1483     paddusb        m4, m3           ; q0-f1
1484
1485     pxor           m0, m0
1486     pxor           m3, m3
1487     pcmpgtb        m0, m1           ; which values are <0?
1488     psubb          m3, m1           ; -f2<<3
1489     psrlq          m1, 3            ; +f2
1490     psrlq          m3, 3            ; -f2
1491     pand           m3, m0
1492     pandn          m0, m1
1493     paddusb        m6, m0
1494     psubusb        m6, m3           ; p0+f2
1495
1496     ; store
1497 %ifidn %2, v
1498     mova         [r0], m4
1499     mova      [r0+r1], m6
1500 %else ; h
1501     mova           m0, [rsp]        ; p1
1502     SWAP            2, 4            ; p0
1503     SWAP            1, 6            ; q0
1504     mova           m3, [rsp+mmsize] ; q1
1505
1506     TRANSPOSE4x4B  0, 1, 2, 3, 4
1507 %if mmsize == 16 ; sse2
1508     add            r3, r1           ; change from r4*8*stride to r0+8*stride
1509     WRITE_4x4D 0, 1, 2, 3, r0, r4, r3, r1, r2, 16
1510 %else ; mmx/mmxext
1511     WRITE_4x2D 0, 1, 2, 3, r0, r4, r1, r2
1512 %endif
1513 %endif
1514
1515 %if mmsize == 8 ; mmx/mmxext
1516     ; next 8 pixels
1517 %ifidn %2, v
1518     add            r0, 8            ; advance 8 cols = pixels
1519 %else ; h
1520     lea            r0, [r0+r2*8]    ; advance 8 rows = lines
1521 %endif
1522     dec            r3
1523     jg .next8px
1524 %ifidn %2, v
1525     REP_RET
1526 %else ; h
1527     mov           rsp, r5           ; restore stack pointer
1528     RET
1529 %endif
1530 %else ; sse2
1531 %ifidn %2, h
1532     mov           rsp, r5           ; restore stack pointer
1533 %endif
1534     RET
1535 %endif
1536 %endmacro
1537
1538 INIT_MMX
1539 %define SPLATB_REG SPLATB_REG_MMX
1540 SIMPLE_LOOPFILTER mmx,    v, 4
1541 SIMPLE_LOOPFILTER mmx,    h, 6
1542 %define SPLATB_REG SPLATB_REG_MMXEXT
1543 SIMPLE_LOOPFILTER mmxext, v, 4
1544 SIMPLE_LOOPFILTER mmxext, h, 6
1545 INIT_XMM
1546 %define SPLATB_REG SPLATB_REG_SSE2
1547 SIMPLE_LOOPFILTER sse2,   v, 3
1548 SIMPLE_LOOPFILTER sse2,   h, 6
1549 %define SPLATB_REG SPLATB_REG_SSSE3
1550 SIMPLE_LOOPFILTER ssse3,  v, 3
1551 SIMPLE_LOOPFILTER ssse3,  h, 6
1552
1553 ;-----------------------------------------------------------------------------
1554 ; void vp8_h/v_loop_filter<size>_inner_<opt>(uint8_t *dst, [uint8_t *v,] int stride,
1555 ;                                            int flimE, int flimI, int hev_thr);
1556 ;-----------------------------------------------------------------------------
1557
1558 %macro INNER_LOOPFILTER 5
1559 %if %4 == 8 ; chroma
1560 cglobal vp8_%2_loop_filter8uv_inner_%1, 6, %3, %5
1561 %define dst8_reg    r1
1562 %define mstride_reg r2
1563 %define E_reg       r3
1564 %define I_reg       r4
1565 %define hev_thr_reg r5
1566 %else ; luma
1567 cglobal vp8_%2_loop_filter16y_inner_%1, 5, %3, %5
1568 %define mstride_reg r1
1569 %define E_reg       r2
1570 %define I_reg       r3
1571 %define hev_thr_reg r4
1572 %ifdef m8 ; x86-64, sse2
1573 %define dst8_reg    r4
1574 %elif mmsize == 16 ; x86-32, sse2
1575 %define dst8_reg    r5
1576 %else ; x86-32, mmx/mmxext
1577 %define cnt_reg     r5
1578 %endif
1579 %endif
1580 %define dst_reg     r0
1581 %define stride_reg  E_reg
1582 %define dst2_reg    I_reg
1583 %ifndef m8
1584 %define stack_reg   hev_thr_reg
1585 %endif
1586
1587 %ifnidn %1, sse2 && mmsize == 16
1588     pxor             m7, m7
1589 %endif
1590
1591 %ifndef m8 ; mmx/mmxext or sse2 on x86-32
1592     ; splat function arguments
1593     SPLATB_REG       m0, E_reg, m7   ; E
1594     SPLATB_REG       m1, I_reg, m7   ; I
1595     SPLATB_REG       m2, hev_thr_reg, m7 ; hev_thresh
1596
1597     ; align stack
1598     mov       stack_reg, rsp         ; backup stack pointer
1599     and             rsp, ~(mmsize-1) ; align stack
1600 %ifidn %2, v
1601     sub             rsp, mmsize * 4  ; stack layout: [0]=E, [1]=I, [2]=hev_thr
1602                                      ;               [3]=hev() result
1603 %else ; h
1604     sub             rsp, mmsize * 5  ; extra storage space for transposes
1605 %endif
1606
1607 %define flim_E   [rsp]
1608 %define flim_I   [rsp+mmsize]
1609 %define hev_thr  [rsp+mmsize*2]
1610 %define mask_res [rsp+mmsize*3]
1611 %define p0backup [rsp+mmsize*3]
1612 %define q0backup [rsp+mmsize*4]
1613
1614     mova         flim_E, m0
1615     mova         flim_I, m1
1616     mova        hev_thr, m2
1617
1618 %else ; sse2 on x86-64
1619
1620 %define flim_E   m9
1621 %define flim_I   m10
1622 %define hev_thr  m11
1623 %define mask_res m12
1624 %define p0backup m12
1625 %define q0backup m8
1626
1627     ; splat function arguments
1628     SPLATB_REG   flim_E, E_reg, m7   ; E
1629     SPLATB_REG   flim_I, I_reg, m7   ; I
1630     SPLATB_REG  hev_thr, hev_thr_reg, m7 ; hev_thresh
1631 %endif
1632
1633 %if mmsize == 8 && %4 == 16 ; mmx/mmxext
1634     mov         cnt_reg, 2
1635 %endif
1636     mov      stride_reg, mstride_reg
1637     neg     mstride_reg
1638 %ifidn %2, h
1639     lea         dst_reg, [dst_reg + stride_reg*4-4]
1640 %if %4 == 8
1641     lea        dst8_reg, [dst8_reg+ stride_reg*4-4]
1642 %endif
1643 %endif
1644
1645 %if mmsize == 8
1646 .next8px
1647 %endif
1648     ; read
1649     lea        dst2_reg, [dst_reg + stride_reg]
1650 %ifidn %2, v
1651 %if %4 == 8 && mmsize == 16
1652 %define movrow movh
1653 %else
1654 %define movrow mova
1655 %endif
1656     movrow           m0, [dst_reg +mstride_reg*4] ; p3
1657     movrow           m1, [dst2_reg+mstride_reg*4] ; p2
1658     movrow           m2, [dst_reg +mstride_reg*2] ; p1
1659     movrow           m5, [dst2_reg]               ; q1
1660     movrow           m6, [dst2_reg+ stride_reg]   ; q2
1661     movrow           m7, [dst2_reg+ stride_reg*2] ; q3
1662 %if mmsize == 16 && %4 == 8
1663     movhps           m0, [dst8_reg+mstride_reg*4]
1664     movhps           m2, [dst8_reg+mstride_reg*2]
1665     add        dst8_reg, stride_reg
1666     movhps           m1, [dst8_reg+mstride_reg*4]
1667     movhps           m5, [dst8_reg]
1668     movhps           m6, [dst8_reg+ stride_reg]
1669     movhps           m7, [dst8_reg+ stride_reg*2]
1670     add        dst8_reg, mstride_reg
1671 %endif
1672 %elif mmsize == 8 ; mmx/mmxext (h)
1673     ; read 8 rows of 8px each
1674     movu             m0, [dst_reg +mstride_reg*4]
1675     movu             m1, [dst2_reg+mstride_reg*4]
1676     movu             m2, [dst_reg +mstride_reg*2]
1677     movu             m3, [dst_reg +mstride_reg]
1678     movu             m4, [dst_reg]
1679     movu             m5, [dst2_reg]
1680     movu             m6, [dst2_reg+ stride_reg]
1681
1682     ; 8x8 transpose
1683     TRANSPOSE4x4B     0, 1, 2, 3, 7
1684     mova       q0backup, m1
1685     movu             m7, [dst2_reg+ stride_reg*2]
1686     TRANSPOSE4x4B     4, 5, 6, 7, 1
1687     SBUTTERFLY       dq, 0, 4, 1     ; p3/p2
1688     SBUTTERFLY       dq, 2, 6, 1     ; q0/q1
1689     SBUTTERFLY       dq, 3, 7, 1     ; q2/q3
1690     mova             m1, q0backup
1691     mova       q0backup, m2          ; store q0
1692     SBUTTERFLY       dq, 1, 5, 2     ; p1/p0
1693     mova       p0backup, m5          ; store p0
1694     SWAP              1, 4
1695     SWAP              2, 4
1696     SWAP              6, 3
1697     SWAP              5, 3
1698 %else ; sse2 (h)
1699 %if %4 == 16
1700     lea        dst8_reg, [dst_reg + stride_reg*8]
1701 %endif
1702
1703     ; read 16 rows of 8px each, interleave
1704     movh             m0, [dst_reg +mstride_reg*4]
1705     movh             m1, [dst8_reg+mstride_reg*4]
1706     movh             m2, [dst_reg +mstride_reg*2]
1707     movh             m5, [dst8_reg+mstride_reg*2]
1708     movh             m3, [dst_reg +mstride_reg]
1709     movh             m6, [dst8_reg+mstride_reg]
1710     movh             m4, [dst_reg]
1711     movh             m7, [dst8_reg]
1712     punpcklbw        m0, m1          ; A/I
1713     punpcklbw        m2, m5          ; C/K
1714     punpcklbw        m3, m6          ; D/L
1715     punpcklbw        m4, m7          ; E/M
1716
1717     add        dst8_reg, stride_reg
1718     movh             m1, [dst2_reg+mstride_reg*4]
1719     movh             m6, [dst8_reg+mstride_reg*4]
1720     movh             m5, [dst2_reg]
1721     movh             m7, [dst8_reg]
1722     punpcklbw        m1, m6          ; B/J
1723     punpcklbw        m5, m7          ; F/N
1724     movh             m6, [dst2_reg+ stride_reg]
1725     movh             m7, [dst8_reg+ stride_reg]
1726     punpcklbw        m6, m7          ; G/O
1727
1728     ; 8x16 transpose
1729     TRANSPOSE4x4B     0, 1, 2, 3, 7
1730 %ifdef m8
1731     SWAP              1, 8
1732 %else
1733     mova       q0backup, m1
1734 %endif
1735     movh             m7, [dst2_reg+ stride_reg*2]
1736     movh             m1, [dst8_reg+ stride_reg*2]
1737     punpcklbw        m7, m1          ; H/P
1738     TRANSPOSE4x4B     4, 5, 6, 7, 1
1739     SBUTTERFLY       dq, 0, 4, 1     ; p3/p2
1740     SBUTTERFLY       dq, 2, 6, 1     ; q0/q1
1741     SBUTTERFLY       dq, 3, 7, 1     ; q2/q3
1742 %ifdef m8
1743     SWAP              1, 8
1744     SWAP              2, 8
1745 %else
1746     mova             m1, q0backup
1747     mova       q0backup, m2          ; store q0
1748 %endif
1749     SBUTTERFLY       dq, 1, 5, 2     ; p1/p0
1750 %ifdef m12
1751     SWAP              5, 12
1752 %else
1753     mova       p0backup, m5          ; store p0
1754 %endif
1755     SWAP              1, 4
1756     SWAP              2, 4
1757     SWAP              6, 3
1758     SWAP              5, 3
1759 %endif
1760
1761     ; normal_limit for p3-p2, p2-p1, q3-q2 and q2-q1
1762     mova             m4, m1
1763     SWAP              4, 1
1764     psubusb          m4, m0          ; p2-p3
1765     psubusb          m0, m1          ; p3-p2
1766     por              m0, m4          ; abs(p3-p2)
1767
1768     mova             m4, m2
1769     SWAP              4, 2
1770     psubusb          m4, m1          ; p1-p2
1771     psubusb          m1, m2          ; p2-p1
1772     por              m1, m4          ; abs(p2-p1)
1773
1774     mova             m4, m6
1775     SWAP              4, 6
1776     psubusb          m4, m7          ; q2-q3
1777     psubusb          m7, m6          ; q3-q2
1778     por              m7, m4          ; abs(q3-q2)
1779
1780     mova             m4, m5
1781     SWAP              4, 5
1782     psubusb          m4, m6          ; q1-q2
1783     psubusb          m6, m5          ; q2-q1
1784     por              m6, m4          ; abs(q2-q1)
1785
1786 %ifidn %1, mmx
1787     mova             m4, flim_I
1788     pxor             m3, m3
1789     psubusb          m0, m4
1790     psubusb          m1, m4
1791     psubusb          m7, m4
1792     psubusb          m6, m4
1793     pcmpeqb          m0, m3          ; abs(p3-p2) <= I
1794     pcmpeqb          m1, m3          ; abs(p2-p1) <= I
1795     pcmpeqb          m7, m3          ; abs(q3-q2) <= I
1796     pcmpeqb          m6, m3          ; abs(q2-q1) <= I
1797     pand             m0, m1
1798     pand             m7, m6
1799     pand             m0, m7
1800 %else ; mmxext/sse2
1801     pmaxub           m0, m1
1802     pmaxub           m6, m7
1803     pmaxub           m0, m6
1804 %endif
1805
1806     ; normal_limit and high_edge_variance for p1-p0, q1-q0
1807     SWAP              7, 3           ; now m7 is zero
1808 %ifidn %2, v
1809     movrow           m3, [dst_reg +mstride_reg] ; p0
1810 %if mmsize == 16 && %4 == 8
1811     movhps           m3, [dst8_reg+mstride_reg]
1812 %endif
1813 %elifdef m12
1814     SWAP              3, 12
1815 %else
1816     mova             m3, p0backup
1817 %endif
1818
1819     mova             m1, m2
1820     SWAP              1, 2
1821     mova             m6, m3
1822     SWAP              3, 6
1823     psubusb          m1, m3          ; p1-p0
1824     psubusb          m6, m2          ; p0-p1
1825     por              m1, m6          ; abs(p1-p0)
1826 %ifidn %1, mmx
1827     mova             m6, m1
1828     psubusb          m1, m4
1829     psubusb          m6, hev_thr
1830     pcmpeqb          m1, m7          ; abs(p1-p0) <= I
1831     pcmpeqb          m6, m7          ; abs(p1-p0) <= hev_thresh
1832     pand             m0, m1
1833     mova       mask_res, m6
1834 %else ; mmxext/sse2
1835     pmaxub           m0, m1          ; max_I
1836     SWAP              1, 4           ; max_hev_thresh
1837 %endif
1838
1839     SWAP              6, 4           ; now m6 is I
1840 %ifidn %2, v
1841     movrow           m4, [dst_reg]   ; q0
1842 %if mmsize == 16 && %4 == 8
1843     movhps           m4, [dst8_reg]
1844 %endif
1845 %elifdef m8
1846     SWAP              4, 8
1847 %else
1848     mova             m4, q0backup
1849 %endif
1850     mova             m1, m4
1851     SWAP              1, 4
1852     mova             m7, m5
1853     SWAP              7, 5
1854     psubusb          m1, m5          ; q0-q1
1855     psubusb          m7, m4          ; q1-q0
1856     por              m1, m7          ; abs(q1-q0)
1857 %ifidn %1, mmx
1858     mova             m7, m1
1859     psubusb          m1, m6
1860     psubusb          m7, hev_thr
1861     pxor             m6, m6
1862     pcmpeqb          m1, m6          ; abs(q1-q0) <= I
1863     pcmpeqb          m7, m6          ; abs(q1-q0) <= hev_thresh
1864     mova             m6, mask_res
1865     pand             m0, m1          ; abs([pq][321]-[pq][210]) <= I
1866     pand             m6, m7
1867 %else ; mmxext/sse2
1868     pxor             m7, m7
1869     pmaxub           m0, m1
1870     pmaxub           m6, m1
1871     psubusb          m0, flim_I
1872     psubusb          m6, hev_thr
1873     pcmpeqb          m0, m7          ; max(abs(..)) <= I
1874     pcmpeqb          m6, m7          ; !(max(abs..) > thresh)
1875 %endif
1876 %ifdef m12
1877     SWAP              6, 12
1878 %else
1879     mova       mask_res, m6          ; !(abs(p1-p0) > hev_t || abs(q1-q0) > hev_t)
1880 %endif
1881
1882     ; simple_limit
1883     mova             m1, m3
1884     SWAP              1, 3
1885     mova             m6, m4          ; keep copies of p0/q0 around for later use
1886     SWAP              6, 4
1887     psubusb          m1, m4          ; p0-q0
1888     psubusb          m6, m3          ; q0-p0
1889     por              m1, m6          ; abs(q0-p0)
1890     paddusb          m1, m1          ; m1=2*abs(q0-p0)
1891
1892     mova             m7, m2
1893     SWAP              7, 2
1894     mova             m6, m5
1895     SWAP              6, 5
1896     psubusb          m7, m5          ; p1-q1
1897     psubusb          m6, m2          ; q1-p1
1898     por              m7, m6          ; abs(q1-p1)
1899     pxor             m6, m6
1900     pand             m7, [pb_FE]
1901     psrlq            m7, 1           ; abs(q1-p1)/2
1902     paddusb          m7, m1          ; abs(q0-p0)*2+abs(q1-p1)/2
1903     psubusb          m7, flim_E
1904     pcmpeqb          m7, m6          ; abs(q0-p0)*2+abs(q1-p1)/2 <= E
1905     pand             m0, m7          ; normal_limit result
1906
1907     ; filter_common; at this point, m2-m5=p1-q1 and m0 is filter_mask
1908 %ifdef m8 ; x86-64 && sse2
1909     mova             m8, [pb_80]
1910 %define pb_80_var m8
1911 %else ; x86-32 or mmx/mmxext
1912 %define pb_80_var [pb_80]
1913 %endif
1914     mova             m1, m4
1915     mova             m7, m3
1916     pxor             m1, pb_80_var
1917     pxor             m7, pb_80_var
1918     psubsb           m1, m7          ; (signed) q0-p0
1919     mova             m6, m2
1920     mova             m7, m5
1921     pxor             m6, pb_80_var
1922     pxor             m7, pb_80_var
1923     psubsb           m6, m7          ; (signed) p1-q1
1924     mova             m7, mask_res
1925     pandn            m7, m6
1926     paddsb           m7, m1
1927     paddsb           m7, m1
1928     paddsb           m7, m1          ; 3*(q0-p0)+is4tap?(p1-q1)
1929
1930     pand             m7, m0
1931     mova             m1, [pb_F8]
1932     mova             m6, m7
1933     paddsb           m7, [pb_3]
1934     paddsb           m6, [pb_4]
1935     pand             m7, m1
1936     pand             m6, m1
1937
1938     pxor             m1, m1
1939     pxor             m0, m0
1940     pcmpgtb          m1, m7
1941     psubb            m0, m7
1942     psrlq            m7, 3           ; +f2
1943     psrlq            m0, 3           ; -f2
1944     pand             m0, m1
1945     pandn            m1, m7
1946     psubusb          m3, m0
1947     paddusb          m3, m1          ; p0+f2
1948
1949     pxor             m1, m1
1950     pxor             m0, m0
1951     pcmpgtb          m0, m6
1952     psubb            m1, m6
1953     psrlq            m6, 3           ; +f1
1954     psrlq            m1, 3           ; -f1
1955     pand             m1, m0
1956     pandn            m0, m6
1957     psubusb          m4, m0
1958     paddusb          m4, m1          ; q0-f1
1959
1960 %ifdef m12
1961     SWAP              6, 12
1962 %else
1963     mova             m6, mask_res
1964 %endif
1965 %ifidn %1, mmx
1966     mova             m7, [pb_1]
1967 %else ; mmxext/sse2
1968     pxor             m7, m7
1969 %endif
1970     pand             m0, m6
1971     pand             m1, m6
1972 %ifidn %1, mmx
1973     paddusb          m0, m7
1974     pand             m1, [pb_FE]
1975     pandn            m7, m0
1976     psrlq            m1, 1
1977     psrlq            m7, 1
1978     SWAP              0, 7
1979 %else ; mmxext/sse2
1980     psubusb          m1, [pb_1]
1981     pavgb            m0, m7          ; a
1982     pavgb            m1, m7          ; -a
1983 %endif
1984     psubusb          m5, m0
1985     psubusb          m2, m1
1986     paddusb          m5, m1          ; q1-a
1987     paddusb          m2, m0          ; p1+a
1988
1989     ; store
1990 %ifidn %2, v
1991     movrow [dst_reg +mstride_reg*2], m2
1992     movrow [dst_reg +mstride_reg  ], m3
1993     movrow    [dst_reg], m4
1994     movrow [dst_reg + stride_reg  ], m5
1995 %if mmsize == 16 && %4 == 8
1996     movhps [dst8_reg+mstride_reg*2], m2
1997     movhps [dst8_reg+mstride_reg  ], m3
1998     movhps   [dst8_reg], m4
1999     movhps [dst8_reg+ stride_reg  ], m5
2000 %endif
2001 %else ; h
2002     add         dst_reg, 2
2003     add        dst2_reg, 2
2004
2005     ; 4x8/16 transpose
2006     TRANSPOSE4x4B     2, 3, 4, 5, 6
2007
2008 %if mmsize == 8 ; mmx/mmxext (h)
2009     WRITE_4x2D        2, 3, 4, 5, dst_reg, dst2_reg, mstride_reg, stride_reg
2010 %else ; sse2 (h)
2011     lea        dst8_reg, [dst8_reg+mstride_reg+2]
2012     WRITE_4x4D        2, 3, 4, 5, dst_reg, dst2_reg, dst8_reg, mstride_reg, stride_reg, %4
2013 %endif
2014 %endif
2015
2016 %if mmsize == 8
2017 %if %4 == 8 ; chroma
2018 %ifidn %2, h
2019     sub         dst_reg, 2
2020 %endif
2021     cmp         dst_reg, dst8_reg
2022     mov         dst_reg, dst8_reg
2023     jnz .next8px
2024 %else
2025 %ifidn %2, h
2026     lea         dst_reg, [dst_reg + stride_reg*8-2]
2027 %else ; v
2028     add         dst_reg, 8
2029 %endif
2030     dec         cnt_reg
2031     jg .next8px
2032 %endif
2033 %endif
2034
2035 %ifndef m8 ; sse2 on x86-32 or mmx/mmxext
2036     mov             rsp, stack_reg   ; restore stack pointer
2037 %endif
2038     RET
2039 %endmacro
2040
2041 INIT_MMX
2042 %define SPLATB_REG SPLATB_REG_MMX
2043 INNER_LOOPFILTER mmx,    v, 6, 16, 0
2044 INNER_LOOPFILTER mmx,    h, 6, 16, 0
2045 INNER_LOOPFILTER mmx,    v, 6,  8, 0
2046 INNER_LOOPFILTER mmx,    h, 6,  8, 0
2047
2048 %define SPLATB_REG SPLATB_REG_MMXEXT
2049 INNER_LOOPFILTER mmxext, v, 6, 16, 0
2050 INNER_LOOPFILTER mmxext, h, 6, 16, 0
2051 INNER_LOOPFILTER mmxext, v, 6,  8, 0
2052 INNER_LOOPFILTER mmxext, h, 6,  8, 0
2053
2054 INIT_XMM
2055 %define SPLATB_REG SPLATB_REG_SSE2
2056 INNER_LOOPFILTER sse2,   v, 5, 16, 13
2057 %ifdef m8
2058 INNER_LOOPFILTER sse2,   h, 5, 16, 13
2059 %else
2060 INNER_LOOPFILTER sse2,   h, 6, 16, 13
2061 %endif
2062 INNER_LOOPFILTER sse2,   v, 6,  8, 13
2063 INNER_LOOPFILTER sse2,   h, 6,  8, 13
2064
2065 %define SPLATB_REG SPLATB_REG_SSSE3
2066 INNER_LOOPFILTER ssse3,  v, 5, 16, 13
2067 %ifdef m8
2068 INNER_LOOPFILTER ssse3,  h, 5, 16, 13
2069 %else
2070 INNER_LOOPFILTER ssse3,  h, 6, 16, 13
2071 %endif
2072 INNER_LOOPFILTER ssse3,  v, 6,  8, 13
2073 INNER_LOOPFILTER ssse3,  h, 6,  8, 13
2074
2075 ;-----------------------------------------------------------------------------
2076 ; void vp8_h/v_loop_filter<size>_mbedge_<opt>(uint8_t *dst, [uint8_t *v,] int stride,
2077 ;                                            int flimE, int flimI, int hev_thr);
2078 ;-----------------------------------------------------------------------------
2079
2080 ; write 4 or 8 words in the mmx/xmm registers as 8 lines
2081 ; 1 and 2 are the registers to write, this can be the same (for SSE2)
2082 ; for pre-SSE4:
2083 ; 3 is a general-purpose register that we will clobber
2084 ; for SSE4:
2085 ; 3 is a pointer to the destination's 5th line
2086 ; 4 is a pointer to the destination's 4th line
2087 ; 5/6 is -stride and +stride
2088 ; 7 is optimization string
2089 %macro WRITE_8W 7
2090 %ifidn %7, sse4
2091     pextrw    [%4+%5*4], %1, 0
2092     pextrw    [%3+%5*4], %1, 1
2093     pextrw    [%4+%5*2], %1, 2
2094     pextrw    [%4+%5  ], %1, 3
2095     pextrw    [%4     ], %1, 4
2096     pextrw    [%3     ], %1, 5
2097     pextrw    [%3+%6  ], %1, 6
2098     pextrw    [%3+%6*2], %1, 7
2099 %else
2100     movd             %3, %1
2101 %if mmsize == 8
2102     punpckhdq        %1, %1
2103 %else
2104     psrldq           %1, 4
2105 %endif
2106     mov       [%4+%5*4], %3w
2107     shr              %3, 16
2108     add              %4, %6
2109     mov       [%4+%5*4], %3w
2110
2111     movd             %3, %1
2112 %if mmsize == 16
2113     psrldq           %1, 4
2114 %endif
2115     add              %4, %5
2116     mov       [%4+%5*2], %3w
2117     shr              %3, 16
2118     mov       [%4+%5  ], %3w
2119
2120     movd             %3, %2
2121 %if mmsize == 8
2122     punpckhdq        %2, %2
2123 %else
2124     psrldq           %2, 4
2125 %endif
2126     mov       [%4     ], %3w
2127     shr              %3, 16
2128     mov       [%4+%6  ], %3w
2129
2130     movd             %3, %2
2131     add              %4, %6
2132     mov       [%4+%6  ], %3w
2133     shr              %3, 16
2134     mov       [%4+%6*2], %3w
2135 %if mmsize == 8
2136     add              %4, %5
2137 %endif
2138 %endif
2139 %endmacro
2140
2141 %macro MBEDGE_LOOPFILTER 5
2142 %if %4 == 8 ; chroma
2143 cglobal vp8_%2_loop_filter8uv_mbedge_%1, 6, %3, %5
2144 %define dst8_reg    r1
2145 %define mstride_reg r2
2146 %define E_reg       r3
2147 %define I_reg       r4
2148 %define hev_thr_reg r5
2149 %else ; luma
2150 cglobal vp8_%2_loop_filter16y_mbedge_%1, 5, %3, %5
2151 %define mstride_reg r1
2152 %define E_reg       r2
2153 %define I_reg       r3
2154 %define hev_thr_reg r4
2155 %ifdef m8 ; x86-64, sse2
2156 %define dst8_reg    r4
2157 %elif mmsize == 16 ; x86-32, sse2
2158 %define dst8_reg    r5
2159 %else ; x86-32, mmx/mmxext
2160 %define cnt_reg     r5
2161 %endif
2162 %endif
2163 %define dst_reg     r0
2164 %define stride_reg  E_reg
2165 %define dst2_reg    I_reg
2166 %ifndef m8
2167 %define stack_reg   hev_thr_reg
2168 %endif
2169
2170 %ifnidn %1, sse2 && mmsize == 16
2171     pxor             m7, m7
2172 %endif
2173
2174 %ifndef m8 ; mmx/mmxext or sse2 on x86-32
2175     ; splat function arguments
2176     SPLATB_REG       m0, E_reg, m7   ; E
2177     SPLATB_REG       m1, I_reg, m7   ; I
2178     SPLATB_REG       m2, hev_thr_reg, m7 ; hev_thresh
2179
2180     ; align stack
2181     mov       stack_reg, rsp         ; backup stack pointer
2182     and             rsp, ~(mmsize-1) ; align stack
2183     sub             rsp, mmsize * 8  ; stack layout: [0]=E, [1]=I, [2]=hev_thr
2184                                      ;               [3]=hev() result
2185                                      ;               [4]=filter tmp result
2186                                      ;               [5]/[6] = p2/q2 backup
2187                                      ;               [7]=lim_res sign result
2188
2189 %define flim_E   [rsp]
2190 %define flim_I   [rsp+mmsize]
2191 %define hev_thr  [rsp+mmsize*2]
2192 %define mask_res [rsp+mmsize*3]
2193 %define lim_res  [rsp+mmsize*4]
2194 %define p0backup [rsp+mmsize*3]
2195 %define q0backup [rsp+mmsize*4]
2196 %define p2backup [rsp+mmsize*5]
2197 %define q2backup [rsp+mmsize*6]
2198 %define lim_sign [rsp+mmsize*7]
2199
2200     mova         flim_E, m0
2201     mova         flim_I, m1
2202     mova        hev_thr, m2
2203
2204 %else ; sse2 on x86-64
2205
2206 %define flim_E   m9
2207 %define flim_I   m10
2208 %define hev_thr  m11
2209 %define mask_res m12
2210 %define lim_res  m8
2211 %define p0backup m12
2212 %define q0backup m8
2213 %define p2backup m13
2214 %define q2backup m14
2215 %define lim_sign m15
2216
2217     ; splat function arguments
2218     SPLATB_REG   flim_E, E_reg, m7   ; E
2219     SPLATB_REG   flim_I, I_reg, m7   ; I
2220     SPLATB_REG  hev_thr, hev_thr_reg, m7 ; hev_thresh
2221 %endif
2222
2223 %if mmsize == 8 && %4 == 16 ; mmx/mmxext
2224     mov         cnt_reg, 2
2225 %endif
2226     mov      stride_reg, mstride_reg
2227     neg     mstride_reg
2228 %ifidn %2, h
2229     lea         dst_reg, [dst_reg + stride_reg*4-4]
2230 %if %4 == 8
2231     lea        dst8_reg, [dst8_reg+ stride_reg*4-4]
2232 %endif
2233 %endif
2234
2235 %if mmsize == 8
2236 .next8px
2237 %endif
2238     ; read
2239     lea        dst2_reg, [dst_reg + stride_reg]
2240 %ifidn %2, v
2241 %if %4 == 8 && mmsize == 16
2242 %define movrow movh
2243 %else
2244 %define movrow mova
2245 %endif
2246     movrow           m0, [dst_reg +mstride_reg*4] ; p3
2247     movrow           m1, [dst2_reg+mstride_reg*4] ; p2
2248     movrow           m2, [dst_reg +mstride_reg*2] ; p1
2249     movrow           m5, [dst2_reg]               ; q1
2250     movrow           m6, [dst2_reg+ stride_reg]   ; q2
2251     movrow           m7, [dst2_reg+ stride_reg*2] ; q3
2252 %if mmsize == 16 && %4 == 8
2253     movhps           m0, [dst8_reg+mstride_reg*4]
2254     movhps           m2, [dst8_reg+mstride_reg*2]
2255     add        dst8_reg, stride_reg
2256     movhps           m1, [dst8_reg+mstride_reg*4]
2257     movhps           m5, [dst8_reg]
2258     movhps           m6, [dst8_reg+ stride_reg]
2259     movhps           m7, [dst8_reg+ stride_reg*2]
2260     add        dst8_reg, mstride_reg
2261 %endif
2262 %elif mmsize == 8 ; mmx/mmxext (h)
2263     ; read 8 rows of 8px each
2264     movu             m0, [dst_reg +mstride_reg*4]
2265     movu             m1, [dst2_reg+mstride_reg*4]
2266     movu             m2, [dst_reg +mstride_reg*2]
2267     movu             m3, [dst_reg +mstride_reg]
2268     movu             m4, [dst_reg]
2269     movu             m5, [dst2_reg]
2270     movu             m6, [dst2_reg+ stride_reg]
2271
2272     ; 8x8 transpose
2273     TRANSPOSE4x4B     0, 1, 2, 3, 7
2274     mova       q0backup, m1
2275     movu             m7, [dst2_reg+ stride_reg*2]
2276     TRANSPOSE4x4B     4, 5, 6, 7, 1
2277     SBUTTERFLY       dq, 0, 4, 1     ; p3/p2
2278     SBUTTERFLY       dq, 2, 6, 1     ; q0/q1
2279     SBUTTERFLY       dq, 3, 7, 1     ; q2/q3
2280     mova             m1, q0backup
2281     mova       q0backup, m2          ; store q0
2282     SBUTTERFLY       dq, 1, 5, 2     ; p1/p0
2283     mova       p0backup, m5          ; store p0
2284     SWAP              1, 4
2285     SWAP              2, 4
2286     SWAP              6, 3
2287     SWAP              5, 3
2288 %else ; sse2 (h)
2289 %if %4 == 16
2290     lea        dst8_reg, [dst_reg + stride_reg*8]
2291 %endif
2292
2293     ; read 16 rows of 8px each, interleave
2294     movh             m0, [dst_reg +mstride_reg*4]
2295     movh             m1, [dst8_reg+mstride_reg*4]
2296     movh             m2, [dst_reg +mstride_reg*2]
2297     movh             m5, [dst8_reg+mstride_reg*2]
2298     movh             m3, [dst_reg +mstride_reg]
2299     movh             m6, [dst8_reg+mstride_reg]
2300     movh             m4, [dst_reg]
2301     movh             m7, [dst8_reg]
2302     punpcklbw        m0, m1          ; A/I
2303     punpcklbw        m2, m5          ; C/K
2304     punpcklbw        m3, m6          ; D/L
2305     punpcklbw        m4, m7          ; E/M
2306
2307     add        dst8_reg, stride_reg
2308     movh             m1, [dst2_reg+mstride_reg*4]
2309     movh             m6, [dst8_reg+mstride_reg*4]
2310     movh             m5, [dst2_reg]
2311     movh             m7, [dst8_reg]
2312     punpcklbw        m1, m6          ; B/J
2313     punpcklbw        m5, m7          ; F/N
2314     movh             m6, [dst2_reg+ stride_reg]
2315     movh             m7, [dst8_reg+ stride_reg]
2316     punpcklbw        m6, m7          ; G/O
2317
2318     ; 8x16 transpose
2319     TRANSPOSE4x4B     0, 1, 2, 3, 7
2320 %ifdef m8
2321     SWAP              1, 8
2322 %else
2323     mova       q0backup, m1
2324 %endif
2325     movh             m7, [dst2_reg+ stride_reg*2]
2326     movh             m1, [dst8_reg+ stride_reg*2]
2327     punpcklbw        m7, m1          ; H/P
2328     TRANSPOSE4x4B     4, 5, 6, 7, 1
2329     SBUTTERFLY       dq, 0, 4, 1     ; p3/p2
2330     SBUTTERFLY       dq, 2, 6, 1     ; q0/q1
2331     SBUTTERFLY       dq, 3, 7, 1     ; q2/q3
2332 %ifdef m8
2333     SWAP              1, 8
2334     SWAP              2, 8
2335 %else
2336     mova             m1, q0backup
2337     mova       q0backup, m2          ; store q0
2338 %endif
2339     SBUTTERFLY       dq, 1, 5, 2     ; p1/p0
2340 %ifdef m12
2341     SWAP              5, 12
2342 %else
2343     mova       p0backup, m5          ; store p0
2344 %endif
2345     SWAP              1, 4
2346     SWAP              2, 4
2347     SWAP              6, 3
2348     SWAP              5, 3
2349 %endif
2350
2351     ; normal_limit for p3-p2, p2-p1, q3-q2 and q2-q1
2352     mova             m4, m1
2353     SWAP              4, 1
2354     psubusb          m4, m0          ; p2-p3
2355     psubusb          m0, m1          ; p3-p2
2356     por              m0, m4          ; abs(p3-p2)
2357
2358     mova             m4, m2
2359     SWAP              4, 2
2360     psubusb          m4, m1          ; p1-p2
2361     mova       p2backup, m1
2362     psubusb          m1, m2          ; p2-p1
2363     por              m1, m4          ; abs(p2-p1)
2364
2365     mova             m4, m6
2366     SWAP              4, 6
2367     psubusb          m4, m7          ; q2-q3
2368     psubusb          m7, m6          ; q3-q2
2369     por              m7, m4          ; abs(q3-q2)
2370
2371     mova             m4, m5
2372     SWAP              4, 5
2373     psubusb          m4, m6          ; q1-q2
2374     mova       q2backup, m6
2375     psubusb          m6, m5          ; q2-q1
2376     por              m6, m4          ; abs(q2-q1)
2377
2378 %ifidn %1, mmx
2379     mova             m4, flim_I
2380     pxor             m3, m3
2381     psubusb          m0, m4
2382     psubusb          m1, m4
2383     psubusb          m7, m4
2384     psubusb          m6, m4
2385     pcmpeqb          m0, m3          ; abs(p3-p2) <= I
2386     pcmpeqb          m1, m3          ; abs(p2-p1) <= I
2387     pcmpeqb          m7, m3          ; abs(q3-q2) <= I
2388     pcmpeqb          m6, m3          ; abs(q2-q1) <= I
2389     pand             m0, m1
2390     pand             m7, m6
2391     pand             m0, m7
2392 %else ; mmxext/sse2
2393     pmaxub           m0, m1
2394     pmaxub           m6, m7
2395     pmaxub           m0, m6
2396 %endif
2397
2398     ; normal_limit and high_edge_variance for p1-p0, q1-q0
2399     SWAP              7, 3           ; now m7 is zero
2400 %ifidn %2, v
2401     movrow           m3, [dst_reg +mstride_reg] ; p0
2402 %if mmsize == 16 && %4 == 8
2403     movhps           m3, [dst8_reg+mstride_reg]
2404 %endif
2405 %elifdef m12
2406     SWAP              3, 12
2407 %else
2408     mova             m3, p0backup
2409 %endif
2410
2411     mova             m1, m2
2412     SWAP              1, 2
2413     mova             m6, m3
2414     SWAP              3, 6
2415     psubusb          m1, m3          ; p1-p0
2416     psubusb          m6, m2          ; p0-p1
2417     por              m1, m6          ; abs(p1-p0)
2418 %ifidn %1, mmx
2419     mova             m6, m1
2420     psubusb          m1, m4
2421     psubusb          m6, hev_thr
2422     pcmpeqb          m1, m7          ; abs(p1-p0) <= I
2423     pcmpeqb          m6, m7          ; abs(p1-p0) <= hev_thresh
2424     pand             m0, m1
2425     mova       mask_res, m6
2426 %else ; mmxext/sse2
2427     pmaxub           m0, m1          ; max_I
2428     SWAP              1, 4           ; max_hev_thresh
2429 %endif
2430
2431     SWAP              6, 4           ; now m6 is I
2432 %ifidn %2, v
2433     movrow           m4, [dst_reg]   ; q0
2434 %if mmsize == 16 && %4 == 8
2435     movhps           m4, [dst8_reg]
2436 %endif
2437 %elifdef m8
2438     SWAP              4, 8
2439 %else
2440     mova             m4, q0backup
2441 %endif
2442     mova             m1, m4
2443     SWAP              1, 4
2444     mova             m7, m5
2445     SWAP              7, 5
2446     psubusb          m1, m5          ; q0-q1
2447     psubusb          m7, m4          ; q1-q0
2448     por              m1, m7          ; abs(q1-q0)
2449 %ifidn %1, mmx
2450     mova             m7, m1
2451     psubusb          m1, m6
2452     psubusb          m7, hev_thr
2453     pxor             m6, m6
2454     pcmpeqb          m1, m6          ; abs(q1-q0) <= I
2455     pcmpeqb          m7, m6          ; abs(q1-q0) <= hev_thresh
2456     mova             m6, mask_res
2457     pand             m0, m1          ; abs([pq][321]-[pq][210]) <= I
2458     pand             m6, m7
2459 %else ; mmxext/sse2
2460     pxor             m7, m7
2461     pmaxub           m0, m1
2462     pmaxub           m6, m1
2463     psubusb          m0, flim_I
2464     psubusb          m6, hev_thr
2465     pcmpeqb          m0, m7          ; max(abs(..)) <= I
2466     pcmpeqb          m6, m7          ; !(max(abs..) > thresh)
2467 %endif
2468 %ifdef m12
2469     SWAP              6, 12
2470 %else
2471     mova       mask_res, m6          ; !(abs(p1-p0) > hev_t || abs(q1-q0) > hev_t)
2472 %endif
2473
2474     ; simple_limit
2475     mova             m1, m3
2476     SWAP              1, 3
2477     mova             m6, m4          ; keep copies of p0/q0 around for later use
2478     SWAP              6, 4
2479     psubusb          m1, m4          ; p0-q0
2480     psubusb          m6, m3          ; q0-p0
2481     por              m1, m6          ; abs(q0-p0)
2482     paddusb          m1, m1          ; m1=2*abs(q0-p0)
2483
2484     mova             m7, m2
2485     SWAP              7, 2
2486     mova             m6, m5
2487     SWAP              6, 5
2488     psubusb          m7, m5          ; p1-q1
2489     psubusb          m6, m2          ; q1-p1
2490     por              m7, m6          ; abs(q1-p1)
2491     pxor             m6, m6
2492     pand             m7, [pb_FE]
2493     psrlq            m7, 1           ; abs(q1-p1)/2
2494     paddusb          m7, m1          ; abs(q0-p0)*2+abs(q1-p1)/2
2495     psubusb          m7, flim_E
2496     pcmpeqb          m7, m6          ; abs(q0-p0)*2+abs(q1-p1)/2 <= E
2497     pand             m0, m7          ; normal_limit result
2498
2499     ; filter_common; at this point, m2-m5=p1-q1 and m0 is filter_mask
2500 %ifdef m8 ; x86-64 && sse2
2501     mova             m8, [pb_80]
2502 %define pb_80_var m8
2503 %else ; x86-32 or mmx/mmxext
2504 %define pb_80_var [pb_80]
2505 %endif
2506     mova             m1, m4
2507     mova             m7, m3
2508     pxor             m1, pb_80_var
2509     pxor             m7, pb_80_var
2510     psubsb           m1, m7          ; (signed) q0-p0
2511     mova             m6, m2
2512     mova             m7, m5
2513     pxor             m6, pb_80_var
2514     pxor             m7, pb_80_var
2515     psubsb           m6, m7          ; (signed) p1-q1
2516     mova             m7, mask_res
2517     paddsb           m6, m1
2518     paddsb           m6, m1
2519     paddsb           m6, m1
2520     pand             m6, m0
2521 %ifdef m8
2522     mova        lim_res, m6          ; 3*(qp-p0)+(p1-q1) masked for filter_mbedge
2523     pand        lim_res, m7
2524 %else
2525     mova             m0, m6
2526     pand             m0, m7
2527     mova        lim_res, m0
2528 %endif
2529     pandn            m7, m6          ; 3*(q0-p0)+(p1-q1) masked for filter_common
2530
2531     mova             m1, [pb_F8]
2532     mova             m6, m7
2533     paddsb           m7, [pb_3]
2534     paddsb           m6, [pb_4]
2535     pand             m7, m1
2536     pand             m6, m1
2537
2538     pxor             m1, m1
2539     pxor             m0, m0
2540     pcmpgtb          m1, m7
2541     psubb            m0, m7
2542     psrlq            m7, 3           ; +f2
2543     psrlq            m0, 3           ; -f2
2544     pand             m0, m1
2545     pandn            m1, m7
2546     psubusb          m3, m0
2547     paddusb          m3, m1          ; p0+f2
2548
2549     pxor             m1, m1
2550     pxor             m0, m0
2551     pcmpgtb          m0, m6
2552     psubb            m1, m6
2553     psrlq            m6, 3           ; +f1
2554     psrlq            m1, 3           ; -f1
2555     pand             m1, m0
2556     pandn            m0, m6
2557     psubusb          m4, m0
2558     paddusb          m4, m1          ; q0-f1
2559
2560     ; filter_mbedge (m2-m5 = p1-q1; lim_res carries w)
2561     mova             m7, [pw_63]
2562 %ifdef m8
2563     SWAP              1, 8
2564 %else
2565     mova             m1, lim_res
2566 %endif
2567     pxor             m0, m0
2568     mova             m6, m1
2569     pcmpgtb          m0, m1         ; which are negative
2570     punpcklbw        m6, m0         ; signed byte->word
2571     punpckhbw        m1, m0
2572     mova       lim_sign, m0
2573     mova       mask_res, m6         ; backup for later in filter
2574     mova        lim_res, m1
2575     pmullw          m6, [pw_27]
2576     pmullw          m1, [pw_27]
2577     paddw           m6, m7
2578     paddw           m1, m7
2579     psraw           m6, 7
2580     psraw           m1, 7
2581     packsswb        m6, m1          ; a0
2582     pxor            m1, m1
2583     psubb           m1, m6
2584     pand            m1, m0          ; -a0
2585     pandn           m0, m6          ; +a0
2586     psubusb         m3, m1
2587     paddusb         m4, m1
2588     paddusb         m3, m0          ; p0+a0
2589     psubusb         m4, m0          ; q0-a0
2590
2591     mova            m6, mask_res
2592     mova            m1, lim_res
2593     mova            m0, lim_sign
2594     pmullw          m6, [pw_18]
2595     pmullw          m1, [pw_18]
2596     paddw           m6, m7
2597     paddw           m1, m7
2598     psraw           m6, 7
2599     psraw           m1, 7
2600     packsswb        m6, m1          ; a1
2601     pxor            m1, m1
2602     psubb           m1, m6
2603     pand            m1, m0          ; -a1
2604     pandn           m0, m6          ; +a1
2605     psubusb         m2, m1
2606     paddusb         m5, m1
2607     paddusb         m2, m0          ; p1+a1
2608     psubusb         m5, m0          ; q1-a1
2609
2610 %ifdef m8
2611     SWAP             6, 12
2612     SWAP             1, 8
2613 %else
2614     mova            m6, mask_res
2615     mova            m1, lim_res
2616 %endif
2617     pmullw          m6, [pw_9]
2618     pmullw          m1, [pw_9]
2619     paddw           m6, m7
2620     paddw           m1, m7
2621 %ifdef m15
2622     SWAP             7, 15
2623 %else
2624     mova            m7, lim_sign
2625 %endif
2626     psraw           m6, 7
2627     psraw           m1, 7
2628     packsswb        m6, m1          ; a1
2629     pxor            m0, m0
2630     psubb           m0, m6
2631     pand            m0, m7          ; -a1
2632     pandn           m7, m6          ; +a1
2633 %ifdef m8
2634     SWAP             1, 13
2635     SWAP             6, 14
2636 %else
2637     mova            m1, p2backup
2638     mova            m6, q2backup
2639 %endif
2640     psubusb         m1, m0
2641     paddusb         m6, m0
2642     paddusb         m1, m7          ; p1+a1
2643     psubusb         m6, m7          ; q1-a1
2644
2645     ; store
2646 %ifidn %2, v
2647     movrow [dst2_reg+mstride_reg*4], m1
2648     movrow [dst_reg +mstride_reg*2], m2
2649     movrow [dst_reg +mstride_reg  ], m3
2650     movrow    [dst_reg], m4
2651     movrow   [dst2_reg], m5
2652     movrow [dst2_reg+ stride_reg  ], m6
2653 %if mmsize == 16 && %4 == 8
2654     add        dst8_reg, mstride_reg
2655     movhps [dst8_reg+mstride_reg*2], m1
2656     movhps [dst8_reg+mstride_reg  ], m2
2657     movhps   [dst8_reg], m3
2658     add        dst8_reg, stride_reg
2659     movhps   [dst8_reg], m4
2660     movhps [dst8_reg+ stride_reg  ], m5
2661     movhps [dst8_reg+ stride_reg*2], m6
2662 %endif
2663 %else ; h
2664     inc         dst_reg
2665     inc        dst2_reg
2666
2667     ; 4x8/16 transpose
2668     TRANSPOSE4x4B     1, 2, 3, 4, 0
2669     SBUTTERFLY       bw, 5, 6, 0
2670
2671 %if mmsize == 8 ; mmx/mmxext (h)
2672     WRITE_4x2D        1, 2, 3, 4, dst_reg, dst2_reg, mstride_reg, stride_reg
2673     add         dst_reg, 4
2674     WRITE_8W         m5, m6, dst2_reg, dst_reg, mstride_reg, stride_reg, %4
2675 %else ; sse2 (h)
2676     lea        dst8_reg, [dst8_reg+mstride_reg+1]
2677     WRITE_4x4D        1, 2, 3, 4, dst_reg, dst2_reg, dst8_reg, mstride_reg, stride_reg, %4
2678     lea         dst_reg, [dst2_reg+mstride_reg+4]
2679     lea        dst8_reg, [dst8_reg+mstride_reg+4]
2680     WRITE_8W         m5, m5, dst2_reg, dst_reg,  mstride_reg, stride_reg, %2
2681 %ifidn %2, sse4
2682     lea         dst_reg, [dst8_reg+ stride_reg]
2683 %endif
2684     WRITE_8W         m6, m6, dst2_reg, dst8_reg, mstride_reg, stride_reg, %2
2685 %endif
2686 %endif
2687
2688 %if mmsize == 8
2689 %if %4 == 8 ; chroma
2690 %ifidn %2, h
2691     sub         dst_reg, 5
2692 %endif
2693     cmp         dst_reg, dst8_reg
2694     mov         dst_reg, dst8_reg
2695     jnz .next8px
2696 %else
2697 %ifidn %2, h
2698     lea         dst_reg, [dst_reg + stride_reg*8-5]
2699 %else ; v
2700     add         dst_reg, 8
2701 %endif
2702     dec         cnt_reg
2703     jg .next8px
2704 %endif
2705 %endif
2706
2707 %ifndef m8 ; sse2 on x86-32 or mmx/mmxext
2708     mov             rsp, stack_reg   ; restore stack pointer
2709 %endif
2710     RET
2711 %endmacro
2712
2713 INIT_MMX
2714 %define SPLATB_REG SPLATB_REG_MMX
2715 MBEDGE_LOOPFILTER mmx,    v, 6, 16, 0
2716 MBEDGE_LOOPFILTER mmx,    h, 6, 16, 0
2717 MBEDGE_LOOPFILTER mmx,    v, 6,  8, 0
2718 MBEDGE_LOOPFILTER mmx,    h, 6,  8, 0
2719
2720 %define SPLATB_REG SPLATB_REG_MMXEXT
2721 MBEDGE_LOOPFILTER mmxext, v, 6, 16, 0
2722 MBEDGE_LOOPFILTER mmxext, h, 6, 16, 0
2723 MBEDGE_LOOPFILTER mmxext, v, 6,  8, 0
2724 MBEDGE_LOOPFILTER mmxext, h, 6,  8, 0
2725
2726 INIT_XMM
2727 %define SPLATB_REG SPLATB_REG_SSE2
2728 MBEDGE_LOOPFILTER sse2,   v, 5, 16, 16
2729 %ifdef m8
2730 MBEDGE_LOOPFILTER sse2,   h, 5, 16, 16
2731 %else
2732 MBEDGE_LOOPFILTER sse2,   h, 6, 16, 16
2733 %endif
2734 MBEDGE_LOOPFILTER sse2,   v, 6,  8, 16
2735 MBEDGE_LOOPFILTER sse2,   h, 6,  8, 16
2736
2737 %define SPLATB_REG SPLATB_REG_SSSE3
2738 MBEDGE_LOOPFILTER ssse3,  v, 5, 16, 16
2739 %ifdef m8
2740 MBEDGE_LOOPFILTER ssse3,  h, 5, 16, 16
2741 %else
2742 MBEDGE_LOOPFILTER ssse3,  h, 6, 16, 16
2743 %endif
2744 MBEDGE_LOOPFILTER ssse3,  v, 6,  8, 16
2745 MBEDGE_LOOPFILTER ssse3,  h, 6,  8, 16
2746
2747 %ifdef m8
2748 MBEDGE_LOOPFILTER sse4,   h, 5, 16, 16
2749 %else
2750 MBEDGE_LOOPFILTER sse4,   h, 6, 16, 16
2751 %endif
2752 MBEDGE_LOOPFILTER sse4,   h, 6,  8, 16