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