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