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