VP8: Much faster SSE2 MC
[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 INIT_XMM
442 cglobal put_vp8_epel8_h4_sse2, 6, 6, 10
443     shl      r5d, 5
444 %ifdef PIC
445     lea      r11, [fourtap_filter_v_m]
446 %endif
447     lea       r5, [fourtap_filter_v+r5-32]
448     pxor      m7, m7
449     mova      m4, [pw_64]
450     mova      m5, [r5+ 0]
451     mova      m6, [r5+16]
452 %ifdef m8
453     mova      m8, [r5+32]
454     mova      m9, [r5+48]
455 %endif
456 .nextrow
457     movq      m0, [r2-1]
458     movq      m1, [r2-0]
459     movq      m2, [r2+1]
460     movq      m3, [r2+2]
461     punpcklbw m0, m7
462     punpcklbw m1, m7
463     punpcklbw m2, m7
464     punpcklbw m3, m7
465     pmullw    m0, m5
466     pmullw    m1, m6
467 %ifdef m8
468     pmullw    m2, m8
469     pmullw    m3, m9
470 %else
471     pmullw    m2, [r5+32]
472     pmullw    m3, [r5+48]
473 %endif
474     paddsw    m0, m1
475     paddsw    m2, m3
476     paddsw    m0, m2
477     paddsw    m0, m4
478     psraw     m0, 7
479     packuswb  m0, m7
480     movh    [r0], m0        ; store
481
482     ; go to next line
483     add       r0, r1
484     add       r2, r3
485     dec       r4            ; next row
486     jg .nextrow
487     REP_RET
488
489 cglobal put_vp8_epel8_h6_sse2, 6, 6, 14
490     lea      r5d, [r5*3]
491     shl      r5d, 4
492 %ifdef PIC
493     lea      r11, [sixtap_filter_v_m]
494 %endif
495     lea       r5, [sixtap_filter_v+r5-96]
496     pxor      m7, m7
497     mova      m6, [pw_64]
498 %ifdef m8
499     mova      m8, [r5+ 0]
500     mova      m9, [r5+16]
501     mova     m10, [r5+32]
502     mova     m11, [r5+48]
503     mova     m12, [r5+64]
504     mova     m13, [r5+80]
505 %endif
506 .nextrow
507     movq      m0, [r2-2]
508     movq      m1, [r2-1]
509     movq      m2, [r2-0]
510     movq      m3, [r2+1]
511     movq      m4, [r2+2]
512     movq      m5, [r2+3]
513     punpcklbw m0, m7
514     punpcklbw m1, m7
515     punpcklbw m2, m7
516     punpcklbw m3, m7
517     punpcklbw m4, m7
518     punpcklbw m5, m7
519 %ifdef m8
520     pmullw    m0, m8
521     pmullw    m1, m9
522     pmullw    m2, m10
523     pmullw    m3, m11
524     pmullw    m4, m12
525     pmullw    m5, m13
526 %else
527     pmullw    m0, [r5+ 0]
528     pmullw    m1, [r5+16]
529     pmullw    m2, [r5+32]
530     pmullw    m3, [r5+48]
531     pmullw    m4, [r5+64]
532     pmullw    m5, [r5+80]
533 %endif
534     paddsw    m1, m4
535     paddsw    m0, m5
536     paddsw    m1, m2
537     paddsw    m0, m3
538     paddsw    m0, m1
539     paddsw    m0, m6
540     psraw     m0, 7
541     packuswb  m0, m7
542     movh    [r0], m0        ; store
543
544     ; go to next line
545     add       r0, r1
546     add       r2, r3
547     dec       r4            ; next row
548     jg .nextrow
549     REP_RET
550
551 %macro FILTER_V 3
552 ; 4x4 block, V-only 4-tap filter
553 cglobal put_vp8_epel%2_v4_%1, 7, 7, %3
554     shl      r6d, 5
555 %ifdef PIC
556     lea      r11, [fourtap_filter_v_m]
557 %endif
558     lea       r6, [fourtap_filter_v+r6-32]
559     mova      m6, [pw_64]
560     pxor      m7, m7
561     mova      m5, [r6+48]
562
563     ; read 3 lines
564     sub       r2, r3
565     movh      m0, [r2]
566     movh      m1, [r2+  r3]
567     movh      m2, [r2+2*r3]
568     add       r2, r3
569     punpcklbw m0, m7
570     punpcklbw m1, m7
571     punpcklbw m2, m7
572
573 .nextrow
574     ; first calculate negative taps (to prevent losing positive overflows)
575     movh      m4, [r2+2*r3]                ; read new row
576     punpcklbw m4, m7
577     mova      m3, m4
578     pmullw    m0, [r6+0]
579     pmullw    m4, m5
580     paddsw    m4, m0
581
582     ; then calculate positive taps
583     mova      m0, m1
584     pmullw    m1, [r6+16]
585     paddsw    m4, m1
586     mova      m1, m2
587     pmullw    m2, [r6+32]
588     paddsw    m4, m2
589     mova      m2, m3
590
591     ; round/clip/store
592     paddsw    m4, m6
593     psraw     m4, 7
594     packuswb  m4, m7
595     movh    [r0], m4
596
597     ; go to next line
598     add       r0, r1
599     add       r2, r3
600     dec       r4                           ; next row
601     jg .nextrow
602     REP_RET
603
604
605 ; 4x4 block, V-only 6-tap filter
606 cglobal put_vp8_epel%2_v6_%1, 7, 7, %3
607     shl      r6d, 4
608     lea       r6, [r6*3]
609 %ifdef PIC
610     lea      r11, [sixtap_filter_v_m]
611 %endif
612     lea       r6, [sixtap_filter_v+r6-96]
613     pxor      m7, m7
614
615     ; read 5 lines
616     sub       r2, r3
617     sub       r2, r3
618     movh      m0, [r2]
619     movh      m1, [r2+r3]
620     movh      m2, [r2+r3*2]
621     lea       r2, [r2+r3*2]
622     add       r2, r3
623     movh      m3, [r2]
624     movh      m4, [r2+r3]
625     punpcklbw m0, m7
626     punpcklbw m1, m7
627     punpcklbw m2, m7
628     punpcklbw m3, m7
629     punpcklbw m4, m7
630
631 .nextrow
632     ; first calculate negative taps (to prevent losing positive overflows)
633     mova      m5, m1
634     pmullw    m5, [r6+16]
635     mova      m6, m4
636     pmullw    m6, [r6+64]
637     paddsw    m6, m5
638
639     ; then calculate positive taps
640     movh      m5, [r2+2*r3]                ; read new row
641     punpcklbw m5, m7
642     pmullw    m0, [r6+0]
643     paddsw    m6, m0
644     mova      m0, m1
645     mova      m1, m2
646     pmullw    m2, [r6+32]
647     paddsw    m6, m2
648     mova      m2, m3
649     pmullw    m3, [r6+48]
650     paddsw    m6, m3
651     mova      m3, m4
652     mova      m4, m5
653     pmullw    m5, [r6+80]
654     paddsw    m6, m5
655
656     ; round/clip/store
657     paddsw    m6, [pw_64]
658     psraw     m6, 7
659     packuswb  m6, m7
660     movh    [r0], m6
661
662     ; go to next line
663     add       r0, r1
664     add       r2, r3
665     dec       r4                           ; next row
666     jg .nextrow
667     REP_RET
668 %endmacro
669
670 INIT_MMX
671 FILTER_V mmxext, 4, 0
672 INIT_XMM
673 FILTER_V sse2,   8, 8
674
675 %macro FILTER_BILINEAR 3
676 cglobal put_vp8_bilinear%2_v_%1, 7,7,%3
677     mov      r5d, 8*16
678     shl      r6d, 4
679     sub      r5d, r6d
680 %ifdef PIC
681     lea      r11, [bilinear_filter_vw_m]
682 %endif
683     pxor      m6, m6
684     mova      m4, [bilinear_filter_vw+r5-16]
685     mova      m5, [bilinear_filter_vw+r6-16]
686 .nextrow
687     movh      m0, [r2+r3*0]
688     movh      m1, [r2+r3*1]
689     movh      m3, [r2+r3*2]
690     punpcklbw m0, m6
691     punpcklbw m1, m6
692     punpcklbw m3, m6
693     mova      m2, m1
694     pmullw    m0, m4
695     pmullw    m1, m5
696     pmullw    m2, m4
697     pmullw    m3, m5
698     paddsw    m0, m1
699     paddsw    m2, m3
700     psraw     m0, 2
701     psraw     m2, 2
702     pavgw     m0, m6
703     pavgw     m2, m6
704 %ifidn %1, mmxext
705     packuswb  m0, m0
706     packuswb  m2, m2
707     movh [r0+r1*0], m0
708     movh [r0+r1*1], m2
709 %else
710     packuswb  m0, m2
711     movh   [r0+r1*0], m0
712     movhps [r0+r1*1], m0
713 %endif
714
715     lea       r0, [r0+r1*2]
716     lea       r2, [r2+r3*2]
717     sub       r4, 2
718     jg .nextrow
719     REP_RET
720
721 cglobal put_vp8_bilinear%2_h_%1, 7,7,%3
722     mov      r6d, 8*16
723     shl      r5d, 4
724     sub      r6d, r5d
725 %ifdef PIC
726     lea      r11, [bilinear_filter_vw_m]
727 %endif
728     pxor      m6, m6
729     mova      m4, [bilinear_filter_vw+r6-16]
730     mova      m5, [bilinear_filter_vw+r5-16]
731 .nextrow
732     movh      m0, [r2+r3*0+0]
733     movh      m1, [r2+r3*0+1]
734     movh      m2, [r2+r3*1+0]
735     movh      m3, [r2+r3*1+1]
736     punpcklbw m0, m6
737     punpcklbw m1, m6
738     punpcklbw m2, m6
739     punpcklbw m3, m6
740     pmullw    m0, m4
741     pmullw    m1, m5
742     pmullw    m2, m4
743     pmullw    m3, m5
744     paddsw    m0, m1
745     paddsw    m2, m3
746     psraw     m0, 2
747     psraw     m2, 2
748     pavgw     m0, m6
749     pavgw     m2, m6
750 %ifidn %1, mmxext
751     packuswb  m0, m0
752     packuswb  m2, m2
753     movh [r0+r1*0], m0
754     movh [r0+r1*1], m2
755 %else
756     packuswb  m0, m2
757     movh   [r0+r1*0], m0
758     movhps [r0+r1*1], m0
759 %endif
760
761     lea       r0, [r0+r1*2]
762     lea       r2, [r2+r3*2]
763     sub       r4, 2
764     jg .nextrow
765     REP_RET
766 %endmacro
767
768 INIT_MMX
769 FILTER_BILINEAR mmxext, 4, 0
770 INIT_XMM
771 FILTER_BILINEAR   sse2, 8, 7
772
773 %macro FILTER_BILINEAR_SSSE3 1
774 cglobal put_vp8_bilinear%1_v_ssse3, 7,7
775     shl      r6d, 4
776 %ifdef PIC
777     lea      r11, [bilinear_filter_vb_m]
778 %endif
779     pxor      m4, m4
780     mova      m3, [bilinear_filter_vb+r6-16]
781 .nextrow
782     movh      m0, [r2+r3*0]
783     movh      m1, [r2+r3*1]
784     movh      m2, [r2+r3*2]
785     punpcklbw m0, m1
786     punpcklbw m1, m2
787     pmaddubsw m0, m3
788     pmaddubsw m1, m3
789     psraw     m0, 2
790     psraw     m1, 2
791     pavgw     m0, m4
792     pavgw     m1, m4
793 %if mmsize==8
794     packuswb  m0, m0
795     packuswb  m1, m1
796     movh [r0+r1*0], m0
797     movh [r0+r1*1], m1
798 %else
799     packuswb  m0, m1
800     movh   [r0+r1*0], m0
801     movhps [r0+r1*1], m0
802 %endif
803
804     lea       r0, [r0+r1*2]
805     lea       r2, [r2+r3*2]
806     sub       r4, 2
807     jg .nextrow
808     REP_RET
809
810 cglobal put_vp8_bilinear%1_h_ssse3, 7,7
811     shl      r5d, 4
812 %ifdef PIC
813     lea      r11, [bilinear_filter_vb_m]
814 %endif
815     pxor      m4, m4
816     mova      m2, [filter_h2_shuf]
817     mova      m3, [bilinear_filter_vb+r5-16]
818 .nextrow
819     movu      m0, [r2+r3*0]
820     movu      m1, [r2+r3*1]
821     pshufb    m0, m2
822     pshufb    m1, m2
823     pmaddubsw m0, m3
824     pmaddubsw m1, m3
825     psraw     m0, 2
826     psraw     m1, 2
827     pavgw     m0, m4
828     pavgw     m1, m4
829 %if mmsize==8
830     packuswb  m0, m0
831     packuswb  m1, m1
832     movh [r0+r1*0], m0
833     movh [r0+r1*1], m1
834 %else
835     packuswb  m0, m1
836     movh   [r0+r1*0], m0
837     movhps [r0+r1*1], m0
838 %endif
839
840     lea       r0, [r0+r1*2]
841     lea       r2, [r2+r3*2]
842     sub       r4, 2
843     jg .nextrow
844     REP_RET
845 %endmacro
846
847 INIT_MMX
848 FILTER_BILINEAR_SSSE3 4
849 INIT_XMM
850 FILTER_BILINEAR_SSSE3 8
851
852 cglobal put_vp8_pixels8_mmx, 5,5
853 .nextrow:
854     movq  mm0, [r2+r3*0]
855     movq  mm1, [r2+r3*1]
856     lea    r2, [r2+r3*2]
857     movq [r0+r1*0], mm0
858     movq [r0+r1*1], mm1
859     lea    r0, [r0+r1*2]
860     sub   r4d, 2
861     jg .nextrow
862     REP_RET
863
864 cglobal put_vp8_pixels16_mmx, 5,5
865 .nextrow:
866     movq  mm0, [r2+r3*0+0]
867     movq  mm1, [r2+r3*0+8]
868     movq  mm2, [r2+r3*1+0]
869     movq  mm3, [r2+r3*1+8]
870     lea    r2, [r2+r3*2]
871     movq [r0+r1*0+0], mm0
872     movq [r0+r1*0+8], mm1
873     movq [r0+r1*1+0], mm2
874     movq [r0+r1*1+8], mm3
875     lea    r0, [r0+r1*2]
876     sub   r4d, 2
877     jg .nextrow
878     REP_RET
879
880 cglobal put_vp8_pixels16_sse, 5,5,2
881 .nextrow:
882     movups xmm0, [r2+r3*0]
883     movups xmm1, [r2+r3*1]
884     lea     r2, [r2+r3*2]
885     movaps [r0+r1*0], xmm0
886     movaps [r0+r1*1], xmm1
887     lea     r0, [r0+r1*2]
888     sub    r4d, 2
889     jg .nextrow
890     REP_RET
891
892 ;-----------------------------------------------------------------------------
893 ; void vp8_idct_dc_add_<opt>(uint8_t *dst, DCTELEM block[16], int stride);
894 ;-----------------------------------------------------------------------------
895
896 %macro ADD_DC 4
897     %4        m2, [r0+%3]
898     %4        m3, [r0+r2+%3]
899     %4        m4, [r1+%3]
900     %4        m5, [r1+r2+%3]
901     paddusb   m2, %1
902     paddusb   m3, %1
903     paddusb   m4, %1
904     paddusb   m5, %1
905     psubusb   m2, %2
906     psubusb   m3, %2
907     psubusb   m4, %2
908     psubusb   m5, %2
909     %4    [r0+%3], m2
910     %4 [r0+r2+%3], m3
911     %4    [r1+%3], m4
912     %4 [r1+r2+%3], m5
913 %endmacro
914
915 INIT_MMX
916 cglobal vp8_idct_dc_add_mmx, 3, 3
917     ; load data
918     movd       m0, [r1]
919
920     ; calculate DC
921     paddw      m0, [pw_4]
922     pxor       m1, m1
923     psraw      m0, 3
924     movd      [r1], m1
925     psubw      m1, m0
926     packuswb   m0, m0
927     packuswb   m1, m1
928     punpcklbw  m0, m0
929     punpcklbw  m1, m1
930     punpcklwd  m0, m0
931     punpcklwd  m1, m1
932
933     ; add DC
934     lea        r1, [r0+r2*2]
935     ADD_DC     m0, m1, 0, movh
936     RET
937
938 INIT_XMM
939 cglobal vp8_idct_dc_add_sse4, 3, 3, 6
940     ; load data
941     movd       m0, [r1]
942     pxor       m1, m1
943
944     ; calculate DC
945     paddw      m0, [pw_4]
946     movd     [r1], m1
947     lea        r1, [r0+r2*2]
948     movd       m2, [r0]
949     movd       m3, [r0+r2]
950     movd       m4, [r1]
951     movd       m5, [r1+r2]
952     psraw      m0, 3
953     pshuflw    m0, m0, 0
954     punpcklqdq m0, m0
955     punpckldq  m2, m3
956     punpckldq  m4, m5
957     punpcklbw  m2, m1
958     punpcklbw  m4, m1
959     paddw      m2, m0
960     paddw      m4, m0
961     packuswb   m2, m4
962     movd      [r0], m2
963     pextrd [r0+r2], m2, 1
964     pextrd    [r1], m2, 2
965     pextrd [r1+r2], m2, 3
966     RET
967
968 ;-----------------------------------------------------------------------------
969 ; void vp8_idct_dc_add4y_<opt>(uint8_t *dst, DCTELEM block[4][16], int stride);
970 ;-----------------------------------------------------------------------------
971
972 INIT_MMX
973 cglobal vp8_idct_dc_add4y_mmx, 3, 3
974     ; load data
975     movd      m0, [r1+32*0] ; A
976     movd      m1, [r1+32*2] ; C
977     punpcklwd m0, [r1+32*1] ; A B
978     punpcklwd m1, [r1+32*3] ; C D
979     punpckldq m0, m1        ; A B C D
980     pxor      m6, m6
981
982     ; calculate DC
983     paddw     m0, [pw_4]
984     movd [r1+32*0], m6
985     movd [r1+32*1], m6
986     movd [r1+32*2], m6
987     movd [r1+32*3], m6
988     psraw     m0, 3
989     psubw     m6, m0
990     packuswb  m0, m0
991     packuswb  m6, m6
992     punpcklbw m0, m0 ; AABBCCDD
993     punpcklbw m6, m6 ; AABBCCDD
994     movq      m1, m0
995     movq      m7, m6
996     punpcklbw m0, m0 ; AAAABBBB
997     punpckhbw m1, m1 ; CCCCDDDD
998     punpcklbw m6, m6 ; AAAABBBB
999     punpckhbw m7, m7 ; CCCCDDDD
1000
1001     ; add DC
1002     lea       r1, [r0+r2*2]
1003     ADD_DC    m0, m6, 0, mova
1004     ADD_DC    m1, m7, 8, mova
1005     RET
1006
1007 INIT_XMM
1008 cglobal vp8_idct_dc_add4y_sse2, 3, 3, 6
1009     ; load data
1010     movd      m0, [r1+32*0] ; A
1011     movd      m1, [r1+32*2] ; C
1012     punpcklwd m0, [r1+32*1] ; A B
1013     punpcklwd m1, [r1+32*3] ; C D
1014     punpckldq m0, m1        ; A B C D
1015     pxor      m1, m1
1016
1017     ; calculate DC
1018     paddw     m0, [pw_4]
1019     movd [r1+32*0], m1
1020     movd [r1+32*1], m1
1021     movd [r1+32*2], m1
1022     movd [r1+32*3], m1
1023     psraw     m0, 3
1024     psubw     m1, m0
1025     packuswb  m0, m0
1026     packuswb  m1, m1
1027     punpcklbw m0, m0
1028     punpcklbw m1, m1
1029     punpcklbw m0, m0
1030     punpcklbw m1, m1
1031
1032     ; add DC
1033     lea       r1, [r0+r2*2]
1034     ADD_DC    m0, m1, 0, mova
1035     RET
1036
1037 ;-----------------------------------------------------------------------------
1038 ; void vp8_idct_dc_add4uv_<opt>(uint8_t *dst, DCTELEM block[4][16], int stride);
1039 ;-----------------------------------------------------------------------------
1040
1041 INIT_MMX
1042 cglobal vp8_idct_dc_add4uv_mmx, 3, 3
1043     ; load data
1044     movd      m0, [r1+32*0] ; A
1045     movd      m1, [r1+32*2] ; C
1046     punpcklwd m0, [r1+32*1] ; A B
1047     punpcklwd m1, [r1+32*3] ; C D
1048     punpckldq m0, m1        ; A B C D
1049     pxor      m6, m6
1050
1051     ; calculate DC
1052     paddw     m0, [pw_4]
1053     movd [r1+32*0], m6
1054     movd [r1+32*1], m6
1055     movd [r1+32*2], m6
1056     movd [r1+32*3], m6
1057     psraw     m0, 3
1058     psubw     m6, m0
1059     packuswb  m0, m0
1060     packuswb  m6, m6
1061     punpcklbw m0, m0 ; AABBCCDD
1062     punpcklbw m6, m6 ; AABBCCDD
1063     movq      m1, m0
1064     movq      m7, m6
1065     punpcklbw m0, m0 ; AAAABBBB
1066     punpckhbw m1, m1 ; CCCCDDDD
1067     punpcklbw m6, m6 ; AAAABBBB
1068     punpckhbw m7, m7 ; CCCCDDDD
1069
1070     ; add DC
1071     lea       r1, [r0+r2*2]
1072     ADD_DC    m0, m6, 0, mova
1073     lea       r0, [r0+r2*4]
1074     lea       r1, [r1+r2*4]
1075     ADD_DC    m1, m7, 0, mova
1076     RET
1077
1078 ;-----------------------------------------------------------------------------
1079 ; void vp8_idct_add_<opt>(uint8_t *dst, DCTELEM block[16], int stride);
1080 ;-----------------------------------------------------------------------------
1081
1082 ; calculate %1=mul_35468(%1)-mul_20091(%2); %2=mul_20091(%1)+mul_35468(%2)
1083 ;           this macro assumes that m6/m7 have words for 20091/17734 loaded
1084 %macro VP8_MULTIPLY_SUMSUB 4
1085     mova      %3, %1
1086     mova      %4, %2
1087     pmulhw    %3, m6 ;20091(1)
1088     pmulhw    %4, m6 ;20091(2)
1089     paddw     %3, %1
1090     paddw     %4, %2
1091     paddw     %1, %1
1092     paddw     %2, %2
1093     pmulhw    %1, m7 ;35468(1)
1094     pmulhw    %2, m7 ;35468(2)
1095     psubw     %1, %4
1096     paddw     %2, %3
1097 %endmacro
1098
1099 ; calculate x0=%1+%3; x1=%1-%3
1100 ;           x2=mul_35468(%2)-mul_20091(%4); x3=mul_20091(%2)+mul_35468(%4)
1101 ;           %1=x0+x3 (tmp0); %2=x1+x2 (tmp1); %3=x1-x2 (tmp2); %4=x0-x3 (tmp3)
1102 ;           %5/%6 are temporary registers
1103 ;           we assume m6/m7 have constant words 20091/17734 loaded in them
1104 %macro VP8_IDCT_TRANSFORM4x4_1D 6
1105     SUMSUB_BA           m%3, m%1, m%5     ;t0, t1
1106     VP8_MULTIPLY_SUMSUB m%2, m%4, m%5,m%6 ;t2, t3
1107     SUMSUB_BA           m%4, m%3, m%5     ;tmp0, tmp3
1108     SUMSUB_BA           m%2, m%1, m%5     ;tmp1, tmp2
1109     SWAP                 %4,  %1
1110     SWAP                 %4,  %3
1111 %endmacro
1112
1113 INIT_MMX
1114 %macro VP8_IDCT_ADD 1
1115 cglobal vp8_idct_add_%1, 3, 3
1116     ; load block data
1117     movq         m0, [r1+ 0]
1118     movq         m1, [r1+ 8]
1119     movq         m2, [r1+16]
1120     movq         m3, [r1+24]
1121     movq         m6, [pw_20091]
1122     movq         m7, [pw_17734]
1123 %ifidn %1, sse
1124     xorps      xmm0, xmm0
1125     movaps  [r1+ 0], xmm0
1126     movaps  [r1+16], xmm0
1127 %else
1128     pxor         m4, m4
1129     movq    [r1+ 0], m4
1130     movq    [r1+ 8], m4
1131     movq    [r1+16], m4
1132     movq    [r1+24], m4
1133 %endif
1134
1135     ; actual IDCT
1136     VP8_IDCT_TRANSFORM4x4_1D 0, 1, 2, 3, 4, 5
1137     TRANSPOSE4x4W            0, 1, 2, 3, 4
1138     paddw        m0, [pw_4]
1139     VP8_IDCT_TRANSFORM4x4_1D 0, 1, 2, 3, 4, 5
1140     TRANSPOSE4x4W            0, 1, 2, 3, 4
1141
1142     ; store
1143     pxor         m4, m4
1144     lea          r1, [r0+2*r2]
1145     STORE_DIFFx2 m0, m1, m6, m7, m4, 3, r0, r2
1146     STORE_DIFFx2 m2, m3, m6, m7, m4, 3, r1, r2
1147
1148     RET
1149 %endmacro
1150
1151 VP8_IDCT_ADD mmx
1152 VP8_IDCT_ADD sse
1153
1154 ;-----------------------------------------------------------------------------
1155 ; void vp8_luma_dc_wht_mmxext(DCTELEM block[4][4][16], DCTELEM dc[16])
1156 ;-----------------------------------------------------------------------------
1157
1158 %macro SCATTER_WHT 3
1159     movd  r1d, m%1
1160     movd  r2d, m%2
1161     mov [r0+2*16*(0+%3)], r1w
1162     mov [r0+2*16*(1+%3)], r2w
1163     shr   r1d, 16
1164     shr   r2d, 16
1165     psrlq m%1, 32
1166     psrlq m%2, 32
1167     mov [r0+2*16*(4+%3)], r1w
1168     mov [r0+2*16*(5+%3)], r2w
1169     movd  r1d, m%1
1170     movd  r2d, m%2
1171     mov [r0+2*16*(8+%3)], r1w
1172     mov [r0+2*16*(9+%3)], r2w
1173     shr   r1d, 16
1174     shr   r2d, 16
1175     mov [r0+2*16*(12+%3)], r1w
1176     mov [r0+2*16*(13+%3)], r2w
1177 %endmacro
1178
1179 %macro HADAMARD4_1D 4
1180     SUMSUB_BADC m%2, m%1, m%4, m%3
1181     SUMSUB_BADC m%4, m%2, m%3, m%1
1182     SWAP %1, %4, %3
1183 %endmacro
1184
1185 INIT_MMX
1186 cglobal vp8_luma_dc_wht_mmx, 2,3
1187     movq          m0, [r1]
1188     movq          m1, [r1+8]
1189     movq          m2, [r1+16]
1190     movq          m3, [r1+24]
1191     HADAMARD4_1D  0, 1, 2, 3
1192     TRANSPOSE4x4W 0, 1, 2, 3, 4
1193     paddw         m0, [pw_3]
1194     HADAMARD4_1D  0, 1, 2, 3
1195     psraw         m0, 3
1196     psraw         m1, 3
1197     psraw         m2, 3
1198     psraw         m3, 3
1199     SCATTER_WHT   0, 1, 0
1200     SCATTER_WHT   2, 3, 2
1201     RET
1202
1203 ;-----------------------------------------------------------------------------
1204 ; void vp8_h/v_loop_filter_simple_<opt>(uint8_t *dst, int stride, int flim);
1205 ;-----------------------------------------------------------------------------
1206
1207 ; macro called with 7 mm register indexes as argument, and 4 regular registers
1208 ;
1209 ; first 4 mm registers will carry the transposed pixel data
1210 ; the other three are scratchspace (one would be sufficient, but this allows
1211 ; for more spreading/pipelining and thus faster execution on OOE CPUs)
1212 ;
1213 ; first two regular registers are buf+4*stride and buf+5*stride
1214 ; third is -stride, fourth is +stride
1215 %macro READ_8x4_INTERLEAVED 11
1216     ; interleave 8 (A-H) rows of 4 pixels each
1217     movd          m%1, [%8+%10*4]   ; A0-3
1218     movd          m%5, [%9+%10*4]   ; B0-3
1219     movd          m%2, [%8+%10*2]   ; C0-3
1220     movd          m%6, [%8+%10]     ; D0-3
1221     movd          m%3, [%8]         ; E0-3
1222     movd          m%7, [%9]         ; F0-3
1223     movd          m%4, [%9+%11]     ; G0-3
1224     punpcklbw     m%1, m%5          ; A/B interleaved
1225     movd          m%5, [%9+%11*2]   ; H0-3
1226     punpcklbw     m%2, m%6          ; C/D interleaved
1227     punpcklbw     m%3, m%7          ; E/F interleaved
1228     punpcklbw     m%4, m%5          ; G/H interleaved
1229 %endmacro
1230
1231 ; macro called with 7 mm register indexes as argument, and 5 regular registers
1232 ; first 11 mean the same as READ_8x4_TRANSPOSED above
1233 ; fifth regular register is scratchspace to reach the bottom 8 rows, it
1234 ; will be set to second regular register + 8*stride at the end
1235 %macro READ_16x4_INTERLEAVED 12
1236     ; transpose 16 (A-P) rows of 4 pixels each
1237     lea           %12, [r0+8*r2]
1238
1239     ; read (and interleave) those addressable by %8 (=r0), A/C/D/E/I/K/L/M
1240     movd          m%1, [%8+%10*4]   ; A0-3
1241     movd          m%3, [%12+%10*4]  ; I0-3
1242     movd          m%2, [%8+%10*2]   ; C0-3
1243     movd          m%4, [%12+%10*2]  ; K0-3
1244     movd          m%6, [%8+%10]     ; D0-3
1245     movd          m%5, [%12+%10]    ; L0-3
1246     movd          m%7, [%12]        ; M0-3
1247     add           %12, %11
1248     punpcklbw     m%1, m%3          ; A/I
1249     movd          m%3, [%8]         ; E0-3
1250     punpcklbw     m%2, m%4          ; C/K
1251     punpcklbw     m%6, m%5          ; D/L
1252     punpcklbw     m%3, m%7          ; E/M
1253     punpcklbw     m%2, m%6          ; C/D/K/L interleaved
1254
1255     ; read (and interleave) those addressable by %9 (=r4), B/F/G/H/J/N/O/P
1256     movd         m%5, [%9+%10*4]   ; B0-3
1257     movd         m%4, [%12+%10*4]  ; J0-3
1258     movd         m%7, [%9]         ; F0-3
1259     movd         m%6, [%12]        ; N0-3
1260     punpcklbw    m%5, m%4          ; B/J
1261     punpcklbw    m%7, m%6          ; F/N
1262     punpcklbw    m%1, m%5          ; A/B/I/J interleaved
1263     punpcklbw    m%3, m%7          ; E/F/M/N interleaved
1264     movd         m%4, [%9+%11]     ; G0-3
1265     movd         m%6, [%12+%11]    ; O0-3
1266     movd         m%5, [%9+%11*2]   ; H0-3
1267     movd         m%7, [%12+%11*2]  ; P0-3
1268     punpcklbw    m%4, m%6          ; G/O
1269     punpcklbw    m%5, m%7          ; H/P
1270     punpcklbw    m%4, m%5          ; G/H/O/P interleaved
1271 %endmacro
1272
1273 ; write 4 mm registers of 2 dwords each
1274 ; first four arguments are mm register indexes containing source data
1275 ; last four are registers containing buf+4*stride, buf+5*stride,
1276 ; -stride and +stride
1277 %macro WRITE_4x2D 8
1278     ; write out (2 dwords per register)
1279     movd    [%5+%7*4], m%1
1280     movd    [%5+%7*2], m%2
1281     movd         [%5], m%3
1282     movd      [%6+%8], m%4
1283     punpckhdq     m%1, m%1
1284     punpckhdq     m%2, m%2
1285     punpckhdq     m%3, m%3
1286     punpckhdq     m%4, m%4
1287     movd    [%6+%7*4], m%1
1288     movd      [%5+%7], m%2
1289     movd         [%6], m%3
1290     movd    [%6+%8*2], m%4
1291 %endmacro
1292
1293 ; write 4 xmm registers of 4 dwords each
1294 ; arguments same as WRITE_2x4D, but with an extra register, so that the 5 regular
1295 ; registers contain buf+4*stride, buf+5*stride, buf+12*stride, -stride and +stride
1296 ; we add 1*stride to the third regular registry in the process
1297 ; the 10th argument is 16 if it's a Y filter (i.e. all regular registers cover the
1298 ; same memory region), or 8 if they cover two separate buffers (third one points to
1299 ; a different memory region than the first two), allowing for more optimal code for
1300 ; the 16-width case
1301 %macro WRITE_4x4D 10
1302     ; write out (4 dwords per register), start with dwords zero
1303     movd    [%5+%8*4], m%1
1304     movd         [%5], m%2
1305     movd    [%7+%8*4], m%3
1306     movd         [%7], m%4
1307
1308     ; store dwords 1
1309     psrldq        m%1, 4
1310     psrldq        m%2, 4
1311     psrldq        m%3, 4
1312     psrldq        m%4, 4
1313     movd    [%6+%8*4], m%1
1314     movd         [%6], m%2
1315 %if %10 == 16
1316     movd    [%6+%9*4], m%3
1317 %endif
1318     movd      [%7+%9], m%4
1319
1320     ; write dwords 2
1321     psrldq        m%1, 4
1322     psrldq        m%2, 4
1323 %if %10 == 8
1324     movd    [%5+%8*2], m%1
1325     movd           %5, m%3
1326 %endif
1327     psrldq        m%3, 4
1328     psrldq        m%4, 4
1329 %if %10 == 16
1330     movd    [%5+%8*2], m%1
1331 %endif
1332     movd      [%6+%9], m%2
1333     movd    [%7+%8*2], m%3
1334     movd    [%7+%9*2], m%4
1335     add            %7, %9
1336
1337     ; store dwords 3
1338     psrldq        m%1, 4
1339     psrldq        m%2, 4
1340     psrldq        m%3, 4
1341     psrldq        m%4, 4
1342 %if %10 == 8
1343     mov     [%7+%8*4], %5d
1344     movd    [%6+%8*2], m%1
1345 %else
1346     movd      [%5+%8], m%1
1347 %endif
1348     movd    [%6+%9*2], m%2
1349     movd    [%7+%8*2], m%3
1350     movd    [%7+%9*2], m%4
1351 %endmacro
1352
1353 %macro SPLATB_REG_MMX 2-3
1354     movd           %1, %2
1355     punpcklbw      %1, %1
1356     punpcklwd      %1, %1
1357     punpckldq      %1, %1
1358 %endmacro
1359
1360 %macro SPLATB_REG_MMXEXT 2-3
1361     movd           %1, %2
1362     punpcklbw      %1, %1
1363     pshufw         %1, %1, 0x0
1364 %endmacro
1365
1366 %macro SPLATB_REG_SSE2 2-3
1367     movd           %1, %2
1368     punpcklbw      %1, %1
1369     pshuflw        %1, %1, 0x0
1370     punpcklqdq     %1, %1
1371 %endmacro
1372
1373 %macro SPLATB_REG_SSSE3 3
1374     movd           %1, %2
1375     pshufb         %1, %3
1376 %endmacro
1377
1378 %macro SIMPLE_LOOPFILTER 3
1379 cglobal vp8_%2_loop_filter_simple_%1, 3, %3
1380 %ifidn %2, h
1381     mov            r5, rsp          ; backup stack pointer
1382     and           rsp, ~(mmsize-1)  ; align stack
1383 %endif
1384 %if mmsize == 8 ; mmx/mmxext
1385     mov            r3, 2
1386 %endif
1387 %ifnidn %1, sse2
1388 %if mmsize == 16
1389     pxor           m0, m0
1390 %endif
1391 %endif
1392     SPLATB_REG     m7, r2, m0       ; splat "flim" into register
1393
1394     ; set up indexes to address 4 rows
1395     mov            r2, r1
1396     neg            r1
1397 %ifidn %2, h
1398     lea            r0, [r0+4*r2-2]
1399     sub           rsp, mmsize*2     ; (aligned) storage space for saving p1/q1
1400 %endif
1401
1402 %if mmsize == 8 ; mmx / mmxext
1403 .next8px
1404 %endif
1405 %ifidn %2, v
1406     ; read 4 half/full rows of pixels
1407     mova           m0, [r0+r1*2]    ; p1
1408     mova           m1, [r0+r1]      ; p0
1409     mova           m2, [r0]         ; q0
1410     mova           m3, [r0+r2]      ; q1
1411 %else ; h
1412     lea            r4, [r0+r2]
1413
1414 %if mmsize == 8 ; mmx/mmxext
1415     READ_8x4_INTERLEAVED  0, 1, 2, 3, 4, 5, 6, r0, r4, r1, r2
1416 %else ; sse2
1417     READ_16x4_INTERLEAVED 0, 1, 2, 3, 4, 5, 6, r0, r4, r1, r2, r3
1418 %endif
1419     TRANSPOSE4x4W         0, 1, 2, 3, 4
1420
1421     mova        [rsp], m0           ; store p1
1422     mova [rsp+mmsize], m3           ; store q1
1423 %endif
1424
1425     ; simple_limit
1426     mova           m5, m2           ; m5=backup of q0
1427     mova           m6, m1           ; m6=backup of p0
1428     psubusb        m1, m2           ; p0-q0
1429     psubusb        m2, m6           ; q0-p0
1430     por            m1, m2           ; FFABS(p0-q0)
1431     paddusb        m1, m1           ; m1=FFABS(p0-q0)*2
1432
1433     mova           m4, m3
1434     mova           m2, m0
1435     psubusb        m3, m0           ; q1-p1
1436     psubusb        m0, m4           ; p1-q1
1437     por            m3, m0           ; FFABS(p1-q1)
1438     mova           m0, [pb_80]
1439     pxor           m2, m0
1440     pxor           m4, m0
1441     psubsb         m2, m4           ; m2=p1-q1 (signed) backup for below
1442     pand           m3, [pb_FE]
1443     psrlq          m3, 1            ; m3=FFABS(p1-q1)/2, this can be used signed
1444     paddusb        m3, m1
1445     psubusb        m3, m7
1446     pxor           m1, m1
1447     pcmpeqb        m3, m1           ; abs(p0-q0)*2+abs(p1-q1)/2<=flim mask(0xff/0x0)
1448
1449     ; filter_common (use m2/p1-q1, m4=q0, m6=p0, m5/q0-p0 and m3/mask)
1450     mova           m4, m5
1451     pxor           m5, m0
1452     pxor           m0, m6
1453     psubsb         m5, m0           ; q0-p0 (signed)
1454     paddsb         m2, m5
1455     paddsb         m2, m5
1456     paddsb         m2, m5           ; a=(p1-q1) + 3*(q0-p0)
1457     pand           m2, m3           ; apply filter mask (m3)
1458
1459     mova           m3, [pb_F8]
1460     mova           m1, m2
1461     paddsb         m2, [pb_4]       ; f1<<3=a+4
1462     paddsb         m1, [pb_3]       ; f2<<3=a+3
1463     pand           m2, m3
1464     pand           m1, m3           ; cache f2<<3
1465
1466     pxor           m0, m0
1467     pxor           m3, m3
1468     pcmpgtb        m0, m2           ; which values are <0?
1469     psubb          m3, m2           ; -f1<<3
1470     psrlq          m2, 3            ; +f1
1471     psrlq          m3, 3            ; -f1
1472     pand           m3, m0
1473     pandn          m0, m2
1474     psubusb        m4, m0
1475     paddusb        m4, m3           ; q0-f1
1476
1477     pxor           m0, m0
1478     pxor           m3, m3
1479     pcmpgtb        m0, m1           ; which values are <0?
1480     psubb          m3, m1           ; -f2<<3
1481     psrlq          m1, 3            ; +f2
1482     psrlq          m3, 3            ; -f2
1483     pand           m3, m0
1484     pandn          m0, m1
1485     paddusb        m6, m0
1486     psubusb        m6, m3           ; p0+f2
1487
1488     ; store
1489 %ifidn %2, v
1490     mova         [r0], m4
1491     mova      [r0+r1], m6
1492 %else ; h
1493     mova           m0, [rsp]        ; p1
1494     SWAP            2, 4            ; p0
1495     SWAP            1, 6            ; q0
1496     mova           m3, [rsp+mmsize] ; q1
1497
1498     TRANSPOSE4x4B  0, 1, 2, 3, 4
1499 %if mmsize == 16 ; sse2
1500     add            r3, r1           ; change from r4*8*stride to r0+8*stride
1501     WRITE_4x4D 0, 1, 2, 3, r0, r4, r3, r1, r2, 16
1502 %else ; mmx/mmxext
1503     WRITE_4x2D 0, 1, 2, 3, r0, r4, r1, r2
1504 %endif
1505 %endif
1506
1507 %if mmsize == 8 ; mmx/mmxext
1508     ; next 8 pixels
1509 %ifidn %2, v
1510     add            r0, 8            ; advance 8 cols = pixels
1511 %else ; h
1512     lea            r0, [r0+r2*8]    ; advance 8 rows = lines
1513 %endif
1514     dec            r3
1515     jg .next8px
1516 %ifidn %2, v
1517     REP_RET
1518 %else ; h
1519     mov           rsp, r5           ; restore stack pointer
1520     RET
1521 %endif
1522 %else ; sse2
1523 %ifidn %2, h
1524     mov           rsp, r5           ; restore stack pointer
1525 %endif
1526     RET
1527 %endif
1528 %endmacro
1529
1530 INIT_MMX
1531 %define SPLATB_REG SPLATB_REG_MMX
1532 SIMPLE_LOOPFILTER mmx,    v, 4
1533 SIMPLE_LOOPFILTER mmx,    h, 6
1534 %define SPLATB_REG SPLATB_REG_MMXEXT
1535 SIMPLE_LOOPFILTER mmxext, v, 4
1536 SIMPLE_LOOPFILTER mmxext, h, 6
1537 INIT_XMM
1538 %define SPLATB_REG SPLATB_REG_SSE2
1539 SIMPLE_LOOPFILTER sse2,   v, 3
1540 SIMPLE_LOOPFILTER sse2,   h, 6
1541 %define SPLATB_REG SPLATB_REG_SSSE3
1542 SIMPLE_LOOPFILTER ssse3,  v, 3
1543 SIMPLE_LOOPFILTER ssse3,  h, 6
1544
1545 ;-----------------------------------------------------------------------------
1546 ; void vp8_h/v_loop_filter<size>_inner_<opt>(uint8_t *dst, [uint8_t *v,] int stride,
1547 ;                                            int flimE, int flimI, int hev_thr);
1548 ;-----------------------------------------------------------------------------
1549
1550 %macro INNER_LOOPFILTER 5
1551 %if %4 == 8 ; chroma
1552 cglobal vp8_%2_loop_filter8uv_inner_%1, 6, %3, %5
1553 %define dst8_reg    r1
1554 %define mstride_reg r2
1555 %define E_reg       r3
1556 %define I_reg       r4
1557 %define hev_thr_reg r5
1558 %else ; luma
1559 cglobal vp8_%2_loop_filter16y_inner_%1, 5, %3, %5
1560 %define mstride_reg r1
1561 %define E_reg       r2
1562 %define I_reg       r3
1563 %define hev_thr_reg r4
1564 %ifdef m8 ; x86-64, sse2
1565 %define dst8_reg    r4
1566 %elif mmsize == 16 ; x86-32, sse2
1567 %define dst8_reg    r5
1568 %else ; x86-32, mmx/mmxext
1569 %define cnt_reg     r5
1570 %endif
1571 %endif
1572 %define dst_reg     r0
1573 %define stride_reg  E_reg
1574 %define dst2_reg    I_reg
1575 %ifndef m8
1576 %define stack_reg   hev_thr_reg
1577 %endif
1578
1579 %ifnidn %1, sse2
1580 %if mmsize == 16
1581     pxor             m7, m7
1582 %endif
1583 %endif
1584
1585 %ifndef m8 ; mmx/mmxext or sse2 on x86-32
1586     ; splat function arguments
1587     SPLATB_REG       m0, E_reg, m7   ; E
1588     SPLATB_REG       m1, I_reg, m7   ; I
1589     SPLATB_REG       m2, hev_thr_reg, m7 ; hev_thresh
1590
1591     ; align stack
1592     mov       stack_reg, rsp         ; backup stack pointer
1593     and             rsp, ~(mmsize-1) ; align stack
1594 %ifidn %2, v
1595     sub             rsp, mmsize * 4  ; stack layout: [0]=E, [1]=I, [2]=hev_thr
1596                                      ;               [3]=hev() result
1597 %else ; h
1598     sub             rsp, mmsize * 5  ; extra storage space for transposes
1599 %endif
1600
1601 %define flim_E   [rsp]
1602 %define flim_I   [rsp+mmsize]
1603 %define hev_thr  [rsp+mmsize*2]
1604 %define mask_res [rsp+mmsize*3]
1605 %define p0backup [rsp+mmsize*3]
1606 %define q0backup [rsp+mmsize*4]
1607
1608     mova         flim_E, m0
1609     mova         flim_I, m1
1610     mova        hev_thr, m2
1611
1612 %else ; sse2 on x86-64
1613
1614 %define flim_E   m9
1615 %define flim_I   m10
1616 %define hev_thr  m11
1617 %define mask_res m12
1618 %define p0backup m12
1619 %define q0backup m8
1620
1621     ; splat function arguments
1622     SPLATB_REG   flim_E, E_reg, m7   ; E
1623     SPLATB_REG   flim_I, I_reg, m7   ; I
1624     SPLATB_REG  hev_thr, hev_thr_reg, m7 ; hev_thresh
1625 %endif
1626
1627 %if mmsize == 8 && %4 == 16 ; mmx/mmxext
1628     mov         cnt_reg, 2
1629 %endif
1630     mov      stride_reg, mstride_reg
1631     neg     mstride_reg
1632 %ifidn %2, h
1633     lea         dst_reg, [dst_reg + stride_reg*4-4]
1634 %if %4 == 8
1635     lea        dst8_reg, [dst8_reg+ stride_reg*4-4]
1636 %endif
1637 %endif
1638
1639 %if mmsize == 8
1640 .next8px
1641 %endif
1642     ; read
1643     lea        dst2_reg, [dst_reg + stride_reg]
1644 %ifidn %2, v
1645 %if %4 == 8 && mmsize == 16
1646 %define movrow movh
1647 %else
1648 %define movrow mova
1649 %endif
1650     movrow           m0, [dst_reg +mstride_reg*4] ; p3
1651     movrow           m1, [dst2_reg+mstride_reg*4] ; p2
1652     movrow           m2, [dst_reg +mstride_reg*2] ; p1
1653     movrow           m5, [dst2_reg]               ; q1
1654     movrow           m6, [dst2_reg+ stride_reg]   ; q2
1655     movrow           m7, [dst2_reg+ stride_reg*2] ; q3
1656 %if mmsize == 16 && %4 == 8
1657     movhps           m0, [dst8_reg+mstride_reg*4]
1658     movhps           m2, [dst8_reg+mstride_reg*2]
1659     add        dst8_reg, stride_reg
1660     movhps           m1, [dst8_reg+mstride_reg*4]
1661     movhps           m5, [dst8_reg]
1662     movhps           m6, [dst8_reg+ stride_reg]
1663     movhps           m7, [dst8_reg+ stride_reg*2]
1664     add        dst8_reg, mstride_reg
1665 %endif
1666 %elif mmsize == 8 ; mmx/mmxext (h)
1667     ; read 8 rows of 8px each
1668     movu             m0, [dst_reg +mstride_reg*4]
1669     movu             m1, [dst2_reg+mstride_reg*4]
1670     movu             m2, [dst_reg +mstride_reg*2]
1671     movu             m3, [dst_reg +mstride_reg]
1672     movu             m4, [dst_reg]
1673     movu             m5, [dst2_reg]
1674     movu             m6, [dst2_reg+ stride_reg]
1675
1676     ; 8x8 transpose
1677     TRANSPOSE4x4B     0, 1, 2, 3, 7
1678     mova       q0backup, m1
1679     movu             m7, [dst2_reg+ stride_reg*2]
1680     TRANSPOSE4x4B     4, 5, 6, 7, 1
1681     SBUTTERFLY       dq, 0, 4, 1     ; p3/p2
1682     SBUTTERFLY       dq, 2, 6, 1     ; q0/q1
1683     SBUTTERFLY       dq, 3, 7, 1     ; q2/q3
1684     mova             m1, q0backup
1685     mova       q0backup, m2          ; store q0
1686     SBUTTERFLY       dq, 1, 5, 2     ; p1/p0
1687     mova       p0backup, m5          ; store p0
1688     SWAP              1, 4
1689     SWAP              2, 4
1690     SWAP              6, 3
1691     SWAP              5, 3
1692 %else ; sse2 (h)
1693 %if %4 == 16
1694     lea        dst8_reg, [dst_reg + stride_reg*8]
1695 %endif
1696
1697     ; read 16 rows of 8px each, interleave
1698     movh             m0, [dst_reg +mstride_reg*4]
1699     movh             m1, [dst8_reg+mstride_reg*4]
1700     movh             m2, [dst_reg +mstride_reg*2]
1701     movh             m5, [dst8_reg+mstride_reg*2]
1702     movh             m3, [dst_reg +mstride_reg]
1703     movh             m6, [dst8_reg+mstride_reg]
1704     movh             m4, [dst_reg]
1705     movh             m7, [dst8_reg]
1706     punpcklbw        m0, m1          ; A/I
1707     punpcklbw        m2, m5          ; C/K
1708     punpcklbw        m3, m6          ; D/L
1709     punpcklbw        m4, m7          ; E/M
1710
1711     add        dst8_reg, stride_reg
1712     movh             m1, [dst2_reg+mstride_reg*4]
1713     movh             m6, [dst8_reg+mstride_reg*4]
1714     movh             m5, [dst2_reg]
1715     movh             m7, [dst8_reg]
1716     punpcklbw        m1, m6          ; B/J
1717     punpcklbw        m5, m7          ; F/N
1718     movh             m6, [dst2_reg+ stride_reg]
1719     movh             m7, [dst8_reg+ stride_reg]
1720     punpcklbw        m6, m7          ; G/O
1721
1722     ; 8x16 transpose
1723     TRANSPOSE4x4B     0, 1, 2, 3, 7
1724 %ifdef m8
1725     SWAP              1, 8
1726 %else
1727     mova       q0backup, m1
1728 %endif
1729     movh             m7, [dst2_reg+ stride_reg*2]
1730     movh             m1, [dst8_reg+ stride_reg*2]
1731     punpcklbw        m7, m1          ; H/P
1732     TRANSPOSE4x4B     4, 5, 6, 7, 1
1733     SBUTTERFLY       dq, 0, 4, 1     ; p3/p2
1734     SBUTTERFLY       dq, 2, 6, 1     ; q0/q1
1735     SBUTTERFLY       dq, 3, 7, 1     ; q2/q3
1736 %ifdef m8
1737     SWAP              1, 8
1738     SWAP              2, 8
1739 %else
1740     mova             m1, q0backup
1741     mova       q0backup, m2          ; store q0
1742 %endif
1743     SBUTTERFLY       dq, 1, 5, 2     ; p1/p0
1744 %ifdef m12
1745     SWAP              5, 12
1746 %else
1747     mova       p0backup, m5          ; store p0
1748 %endif
1749     SWAP              1, 4
1750     SWAP              2, 4
1751     SWAP              6, 3
1752     SWAP              5, 3
1753 %endif
1754
1755     ; normal_limit for p3-p2, p2-p1, q3-q2 and q2-q1
1756     mova             m4, m1
1757     SWAP              4, 1
1758     psubusb          m4, m0          ; p2-p3
1759     psubusb          m0, m1          ; p3-p2
1760     por              m0, m4          ; abs(p3-p2)
1761
1762     mova             m4, m2
1763     SWAP              4, 2
1764     psubusb          m4, m1          ; p1-p2
1765     psubusb          m1, m2          ; p2-p1
1766     por              m1, m4          ; abs(p2-p1)
1767
1768     mova             m4, m6
1769     SWAP              4, 6
1770     psubusb          m4, m7          ; q2-q3
1771     psubusb          m7, m6          ; q3-q2
1772     por              m7, m4          ; abs(q3-q2)
1773
1774     mova             m4, m5
1775     SWAP              4, 5
1776     psubusb          m4, m6          ; q1-q2
1777     psubusb          m6, m5          ; q2-q1
1778     por              m6, m4          ; abs(q2-q1)
1779
1780 %ifidn %1, mmx
1781     mova             m4, flim_I
1782     pxor             m3, m3
1783     psubusb          m0, m4
1784     psubusb          m1, m4
1785     psubusb          m7, m4
1786     psubusb          m6, m4
1787     pcmpeqb          m0, m3          ; abs(p3-p2) <= I
1788     pcmpeqb          m1, m3          ; abs(p2-p1) <= I
1789     pcmpeqb          m7, m3          ; abs(q3-q2) <= I
1790     pcmpeqb          m6, m3          ; abs(q2-q1) <= I
1791     pand             m0, m1
1792     pand             m7, m6
1793     pand             m0, m7
1794 %else ; mmxext/sse2
1795     pmaxub           m0, m1
1796     pmaxub           m6, m7
1797     pmaxub           m0, m6
1798 %endif
1799
1800     ; normal_limit and high_edge_variance for p1-p0, q1-q0
1801     SWAP              7, 3           ; now m7 is zero
1802 %ifidn %2, v
1803     movrow           m3, [dst_reg +mstride_reg] ; p0
1804 %if mmsize == 16 && %4 == 8
1805     movhps           m3, [dst8_reg+mstride_reg]
1806 %endif
1807 %elifdef m12
1808     SWAP              3, 12
1809 %else
1810     mova             m3, p0backup
1811 %endif
1812
1813     mova             m1, m2
1814     SWAP              1, 2
1815     mova             m6, m3
1816     SWAP              3, 6
1817     psubusb          m1, m3          ; p1-p0
1818     psubusb          m6, m2          ; p0-p1
1819     por              m1, m6          ; abs(p1-p0)
1820 %ifidn %1, mmx
1821     mova             m6, m1
1822     psubusb          m1, m4
1823     psubusb          m6, hev_thr
1824     pcmpeqb          m1, m7          ; abs(p1-p0) <= I
1825     pcmpeqb          m6, m7          ; abs(p1-p0) <= hev_thresh
1826     pand             m0, m1
1827     mova       mask_res, m6
1828 %else ; mmxext/sse2
1829     pmaxub           m0, m1          ; max_I
1830     SWAP              1, 4           ; max_hev_thresh
1831 %endif
1832
1833     SWAP              6, 4           ; now m6 is I
1834 %ifidn %2, v
1835     movrow           m4, [dst_reg]   ; q0
1836 %if mmsize == 16 && %4 == 8
1837     movhps           m4, [dst8_reg]
1838 %endif
1839 %elifdef m8
1840     SWAP              4, 8
1841 %else
1842     mova             m4, q0backup
1843 %endif
1844     mova             m1, m4
1845     SWAP              1, 4
1846     mova             m7, m5
1847     SWAP              7, 5
1848     psubusb          m1, m5          ; q0-q1
1849     psubusb          m7, m4          ; q1-q0
1850     por              m1, m7          ; abs(q1-q0)
1851 %ifidn %1, mmx
1852     mova             m7, m1
1853     psubusb          m1, m6
1854     psubusb          m7, hev_thr
1855     pxor             m6, m6
1856     pcmpeqb          m1, m6          ; abs(q1-q0) <= I
1857     pcmpeqb          m7, m6          ; abs(q1-q0) <= hev_thresh
1858     mova             m6, mask_res
1859     pand             m0, m1          ; abs([pq][321]-[pq][210]) <= I
1860     pand             m6, m7
1861 %else ; mmxext/sse2
1862     pxor             m7, m7
1863     pmaxub           m0, m1
1864     pmaxub           m6, m1
1865     psubusb          m0, flim_I
1866     psubusb          m6, hev_thr
1867     pcmpeqb          m0, m7          ; max(abs(..)) <= I
1868     pcmpeqb          m6, m7          ; !(max(abs..) > thresh)
1869 %endif
1870 %ifdef m12
1871     SWAP              6, 12
1872 %else
1873     mova       mask_res, m6          ; !(abs(p1-p0) > hev_t || abs(q1-q0) > hev_t)
1874 %endif
1875
1876     ; simple_limit
1877     mova             m1, m3
1878     SWAP              1, 3
1879     mova             m6, m4          ; keep copies of p0/q0 around for later use
1880     SWAP              6, 4
1881     psubusb          m1, m4          ; p0-q0
1882     psubusb          m6, m3          ; q0-p0
1883     por              m1, m6          ; abs(q0-p0)
1884     paddusb          m1, m1          ; m1=2*abs(q0-p0)
1885
1886     mova             m7, m2
1887     SWAP              7, 2
1888     mova             m6, m5
1889     SWAP              6, 5
1890     psubusb          m7, m5          ; p1-q1
1891     psubusb          m6, m2          ; q1-p1
1892     por              m7, m6          ; abs(q1-p1)
1893     pxor             m6, m6
1894     pand             m7, [pb_FE]
1895     psrlq            m7, 1           ; abs(q1-p1)/2
1896     paddusb          m7, m1          ; abs(q0-p0)*2+abs(q1-p1)/2
1897     psubusb          m7, flim_E
1898     pcmpeqb          m7, m6          ; abs(q0-p0)*2+abs(q1-p1)/2 <= E
1899     pand             m0, m7          ; normal_limit result
1900
1901     ; filter_common; at this point, m2-m5=p1-q1 and m0 is filter_mask
1902 %ifdef m8 ; x86-64 && sse2
1903     mova             m8, [pb_80]
1904 %define pb_80_var m8
1905 %else ; x86-32 or mmx/mmxext
1906 %define pb_80_var [pb_80]
1907 %endif
1908     mova             m1, m4
1909     mova             m7, m3
1910     pxor             m1, pb_80_var
1911     pxor             m7, pb_80_var
1912     psubsb           m1, m7          ; (signed) q0-p0
1913     mova             m6, m2
1914     mova             m7, m5
1915     pxor             m6, pb_80_var
1916     pxor             m7, pb_80_var
1917     psubsb           m6, m7          ; (signed) p1-q1
1918     mova             m7, mask_res
1919     pandn            m7, m6
1920     paddsb           m7, m1
1921     paddsb           m7, m1
1922     paddsb           m7, m1          ; 3*(q0-p0)+is4tap?(p1-q1)
1923
1924     pand             m7, m0
1925     mova             m1, [pb_F8]
1926     mova             m6, m7
1927     paddsb           m7, [pb_3]
1928     paddsb           m6, [pb_4]
1929     pand             m7, m1
1930     pand             m6, m1
1931
1932     pxor             m1, m1
1933     pxor             m0, m0
1934     pcmpgtb          m1, m7
1935     psubb            m0, m7
1936     psrlq            m7, 3           ; +f2
1937     psrlq            m0, 3           ; -f2
1938     pand             m0, m1
1939     pandn            m1, m7
1940     psubusb          m3, m0
1941     paddusb          m3, m1          ; p0+f2
1942
1943     pxor             m1, m1
1944     pxor             m0, m0
1945     pcmpgtb          m0, m6
1946     psubb            m1, m6
1947     psrlq            m6, 3           ; +f1
1948     psrlq            m1, 3           ; -f1
1949     pand             m1, m0
1950     pandn            m0, m6
1951     psubusb          m4, m0
1952     paddusb          m4, m1          ; q0-f1
1953
1954 %ifdef m12
1955     SWAP              6, 12
1956 %else
1957     mova             m6, mask_res
1958 %endif
1959 %ifidn %1, mmx
1960     mova             m7, [pb_1]
1961 %else ; mmxext/sse2
1962     pxor             m7, m7
1963 %endif
1964     pand             m0, m6
1965     pand             m1, m6
1966 %ifidn %1, mmx
1967     paddusb          m0, m7
1968     pand             m1, [pb_FE]
1969     pandn            m7, m0
1970     psrlq            m1, 1
1971     psrlq            m7, 1
1972     SWAP              0, 7
1973 %else ; mmxext/sse2
1974     psubusb          m1, [pb_1]
1975     pavgb            m0, m7          ; a
1976     pavgb            m1, m7          ; -a
1977 %endif
1978     psubusb          m5, m0
1979     psubusb          m2, m1
1980     paddusb          m5, m1          ; q1-a
1981     paddusb          m2, m0          ; p1+a
1982
1983     ; store
1984 %ifidn %2, v
1985     movrow [dst_reg +mstride_reg*2], m2
1986     movrow [dst_reg +mstride_reg  ], m3
1987     movrow    [dst_reg], m4
1988     movrow [dst_reg + stride_reg  ], m5
1989 %if mmsize == 16 && %4 == 8
1990     movhps [dst8_reg+mstride_reg*2], m2
1991     movhps [dst8_reg+mstride_reg  ], m3
1992     movhps   [dst8_reg], m4
1993     movhps [dst8_reg+ stride_reg  ], m5
1994 %endif
1995 %else ; h
1996     add         dst_reg, 2
1997     add        dst2_reg, 2
1998
1999     ; 4x8/16 transpose
2000     TRANSPOSE4x4B     2, 3, 4, 5, 6
2001
2002 %if mmsize == 8 ; mmx/mmxext (h)
2003     WRITE_4x2D        2, 3, 4, 5, dst_reg, dst2_reg, mstride_reg, stride_reg
2004 %else ; sse2 (h)
2005     lea        dst8_reg, [dst8_reg+mstride_reg+2]
2006     WRITE_4x4D        2, 3, 4, 5, dst_reg, dst2_reg, dst8_reg, mstride_reg, stride_reg, %4
2007 %endif
2008 %endif
2009
2010 %if mmsize == 8
2011 %if %4 == 8 ; chroma
2012 %ifidn %2, h
2013     sub         dst_reg, 2
2014 %endif
2015     cmp         dst_reg, dst8_reg
2016     mov         dst_reg, dst8_reg
2017     jnz .next8px
2018 %else
2019 %ifidn %2, h
2020     lea         dst_reg, [dst_reg + stride_reg*8-2]
2021 %else ; v
2022     add         dst_reg, 8
2023 %endif
2024     dec         cnt_reg
2025     jg .next8px
2026 %endif
2027 %endif
2028
2029 %ifndef m8 ; sse2 on x86-32 or mmx/mmxext
2030     mov             rsp, stack_reg   ; restore stack pointer
2031 %endif
2032     RET
2033 %endmacro
2034
2035 INIT_MMX
2036 %define SPLATB_REG SPLATB_REG_MMX
2037 INNER_LOOPFILTER mmx,    v, 6, 16, 0
2038 INNER_LOOPFILTER mmx,    h, 6, 16, 0
2039 INNER_LOOPFILTER mmx,    v, 6,  8, 0
2040 INNER_LOOPFILTER mmx,    h, 6,  8, 0
2041
2042 %define SPLATB_REG SPLATB_REG_MMXEXT
2043 INNER_LOOPFILTER mmxext, v, 6, 16, 0
2044 INNER_LOOPFILTER mmxext, h, 6, 16, 0
2045 INNER_LOOPFILTER mmxext, v, 6,  8, 0
2046 INNER_LOOPFILTER mmxext, h, 6,  8, 0
2047
2048 INIT_XMM
2049 %define SPLATB_REG SPLATB_REG_SSE2
2050 INNER_LOOPFILTER sse2,   v, 5, 16, 13
2051 %ifdef m8
2052 INNER_LOOPFILTER sse2,   h, 5, 16, 13
2053 %else
2054 INNER_LOOPFILTER sse2,   h, 6, 16, 13
2055 %endif
2056 INNER_LOOPFILTER sse2,   v, 6,  8, 13
2057 INNER_LOOPFILTER sse2,   h, 6,  8, 13
2058
2059 %define SPLATB_REG SPLATB_REG_SSSE3
2060 INNER_LOOPFILTER ssse3,  v, 5, 16, 13
2061 %ifdef m8
2062 INNER_LOOPFILTER ssse3,  h, 5, 16, 13
2063 %else
2064 INNER_LOOPFILTER ssse3,  h, 6, 16, 13
2065 %endif
2066 INNER_LOOPFILTER ssse3,  v, 6,  8, 13
2067 INNER_LOOPFILTER ssse3,  h, 6,  8, 13
2068
2069 ;-----------------------------------------------------------------------------
2070 ; void vp8_h/v_loop_filter<size>_mbedge_<opt>(uint8_t *dst, [uint8_t *v,] int stride,
2071 ;                                            int flimE, int flimI, int hev_thr);
2072 ;-----------------------------------------------------------------------------
2073
2074 ; write 4 or 8 words in the mmx/xmm registers as 8 lines
2075 ; 1 and 2 are the registers to write, this can be the same (for SSE2)
2076 ; for pre-SSE4:
2077 ; 3 is a general-purpose register that we will clobber
2078 ; for SSE4:
2079 ; 3 is a pointer to the destination's 5th line
2080 ; 4 is a pointer to the destination's 4th line
2081 ; 5/6 is -stride and +stride
2082 %macro WRITE_2x4W 6
2083     movd             %3, %1
2084     punpckhdq        %1, %1
2085     mov       [%4+%5*4], %3w
2086     shr              %3, 16
2087     add              %4, %6
2088     mov       [%4+%5*4], %3w
2089
2090     movd             %3, %1
2091     add              %4, %5
2092     mov       [%4+%5*2], %3w
2093     shr              %3, 16
2094     mov       [%4+%5  ], %3w
2095
2096     movd             %3, %2
2097     punpckhdq        %2, %2
2098     mov       [%4     ], %3w
2099     shr              %3, 16
2100     mov       [%4+%6  ], %3w
2101
2102     movd             %3, %2
2103     add              %4, %6
2104     mov       [%4+%6  ], %3w
2105     shr              %3, 16
2106     mov       [%4+%6*2], %3w
2107     add              %4, %5
2108 %endmacro
2109
2110 %macro WRITE_8W_SSE2 5
2111     movd             %2, %1
2112     psrldq           %1, 4
2113     mov       [%3+%4*4], %2w
2114     shr              %2, 16
2115     add              %3, %5
2116     mov       [%3+%4*4], %2w
2117
2118     movd             %2, %1
2119     psrldq           %1, 4
2120     add              %3, %4
2121     mov       [%3+%4*2], %2w
2122     shr              %2, 16
2123     mov       [%3+%4  ], %2w
2124
2125     movd             %2, %1
2126     psrldq           %1, 4
2127     mov       [%3     ], %2w
2128     shr              %2, 16
2129     mov       [%3+%5  ], %2w
2130
2131     movd             %2, %1
2132     add              %3, %5
2133     mov       [%3+%5  ], %2w
2134     shr              %2, 16
2135     mov       [%3+%5*2], %2w
2136 %endmacro
2137
2138 %macro WRITE_8W_SSE4 5
2139     pextrw    [%3+%4*4], %1, 0
2140     pextrw    [%2+%4*4], %1, 1
2141     pextrw    [%3+%4*2], %1, 2
2142     pextrw    [%3+%4  ], %1, 3
2143     pextrw    [%3     ], %1, 4
2144     pextrw    [%2     ], %1, 5
2145     pextrw    [%2+%5  ], %1, 6
2146     pextrw    [%2+%5*2], %1, 7
2147 %endmacro
2148
2149 %macro MBEDGE_LOOPFILTER 5
2150 %if %4 == 8 ; chroma
2151 cglobal vp8_%2_loop_filter8uv_mbedge_%1, 6, %3, %5
2152 %define dst8_reg    r1
2153 %define mstride_reg r2
2154 %define E_reg       r3
2155 %define I_reg       r4
2156 %define hev_thr_reg r5
2157 %else ; luma
2158 cglobal vp8_%2_loop_filter16y_mbedge_%1, 5, %3, %5
2159 %define mstride_reg r1
2160 %define E_reg       r2
2161 %define I_reg       r3
2162 %define hev_thr_reg r4
2163 %ifdef m8 ; x86-64, sse2
2164 %define dst8_reg    r4
2165 %elif mmsize == 16 ; x86-32, sse2
2166 %define dst8_reg    r5
2167 %else ; x86-32, mmx/mmxext
2168 %define cnt_reg     r5
2169 %endif
2170 %endif
2171 %define dst_reg     r0
2172 %define stride_reg  E_reg
2173 %define dst2_reg    I_reg
2174 %ifndef m8
2175 %define stack_reg   hev_thr_reg
2176 %endif
2177
2178 %ifnidn %1, sse2
2179 %if mmsize == 16
2180     pxor             m7, m7
2181 %endif
2182 %endif
2183
2184 %ifndef m8 ; mmx/mmxext or sse2 on x86-32
2185     ; splat function arguments
2186     SPLATB_REG       m0, E_reg, m7   ; E
2187     SPLATB_REG       m1, I_reg, m7   ; I
2188     SPLATB_REG       m2, hev_thr_reg, m7 ; hev_thresh
2189
2190     ; align stack
2191     mov       stack_reg, rsp         ; backup stack pointer
2192     and             rsp, ~(mmsize-1) ; align stack
2193 %if mmsize == 16
2194     sub             rsp, mmsize * 7
2195 %else
2196     sub             rsp, mmsize * 8  ; stack layout: [0]=E, [1]=I, [2]=hev_thr
2197                                      ;               [3]=hev() result
2198                                      ;               [4]=filter tmp result
2199                                      ;               [5]/[6] = p2/q2 backup
2200                                      ;               [7]=lim_res sign result
2201 %endif
2202
2203 %define flim_E   [rsp]
2204 %define flim_I   [rsp+mmsize]
2205 %define hev_thr  [rsp+mmsize*2]
2206 %define mask_res [rsp+mmsize*3]
2207 %define lim_res  [rsp+mmsize*4]
2208 %define p0backup [rsp+mmsize*3]
2209 %define q0backup [rsp+mmsize*4]
2210 %define p2backup [rsp+mmsize*5]
2211 %define q2backup [rsp+mmsize*6]
2212 %if mmsize == 16
2213 %define lim_sign [rsp]
2214 %else
2215 %define lim_sign [rsp+mmsize*7]
2216 %endif
2217
2218     mova         flim_E, m0
2219     mova         flim_I, m1
2220     mova        hev_thr, m2
2221
2222 %else ; sse2 on x86-64
2223
2224 %define flim_E   m9
2225 %define flim_I   m10
2226 %define hev_thr  m11
2227 %define mask_res m12
2228 %define lim_res  m8
2229 %define p0backup m12
2230 %define q0backup m8
2231 %define p2backup m13
2232 %define q2backup m14
2233 %define lim_sign m9
2234
2235     ; splat function arguments
2236     SPLATB_REG   flim_E, E_reg, m7   ; E
2237     SPLATB_REG   flim_I, I_reg, m7   ; I
2238     SPLATB_REG  hev_thr, hev_thr_reg, m7 ; hev_thresh
2239 %endif
2240
2241 %if mmsize == 8 && %4 == 16 ; mmx/mmxext
2242     mov         cnt_reg, 2
2243 %endif
2244     mov      stride_reg, mstride_reg
2245     neg     mstride_reg
2246 %ifidn %2, h
2247     lea         dst_reg, [dst_reg + stride_reg*4-4]
2248 %if %4 == 8
2249     lea        dst8_reg, [dst8_reg+ stride_reg*4-4]
2250 %endif
2251 %endif
2252
2253 %if mmsize == 8
2254 .next8px
2255 %endif
2256     ; read
2257     lea        dst2_reg, [dst_reg + stride_reg]
2258 %ifidn %2, v
2259 %if %4 == 8 && mmsize == 16
2260 %define movrow movh
2261 %else
2262 %define movrow mova
2263 %endif
2264     movrow           m0, [dst_reg +mstride_reg*4] ; p3
2265     movrow           m1, [dst2_reg+mstride_reg*4] ; p2
2266     movrow           m2, [dst_reg +mstride_reg*2] ; p1
2267     movrow           m5, [dst2_reg]               ; q1
2268     movrow           m6, [dst2_reg+ stride_reg]   ; q2
2269     movrow           m7, [dst2_reg+ stride_reg*2] ; q3
2270 %if mmsize == 16 && %4 == 8
2271     movhps           m0, [dst8_reg+mstride_reg*4]
2272     movhps           m2, [dst8_reg+mstride_reg*2]
2273     add        dst8_reg, stride_reg
2274     movhps           m1, [dst8_reg+mstride_reg*4]
2275     movhps           m5, [dst8_reg]
2276     movhps           m6, [dst8_reg+ stride_reg]
2277     movhps           m7, [dst8_reg+ stride_reg*2]
2278     add        dst8_reg, mstride_reg
2279 %endif
2280 %elif mmsize == 8 ; mmx/mmxext (h)
2281     ; read 8 rows of 8px each
2282     movu             m0, [dst_reg +mstride_reg*4]
2283     movu             m1, [dst2_reg+mstride_reg*4]
2284     movu             m2, [dst_reg +mstride_reg*2]
2285     movu             m3, [dst_reg +mstride_reg]
2286     movu             m4, [dst_reg]
2287     movu             m5, [dst2_reg]
2288     movu             m6, [dst2_reg+ stride_reg]
2289
2290     ; 8x8 transpose
2291     TRANSPOSE4x4B     0, 1, 2, 3, 7
2292     mova       q0backup, m1
2293     movu             m7, [dst2_reg+ stride_reg*2]
2294     TRANSPOSE4x4B     4, 5, 6, 7, 1
2295     SBUTTERFLY       dq, 0, 4, 1     ; p3/p2
2296     SBUTTERFLY       dq, 2, 6, 1     ; q0/q1
2297     SBUTTERFLY       dq, 3, 7, 1     ; q2/q3
2298     mova             m1, q0backup
2299     mova       q0backup, m2          ; store q0
2300     SBUTTERFLY       dq, 1, 5, 2     ; p1/p0
2301     mova       p0backup, m5          ; store p0
2302     SWAP              1, 4
2303     SWAP              2, 4
2304     SWAP              6, 3
2305     SWAP              5, 3
2306 %else ; sse2 (h)
2307 %if %4 == 16
2308     lea        dst8_reg, [dst_reg + stride_reg*8]
2309 %endif
2310
2311     ; read 16 rows of 8px each, interleave
2312     movh             m0, [dst_reg +mstride_reg*4]
2313     movh             m1, [dst8_reg+mstride_reg*4]
2314     movh             m2, [dst_reg +mstride_reg*2]
2315     movh             m5, [dst8_reg+mstride_reg*2]
2316     movh             m3, [dst_reg +mstride_reg]
2317     movh             m6, [dst8_reg+mstride_reg]
2318     movh             m4, [dst_reg]
2319     movh             m7, [dst8_reg]
2320     punpcklbw        m0, m1          ; A/I
2321     punpcklbw        m2, m5          ; C/K
2322     punpcklbw        m3, m6          ; D/L
2323     punpcklbw        m4, m7          ; E/M
2324
2325     add        dst8_reg, stride_reg
2326     movh             m1, [dst2_reg+mstride_reg*4]
2327     movh             m6, [dst8_reg+mstride_reg*4]
2328     movh             m5, [dst2_reg]
2329     movh             m7, [dst8_reg]
2330     punpcklbw        m1, m6          ; B/J
2331     punpcklbw        m5, m7          ; F/N
2332     movh             m6, [dst2_reg+ stride_reg]
2333     movh             m7, [dst8_reg+ stride_reg]
2334     punpcklbw        m6, m7          ; G/O
2335
2336     ; 8x16 transpose
2337     TRANSPOSE4x4B     0, 1, 2, 3, 7
2338 %ifdef m8
2339     SWAP              1, 8
2340 %else
2341     mova       q0backup, m1
2342 %endif
2343     movh             m7, [dst2_reg+ stride_reg*2]
2344     movh             m1, [dst8_reg+ stride_reg*2]
2345     punpcklbw        m7, m1          ; H/P
2346     TRANSPOSE4x4B     4, 5, 6, 7, 1
2347     SBUTTERFLY       dq, 0, 4, 1     ; p3/p2
2348     SBUTTERFLY       dq, 2, 6, 1     ; q0/q1
2349     SBUTTERFLY       dq, 3, 7, 1     ; q2/q3
2350 %ifdef m8
2351     SWAP              1, 8
2352     SWAP              2, 8
2353 %else
2354     mova             m1, q0backup
2355     mova       q0backup, m2          ; store q0
2356 %endif
2357     SBUTTERFLY       dq, 1, 5, 2     ; p1/p0
2358 %ifdef m12
2359     SWAP              5, 12
2360 %else
2361     mova       p0backup, m5          ; store p0
2362 %endif
2363     SWAP              1, 4
2364     SWAP              2, 4
2365     SWAP              6, 3
2366     SWAP              5, 3
2367 %endif
2368
2369     ; normal_limit for p3-p2, p2-p1, q3-q2 and q2-q1
2370     mova             m4, m1
2371     SWAP              4, 1
2372     psubusb          m4, m0          ; p2-p3
2373     psubusb          m0, m1          ; p3-p2
2374     por              m0, m4          ; abs(p3-p2)
2375
2376     mova             m4, m2
2377     SWAP              4, 2
2378     psubusb          m4, m1          ; p1-p2
2379     mova       p2backup, m1
2380     psubusb          m1, m2          ; p2-p1
2381     por              m1, m4          ; abs(p2-p1)
2382
2383     mova             m4, m6
2384     SWAP              4, 6
2385     psubusb          m4, m7          ; q2-q3
2386     psubusb          m7, m6          ; q3-q2
2387     por              m7, m4          ; abs(q3-q2)
2388
2389     mova             m4, m5
2390     SWAP              4, 5
2391     psubusb          m4, m6          ; q1-q2
2392     mova       q2backup, m6
2393     psubusb          m6, m5          ; q2-q1
2394     por              m6, m4          ; abs(q2-q1)
2395
2396 %ifidn %1, mmx
2397     mova             m4, flim_I
2398     pxor             m3, m3
2399     psubusb          m0, m4
2400     psubusb          m1, m4
2401     psubusb          m7, m4
2402     psubusb          m6, m4
2403     pcmpeqb          m0, m3          ; abs(p3-p2) <= I
2404     pcmpeqb          m1, m3          ; abs(p2-p1) <= I
2405     pcmpeqb          m7, m3          ; abs(q3-q2) <= I
2406     pcmpeqb          m6, m3          ; abs(q2-q1) <= I
2407     pand             m0, m1
2408     pand             m7, m6
2409     pand             m0, m7
2410 %else ; mmxext/sse2
2411     pmaxub           m0, m1
2412     pmaxub           m6, m7
2413     pmaxub           m0, m6
2414 %endif
2415
2416     ; normal_limit and high_edge_variance for p1-p0, q1-q0
2417     SWAP              7, 3           ; now m7 is zero
2418 %ifidn %2, v
2419     movrow           m3, [dst_reg +mstride_reg] ; p0
2420 %if mmsize == 16 && %4 == 8
2421     movhps           m3, [dst8_reg+mstride_reg]
2422 %endif
2423 %elifdef m12
2424     SWAP              3, 12
2425 %else
2426     mova             m3, p0backup
2427 %endif
2428
2429     mova             m1, m2
2430     SWAP              1, 2
2431     mova             m6, m3
2432     SWAP              3, 6
2433     psubusb          m1, m3          ; p1-p0
2434     psubusb          m6, m2          ; p0-p1
2435     por              m1, m6          ; abs(p1-p0)
2436 %ifidn %1, mmx
2437     mova             m6, m1
2438     psubusb          m1, m4
2439     psubusb          m6, hev_thr
2440     pcmpeqb          m1, m7          ; abs(p1-p0) <= I
2441     pcmpeqb          m6, m7          ; abs(p1-p0) <= hev_thresh
2442     pand             m0, m1
2443     mova       mask_res, m6
2444 %else ; mmxext/sse2
2445     pmaxub           m0, m1          ; max_I
2446     SWAP              1, 4           ; max_hev_thresh
2447 %endif
2448
2449     SWAP              6, 4           ; now m6 is I
2450 %ifidn %2, v
2451     movrow           m4, [dst_reg]   ; q0
2452 %if mmsize == 16 && %4 == 8
2453     movhps           m4, [dst8_reg]
2454 %endif
2455 %elifdef m8
2456     SWAP              4, 8
2457 %else
2458     mova             m4, q0backup
2459 %endif
2460     mova             m1, m4
2461     SWAP              1, 4
2462     mova             m7, m5
2463     SWAP              7, 5
2464     psubusb          m1, m5          ; q0-q1
2465     psubusb          m7, m4          ; q1-q0
2466     por              m1, m7          ; abs(q1-q0)
2467 %ifidn %1, mmx
2468     mova             m7, m1
2469     psubusb          m1, m6
2470     psubusb          m7, hev_thr
2471     pxor             m6, m6
2472     pcmpeqb          m1, m6          ; abs(q1-q0) <= I
2473     pcmpeqb          m7, m6          ; abs(q1-q0) <= hev_thresh
2474     mova             m6, mask_res
2475     pand             m0, m1          ; abs([pq][321]-[pq][210]) <= I
2476     pand             m6, m7
2477 %else ; mmxext/sse2
2478     pxor             m7, m7
2479     pmaxub           m0, m1
2480     pmaxub           m6, m1
2481     psubusb          m0, flim_I
2482     psubusb          m6, hev_thr
2483     pcmpeqb          m0, m7          ; max(abs(..)) <= I
2484     pcmpeqb          m6, m7          ; !(max(abs..) > thresh)
2485 %endif
2486 %ifdef m12
2487     SWAP              6, 12
2488 %else
2489     mova       mask_res, m6          ; !(abs(p1-p0) > hev_t || abs(q1-q0) > hev_t)
2490 %endif
2491
2492     ; simple_limit
2493     mova             m1, m3
2494     SWAP              1, 3
2495     mova             m6, m4          ; keep copies of p0/q0 around for later use
2496     SWAP              6, 4
2497     psubusb          m1, m4          ; p0-q0
2498     psubusb          m6, m3          ; q0-p0
2499     por              m1, m6          ; abs(q0-p0)
2500     paddusb          m1, m1          ; m1=2*abs(q0-p0)
2501
2502     mova             m7, m2
2503     SWAP              7, 2
2504     mova             m6, m5
2505     SWAP              6, 5
2506     psubusb          m7, m5          ; p1-q1
2507     psubusb          m6, m2          ; q1-p1
2508     por              m7, m6          ; abs(q1-p1)
2509     pxor             m6, m6
2510     pand             m7, [pb_FE]
2511     psrlq            m7, 1           ; abs(q1-p1)/2
2512     paddusb          m7, m1          ; abs(q0-p0)*2+abs(q1-p1)/2
2513     psubusb          m7, flim_E
2514     pcmpeqb          m7, m6          ; abs(q0-p0)*2+abs(q1-p1)/2 <= E
2515     pand             m0, m7          ; normal_limit result
2516
2517     ; filter_common; at this point, m2-m5=p1-q1 and m0 is filter_mask
2518 %ifdef m8 ; x86-64 && sse2
2519     mova             m8, [pb_80]
2520 %define pb_80_var m8
2521 %else ; x86-32 or mmx/mmxext
2522 %define pb_80_var [pb_80]
2523 %endif
2524     mova             m1, m4
2525     mova             m7, m3
2526     pxor             m1, pb_80_var
2527     pxor             m7, pb_80_var
2528     psubsb           m1, m7          ; (signed) q0-p0
2529     mova             m6, m2
2530     mova             m7, m5
2531     pxor             m6, pb_80_var
2532     pxor             m7, pb_80_var
2533     psubsb           m6, m7          ; (signed) p1-q1
2534     mova             m7, mask_res
2535     paddsb           m6, m1
2536     paddsb           m6, m1
2537     paddsb           m6, m1
2538     pand             m6, m0
2539 %ifdef m8
2540     mova        lim_res, m6          ; 3*(qp-p0)+(p1-q1) masked for filter_mbedge
2541     pand        lim_res, m7
2542 %else
2543     mova             m0, m6
2544     pand             m0, m7
2545     mova        lim_res, m0
2546 %endif
2547     pandn            m7, m6          ; 3*(q0-p0)+(p1-q1) masked for filter_common
2548
2549     mova             m1, [pb_F8]
2550     mova             m6, m7
2551     paddsb           m7, [pb_3]
2552     paddsb           m6, [pb_4]
2553     pand             m7, m1
2554     pand             m6, m1
2555
2556     pxor             m1, m1
2557     pxor             m0, m0
2558     pcmpgtb          m1, m7
2559     psubb            m0, m7
2560     psrlq            m7, 3           ; +f2
2561     psrlq            m0, 3           ; -f2
2562     pand             m0, m1
2563     pandn            m1, m7
2564     psubusb          m3, m0
2565     paddusb          m3, m1          ; p0+f2
2566
2567     pxor             m1, m1
2568     pxor             m0, m0
2569     pcmpgtb          m0, m6
2570     psubb            m1, m6
2571     psrlq            m6, 3           ; +f1
2572     psrlq            m1, 3           ; -f1
2573     pand             m1, m0
2574     pandn            m0, m6
2575     psubusb          m4, m0
2576     paddusb          m4, m1          ; q0-f1
2577
2578     ; filter_mbedge (m2-m5 = p1-q1; lim_res carries w)
2579     mova             m7, [pw_63]
2580 %ifdef m8
2581     SWAP              1, 8
2582 %else
2583     mova             m1, lim_res
2584 %endif
2585     pxor             m0, m0
2586     mova             m6, m1
2587     pcmpgtb          m0, m1         ; which are negative
2588     punpcklbw        m6, m0         ; signed byte->word
2589     punpckhbw        m1, m0
2590     mova       lim_sign, m0
2591     mova       mask_res, m6         ; backup for later in filter
2592     mova        lim_res, m1
2593     pmullw          m6, [pw_27]
2594     pmullw          m1, [pw_27]
2595     paddw           m6, m7
2596     paddw           m1, m7
2597     psraw           m6, 7
2598     psraw           m1, 7
2599     packsswb        m6, m1          ; a0
2600     pxor            m1, m1
2601     psubb           m1, m6
2602     pand            m1, m0          ; -a0
2603     pandn           m0, m6          ; +a0
2604     psubusb         m3, m1
2605     paddusb         m4, m1
2606     paddusb         m3, m0          ; p0+a0
2607     psubusb         m4, m0          ; q0-a0
2608
2609     mova            m6, mask_res
2610     mova            m1, lim_res
2611     mova            m0, lim_sign
2612     pmullw          m6, [pw_18]
2613     pmullw          m1, [pw_18]
2614     paddw           m6, m7
2615     paddw           m1, m7
2616     psraw           m6, 7
2617     psraw           m1, 7
2618     packsswb        m6, m1          ; a1
2619     pxor            m1, m1
2620     psubb           m1, m6
2621     pand            m1, m0          ; -a1
2622     pandn           m0, m6          ; +a1
2623     psubusb         m2, m1
2624     paddusb         m5, m1
2625     paddusb         m2, m0          ; p1+a1
2626     psubusb         m5, m0          ; q1-a1
2627
2628 %ifdef m8
2629     SWAP             6, 12
2630     SWAP             1, 8
2631 %else
2632     mova            m6, mask_res
2633     mova            m1, lim_res
2634 %endif
2635     pmullw          m6, [pw_9]
2636     pmullw          m1, [pw_9]
2637     paddw           m6, m7
2638     paddw           m1, m7
2639 %ifdef m9
2640     SWAP             7, 9
2641 %else
2642     mova            m7, lim_sign
2643 %endif
2644     psraw           m6, 7
2645     psraw           m1, 7
2646     packsswb        m6, m1          ; a1
2647     pxor            m0, m0
2648     psubb           m0, m6
2649     pand            m0, m7          ; -a1
2650     pandn           m7, m6          ; +a1
2651 %ifdef m8
2652     SWAP             1, 13
2653     SWAP             6, 14
2654 %else
2655     mova            m1, p2backup
2656     mova            m6, q2backup
2657 %endif
2658     psubusb         m1, m0
2659     paddusb         m6, m0
2660     paddusb         m1, m7          ; p1+a1
2661     psubusb         m6, m7          ; q1-a1
2662
2663     ; store
2664 %ifidn %2, v
2665     movrow [dst2_reg+mstride_reg*4], m1
2666     movrow [dst_reg +mstride_reg*2], m2
2667     movrow [dst_reg +mstride_reg  ], m3
2668     movrow    [dst_reg], m4
2669     movrow   [dst2_reg], m5
2670     movrow [dst2_reg+ stride_reg  ], m6
2671 %if mmsize == 16 && %4 == 8
2672     add        dst8_reg, mstride_reg
2673     movhps [dst8_reg+mstride_reg*2], m1
2674     movhps [dst8_reg+mstride_reg  ], m2
2675     movhps   [dst8_reg], m3
2676     add        dst8_reg, stride_reg
2677     movhps   [dst8_reg], m4
2678     movhps [dst8_reg+ stride_reg  ], m5
2679     movhps [dst8_reg+ stride_reg*2], m6
2680 %endif
2681 %else ; h
2682     inc         dst_reg
2683     inc        dst2_reg
2684
2685     ; 4x8/16 transpose
2686     TRANSPOSE4x4B     1, 2, 3, 4, 0
2687     SBUTTERFLY       bw, 5, 6, 0
2688
2689 %if mmsize == 8 ; mmx/mmxext (h)
2690     WRITE_4x2D        1, 2, 3, 4, dst_reg, dst2_reg, mstride_reg, stride_reg
2691     add         dst_reg, 4
2692     WRITE_2x4W       m5, m6, dst2_reg, dst_reg, mstride_reg, stride_reg
2693 %else ; sse2 (h)
2694     lea        dst8_reg, [dst8_reg+mstride_reg+1]
2695     WRITE_4x4D        1, 2, 3, 4, dst_reg, dst2_reg, dst8_reg, mstride_reg, stride_reg, %4
2696     lea         dst_reg, [dst2_reg+mstride_reg+4]
2697     lea        dst8_reg, [dst8_reg+mstride_reg+4]
2698 %ifidn %1, sse4
2699     add        dst2_reg, 4
2700 %endif
2701     WRITE_8W         m5, dst2_reg, dst_reg,  mstride_reg, stride_reg
2702 %ifidn %1, sse4
2703     lea        dst2_reg, [dst8_reg+ stride_reg]
2704 %endif
2705     WRITE_8W         m6, dst2_reg, dst8_reg, mstride_reg, stride_reg
2706 %endif
2707 %endif
2708
2709 %if mmsize == 8
2710 %if %4 == 8 ; chroma
2711 %ifidn %2, h
2712     sub         dst_reg, 5
2713 %endif
2714     cmp         dst_reg, dst8_reg
2715     mov         dst_reg, dst8_reg
2716     jnz .next8px
2717 %else
2718 %ifidn %2, h
2719     lea         dst_reg, [dst_reg + stride_reg*8-5]
2720 %else ; v
2721     add         dst_reg, 8
2722 %endif
2723     dec         cnt_reg
2724     jg .next8px
2725 %endif
2726 %endif
2727
2728 %ifndef m8 ; sse2 on x86-32 or mmx/mmxext
2729     mov             rsp, stack_reg   ; restore stack pointer
2730 %endif
2731     RET
2732 %endmacro
2733
2734 INIT_MMX
2735 %define SPLATB_REG SPLATB_REG_MMX
2736 MBEDGE_LOOPFILTER mmx,    v, 6, 16, 0
2737 MBEDGE_LOOPFILTER mmx,    h, 6, 16, 0
2738 MBEDGE_LOOPFILTER mmx,    v, 6,  8, 0
2739 MBEDGE_LOOPFILTER mmx,    h, 6,  8, 0
2740
2741 %define SPLATB_REG SPLATB_REG_MMXEXT
2742 MBEDGE_LOOPFILTER mmxext, v, 6, 16, 0
2743 MBEDGE_LOOPFILTER mmxext, h, 6, 16, 0
2744 MBEDGE_LOOPFILTER mmxext, v, 6,  8, 0
2745 MBEDGE_LOOPFILTER mmxext, h, 6,  8, 0
2746
2747 INIT_XMM
2748 %define SPLATB_REG SPLATB_REG_SSE2
2749 %define WRITE_8W   WRITE_8W_SSE2
2750 MBEDGE_LOOPFILTER sse2,   v, 5, 16, 15
2751 %ifdef m8
2752 MBEDGE_LOOPFILTER sse2,   h, 5, 16, 15
2753 %else
2754 MBEDGE_LOOPFILTER sse2,   h, 6, 16, 15
2755 %endif
2756 MBEDGE_LOOPFILTER sse2,   v, 6,  8, 15
2757 MBEDGE_LOOPFILTER sse2,   h, 6,  8, 15
2758
2759 %define SPLATB_REG SPLATB_REG_SSSE3
2760 MBEDGE_LOOPFILTER ssse3,  v, 5, 16, 15
2761 %ifdef m8
2762 MBEDGE_LOOPFILTER ssse3,  h, 5, 16, 15
2763 %else
2764 MBEDGE_LOOPFILTER ssse3,  h, 6, 16, 15
2765 %endif
2766 MBEDGE_LOOPFILTER ssse3,  v, 6,  8, 15
2767 MBEDGE_LOOPFILTER ssse3,  h, 6,  8, 15
2768
2769 %define WRITE_8W   WRITE_8W_SSE4
2770 %ifdef m8
2771 MBEDGE_LOOPFILTER sse4,   h, 5, 16, 15
2772 %else
2773 MBEDGE_LOOPFILTER sse4,   h, 6, 16, 15
2774 %endif
2775 MBEDGE_LOOPFILTER sse4,   h, 6,  8, 15