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