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