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