1d9d8c5b6c551e72fe4c99eda2da0d27438628ab
[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
1233     movd           %1, %2
1234     punpcklbw      %1, %1
1235 %if mmsize == 16 ; sse2
1236     punpcklwd      %1, %1
1237     pshufd         %1, %1, 0x0
1238 %elifidn %3, mmx
1239     punpcklwd      %1, %1
1240     punpckldq      %1, %1
1241 %else ; mmxext
1242     pshufw         %1, %1, 0x0
1243 %endif
1244 %endmacro
1245
1246 %macro SIMPLE_LOOPFILTER 3
1247 cglobal vp8_%2_loop_filter_simple_%1, 3, %3
1248 %ifidn %2, h
1249     mov            r5, rsp          ; backup stack pointer
1250     and           rsp, ~(mmsize-1)  ; align stack
1251 %endif
1252 %if mmsize == 8 ; mmx/mmxext
1253     mov            r3, 2
1254 %endif
1255     SPLATB_REG     m7, r2, %1       ; splat "flim" into register
1256
1257     ; set up indexes to address 4 rows
1258     mov            r2, r1
1259     neg            r1
1260 %ifidn %2, h
1261     lea            r0, [r0+4*r2-2]
1262     sub           rsp, mmsize*2     ; (aligned) storage space for saving p1/q1
1263 %endif
1264
1265 %if mmsize == 8 ; mmx / mmxext
1266 .next8px
1267 %endif
1268 %ifidn %2, v
1269     ; read 4 half/full rows of pixels
1270     mova           m0, [r0+r1*2]    ; p1
1271     mova           m1, [r0+r1]      ; p0
1272     mova           m2, [r0]         ; q0
1273     mova           m3, [r0+r2]      ; q1
1274 %else ; h
1275     lea            r4, [r0+r2]
1276
1277 %if mmsize == 8 ; mmx/mmxext
1278     READ_8x4_INTERLEAVED  0, 1, 2, 3, 4, 5, 6, r0, r4, r1, r2
1279 %else ; sse2
1280     READ_16x4_INTERLEAVED 0, 1, 2, 3, 4, 5, 6, r0, r4, r1, r2, r3
1281 %endif
1282     TRANSPOSE4x4W         0, 1, 2, 3, 4
1283
1284     mova        [rsp], m0           ; store p1
1285     mova [rsp+mmsize], m3           ; store q1
1286 %endif
1287
1288     ; simple_limit
1289     mova           m5, m2           ; m5=backup of q0
1290     mova           m6, m1           ; m6=backup of p0
1291     psubusb        m1, m2           ; p0-q0
1292     psubusb        m2, m6           ; q0-p0
1293     por            m1, m2           ; FFABS(p0-q0)
1294     paddusb        m1, m1           ; m1=FFABS(p0-q0)*2
1295
1296     mova           m4, m3
1297     mova           m2, m0
1298     psubusb        m3, m0           ; q1-p1
1299     psubusb        m0, m4           ; p1-q1
1300     por            m3, m0           ; FFABS(p1-q1)
1301     mova           m0, [pb_80]
1302     pxor           m2, m0
1303     pxor           m4, m0
1304     psubsb         m2, m4           ; m2=p1-q1 (signed) backup for below
1305     pand           m3, [pb_FE]
1306     psrlq          m3, 1            ; m3=FFABS(p1-q1)/2, this can be used signed
1307     paddusb        m3, m1
1308     psubusb        m3, m7
1309     pxor           m1, m1
1310     pcmpeqb        m3, m1           ; abs(p0-q0)*2+abs(p1-q1)/2<=flim mask(0xff/0x0)
1311
1312     ; filter_common (use m2/p1-q1, m4=q0, m6=p0, m5/q0-p0 and m3/mask)
1313     mova           m4, m5
1314     pxor           m5, m0
1315     pxor           m0, m6
1316     psubsb         m5, m0           ; q0-p0 (signed)
1317     paddsb         m2, m5
1318     paddsb         m2, m5
1319     paddsb         m2, m5           ; a=(p1-q1) + 3*(q0-p0)
1320     pand           m2, m3           ; apply filter mask (m3)
1321
1322     mova           m3, [pb_F8]
1323     mova           m1, m2
1324     paddsb         m2, [pb_4]       ; f1<<3=a+4
1325     paddsb         m1, [pb_3]       ; f2<<3=a+3
1326     pand           m2, m3
1327     pand           m1, m3           ; cache f2<<3
1328
1329     pxor           m0, m0
1330     pxor           m3, m3
1331     pcmpgtb        m0, m2           ; which values are <0?
1332     psubb          m3, m2           ; -f1<<3
1333     psrlq          m2, 3            ; +f1
1334     psrlq          m3, 3            ; -f1
1335     pand           m3, m0
1336     pandn          m0, m2
1337     psubusb        m4, m0
1338     paddusb        m4, m3           ; q0-f1
1339
1340     pxor           m0, m0
1341     pxor           m3, m3
1342     pcmpgtb        m0, m1           ; which values are <0?
1343     psubb          m3, m1           ; -f2<<3
1344     psrlq          m1, 3            ; +f2
1345     psrlq          m3, 3            ; -f2
1346     pand           m3, m0
1347     pandn          m0, m1
1348     paddusb        m6, m0
1349     psubusb        m6, m3           ; p0+f2
1350
1351     ; store
1352 %ifidn %2, v
1353     mova         [r0], m4
1354     mova      [r0+r1], m6
1355 %else ; h
1356     mova           m0, [rsp]        ; p1
1357     SWAP            2, 4            ; p0
1358     SWAP            1, 6            ; q0
1359     mova           m3, [rsp+mmsize] ; q1
1360
1361     TRANSPOSE4x4B  0, 1, 2, 3, 4
1362 %if mmsize == 16 ; sse2
1363     add            r3, r1           ; change from r4*8*stride to r0+8*stride
1364     WRITE_4x4D 0, 1, 2, 3, r0, r4, r3, r1, r2, 16
1365 %else ; mmx/mmxext
1366     WRITE_4x2D 0, 1, 2, 3, r0, r4, r1, r2
1367 %endif
1368 %endif
1369
1370 %if mmsize == 8 ; mmx/mmxext
1371     ; next 8 pixels
1372 %ifidn %2, v
1373     add            r0, 8            ; advance 8 cols = pixels
1374 %else ; h
1375     lea            r0, [r0+r2*8]    ; advance 8 rows = lines
1376 %endif
1377     dec            r3
1378     jg .next8px
1379 %ifidn %2, v
1380     REP_RET
1381 %else ; h
1382     mov           rsp, r5           ; restore stack pointer
1383     RET
1384 %endif
1385 %else ; sse2
1386 %ifidn %2, h
1387     mov           rsp, r5           ; restore stack pointer
1388 %endif
1389     RET
1390 %endif
1391 %endmacro
1392
1393 INIT_MMX
1394 SIMPLE_LOOPFILTER mmx,    v, 4
1395 SIMPLE_LOOPFILTER mmx,    h, 6
1396 SIMPLE_LOOPFILTER mmxext, v, 4
1397 SIMPLE_LOOPFILTER mmxext, h, 6
1398 INIT_XMM
1399 SIMPLE_LOOPFILTER sse2,   v, 3
1400 SIMPLE_LOOPFILTER sse2,   h, 6
1401
1402 ;-----------------------------------------------------------------------------
1403 ; void vp8_h/v_loop_filter<size>_inner_<opt>(uint8_t *dst, [uint8_t *v,] int stride,
1404 ;                                            int flimE, int flimI, int hev_thr);
1405 ;-----------------------------------------------------------------------------
1406
1407 %macro INNER_LOOPFILTER 5
1408 %if %4 == 8 ; chroma
1409 cglobal vp8_%2_loop_filter8uv_inner_%1, 6, %3, %5
1410 %define dst8_reg    r1
1411 %define mstride_reg r2
1412 %define E_reg       r3
1413 %define I_reg       r4
1414 %define hev_thr_reg r5
1415 %else ; luma
1416 cglobal vp8_%2_loop_filter16y_inner_%1, 5, %3, %5
1417 %define mstride_reg r1
1418 %define E_reg       r2
1419 %define I_reg       r3
1420 %define hev_thr_reg r4
1421 %ifdef m8 ; x86-64, sse2
1422 %define dst8_reg    r4
1423 %elif mmsize == 16 ; x86-32, sse2
1424 %define dst8_reg    r5
1425 %else ; x86-32, mmx/mmxext
1426 %define cnt_reg     r5
1427 %endif
1428 %endif
1429 %define dst_reg     r0
1430 %define stride_reg  E_reg
1431 %define dst2_reg    I_reg
1432 %ifndef m8
1433 %define stack_reg   hev_thr_reg
1434 %endif
1435
1436 %ifndef m8 ; mmx/mmxext or sse2 on x86-32
1437     ; splat function arguments
1438     SPLATB_REG       m0, E_reg, %1   ; E
1439     SPLATB_REG       m1, I_reg, %1   ; I
1440     SPLATB_REG       m2, hev_thr_reg, %1 ; hev_thresh
1441
1442     ; align stack
1443     mov       stack_reg, rsp         ; backup stack pointer
1444     and             rsp, ~(mmsize-1) ; align stack
1445 %ifidn %2, v
1446     sub             rsp, mmsize * 4  ; stack layout: [0]=E, [1]=I, [2]=hev_thr
1447                                      ;               [3]=hev() result
1448 %else ; h
1449     sub             rsp, mmsize * 5  ; extra storage space for transposes
1450 %endif
1451
1452 %define flim_E   [rsp]
1453 %define flim_I   [rsp+mmsize]
1454 %define hev_thr  [rsp+mmsize*2]
1455 %define mask_res [rsp+mmsize*3]
1456 %define p0backup [rsp+mmsize*3]
1457 %define q0backup [rsp+mmsize*4]
1458
1459     mova         flim_E, m0
1460     mova         flim_I, m1
1461     mova        hev_thr, m2
1462
1463 %else ; sse2 on x86-64
1464
1465 %define flim_E   m9
1466 %define flim_I   m10
1467 %define hev_thr  m11
1468 %define mask_res m12
1469 %define p0backup m12
1470 %define q0backup m8
1471
1472     ; splat function arguments
1473     SPLATB_REG   flim_E, E_reg, %1   ; E
1474     SPLATB_REG   flim_I, I_reg, %1   ; I
1475     SPLATB_REG  hev_thr, hev_thr_reg, %1 ; hev_thresh
1476 %endif
1477
1478 %if mmsize == 8 && %4 == 16 ; mmx/mmxext
1479     mov         cnt_reg, 2
1480 %endif
1481     mov      stride_reg, mstride_reg
1482     neg     mstride_reg
1483 %ifidn %2, h
1484     lea         dst_reg, [dst_reg + stride_reg*4-4]
1485 %if %4 == 8
1486     lea        dst8_reg, [dst8_reg+ stride_reg*4-4]
1487 %endif
1488 %endif
1489
1490 %if mmsize == 8
1491 .next8px
1492 %endif
1493     ; read
1494     lea        dst2_reg, [dst_reg + stride_reg]
1495 %ifidn %2, v
1496 %if %4 == 8 && mmsize == 16
1497 %define movrow movh
1498 %else
1499 %define movrow mova
1500 %endif
1501     movrow           m0, [dst_reg +mstride_reg*4] ; p3
1502     movrow           m1, [dst2_reg+mstride_reg*4] ; p2
1503     movrow           m2, [dst_reg +mstride_reg*2] ; p1
1504     movrow           m5, [dst2_reg]               ; q1
1505     movrow           m6, [dst2_reg+ stride_reg]   ; q2
1506     movrow           m7, [dst2_reg+ stride_reg*2] ; q3
1507 %if mmsize == 16 && %4 == 8
1508     movhps           m0, [dst8_reg+mstride_reg*4]
1509     movhps           m2, [dst8_reg+mstride_reg*2]
1510     add        dst8_reg, stride_reg
1511     movhps           m1, [dst8_reg+mstride_reg*4]
1512     movhps           m5, [dst8_reg]
1513     movhps           m6, [dst8_reg+ stride_reg]
1514     movhps           m7, [dst8_reg+ stride_reg*2]
1515     add        dst8_reg, mstride_reg
1516 %endif
1517 %elif mmsize == 8 ; mmx/mmxext (h)
1518     ; read 8 rows of 8px each
1519     movu             m0, [dst_reg +mstride_reg*4]
1520     movu             m1, [dst2_reg+mstride_reg*4]
1521     movu             m2, [dst_reg +mstride_reg*2]
1522     movu             m3, [dst_reg +mstride_reg]
1523     movu             m4, [dst_reg]
1524     movu             m5, [dst2_reg]
1525     movu             m6, [dst2_reg+ stride_reg]
1526
1527     ; 8x8 transpose
1528     TRANSPOSE4x4B     0, 1, 2, 3, 7
1529     mova       q0backup, m1
1530     movu             m7, [dst2_reg+ stride_reg*2]
1531     TRANSPOSE4x4B     4, 5, 6, 7, 1
1532     SBUTTERFLY       dq, 0, 4, 1     ; p3/p2
1533     SBUTTERFLY       dq, 2, 6, 1     ; q0/q1
1534     SBUTTERFLY       dq, 3, 7, 1     ; q2/q3
1535     mova             m1, q0backup
1536     mova       q0backup, m2          ; store q0
1537     SBUTTERFLY       dq, 1, 5, 2     ; p1/p0
1538     mova       p0backup, m5          ; store p0
1539     SWAP              1, 4
1540     SWAP              2, 4
1541     SWAP              6, 3
1542     SWAP              5, 3
1543 %else ; sse2 (h)
1544 %if %4 == 16
1545     lea        dst8_reg, [dst_reg + stride_reg*8]
1546 %endif
1547
1548     ; read 16 rows of 8px each, interleave
1549     movh             m0, [dst_reg +mstride_reg*4]
1550     movh             m1, [dst8_reg+mstride_reg*4]
1551     movh             m2, [dst_reg +mstride_reg*2]
1552     movh             m5, [dst8_reg+mstride_reg*2]
1553     movh             m3, [dst_reg +mstride_reg]
1554     movh             m6, [dst8_reg+mstride_reg]
1555     movh             m4, [dst_reg]
1556     movh             m7, [dst8_reg]
1557     punpcklbw        m0, m1          ; A/I
1558     punpcklbw        m2, m5          ; C/K
1559     punpcklbw        m3, m6          ; D/L
1560     punpcklbw        m4, m7          ; E/M
1561
1562     add        dst8_reg, stride_reg
1563     movh             m1, [dst2_reg+mstride_reg*4]
1564     movh             m6, [dst8_reg+mstride_reg*4]
1565     movh             m5, [dst2_reg]
1566     movh             m7, [dst8_reg]
1567     punpcklbw        m1, m6          ; B/J
1568     punpcklbw        m5, m7          ; F/N
1569     movh             m6, [dst2_reg+ stride_reg]
1570     movh             m7, [dst8_reg+ stride_reg]
1571     punpcklbw        m6, m7          ; G/O
1572
1573     ; 8x16 transpose
1574     TRANSPOSE4x4B     0, 1, 2, 3, 7
1575 %ifdef m8
1576     SWAP              1, 8
1577 %else
1578     mova       q0backup, m1
1579 %endif
1580     movh             m7, [dst2_reg+ stride_reg*2]
1581     movh             m1, [dst8_reg+ stride_reg*2]
1582     punpcklbw        m7, m1          ; H/P
1583     TRANSPOSE4x4B     4, 5, 6, 7, 1
1584     SBUTTERFLY       dq, 0, 4, 1     ; p3/p2
1585     SBUTTERFLY       dq, 2, 6, 1     ; q0/q1
1586     SBUTTERFLY       dq, 3, 7, 1     ; q2/q3
1587 %ifdef m8
1588     SWAP              1, 8
1589     SWAP              2, 8
1590 %else
1591     mova             m1, q0backup
1592     mova       q0backup, m2          ; store q0
1593 %endif
1594     SBUTTERFLY       dq, 1, 5, 2     ; p1/p0
1595 %ifdef m12
1596     SWAP              5, 12
1597 %else
1598     mova       p0backup, m5          ; store p0
1599 %endif
1600     SWAP              1, 4
1601     SWAP              2, 4
1602     SWAP              6, 3
1603     SWAP              5, 3
1604 %endif
1605
1606     ; normal_limit for p3-p2, p2-p1, q3-q2 and q2-q1
1607     mova             m4, m1
1608     SWAP              4, 1
1609     psubusb          m4, m0          ; p2-p3
1610     psubusb          m0, m1          ; p3-p2
1611     por              m0, m4          ; abs(p3-p2)
1612
1613     mova             m4, m2
1614     SWAP              4, 2
1615     psubusb          m4, m1          ; p1-p2
1616     psubusb          m1, m2          ; p2-p1
1617     por              m1, m4          ; abs(p2-p1)
1618
1619     mova             m4, m6
1620     SWAP              4, 6
1621     psubusb          m4, m7          ; q2-q3
1622     psubusb          m7, m6          ; q3-q2
1623     por              m7, m4          ; abs(q3-q2)
1624
1625     mova             m4, m5
1626     SWAP              4, 5
1627     psubusb          m4, m6          ; q1-q2
1628     psubusb          m6, m5          ; q2-q1
1629     por              m6, m4          ; abs(q2-q1)
1630
1631 %ifidn %1, mmx
1632     mova             m4, flim_I
1633     pxor             m3, m3
1634     psubusb          m0, m4
1635     psubusb          m1, m4
1636     psubusb          m7, m4
1637     psubusb          m6, m4
1638     pcmpeqb          m0, m3          ; abs(p3-p2) <= I
1639     pcmpeqb          m1, m3          ; abs(p2-p1) <= I
1640     pcmpeqb          m7, m3          ; abs(q3-q2) <= I
1641     pcmpeqb          m6, m3          ; abs(q2-q1) <= I
1642     pand             m0, m1
1643     pand             m7, m6
1644     pand             m0, m7
1645 %else ; mmxext/sse2
1646     pmaxub           m0, m1
1647     pmaxub           m6, m7
1648     pmaxub           m0, m6
1649 %endif
1650
1651     ; normal_limit and high_edge_variance for p1-p0, q1-q0
1652     SWAP              7, 3           ; now m7 is zero
1653 %ifidn %2, v
1654     movrow           m3, [dst_reg +mstride_reg] ; p0
1655 %if mmsize == 16 && %4 == 8
1656     movhps           m3, [dst8_reg+mstride_reg]
1657 %endif
1658 %elifdef m12
1659     SWAP              3, 12
1660 %else
1661     mova             m3, p0backup
1662 %endif
1663
1664     mova             m1, m2
1665     SWAP              1, 2
1666     mova             m6, m3
1667     SWAP              3, 6
1668     psubusb          m1, m3          ; p1-p0
1669     psubusb          m6, m2          ; p0-p1
1670     por              m1, m6          ; abs(p1-p0)
1671 %ifidn %1, mmx
1672     mova             m6, m1
1673     psubusb          m1, m4
1674     psubusb          m6, hev_thr
1675     pcmpeqb          m1, m7          ; abs(p1-p0) <= I
1676     pcmpeqb          m6, m7          ; abs(p1-p0) <= hev_thresh
1677     pand             m0, m1
1678     mova       mask_res, m6
1679 %else ; mmxext/sse2
1680     pmaxub           m0, m1          ; max_I
1681     SWAP              1, 4           ; max_hev_thresh
1682 %endif
1683
1684     SWAP              6, 4           ; now m6 is I
1685 %ifidn %2, v
1686     movrow           m4, [dst_reg]   ; q0
1687 %if mmsize == 16 && %4 == 8
1688     movhps           m4, [dst8_reg]
1689 %endif
1690 %elifdef m8
1691     SWAP              4, 8
1692 %else
1693     mova             m4, q0backup
1694 %endif
1695     mova             m1, m4
1696     SWAP              1, 4
1697     mova             m7, m5
1698     SWAP              7, 5
1699     psubusb          m1, m5          ; q0-q1
1700     psubusb          m7, m4          ; q1-q0
1701     por              m1, m7          ; abs(q1-q0)
1702 %ifidn %1, mmx
1703     mova             m7, m1
1704     psubusb          m1, m6
1705     psubusb          m7, hev_thr
1706     pxor             m6, m6
1707     pcmpeqb          m1, m6          ; abs(q1-q0) <= I
1708     pcmpeqb          m7, m6          ; abs(q1-q0) <= hev_thresh
1709     mova             m6, mask_res
1710     pand             m0, m1          ; abs([pq][321]-[pq][210]) <= I
1711     pand             m6, m7
1712 %else ; mmxext/sse2
1713     pxor             m7, m7
1714     pmaxub           m0, m1
1715     pmaxub           m6, m1
1716     psubusb          m0, flim_I
1717     psubusb          m6, hev_thr
1718     pcmpeqb          m0, m7          ; max(abs(..)) <= I
1719     pcmpeqb          m6, m7          ; !(max(abs..) > thresh)
1720 %endif
1721 %ifdef m12
1722     SWAP              6, 12
1723 %else
1724     mova       mask_res, m6          ; !(abs(p1-p0) > hev_t || abs(q1-q0) > hev_t)
1725 %endif
1726
1727     ; simple_limit
1728     mova             m1, m3
1729     SWAP              1, 3
1730     mova             m6, m4          ; keep copies of p0/q0 around for later use
1731     SWAP              6, 4
1732     psubusb          m1, m4          ; p0-q0
1733     psubusb          m6, m3          ; q0-p0
1734     por              m1, m6          ; abs(q0-p0)
1735     paddusb          m1, m1          ; m1=2*abs(q0-p0)
1736
1737     mova             m7, m2
1738     SWAP              7, 2
1739     mova             m6, m5
1740     SWAP              6, 5
1741     psubusb          m7, m5          ; p1-q1
1742     psubusb          m6, m2          ; q1-p1
1743     por              m7, m6          ; abs(q1-p1)
1744     pxor             m6, m6
1745     pand             m7, [pb_FE]
1746     psrlq            m7, 1           ; abs(q1-p1)/2
1747     paddusb          m7, m1          ; abs(q0-p0)*2+abs(q1-p1)/2
1748     psubusb          m7, flim_E
1749     pcmpeqb          m7, m6          ; abs(q0-p0)*2+abs(q1-p1)/2 <= E
1750     pand             m0, m7          ; normal_limit result
1751
1752     ; filter_common; at this point, m2-m5=p1-q1 and m0 is filter_mask
1753 %ifdef m8 ; x86-64 && sse2
1754     mova             m8, [pb_80]
1755 %define pb_80_var m8
1756 %else ; x86-32 or mmx/mmxext
1757 %define pb_80_var [pb_80]
1758 %endif
1759     mova             m1, m4
1760     mova             m7, m3
1761     pxor             m1, pb_80_var
1762     pxor             m7, pb_80_var
1763     psubsb           m1, m7          ; (signed) q0-p0
1764     mova             m6, m2
1765     mova             m7, m5
1766     pxor             m6, pb_80_var
1767     pxor             m7, pb_80_var
1768     psubsb           m6, m7          ; (signed) p1-q1
1769     mova             m7, mask_res
1770     pandn            m7, m6
1771     paddsb           m7, m1
1772     paddsb           m7, m1
1773     paddsb           m7, m1          ; 3*(q0-p0)+is4tap?(p1-q1)
1774
1775     pand             m7, m0
1776     mova             m1, [pb_F8]
1777     mova             m6, m7
1778     paddsb           m7, [pb_3]
1779     paddsb           m6, [pb_4]
1780     pand             m7, m1
1781     pand             m6, m1
1782
1783     pxor             m1, m1
1784     pxor             m0, m0
1785     pcmpgtb          m1, m7
1786     psubb            m0, m7
1787     psrlq            m7, 3           ; +f2
1788     psrlq            m0, 3           ; -f2
1789     pand             m0, m1
1790     pandn            m1, m7
1791     psubusb          m3, m0
1792     paddusb          m3, m1          ; p0+f2
1793
1794     pxor             m1, m1
1795     pxor             m0, m0
1796     pcmpgtb          m0, m6
1797     psubb            m1, m6
1798     psrlq            m6, 3           ; +f1
1799     psrlq            m1, 3           ; -f1
1800     pand             m1, m0
1801     pandn            m0, m6
1802     psubusb          m4, m0
1803     paddusb          m4, m1          ; q0-f1
1804
1805 %ifdef m12
1806     SWAP              6, 12
1807 %else
1808     mova             m6, mask_res
1809 %endif
1810 %ifidn %1, mmx
1811     mova             m7, [pb_1]
1812 %else ; mmxext/sse2
1813     pxor             m7, m7
1814 %endif
1815     pand             m0, m6
1816     pand             m1, m6
1817 %ifidn %1, mmx
1818     paddusb          m0, m7
1819     pand             m1, [pb_FE]
1820     pandn            m7, m0
1821     psrlq            m1, 1
1822     psrlq            m7, 1
1823     SWAP              0, 7
1824 %else ; mmxext/sse2
1825     psubusb          m1, [pb_1]
1826     pavgb            m0, m7          ; a
1827     pavgb            m1, m7          ; -a
1828 %endif
1829     psubusb          m5, m0
1830     psubusb          m2, m1
1831     paddusb          m5, m1          ; q1-a
1832     paddusb          m2, m0          ; p1+a
1833
1834     ; store
1835 %ifidn %2, v
1836     movrow [dst_reg +mstride_reg*2], m2
1837     movrow [dst_reg +mstride_reg  ], m3
1838     movrow    [dst_reg], m4
1839     movrow [dst_reg + stride_reg  ], m5
1840 %if mmsize == 16 && %4 == 8
1841     movhps [dst8_reg+mstride_reg*2], m2
1842     movhps [dst8_reg+mstride_reg  ], m3
1843     movhps   [dst8_reg], m4
1844     movhps [dst8_reg+ stride_reg  ], m5
1845 %endif
1846 %else ; h
1847     add         dst_reg, 2
1848     add        dst2_reg, 2
1849
1850     ; 4x8/16 transpose
1851     TRANSPOSE4x4B     2, 3, 4, 5, 6
1852
1853 %if mmsize == 8 ; mmx/mmxext (h)
1854     WRITE_4x2D        2, 3, 4, 5, dst_reg, dst2_reg, mstride_reg, stride_reg
1855 %else ; sse2 (h)
1856     lea        dst8_reg, [dst8_reg+mstride_reg+2]
1857     WRITE_4x4D        2, 3, 4, 5, dst_reg, dst2_reg, dst8_reg, mstride_reg, stride_reg, %4
1858 %endif
1859 %endif
1860
1861 %if mmsize == 8
1862 %if %4 == 8 ; chroma
1863 %ifidn %2, h
1864     sub         dst_reg, 2
1865 %endif
1866     cmp         dst_reg, dst8_reg
1867     mov         dst_reg, dst8_reg
1868     jnz .next8px
1869 %else
1870 %ifidn %2, h
1871     lea         dst_reg, [dst_reg + stride_reg*8-2]
1872 %else ; v
1873     add         dst_reg, 8
1874 %endif
1875     dec         cnt_reg
1876     jg .next8px
1877 %endif
1878 %endif
1879
1880 %ifndef m8 ; sse2 on x86-32 or mmx/mmxext
1881     mov             rsp, stack_reg   ; restore stack pointer
1882 %endif
1883     RET
1884 %endmacro
1885
1886 INIT_MMX
1887 INNER_LOOPFILTER mmx,    v, 6, 16, 8
1888 INNER_LOOPFILTER mmx,    h, 6, 16, 8
1889 INNER_LOOPFILTER mmxext, v, 6, 16, 8
1890 INNER_LOOPFILTER mmxext, h, 6, 16, 8
1891
1892 INNER_LOOPFILTER mmx,    v, 6,  8, 8
1893 INNER_LOOPFILTER mmx,    h, 6,  8, 8
1894 INNER_LOOPFILTER mmxext, v, 6,  8, 8
1895 INNER_LOOPFILTER mmxext, h, 6,  8, 8
1896
1897 INIT_XMM
1898 INNER_LOOPFILTER sse2,   v, 5, 16, 13
1899 %ifdef m8
1900 INNER_LOOPFILTER sse2,   h, 5, 16, 13
1901 %else
1902 INNER_LOOPFILTER sse2,   h, 6, 16, 13
1903 %endif
1904 INNER_LOOPFILTER sse2,   v, 6,  8, 13
1905 INNER_LOOPFILTER sse2,   h, 6,  8, 13
1906
1907 ;-----------------------------------------------------------------------------
1908 ; void vp8_h/v_loop_filter<size>_mbedge_<opt>(uint8_t *dst, [uint8_t *v,] int stride,
1909 ;                                            int flimE, int flimI, int hev_thr);
1910 ;-----------------------------------------------------------------------------
1911
1912 ; write 4 or 8 words in the mmx/xmm registers as 8 lines
1913 ; 1 and 2 are the registers to write, this can be the same (for SSE2)
1914 ; 3 is a general-purpose register that we will clobber
1915 ; 4 is a pointer to the destination's 4th line
1916 ; 5 is -stride and +stride
1917 %macro WRITE_8W 6
1918     movd             %3, %1
1919 %if mmsize == 8
1920     punpckhdq        %1, %1
1921 %else
1922     psrldq           %1, 4
1923 %endif
1924     mov       [%4+%5*4], %3w
1925     shr              %3, 16
1926     add              %4, %6
1927     mov       [%4+%5*4], %3w
1928
1929     movd             %3, %1
1930 %if mmsize == 16
1931     psrldq           %1, 4
1932 %endif
1933     add              %4, %5
1934     mov       [%4+%5*2], %3w
1935     shr              %3, 16
1936     mov       [%4+%5  ], %3w
1937
1938     movd             %3, %2
1939 %if mmsize == 8
1940     punpckhdq        %2, %2
1941 %else
1942     psrldq           %2, 4
1943 %endif
1944     mov       [%4     ], %3w
1945     shr              %3, 16
1946     mov       [%4+%6  ], %3w
1947
1948     movd             %3, %2
1949     add              %4, %6
1950     mov       [%4+%6  ], %3w
1951     shr              %3, 16
1952     mov       [%4+%6*2], %3w
1953 %if mmsize == 8
1954     add              %4, %5
1955 %endif
1956 %endmacro
1957
1958 %macro MBEDGE_LOOPFILTER 5
1959 %if %4 == 8 ; chroma
1960 cglobal vp8_%2_loop_filter8uv_mbedge_%1, 6, %3, %5
1961 %define dst8_reg    r1
1962 %define mstride_reg r2
1963 %define E_reg       r3
1964 %define I_reg       r4
1965 %define hev_thr_reg r5
1966 %else ; luma
1967 cglobal vp8_%2_loop_filter16y_mbedge_%1, 5, %3, %5
1968 %define mstride_reg r1
1969 %define E_reg       r2
1970 %define I_reg       r3
1971 %define hev_thr_reg r4
1972 %ifdef m8 ; x86-64, sse2
1973 %define dst8_reg    r4
1974 %elif mmsize == 16 ; x86-32, sse2
1975 %define dst8_reg    r5
1976 %else ; x86-32, mmx/mmxext
1977 %define cnt_reg     r5
1978 %endif
1979 %endif
1980 %define dst_reg     r0
1981 %define stride_reg  E_reg
1982 %define dst2_reg    I_reg
1983 %ifndef m8
1984 %define stack_reg   hev_thr_reg
1985 %endif
1986
1987 %ifndef m8 ; mmx/mmxext or sse2 on x86-32
1988     ; splat function arguments
1989     SPLATB_REG       m0, E_reg, %1   ; E
1990     SPLATB_REG       m1, I_reg, %1   ; I
1991     SPLATB_REG       m2, hev_thr_reg, %1 ; hev_thresh
1992
1993     ; align stack
1994     mov       stack_reg, rsp         ; backup stack pointer
1995     and             rsp, ~(mmsize-1) ; align stack
1996     sub             rsp, mmsize * 8  ; stack layout: [0]=E, [1]=I, [2]=hev_thr
1997                                      ;               [3]=hev() result
1998                                      ;               [4]=filter tmp result
1999                                      ;               [5]/[6] = p2/q2 backup
2000                                      ;               [7]=lim_res sign result
2001
2002 %define flim_E   [rsp]
2003 %define flim_I   [rsp+mmsize]
2004 %define hev_thr  [rsp+mmsize*2]
2005 %define mask_res [rsp+mmsize*3]
2006 %define lim_res  [rsp+mmsize*4]
2007 %define p0backup [rsp+mmsize*3]
2008 %define q0backup [rsp+mmsize*4]
2009 %define p2backup [rsp+mmsize*5]
2010 %define q2backup [rsp+mmsize*6]
2011 %define lim_sign [rsp+mmsize*7]
2012
2013     mova         flim_E, m0
2014     mova         flim_I, m1
2015     mova        hev_thr, m2
2016
2017 %else ; sse2 on x86-64
2018
2019 %define flim_E   m9
2020 %define flim_I   m10
2021 %define hev_thr  m11
2022 %define mask_res m12
2023 %define lim_res  m8
2024 %define p0backup m12
2025 %define q0backup m8
2026 %define p2backup m13
2027 %define q2backup m14
2028 %define lim_sign m15
2029
2030     ; splat function arguments
2031     SPLATB_REG   flim_E, E_reg, %1   ; E
2032     SPLATB_REG   flim_I, I_reg, %1   ; I
2033     SPLATB_REG  hev_thr, hev_thr_reg, %1 ; hev_thresh
2034 %endif
2035
2036 %if mmsize == 8 && %4 == 16 ; mmx/mmxext
2037     mov         cnt_reg, 2
2038 %endif
2039     mov      stride_reg, mstride_reg
2040     neg     mstride_reg
2041 %ifidn %2, h
2042     lea         dst_reg, [dst_reg + stride_reg*4-4]
2043 %if %4 == 8
2044     lea        dst8_reg, [dst8_reg+ stride_reg*4-4]
2045 %endif
2046 %endif
2047
2048 %if mmsize == 8
2049 .next8px
2050 %endif
2051     ; read
2052     lea        dst2_reg, [dst_reg + stride_reg]
2053 %ifidn %2, v
2054 %if %4 == 8 && mmsize == 16
2055 %define movrow movh
2056 %else
2057 %define movrow mova
2058 %endif
2059     movrow           m0, [dst_reg +mstride_reg*4] ; p3
2060     movrow           m1, [dst2_reg+mstride_reg*4] ; p2
2061     movrow           m2, [dst_reg +mstride_reg*2] ; p1
2062     movrow           m5, [dst2_reg]               ; q1
2063     movrow           m6, [dst2_reg+ stride_reg]   ; q2
2064     movrow           m7, [dst2_reg+ stride_reg*2] ; q3
2065 %if mmsize == 16 && %4 == 8
2066     movhps           m0, [dst8_reg+mstride_reg*4]
2067     movhps           m2, [dst8_reg+mstride_reg*2]
2068     add        dst8_reg, stride_reg
2069     movhps           m1, [dst8_reg+mstride_reg*4]
2070     movhps           m5, [dst8_reg]
2071     movhps           m6, [dst8_reg+ stride_reg]
2072     movhps           m7, [dst8_reg+ stride_reg*2]
2073     add        dst8_reg, mstride_reg
2074 %endif
2075 %elif mmsize == 8 ; mmx/mmxext (h)
2076     ; read 8 rows of 8px each
2077     movu             m0, [dst_reg +mstride_reg*4]
2078     movu             m1, [dst2_reg+mstride_reg*4]
2079     movu             m2, [dst_reg +mstride_reg*2]
2080     movu             m3, [dst_reg +mstride_reg]
2081     movu             m4, [dst_reg]
2082     movu             m5, [dst2_reg]
2083     movu             m6, [dst2_reg+ stride_reg]
2084
2085     ; 8x8 transpose
2086     TRANSPOSE4x4B     0, 1, 2, 3, 7
2087     mova       q0backup, m1
2088     movu             m7, [dst2_reg+ stride_reg*2]
2089     TRANSPOSE4x4B     4, 5, 6, 7, 1
2090     SBUTTERFLY       dq, 0, 4, 1     ; p3/p2
2091     SBUTTERFLY       dq, 2, 6, 1     ; q0/q1
2092     SBUTTERFLY       dq, 3, 7, 1     ; q2/q3
2093     mova             m1, q0backup
2094     mova       q0backup, m2          ; store q0
2095     SBUTTERFLY       dq, 1, 5, 2     ; p1/p0
2096     mova       p0backup, m5          ; store p0
2097     SWAP              1, 4
2098     SWAP              2, 4
2099     SWAP              6, 3
2100     SWAP              5, 3
2101 %else ; sse2 (h)
2102 %if %4 == 16
2103     lea        dst8_reg, [dst_reg + stride_reg*8]
2104 %endif
2105
2106     ; read 16 rows of 8px each, interleave
2107     movh             m0, [dst_reg +mstride_reg*4]
2108     movh             m1, [dst8_reg+mstride_reg*4]
2109     movh             m2, [dst_reg +mstride_reg*2]
2110     movh             m5, [dst8_reg+mstride_reg*2]
2111     movh             m3, [dst_reg +mstride_reg]
2112     movh             m6, [dst8_reg+mstride_reg]
2113     movh             m4, [dst_reg]
2114     movh             m7, [dst8_reg]
2115     punpcklbw        m0, m1          ; A/I
2116     punpcklbw        m2, m5          ; C/K
2117     punpcklbw        m3, m6          ; D/L
2118     punpcklbw        m4, m7          ; E/M
2119
2120     add        dst8_reg, stride_reg
2121     movh             m1, [dst2_reg+mstride_reg*4]
2122     movh             m6, [dst8_reg+mstride_reg*4]
2123     movh             m5, [dst2_reg]
2124     movh             m7, [dst8_reg]
2125     punpcklbw        m1, m6          ; B/J
2126     punpcklbw        m5, m7          ; F/N
2127     movh             m6, [dst2_reg+ stride_reg]
2128     movh             m7, [dst8_reg+ stride_reg]
2129     punpcklbw        m6, m7          ; G/O
2130
2131     ; 8x16 transpose
2132     TRANSPOSE4x4B     0, 1, 2, 3, 7
2133 %ifdef m8
2134     SWAP              1, 8
2135 %else
2136     mova       q0backup, m1
2137 %endif
2138     movh             m7, [dst2_reg+ stride_reg*2]
2139     movh             m1, [dst8_reg+ stride_reg*2]
2140     punpcklbw        m7, m1          ; H/P
2141     TRANSPOSE4x4B     4, 5, 6, 7, 1
2142     SBUTTERFLY       dq, 0, 4, 1     ; p3/p2
2143     SBUTTERFLY       dq, 2, 6, 1     ; q0/q1
2144     SBUTTERFLY       dq, 3, 7, 1     ; q2/q3
2145 %ifdef m8
2146     SWAP              1, 8
2147     SWAP              2, 8
2148 %else
2149     mova             m1, q0backup
2150     mova       q0backup, m2          ; store q0
2151 %endif
2152     SBUTTERFLY       dq, 1, 5, 2     ; p1/p0
2153 %ifdef m12
2154     SWAP              5, 12
2155 %else
2156     mova       p0backup, m5          ; store p0
2157 %endif
2158     SWAP              1, 4
2159     SWAP              2, 4
2160     SWAP              6, 3
2161     SWAP              5, 3
2162 %endif
2163
2164     ; normal_limit for p3-p2, p2-p1, q3-q2 and q2-q1
2165     mova             m4, m1
2166     SWAP              4, 1
2167     psubusb          m4, m0          ; p2-p3
2168     psubusb          m0, m1          ; p3-p2
2169     por              m0, m4          ; abs(p3-p2)
2170
2171     mova             m4, m2
2172     SWAP              4, 2
2173     psubusb          m4, m1          ; p1-p2
2174     mova       p2backup, m1
2175     psubusb          m1, m2          ; p2-p1
2176     por              m1, m4          ; abs(p2-p1)
2177
2178     mova             m4, m6
2179     SWAP              4, 6
2180     psubusb          m4, m7          ; q2-q3
2181     psubusb          m7, m6          ; q3-q2
2182     por              m7, m4          ; abs(q3-q2)
2183
2184     mova             m4, m5
2185     SWAP              4, 5
2186     psubusb          m4, m6          ; q1-q2
2187     mova       q2backup, m6
2188     psubusb          m6, m5          ; q2-q1
2189     por              m6, m4          ; abs(q2-q1)
2190
2191 %ifidn %1, mmx
2192     mova             m4, flim_I
2193     pxor             m3, m3
2194     psubusb          m0, m4
2195     psubusb          m1, m4
2196     psubusb          m7, m4
2197     psubusb          m6, m4
2198     pcmpeqb          m0, m3          ; abs(p3-p2) <= I
2199     pcmpeqb          m1, m3          ; abs(p2-p1) <= I
2200     pcmpeqb          m7, m3          ; abs(q3-q2) <= I
2201     pcmpeqb          m6, m3          ; abs(q2-q1) <= I
2202     pand             m0, m1
2203     pand             m7, m6
2204     pand             m0, m7
2205 %else ; mmxext/sse2
2206     pmaxub           m0, m1
2207     pmaxub           m6, m7
2208     pmaxub           m0, m6
2209 %endif
2210
2211     ; normal_limit and high_edge_variance for p1-p0, q1-q0
2212     SWAP              7, 3           ; now m7 is zero
2213 %ifidn %2, v
2214     movrow           m3, [dst_reg +mstride_reg] ; p0
2215 %if mmsize == 16 && %4 == 8
2216     movhps           m3, [dst8_reg+mstride_reg]
2217 %endif
2218 %elifdef m12
2219     SWAP              3, 12
2220 %else
2221     mova             m3, p0backup
2222 %endif
2223
2224     mova             m1, m2
2225     SWAP              1, 2
2226     mova             m6, m3
2227     SWAP              3, 6
2228     psubusb          m1, m3          ; p1-p0
2229     psubusb          m6, m2          ; p0-p1
2230     por              m1, m6          ; abs(p1-p0)
2231 %ifidn %1, mmx
2232     mova             m6, m1
2233     psubusb          m1, m4
2234     psubusb          m6, hev_thr
2235     pcmpeqb          m1, m7          ; abs(p1-p0) <= I
2236     pcmpeqb          m6, m7          ; abs(p1-p0) <= hev_thresh
2237     pand             m0, m1
2238     mova       mask_res, m6
2239 %else ; mmxext/sse2
2240     pmaxub           m0, m1          ; max_I
2241     SWAP              1, 4           ; max_hev_thresh
2242 %endif
2243
2244     SWAP              6, 4           ; now m6 is I
2245 %ifidn %2, v
2246     movrow           m4, [dst_reg]   ; q0
2247 %if mmsize == 16 && %4 == 8
2248     movhps           m4, [dst8_reg]
2249 %endif
2250 %elifdef m8
2251     SWAP              4, 8
2252 %else
2253     mova             m4, q0backup
2254 %endif
2255     mova             m1, m4
2256     SWAP              1, 4
2257     mova             m7, m5
2258     SWAP              7, 5
2259     psubusb          m1, m5          ; q0-q1
2260     psubusb          m7, m4          ; q1-q0
2261     por              m1, m7          ; abs(q1-q0)
2262 %ifidn %1, mmx
2263     mova             m7, m1
2264     psubusb          m1, m6
2265     psubusb          m7, hev_thr
2266     pxor             m6, m6
2267     pcmpeqb          m1, m6          ; abs(q1-q0) <= I
2268     pcmpeqb          m7, m6          ; abs(q1-q0) <= hev_thresh
2269     mova             m6, mask_res
2270     pand             m0, m1          ; abs([pq][321]-[pq][210]) <= I
2271     pand             m6, m7
2272 %else ; mmxext/sse2
2273     pxor             m7, m7
2274     pmaxub           m0, m1
2275     pmaxub           m6, m1
2276     psubusb          m0, flim_I
2277     psubusb          m6, hev_thr
2278     pcmpeqb          m0, m7          ; max(abs(..)) <= I
2279     pcmpeqb          m6, m7          ; !(max(abs..) > thresh)
2280 %endif
2281 %ifdef m12
2282     SWAP              6, 12
2283 %else
2284     mova       mask_res, m6          ; !(abs(p1-p0) > hev_t || abs(q1-q0) > hev_t)
2285 %endif
2286
2287     ; simple_limit
2288     mova             m1, m3
2289     SWAP              1, 3
2290     mova             m6, m4          ; keep copies of p0/q0 around for later use
2291     SWAP              6, 4
2292     psubusb          m1, m4          ; p0-q0
2293     psubusb          m6, m3          ; q0-p0
2294     por              m1, m6          ; abs(q0-p0)
2295     paddusb          m1, m1          ; m1=2*abs(q0-p0)
2296
2297     mova             m7, m2
2298     SWAP              7, 2
2299     mova             m6, m5
2300     SWAP              6, 5
2301     psubusb          m7, m5          ; p1-q1
2302     psubusb          m6, m2          ; q1-p1
2303     por              m7, m6          ; abs(q1-p1)
2304     pxor             m6, m6
2305     pand             m7, [pb_FE]
2306     psrlq            m7, 1           ; abs(q1-p1)/2
2307     paddusb          m7, m1          ; abs(q0-p0)*2+abs(q1-p1)/2
2308     psubusb          m7, flim_E
2309     pcmpeqb          m7, m6          ; abs(q0-p0)*2+abs(q1-p1)/2 <= E
2310     pand             m0, m7          ; normal_limit result
2311
2312     ; filter_common; at this point, m2-m5=p1-q1 and m0 is filter_mask
2313 %ifdef m8 ; x86-64 && sse2
2314     mova             m8, [pb_80]
2315 %define pb_80_var m8
2316 %else ; x86-32 or mmx/mmxext
2317 %define pb_80_var [pb_80]
2318 %endif
2319     mova             m1, m4
2320     mova             m7, m3
2321     pxor             m1, pb_80_var
2322     pxor             m7, pb_80_var
2323     psubsb           m1, m7          ; (signed) q0-p0
2324     mova             m6, m2
2325     mova             m7, m5
2326     pxor             m6, pb_80_var
2327     pxor             m7, pb_80_var
2328     psubsb           m6, m7          ; (signed) p1-q1
2329     mova             m7, mask_res
2330     paddsb           m6, m1
2331     paddsb           m6, m1
2332     paddsb           m6, m1
2333     pand             m6, m0
2334 %ifdef m8
2335     mova        lim_res, m6          ; 3*(qp-p0)+(p1-q1) masked for filter_mbedge
2336     pand        lim_res, m7
2337 %else
2338     mova             m0, m6
2339     pand             m0, m7
2340     mova        lim_res, m0
2341 %endif
2342     pandn            m7, m6          ; 3*(q0-p0)+(p1-q1) masked for filter_common
2343
2344     mova             m1, [pb_F8]
2345     mova             m6, m7
2346     paddsb           m7, [pb_3]
2347     paddsb           m6, [pb_4]
2348     pand             m7, m1
2349     pand             m6, m1
2350
2351     pxor             m1, m1
2352     pxor             m0, m0
2353     pcmpgtb          m1, m7
2354     psubb            m0, m7
2355     psrlq            m7, 3           ; +f2
2356     psrlq            m0, 3           ; -f2
2357     pand             m0, m1
2358     pandn            m1, m7
2359     psubusb          m3, m0
2360     paddusb          m3, m1          ; p0+f2
2361
2362     pxor             m1, m1
2363     pxor             m0, m0
2364     pcmpgtb          m0, m6
2365     psubb            m1, m6
2366     psrlq            m6, 3           ; +f1
2367     psrlq            m1, 3           ; -f1
2368     pand             m1, m0
2369     pandn            m0, m6
2370     psubusb          m4, m0
2371     paddusb          m4, m1          ; q0-f1
2372
2373     ; filter_mbedge (m2-m5 = p1-q1; lim_res carries w)
2374     mova             m7, [pw_63]
2375 %ifdef m8
2376     SWAP              1, 8
2377 %else
2378     mova             m1, lim_res
2379 %endif
2380     pxor             m0, m0
2381     mova             m6, m1
2382     pcmpgtb          m0, m1         ; which are negative
2383     punpcklbw        m6, m0         ; signed byte->word
2384     punpckhbw        m1, m0
2385     mova       lim_sign, m0
2386     mova       mask_res, m6         ; backup for later in filter
2387     mova        lim_res, m1
2388     pmullw          m6, [pw_27]
2389     pmullw          m1, [pw_27]
2390     paddw           m6, m7
2391     paddw           m1, m7
2392     psraw           m6, 7
2393     psraw           m1, 7
2394     packsswb        m6, m1          ; a0
2395     pxor            m1, m1
2396     psubb           m1, m6
2397     pand            m1, m0          ; -a0
2398     pandn           m0, m6          ; +a0
2399     psubusb         m3, m1
2400     paddusb         m4, m1
2401     paddusb         m3, m0          ; p0+a0
2402     psubusb         m4, m0          ; q0-a0
2403
2404     mova            m6, mask_res
2405     mova            m1, lim_res
2406     mova            m0, lim_sign
2407     pmullw          m6, [pw_18]
2408     pmullw          m1, [pw_18]
2409     paddw           m6, m7
2410     paddw           m1, m7
2411     psraw           m6, 7
2412     psraw           m1, 7
2413     packsswb        m6, m1          ; a1
2414     pxor            m1, m1
2415     psubb           m1, m6
2416     pand            m1, m0          ; -a1
2417     pandn           m0, m6          ; +a1
2418     psubusb         m2, m1
2419     paddusb         m5, m1
2420     paddusb         m2, m0          ; p1+a1
2421     psubusb         m5, m0          ; q1-a1
2422
2423 %ifdef m8
2424     SWAP             6, 12
2425     SWAP             1, 8
2426 %else
2427     mova            m6, mask_res
2428     mova            m1, lim_res
2429 %endif
2430     pmullw          m6, [pw_9]
2431     pmullw          m1, [pw_9]
2432     paddw           m6, m7
2433     paddw           m1, m7
2434 %ifdef m15
2435     SWAP             7, 15
2436 %else
2437     mova            m7, lim_sign
2438 %endif
2439     psraw           m6, 7
2440     psraw           m1, 7
2441     packsswb        m6, m1          ; a1
2442     pxor            m0, m0
2443     psubb           m0, m6
2444     pand            m0, m7          ; -a1
2445     pandn           m7, m6          ; +a1
2446 %ifdef m8
2447     SWAP             1, 13
2448     SWAP             6, 14
2449 %else
2450     mova            m1, p2backup
2451     mova            m6, q2backup
2452 %endif
2453     psubusb         m1, m0
2454     paddusb         m6, m0
2455     paddusb         m1, m7          ; p1+a1
2456     psubusb         m6, m7          ; q1-a1
2457
2458     ; store
2459 %ifidn %2, v
2460     movrow [dst2_reg+mstride_reg*4], m1
2461     movrow [dst_reg +mstride_reg*2], m2
2462     movrow [dst_reg +mstride_reg  ], m3
2463     movrow    [dst_reg], m4
2464     movrow   [dst2_reg], m5
2465     movrow [dst2_reg+ stride_reg  ], m6
2466 %if mmsize == 16 && %4 == 8
2467     add        dst8_reg, mstride_reg
2468     movhps [dst8_reg+mstride_reg*2], m1
2469     movhps [dst8_reg+mstride_reg  ], m2
2470     movhps   [dst8_reg], m3
2471     add        dst8_reg, stride_reg
2472     movhps   [dst8_reg], m4
2473     movhps [dst8_reg+ stride_reg  ], m5
2474     movhps [dst8_reg+ stride_reg*2], m6
2475 %endif
2476 %else ; h
2477     inc         dst_reg
2478     inc        dst2_reg
2479
2480     ; 4x8/16 transpose
2481     TRANSPOSE4x4B     1, 2, 3, 4, 0
2482     SBUTTERFLY       bw, 5, 6, 0
2483
2484 %if mmsize == 8 ; mmx/mmxext (h)
2485     WRITE_4x2D        1, 2, 3, 4, dst_reg, dst2_reg, mstride_reg, stride_reg
2486     add         dst_reg, 4
2487     WRITE_8W         m5, m6, dst2_reg, dst_reg, mstride_reg, stride_reg
2488 %else ; sse2 (h)
2489     lea        dst8_reg, [dst8_reg+mstride_reg+1]
2490     WRITE_4x4D        1, 2, 3, 4, dst_reg, dst2_reg, dst8_reg, mstride_reg, stride_reg, %4
2491     add         dst_reg, 4
2492     add        dst8_reg, 4
2493     WRITE_8W         m5, m5, dst2_reg, dst_reg,  mstride_reg, stride_reg
2494     WRITE_8W         m6, m6, dst2_reg, dst8_reg, mstride_reg, stride_reg
2495 %endif
2496 %endif
2497
2498 %if mmsize == 8
2499 %if %4 == 8 ; chroma
2500 %ifidn %2, h
2501     sub         dst_reg, 5
2502 %endif
2503     cmp         dst_reg, dst8_reg
2504     mov         dst_reg, dst8_reg
2505     jnz .next8px
2506 %else
2507 %ifidn %2, h
2508     lea         dst_reg, [dst_reg + stride_reg*8-5]
2509 %else ; v
2510     add         dst_reg, 8
2511 %endif
2512     dec         cnt_reg
2513     jg .next8px
2514 %endif
2515 %endif
2516
2517 %ifndef m8 ; sse2 on x86-32 or mmx/mmxext
2518     mov             rsp, stack_reg   ; restore stack pointer
2519 %endif
2520     RET
2521 %endmacro
2522
2523 INIT_MMX
2524 MBEDGE_LOOPFILTER mmx,    v, 6, 16, 8
2525 MBEDGE_LOOPFILTER mmx,    h, 6, 16, 8
2526 MBEDGE_LOOPFILTER mmxext, v, 6, 16, 8
2527 MBEDGE_LOOPFILTER mmxext, h, 6, 16, 8
2528
2529 MBEDGE_LOOPFILTER mmx,    v, 6,  8, 8
2530 MBEDGE_LOOPFILTER mmx,    h, 6,  8, 8
2531 MBEDGE_LOOPFILTER mmxext, v, 6,  8, 8
2532 MBEDGE_LOOPFILTER mmxext, h, 6,  8, 8
2533
2534 INIT_XMM
2535 MBEDGE_LOOPFILTER sse2,   v, 5, 16, 16
2536 %ifdef m8
2537 MBEDGE_LOOPFILTER sse2,   h, 5, 16, 16
2538 %else
2539 MBEDGE_LOOPFILTER sse2,   h, 6, 16, 16
2540 %endif
2541 MBEDGE_LOOPFILTER sse2,   v, 6,  8, 16
2542 MBEDGE_LOOPFILTER sse2,   h, 6,  8, 16