VP8: 30% faster idct_mb
[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_add4_<opt>(uint8_t *dst, DCTELEM block[4][16], int stride);
980 ;-----------------------------------------------------------------------------
981
982 INIT_MMX
983 cglobal vp8_idct_dc_add4_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_add4_sse2, 3, 3
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_add_<opt>(uint8_t *dst, DCTELEM block[16], int stride);
1049 ;-----------------------------------------------------------------------------
1050
1051 ; calculate %1=mul_35468(%1)-mul_20091(%2); %2=mul_20091(%1)+mul_35468(%2)
1052 ;           this macro assumes that m6/m7 have words for 20091/17734 loaded
1053 %macro VP8_MULTIPLY_SUMSUB 4
1054     mova      %3, %1
1055     mova      %4, %2
1056     pmulhw    %3, m6 ;20091(1)
1057     pmulhw    %4, m6 ;20091(2)
1058     paddw     %3, %1
1059     paddw     %4, %2
1060     paddw     %1, %1
1061     paddw     %2, %2
1062     pmulhw    %1, m7 ;35468(1)
1063     pmulhw    %2, m7 ;35468(2)
1064     psubw     %1, %4
1065     paddw     %2, %3
1066 %endmacro
1067
1068 ; calculate x0=%1+%3; x1=%1-%3
1069 ;           x2=mul_35468(%2)-mul_20091(%4); x3=mul_20091(%2)+mul_35468(%4)
1070 ;           %1=x0+x3 (tmp0); %2=x1+x2 (tmp1); %3=x1-x2 (tmp2); %4=x0-x3 (tmp3)
1071 ;           %5/%6 are temporary registers
1072 ;           we assume m6/m7 have constant words 20091/17734 loaded in them
1073 %macro VP8_IDCT_TRANSFORM4x4_1D 6
1074     SUMSUB_BA           m%3, m%1, m%5     ;t0, t1
1075     VP8_MULTIPLY_SUMSUB m%2, m%4, m%5,m%6 ;t2, t3
1076     SUMSUB_BA           m%4, m%3, m%5     ;tmp0, tmp3
1077     SUMSUB_BA           m%2, m%1, m%5     ;tmp1, tmp2
1078     SWAP                 %4,  %1
1079     SWAP                 %4,  %3
1080 %endmacro
1081
1082 INIT_MMX
1083 %macro VP8_IDCT_ADD 1
1084 cglobal vp8_idct_add_%1, 3, 3
1085     ; load block data
1086     movq         m0, [r1+ 0]
1087     movq         m1, [r1+ 8]
1088     movq         m2, [r1+16]
1089     movq         m3, [r1+24]
1090     movq         m6, [pw_20091]
1091     movq         m7, [pw_17734]
1092 %ifidn %1, sse
1093     xorps      xmm0, xmm0
1094     movaps  [r1+ 0], xmm0
1095     movaps  [r1+16], xmm0
1096 %else
1097     pxor         m4, m4
1098     movq    [r1+ 0], m4
1099     movq    [r1+ 8], m4
1100     movq    [r1+16], m4
1101     movq    [r1+24], m4
1102 %endif
1103
1104     ; actual IDCT
1105     VP8_IDCT_TRANSFORM4x4_1D 0, 1, 2, 3, 4, 5
1106     TRANSPOSE4x4W            0, 1, 2, 3, 4
1107     paddw        m0, [pw_4]
1108     VP8_IDCT_TRANSFORM4x4_1D 0, 1, 2, 3, 4, 5
1109     TRANSPOSE4x4W            0, 1, 2, 3, 4
1110
1111     ; store
1112     pxor         m4, m4
1113     lea          r1, [r0+2*r2]
1114     STORE_DIFFx2 m0, m1, m6, m7, m4, 3, r0, r2
1115     STORE_DIFFx2 m2, m3, m6, m7, m4, 3, r1, r2
1116
1117     RET
1118 %endmacro
1119
1120 VP8_IDCT_ADD mmx
1121 VP8_IDCT_ADD sse
1122
1123 ;-----------------------------------------------------------------------------
1124 ; void vp8_luma_dc_wht_mmxext(DCTELEM block[4][4][16], DCTELEM dc[16])
1125 ;-----------------------------------------------------------------------------
1126
1127 %macro SCATTER_WHT 3
1128     movd  r1d, m%1
1129     movd  r2d, m%2
1130     mov [r0+2*16*(0+%3)], r1w
1131     mov [r0+2*16*(1+%3)], r2w
1132     shr   r1d, 16
1133     shr   r2d, 16
1134     psrlq m%1, 32
1135     psrlq m%2, 32
1136     mov [r0+2*16*(4+%3)], r1w
1137     mov [r0+2*16*(5+%3)], r2w
1138     movd  r1d, m%1
1139     movd  r2d, m%2
1140     mov [r0+2*16*(8+%3)], r1w
1141     mov [r0+2*16*(9+%3)], r2w
1142     shr   r1d, 16
1143     shr   r2d, 16
1144     mov [r0+2*16*(12+%3)], r1w
1145     mov [r0+2*16*(13+%3)], r2w
1146 %endmacro
1147
1148 %macro HADAMARD4_1D 4
1149     SUMSUB_BADC m%2, m%1, m%4, m%3
1150     SUMSUB_BADC m%4, m%2, m%3, m%1
1151     SWAP %1, %4, %3
1152 %endmacro
1153
1154 INIT_MMX
1155 cglobal vp8_luma_dc_wht_mmx, 2,3
1156     movq          m0, [r1]
1157     movq          m1, [r1+8]
1158     movq          m2, [r1+16]
1159     movq          m3, [r1+24]
1160     HADAMARD4_1D  0, 1, 2, 3
1161     TRANSPOSE4x4W 0, 1, 2, 3, 4
1162     paddw         m0, [pw_3]
1163     HADAMARD4_1D  0, 1, 2, 3
1164     psraw         m0, 3
1165     psraw         m1, 3
1166     psraw         m2, 3
1167     psraw         m3, 3
1168     SCATTER_WHT   0, 1, 0
1169     SCATTER_WHT   2, 3, 2
1170     RET
1171
1172 ;-----------------------------------------------------------------------------
1173 ; void vp8_h/v_loop_filter_simple_<opt>(uint8_t *dst, int stride, int flim);
1174 ;-----------------------------------------------------------------------------
1175
1176 ; macro called with 7 mm register indexes as argument, and 4 regular registers
1177 ;
1178 ; first 4 mm registers will carry the transposed pixel data
1179 ; the other three are scratchspace (one would be sufficient, but this allows
1180 ; for more spreading/pipelining and thus faster execution on OOE CPUs)
1181 ;
1182 ; first two regular registers are buf+4*stride and buf+5*stride
1183 ; third is -stride, fourth is +stride
1184 %macro READ_8x4_INTERLEAVED 11
1185     ; interleave 8 (A-H) rows of 4 pixels each
1186     movd          m%1, [%8+%10*4]   ; A0-3
1187     movd          m%5, [%9+%10*4]   ; B0-3
1188     movd          m%2, [%8+%10*2]   ; C0-3
1189     movd          m%6, [%8+%10]     ; D0-3
1190     movd          m%3, [%8]         ; E0-3
1191     movd          m%7, [%9]         ; F0-3
1192     movd          m%4, [%9+%11]     ; G0-3
1193     punpcklbw     m%1, m%5          ; A/B interleaved
1194     movd          m%5, [%9+%11*2]   ; H0-3
1195     punpcklbw     m%2, m%6          ; C/D interleaved
1196     punpcklbw     m%3, m%7          ; E/F interleaved
1197     punpcklbw     m%4, m%5          ; G/H interleaved
1198 %endmacro
1199
1200 ; macro called with 7 mm register indexes as argument, and 5 regular registers
1201 ; first 11 mean the same as READ_8x4_TRANSPOSED above
1202 ; fifth regular register is scratchspace to reach the bottom 8 rows, it
1203 ; will be set to second regular register + 8*stride at the end
1204 %macro READ_16x4_INTERLEAVED 12
1205     ; transpose 16 (A-P) rows of 4 pixels each
1206     lea           %12, [r0+8*r2]
1207
1208     ; read (and interleave) those addressable by %8 (=r0), A/C/D/E/I/K/L/M
1209     movd          m%1, [%8+%10*4]   ; A0-3
1210     movd          m%3, [%12+%10*4]  ; I0-3
1211     movd          m%2, [%8+%10*2]   ; C0-3
1212     movd          m%4, [%12+%10*2]  ; K0-3
1213     movd          m%6, [%8+%10]     ; D0-3
1214     movd          m%5, [%12+%10]    ; L0-3
1215     movd          m%7, [%12]        ; M0-3
1216     add           %12, %11
1217     punpcklbw     m%1, m%3          ; A/I
1218     movd          m%3, [%8]         ; E0-3
1219     punpcklbw     m%2, m%4          ; C/K
1220     punpcklbw     m%6, m%5          ; D/L
1221     punpcklbw     m%3, m%7          ; E/M
1222     punpcklbw     m%2, m%6          ; C/D/K/L interleaved
1223
1224     ; read (and interleave) those addressable by %9 (=r4), B/F/G/H/J/N/O/P
1225     movd         m%5, [%9+%10*4]   ; B0-3
1226     movd         m%4, [%12+%10*4]  ; J0-3
1227     movd         m%7, [%9]         ; F0-3
1228     movd         m%6, [%12]        ; N0-3
1229     punpcklbw    m%5, m%4          ; B/J
1230     punpcklbw    m%7, m%6          ; F/N
1231     punpcklbw    m%1, m%5          ; A/B/I/J interleaved
1232     punpcklbw    m%3, m%7          ; E/F/M/N interleaved
1233     movd         m%4, [%9+%11]     ; G0-3
1234     movd         m%6, [%12+%11]    ; O0-3
1235     movd         m%5, [%9+%11*2]   ; H0-3
1236     movd         m%7, [%12+%11*2]  ; P0-3
1237     punpcklbw    m%4, m%6          ; G/O
1238     punpcklbw    m%5, m%7          ; H/P
1239     punpcklbw    m%4, m%5          ; G/H/O/P interleaved
1240 %endmacro
1241
1242 ; write 4 mm registers of 2 dwords each
1243 ; first four arguments are mm register indexes containing source data
1244 ; last four are registers containing buf+4*stride, buf+5*stride,
1245 ; -stride and +stride
1246 %macro WRITE_4x2D 8
1247     ; write out (2 dwords per register)
1248     movd    [%5+%7*4], m%1
1249     movd    [%5+%7*2], m%2
1250     movd         [%5], m%3
1251     movd      [%6+%8], m%4
1252     punpckhdq     m%1, m%1
1253     punpckhdq     m%2, m%2
1254     punpckhdq     m%3, m%3
1255     punpckhdq     m%4, m%4
1256     movd    [%6+%7*4], m%1
1257     movd      [%5+%7], m%2
1258     movd         [%6], m%3
1259     movd    [%6+%8*2], m%4
1260 %endmacro
1261
1262 ; write 4 xmm registers of 4 dwords each
1263 ; arguments same as WRITE_2x4D, but with an extra register, so that the 5 regular
1264 ; registers contain buf+4*stride, buf+5*stride, buf+12*stride, -stride and +stride
1265 ; we add 1*stride to the third regular registry in the process
1266 ; the 10th argument is 16 if it's a Y filter (i.e. all regular registers cover the
1267 ; same memory region), or 8 if they cover two separate buffers (third one points to
1268 ; a different memory region than the first two), allowing for more optimal code for
1269 ; the 16-width case
1270 %macro WRITE_4x4D 10
1271     ; write out (4 dwords per register), start with dwords zero
1272     movd    [%5+%8*4], m%1
1273     movd         [%5], m%2
1274     movd    [%7+%8*4], m%3
1275     movd         [%7], m%4
1276
1277     ; store dwords 1
1278     psrldq        m%1, 4
1279     psrldq        m%2, 4
1280     psrldq        m%3, 4
1281     psrldq        m%4, 4
1282     movd    [%6+%8*4], m%1
1283     movd         [%6], m%2
1284 %if %10 == 16
1285     movd    [%6+%9*4], m%3
1286 %endif
1287     movd      [%7+%9], m%4
1288
1289     ; write dwords 2
1290     psrldq        m%1, 4
1291     psrldq        m%2, 4
1292 %if %10 == 8
1293     movd    [%5+%8*2], m%1
1294     movd           %5, m%3
1295 %endif
1296     psrldq        m%3, 4
1297     psrldq        m%4, 4
1298 %if %10 == 16
1299     movd    [%5+%8*2], m%1
1300 %endif
1301     movd      [%6+%9], m%2
1302     movd    [%7+%8*2], m%3
1303     movd    [%7+%9*2], m%4
1304     add            %7, %9
1305
1306     ; store dwords 3
1307     psrldq        m%1, 4
1308     psrldq        m%2, 4
1309     psrldq        m%3, 4
1310     psrldq        m%4, 4
1311 %if %10 == 8
1312     mov     [%7+%8*4], %5d
1313     movd    [%6+%8*2], m%1
1314 %else
1315     movd      [%5+%8], m%1
1316 %endif
1317     movd    [%6+%9*2], m%2
1318     movd    [%7+%8*2], m%3
1319     movd    [%7+%9*2], m%4
1320 %endmacro
1321
1322 %macro SPLATB_REG 3-4
1323     movd           %1, %2
1324 %ifidn %3, ssse3
1325     pshufb         %1, %4
1326 %else
1327     punpcklbw      %1, %1
1328 %if mmsize == 16 ; sse2
1329     pshuflw        %1, %1, 0x0
1330     punpcklqdq     %1, %1
1331 %elifidn %3, mmx
1332     punpcklwd      %1, %1
1333     punpckldq      %1, %1
1334 %else ; mmxext
1335     pshufw         %1, %1, 0x0
1336 %endif
1337 %endif
1338 %endmacro
1339
1340 %macro SIMPLE_LOOPFILTER 3
1341 cglobal vp8_%2_loop_filter_simple_%1, 3, %3
1342 %ifidn %2, h
1343     mov            r5, rsp          ; backup stack pointer
1344     and           rsp, ~(mmsize-1)  ; align stack
1345 %endif
1346 %if mmsize == 8 ; mmx/mmxext
1347     mov            r3, 2
1348 %endif
1349 %ifidn %1, ssse3
1350     pxor           m0, m0
1351 %endif
1352     SPLATB_REG     m7, r2, %1, m0   ; splat "flim" into register
1353
1354     ; set up indexes to address 4 rows
1355     mov            r2, r1
1356     neg            r1
1357 %ifidn %2, h
1358     lea            r0, [r0+4*r2-2]
1359     sub           rsp, mmsize*2     ; (aligned) storage space for saving p1/q1
1360 %endif
1361
1362 %if mmsize == 8 ; mmx / mmxext
1363 .next8px
1364 %endif
1365 %ifidn %2, v
1366     ; read 4 half/full rows of pixels
1367     mova           m0, [r0+r1*2]    ; p1
1368     mova           m1, [r0+r1]      ; p0
1369     mova           m2, [r0]         ; q0
1370     mova           m3, [r0+r2]      ; q1
1371 %else ; h
1372     lea            r4, [r0+r2]
1373
1374 %if mmsize == 8 ; mmx/mmxext
1375     READ_8x4_INTERLEAVED  0, 1, 2, 3, 4, 5, 6, r0, r4, r1, r2
1376 %else ; sse2
1377     READ_16x4_INTERLEAVED 0, 1, 2, 3, 4, 5, 6, r0, r4, r1, r2, r3
1378 %endif
1379     TRANSPOSE4x4W         0, 1, 2, 3, 4
1380
1381     mova        [rsp], m0           ; store p1
1382     mova [rsp+mmsize], m3           ; store q1
1383 %endif
1384
1385     ; simple_limit
1386     mova           m5, m2           ; m5=backup of q0
1387     mova           m6, m1           ; m6=backup of p0
1388     psubusb        m1, m2           ; p0-q0
1389     psubusb        m2, m6           ; q0-p0
1390     por            m1, m2           ; FFABS(p0-q0)
1391     paddusb        m1, m1           ; m1=FFABS(p0-q0)*2
1392
1393     mova           m4, m3
1394     mova           m2, m0
1395     psubusb        m3, m0           ; q1-p1
1396     psubusb        m0, m4           ; p1-q1
1397     por            m3, m0           ; FFABS(p1-q1)
1398     mova           m0, [pb_80]
1399     pxor           m2, m0
1400     pxor           m4, m0
1401     psubsb         m2, m4           ; m2=p1-q1 (signed) backup for below
1402     pand           m3, [pb_FE]
1403     psrlq          m3, 1            ; m3=FFABS(p1-q1)/2, this can be used signed
1404     paddusb        m3, m1
1405     psubusb        m3, m7
1406     pxor           m1, m1
1407     pcmpeqb        m3, m1           ; abs(p0-q0)*2+abs(p1-q1)/2<=flim mask(0xff/0x0)
1408
1409     ; filter_common (use m2/p1-q1, m4=q0, m6=p0, m5/q0-p0 and m3/mask)
1410     mova           m4, m5
1411     pxor           m5, m0
1412     pxor           m0, m6
1413     psubsb         m5, m0           ; q0-p0 (signed)
1414     paddsb         m2, m5
1415     paddsb         m2, m5
1416     paddsb         m2, m5           ; a=(p1-q1) + 3*(q0-p0)
1417     pand           m2, m3           ; apply filter mask (m3)
1418
1419     mova           m3, [pb_F8]
1420     mova           m1, m2
1421     paddsb         m2, [pb_4]       ; f1<<3=a+4
1422     paddsb         m1, [pb_3]       ; f2<<3=a+3
1423     pand           m2, m3
1424     pand           m1, m3           ; cache f2<<3
1425
1426     pxor           m0, m0
1427     pxor           m3, m3
1428     pcmpgtb        m0, m2           ; which values are <0?
1429     psubb          m3, m2           ; -f1<<3
1430     psrlq          m2, 3            ; +f1
1431     psrlq          m3, 3            ; -f1
1432     pand           m3, m0
1433     pandn          m0, m2
1434     psubusb        m4, m0
1435     paddusb        m4, m3           ; q0-f1
1436
1437     pxor           m0, m0
1438     pxor           m3, m3
1439     pcmpgtb        m0, m1           ; which values are <0?
1440     psubb          m3, m1           ; -f2<<3
1441     psrlq          m1, 3            ; +f2
1442     psrlq          m3, 3            ; -f2
1443     pand           m3, m0
1444     pandn          m0, m1
1445     paddusb        m6, m0
1446     psubusb        m6, m3           ; p0+f2
1447
1448     ; store
1449 %ifidn %2, v
1450     mova         [r0], m4
1451     mova      [r0+r1], m6
1452 %else ; h
1453     mova           m0, [rsp]        ; p1
1454     SWAP            2, 4            ; p0
1455     SWAP            1, 6            ; q0
1456     mova           m3, [rsp+mmsize] ; q1
1457
1458     TRANSPOSE4x4B  0, 1, 2, 3, 4
1459 %if mmsize == 16 ; sse2
1460     add            r3, r1           ; change from r4*8*stride to r0+8*stride
1461     WRITE_4x4D 0, 1, 2, 3, r0, r4, r3, r1, r2, 16
1462 %else ; mmx/mmxext
1463     WRITE_4x2D 0, 1, 2, 3, r0, r4, r1, r2
1464 %endif
1465 %endif
1466
1467 %if mmsize == 8 ; mmx/mmxext
1468     ; next 8 pixels
1469 %ifidn %2, v
1470     add            r0, 8            ; advance 8 cols = pixels
1471 %else ; h
1472     lea            r0, [r0+r2*8]    ; advance 8 rows = lines
1473 %endif
1474     dec            r3
1475     jg .next8px
1476 %ifidn %2, v
1477     REP_RET
1478 %else ; h
1479     mov           rsp, r5           ; restore stack pointer
1480     RET
1481 %endif
1482 %else ; sse2
1483 %ifidn %2, h
1484     mov           rsp, r5           ; restore stack pointer
1485 %endif
1486     RET
1487 %endif
1488 %endmacro
1489
1490 INIT_MMX
1491 SIMPLE_LOOPFILTER mmx,    v, 4
1492 SIMPLE_LOOPFILTER mmx,    h, 6
1493 SIMPLE_LOOPFILTER mmxext, v, 4
1494 SIMPLE_LOOPFILTER mmxext, h, 6
1495 INIT_XMM
1496 SIMPLE_LOOPFILTER sse2,   v, 3
1497 SIMPLE_LOOPFILTER sse2,   h, 6
1498 SIMPLE_LOOPFILTER ssse3,  v, 3
1499 SIMPLE_LOOPFILTER ssse3,  h, 6
1500
1501 ;-----------------------------------------------------------------------------
1502 ; void vp8_h/v_loop_filter<size>_inner_<opt>(uint8_t *dst, [uint8_t *v,] int stride,
1503 ;                                            int flimE, int flimI, int hev_thr);
1504 ;-----------------------------------------------------------------------------
1505
1506 %macro INNER_LOOPFILTER 5
1507 %if %4 == 8 ; chroma
1508 cglobal vp8_%2_loop_filter8uv_inner_%1, 6, %3, %5
1509 %define dst8_reg    r1
1510 %define mstride_reg r2
1511 %define E_reg       r3
1512 %define I_reg       r4
1513 %define hev_thr_reg r5
1514 %else ; luma
1515 cglobal vp8_%2_loop_filter16y_inner_%1, 5, %3, %5
1516 %define mstride_reg r1
1517 %define E_reg       r2
1518 %define I_reg       r3
1519 %define hev_thr_reg r4
1520 %ifdef m8 ; x86-64, sse2
1521 %define dst8_reg    r4
1522 %elif mmsize == 16 ; x86-32, sse2
1523 %define dst8_reg    r5
1524 %else ; x86-32, mmx/mmxext
1525 %define cnt_reg     r5
1526 %endif
1527 %endif
1528 %define dst_reg     r0
1529 %define stride_reg  E_reg
1530 %define dst2_reg    I_reg
1531 %ifndef m8
1532 %define stack_reg   hev_thr_reg
1533 %endif
1534
1535 %ifidn %1, ssse3
1536     pxor             m7, m7
1537 %endif
1538
1539 %ifndef m8 ; mmx/mmxext or sse2 on x86-32
1540     ; splat function arguments
1541     SPLATB_REG       m0, E_reg, %1, m7 ; E
1542     SPLATB_REG       m1, I_reg, %1, m7 ; I
1543     SPLATB_REG       m2, hev_thr_reg, %1, m7 ; hev_thresh
1544
1545     ; align stack
1546     mov       stack_reg, rsp         ; backup stack pointer
1547     and             rsp, ~(mmsize-1) ; align stack
1548 %ifidn %2, v
1549     sub             rsp, mmsize * 4  ; stack layout: [0]=E, [1]=I, [2]=hev_thr
1550                                      ;               [3]=hev() result
1551 %else ; h
1552     sub             rsp, mmsize * 5  ; extra storage space for transposes
1553 %endif
1554
1555 %define flim_E   [rsp]
1556 %define flim_I   [rsp+mmsize]
1557 %define hev_thr  [rsp+mmsize*2]
1558 %define mask_res [rsp+mmsize*3]
1559 %define p0backup [rsp+mmsize*3]
1560 %define q0backup [rsp+mmsize*4]
1561
1562     mova         flim_E, m0
1563     mova         flim_I, m1
1564     mova        hev_thr, m2
1565
1566 %else ; sse2 on x86-64
1567
1568 %define flim_E   m9
1569 %define flim_I   m10
1570 %define hev_thr  m11
1571 %define mask_res m12
1572 %define p0backup m12
1573 %define q0backup m8
1574
1575     ; splat function arguments
1576     SPLATB_REG   flim_E, E_reg, %1, m7 ; E
1577     SPLATB_REG   flim_I, I_reg, %1, m7 ; I
1578     SPLATB_REG  hev_thr, hev_thr_reg, %1, m7 ; hev_thresh
1579 %endif
1580
1581 %if mmsize == 8 && %4 == 16 ; mmx/mmxext
1582     mov         cnt_reg, 2
1583 %endif
1584     mov      stride_reg, mstride_reg
1585     neg     mstride_reg
1586 %ifidn %2, h
1587     lea         dst_reg, [dst_reg + stride_reg*4-4]
1588 %if %4 == 8
1589     lea        dst8_reg, [dst8_reg+ stride_reg*4-4]
1590 %endif
1591 %endif
1592
1593 %if mmsize == 8
1594 .next8px
1595 %endif
1596     ; read
1597     lea        dst2_reg, [dst_reg + stride_reg]
1598 %ifidn %2, v
1599 %if %4 == 8 && mmsize == 16
1600 %define movrow movh
1601 %else
1602 %define movrow mova
1603 %endif
1604     movrow           m0, [dst_reg +mstride_reg*4] ; p3
1605     movrow           m1, [dst2_reg+mstride_reg*4] ; p2
1606     movrow           m2, [dst_reg +mstride_reg*2] ; p1
1607     movrow           m5, [dst2_reg]               ; q1
1608     movrow           m6, [dst2_reg+ stride_reg]   ; q2
1609     movrow           m7, [dst2_reg+ stride_reg*2] ; q3
1610 %if mmsize == 16 && %4 == 8
1611     movhps           m0, [dst8_reg+mstride_reg*4]
1612     movhps           m2, [dst8_reg+mstride_reg*2]
1613     add        dst8_reg, stride_reg
1614     movhps           m1, [dst8_reg+mstride_reg*4]
1615     movhps           m5, [dst8_reg]
1616     movhps           m6, [dst8_reg+ stride_reg]
1617     movhps           m7, [dst8_reg+ stride_reg*2]
1618     add        dst8_reg, mstride_reg
1619 %endif
1620 %elif mmsize == 8 ; mmx/mmxext (h)
1621     ; read 8 rows of 8px each
1622     movu             m0, [dst_reg +mstride_reg*4]
1623     movu             m1, [dst2_reg+mstride_reg*4]
1624     movu             m2, [dst_reg +mstride_reg*2]
1625     movu             m3, [dst_reg +mstride_reg]
1626     movu             m4, [dst_reg]
1627     movu             m5, [dst2_reg]
1628     movu             m6, [dst2_reg+ stride_reg]
1629
1630     ; 8x8 transpose
1631     TRANSPOSE4x4B     0, 1, 2, 3, 7
1632     mova       q0backup, m1
1633     movu             m7, [dst2_reg+ stride_reg*2]
1634     TRANSPOSE4x4B     4, 5, 6, 7, 1
1635     SBUTTERFLY       dq, 0, 4, 1     ; p3/p2
1636     SBUTTERFLY       dq, 2, 6, 1     ; q0/q1
1637     SBUTTERFLY       dq, 3, 7, 1     ; q2/q3
1638     mova             m1, q0backup
1639     mova       q0backup, m2          ; store q0
1640     SBUTTERFLY       dq, 1, 5, 2     ; p1/p0
1641     mova       p0backup, m5          ; store p0
1642     SWAP              1, 4
1643     SWAP              2, 4
1644     SWAP              6, 3
1645     SWAP              5, 3
1646 %else ; sse2 (h)
1647 %if %4 == 16
1648     lea        dst8_reg, [dst_reg + stride_reg*8]
1649 %endif
1650
1651     ; read 16 rows of 8px each, interleave
1652     movh             m0, [dst_reg +mstride_reg*4]
1653     movh             m1, [dst8_reg+mstride_reg*4]
1654     movh             m2, [dst_reg +mstride_reg*2]
1655     movh             m5, [dst8_reg+mstride_reg*2]
1656     movh             m3, [dst_reg +mstride_reg]
1657     movh             m6, [dst8_reg+mstride_reg]
1658     movh             m4, [dst_reg]
1659     movh             m7, [dst8_reg]
1660     punpcklbw        m0, m1          ; A/I
1661     punpcklbw        m2, m5          ; C/K
1662     punpcklbw        m3, m6          ; D/L
1663     punpcklbw        m4, m7          ; E/M
1664
1665     add        dst8_reg, stride_reg
1666     movh             m1, [dst2_reg+mstride_reg*4]
1667     movh             m6, [dst8_reg+mstride_reg*4]
1668     movh             m5, [dst2_reg]
1669     movh             m7, [dst8_reg]
1670     punpcklbw        m1, m6          ; B/J
1671     punpcklbw        m5, m7          ; F/N
1672     movh             m6, [dst2_reg+ stride_reg]
1673     movh             m7, [dst8_reg+ stride_reg]
1674     punpcklbw        m6, m7          ; G/O
1675
1676     ; 8x16 transpose
1677     TRANSPOSE4x4B     0, 1, 2, 3, 7
1678 %ifdef m8
1679     SWAP              1, 8
1680 %else
1681     mova       q0backup, m1
1682 %endif
1683     movh             m7, [dst2_reg+ stride_reg*2]
1684     movh             m1, [dst8_reg+ stride_reg*2]
1685     punpcklbw        m7, m1          ; H/P
1686     TRANSPOSE4x4B     4, 5, 6, 7, 1
1687     SBUTTERFLY       dq, 0, 4, 1     ; p3/p2
1688     SBUTTERFLY       dq, 2, 6, 1     ; q0/q1
1689     SBUTTERFLY       dq, 3, 7, 1     ; q2/q3
1690 %ifdef m8
1691     SWAP              1, 8
1692     SWAP              2, 8
1693 %else
1694     mova             m1, q0backup
1695     mova       q0backup, m2          ; store q0
1696 %endif
1697     SBUTTERFLY       dq, 1, 5, 2     ; p1/p0
1698 %ifdef m12
1699     SWAP              5, 12
1700 %else
1701     mova       p0backup, m5          ; store p0
1702 %endif
1703     SWAP              1, 4
1704     SWAP              2, 4
1705     SWAP              6, 3
1706     SWAP              5, 3
1707 %endif
1708
1709     ; normal_limit for p3-p2, p2-p1, q3-q2 and q2-q1
1710     mova             m4, m1
1711     SWAP              4, 1
1712     psubusb          m4, m0          ; p2-p3
1713     psubusb          m0, m1          ; p3-p2
1714     por              m0, m4          ; abs(p3-p2)
1715
1716     mova             m4, m2
1717     SWAP              4, 2
1718     psubusb          m4, m1          ; p1-p2
1719     psubusb          m1, m2          ; p2-p1
1720     por              m1, m4          ; abs(p2-p1)
1721
1722     mova             m4, m6
1723     SWAP              4, 6
1724     psubusb          m4, m7          ; q2-q3
1725     psubusb          m7, m6          ; q3-q2
1726     por              m7, m4          ; abs(q3-q2)
1727
1728     mova             m4, m5
1729     SWAP              4, 5
1730     psubusb          m4, m6          ; q1-q2
1731     psubusb          m6, m5          ; q2-q1
1732     por              m6, m4          ; abs(q2-q1)
1733
1734 %ifidn %1, mmx
1735     mova             m4, flim_I
1736     pxor             m3, m3
1737     psubusb          m0, m4
1738     psubusb          m1, m4
1739     psubusb          m7, m4
1740     psubusb          m6, m4
1741     pcmpeqb          m0, m3          ; abs(p3-p2) <= I
1742     pcmpeqb          m1, m3          ; abs(p2-p1) <= I
1743     pcmpeqb          m7, m3          ; abs(q3-q2) <= I
1744     pcmpeqb          m6, m3          ; abs(q2-q1) <= I
1745     pand             m0, m1
1746     pand             m7, m6
1747     pand             m0, m7
1748 %else ; mmxext/sse2
1749     pmaxub           m0, m1
1750     pmaxub           m6, m7
1751     pmaxub           m0, m6
1752 %endif
1753
1754     ; normal_limit and high_edge_variance for p1-p0, q1-q0
1755     SWAP              7, 3           ; now m7 is zero
1756 %ifidn %2, v
1757     movrow           m3, [dst_reg +mstride_reg] ; p0
1758 %if mmsize == 16 && %4 == 8
1759     movhps           m3, [dst8_reg+mstride_reg]
1760 %endif
1761 %elifdef m12
1762     SWAP              3, 12
1763 %else
1764     mova             m3, p0backup
1765 %endif
1766
1767     mova             m1, m2
1768     SWAP              1, 2
1769     mova             m6, m3
1770     SWAP              3, 6
1771     psubusb          m1, m3          ; p1-p0
1772     psubusb          m6, m2          ; p0-p1
1773     por              m1, m6          ; abs(p1-p0)
1774 %ifidn %1, mmx
1775     mova             m6, m1
1776     psubusb          m1, m4
1777     psubusb          m6, hev_thr
1778     pcmpeqb          m1, m7          ; abs(p1-p0) <= I
1779     pcmpeqb          m6, m7          ; abs(p1-p0) <= hev_thresh
1780     pand             m0, m1
1781     mova       mask_res, m6
1782 %else ; mmxext/sse2
1783     pmaxub           m0, m1          ; max_I
1784     SWAP              1, 4           ; max_hev_thresh
1785 %endif
1786
1787     SWAP              6, 4           ; now m6 is I
1788 %ifidn %2, v
1789     movrow           m4, [dst_reg]   ; q0
1790 %if mmsize == 16 && %4 == 8
1791     movhps           m4, [dst8_reg]
1792 %endif
1793 %elifdef m8
1794     SWAP              4, 8
1795 %else
1796     mova             m4, q0backup
1797 %endif
1798     mova             m1, m4
1799     SWAP              1, 4
1800     mova             m7, m5
1801     SWAP              7, 5
1802     psubusb          m1, m5          ; q0-q1
1803     psubusb          m7, m4          ; q1-q0
1804     por              m1, m7          ; abs(q1-q0)
1805 %ifidn %1, mmx
1806     mova             m7, m1
1807     psubusb          m1, m6
1808     psubusb          m7, hev_thr
1809     pxor             m6, m6
1810     pcmpeqb          m1, m6          ; abs(q1-q0) <= I
1811     pcmpeqb          m7, m6          ; abs(q1-q0) <= hev_thresh
1812     mova             m6, mask_res
1813     pand             m0, m1          ; abs([pq][321]-[pq][210]) <= I
1814     pand             m6, m7
1815 %else ; mmxext/sse2
1816     pxor             m7, m7
1817     pmaxub           m0, m1
1818     pmaxub           m6, m1
1819     psubusb          m0, flim_I
1820     psubusb          m6, hev_thr
1821     pcmpeqb          m0, m7          ; max(abs(..)) <= I
1822     pcmpeqb          m6, m7          ; !(max(abs..) > thresh)
1823 %endif
1824 %ifdef m12
1825     SWAP              6, 12
1826 %else
1827     mova       mask_res, m6          ; !(abs(p1-p0) > hev_t || abs(q1-q0) > hev_t)
1828 %endif
1829
1830     ; simple_limit
1831     mova             m1, m3
1832     SWAP              1, 3
1833     mova             m6, m4          ; keep copies of p0/q0 around for later use
1834     SWAP              6, 4
1835     psubusb          m1, m4          ; p0-q0
1836     psubusb          m6, m3          ; q0-p0
1837     por              m1, m6          ; abs(q0-p0)
1838     paddusb          m1, m1          ; m1=2*abs(q0-p0)
1839
1840     mova             m7, m2
1841     SWAP              7, 2
1842     mova             m6, m5
1843     SWAP              6, 5
1844     psubusb          m7, m5          ; p1-q1
1845     psubusb          m6, m2          ; q1-p1
1846     por              m7, m6          ; abs(q1-p1)
1847     pxor             m6, m6
1848     pand             m7, [pb_FE]
1849     psrlq            m7, 1           ; abs(q1-p1)/2
1850     paddusb          m7, m1          ; abs(q0-p0)*2+abs(q1-p1)/2
1851     psubusb          m7, flim_E
1852     pcmpeqb          m7, m6          ; abs(q0-p0)*2+abs(q1-p1)/2 <= E
1853     pand             m0, m7          ; normal_limit result
1854
1855     ; filter_common; at this point, m2-m5=p1-q1 and m0 is filter_mask
1856 %ifdef m8 ; x86-64 && sse2
1857     mova             m8, [pb_80]
1858 %define pb_80_var m8
1859 %else ; x86-32 or mmx/mmxext
1860 %define pb_80_var [pb_80]
1861 %endif
1862     mova             m1, m4
1863     mova             m7, m3
1864     pxor             m1, pb_80_var
1865     pxor             m7, pb_80_var
1866     psubsb           m1, m7          ; (signed) q0-p0
1867     mova             m6, m2
1868     mova             m7, m5
1869     pxor             m6, pb_80_var
1870     pxor             m7, pb_80_var
1871     psubsb           m6, m7          ; (signed) p1-q1
1872     mova             m7, mask_res
1873     pandn            m7, m6
1874     paddsb           m7, m1
1875     paddsb           m7, m1
1876     paddsb           m7, m1          ; 3*(q0-p0)+is4tap?(p1-q1)
1877
1878     pand             m7, m0
1879     mova             m1, [pb_F8]
1880     mova             m6, m7
1881     paddsb           m7, [pb_3]
1882     paddsb           m6, [pb_4]
1883     pand             m7, m1
1884     pand             m6, m1
1885
1886     pxor             m1, m1
1887     pxor             m0, m0
1888     pcmpgtb          m1, m7
1889     psubb            m0, m7
1890     psrlq            m7, 3           ; +f2
1891     psrlq            m0, 3           ; -f2
1892     pand             m0, m1
1893     pandn            m1, m7
1894     psubusb          m3, m0
1895     paddusb          m3, m1          ; p0+f2
1896
1897     pxor             m1, m1
1898     pxor             m0, m0
1899     pcmpgtb          m0, m6
1900     psubb            m1, m6
1901     psrlq            m6, 3           ; +f1
1902     psrlq            m1, 3           ; -f1
1903     pand             m1, m0
1904     pandn            m0, m6
1905     psubusb          m4, m0
1906     paddusb          m4, m1          ; q0-f1
1907
1908 %ifdef m12
1909     SWAP              6, 12
1910 %else
1911     mova             m6, mask_res
1912 %endif
1913 %ifidn %1, mmx
1914     mova             m7, [pb_1]
1915 %else ; mmxext/sse2
1916     pxor             m7, m7
1917 %endif
1918     pand             m0, m6
1919     pand             m1, m6
1920 %ifidn %1, mmx
1921     paddusb          m0, m7
1922     pand             m1, [pb_FE]
1923     pandn            m7, m0
1924     psrlq            m1, 1
1925     psrlq            m7, 1
1926     SWAP              0, 7
1927 %else ; mmxext/sse2
1928     psubusb          m1, [pb_1]
1929     pavgb            m0, m7          ; a
1930     pavgb            m1, m7          ; -a
1931 %endif
1932     psubusb          m5, m0
1933     psubusb          m2, m1
1934     paddusb          m5, m1          ; q1-a
1935     paddusb          m2, m0          ; p1+a
1936
1937     ; store
1938 %ifidn %2, v
1939     movrow [dst_reg +mstride_reg*2], m2
1940     movrow [dst_reg +mstride_reg  ], m3
1941     movrow    [dst_reg], m4
1942     movrow [dst_reg + stride_reg  ], m5
1943 %if mmsize == 16 && %4 == 8
1944     movhps [dst8_reg+mstride_reg*2], m2
1945     movhps [dst8_reg+mstride_reg  ], m3
1946     movhps   [dst8_reg], m4
1947     movhps [dst8_reg+ stride_reg  ], m5
1948 %endif
1949 %else ; h
1950     add         dst_reg, 2
1951     add        dst2_reg, 2
1952
1953     ; 4x8/16 transpose
1954     TRANSPOSE4x4B     2, 3, 4, 5, 6
1955
1956 %if mmsize == 8 ; mmx/mmxext (h)
1957     WRITE_4x2D        2, 3, 4, 5, dst_reg, dst2_reg, mstride_reg, stride_reg
1958 %else ; sse2 (h)
1959     lea        dst8_reg, [dst8_reg+mstride_reg+2]
1960     WRITE_4x4D        2, 3, 4, 5, dst_reg, dst2_reg, dst8_reg, mstride_reg, stride_reg, %4
1961 %endif
1962 %endif
1963
1964 %if mmsize == 8
1965 %if %4 == 8 ; chroma
1966 %ifidn %2, h
1967     sub         dst_reg, 2
1968 %endif
1969     cmp         dst_reg, dst8_reg
1970     mov         dst_reg, dst8_reg
1971     jnz .next8px
1972 %else
1973 %ifidn %2, h
1974     lea         dst_reg, [dst_reg + stride_reg*8-2]
1975 %else ; v
1976     add         dst_reg, 8
1977 %endif
1978     dec         cnt_reg
1979     jg .next8px
1980 %endif
1981 %endif
1982
1983 %ifndef m8 ; sse2 on x86-32 or mmx/mmxext
1984     mov             rsp, stack_reg   ; restore stack pointer
1985 %endif
1986     RET
1987 %endmacro
1988
1989 INIT_MMX
1990 INNER_LOOPFILTER mmx,    v, 6, 16, 0
1991 INNER_LOOPFILTER mmx,    h, 6, 16, 0
1992 INNER_LOOPFILTER mmxext, v, 6, 16, 0
1993 INNER_LOOPFILTER mmxext, h, 6, 16, 0
1994
1995 INNER_LOOPFILTER mmx,    v, 6,  8, 0
1996 INNER_LOOPFILTER mmx,    h, 6,  8, 0
1997 INNER_LOOPFILTER mmxext, v, 6,  8, 0
1998 INNER_LOOPFILTER mmxext, h, 6,  8, 0
1999
2000 INIT_XMM
2001 INNER_LOOPFILTER sse2,   v, 5, 16, 13
2002 %ifdef m8
2003 INNER_LOOPFILTER sse2,   h, 5, 16, 13
2004 %else
2005 INNER_LOOPFILTER sse2,   h, 6, 16, 13
2006 %endif
2007 INNER_LOOPFILTER sse2,   v, 6,  8, 13
2008 INNER_LOOPFILTER sse2,   h, 6,  8, 13
2009
2010 INNER_LOOPFILTER ssse3,  v, 5, 16, 13
2011 %ifdef m8
2012 INNER_LOOPFILTER ssse3,  h, 5, 16, 13
2013 %else
2014 INNER_LOOPFILTER ssse3,  h, 6, 16, 13
2015 %endif
2016 INNER_LOOPFILTER ssse3,  v, 6,  8, 13
2017 INNER_LOOPFILTER ssse3,  h, 6,  8, 13
2018
2019 ;-----------------------------------------------------------------------------
2020 ; void vp8_h/v_loop_filter<size>_mbedge_<opt>(uint8_t *dst, [uint8_t *v,] int stride,
2021 ;                                            int flimE, int flimI, int hev_thr);
2022 ;-----------------------------------------------------------------------------
2023
2024 ; write 4 or 8 words in the mmx/xmm registers as 8 lines
2025 ; 1 and 2 are the registers to write, this can be the same (for SSE2)
2026 ; for pre-SSE4:
2027 ; 3 is a general-purpose register that we will clobber
2028 ; for SSE4:
2029 ; 3 is a pointer to the destination's 5th line
2030 ; 4 is a pointer to the destination's 4th line
2031 ; 5/6 is -stride and +stride
2032 ; 7 is optimization string
2033 %macro WRITE_8W 7
2034 %ifidn %7, sse4
2035     pextrw    [%4+%5*4], %1, 0
2036     pextrw    [%3+%5*4], %1, 1
2037     pextrw    [%4+%5*2], %1, 2
2038     pextrw    [%4+%5  ], %1, 3
2039     pextrw    [%4     ], %1, 4
2040     pextrw    [%3     ], %1, 5
2041     pextrw    [%3+%6  ], %1, 6
2042     pextrw    [%3+%6*2], %1, 7
2043 %else
2044     movd             %3, %1
2045 %if mmsize == 8
2046     punpckhdq        %1, %1
2047 %else
2048     psrldq           %1, 4
2049 %endif
2050     mov       [%4+%5*4], %3w
2051     shr              %3, 16
2052     add              %4, %6
2053     mov       [%4+%5*4], %3w
2054
2055     movd             %3, %1
2056 %if mmsize == 16
2057     psrldq           %1, 4
2058 %endif
2059     add              %4, %5
2060     mov       [%4+%5*2], %3w
2061     shr              %3, 16
2062     mov       [%4+%5  ], %3w
2063
2064     movd             %3, %2
2065 %if mmsize == 8
2066     punpckhdq        %2, %2
2067 %else
2068     psrldq           %2, 4
2069 %endif
2070     mov       [%4     ], %3w
2071     shr              %3, 16
2072     mov       [%4+%6  ], %3w
2073
2074     movd             %3, %2
2075     add              %4, %6
2076     mov       [%4+%6  ], %3w
2077     shr              %3, 16
2078     mov       [%4+%6*2], %3w
2079 %if mmsize == 8
2080     add              %4, %5
2081 %endif
2082 %endif
2083 %endmacro
2084
2085 %macro MBEDGE_LOOPFILTER 5
2086 %if %4 == 8 ; chroma
2087 cglobal vp8_%2_loop_filter8uv_mbedge_%1, 6, %3, %5
2088 %define dst8_reg    r1
2089 %define mstride_reg r2
2090 %define E_reg       r3
2091 %define I_reg       r4
2092 %define hev_thr_reg r5
2093 %else ; luma
2094 cglobal vp8_%2_loop_filter16y_mbedge_%1, 5, %3, %5
2095 %define mstride_reg r1
2096 %define E_reg       r2
2097 %define I_reg       r3
2098 %define hev_thr_reg r4
2099 %ifdef m8 ; x86-64, sse2
2100 %define dst8_reg    r4
2101 %elif mmsize == 16 ; x86-32, sse2
2102 %define dst8_reg    r5
2103 %else ; x86-32, mmx/mmxext
2104 %define cnt_reg     r5
2105 %endif
2106 %endif
2107 %define dst_reg     r0
2108 %define stride_reg  E_reg
2109 %define dst2_reg    I_reg
2110 %ifndef m8
2111 %define stack_reg   hev_thr_reg
2112 %endif
2113
2114 %ifidn %1, ssse3
2115     pxor             m7, m7
2116 %endif
2117
2118 %ifndef m8 ; mmx/mmxext or sse2 on x86-32
2119     ; splat function arguments
2120     SPLATB_REG       m0, E_reg, %1, m7 ; E
2121     SPLATB_REG       m1, I_reg, %1, m7 ; I
2122     SPLATB_REG       m2, hev_thr_reg, %1, m7 ; hev_thresh
2123
2124     ; align stack
2125     mov       stack_reg, rsp         ; backup stack pointer
2126     and             rsp, ~(mmsize-1) ; align stack
2127     sub             rsp, mmsize * 8  ; stack layout: [0]=E, [1]=I, [2]=hev_thr
2128                                      ;               [3]=hev() result
2129                                      ;               [4]=filter tmp result
2130                                      ;               [5]/[6] = p2/q2 backup
2131                                      ;               [7]=lim_res sign result
2132
2133 %define flim_E   [rsp]
2134 %define flim_I   [rsp+mmsize]
2135 %define hev_thr  [rsp+mmsize*2]
2136 %define mask_res [rsp+mmsize*3]
2137 %define lim_res  [rsp+mmsize*4]
2138 %define p0backup [rsp+mmsize*3]
2139 %define q0backup [rsp+mmsize*4]
2140 %define p2backup [rsp+mmsize*5]
2141 %define q2backup [rsp+mmsize*6]
2142 %define lim_sign [rsp+mmsize*7]
2143
2144     mova         flim_E, m0
2145     mova         flim_I, m1
2146     mova        hev_thr, m2
2147
2148 %else ; sse2 on x86-64
2149
2150 %define flim_E   m9
2151 %define flim_I   m10
2152 %define hev_thr  m11
2153 %define mask_res m12
2154 %define lim_res  m8
2155 %define p0backup m12
2156 %define q0backup m8
2157 %define p2backup m13
2158 %define q2backup m14
2159 %define lim_sign m15
2160
2161     ; splat function arguments
2162     SPLATB_REG   flim_E, E_reg, %1, m7 ; E
2163     SPLATB_REG   flim_I, I_reg, %1, m7 ; I
2164     SPLATB_REG  hev_thr, hev_thr_reg, %1, m7 ; hev_thresh
2165 %endif
2166
2167 %if mmsize == 8 && %4 == 16 ; mmx/mmxext
2168     mov         cnt_reg, 2
2169 %endif
2170     mov      stride_reg, mstride_reg
2171     neg     mstride_reg
2172 %ifidn %2, h
2173     lea         dst_reg, [dst_reg + stride_reg*4-4]
2174 %if %4 == 8
2175     lea        dst8_reg, [dst8_reg+ stride_reg*4-4]
2176 %endif
2177 %endif
2178
2179 %if mmsize == 8
2180 .next8px
2181 %endif
2182     ; read
2183     lea        dst2_reg, [dst_reg + stride_reg]
2184 %ifidn %2, v
2185 %if %4 == 8 && mmsize == 16
2186 %define movrow movh
2187 %else
2188 %define movrow mova
2189 %endif
2190     movrow           m0, [dst_reg +mstride_reg*4] ; p3
2191     movrow           m1, [dst2_reg+mstride_reg*4] ; p2
2192     movrow           m2, [dst_reg +mstride_reg*2] ; p1
2193     movrow           m5, [dst2_reg]               ; q1
2194     movrow           m6, [dst2_reg+ stride_reg]   ; q2
2195     movrow           m7, [dst2_reg+ stride_reg*2] ; q3
2196 %if mmsize == 16 && %4 == 8
2197     movhps           m0, [dst8_reg+mstride_reg*4]
2198     movhps           m2, [dst8_reg+mstride_reg*2]
2199     add        dst8_reg, stride_reg
2200     movhps           m1, [dst8_reg+mstride_reg*4]
2201     movhps           m5, [dst8_reg]
2202     movhps           m6, [dst8_reg+ stride_reg]
2203     movhps           m7, [dst8_reg+ stride_reg*2]
2204     add        dst8_reg, mstride_reg
2205 %endif
2206 %elif mmsize == 8 ; mmx/mmxext (h)
2207     ; read 8 rows of 8px each
2208     movu             m0, [dst_reg +mstride_reg*4]
2209     movu             m1, [dst2_reg+mstride_reg*4]
2210     movu             m2, [dst_reg +mstride_reg*2]
2211     movu             m3, [dst_reg +mstride_reg]
2212     movu             m4, [dst_reg]
2213     movu             m5, [dst2_reg]
2214     movu             m6, [dst2_reg+ stride_reg]
2215
2216     ; 8x8 transpose
2217     TRANSPOSE4x4B     0, 1, 2, 3, 7
2218     mova       q0backup, m1
2219     movu             m7, [dst2_reg+ stride_reg*2]
2220     TRANSPOSE4x4B     4, 5, 6, 7, 1
2221     SBUTTERFLY       dq, 0, 4, 1     ; p3/p2
2222     SBUTTERFLY       dq, 2, 6, 1     ; q0/q1
2223     SBUTTERFLY       dq, 3, 7, 1     ; q2/q3
2224     mova             m1, q0backup
2225     mova       q0backup, m2          ; store q0
2226     SBUTTERFLY       dq, 1, 5, 2     ; p1/p0
2227     mova       p0backup, m5          ; store p0
2228     SWAP              1, 4
2229     SWAP              2, 4
2230     SWAP              6, 3
2231     SWAP              5, 3
2232 %else ; sse2 (h)
2233 %if %4 == 16
2234     lea        dst8_reg, [dst_reg + stride_reg*8]
2235 %endif
2236
2237     ; read 16 rows of 8px each, interleave
2238     movh             m0, [dst_reg +mstride_reg*4]
2239     movh             m1, [dst8_reg+mstride_reg*4]
2240     movh             m2, [dst_reg +mstride_reg*2]
2241     movh             m5, [dst8_reg+mstride_reg*2]
2242     movh             m3, [dst_reg +mstride_reg]
2243     movh             m6, [dst8_reg+mstride_reg]
2244     movh             m4, [dst_reg]
2245     movh             m7, [dst8_reg]
2246     punpcklbw        m0, m1          ; A/I
2247     punpcklbw        m2, m5          ; C/K
2248     punpcklbw        m3, m6          ; D/L
2249     punpcklbw        m4, m7          ; E/M
2250
2251     add        dst8_reg, stride_reg
2252     movh             m1, [dst2_reg+mstride_reg*4]
2253     movh             m6, [dst8_reg+mstride_reg*4]
2254     movh             m5, [dst2_reg]
2255     movh             m7, [dst8_reg]
2256     punpcklbw        m1, m6          ; B/J
2257     punpcklbw        m5, m7          ; F/N
2258     movh             m6, [dst2_reg+ stride_reg]
2259     movh             m7, [dst8_reg+ stride_reg]
2260     punpcklbw        m6, m7          ; G/O
2261
2262     ; 8x16 transpose
2263     TRANSPOSE4x4B     0, 1, 2, 3, 7
2264 %ifdef m8
2265     SWAP              1, 8
2266 %else
2267     mova       q0backup, m1
2268 %endif
2269     movh             m7, [dst2_reg+ stride_reg*2]
2270     movh             m1, [dst8_reg+ stride_reg*2]
2271     punpcklbw        m7, m1          ; H/P
2272     TRANSPOSE4x4B     4, 5, 6, 7, 1
2273     SBUTTERFLY       dq, 0, 4, 1     ; p3/p2
2274     SBUTTERFLY       dq, 2, 6, 1     ; q0/q1
2275     SBUTTERFLY       dq, 3, 7, 1     ; q2/q3
2276 %ifdef m8
2277     SWAP              1, 8
2278     SWAP              2, 8
2279 %else
2280     mova             m1, q0backup
2281     mova       q0backup, m2          ; store q0
2282 %endif
2283     SBUTTERFLY       dq, 1, 5, 2     ; p1/p0
2284 %ifdef m12
2285     SWAP              5, 12
2286 %else
2287     mova       p0backup, m5          ; store p0
2288 %endif
2289     SWAP              1, 4
2290     SWAP              2, 4
2291     SWAP              6, 3
2292     SWAP              5, 3
2293 %endif
2294
2295     ; normal_limit for p3-p2, p2-p1, q3-q2 and q2-q1
2296     mova             m4, m1
2297     SWAP              4, 1
2298     psubusb          m4, m0          ; p2-p3
2299     psubusb          m0, m1          ; p3-p2
2300     por              m0, m4          ; abs(p3-p2)
2301
2302     mova             m4, m2
2303     SWAP              4, 2
2304     psubusb          m4, m1          ; p1-p2
2305     mova       p2backup, m1
2306     psubusb          m1, m2          ; p2-p1
2307     por              m1, m4          ; abs(p2-p1)
2308
2309     mova             m4, m6
2310     SWAP              4, 6
2311     psubusb          m4, m7          ; q2-q3
2312     psubusb          m7, m6          ; q3-q2
2313     por              m7, m4          ; abs(q3-q2)
2314
2315     mova             m4, m5
2316     SWAP              4, 5
2317     psubusb          m4, m6          ; q1-q2
2318     mova       q2backup, m6
2319     psubusb          m6, m5          ; q2-q1
2320     por              m6, m4          ; abs(q2-q1)
2321
2322 %ifidn %1, mmx
2323     mova             m4, flim_I
2324     pxor             m3, m3
2325     psubusb          m0, m4
2326     psubusb          m1, m4
2327     psubusb          m7, m4
2328     psubusb          m6, m4
2329     pcmpeqb          m0, m3          ; abs(p3-p2) <= I
2330     pcmpeqb          m1, m3          ; abs(p2-p1) <= I
2331     pcmpeqb          m7, m3          ; abs(q3-q2) <= I
2332     pcmpeqb          m6, m3          ; abs(q2-q1) <= I
2333     pand             m0, m1
2334     pand             m7, m6
2335     pand             m0, m7
2336 %else ; mmxext/sse2
2337     pmaxub           m0, m1
2338     pmaxub           m6, m7
2339     pmaxub           m0, m6
2340 %endif
2341
2342     ; normal_limit and high_edge_variance for p1-p0, q1-q0
2343     SWAP              7, 3           ; now m7 is zero
2344 %ifidn %2, v
2345     movrow           m3, [dst_reg +mstride_reg] ; p0
2346 %if mmsize == 16 && %4 == 8
2347     movhps           m3, [dst8_reg+mstride_reg]
2348 %endif
2349 %elifdef m12
2350     SWAP              3, 12
2351 %else
2352     mova             m3, p0backup
2353 %endif
2354
2355     mova             m1, m2
2356     SWAP              1, 2
2357     mova             m6, m3
2358     SWAP              3, 6
2359     psubusb          m1, m3          ; p1-p0
2360     psubusb          m6, m2          ; p0-p1
2361     por              m1, m6          ; abs(p1-p0)
2362 %ifidn %1, mmx
2363     mova             m6, m1
2364     psubusb          m1, m4
2365     psubusb          m6, hev_thr
2366     pcmpeqb          m1, m7          ; abs(p1-p0) <= I
2367     pcmpeqb          m6, m7          ; abs(p1-p0) <= hev_thresh
2368     pand             m0, m1
2369     mova       mask_res, m6
2370 %else ; mmxext/sse2
2371     pmaxub           m0, m1          ; max_I
2372     SWAP              1, 4           ; max_hev_thresh
2373 %endif
2374
2375     SWAP              6, 4           ; now m6 is I
2376 %ifidn %2, v
2377     movrow           m4, [dst_reg]   ; q0
2378 %if mmsize == 16 && %4 == 8
2379     movhps           m4, [dst8_reg]
2380 %endif
2381 %elifdef m8
2382     SWAP              4, 8
2383 %else
2384     mova             m4, q0backup
2385 %endif
2386     mova             m1, m4
2387     SWAP              1, 4
2388     mova             m7, m5
2389     SWAP              7, 5
2390     psubusb          m1, m5          ; q0-q1
2391     psubusb          m7, m4          ; q1-q0
2392     por              m1, m7          ; abs(q1-q0)
2393 %ifidn %1, mmx
2394     mova             m7, m1
2395     psubusb          m1, m6
2396     psubusb          m7, hev_thr
2397     pxor             m6, m6
2398     pcmpeqb          m1, m6          ; abs(q1-q0) <= I
2399     pcmpeqb          m7, m6          ; abs(q1-q0) <= hev_thresh
2400     mova             m6, mask_res
2401     pand             m0, m1          ; abs([pq][321]-[pq][210]) <= I
2402     pand             m6, m7
2403 %else ; mmxext/sse2
2404     pxor             m7, m7
2405     pmaxub           m0, m1
2406     pmaxub           m6, m1
2407     psubusb          m0, flim_I
2408     psubusb          m6, hev_thr
2409     pcmpeqb          m0, m7          ; max(abs(..)) <= I
2410     pcmpeqb          m6, m7          ; !(max(abs..) > thresh)
2411 %endif
2412 %ifdef m12
2413     SWAP              6, 12
2414 %else
2415     mova       mask_res, m6          ; !(abs(p1-p0) > hev_t || abs(q1-q0) > hev_t)
2416 %endif
2417
2418     ; simple_limit
2419     mova             m1, m3
2420     SWAP              1, 3
2421     mova             m6, m4          ; keep copies of p0/q0 around for later use
2422     SWAP              6, 4
2423     psubusb          m1, m4          ; p0-q0
2424     psubusb          m6, m3          ; q0-p0
2425     por              m1, m6          ; abs(q0-p0)
2426     paddusb          m1, m1          ; m1=2*abs(q0-p0)
2427
2428     mova             m7, m2
2429     SWAP              7, 2
2430     mova             m6, m5
2431     SWAP              6, 5
2432     psubusb          m7, m5          ; p1-q1
2433     psubusb          m6, m2          ; q1-p1
2434     por              m7, m6          ; abs(q1-p1)
2435     pxor             m6, m6
2436     pand             m7, [pb_FE]
2437     psrlq            m7, 1           ; abs(q1-p1)/2
2438     paddusb          m7, m1          ; abs(q0-p0)*2+abs(q1-p1)/2
2439     psubusb          m7, flim_E
2440     pcmpeqb          m7, m6          ; abs(q0-p0)*2+abs(q1-p1)/2 <= E
2441     pand             m0, m7          ; normal_limit result
2442
2443     ; filter_common; at this point, m2-m5=p1-q1 and m0 is filter_mask
2444 %ifdef m8 ; x86-64 && sse2
2445     mova             m8, [pb_80]
2446 %define pb_80_var m8
2447 %else ; x86-32 or mmx/mmxext
2448 %define pb_80_var [pb_80]
2449 %endif
2450     mova             m1, m4
2451     mova             m7, m3
2452     pxor             m1, pb_80_var
2453     pxor             m7, pb_80_var
2454     psubsb           m1, m7          ; (signed) q0-p0
2455     mova             m6, m2
2456     mova             m7, m5
2457     pxor             m6, pb_80_var
2458     pxor             m7, pb_80_var
2459     psubsb           m6, m7          ; (signed) p1-q1
2460     mova             m7, mask_res
2461     paddsb           m6, m1
2462     paddsb           m6, m1
2463     paddsb           m6, m1
2464     pand             m6, m0
2465 %ifdef m8
2466     mova        lim_res, m6          ; 3*(qp-p0)+(p1-q1) masked for filter_mbedge
2467     pand        lim_res, m7
2468 %else
2469     mova             m0, m6
2470     pand             m0, m7
2471     mova        lim_res, m0
2472 %endif
2473     pandn            m7, m6          ; 3*(q0-p0)+(p1-q1) masked for filter_common
2474
2475     mova             m1, [pb_F8]
2476     mova             m6, m7
2477     paddsb           m7, [pb_3]
2478     paddsb           m6, [pb_4]
2479     pand             m7, m1
2480     pand             m6, m1
2481
2482     pxor             m1, m1
2483     pxor             m0, m0
2484     pcmpgtb          m1, m7
2485     psubb            m0, m7
2486     psrlq            m7, 3           ; +f2
2487     psrlq            m0, 3           ; -f2
2488     pand             m0, m1
2489     pandn            m1, m7
2490     psubusb          m3, m0
2491     paddusb          m3, m1          ; p0+f2
2492
2493     pxor             m1, m1
2494     pxor             m0, m0
2495     pcmpgtb          m0, m6
2496     psubb            m1, m6
2497     psrlq            m6, 3           ; +f1
2498     psrlq            m1, 3           ; -f1
2499     pand             m1, m0
2500     pandn            m0, m6
2501     psubusb          m4, m0
2502     paddusb          m4, m1          ; q0-f1
2503
2504     ; filter_mbedge (m2-m5 = p1-q1; lim_res carries w)
2505     mova             m7, [pw_63]
2506 %ifdef m8
2507     SWAP              1, 8
2508 %else
2509     mova             m1, lim_res
2510 %endif
2511     pxor             m0, m0
2512     mova             m6, m1
2513     pcmpgtb          m0, m1         ; which are negative
2514     punpcklbw        m6, m0         ; signed byte->word
2515     punpckhbw        m1, m0
2516     mova       lim_sign, m0
2517     mova       mask_res, m6         ; backup for later in filter
2518     mova        lim_res, m1
2519     pmullw          m6, [pw_27]
2520     pmullw          m1, [pw_27]
2521     paddw           m6, m7
2522     paddw           m1, m7
2523     psraw           m6, 7
2524     psraw           m1, 7
2525     packsswb        m6, m1          ; a0
2526     pxor            m1, m1
2527     psubb           m1, m6
2528     pand            m1, m0          ; -a0
2529     pandn           m0, m6          ; +a0
2530     psubusb         m3, m1
2531     paddusb         m4, m1
2532     paddusb         m3, m0          ; p0+a0
2533     psubusb         m4, m0          ; q0-a0
2534
2535     mova            m6, mask_res
2536     mova            m1, lim_res
2537     mova            m0, lim_sign
2538     pmullw          m6, [pw_18]
2539     pmullw          m1, [pw_18]
2540     paddw           m6, m7
2541     paddw           m1, m7
2542     psraw           m6, 7
2543     psraw           m1, 7
2544     packsswb        m6, m1          ; a1
2545     pxor            m1, m1
2546     psubb           m1, m6
2547     pand            m1, m0          ; -a1
2548     pandn           m0, m6          ; +a1
2549     psubusb         m2, m1
2550     paddusb         m5, m1
2551     paddusb         m2, m0          ; p1+a1
2552     psubusb         m5, m0          ; q1-a1
2553
2554 %ifdef m8
2555     SWAP             6, 12
2556     SWAP             1, 8
2557 %else
2558     mova            m6, mask_res
2559     mova            m1, lim_res
2560 %endif
2561     pmullw          m6, [pw_9]
2562     pmullw          m1, [pw_9]
2563     paddw           m6, m7
2564     paddw           m1, m7
2565 %ifdef m15
2566     SWAP             7, 15
2567 %else
2568     mova            m7, lim_sign
2569 %endif
2570     psraw           m6, 7
2571     psraw           m1, 7
2572     packsswb        m6, m1          ; a1
2573     pxor            m0, m0
2574     psubb           m0, m6
2575     pand            m0, m7          ; -a1
2576     pandn           m7, m6          ; +a1
2577 %ifdef m8
2578     SWAP             1, 13
2579     SWAP             6, 14
2580 %else
2581     mova            m1, p2backup
2582     mova            m6, q2backup
2583 %endif
2584     psubusb         m1, m0
2585     paddusb         m6, m0
2586     paddusb         m1, m7          ; p1+a1
2587     psubusb         m6, m7          ; q1-a1
2588
2589     ; store
2590 %ifidn %2, v
2591     movrow [dst2_reg+mstride_reg*4], m1
2592     movrow [dst_reg +mstride_reg*2], m2
2593     movrow [dst_reg +mstride_reg  ], m3
2594     movrow    [dst_reg], m4
2595     movrow   [dst2_reg], m5
2596     movrow [dst2_reg+ stride_reg  ], m6
2597 %if mmsize == 16 && %4 == 8
2598     add        dst8_reg, mstride_reg
2599     movhps [dst8_reg+mstride_reg*2], m1
2600     movhps [dst8_reg+mstride_reg  ], m2
2601     movhps   [dst8_reg], m3
2602     add        dst8_reg, stride_reg
2603     movhps   [dst8_reg], m4
2604     movhps [dst8_reg+ stride_reg  ], m5
2605     movhps [dst8_reg+ stride_reg*2], m6
2606 %endif
2607 %else ; h
2608     inc         dst_reg
2609     inc        dst2_reg
2610
2611     ; 4x8/16 transpose
2612     TRANSPOSE4x4B     1, 2, 3, 4, 0
2613     SBUTTERFLY       bw, 5, 6, 0
2614
2615 %if mmsize == 8 ; mmx/mmxext (h)
2616     WRITE_4x2D        1, 2, 3, 4, dst_reg, dst2_reg, mstride_reg, stride_reg
2617     add         dst_reg, 4
2618     WRITE_8W         m5, m6, dst2_reg, dst_reg, mstride_reg, stride_reg, %4
2619 %else ; sse2 (h)
2620     lea        dst8_reg, [dst8_reg+mstride_reg+1]
2621     WRITE_4x4D        1, 2, 3, 4, dst_reg, dst2_reg, dst8_reg, mstride_reg, stride_reg, %4
2622     lea         dst_reg, [dst2_reg+mstride_reg+4]
2623     lea        dst8_reg, [dst8_reg+mstride_reg+4]
2624     WRITE_8W         m5, m5, dst2_reg, dst_reg,  mstride_reg, stride_reg, %2
2625 %ifidn %2, sse4
2626     lea         dst_reg, [dst8_reg+ stride_reg]
2627 %endif
2628     WRITE_8W         m6, m6, dst2_reg, dst8_reg, mstride_reg, stride_reg, %2
2629 %endif
2630 %endif
2631
2632 %if mmsize == 8
2633 %if %4 == 8 ; chroma
2634 %ifidn %2, h
2635     sub         dst_reg, 5
2636 %endif
2637     cmp         dst_reg, dst8_reg
2638     mov         dst_reg, dst8_reg
2639     jnz .next8px
2640 %else
2641 %ifidn %2, h
2642     lea         dst_reg, [dst_reg + stride_reg*8-5]
2643 %else ; v
2644     add         dst_reg, 8
2645 %endif
2646     dec         cnt_reg
2647     jg .next8px
2648 %endif
2649 %endif
2650
2651 %ifndef m8 ; sse2 on x86-32 or mmx/mmxext
2652     mov             rsp, stack_reg   ; restore stack pointer
2653 %endif
2654     RET
2655 %endmacro
2656
2657 INIT_MMX
2658 MBEDGE_LOOPFILTER mmx,    v, 6, 16, 0
2659 MBEDGE_LOOPFILTER mmx,    h, 6, 16, 0
2660 MBEDGE_LOOPFILTER mmxext, v, 6, 16, 0
2661 MBEDGE_LOOPFILTER mmxext, h, 6, 16, 0
2662
2663 MBEDGE_LOOPFILTER mmx,    v, 6,  8, 0
2664 MBEDGE_LOOPFILTER mmx,    h, 6,  8, 0
2665 MBEDGE_LOOPFILTER mmxext, v, 6,  8, 0
2666 MBEDGE_LOOPFILTER mmxext, h, 6,  8, 0
2667
2668 INIT_XMM
2669 MBEDGE_LOOPFILTER sse2,   v, 5, 16, 16
2670 %ifdef m8
2671 MBEDGE_LOOPFILTER sse2,   h, 5, 16, 16
2672 %else
2673 MBEDGE_LOOPFILTER sse2,   h, 6, 16, 16
2674 %endif
2675 MBEDGE_LOOPFILTER sse2,   v, 6,  8, 16
2676 MBEDGE_LOOPFILTER sse2,   h, 6,  8, 16
2677
2678 MBEDGE_LOOPFILTER ssse3,  v, 5, 16, 16
2679 %ifdef m8
2680 MBEDGE_LOOPFILTER ssse3,  h, 5, 16, 16
2681 %else
2682 MBEDGE_LOOPFILTER ssse3,  h, 6, 16, 16
2683 %endif
2684 MBEDGE_LOOPFILTER ssse3,  v, 6,  8, 16
2685 MBEDGE_LOOPFILTER ssse3,  h, 6,  8, 16
2686
2687 %ifdef m8
2688 MBEDGE_LOOPFILTER sse4,   h, 5, 16, 16
2689 %else
2690 MBEDGE_LOOPFILTER sse4,   h, 6, 16, 16
2691 %endif
2692 MBEDGE_LOOPFILTER sse4,   h, 6,  8, 16