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