]> git.sesse.net Git - ffmpeg/blob - libavcodec/x86/vp8dsp.asm
Merge commit '17adcc40adf1f30cba55c9727dabc1365944d32b'
[ffmpeg] / libavcodec / x86 / vp8dsp.asm
1 ;******************************************************************************
2 ;* VP8 MMXEXT optimizations
3 ;* Copyright (c) 2010 Ronald S. Bultje <rsbultje@gmail.com>
4 ;* Copyright (c) 2010 Fiona Glaser <fiona@x264.com>
5 ;*
6 ;* This file is part of FFmpeg.
7 ;*
8 ;* FFmpeg is free software; you can redistribute it and/or
9 ;* modify it under the terms of the GNU Lesser General Public
10 ;* License as published by the Free Software Foundation; either
11 ;* version 2.1 of the License, or (at your option) any later version.
12 ;*
13 ;* FFmpeg is distributed in the hope that it will be useful,
14 ;* but WITHOUT ANY WARRANTY; without even the implied warranty of
15 ;* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16 ;* Lesser General Public License for more details.
17 ;*
18 ;* You should have received a copy of the GNU Lesser General Public
19 ;* License along with FFmpeg; if not, write to the Free Software
20 ;* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
21 ;******************************************************************************
22
23 %include "libavutil/x86/x86util.asm"
24
25 SECTION_RODATA
26
27 fourtap_filter_hw_m: times 4 dw  -6, 123
28                      times 4 dw  12,  -1
29                      times 4 dw  -9,  93
30                      times 4 dw  50,  -6
31                      times 4 dw  -6,  50
32                      times 4 dw  93,  -9
33                      times 4 dw  -1,  12
34                      times 4 dw 123,  -6
35
36 sixtap_filter_hw_m:  times 4 dw   2, -11
37                      times 4 dw 108,  36
38                      times 4 dw  -8,   1
39                      times 4 dw   3, -16
40                      times 4 dw  77,  77
41                      times 4 dw -16,   3
42                      times 4 dw   1,  -8
43                      times 4 dw  36, 108
44                      times 4 dw -11,   2
45
46 fourtap_filter_hb_m: times 8 db  -6, 123
47                      times 8 db  12,  -1
48                      times 8 db  -9,  93
49                      times 8 db  50,  -6
50                      times 8 db  -6,  50
51                      times 8 db  93,  -9
52                      times 8 db  -1,  12
53                      times 8 db 123,  -6
54
55 sixtap_filter_hb_m:  times 8 db   2,   1
56                      times 8 db -11, 108
57                      times 8 db  36,  -8
58                      times 8 db   3,   3
59                      times 8 db -16,  77
60                      times 8 db  77, -16
61                      times 8 db   1,   2
62                      times 8 db  -8,  36
63                      times 8 db 108, -11
64
65 fourtap_filter_v_m:  times 8 dw  -6
66                      times 8 dw 123
67                      times 8 dw  12
68                      times 8 dw  -1
69                      times 8 dw  -9
70                      times 8 dw  93
71                      times 8 dw  50
72                      times 8 dw  -6
73                      times 8 dw  -6
74                      times 8 dw  50
75                      times 8 dw  93
76                      times 8 dw  -9
77                      times 8 dw  -1
78                      times 8 dw  12
79                      times 8 dw 123
80                      times 8 dw  -6
81
82 sixtap_filter_v_m:   times 8 dw   2
83                      times 8 dw -11
84                      times 8 dw 108
85                      times 8 dw  36
86                      times 8 dw  -8
87                      times 8 dw   1
88                      times 8 dw   3
89                      times 8 dw -16
90                      times 8 dw  77
91                      times 8 dw  77
92                      times 8 dw -16
93                      times 8 dw   3
94                      times 8 dw   1
95                      times 8 dw  -8
96                      times 8 dw  36
97                      times 8 dw 108
98                      times 8 dw -11
99                      times 8 dw   2
100
101 bilinear_filter_vw_m: times 8 dw 1
102                       times 8 dw 2
103                       times 8 dw 3
104                       times 8 dw 4
105                       times 8 dw 5
106                       times 8 dw 6
107                       times 8 dw 7
108
109 bilinear_filter_vb_m: times 8 db 7, 1
110                       times 8 db 6, 2
111                       times 8 db 5, 3
112                       times 8 db 4, 4
113                       times 8 db 3, 5
114                       times 8 db 2, 6
115                       times 8 db 1, 7
116
117 %ifdef PIC
118 %define fourtap_filter_hw  picregq
119 %define sixtap_filter_hw   picregq
120 %define fourtap_filter_hb  picregq
121 %define sixtap_filter_hb   picregq
122 %define fourtap_filter_v   picregq
123 %define sixtap_filter_v    picregq
124 %define bilinear_filter_vw picregq
125 %define bilinear_filter_vb picregq
126 %define npicregs 1
127 %else
128 %define fourtap_filter_hw  fourtap_filter_hw_m
129 %define sixtap_filter_hw   sixtap_filter_hw_m
130 %define fourtap_filter_hb  fourtap_filter_hb_m
131 %define sixtap_filter_hb   sixtap_filter_hb_m
132 %define fourtap_filter_v   fourtap_filter_v_m
133 %define sixtap_filter_v    sixtap_filter_v_m
134 %define bilinear_filter_vw bilinear_filter_vw_m
135 %define bilinear_filter_vb bilinear_filter_vb_m
136 %define npicregs 0
137 %endif
138
139 filter_h2_shuf:  db 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5,  6, 6,  7,  7,  8
140 filter_h4_shuf:  db 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7,  8, 8,  9,  9, 10
141
142 filter_h6_shuf1: db 0, 5, 1, 6, 2, 7, 3, 8, 4, 9, 5, 10, 6, 11,  7, 12
143 filter_h6_shuf2: db 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6,  7, 7,  8,  8,  9
144 filter_h6_shuf3: db 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 8,  9, 9, 10, 10, 11
145
146 pw_20091: times 4 dw 20091
147 pw_17734: times 4 dw 17734
148
149 cextern pw_3
150 cextern pw_4
151 cextern pw_64
152 cextern pw_256
153
154 SECTION .text
155
156 ;-------------------------------------------------------------------------------
157 ; subpel MC functions:
158 ;
159 ; void ff_put_vp8_epel<size>_h<htap>v<vtap>_<opt>(uint8_t *dst, ptrdiff_t deststride,
160 ;                                                 uint8_t *src, ptrdiff_t srcstride,
161 ;                                                 int height,   int mx, int my);
162 ;-------------------------------------------------------------------------------
163
164 %macro FILTER_SSSE3 1
165 cglobal put_vp8_epel%1_h6, 6, 6 + npicregs, 8, dst, dststride, src, srcstride, height, mx, picreg
166     lea      mxd, [mxq*3]
167     mova      m3, [filter_h6_shuf2]
168     mova      m4, [filter_h6_shuf3]
169 %ifdef PIC
170     lea  picregq, [sixtap_filter_hb_m]
171 %endif
172     mova      m5, [sixtap_filter_hb+mxq*8-48] ; set up 6tap filter in bytes
173     mova      m6, [sixtap_filter_hb+mxq*8-32]
174     mova      m7, [sixtap_filter_hb+mxq*8-16]
175
176 .nextrow:
177     movu      m0, [srcq-2]
178     mova      m1, m0
179     mova      m2, m0
180 %if mmsize == 8
181 ; For epel4, we need 9 bytes, but only 8 get loaded; to compensate, do the
182 ; shuffle with a memory operand
183     punpcklbw m0, [srcq+3]
184 %else
185     pshufb    m0, [filter_h6_shuf1]
186 %endif
187     pshufb    m1, m3
188     pshufb    m2, m4
189     pmaddubsw m0, m5
190     pmaddubsw m1, m6
191     pmaddubsw m2, m7
192     paddsw    m0, m1
193     paddsw    m0, m2
194     pmulhrsw  m0, [pw_256]
195     packuswb  m0, m0
196     movh  [dstq], m0        ; store
197
198     ; go to next line
199     add     dstq, dststrideq
200     add     srcq, srcstrideq
201     dec  heightd            ; next row
202     jg .nextrow
203     REP_RET
204
205 cglobal put_vp8_epel%1_h4, 6, 6 + npicregs, 7, dst, dststride, src, srcstride, height, mx, picreg
206     shl      mxd, 4
207     mova      m2, [pw_256]
208     mova      m3, [filter_h2_shuf]
209     mova      m4, [filter_h4_shuf]
210 %ifdef PIC
211     lea  picregq, [fourtap_filter_hb_m]
212 %endif
213     mova      m5, [fourtap_filter_hb+mxq-16] ; set up 4tap filter in bytes
214     mova      m6, [fourtap_filter_hb+mxq]
215
216 .nextrow:
217     movu      m0, [srcq-1]
218     mova      m1, m0
219     pshufb    m0, m3
220     pshufb    m1, m4
221     pmaddubsw m0, m5
222     pmaddubsw m1, m6
223     paddsw    m0, m1
224     pmulhrsw  m0, m2
225     packuswb  m0, m0
226     movh  [dstq], m0        ; store
227
228     ; go to next line
229     add     dstq, dststrideq
230     add     srcq, srcstrideq
231     dec  heightd            ; next row
232     jg .nextrow
233     REP_RET
234
235 cglobal put_vp8_epel%1_v4, 7, 7, 8, dst, dststride, src, srcstride, height, picreg, my
236     shl      myd, 4
237 %ifdef PIC
238     lea  picregq, [fourtap_filter_hb_m]
239 %endif
240     mova      m5, [fourtap_filter_hb+myq-16]
241     mova      m6, [fourtap_filter_hb+myq]
242     mova      m7, [pw_256]
243
244     ; read 3 lines
245     sub     srcq, srcstrideq
246     movh      m0, [srcq]
247     movh      m1, [srcq+  srcstrideq]
248     movh      m2, [srcq+2*srcstrideq]
249     add     srcq, srcstrideq
250
251 .nextrow:
252     movh      m3, [srcq+2*srcstrideq]      ; read new row
253     mova      m4, m0
254     mova      m0, m1
255     punpcklbw m4, m1
256     mova      m1, m2
257     punpcklbw m2, m3
258     pmaddubsw m4, m5
259     pmaddubsw m2, m6
260     paddsw    m4, m2
261     mova      m2, m3
262     pmulhrsw  m4, m7
263     packuswb  m4, m4
264     movh  [dstq], m4
265
266     ; go to next line
267     add      dstq, dststrideq
268     add      srcq, srcstrideq
269     dec   heightd                          ; next row
270     jg .nextrow
271     REP_RET
272
273 cglobal put_vp8_epel%1_v6, 7, 7, 8, dst, dststride, src, srcstride, height, picreg, my
274     lea      myd, [myq*3]
275 %ifdef PIC
276     lea  picregq, [sixtap_filter_hb_m]
277 %endif
278     lea      myq, [sixtap_filter_hb+myq*8]
279
280     ; read 5 lines
281     sub     srcq, srcstrideq
282     sub     srcq, srcstrideq
283     movh      m0, [srcq]
284     movh      m1, [srcq+srcstrideq]
285     movh      m2, [srcq+srcstrideq*2]
286     lea     srcq, [srcq+srcstrideq*2]
287     add     srcq, srcstrideq
288     movh      m3, [srcq]
289     movh      m4, [srcq+srcstrideq]
290
291 .nextrow:
292     movh      m5, [srcq+2*srcstrideq]      ; read new row
293     mova      m6, m0
294     punpcklbw m6, m5
295     mova      m0, m1
296     punpcklbw m1, m2
297     mova      m7, m3
298     punpcklbw m7, m4
299     pmaddubsw m6, [myq-48]
300     pmaddubsw m1, [myq-32]
301     pmaddubsw m7, [myq-16]
302     paddsw    m6, m1
303     paddsw    m6, m7
304     mova      m1, m2
305     mova      m2, m3
306     pmulhrsw  m6, [pw_256]
307     mova      m3, m4
308     packuswb  m6, m6
309     mova      m4, m5
310     movh  [dstq], m6
311
312     ; go to next line
313     add      dstq, dststrideq
314     add      srcq, srcstrideq
315     dec   heightd                          ; next row
316     jg .nextrow
317     REP_RET
318 %endmacro
319
320 INIT_MMX ssse3
321 FILTER_SSSE3 4
322 INIT_XMM ssse3
323 FILTER_SSSE3 8
324
325 ; 4x4 block, H-only 4-tap filter
326 INIT_MMX mmxext
327 cglobal put_vp8_epel4_h4, 6, 6 + npicregs, 0, dst, dststride, src, srcstride, height, mx, picreg
328     shl       mxd, 4
329 %ifdef PIC
330     lea   picregq, [fourtap_filter_hw_m]
331 %endif
332     movq      mm4, [fourtap_filter_hw+mxq-16] ; set up 4tap filter in words
333     movq      mm5, [fourtap_filter_hw+mxq]
334     movq      mm7, [pw_64]
335     pxor      mm6, mm6
336
337 .nextrow:
338     movq      mm1, [srcq-1]                ; (ABCDEFGH) load 8 horizontal pixels
339
340     ; first set of 2 pixels
341     movq      mm2, mm1                     ; byte ABCD..
342     punpcklbw mm1, mm6                     ; byte->word ABCD
343     pshufw    mm0, mm2, 9                  ; byte CDEF..
344     punpcklbw mm0, mm6                     ; byte->word CDEF
345     pshufw    mm3, mm1, 0x94               ; word ABBC
346     pshufw    mm1, mm0, 0x94               ; word CDDE
347     pmaddwd   mm3, mm4                     ; multiply 2px with F0/F1
348     movq      mm0, mm1                     ; backup for second set of pixels
349     pmaddwd   mm1, mm5                     ; multiply 2px with F2/F3
350     paddd     mm3, mm1                     ; finish 1st 2px
351
352     ; second set of 2 pixels, use backup of above
353     punpckhbw mm2, mm6                     ; byte->word EFGH
354     pmaddwd   mm0, mm4                     ; multiply backed up 2px with F0/F1
355     pshufw    mm1, mm2, 0x94               ; word EFFG
356     pmaddwd   mm1, mm5                     ; multiply 2px with F2/F3
357     paddd     mm0, mm1                     ; finish 2nd 2px
358
359     ; merge two sets of 2 pixels into one set of 4, round/clip/store
360     packssdw  mm3, mm0                     ; merge dword->word (4px)
361     paddsw    mm3, mm7                     ; rounding
362     psraw     mm3, 7
363     packuswb  mm3, mm6                     ; clip and word->bytes
364     movd   [dstq], mm3                     ; store
365
366     ; go to next line
367     add      dstq, dststrideq
368     add      srcq, srcstrideq
369     dec   heightd                          ; next row
370     jg .nextrow
371     REP_RET
372
373 ; 4x4 block, H-only 6-tap filter
374 INIT_MMX mmxext
375 cglobal put_vp8_epel4_h6, 6, 6 + npicregs, 0, dst, dststride, src, srcstride, height, mx, picreg
376     lea       mxd, [mxq*3]
377 %ifdef PIC
378     lea   picregq, [sixtap_filter_hw_m]
379 %endif
380     movq      mm4, [sixtap_filter_hw+mxq*8-48] ; set up 4tap filter in words
381     movq      mm5, [sixtap_filter_hw+mxq*8-32]
382     movq      mm6, [sixtap_filter_hw+mxq*8-16]
383     movq      mm7, [pw_64]
384     pxor      mm3, mm3
385
386 .nextrow:
387     movq      mm1, [srcq-2]                ; (ABCDEFGH) load 8 horizontal pixels
388
389     ; first set of 2 pixels
390     movq      mm2, mm1                     ; byte ABCD..
391     punpcklbw mm1, mm3                     ; byte->word ABCD
392     pshufw    mm0, mm2, 0x9                ; byte CDEF..
393     punpckhbw mm2, mm3                     ; byte->word EFGH
394     punpcklbw mm0, mm3                     ; byte->word CDEF
395     pshufw    mm1, mm1, 0x94               ; word ABBC
396     pshufw    mm2, mm2, 0x94               ; word EFFG
397     pmaddwd   mm1, mm4                     ; multiply 2px with F0/F1
398     pshufw    mm3, mm0, 0x94               ; word CDDE
399     movq      mm0, mm3                     ; backup for second set of pixels
400     pmaddwd   mm3, mm5                     ; multiply 2px with F2/F3
401     paddd     mm1, mm3                     ; add to 1st 2px cache
402     movq      mm3, mm2                     ; backup for second set of pixels
403     pmaddwd   mm2, mm6                     ; multiply 2px with F4/F5
404     paddd     mm1, mm2                     ; finish 1st 2px
405
406     ; second set of 2 pixels, use backup of above
407     movd      mm2, [srcq+3]                ; byte FGHI (prevent overreads)
408     pmaddwd   mm0, mm4                     ; multiply 1st backed up 2px with F0/F1
409     pmaddwd   mm3, mm5                     ; multiply 2nd backed up 2px with F2/F3
410     paddd     mm0, mm3                     ; add to 2nd 2px cache
411     pxor      mm3, mm3
412     punpcklbw mm2, mm3                     ; byte->word FGHI
413     pshufw    mm2, mm2, 0xE9               ; word GHHI
414     pmaddwd   mm2, mm6                     ; multiply 2px with F4/F5
415     paddd     mm0, mm2                     ; finish 2nd 2px
416
417     ; merge two sets of 2 pixels into one set of 4, round/clip/store
418     packssdw  mm1, mm0                     ; merge dword->word (4px)
419     paddsw    mm1, mm7                     ; rounding
420     psraw     mm1, 7
421     packuswb  mm1, mm3                     ; clip and word->bytes
422     movd   [dstq], mm1                     ; store
423
424     ; go to next line
425     add      dstq, dststrideq
426     add      srcq, srcstrideq
427     dec   heightd                          ; next row
428     jg .nextrow
429     REP_RET
430
431 INIT_XMM sse2
432 cglobal put_vp8_epel8_h4, 6, 6 + npicregs, 10, dst, dststride, src, srcstride, height, mx, picreg
433     shl      mxd, 5
434 %ifdef PIC
435     lea  picregq, [fourtap_filter_v_m]
436 %endif
437     lea      mxq, [fourtap_filter_v+mxq-32]
438     pxor      m7, m7
439     mova      m4, [pw_64]
440     mova      m5, [mxq+ 0]
441     mova      m6, [mxq+16]
442 %ifdef m8
443     mova      m8, [mxq+32]
444     mova      m9, [mxq+48]
445 %endif
446 .nextrow:
447     movq      m0, [srcq-1]
448     movq      m1, [srcq-0]
449     movq      m2, [srcq+1]
450     movq      m3, [srcq+2]
451     punpcklbw m0, m7
452     punpcklbw m1, m7
453     punpcklbw m2, m7
454     punpcklbw m3, m7
455     pmullw    m0, m5
456     pmullw    m1, m6
457 %ifdef m8
458     pmullw    m2, m8
459     pmullw    m3, m9
460 %else
461     pmullw    m2, [mxq+32]
462     pmullw    m3, [mxq+48]
463 %endif
464     paddsw    m0, m1
465     paddsw    m2, m3
466     paddsw    m0, m2
467     paddsw    m0, m4
468     psraw     m0, 7
469     packuswb  m0, m7
470     movh  [dstq], m0        ; store
471
472     ; go to next line
473     add     dstq, dststrideq
474     add     srcq, srcstrideq
475     dec  heightd            ; next row
476     jg .nextrow
477     REP_RET
478
479 INIT_XMM sse2
480 cglobal put_vp8_epel8_h6, 6, 6 + npicregs, 14, dst, dststride, src, srcstride, height, mx, picreg
481     lea      mxd, [mxq*3]
482     shl      mxd, 4
483 %ifdef PIC
484     lea  picregq, [sixtap_filter_v_m]
485 %endif
486     lea      mxq, [sixtap_filter_v+mxq-96]
487     pxor      m7, m7
488     mova      m6, [pw_64]
489 %ifdef m8
490     mova      m8, [mxq+ 0]
491     mova      m9, [mxq+16]
492     mova     m10, [mxq+32]
493     mova     m11, [mxq+48]
494     mova     m12, [mxq+64]
495     mova     m13, [mxq+80]
496 %endif
497 .nextrow:
498     movq      m0, [srcq-2]
499     movq      m1, [srcq-1]
500     movq      m2, [srcq-0]
501     movq      m3, [srcq+1]
502     movq      m4, [srcq+2]
503     movq      m5, [srcq+3]
504     punpcklbw m0, m7
505     punpcklbw m1, m7
506     punpcklbw m2, m7
507     punpcklbw m3, m7
508     punpcklbw m4, m7
509     punpcklbw m5, m7
510 %ifdef m8
511     pmullw    m0, m8
512     pmullw    m1, m9
513     pmullw    m2, m10
514     pmullw    m3, m11
515     pmullw    m4, m12
516     pmullw    m5, m13
517 %else
518     pmullw    m0, [mxq+ 0]
519     pmullw    m1, [mxq+16]
520     pmullw    m2, [mxq+32]
521     pmullw    m3, [mxq+48]
522     pmullw    m4, [mxq+64]
523     pmullw    m5, [mxq+80]
524 %endif
525     paddsw    m1, m4
526     paddsw    m0, m5
527     paddsw    m1, m2
528     paddsw    m0, m3
529     paddsw    m0, m1
530     paddsw    m0, m6
531     psraw     m0, 7
532     packuswb  m0, m7
533     movh  [dstq], m0        ; store
534
535     ; go to next line
536     add     dstq, dststrideq
537     add     srcq, srcstrideq
538     dec  heightd            ; next row
539     jg .nextrow
540     REP_RET
541
542 %macro FILTER_V 1
543 ; 4x4 block, V-only 4-tap filter
544 cglobal put_vp8_epel%1_v4, 7, 7, 8, dst, dststride, src, srcstride, height, picreg, my
545     shl      myd, 5
546 %ifdef PIC
547     lea  picregq, [fourtap_filter_v_m]
548 %endif
549     lea      myq, [fourtap_filter_v+myq-32]
550     mova      m6, [pw_64]
551     pxor      m7, m7
552     mova      m5, [myq+48]
553
554     ; read 3 lines
555     sub     srcq, srcstrideq
556     movh      m0, [srcq]
557     movh      m1, [srcq+  srcstrideq]
558     movh      m2, [srcq+2*srcstrideq]
559     add     srcq, srcstrideq
560     punpcklbw m0, m7
561     punpcklbw m1, m7
562     punpcklbw m2, m7
563
564 .nextrow:
565     ; first calculate negative taps (to prevent losing positive overflows)
566     movh      m4, [srcq+2*srcstrideq]      ; read new row
567     punpcklbw m4, m7
568     mova      m3, m4
569     pmullw    m0, [myq+0]
570     pmullw    m4, m5
571     paddsw    m4, m0
572
573     ; then calculate positive taps
574     mova      m0, m1
575     pmullw    m1, [myq+16]
576     paddsw    m4, m1
577     mova      m1, m2
578     pmullw    m2, [myq+32]
579     paddsw    m4, m2
580     mova      m2, m3
581
582     ; round/clip/store
583     paddsw    m4, m6
584     psraw     m4, 7
585     packuswb  m4, m7
586     movh  [dstq], m4
587
588     ; go to next line
589     add     dstq, dststrideq
590     add     srcq, srcstrideq
591     dec  heightd                           ; next row
592     jg .nextrow
593     REP_RET
594
595
596 ; 4x4 block, V-only 6-tap filter
597 cglobal put_vp8_epel%1_v6, 7, 7, 8, dst, dststride, src, srcstride, height, picreg, my
598     shl      myd, 4
599     lea      myq, [myq*3]
600 %ifdef PIC
601     lea  picregq, [sixtap_filter_v_m]
602 %endif
603     lea      myq, [sixtap_filter_v+myq-96]
604     pxor      m7, m7
605
606     ; read 5 lines
607     sub     srcq, srcstrideq
608     sub     srcq, srcstrideq
609     movh      m0, [srcq]
610     movh      m1, [srcq+srcstrideq]
611     movh      m2, [srcq+srcstrideq*2]
612     lea     srcq, [srcq+srcstrideq*2]
613     add     srcq, srcstrideq
614     movh      m3, [srcq]
615     movh      m4, [srcq+srcstrideq]
616     punpcklbw m0, m7
617     punpcklbw m1, m7
618     punpcklbw m2, m7
619     punpcklbw m3, m7
620     punpcklbw m4, m7
621
622 .nextrow:
623     ; first calculate negative taps (to prevent losing positive overflows)
624     mova      m5, m1
625     pmullw    m5, [myq+16]
626     mova      m6, m4
627     pmullw    m6, [myq+64]
628     paddsw    m6, m5
629
630     ; then calculate positive taps
631     movh      m5, [srcq+2*srcstrideq]      ; read new row
632     punpcklbw m5, m7
633     pmullw    m0, [myq+0]
634     paddsw    m6, m0
635     mova      m0, m1
636     mova      m1, m2
637     pmullw    m2, [myq+32]
638     paddsw    m6, m2
639     mova      m2, m3
640     pmullw    m3, [myq+48]
641     paddsw    m6, m3
642     mova      m3, m4
643     mova      m4, m5
644     pmullw    m5, [myq+80]
645     paddsw    m6, m5
646
647     ; round/clip/store
648     paddsw    m6, [pw_64]
649     psraw     m6, 7
650     packuswb  m6, m7
651     movh  [dstq], m6
652
653     ; go to next line
654     add     dstq, dststrideq
655     add     srcq, srcstrideq
656     dec  heightd                           ; next row
657     jg .nextrow
658     REP_RET
659 %endmacro
660
661 INIT_MMX mmxext
662 FILTER_V 4
663 INIT_XMM sse2
664 FILTER_V 8
665
666 %macro FILTER_BILINEAR 1
667 cglobal put_vp8_bilinear%1_v, 7, 7, 7, dst, dststride, src, srcstride, height, picreg, my
668     shl      myd, 4
669 %ifdef PIC
670     lea  picregq, [bilinear_filter_vw_m]
671 %endif
672     pxor      m6, m6
673     mova      m5, [bilinear_filter_vw+myq-1*16]
674     neg      myq
675     mova      m4, [bilinear_filter_vw+myq+7*16]
676 .nextrow:
677     movh      m0, [srcq+srcstrideq*0]
678     movh      m1, [srcq+srcstrideq*1]
679     movh      m3, [srcq+srcstrideq*2]
680     punpcklbw m0, m6
681     punpcklbw m1, m6
682     punpcklbw m3, m6
683     mova      m2, m1
684     pmullw    m0, m4
685     pmullw    m1, m5
686     pmullw    m2, m4
687     pmullw    m3, m5
688     paddsw    m0, m1
689     paddsw    m2, m3
690     psraw     m0, 2
691     psraw     m2, 2
692     pavgw     m0, m6
693     pavgw     m2, m6
694 %if mmsize == 8
695     packuswb  m0, m0
696     packuswb  m2, m2
697     movh   [dstq+dststrideq*0], m0
698     movh   [dstq+dststrideq*1], m2
699 %else
700     packuswb  m0, m2
701     movh   [dstq+dststrideq*0], m0
702     movhps [dstq+dststrideq*1], m0
703 %endif
704
705     lea     dstq, [dstq+dststrideq*2]
706     lea     srcq, [srcq+srcstrideq*2]
707     sub  heightd, 2
708     jg .nextrow
709     REP_RET
710
711 cglobal put_vp8_bilinear%1_h, 6, 6 + npicregs, 7, dst, dststride, src, srcstride, height, mx, picreg
712     shl      mxd, 4
713 %ifdef PIC
714     lea  picregq, [bilinear_filter_vw_m]
715 %endif
716     pxor      m6, m6
717     mova      m5, [bilinear_filter_vw+mxq-1*16]
718     neg      mxq
719     mova      m4, [bilinear_filter_vw+mxq+7*16]
720 .nextrow:
721     movh      m0, [srcq+srcstrideq*0+0]
722     movh      m1, [srcq+srcstrideq*0+1]
723     movh      m2, [srcq+srcstrideq*1+0]
724     movh      m3, [srcq+srcstrideq*1+1]
725     punpcklbw m0, m6
726     punpcklbw m1, m6
727     punpcklbw m2, m6
728     punpcklbw m3, m6
729     pmullw    m0, m4
730     pmullw    m1, m5
731     pmullw    m2, m4
732     pmullw    m3, m5
733     paddsw    m0, m1
734     paddsw    m2, m3
735     psraw     m0, 2
736     psraw     m2, 2
737     pavgw     m0, m6
738     pavgw     m2, m6
739 %if mmsize == 8
740     packuswb  m0, m0
741     packuswb  m2, m2
742     movh   [dstq+dststrideq*0], m0
743     movh   [dstq+dststrideq*1], m2
744 %else
745     packuswb  m0, m2
746     movh   [dstq+dststrideq*0], m0
747     movhps [dstq+dststrideq*1], m0
748 %endif
749
750     lea     dstq, [dstq+dststrideq*2]
751     lea     srcq, [srcq+srcstrideq*2]
752     sub  heightd, 2
753     jg .nextrow
754     REP_RET
755 %endmacro
756
757 INIT_MMX mmxext
758 FILTER_BILINEAR 4
759 INIT_XMM sse2
760 FILTER_BILINEAR 8
761
762 %macro FILTER_BILINEAR_SSSE3 1
763 cglobal put_vp8_bilinear%1_v, 7, 7, 5, dst, dststride, src, srcstride, height, picreg, my
764     shl      myd, 4
765 %ifdef PIC
766     lea  picregq, [bilinear_filter_vb_m]
767 %endif
768     pxor      m4, m4
769     mova      m3, [bilinear_filter_vb+myq-16]
770 .nextrow:
771     movh      m0, [srcq+srcstrideq*0]
772     movh      m1, [srcq+srcstrideq*1]
773     movh      m2, [srcq+srcstrideq*2]
774     punpcklbw m0, m1
775     punpcklbw m1, m2
776     pmaddubsw m0, m3
777     pmaddubsw m1, m3
778     psraw     m0, 2
779     psraw     m1, 2
780     pavgw     m0, m4
781     pavgw     m1, m4
782 %if mmsize==8
783     packuswb  m0, m0
784     packuswb  m1, m1
785     movh   [dstq+dststrideq*0], m0
786     movh   [dstq+dststrideq*1], m1
787 %else
788     packuswb  m0, m1
789     movh   [dstq+dststrideq*0], m0
790     movhps [dstq+dststrideq*1], m0
791 %endif
792
793     lea     dstq, [dstq+dststrideq*2]
794     lea     srcq, [srcq+srcstrideq*2]
795     sub  heightd, 2
796     jg .nextrow
797     REP_RET
798
799 cglobal put_vp8_bilinear%1_h, 6, 6 + npicregs, 5, dst, dststride, src, srcstride, height, mx, picreg
800     shl      mxd, 4
801 %ifdef PIC
802     lea  picregq, [bilinear_filter_vb_m]
803 %endif
804     pxor      m4, m4
805     mova      m2, [filter_h2_shuf]
806     mova      m3, [bilinear_filter_vb+mxq-16]
807 .nextrow:
808     movu      m0, [srcq+srcstrideq*0]
809     movu      m1, [srcq+srcstrideq*1]
810     pshufb    m0, m2
811     pshufb    m1, m2
812     pmaddubsw m0, m3
813     pmaddubsw m1, m3
814     psraw     m0, 2
815     psraw     m1, 2
816     pavgw     m0, m4
817     pavgw     m1, m4
818 %if mmsize==8
819     packuswb  m0, m0
820     packuswb  m1, m1
821     movh   [dstq+dststrideq*0], m0
822     movh   [dstq+dststrideq*1], m1
823 %else
824     packuswb  m0, m1
825     movh   [dstq+dststrideq*0], m0
826     movhps [dstq+dststrideq*1], m0
827 %endif
828
829     lea     dstq, [dstq+dststrideq*2]
830     lea     srcq, [srcq+srcstrideq*2]
831     sub  heightd, 2
832     jg .nextrow
833     REP_RET
834 %endmacro
835
836 INIT_MMX ssse3
837 FILTER_BILINEAR_SSSE3 4
838 INIT_XMM ssse3
839 FILTER_BILINEAR_SSSE3 8
840
841 INIT_MMX mmx
842 cglobal put_vp8_pixels8, 5, 5, 0, dst, dststride, src, srcstride, height
843 .nextrow:
844     movq    mm0, [srcq+srcstrideq*0]
845     movq    mm1, [srcq+srcstrideq*1]
846     lea    srcq, [srcq+srcstrideq*2]
847     movq [dstq+dststrideq*0], mm0
848     movq [dstq+dststrideq*1], mm1
849     lea    dstq, [dstq+dststrideq*2]
850     sub heightd, 2
851     jg .nextrow
852     REP_RET
853
854 %if ARCH_X86_32
855 INIT_MMX mmx
856 cglobal put_vp8_pixels16, 5, 5, 0, dst, dststride, src, srcstride, height
857 .nextrow:
858     movq    mm0, [srcq+srcstrideq*0+0]
859     movq    mm1, [srcq+srcstrideq*0+8]
860     movq    mm2, [srcq+srcstrideq*1+0]
861     movq    mm3, [srcq+srcstrideq*1+8]
862     lea    srcq, [srcq+srcstrideq*2]
863     movq [dstq+dststrideq*0+0], mm0
864     movq [dstq+dststrideq*0+8], mm1
865     movq [dstq+dststrideq*1+0], mm2
866     movq [dstq+dststrideq*1+8], mm3
867     lea    dstq, [dstq+dststrideq*2]
868     sub heightd, 2
869     jg .nextrow
870     REP_RET
871 %endif
872
873 INIT_XMM sse
874 cglobal put_vp8_pixels16, 5, 5, 2, dst, dststride, src, srcstride, height
875 .nextrow:
876     movups xmm0, [srcq+srcstrideq*0]
877     movups xmm1, [srcq+srcstrideq*1]
878     lea    srcq, [srcq+srcstrideq*2]
879     movaps [dstq+dststrideq*0], xmm0
880     movaps [dstq+dststrideq*1], xmm1
881     lea    dstq, [dstq+dststrideq*2]
882     sub heightd, 2
883     jg .nextrow
884     REP_RET
885
886 ;-----------------------------------------------------------------------------
887 ; void ff_vp8_idct_dc_add_<opt>(uint8_t *dst, int16_t block[16], ptrdiff_t stride);
888 ;-----------------------------------------------------------------------------
889
890 %macro ADD_DC 4
891     %4        m2, [dst1q+%3]
892     %4        m3, [dst1q+strideq+%3]
893     %4        m4, [dst2q+%3]
894     %4        m5, [dst2q+strideq+%3]
895     paddusb   m2, %1
896     paddusb   m3, %1
897     paddusb   m4, %1
898     paddusb   m5, %1
899     psubusb   m2, %2
900     psubusb   m3, %2
901     psubusb   m4, %2
902     psubusb   m5, %2
903     %4 [dst1q+%3], m2
904     %4 [dst1q+strideq+%3], m3
905     %4 [dst2q+%3], m4
906     %4 [dst2q+strideq+%3], m5
907 %endmacro
908
909 %if ARCH_X86_32
910 INIT_MMX mmx
911 cglobal vp8_idct_dc_add, 3, 3, 0, dst, block, stride
912     ; load data
913     movd       m0, [blockq]
914
915     ; calculate DC
916     paddw      m0, [pw_4]
917     pxor       m1, m1
918     psraw      m0, 3
919     movd [blockq], m1
920     psubw      m1, m0
921     packuswb   m0, m0
922     packuswb   m1, m1
923     punpcklbw  m0, m0
924     punpcklbw  m1, m1
925     punpcklwd  m0, m0
926     punpcklwd  m1, m1
927
928     ; add DC
929     DEFINE_ARGS dst1, dst2, stride
930     lea     dst2q, [dst1q+strideq*2]
931     ADD_DC     m0, m1, 0, movh
932     RET
933 %endif
934
935 %macro VP8_IDCT_DC_ADD 0
936 cglobal vp8_idct_dc_add, 3, 3, 6, dst, block, stride
937     ; load data
938     movd       m0, [blockq]
939     pxor       m1, m1
940
941     ; calculate DC
942     paddw      m0, [pw_4]
943     movd [blockq], m1
944     DEFINE_ARGS dst1, dst2, stride
945     lea     dst2q, [dst1q+strideq*2]
946     movd       m2, [dst1q]
947     movd       m3, [dst1q+strideq]
948     movd       m4, [dst2q]
949     movd       m5, [dst2q+strideq]
950     psraw      m0, 3
951     pshuflw    m0, m0, 0
952     punpcklqdq m0, m0
953     punpckldq  m2, m3
954     punpckldq  m4, m5
955     punpcklbw  m2, m1
956     punpcklbw  m4, m1
957     paddw      m2, m0
958     paddw      m4, m0
959     packuswb   m2, m4
960     movd   [dst1q], m2
961 %if cpuflag(sse4)
962     pextrd [dst1q+strideq], m2, 1
963     pextrd [dst2q], m2, 2
964     pextrd [dst2q+strideq], m2, 3
965 %else
966     psrldq     m2, 4
967     movd [dst1q+strideq], m2
968     psrldq     m2, 4
969     movd [dst2q], m2
970     psrldq     m2, 4
971     movd [dst2q+strideq], m2
972 %endif
973     RET
974 %endmacro
975
976 INIT_XMM sse2
977 VP8_IDCT_DC_ADD
978 INIT_XMM sse4
979 VP8_IDCT_DC_ADD
980
981 ;-----------------------------------------------------------------------------
982 ; void ff_vp8_idct_dc_add4y_<opt>(uint8_t *dst, int16_t block[4][16], ptrdiff_t stride);
983 ;-----------------------------------------------------------------------------
984
985 %if ARCH_X86_32
986 INIT_MMX mmx
987 cglobal vp8_idct_dc_add4y, 3, 3, 0, dst, block, stride
988     ; load data
989     movd      m0, [blockq+32*0] ; A
990     movd      m1, [blockq+32*2] ; C
991     punpcklwd m0, [blockq+32*1] ; A B
992     punpcklwd m1, [blockq+32*3] ; C D
993     punpckldq m0, m1        ; A B C D
994     pxor      m6, m6
995
996     ; calculate DC
997     paddw     m0, [pw_4]
998     movd [blockq+32*0], m6
999     movd [blockq+32*1], m6
1000     movd [blockq+32*2], m6
1001     movd [blockq+32*3], m6
1002     psraw     m0, 3
1003     psubw     m6, m0
1004     packuswb  m0, m0
1005     packuswb  m6, m6
1006     punpcklbw m0, m0 ; AABBCCDD
1007     punpcklbw m6, m6 ; AABBCCDD
1008     movq      m1, m0
1009     movq      m7, m6
1010     punpcklbw m0, m0 ; AAAABBBB
1011     punpckhbw m1, m1 ; CCCCDDDD
1012     punpcklbw m6, m6 ; AAAABBBB
1013     punpckhbw m7, m7 ; CCCCDDDD
1014
1015     ; add DC
1016     DEFINE_ARGS dst1, dst2, stride
1017     lea    dst2q, [dst1q+strideq*2]
1018     ADD_DC    m0, m6, 0, mova
1019     ADD_DC    m1, m7, 8, mova
1020     RET
1021 %endif
1022
1023 INIT_XMM sse2
1024 cglobal vp8_idct_dc_add4y, 3, 3, 6, dst, block, stride
1025     ; load data
1026     movd      m0, [blockq+32*0] ; A
1027     movd      m1, [blockq+32*2] ; C
1028     punpcklwd m0, [blockq+32*1] ; A B
1029     punpcklwd m1, [blockq+32*3] ; C D
1030     punpckldq m0, m1        ; A B C D
1031     pxor      m1, m1
1032
1033     ; calculate DC
1034     paddw     m0, [pw_4]
1035     movd [blockq+32*0], m1
1036     movd [blockq+32*1], m1
1037     movd [blockq+32*2], m1
1038     movd [blockq+32*3], m1
1039     psraw     m0, 3
1040     psubw     m1, m0
1041     packuswb  m0, m0
1042     packuswb  m1, m1
1043     punpcklbw m0, m0
1044     punpcklbw m1, m1
1045     punpcklbw m0, m0
1046     punpcklbw m1, m1
1047
1048     ; add DC
1049     DEFINE_ARGS dst1, dst2, stride
1050     lea    dst2q, [dst1q+strideq*2]
1051     ADD_DC    m0, m1, 0, mova
1052     RET
1053
1054 ;-----------------------------------------------------------------------------
1055 ; void ff_vp8_idct_dc_add4uv_<opt>(uint8_t *dst, int16_t block[4][16], ptrdiff_t stride);
1056 ;-----------------------------------------------------------------------------
1057
1058 INIT_MMX mmx
1059 cglobal vp8_idct_dc_add4uv, 3, 3, 0, dst, block, stride
1060     ; load data
1061     movd      m0, [blockq+32*0] ; A
1062     movd      m1, [blockq+32*2] ; C
1063     punpcklwd m0, [blockq+32*1] ; A B
1064     punpcklwd m1, [blockq+32*3] ; C D
1065     punpckldq m0, m1        ; A B C D
1066     pxor      m6, m6
1067
1068     ; calculate DC
1069     paddw     m0, [pw_4]
1070     movd [blockq+32*0], m6
1071     movd [blockq+32*1], m6
1072     movd [blockq+32*2], m6
1073     movd [blockq+32*3], m6
1074     psraw     m0, 3
1075     psubw     m6, m0
1076     packuswb  m0, m0
1077     packuswb  m6, m6
1078     punpcklbw m0, m0 ; AABBCCDD
1079     punpcklbw m6, m6 ; AABBCCDD
1080     movq      m1, m0
1081     movq      m7, m6
1082     punpcklbw m0, m0 ; AAAABBBB
1083     punpckhbw m1, m1 ; CCCCDDDD
1084     punpcklbw m6, m6 ; AAAABBBB
1085     punpckhbw m7, m7 ; CCCCDDDD
1086
1087     ; add DC
1088     DEFINE_ARGS dst1, dst2, stride
1089     lea    dst2q, [dst1q+strideq*2]
1090     ADD_DC    m0, m6, 0, mova
1091     lea    dst1q, [dst1q+strideq*4]
1092     lea    dst2q, [dst2q+strideq*4]
1093     ADD_DC    m1, m7, 0, mova
1094     RET
1095
1096 ;-----------------------------------------------------------------------------
1097 ; void ff_vp8_idct_add_<opt>(uint8_t *dst, int16_t block[16], ptrdiff_t stride);
1098 ;-----------------------------------------------------------------------------
1099
1100 ; calculate %1=mul_35468(%1)-mul_20091(%2); %2=mul_20091(%1)+mul_35468(%2)
1101 ;           this macro assumes that m6/m7 have words for 20091/17734 loaded
1102 %macro VP8_MULTIPLY_SUMSUB 4
1103     mova      %3, %1
1104     mova      %4, %2
1105     pmulhw    %3, m6 ;20091(1)
1106     pmulhw    %4, m6 ;20091(2)
1107     paddw     %3, %1
1108     paddw     %4, %2
1109     paddw     %1, %1
1110     paddw     %2, %2
1111     pmulhw    %1, m7 ;35468(1)
1112     pmulhw    %2, m7 ;35468(2)
1113     psubw     %1, %4
1114     paddw     %2, %3
1115 %endmacro
1116
1117 ; calculate x0=%1+%3; x1=%1-%3
1118 ;           x2=mul_35468(%2)-mul_20091(%4); x3=mul_20091(%2)+mul_35468(%4)
1119 ;           %1=x0+x3 (tmp0); %2=x1+x2 (tmp1); %3=x1-x2 (tmp2); %4=x0-x3 (tmp3)
1120 ;           %5/%6 are temporary registers
1121 ;           we assume m6/m7 have constant words 20091/17734 loaded in them
1122 %macro VP8_IDCT_TRANSFORM4x4_1D 6
1123     SUMSUB_BA         w, %3,  %1,  %5     ;t0, t1
1124     VP8_MULTIPLY_SUMSUB m%2, m%4, m%5,m%6 ;t2, t3
1125     SUMSUB_BA         w, %4,  %3,  %5     ;tmp0, tmp3
1126     SUMSUB_BA         w, %2,  %1,  %5     ;tmp1, tmp2
1127     SWAP                 %4,  %1
1128     SWAP                 %4,  %3
1129 %endmacro
1130
1131 %macro VP8_IDCT_ADD 0
1132 cglobal vp8_idct_add, 3, 3, 0, dst, block, stride
1133     ; load block data
1134     movq         m0, [blockq+ 0]
1135     movq         m1, [blockq+ 8]
1136     movq         m2, [blockq+16]
1137     movq         m3, [blockq+24]
1138     movq         m6, [pw_20091]
1139     movq         m7, [pw_17734]
1140 %if cpuflag(sse)
1141     xorps      xmm0, xmm0
1142     movaps [blockq+ 0], xmm0
1143     movaps [blockq+16], xmm0
1144 %else
1145     pxor         m4, m4
1146     movq [blockq+ 0], m4
1147     movq [blockq+ 8], m4
1148     movq [blockq+16], m4
1149     movq [blockq+24], m4
1150 %endif
1151
1152     ; actual IDCT
1153     VP8_IDCT_TRANSFORM4x4_1D 0, 1, 2, 3, 4, 5
1154     TRANSPOSE4x4W            0, 1, 2, 3, 4
1155     paddw        m0, [pw_4]
1156     VP8_IDCT_TRANSFORM4x4_1D 0, 1, 2, 3, 4, 5
1157     TRANSPOSE4x4W            0, 1, 2, 3, 4
1158
1159     ; store
1160     pxor         m4, m4
1161     DEFINE_ARGS dst1, dst2, stride
1162     lea       dst2q, [dst1q+2*strideq]
1163     STORE_DIFFx2 m0, m1, m6, m7, m4, 3, dst1q, strideq
1164     STORE_DIFFx2 m2, m3, m6, m7, m4, 3, dst2q, strideq
1165
1166     RET
1167 %endmacro
1168
1169 %if ARCH_X86_32
1170 INIT_MMX mmx
1171 VP8_IDCT_ADD
1172 %endif
1173 INIT_MMX sse
1174 VP8_IDCT_ADD
1175
1176 ;-----------------------------------------------------------------------------
1177 ; void ff_vp8_luma_dc_wht(int16_t block[4][4][16], int16_t dc[16])
1178 ;-----------------------------------------------------------------------------
1179
1180 %macro SCATTER_WHT 3
1181     movd dc1d, m%1
1182     movd dc2d, m%2
1183     mov [blockq+2*16*(0+%3)], dc1w
1184     mov [blockq+2*16*(1+%3)], dc2w
1185     shr  dc1d, 16
1186     shr  dc2d, 16
1187     psrlq m%1, 32
1188     psrlq m%2, 32
1189     mov [blockq+2*16*(4+%3)], dc1w
1190     mov [blockq+2*16*(5+%3)], dc2w
1191     movd dc1d, m%1
1192     movd dc2d, m%2
1193     mov [blockq+2*16*(8+%3)], dc1w
1194     mov [blockq+2*16*(9+%3)], dc2w
1195     shr  dc1d, 16
1196     shr  dc2d, 16
1197     mov [blockq+2*16*(12+%3)], dc1w
1198     mov [blockq+2*16*(13+%3)], dc2w
1199 %endmacro
1200
1201 %macro HADAMARD4_1D 4
1202     SUMSUB_BADC w, %2, %1, %4, %3
1203     SUMSUB_BADC w, %4, %2, %3, %1
1204     SWAP %1, %4, %3
1205 %endmacro
1206
1207 %macro VP8_DC_WHT 0
1208 cglobal vp8_luma_dc_wht, 2, 3, 0, block, dc1, dc2
1209     movq          m0, [dc1q]
1210     movq          m1, [dc1q+8]
1211     movq          m2, [dc1q+16]
1212     movq          m3, [dc1q+24]
1213 %if cpuflag(sse)
1214     xorps      xmm0, xmm0
1215     movaps [dc1q+ 0], xmm0
1216     movaps [dc1q+16], xmm0
1217 %else
1218     pxor         m4, m4
1219     movq  [dc1q+ 0], m4
1220     movq  [dc1q+ 8], m4
1221     movq  [dc1q+16], m4
1222     movq  [dc1q+24], m4
1223 %endif
1224     HADAMARD4_1D  0, 1, 2, 3
1225     TRANSPOSE4x4W 0, 1, 2, 3, 4
1226     paddw         m0, [pw_3]
1227     HADAMARD4_1D  0, 1, 2, 3
1228     psraw         m0, 3
1229     psraw         m1, 3
1230     psraw         m2, 3
1231     psraw         m3, 3
1232     SCATTER_WHT   0, 1, 0
1233     SCATTER_WHT   2, 3, 2
1234     RET
1235 %endmacro
1236
1237 %if ARCH_X86_32
1238 INIT_MMX mmx
1239 VP8_DC_WHT
1240 %endif
1241 INIT_MMX sse
1242 VP8_DC_WHT