Enable no-loop memory/register saving for ssse3/sse4 also.
[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
1398 %if mmsize == 16
1399     pxor           m0, m0
1400 %endif
1401 %endif
1402     SPLATB_REG     m7, r2, m0       ; splat "flim" into register
1403
1404     ; set up indexes to address 4 rows
1405     mov            r2, r1
1406     neg            r1
1407 %ifidn %2, h
1408     lea            r0, [r0+4*r2-2]
1409     sub           rsp, mmsize*2     ; (aligned) storage space for saving p1/q1
1410 %endif
1411
1412 %if mmsize == 8 ; mmx / mmxext
1413 .next8px
1414 %endif
1415 %ifidn %2, v
1416     ; read 4 half/full rows of pixels
1417     mova           m0, [r0+r1*2]    ; p1
1418     mova           m1, [r0+r1]      ; p0
1419     mova           m2, [r0]         ; q0
1420     mova           m3, [r0+r2]      ; q1
1421 %else ; h
1422     lea            r4, [r0+r2]
1423
1424 %if mmsize == 8 ; mmx/mmxext
1425     READ_8x4_INTERLEAVED  0, 1, 2, 3, 4, 5, 6, r0, r4, r1, r2
1426 %else ; sse2
1427     READ_16x4_INTERLEAVED 0, 1, 2, 3, 4, 5, 6, r0, r4, r1, r2, r3
1428 %endif
1429     TRANSPOSE4x4W         0, 1, 2, 3, 4
1430
1431     mova        [rsp], m0           ; store p1
1432     mova [rsp+mmsize], m3           ; store q1
1433 %endif
1434
1435     ; simple_limit
1436     mova           m5, m2           ; m5=backup of q0
1437     mova           m6, m1           ; m6=backup of p0
1438     psubusb        m1, m2           ; p0-q0
1439     psubusb        m2, m6           ; q0-p0
1440     por            m1, m2           ; FFABS(p0-q0)
1441     paddusb        m1, m1           ; m1=FFABS(p0-q0)*2
1442
1443     mova           m4, m3
1444     mova           m2, m0
1445     psubusb        m3, m0           ; q1-p1
1446     psubusb        m0, m4           ; p1-q1
1447     por            m3, m0           ; FFABS(p1-q1)
1448     mova           m0, [pb_80]
1449     pxor           m2, m0
1450     pxor           m4, m0
1451     psubsb         m2, m4           ; m2=p1-q1 (signed) backup for below
1452     pand           m3, [pb_FE]
1453     psrlq          m3, 1            ; m3=FFABS(p1-q1)/2, this can be used signed
1454     paddusb        m3, m1
1455     psubusb        m3, m7
1456     pxor           m1, m1
1457     pcmpeqb        m3, m1           ; abs(p0-q0)*2+abs(p1-q1)/2<=flim mask(0xff/0x0)
1458
1459     ; filter_common (use m2/p1-q1, m4=q0, m6=p0, m5/q0-p0 and m3/mask)
1460     mova           m4, m5
1461     pxor           m5, m0
1462     pxor           m0, m6
1463     psubsb         m5, m0           ; q0-p0 (signed)
1464     paddsb         m2, m5
1465     paddsb         m2, m5
1466     paddsb         m2, m5           ; a=(p1-q1) + 3*(q0-p0)
1467     pand           m2, m3           ; apply filter mask (m3)
1468
1469     mova           m3, [pb_F8]
1470     mova           m1, m2
1471     paddsb         m2, [pb_4]       ; f1<<3=a+4
1472     paddsb         m1, [pb_3]       ; f2<<3=a+3
1473     pand           m2, m3
1474     pand           m1, m3           ; cache f2<<3
1475
1476     pxor           m0, m0
1477     pxor           m3, m3
1478     pcmpgtb        m0, m2           ; which values are <0?
1479     psubb          m3, m2           ; -f1<<3
1480     psrlq          m2, 3            ; +f1
1481     psrlq          m3, 3            ; -f1
1482     pand           m3, m0
1483     pandn          m0, m2
1484     psubusb        m4, m0
1485     paddusb        m4, m3           ; q0-f1
1486
1487     pxor           m0, m0
1488     pxor           m3, m3
1489     pcmpgtb        m0, m1           ; which values are <0?
1490     psubb          m3, m1           ; -f2<<3
1491     psrlq          m1, 3            ; +f2
1492     psrlq          m3, 3            ; -f2
1493     pand           m3, m0
1494     pandn          m0, m1
1495     paddusb        m6, m0
1496     psubusb        m6, m3           ; p0+f2
1497
1498     ; store
1499 %ifidn %2, v
1500     mova         [r0], m4
1501     mova      [r0+r1], m6
1502 %else ; h
1503     mova           m0, [rsp]        ; p1
1504     SWAP            2, 4            ; p0
1505     SWAP            1, 6            ; q0
1506     mova           m3, [rsp+mmsize] ; q1
1507
1508     TRANSPOSE4x4B  0, 1, 2, 3, 4
1509 %if mmsize == 16 ; sse2
1510     add            r3, r1           ; change from r4*8*stride to r0+8*stride
1511     WRITE_4x4D 0, 1, 2, 3, r0, r4, r3, r1, r2, 16
1512 %else ; mmx/mmxext
1513     WRITE_4x2D 0, 1, 2, 3, r0, r4, r1, r2
1514 %endif
1515 %endif
1516
1517 %if mmsize == 8 ; mmx/mmxext
1518     ; next 8 pixels
1519 %ifidn %2, v
1520     add            r0, 8            ; advance 8 cols = pixels
1521 %else ; h
1522     lea            r0, [r0+r2*8]    ; advance 8 rows = lines
1523 %endif
1524     dec            r3
1525     jg .next8px
1526 %ifidn %2, v
1527     REP_RET
1528 %else ; h
1529     mov           rsp, r5           ; restore stack pointer
1530     RET
1531 %endif
1532 %else ; sse2
1533 %ifidn %2, h
1534     mov           rsp, r5           ; restore stack pointer
1535 %endif
1536     RET
1537 %endif
1538 %endmacro
1539
1540 INIT_MMX
1541 %define SPLATB_REG SPLATB_REG_MMX
1542 SIMPLE_LOOPFILTER mmx,    v, 4
1543 SIMPLE_LOOPFILTER mmx,    h, 6
1544 %define SPLATB_REG SPLATB_REG_MMXEXT
1545 SIMPLE_LOOPFILTER mmxext, v, 4
1546 SIMPLE_LOOPFILTER mmxext, h, 6
1547 INIT_XMM
1548 %define SPLATB_REG SPLATB_REG_SSE2
1549 SIMPLE_LOOPFILTER sse2,   v, 3
1550 SIMPLE_LOOPFILTER sse2,   h, 6
1551 %define SPLATB_REG SPLATB_REG_SSSE3
1552 SIMPLE_LOOPFILTER ssse3,  v, 3
1553 SIMPLE_LOOPFILTER ssse3,  h, 6
1554
1555 ;-----------------------------------------------------------------------------
1556 ; void vp8_h/v_loop_filter<size>_inner_<opt>(uint8_t *dst, [uint8_t *v,] int stride,
1557 ;                                            int flimE, int flimI, int hev_thr);
1558 ;-----------------------------------------------------------------------------
1559
1560 %macro INNER_LOOPFILTER 5
1561 %if %4 == 8 ; chroma
1562 cglobal vp8_%2_loop_filter8uv_inner_%1, 6, %3, %5
1563 %define dst8_reg    r1
1564 %define mstride_reg r2
1565 %define E_reg       r3
1566 %define I_reg       r4
1567 %define hev_thr_reg r5
1568 %else ; luma
1569 cglobal vp8_%2_loop_filter16y_inner_%1, 5, %3, %5
1570 %define mstride_reg r1
1571 %define E_reg       r2
1572 %define I_reg       r3
1573 %define hev_thr_reg r4
1574 %ifdef m8 ; x86-64, sse2
1575 %define dst8_reg    r4
1576 %elif mmsize == 16 ; x86-32, sse2
1577 %define dst8_reg    r5
1578 %else ; x86-32, mmx/mmxext
1579 %define cnt_reg     r5
1580 %endif
1581 %endif
1582 %define dst_reg     r0
1583 %define stride_reg  E_reg
1584 %define dst2_reg    I_reg
1585 %ifndef m8
1586 %define stack_reg   hev_thr_reg
1587 %endif
1588
1589 %ifnidn %1, sse2
1590 %if mmsize == 16
1591     pxor             m7, m7
1592 %endif
1593 %endif
1594
1595 %ifndef m8 ; mmx/mmxext or sse2 on x86-32
1596     ; splat function arguments
1597     SPLATB_REG       m0, E_reg, m7   ; E
1598     SPLATB_REG       m1, I_reg, m7   ; I
1599     SPLATB_REG       m2, hev_thr_reg, m7 ; hev_thresh
1600
1601     ; align stack
1602     mov       stack_reg, rsp         ; backup stack pointer
1603     and             rsp, ~(mmsize-1) ; align stack
1604 %ifidn %2, v
1605     sub             rsp, mmsize * 4  ; stack layout: [0]=E, [1]=I, [2]=hev_thr
1606                                      ;               [3]=hev() result
1607 %else ; h
1608     sub             rsp, mmsize * 5  ; extra storage space for transposes
1609 %endif
1610
1611 %define flim_E   [rsp]
1612 %define flim_I   [rsp+mmsize]
1613 %define hev_thr  [rsp+mmsize*2]
1614 %define mask_res [rsp+mmsize*3]
1615 %define p0backup [rsp+mmsize*3]
1616 %define q0backup [rsp+mmsize*4]
1617
1618     mova         flim_E, m0
1619     mova         flim_I, m1
1620     mova        hev_thr, m2
1621
1622 %else ; sse2 on x86-64
1623
1624 %define flim_E   m9
1625 %define flim_I   m10
1626 %define hev_thr  m11
1627 %define mask_res m12
1628 %define p0backup m12
1629 %define q0backup m8
1630
1631     ; splat function arguments
1632     SPLATB_REG   flim_E, E_reg, m7   ; E
1633     SPLATB_REG   flim_I, I_reg, m7   ; I
1634     SPLATB_REG  hev_thr, hev_thr_reg, m7 ; hev_thresh
1635 %endif
1636
1637 %if mmsize == 8 && %4 == 16 ; mmx/mmxext
1638     mov         cnt_reg, 2
1639 %endif
1640     mov      stride_reg, mstride_reg
1641     neg     mstride_reg
1642 %ifidn %2, h
1643     lea         dst_reg, [dst_reg + stride_reg*4-4]
1644 %if %4 == 8
1645     lea        dst8_reg, [dst8_reg+ stride_reg*4-4]
1646 %endif
1647 %endif
1648
1649 %if mmsize == 8
1650 .next8px
1651 %endif
1652     ; read
1653     lea        dst2_reg, [dst_reg + stride_reg]
1654 %ifidn %2, v
1655 %if %4 == 8 && mmsize == 16
1656 %define movrow movh
1657 %else
1658 %define movrow mova
1659 %endif
1660     movrow           m0, [dst_reg +mstride_reg*4] ; p3
1661     movrow           m1, [dst2_reg+mstride_reg*4] ; p2
1662     movrow           m2, [dst_reg +mstride_reg*2] ; p1
1663     movrow           m5, [dst2_reg]               ; q1
1664     movrow           m6, [dst2_reg+ stride_reg]   ; q2
1665     movrow           m7, [dst2_reg+ stride_reg*2] ; q3
1666 %if mmsize == 16 && %4 == 8
1667     movhps           m0, [dst8_reg+mstride_reg*4]
1668     movhps           m2, [dst8_reg+mstride_reg*2]
1669     add        dst8_reg, stride_reg
1670     movhps           m1, [dst8_reg+mstride_reg*4]
1671     movhps           m5, [dst8_reg]
1672     movhps           m6, [dst8_reg+ stride_reg]
1673     movhps           m7, [dst8_reg+ stride_reg*2]
1674     add        dst8_reg, mstride_reg
1675 %endif
1676 %elif mmsize == 8 ; mmx/mmxext (h)
1677     ; read 8 rows of 8px each
1678     movu             m0, [dst_reg +mstride_reg*4]
1679     movu             m1, [dst2_reg+mstride_reg*4]
1680     movu             m2, [dst_reg +mstride_reg*2]
1681     movu             m3, [dst_reg +mstride_reg]
1682     movu             m4, [dst_reg]
1683     movu             m5, [dst2_reg]
1684     movu             m6, [dst2_reg+ stride_reg]
1685
1686     ; 8x8 transpose
1687     TRANSPOSE4x4B     0, 1, 2, 3, 7
1688     mova       q0backup, m1
1689     movu             m7, [dst2_reg+ stride_reg*2]
1690     TRANSPOSE4x4B     4, 5, 6, 7, 1
1691     SBUTTERFLY       dq, 0, 4, 1     ; p3/p2
1692     SBUTTERFLY       dq, 2, 6, 1     ; q0/q1
1693     SBUTTERFLY       dq, 3, 7, 1     ; q2/q3
1694     mova             m1, q0backup
1695     mova       q0backup, m2          ; store q0
1696     SBUTTERFLY       dq, 1, 5, 2     ; p1/p0
1697     mova       p0backup, m5          ; store p0
1698     SWAP              1, 4
1699     SWAP              2, 4
1700     SWAP              6, 3
1701     SWAP              5, 3
1702 %else ; sse2 (h)
1703 %if %4 == 16
1704     lea        dst8_reg, [dst_reg + stride_reg*8]
1705 %endif
1706
1707     ; read 16 rows of 8px each, interleave
1708     movh             m0, [dst_reg +mstride_reg*4]
1709     movh             m1, [dst8_reg+mstride_reg*4]
1710     movh             m2, [dst_reg +mstride_reg*2]
1711     movh             m5, [dst8_reg+mstride_reg*2]
1712     movh             m3, [dst_reg +mstride_reg]
1713     movh             m6, [dst8_reg+mstride_reg]
1714     movh             m4, [dst_reg]
1715     movh             m7, [dst8_reg]
1716     punpcklbw        m0, m1          ; A/I
1717     punpcklbw        m2, m5          ; C/K
1718     punpcklbw        m3, m6          ; D/L
1719     punpcklbw        m4, m7          ; E/M
1720
1721     add        dst8_reg, stride_reg
1722     movh             m1, [dst2_reg+mstride_reg*4]
1723     movh             m6, [dst8_reg+mstride_reg*4]
1724     movh             m5, [dst2_reg]
1725     movh             m7, [dst8_reg]
1726     punpcklbw        m1, m6          ; B/J
1727     punpcklbw        m5, m7          ; F/N
1728     movh             m6, [dst2_reg+ stride_reg]
1729     movh             m7, [dst8_reg+ stride_reg]
1730     punpcklbw        m6, m7          ; G/O
1731
1732     ; 8x16 transpose
1733     TRANSPOSE4x4B     0, 1, 2, 3, 7
1734 %ifdef m8
1735     SWAP              1, 8
1736 %else
1737     mova       q0backup, m1
1738 %endif
1739     movh             m7, [dst2_reg+ stride_reg*2]
1740     movh             m1, [dst8_reg+ stride_reg*2]
1741     punpcklbw        m7, m1          ; H/P
1742     TRANSPOSE4x4B     4, 5, 6, 7, 1
1743     SBUTTERFLY       dq, 0, 4, 1     ; p3/p2
1744     SBUTTERFLY       dq, 2, 6, 1     ; q0/q1
1745     SBUTTERFLY       dq, 3, 7, 1     ; q2/q3
1746 %ifdef m8
1747     SWAP              1, 8
1748     SWAP              2, 8
1749 %else
1750     mova             m1, q0backup
1751     mova       q0backup, m2          ; store q0
1752 %endif
1753     SBUTTERFLY       dq, 1, 5, 2     ; p1/p0
1754 %ifdef m12
1755     SWAP              5, 12
1756 %else
1757     mova       p0backup, m5          ; store p0
1758 %endif
1759     SWAP              1, 4
1760     SWAP              2, 4
1761     SWAP              6, 3
1762     SWAP              5, 3
1763 %endif
1764
1765     ; normal_limit for p3-p2, p2-p1, q3-q2 and q2-q1
1766     mova             m4, m1
1767     SWAP              4, 1
1768     psubusb          m4, m0          ; p2-p3
1769     psubusb          m0, m1          ; p3-p2
1770     por              m0, m4          ; abs(p3-p2)
1771
1772     mova             m4, m2
1773     SWAP              4, 2
1774     psubusb          m4, m1          ; p1-p2
1775     psubusb          m1, m2          ; p2-p1
1776     por              m1, m4          ; abs(p2-p1)
1777
1778     mova             m4, m6
1779     SWAP              4, 6
1780     psubusb          m4, m7          ; q2-q3
1781     psubusb          m7, m6          ; q3-q2
1782     por              m7, m4          ; abs(q3-q2)
1783
1784     mova             m4, m5
1785     SWAP              4, 5
1786     psubusb          m4, m6          ; q1-q2
1787     psubusb          m6, m5          ; q2-q1
1788     por              m6, m4          ; abs(q2-q1)
1789
1790 %ifidn %1, mmx
1791     mova             m4, flim_I
1792     pxor             m3, m3
1793     psubusb          m0, m4
1794     psubusb          m1, m4
1795     psubusb          m7, m4
1796     psubusb          m6, m4
1797     pcmpeqb          m0, m3          ; abs(p3-p2) <= I
1798     pcmpeqb          m1, m3          ; abs(p2-p1) <= I
1799     pcmpeqb          m7, m3          ; abs(q3-q2) <= I
1800     pcmpeqb          m6, m3          ; abs(q2-q1) <= I
1801     pand             m0, m1
1802     pand             m7, m6
1803     pand             m0, m7
1804 %else ; mmxext/sse2
1805     pmaxub           m0, m1
1806     pmaxub           m6, m7
1807     pmaxub           m0, m6
1808 %endif
1809
1810     ; normal_limit and high_edge_variance for p1-p0, q1-q0
1811     SWAP              7, 3           ; now m7 is zero
1812 %ifidn %2, v
1813     movrow           m3, [dst_reg +mstride_reg] ; p0
1814 %if mmsize == 16 && %4 == 8
1815     movhps           m3, [dst8_reg+mstride_reg]
1816 %endif
1817 %elifdef m12
1818     SWAP              3, 12
1819 %else
1820     mova             m3, p0backup
1821 %endif
1822
1823     mova             m1, m2
1824     SWAP              1, 2
1825     mova             m6, m3
1826     SWAP              3, 6
1827     psubusb          m1, m3          ; p1-p0
1828     psubusb          m6, m2          ; p0-p1
1829     por              m1, m6          ; abs(p1-p0)
1830 %ifidn %1, mmx
1831     mova             m6, m1
1832     psubusb          m1, m4
1833     psubusb          m6, hev_thr
1834     pcmpeqb          m1, m7          ; abs(p1-p0) <= I
1835     pcmpeqb          m6, m7          ; abs(p1-p0) <= hev_thresh
1836     pand             m0, m1
1837     mova       mask_res, m6
1838 %else ; mmxext/sse2
1839     pmaxub           m0, m1          ; max_I
1840     SWAP              1, 4           ; max_hev_thresh
1841 %endif
1842
1843     SWAP              6, 4           ; now m6 is I
1844 %ifidn %2, v
1845     movrow           m4, [dst_reg]   ; q0
1846 %if mmsize == 16 && %4 == 8
1847     movhps           m4, [dst8_reg]
1848 %endif
1849 %elifdef m8
1850     SWAP              4, 8
1851 %else
1852     mova             m4, q0backup
1853 %endif
1854     mova             m1, m4
1855     SWAP              1, 4
1856     mova             m7, m5
1857     SWAP              7, 5
1858     psubusb          m1, m5          ; q0-q1
1859     psubusb          m7, m4          ; q1-q0
1860     por              m1, m7          ; abs(q1-q0)
1861 %ifidn %1, mmx
1862     mova             m7, m1
1863     psubusb          m1, m6
1864     psubusb          m7, hev_thr
1865     pxor             m6, m6
1866     pcmpeqb          m1, m6          ; abs(q1-q0) <= I
1867     pcmpeqb          m7, m6          ; abs(q1-q0) <= hev_thresh
1868     mova             m6, mask_res
1869     pand             m0, m1          ; abs([pq][321]-[pq][210]) <= I
1870     pand             m6, m7
1871 %else ; mmxext/sse2
1872     pxor             m7, m7
1873     pmaxub           m0, m1
1874     pmaxub           m6, m1
1875     psubusb          m0, flim_I
1876     psubusb          m6, hev_thr
1877     pcmpeqb          m0, m7          ; max(abs(..)) <= I
1878     pcmpeqb          m6, m7          ; !(max(abs..) > thresh)
1879 %endif
1880 %ifdef m12
1881     SWAP              6, 12
1882 %else
1883     mova       mask_res, m6          ; !(abs(p1-p0) > hev_t || abs(q1-q0) > hev_t)
1884 %endif
1885
1886     ; simple_limit
1887     mova             m1, m3
1888     SWAP              1, 3
1889     mova             m6, m4          ; keep copies of p0/q0 around for later use
1890     SWAP              6, 4
1891     psubusb          m1, m4          ; p0-q0
1892     psubusb          m6, m3          ; q0-p0
1893     por              m1, m6          ; abs(q0-p0)
1894     paddusb          m1, m1          ; m1=2*abs(q0-p0)
1895
1896     mova             m7, m2
1897     SWAP              7, 2
1898     mova             m6, m5
1899     SWAP              6, 5
1900     psubusb          m7, m5          ; p1-q1
1901     psubusb          m6, m2          ; q1-p1
1902     por              m7, m6          ; abs(q1-p1)
1903     pxor             m6, m6
1904     pand             m7, [pb_FE]
1905     psrlq            m7, 1           ; abs(q1-p1)/2
1906     paddusb          m7, m1          ; abs(q0-p0)*2+abs(q1-p1)/2
1907     psubusb          m7, flim_E
1908     pcmpeqb          m7, m6          ; abs(q0-p0)*2+abs(q1-p1)/2 <= E
1909     pand             m0, m7          ; normal_limit result
1910
1911     ; filter_common; at this point, m2-m5=p1-q1 and m0 is filter_mask
1912 %ifdef m8 ; x86-64 && sse2
1913     mova             m8, [pb_80]
1914 %define pb_80_var m8
1915 %else ; x86-32 or mmx/mmxext
1916 %define pb_80_var [pb_80]
1917 %endif
1918     mova             m1, m4
1919     mova             m7, m3
1920     pxor             m1, pb_80_var
1921     pxor             m7, pb_80_var
1922     psubsb           m1, m7          ; (signed) q0-p0
1923     mova             m6, m2
1924     mova             m7, m5
1925     pxor             m6, pb_80_var
1926     pxor             m7, pb_80_var
1927     psubsb           m6, m7          ; (signed) p1-q1
1928     mova             m7, mask_res
1929     pandn            m7, m6
1930     paddsb           m7, m1
1931     paddsb           m7, m1
1932     paddsb           m7, m1          ; 3*(q0-p0)+is4tap?(p1-q1)
1933
1934     pand             m7, m0
1935     mova             m1, [pb_F8]
1936     mova             m6, m7
1937     paddsb           m7, [pb_3]
1938     paddsb           m6, [pb_4]
1939     pand             m7, m1
1940     pand             m6, m1
1941
1942     pxor             m1, m1
1943     pxor             m0, m0
1944     pcmpgtb          m1, m7
1945     psubb            m0, m7
1946     psrlq            m7, 3           ; +f2
1947     psrlq            m0, 3           ; -f2
1948     pand             m0, m1
1949     pandn            m1, m7
1950     psubusb          m3, m0
1951     paddusb          m3, m1          ; p0+f2
1952
1953     pxor             m1, m1
1954     pxor             m0, m0
1955     pcmpgtb          m0, m6
1956     psubb            m1, m6
1957     psrlq            m6, 3           ; +f1
1958     psrlq            m1, 3           ; -f1
1959     pand             m1, m0
1960     pandn            m0, m6
1961     psubusb          m4, m0
1962     paddusb          m4, m1          ; q0-f1
1963
1964 %ifdef m12
1965     SWAP              6, 12
1966 %else
1967     mova             m6, mask_res
1968 %endif
1969 %ifidn %1, mmx
1970     mova             m7, [pb_1]
1971 %else ; mmxext/sse2
1972     pxor             m7, m7
1973 %endif
1974     pand             m0, m6
1975     pand             m1, m6
1976 %ifidn %1, mmx
1977     paddusb          m0, m7
1978     pand             m1, [pb_FE]
1979     pandn            m7, m0
1980     psrlq            m1, 1
1981     psrlq            m7, 1
1982     SWAP              0, 7
1983 %else ; mmxext/sse2
1984     psubusb          m1, [pb_1]
1985     pavgb            m0, m7          ; a
1986     pavgb            m1, m7          ; -a
1987 %endif
1988     psubusb          m5, m0
1989     psubusb          m2, m1
1990     paddusb          m5, m1          ; q1-a
1991     paddusb          m2, m0          ; p1+a
1992
1993     ; store
1994 %ifidn %2, v
1995     movrow [dst_reg +mstride_reg*2], m2
1996     movrow [dst_reg +mstride_reg  ], m3
1997     movrow    [dst_reg], m4
1998     movrow [dst_reg + stride_reg  ], m5
1999 %if mmsize == 16 && %4 == 8
2000     movhps [dst8_reg+mstride_reg*2], m2
2001     movhps [dst8_reg+mstride_reg  ], m3
2002     movhps   [dst8_reg], m4
2003     movhps [dst8_reg+ stride_reg  ], m5
2004 %endif
2005 %else ; h
2006     add         dst_reg, 2
2007     add        dst2_reg, 2
2008
2009     ; 4x8/16 transpose
2010     TRANSPOSE4x4B     2, 3, 4, 5, 6
2011
2012 %if mmsize == 8 ; mmx/mmxext (h)
2013     WRITE_4x2D        2, 3, 4, 5, dst_reg, dst2_reg, mstride_reg, stride_reg
2014 %else ; sse2 (h)
2015     lea        dst8_reg, [dst8_reg+mstride_reg+2]
2016     WRITE_4x4D        2, 3, 4, 5, dst_reg, dst2_reg, dst8_reg, mstride_reg, stride_reg, %4
2017 %endif
2018 %endif
2019
2020 %if mmsize == 8
2021 %if %4 == 8 ; chroma
2022 %ifidn %2, h
2023     sub         dst_reg, 2
2024 %endif
2025     cmp         dst_reg, dst8_reg
2026     mov         dst_reg, dst8_reg
2027     jnz .next8px
2028 %else
2029 %ifidn %2, h
2030     lea         dst_reg, [dst_reg + stride_reg*8-2]
2031 %else ; v
2032     add         dst_reg, 8
2033 %endif
2034     dec         cnt_reg
2035     jg .next8px
2036 %endif
2037 %endif
2038
2039 %ifndef m8 ; sse2 on x86-32 or mmx/mmxext
2040     mov             rsp, stack_reg   ; restore stack pointer
2041 %endif
2042     RET
2043 %endmacro
2044
2045 INIT_MMX
2046 %define SPLATB_REG SPLATB_REG_MMX
2047 INNER_LOOPFILTER mmx,    v, 6, 16, 0
2048 INNER_LOOPFILTER mmx,    h, 6, 16, 0
2049 INNER_LOOPFILTER mmx,    v, 6,  8, 0
2050 INNER_LOOPFILTER mmx,    h, 6,  8, 0
2051
2052 %define SPLATB_REG SPLATB_REG_MMXEXT
2053 INNER_LOOPFILTER mmxext, v, 6, 16, 0
2054 INNER_LOOPFILTER mmxext, h, 6, 16, 0
2055 INNER_LOOPFILTER mmxext, v, 6,  8, 0
2056 INNER_LOOPFILTER mmxext, h, 6,  8, 0
2057
2058 INIT_XMM
2059 %define SPLATB_REG SPLATB_REG_SSE2
2060 INNER_LOOPFILTER sse2,   v, 5, 16, 13
2061 %ifdef m8
2062 INNER_LOOPFILTER sse2,   h, 5, 16, 13
2063 %else
2064 INNER_LOOPFILTER sse2,   h, 6, 16, 13
2065 %endif
2066 INNER_LOOPFILTER sse2,   v, 6,  8, 13
2067 INNER_LOOPFILTER sse2,   h, 6,  8, 13
2068
2069 %define SPLATB_REG SPLATB_REG_SSSE3
2070 INNER_LOOPFILTER ssse3,  v, 5, 16, 13
2071 %ifdef m8
2072 INNER_LOOPFILTER ssse3,  h, 5, 16, 13
2073 %else
2074 INNER_LOOPFILTER ssse3,  h, 6, 16, 13
2075 %endif
2076 INNER_LOOPFILTER ssse3,  v, 6,  8, 13
2077 INNER_LOOPFILTER ssse3,  h, 6,  8, 13
2078
2079 ;-----------------------------------------------------------------------------
2080 ; void vp8_h/v_loop_filter<size>_mbedge_<opt>(uint8_t *dst, [uint8_t *v,] int stride,
2081 ;                                            int flimE, int flimI, int hev_thr);
2082 ;-----------------------------------------------------------------------------
2083
2084 ; write 4 or 8 words in the mmx/xmm registers as 8 lines
2085 ; 1 and 2 are the registers to write, this can be the same (for SSE2)
2086 ; for pre-SSE4:
2087 ; 3 is a general-purpose register that we will clobber
2088 ; for SSE4:
2089 ; 3 is a pointer to the destination's 5th line
2090 ; 4 is a pointer to the destination's 4th line
2091 ; 5/6 is -stride and +stride
2092 %macro WRITE_2x4W 6
2093     movd             %3, %1
2094     punpckhdq        %1, %1
2095     mov       [%4+%5*4], %3w
2096     shr              %3, 16
2097     add              %4, %6
2098     mov       [%4+%5*4], %3w
2099
2100     movd             %3, %1
2101     add              %4, %5
2102     mov       [%4+%5*2], %3w
2103     shr              %3, 16
2104     mov       [%4+%5  ], %3w
2105
2106     movd             %3, %2
2107     punpckhdq        %2, %2
2108     mov       [%4     ], %3w
2109     shr              %3, 16
2110     mov       [%4+%6  ], %3w
2111
2112     movd             %3, %2
2113     add              %4, %6
2114     mov       [%4+%6  ], %3w
2115     shr              %3, 16
2116     mov       [%4+%6*2], %3w
2117     add              %4, %5
2118 %endmacro
2119
2120 %macro WRITE_8W_SSE2 5
2121     movd             %2, %1
2122     psrldq           %1, 4
2123     mov       [%3+%4*4], %2w
2124     shr              %2, 16
2125     add              %3, %5
2126     mov       [%3+%4*4], %2w
2127
2128     movd             %2, %1
2129     psrldq           %1, 4
2130     add              %3, %4
2131     mov       [%3+%4*2], %2w
2132     shr              %2, 16
2133     mov       [%3+%4  ], %2w
2134
2135     movd             %2, %1
2136     psrldq           %1, 4
2137     mov       [%3     ], %2w
2138     shr              %2, 16
2139     mov       [%3+%5  ], %2w
2140
2141     movd             %2, %1
2142     add              %3, %5
2143     mov       [%3+%5  ], %2w
2144     shr              %2, 16
2145     mov       [%3+%5*2], %2w
2146 %endmacro
2147
2148 %macro WRITE_8W_SSE4 5
2149     pextrw    [%3+%4*4], %1, 0
2150     pextrw    [%2+%4*4], %1, 1
2151     pextrw    [%3+%4*2], %1, 2
2152     pextrw    [%3+%4  ], %1, 3
2153     pextrw    [%3     ], %1, 4
2154     pextrw    [%2     ], %1, 5
2155     pextrw    [%2+%5  ], %1, 6
2156     pextrw    [%2+%5*2], %1, 7
2157 %endmacro
2158
2159 %macro MBEDGE_LOOPFILTER 5
2160 %if %4 == 8 ; chroma
2161 cglobal vp8_%2_loop_filter8uv_mbedge_%1, 6, %3, %5
2162 %define dst8_reg    r1
2163 %define mstride_reg r2
2164 %define E_reg       r3
2165 %define I_reg       r4
2166 %define hev_thr_reg r5
2167 %else ; luma
2168 cglobal vp8_%2_loop_filter16y_mbedge_%1, 5, %3, %5
2169 %define mstride_reg r1
2170 %define E_reg       r2
2171 %define I_reg       r3
2172 %define hev_thr_reg r4
2173 %ifdef m8 ; x86-64, sse2
2174 %define dst8_reg    r4
2175 %elif mmsize == 16 ; x86-32, sse2
2176 %define dst8_reg    r5
2177 %else ; x86-32, mmx/mmxext
2178 %define cnt_reg     r5
2179 %endif
2180 %endif
2181 %define dst_reg     r0
2182 %define stride_reg  E_reg
2183 %define dst2_reg    I_reg
2184 %ifndef m8
2185 %define stack_reg   hev_thr_reg
2186 %endif
2187
2188 %ifnidn %1, sse2
2189 %if mmsize == 16
2190     pxor             m7, m7
2191 %endif
2192 %endif
2193
2194 %ifndef m8 ; mmx/mmxext or sse2 on x86-32
2195     ; splat function arguments
2196     SPLATB_REG       m0, E_reg, m7   ; E
2197     SPLATB_REG       m1, I_reg, m7   ; I
2198     SPLATB_REG       m2, hev_thr_reg, m7 ; hev_thresh
2199
2200     ; align stack
2201     mov       stack_reg, rsp         ; backup stack pointer
2202     and             rsp, ~(mmsize-1) ; align stack
2203 %if mmsize == 16
2204     sub             rsp, mmsize * 7
2205 %else
2206     sub             rsp, mmsize * 8  ; stack layout: [0]=E, [1]=I, [2]=hev_thr
2207                                      ;               [3]=hev() result
2208                                      ;               [4]=filter tmp result
2209                                      ;               [5]/[6] = p2/q2 backup
2210                                      ;               [7]=lim_res sign result
2211 %endif
2212
2213 %define flim_E   [rsp]
2214 %define flim_I   [rsp+mmsize]
2215 %define hev_thr  [rsp+mmsize*2]
2216 %define mask_res [rsp+mmsize*3]
2217 %define lim_res  [rsp+mmsize*4]
2218 %define p0backup [rsp+mmsize*3]
2219 %define q0backup [rsp+mmsize*4]
2220 %define p2backup [rsp+mmsize*5]
2221 %define q2backup [rsp+mmsize*6]
2222 %if mmsize == 16
2223 %define lim_sign [rsp]
2224 %else
2225 %define lim_sign [rsp+mmsize*7]
2226 %endif
2227
2228     mova         flim_E, m0
2229     mova         flim_I, m1
2230     mova        hev_thr, m2
2231
2232 %else ; sse2 on x86-64
2233
2234 %define flim_E   m9
2235 %define flim_I   m10
2236 %define hev_thr  m11
2237 %define mask_res m12
2238 %define lim_res  m8
2239 %define p0backup m12
2240 %define q0backup m8
2241 %define p2backup m13
2242 %define q2backup m14
2243 %define lim_sign m9
2244
2245     ; splat function arguments
2246     SPLATB_REG   flim_E, E_reg, m7   ; E
2247     SPLATB_REG   flim_I, I_reg, m7   ; I
2248     SPLATB_REG  hev_thr, hev_thr_reg, m7 ; hev_thresh
2249 %endif
2250
2251 %if mmsize == 8 && %4 == 16 ; mmx/mmxext
2252     mov         cnt_reg, 2
2253 %endif
2254     mov      stride_reg, mstride_reg
2255     neg     mstride_reg
2256 %ifidn %2, h
2257     lea         dst_reg, [dst_reg + stride_reg*4-4]
2258 %if %4 == 8
2259     lea        dst8_reg, [dst8_reg+ stride_reg*4-4]
2260 %endif
2261 %endif
2262
2263 %if mmsize == 8
2264 .next8px
2265 %endif
2266     ; read
2267     lea        dst2_reg, [dst_reg + stride_reg]
2268 %ifidn %2, v
2269 %if %4 == 8 && mmsize == 16
2270 %define movrow movh
2271 %else
2272 %define movrow mova
2273 %endif
2274     movrow           m0, [dst_reg +mstride_reg*4] ; p3
2275     movrow           m1, [dst2_reg+mstride_reg*4] ; p2
2276     movrow           m2, [dst_reg +mstride_reg*2] ; p1
2277     movrow           m5, [dst2_reg]               ; q1
2278     movrow           m6, [dst2_reg+ stride_reg]   ; q2
2279     movrow           m7, [dst2_reg+ stride_reg*2] ; q3
2280 %if mmsize == 16 && %4 == 8
2281     movhps           m0, [dst8_reg+mstride_reg*4]
2282     movhps           m2, [dst8_reg+mstride_reg*2]
2283     add        dst8_reg, stride_reg
2284     movhps           m1, [dst8_reg+mstride_reg*4]
2285     movhps           m5, [dst8_reg]
2286     movhps           m6, [dst8_reg+ stride_reg]
2287     movhps           m7, [dst8_reg+ stride_reg*2]
2288     add        dst8_reg, mstride_reg
2289 %endif
2290 %elif mmsize == 8 ; mmx/mmxext (h)
2291     ; read 8 rows of 8px each
2292     movu             m0, [dst_reg +mstride_reg*4]
2293     movu             m1, [dst2_reg+mstride_reg*4]
2294     movu             m2, [dst_reg +mstride_reg*2]
2295     movu             m3, [dst_reg +mstride_reg]
2296     movu             m4, [dst_reg]
2297     movu             m5, [dst2_reg]
2298     movu             m6, [dst2_reg+ stride_reg]
2299
2300     ; 8x8 transpose
2301     TRANSPOSE4x4B     0, 1, 2, 3, 7
2302     mova       q0backup, m1
2303     movu             m7, [dst2_reg+ stride_reg*2]
2304     TRANSPOSE4x4B     4, 5, 6, 7, 1
2305     SBUTTERFLY       dq, 0, 4, 1     ; p3/p2
2306     SBUTTERFLY       dq, 2, 6, 1     ; q0/q1
2307     SBUTTERFLY       dq, 3, 7, 1     ; q2/q3
2308     mova             m1, q0backup
2309     mova       q0backup, m2          ; store q0
2310     SBUTTERFLY       dq, 1, 5, 2     ; p1/p0
2311     mova       p0backup, m5          ; store p0
2312     SWAP              1, 4
2313     SWAP              2, 4
2314     SWAP              6, 3
2315     SWAP              5, 3
2316 %else ; sse2 (h)
2317 %if %4 == 16
2318     lea        dst8_reg, [dst_reg + stride_reg*8]
2319 %endif
2320
2321     ; read 16 rows of 8px each, interleave
2322     movh             m0, [dst_reg +mstride_reg*4]
2323     movh             m1, [dst8_reg+mstride_reg*4]
2324     movh             m2, [dst_reg +mstride_reg*2]
2325     movh             m5, [dst8_reg+mstride_reg*2]
2326     movh             m3, [dst_reg +mstride_reg]
2327     movh             m6, [dst8_reg+mstride_reg]
2328     movh             m4, [dst_reg]
2329     movh             m7, [dst8_reg]
2330     punpcklbw        m0, m1          ; A/I
2331     punpcklbw        m2, m5          ; C/K
2332     punpcklbw        m3, m6          ; D/L
2333     punpcklbw        m4, m7          ; E/M
2334
2335     add        dst8_reg, stride_reg
2336     movh             m1, [dst2_reg+mstride_reg*4]
2337     movh             m6, [dst8_reg+mstride_reg*4]
2338     movh             m5, [dst2_reg]
2339     movh             m7, [dst8_reg]
2340     punpcklbw        m1, m6          ; B/J
2341     punpcklbw        m5, m7          ; F/N
2342     movh             m6, [dst2_reg+ stride_reg]
2343     movh             m7, [dst8_reg+ stride_reg]
2344     punpcklbw        m6, m7          ; G/O
2345
2346     ; 8x16 transpose
2347     TRANSPOSE4x4B     0, 1, 2, 3, 7
2348 %ifdef m8
2349     SWAP              1, 8
2350 %else
2351     mova       q0backup, m1
2352 %endif
2353     movh             m7, [dst2_reg+ stride_reg*2]
2354     movh             m1, [dst8_reg+ stride_reg*2]
2355     punpcklbw        m7, m1          ; H/P
2356     TRANSPOSE4x4B     4, 5, 6, 7, 1
2357     SBUTTERFLY       dq, 0, 4, 1     ; p3/p2
2358     SBUTTERFLY       dq, 2, 6, 1     ; q0/q1
2359     SBUTTERFLY       dq, 3, 7, 1     ; q2/q3
2360 %ifdef m8
2361     SWAP              1, 8
2362     SWAP              2, 8
2363 %else
2364     mova             m1, q0backup
2365     mova       q0backup, m2          ; store q0
2366 %endif
2367     SBUTTERFLY       dq, 1, 5, 2     ; p1/p0
2368 %ifdef m12
2369     SWAP              5, 12
2370 %else
2371     mova       p0backup, m5          ; store p0
2372 %endif
2373     SWAP              1, 4
2374     SWAP              2, 4
2375     SWAP              6, 3
2376     SWAP              5, 3
2377 %endif
2378
2379     ; normal_limit for p3-p2, p2-p1, q3-q2 and q2-q1
2380     mova             m4, m1
2381     SWAP              4, 1
2382     psubusb          m4, m0          ; p2-p3
2383     psubusb          m0, m1          ; p3-p2
2384     por              m0, m4          ; abs(p3-p2)
2385
2386     mova             m4, m2
2387     SWAP              4, 2
2388     psubusb          m4, m1          ; p1-p2
2389     mova       p2backup, m1
2390     psubusb          m1, m2          ; p2-p1
2391     por              m1, m4          ; abs(p2-p1)
2392
2393     mova             m4, m6
2394     SWAP              4, 6
2395     psubusb          m4, m7          ; q2-q3
2396     psubusb          m7, m6          ; q3-q2
2397     por              m7, m4          ; abs(q3-q2)
2398
2399     mova             m4, m5
2400     SWAP              4, 5
2401     psubusb          m4, m6          ; q1-q2
2402     mova       q2backup, m6
2403     psubusb          m6, m5          ; q2-q1
2404     por              m6, m4          ; abs(q2-q1)
2405
2406 %ifidn %1, mmx
2407     mova             m4, flim_I
2408     pxor             m3, m3
2409     psubusb          m0, m4
2410     psubusb          m1, m4
2411     psubusb          m7, m4
2412     psubusb          m6, m4
2413     pcmpeqb          m0, m3          ; abs(p3-p2) <= I
2414     pcmpeqb          m1, m3          ; abs(p2-p1) <= I
2415     pcmpeqb          m7, m3          ; abs(q3-q2) <= I
2416     pcmpeqb          m6, m3          ; abs(q2-q1) <= I
2417     pand             m0, m1
2418     pand             m7, m6
2419     pand             m0, m7
2420 %else ; mmxext/sse2
2421     pmaxub           m0, m1
2422     pmaxub           m6, m7
2423     pmaxub           m0, m6
2424 %endif
2425
2426     ; normal_limit and high_edge_variance for p1-p0, q1-q0
2427     SWAP              7, 3           ; now m7 is zero
2428 %ifidn %2, v
2429     movrow           m3, [dst_reg +mstride_reg] ; p0
2430 %if mmsize == 16 && %4 == 8
2431     movhps           m3, [dst8_reg+mstride_reg]
2432 %endif
2433 %elifdef m12
2434     SWAP              3, 12
2435 %else
2436     mova             m3, p0backup
2437 %endif
2438
2439     mova             m1, m2
2440     SWAP              1, 2
2441     mova             m6, m3
2442     SWAP              3, 6
2443     psubusb          m1, m3          ; p1-p0
2444     psubusb          m6, m2          ; p0-p1
2445     por              m1, m6          ; abs(p1-p0)
2446 %ifidn %1, mmx
2447     mova             m6, m1
2448     psubusb          m1, m4
2449     psubusb          m6, hev_thr
2450     pcmpeqb          m1, m7          ; abs(p1-p0) <= I
2451     pcmpeqb          m6, m7          ; abs(p1-p0) <= hev_thresh
2452     pand             m0, m1
2453     mova       mask_res, m6
2454 %else ; mmxext/sse2
2455     pmaxub           m0, m1          ; max_I
2456     SWAP              1, 4           ; max_hev_thresh
2457 %endif
2458
2459     SWAP              6, 4           ; now m6 is I
2460 %ifidn %2, v
2461     movrow           m4, [dst_reg]   ; q0
2462 %if mmsize == 16 && %4 == 8
2463     movhps           m4, [dst8_reg]
2464 %endif
2465 %elifdef m8
2466     SWAP              4, 8
2467 %else
2468     mova             m4, q0backup
2469 %endif
2470     mova             m1, m4
2471     SWAP              1, 4
2472     mova             m7, m5
2473     SWAP              7, 5
2474     psubusb          m1, m5          ; q0-q1
2475     psubusb          m7, m4          ; q1-q0
2476     por              m1, m7          ; abs(q1-q0)
2477 %ifidn %1, mmx
2478     mova             m7, m1
2479     psubusb          m1, m6
2480     psubusb          m7, hev_thr
2481     pxor             m6, m6
2482     pcmpeqb          m1, m6          ; abs(q1-q0) <= I
2483     pcmpeqb          m7, m6          ; abs(q1-q0) <= hev_thresh
2484     mova             m6, mask_res
2485     pand             m0, m1          ; abs([pq][321]-[pq][210]) <= I
2486     pand             m6, m7
2487 %else ; mmxext/sse2
2488     pxor             m7, m7
2489     pmaxub           m0, m1
2490     pmaxub           m6, m1
2491     psubusb          m0, flim_I
2492     psubusb          m6, hev_thr
2493     pcmpeqb          m0, m7          ; max(abs(..)) <= I
2494     pcmpeqb          m6, m7          ; !(max(abs..) > thresh)
2495 %endif
2496 %ifdef m12
2497     SWAP              6, 12
2498 %else
2499     mova       mask_res, m6          ; !(abs(p1-p0) > hev_t || abs(q1-q0) > hev_t)
2500 %endif
2501
2502     ; simple_limit
2503     mova             m1, m3
2504     SWAP              1, 3
2505     mova             m6, m4          ; keep copies of p0/q0 around for later use
2506     SWAP              6, 4
2507     psubusb          m1, m4          ; p0-q0
2508     psubusb          m6, m3          ; q0-p0
2509     por              m1, m6          ; abs(q0-p0)
2510     paddusb          m1, m1          ; m1=2*abs(q0-p0)
2511
2512     mova             m7, m2
2513     SWAP              7, 2
2514     mova             m6, m5
2515     SWAP              6, 5
2516     psubusb          m7, m5          ; p1-q1
2517     psubusb          m6, m2          ; q1-p1
2518     por              m7, m6          ; abs(q1-p1)
2519     pxor             m6, m6
2520     pand             m7, [pb_FE]
2521     psrlq            m7, 1           ; abs(q1-p1)/2
2522     paddusb          m7, m1          ; abs(q0-p0)*2+abs(q1-p1)/2
2523     psubusb          m7, flim_E
2524     pcmpeqb          m7, m6          ; abs(q0-p0)*2+abs(q1-p1)/2 <= E
2525     pand             m0, m7          ; normal_limit result
2526
2527     ; filter_common; at this point, m2-m5=p1-q1 and m0 is filter_mask
2528 %ifdef m8 ; x86-64 && sse2
2529     mova             m8, [pb_80]
2530 %define pb_80_var m8
2531 %else ; x86-32 or mmx/mmxext
2532 %define pb_80_var [pb_80]
2533 %endif
2534     mova             m1, m4
2535     mova             m7, m3
2536     pxor             m1, pb_80_var
2537     pxor             m7, pb_80_var
2538     psubsb           m1, m7          ; (signed) q0-p0
2539     mova             m6, m2
2540     mova             m7, m5
2541     pxor             m6, pb_80_var
2542     pxor             m7, pb_80_var
2543     psubsb           m6, m7          ; (signed) p1-q1
2544     mova             m7, mask_res
2545     paddsb           m6, m1
2546     paddsb           m6, m1
2547     paddsb           m6, m1
2548     pand             m6, m0
2549 %ifdef m8
2550     mova        lim_res, m6          ; 3*(qp-p0)+(p1-q1) masked for filter_mbedge
2551     pand        lim_res, m7
2552 %else
2553     mova             m0, m6
2554     pand             m0, m7
2555     mova        lim_res, m0
2556 %endif
2557     pandn            m7, m6          ; 3*(q0-p0)+(p1-q1) masked for filter_common
2558
2559     mova             m1, [pb_F8]
2560     mova             m6, m7
2561     paddsb           m7, [pb_3]
2562     paddsb           m6, [pb_4]
2563     pand             m7, m1
2564     pand             m6, m1
2565
2566     pxor             m1, m1
2567     pxor             m0, m0
2568     pcmpgtb          m1, m7
2569     psubb            m0, m7
2570     psrlq            m7, 3           ; +f2
2571     psrlq            m0, 3           ; -f2
2572     pand             m0, m1
2573     pandn            m1, m7
2574     psubusb          m3, m0
2575     paddusb          m3, m1          ; p0+f2
2576
2577     pxor             m1, m1
2578     pxor             m0, m0
2579     pcmpgtb          m0, m6
2580     psubb            m1, m6
2581     psrlq            m6, 3           ; +f1
2582     psrlq            m1, 3           ; -f1
2583     pand             m1, m0
2584     pandn            m0, m6
2585     psubusb          m4, m0
2586     paddusb          m4, m1          ; q0-f1
2587
2588     ; filter_mbedge (m2-m5 = p1-q1; lim_res carries w)
2589     mova             m7, [pw_63]
2590 %ifdef m8
2591     SWAP              1, 8
2592 %else
2593     mova             m1, lim_res
2594 %endif
2595     pxor             m0, m0
2596     mova             m6, m1
2597     pcmpgtb          m0, m1         ; which are negative
2598     punpcklbw        m6, m0         ; signed byte->word
2599     punpckhbw        m1, m0
2600     mova       lim_sign, m0
2601     mova       mask_res, m6         ; backup for later in filter
2602     mova        lim_res, m1
2603     pmullw          m6, [pw_27]
2604     pmullw          m1, [pw_27]
2605     paddw           m6, m7
2606     paddw           m1, m7
2607     psraw           m6, 7
2608     psraw           m1, 7
2609     packsswb        m6, m1          ; a0
2610     pxor            m1, m1
2611     psubb           m1, m6
2612     pand            m1, m0          ; -a0
2613     pandn           m0, m6          ; +a0
2614     psubusb         m3, m1
2615     paddusb         m4, m1
2616     paddusb         m3, m0          ; p0+a0
2617     psubusb         m4, m0          ; q0-a0
2618
2619     mova            m6, mask_res
2620     mova            m1, lim_res
2621     mova            m0, lim_sign
2622     pmullw          m6, [pw_18]
2623     pmullw          m1, [pw_18]
2624     paddw           m6, m7
2625     paddw           m1, m7
2626     psraw           m6, 7
2627     psraw           m1, 7
2628     packsswb        m6, m1          ; a1
2629     pxor            m1, m1
2630     psubb           m1, m6
2631     pand            m1, m0          ; -a1
2632     pandn           m0, m6          ; +a1
2633     psubusb         m2, m1
2634     paddusb         m5, m1
2635     paddusb         m2, m0          ; p1+a1
2636     psubusb         m5, m0          ; q1-a1
2637
2638 %ifdef m8
2639     SWAP             6, 12
2640     SWAP             1, 8
2641 %else
2642     mova            m6, mask_res
2643     mova            m1, lim_res
2644 %endif
2645     pmullw          m6, [pw_9]
2646     pmullw          m1, [pw_9]
2647     paddw           m6, m7
2648     paddw           m1, m7
2649 %ifdef m9
2650     SWAP             7, 9
2651 %else
2652     mova            m7, lim_sign
2653 %endif
2654     psraw           m6, 7
2655     psraw           m1, 7
2656     packsswb        m6, m1          ; a1
2657     pxor            m0, m0
2658     psubb           m0, m6
2659     pand            m0, m7          ; -a1
2660     pandn           m7, m6          ; +a1
2661 %ifdef m8
2662     SWAP             1, 13
2663     SWAP             6, 14
2664 %else
2665     mova            m1, p2backup
2666     mova            m6, q2backup
2667 %endif
2668     psubusb         m1, m0
2669     paddusb         m6, m0
2670     paddusb         m1, m7          ; p1+a1
2671     psubusb         m6, m7          ; q1-a1
2672
2673     ; store
2674 %ifidn %2, v
2675     movrow [dst2_reg+mstride_reg*4], m1
2676     movrow [dst_reg +mstride_reg*2], m2
2677     movrow [dst_reg +mstride_reg  ], m3
2678     movrow    [dst_reg], m4
2679     movrow   [dst2_reg], m5
2680     movrow [dst2_reg+ stride_reg  ], m6
2681 %if mmsize == 16 && %4 == 8
2682     add        dst8_reg, mstride_reg
2683     movhps [dst8_reg+mstride_reg*2], m1
2684     movhps [dst8_reg+mstride_reg  ], m2
2685     movhps   [dst8_reg], m3
2686     add        dst8_reg, stride_reg
2687     movhps   [dst8_reg], m4
2688     movhps [dst8_reg+ stride_reg  ], m5
2689     movhps [dst8_reg+ stride_reg*2], m6
2690 %endif
2691 %else ; h
2692     inc         dst_reg
2693     inc        dst2_reg
2694
2695     ; 4x8/16 transpose
2696     TRANSPOSE4x4B     1, 2, 3, 4, 0
2697     SBUTTERFLY       bw, 5, 6, 0
2698
2699 %if mmsize == 8 ; mmx/mmxext (h)
2700     WRITE_4x2D        1, 2, 3, 4, dst_reg, dst2_reg, mstride_reg, stride_reg
2701     add         dst_reg, 4
2702     WRITE_2x4W       m5, m6, dst2_reg, dst_reg, mstride_reg, stride_reg
2703 %else ; sse2 (h)
2704     lea        dst8_reg, [dst8_reg+mstride_reg+1]
2705     WRITE_4x4D        1, 2, 3, 4, dst_reg, dst2_reg, dst8_reg, mstride_reg, stride_reg, %4
2706     lea         dst_reg, [dst2_reg+mstride_reg+4]
2707     lea        dst8_reg, [dst8_reg+mstride_reg+4]
2708 %ifidn %1, sse4
2709     add        dst2_reg, 4
2710 %endif
2711     WRITE_8W         m5, dst2_reg, dst_reg,  mstride_reg, stride_reg
2712 %ifidn %1, sse4
2713     lea        dst2_reg, [dst8_reg+ stride_reg]
2714 %endif
2715     WRITE_8W         m6, dst2_reg, dst8_reg, mstride_reg, stride_reg
2716 %endif
2717 %endif
2718
2719 %if mmsize == 8
2720 %if %4 == 8 ; chroma
2721 %ifidn %2, h
2722     sub         dst_reg, 5
2723 %endif
2724     cmp         dst_reg, dst8_reg
2725     mov         dst_reg, dst8_reg
2726     jnz .next8px
2727 %else
2728 %ifidn %2, h
2729     lea         dst_reg, [dst_reg + stride_reg*8-5]
2730 %else ; v
2731     add         dst_reg, 8
2732 %endif
2733     dec         cnt_reg
2734     jg .next8px
2735 %endif
2736 %endif
2737
2738 %ifndef m8 ; sse2 on x86-32 or mmx/mmxext
2739     mov             rsp, stack_reg   ; restore stack pointer
2740 %endif
2741     RET
2742 %endmacro
2743
2744 INIT_MMX
2745 %define SPLATB_REG SPLATB_REG_MMX
2746 MBEDGE_LOOPFILTER mmx,    v, 6, 16, 0
2747 MBEDGE_LOOPFILTER mmx,    h, 6, 16, 0
2748 MBEDGE_LOOPFILTER mmx,    v, 6,  8, 0
2749 MBEDGE_LOOPFILTER mmx,    h, 6,  8, 0
2750
2751 %define SPLATB_REG SPLATB_REG_MMXEXT
2752 MBEDGE_LOOPFILTER mmxext, v, 6, 16, 0
2753 MBEDGE_LOOPFILTER mmxext, h, 6, 16, 0
2754 MBEDGE_LOOPFILTER mmxext, v, 6,  8, 0
2755 MBEDGE_LOOPFILTER mmxext, h, 6,  8, 0
2756
2757 INIT_XMM
2758 %define SPLATB_REG SPLATB_REG_SSE2
2759 %define WRITE_8W   WRITE_8W_SSE2
2760 MBEDGE_LOOPFILTER sse2,   v, 5, 16, 15
2761 %ifdef m8
2762 MBEDGE_LOOPFILTER sse2,   h, 5, 16, 15
2763 %else
2764 MBEDGE_LOOPFILTER sse2,   h, 6, 16, 15
2765 %endif
2766 MBEDGE_LOOPFILTER sse2,   v, 6,  8, 15
2767 MBEDGE_LOOPFILTER sse2,   h, 6,  8, 15
2768
2769 %define SPLATB_REG SPLATB_REG_SSSE3
2770 MBEDGE_LOOPFILTER ssse3,  v, 5, 16, 15
2771 %ifdef m8
2772 MBEDGE_LOOPFILTER ssse3,  h, 5, 16, 15
2773 %else
2774 MBEDGE_LOOPFILTER ssse3,  h, 6, 16, 15
2775 %endif
2776 MBEDGE_LOOPFILTER ssse3,  v, 6,  8, 15
2777 MBEDGE_LOOPFILTER ssse3,  h, 6,  8, 15
2778
2779 %define WRITE_8W   WRITE_8W_SSE4
2780 %ifdef m8
2781 MBEDGE_LOOPFILTER sse4,   h, 5, 16, 15
2782 %else
2783 MBEDGE_LOOPFILTER sse4,   h, 6, 16, 15
2784 %endif
2785 MBEDGE_LOOPFILTER sse4,   h, 6,  8, 15