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