]> git.sesse.net Git - ffmpeg/blob - libavcodec/x86/vp8dsp.asm
e640fe31442c78f45eb5c1667a27131fcfa3e5e0
[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 ;* 51, Inc., Foundation Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
21 ;******************************************************************************
22
23 %include "x86inc.asm"
24 %include "x86util.asm"
25
26 SECTION_RODATA
27
28 fourtap_filter_hw_m: times 4 dw  -6, 123
29                      times 4 dw  12,  -1
30                      times 4 dw  -9,  93
31                      times 4 dw  50,  -6
32                      times 4 dw  -6,  50
33                      times 4 dw  93,  -9
34                      times 4 dw  -1,  12
35                      times 4 dw 123,  -6
36
37 sixtap_filter_hw_m:  times 4 dw   2, -11
38                      times 4 dw 108,  36
39                      times 4 dw  -8,   1
40                      times 4 dw   3, -16
41                      times 4 dw  77,  77
42                      times 4 dw -16,   3
43                      times 4 dw   1,  -8
44                      times 4 dw  36, 108
45                      times 4 dw -11,   2
46
47 fourtap_filter_hb_m: times 8 db  -6, 123
48                      times 8 db  12,  -1
49                      times 8 db  -9,  93
50                      times 8 db  50,  -6
51                      times 8 db  -6,  50
52                      times 8 db  93,  -9
53                      times 8 db  -1,  12
54                      times 8 db 123,  -6
55
56 sixtap_filter_hb_m:  times 8 db   2,   1
57                      times 8 db -11, 108
58                      times 8 db  36,  -8
59                      times 8 db   3,   3
60                      times 8 db -16,  77
61                      times 8 db  77, -16
62                      times 8 db   1,   2
63                      times 8 db  -8,  36
64                      times 8 db 108, -11
65
66 fourtap_filter_v_m:  times 8 dw  -6
67                      times 8 dw 123
68                      times 8 dw  12
69                      times 8 dw  -1
70                      times 8 dw  -9
71                      times 8 dw  93
72                      times 8 dw  50
73                      times 8 dw  -6
74                      times 8 dw  -6
75                      times 8 dw  50
76                      times 8 dw  93
77                      times 8 dw  -9
78                      times 8 dw  -1
79                      times 8 dw  12
80                      times 8 dw 123
81                      times 8 dw  -6
82
83 sixtap_filter_v_m:   times 8 dw   2
84                      times 8 dw -11
85                      times 8 dw 108
86                      times 8 dw  36
87                      times 8 dw  -8
88                      times 8 dw   1
89                      times 8 dw   3
90                      times 8 dw -16
91                      times 8 dw  77
92                      times 8 dw  77
93                      times 8 dw -16
94                      times 8 dw   3
95                      times 8 dw   1
96                      times 8 dw  -8
97                      times 8 dw  36
98                      times 8 dw 108
99                      times 8 dw -11
100                      times 8 dw   2
101
102 bilinear_filter_vw_m: times 8 dw 1
103                       times 8 dw 2
104                       times 8 dw 3
105                       times 8 dw 4
106                       times 8 dw 5
107                       times 8 dw 6
108                       times 8 dw 7
109
110 bilinear_filter_vb_m: times 8 db 7, 1
111                       times 8 db 6, 2
112                       times 8 db 5, 3
113                       times 8 db 4, 4
114                       times 8 db 3, 5
115                       times 8 db 2, 6
116                       times 8 db 1, 7
117
118 %ifdef PIC
119 %define fourtap_filter_hw    r11
120 %define sixtap_filter_hw     r11
121 %define fourtap_filter_hb    r11
122 %define sixtap_filter_hb     r11
123 %define fourtap_filter_v     r11
124 %define sixtap_filter_v      r11
125 %define bilinear_filter_vw   r11
126 %define bilinear_filter_vb   r11
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 %endif
137
138 filter_h2_shuf:  db 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5,  6, 6,  7,  7,  8
139 filter_h4_shuf:  db 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7,  8, 8,  9,  9, 10
140
141 filter_h6_shuf1: db 0, 5, 1, 6, 2, 7, 3, 8, 4, 9, 5, 10, 6, 11,  7, 12
142 filter_h6_shuf2: db 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6,  7, 7,  8,  8,  9
143 filter_h6_shuf3: db 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 8,  9, 9, 10, 10, 11
144
145 pw_20091: times 4 dw 20091
146 pw_17734: times 4 dw 17734
147
148 cextern pb_1
149 cextern pw_3
150 cextern pb_3
151 cextern pw_4
152 cextern pb_4
153 cextern pw_64
154 cextern pb_80
155 cextern pb_F8
156 cextern pb_FE
157
158 SECTION .text
159
160 ;-----------------------------------------------------------------------------
161 ; subpel MC functions:
162 ;
163 ; void put_vp8_epel<size>_h<htap>v<vtap>_<opt>(uint8_t *dst, int deststride,
164 ;                                              uint8_t *src, int srcstride,
165 ;                                              int height,   int mx, int my);
166 ;-----------------------------------------------------------------------------
167
168 %macro FILTER_SSSE3 3
169 cglobal put_vp8_epel%1_h6_ssse3, 6, 6, %2
170     lea      r5d, [r5*3]
171     mova      m3, [filter_h6_shuf2]
172     mova      m4, [filter_h6_shuf3]
173 %ifdef PIC
174     lea      r11, [sixtap_filter_hb_m]
175 %endif
176     mova      m5, [sixtap_filter_hb+r5*8-48] ; set up 6tap filter in bytes
177     mova      m6, [sixtap_filter_hb+r5*8-32]
178     mova      m7, [sixtap_filter_hb+r5*8-16]
179
180 .nextrow
181     movu      m0, [r2-2]
182     mova      m1, m0
183     mova      m2, m0
184 %ifidn %1, 4
185 ; For epel4, we need 9 bytes, but only 8 get loaded; to compensate, do the
186 ; shuffle with a memory operand
187     punpcklbw m0, [r2+3]
188 %else
189     pshufb    m0, [filter_h6_shuf1]
190 %endif
191     pshufb    m1, m3
192     pshufb    m2, m4
193     pmaddubsw m0, m5
194     pmaddubsw m1, m6
195     pmaddubsw m2, m7
196     paddsw    m0, m1
197     paddsw    m0, m2
198     paddsw    m0, [pw_64]
199     psraw     m0, 7
200     packuswb  m0, m0
201     movh    [r0], m0        ; store
202
203     ; go to next line
204     add       r0, r1
205     add       r2, r3
206     dec       r4            ; next row
207     jg .nextrow
208     REP_RET
209
210 cglobal put_vp8_epel%1_h4_ssse3, 6, 6, %3
211     shl      r5d, 4
212     mova      m2, [pw_64]
213     mova      m3, [filter_h2_shuf]
214     mova      m4, [filter_h4_shuf]
215 %ifdef PIC
216     lea      r11, [fourtap_filter_hb_m]
217 %endif
218     mova      m5, [fourtap_filter_hb+r5-16] ; set up 4tap filter in bytes
219     mova      m6, [fourtap_filter_hb+r5]
220
221 .nextrow
222     movu      m0, [r2-1]
223     mova      m1, m0
224     pshufb    m0, m3
225     pshufb    m1, m4
226     pmaddubsw m0, m5
227     pmaddubsw m1, m6
228     paddsw    m0, m2
229     paddsw    m0, m1
230     psraw     m0, 7
231     packuswb  m0, m0
232     movh    [r0], m0        ; store
233
234     ; go to next line
235     add       r0, r1
236     add       r2, r3
237     dec       r4            ; next row
238     jg .nextrow
239     REP_RET
240
241 cglobal put_vp8_epel%1_v4_ssse3, 7, 7, %2
242     shl      r6d, 4
243 %ifdef PIC
244     lea      r11, [fourtap_filter_hb_m]
245 %endif
246     mova      m5, [fourtap_filter_hb+r6-16]
247     mova      m6, [fourtap_filter_hb+r6]
248     mova      m7, [pw_64]
249
250     ; read 3 lines
251     sub       r2, r3
252     movh      m0, [r2]
253     movh      m1, [r2+  r3]
254     movh      m2, [r2+2*r3]
255     add       r2, r3
256
257 .nextrow
258     movh      m3, [r2+2*r3]                ; read new row
259     mova      m4, m0
260     mova      m0, m1
261     punpcklbw m4, m1
262     mova      m1, m2
263     punpcklbw m2, m3
264     pmaddubsw m4, m5
265     pmaddubsw m2, m6
266     paddsw    m4, m2
267     mova      m2, m3
268     paddsw    m4, m7
269     psraw     m4, 7
270     packuswb  m4, m4
271     movh    [r0], m4
272
273     ; go to next line
274     add        r0, r1
275     add        r2, r3
276     dec        r4                          ; next row
277     jg .nextrow
278     REP_RET
279
280 cglobal put_vp8_epel%1_v6_ssse3, 7, 7, %2
281     lea      r6d, [r6*3]
282 %ifdef PIC
283     lea      r11, [sixtap_filter_hb_m]
284 %endif
285     lea       r6, [sixtap_filter_hb+r6*8]
286
287     ; read 5 lines
288     sub       r2, r3
289     sub       r2, r3
290     movh      m0, [r2]
291     movh      m1, [r2+r3]
292     movh      m2, [r2+r3*2]
293     lea       r2, [r2+r3*2]
294     add       r2, r3
295     movh      m3, [r2]
296     movh      m4, [r2+r3]
297
298 .nextrow
299     movh      m5, [r2+2*r3]                ; read new row
300     mova      m6, m0
301     punpcklbw m6, m5
302     mova      m0, m1
303     punpcklbw m1, m2
304     mova      m7, m3
305     punpcklbw m7, m4
306     pmaddubsw m6, [r6-48]
307     pmaddubsw m1, [r6-32]
308     pmaddubsw m7, [r6-16]
309     paddsw    m6, m1
310     paddsw    m6, m7
311     mova      m1, m2
312     paddsw    m6, [pw_64]
313     mova      m2, m3
314     psraw     m6, 7
315     mova      m3, m4
316     packuswb  m6, m6
317     mova      m4, m5
318     movh    [r0], m6
319
320     ; go to next line
321     add        r0, r1
322     add        r2, r3
323     dec        r4                          ; next row
324     jg .nextrow
325     REP_RET
326 %endmacro
327
328 INIT_MMX
329 FILTER_SSSE3 4, 0, 0
330 INIT_XMM
331 FILTER_SSSE3 8, 8, 7
332
333 ; 4x4 block, H-only 4-tap filter
334 cglobal put_vp8_epel4_h4_mmxext, 6, 6
335     shl       r5d, 4
336 %ifdef PIC
337     lea       r11, [fourtap_filter_hw_m]
338 %endif
339     movq      mm4, [fourtap_filter_hw+r5-16] ; set up 4tap filter in words
340     movq      mm5, [fourtap_filter_hw+r5]
341     movq      mm7, [pw_64]
342     pxor      mm6, mm6
343
344 .nextrow
345     movq      mm1, [r2-1]                  ; (ABCDEFGH) load 8 horizontal pixels
346
347     ; first set of 2 pixels
348     movq      mm2, mm1                     ; byte ABCD..
349     punpcklbw mm1, mm6                     ; byte->word ABCD
350     pshufw    mm0, mm2, 9                  ; byte CDEF..
351     punpcklbw mm0, mm6                     ; byte->word CDEF
352     pshufw    mm3, mm1, 0x94               ; word ABBC
353     pshufw    mm1, mm0, 0x94               ; word CDDE
354     pmaddwd   mm3, mm4                     ; multiply 2px with F0/F1
355     movq      mm0, mm1                     ; backup for second set of pixels
356     pmaddwd   mm1, mm5                     ; multiply 2px with F2/F3
357     paddd     mm3, mm1                     ; finish 1st 2px
358
359     ; second set of 2 pixels, use backup of above
360     punpckhbw mm2, mm6                     ; byte->word EFGH
361     pmaddwd   mm0, mm4                     ; multiply backed up 2px with F0/F1
362     pshufw    mm1, mm2, 0x94               ; word EFFG
363     pmaddwd   mm1, mm5                     ; multiply 2px with F2/F3
364     paddd     mm0, mm1                     ; finish 2nd 2px
365
366     ; merge two sets of 2 pixels into one set of 4, round/clip/store
367     packssdw  mm3, mm0                     ; merge dword->word (4px)
368     paddsw    mm3, mm7                     ; rounding
369     psraw     mm3, 7
370     packuswb  mm3, mm6                     ; clip and word->bytes
371     movd     [r0], mm3                     ; store
372
373     ; go to next line
374     add        r0, r1
375     add        r2, r3
376     dec        r4                          ; next row
377     jg .nextrow
378     REP_RET
379
380 ; 4x4 block, H-only 6-tap filter
381 cglobal put_vp8_epel4_h6_mmxext, 6, 6
382     lea       r5d, [r5*3]
383 %ifdef PIC
384     lea       r11, [sixtap_filter_hw_m]
385 %endif
386     movq      mm4, [sixtap_filter_hw+r5*8-48] ; set up 4tap filter in words
387     movq      mm5, [sixtap_filter_hw+r5*8-32]
388     movq      mm6, [sixtap_filter_hw+r5*8-16]
389     movq      mm7, [pw_64]
390     pxor      mm3, mm3
391
392 .nextrow
393     movq      mm1, [r2-2]                  ; (ABCDEFGH) load 8 horizontal pixels
394
395     ; first set of 2 pixels
396     movq      mm2, mm1                     ; byte ABCD..
397     punpcklbw mm1, mm3                     ; byte->word ABCD
398     pshufw    mm0, mm2, 0x9                ; byte CDEF..
399     punpckhbw mm2, mm3                     ; byte->word EFGH
400     punpcklbw mm0, mm3                     ; byte->word CDEF
401     pshufw    mm1, mm1, 0x94               ; word ABBC
402     pshufw    mm2, mm2, 0x94               ; word EFFG
403     pmaddwd   mm1, mm4                     ; multiply 2px with F0/F1
404     pshufw    mm3, mm0, 0x94               ; word CDDE
405     movq      mm0, mm3                     ; backup for second set of pixels
406     pmaddwd   mm3, mm5                     ; multiply 2px with F2/F3
407     paddd     mm1, mm3                     ; add to 1st 2px cache
408     movq      mm3, mm2                     ; backup for second set of pixels
409     pmaddwd   mm2, mm6                     ; multiply 2px with F4/F5
410     paddd     mm1, mm2                     ; finish 1st 2px
411
412     ; second set of 2 pixels, use backup of above
413     movd      mm2, [r2+3]                  ; byte FGHI (prevent overreads)
414     pmaddwd   mm0, mm4                     ; multiply 1st backed up 2px with F0/F1
415     pmaddwd   mm3, mm5                     ; multiply 2nd backed up 2px with F2/F3
416     paddd     mm0, mm3                     ; add to 2nd 2px cache
417     pxor      mm3, mm3
418     punpcklbw mm2, mm3                     ; byte->word FGHI
419     pshufw    mm2, mm2, 0xE9               ; word GHHI
420     pmaddwd   mm2, mm6                     ; multiply 2px with F4/F5
421     paddd     mm0, mm2                     ; finish 2nd 2px
422
423     ; merge two sets of 2 pixels into one set of 4, round/clip/store
424     packssdw  mm1, mm0                     ; merge dword->word (4px)
425     paddsw    mm1, mm7                     ; rounding
426     psraw     mm1, 7
427     packuswb  mm1, mm3                     ; clip and word->bytes
428     movd     [r0], mm1                     ; store
429
430     ; go to next line
431     add        r0, r1
432     add        r2, r3
433     dec        r4                          ; next row
434     jg .nextrow
435     REP_RET
436
437 ; 4x4 block, H-only 4-tap filter
438 INIT_XMM
439 cglobal put_vp8_epel8_h4_sse2, 6, 6, 8
440     shl      r5d, 4
441 %ifdef PIC
442     lea      r11, [fourtap_filter_hw_m]
443 %endif
444     mova      m5, [fourtap_filter_hw+r5-16] ; set up 4tap filter in words
445     mova      m6, [fourtap_filter_hw+r5]
446     pxor      m7, m7
447
448 .nextrow
449     movh      m0, [r2-1]
450     punpcklbw m0, m7        ; ABCDEFGH
451     mova      m1, m0
452     mova      m2, m0
453     mova      m3, m0
454     psrldq    m1, 2         ; BCDEFGH
455     psrldq    m2, 4         ; CDEFGH
456     psrldq    m3, 6         ; DEFGH
457     punpcklwd m0, m1        ; ABBCCDDE
458     punpcklwd m2, m3        ; CDDEEFFG
459     pmaddwd   m0, m5
460     pmaddwd   m2, m6
461     paddd     m0, m2
462
463     movh      m1, [r2+3]
464     punpcklbw m1, m7        ; ABCDEFGH
465     mova      m2, m1
466     mova      m3, m1
467     mova      m4, m1
468     psrldq    m2, 2         ; BCDEFGH
469     psrldq    m3, 4         ; CDEFGH
470     psrldq    m4, 6         ; DEFGH
471     punpcklwd m1, m2        ; ABBCCDDE
472     punpcklwd m3, m4        ; CDDEEFFG
473     pmaddwd   m1, m5
474     pmaddwd   m3, m6
475     paddd     m1, m3
476
477     packssdw  m0, m1
478     paddsw    m0, [pw_64]
479     psraw     m0, 7
480     packuswb  m0, m7
481     movh    [r0], m0        ; store
482
483     ; go to next line
484     add       r0, r1
485     add       r2, r3
486     dec       r4            ; next row
487     jg .nextrow
488     REP_RET
489
490 cglobal put_vp8_epel8_h6_sse2, 6, 6, 8
491     lea      r5d, [r5*3]
492 %ifdef PIC
493     lea      r11, [sixtap_filter_hw_m]
494 %endif
495     lea       r5, [sixtap_filter_hw+r5*8]
496     pxor      m7, m7
497
498 .nextrow
499     movu      m0, [r2-2]
500     mova      m6, m0
501     mova      m4, m0
502     punpcklbw m0, m7        ; ABCDEFGHI
503     mova      m1, m0
504     mova      m2, m0
505     mova      m3, m0
506     psrldq    m1, 2         ; BCDEFGH
507     psrldq    m2, 4         ; CDEFGH
508     psrldq    m3, 6         ; DEFGH
509     psrldq    m4, 4
510     punpcklbw m4, m7        ; EFGH
511     mova      m5, m4
512     psrldq    m5, 2         ; FGH
513     punpcklwd m0, m1        ; ABBCCDDE
514     punpcklwd m2, m3        ; CDDEEFFG
515     punpcklwd m4, m5        ; EFFGGHHI
516     pmaddwd   m0, [r5-48]
517     pmaddwd   m2, [r5-32]
518     pmaddwd   m4, [r5-16]
519     paddd     m0, m2
520     paddd     m0, m4
521
522     psrldq    m6, 4
523     mova      m4, m6
524     punpcklbw m6, m7        ; ABCDEFGHI
525     mova      m1, m6
526     mova      m2, m6
527     mova      m3, m6
528     psrldq    m1, 2         ; BCDEFGH
529     psrldq    m2, 4         ; CDEFGH
530     psrldq    m3, 6         ; DEFGH
531     psrldq    m4, 4
532     punpcklbw m4, m7        ; EFGH
533     mova      m5, m4
534     psrldq    m5, 2         ; FGH
535     punpcklwd m6, m1        ; ABBCCDDE
536     punpcklwd m2, m3        ; CDDEEFFG
537     punpcklwd m4, m5        ; EFFGGHHI
538     pmaddwd   m6, [r5-48]
539     pmaddwd   m2, [r5-32]
540     pmaddwd   m4, [r5-16]
541     paddd     m6, m2
542     paddd     m6, m4
543
544     packssdw  m0, m6
545     paddsw    m0, [pw_64]
546     psraw     m0, 7
547     packuswb  m0, m7
548     movh    [r0], m0        ; store
549
550     ; go to next line
551     add       r0, r1
552     add       r2, r3
553     dec       r4            ; next row
554     jg .nextrow
555     REP_RET
556
557 %macro FILTER_V 3
558 ; 4x4 block, V-only 4-tap filter
559 cglobal put_vp8_epel%2_v4_%1, 7, 7, %3
560     shl      r6d, 5
561 %ifdef PIC
562     lea      r11, [fourtap_filter_v_m]
563 %endif
564     lea       r6, [fourtap_filter_v+r6-32]
565     mova      m6, [pw_64]
566     pxor      m7, m7
567     mova      m5, [r6+48]
568
569     ; read 3 lines
570     sub       r2, r3
571     movh      m0, [r2]
572     movh      m1, [r2+  r3]
573     movh      m2, [r2+2*r3]
574     add       r2, r3
575     punpcklbw m0, m7
576     punpcklbw m1, m7
577     punpcklbw m2, m7
578
579 .nextrow
580     ; first calculate negative taps (to prevent losing positive overflows)
581     movh      m4, [r2+2*r3]                ; read new row
582     punpcklbw m4, m7
583     mova      m3, m4
584     pmullw    m0, [r6+0]
585     pmullw    m4, m5
586     paddsw    m4, m0
587
588     ; then calculate positive taps
589     mova      m0, m1
590     pmullw    m1, [r6+16]
591     paddsw    m4, m1
592     mova      m1, m2
593     pmullw    m2, [r6+32]
594     paddsw    m4, m2
595     mova      m2, m3
596
597     ; round/clip/store
598     paddsw    m4, m6
599     psraw     m4, 7
600     packuswb  m4, m7
601     movh    [r0], m4
602
603     ; go to next line
604     add       r0, r1
605     add       r2, r3
606     dec       r4                           ; next row
607     jg .nextrow
608     REP_RET
609
610
611 ; 4x4 block, V-only 6-tap filter
612 cglobal put_vp8_epel%2_v6_%1, 7, 7, %3
613     shl      r6d, 4
614     lea       r6, [r6*3]
615 %ifdef PIC
616     lea      r11, [sixtap_filter_v_m]
617 %endif
618     lea       r6, [sixtap_filter_v+r6-96]
619     pxor      m7, m7
620
621     ; read 5 lines
622     sub       r2, r3
623     sub       r2, r3
624     movh      m0, [r2]
625     movh      m1, [r2+r3]
626     movh      m2, [r2+r3*2]
627     lea       r2, [r2+r3*2]
628     add       r2, r3
629     movh      m3, [r2]
630     movh      m4, [r2+r3]
631     punpcklbw m0, m7
632     punpcklbw m1, m7
633     punpcklbw m2, m7
634     punpcklbw m3, m7
635     punpcklbw m4, m7
636
637 .nextrow
638     ; first calculate negative taps (to prevent losing positive overflows)
639     mova      m5, m1
640     pmullw    m5, [r6+16]
641     mova      m6, m4
642     pmullw    m6, [r6+64]
643     paddsw    m6, m5
644
645     ; then calculate positive taps
646     movh      m5, [r2+2*r3]                ; read new row
647     punpcklbw m5, m7
648     pmullw    m0, [r6+0]
649     paddsw    m6, m0
650     mova      m0, m1
651     mova      m1, m2
652     pmullw    m2, [r6+32]
653     paddsw    m6, m2
654     mova      m2, m3
655     pmullw    m3, [r6+48]
656     paddsw    m6, m3
657     mova      m3, m4
658     mova      m4, m5
659     pmullw    m5, [r6+80]
660     paddsw    m6, m5
661
662     ; round/clip/store
663     paddsw    m6, [pw_64]
664     psraw     m6, 7
665     packuswb  m6, m7
666     movh    [r0], m6
667
668     ; go to next line
669     add       r0, r1
670     add       r2, r3
671     dec       r4                           ; next row
672     jg .nextrow
673     REP_RET
674 %endmacro
675
676 INIT_MMX
677 FILTER_V mmxext, 4, 0
678 INIT_XMM
679 FILTER_V sse2,   8, 8
680
681 %macro FILTER_BILINEAR 3
682 cglobal put_vp8_bilinear%2_v_%1, 7,7,%3
683     mov      r5d, 8*16
684     shl      r6d, 4
685     sub      r5d, r6d
686 %ifdef PIC
687     lea      r11, [bilinear_filter_vw_m]
688 %endif
689     pxor      m6, m6
690     mova      m4, [bilinear_filter_vw+r5-16]
691     mova      m5, [bilinear_filter_vw+r6-16]
692 .nextrow
693     movh      m0, [r2+r3*0]
694     movh      m1, [r2+r3*1]
695     movh      m3, [r2+r3*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 %ifidn %1, mmxext
711     packuswb  m0, m0
712     packuswb  m2, m2
713     movh [r0+r1*0], m0
714     movh [r0+r1*1], m2
715 %else
716     packuswb  m0, m2
717     movh   [r0+r1*0], m0
718     movhps [r0+r1*1], m0
719 %endif
720
721     lea       r0, [r0+r1*2]
722     lea       r2, [r2+r3*2]
723     sub       r4, 2
724     jg .nextrow
725     REP_RET
726
727 cglobal put_vp8_bilinear%2_h_%1, 7,7,%3
728     mov      r6d, 8*16
729     shl      r5d, 4
730     sub      r6d, r5d
731 %ifdef PIC
732     lea      r11, [bilinear_filter_vw_m]
733 %endif
734     pxor      m6, m6
735     mova      m4, [bilinear_filter_vw+r6-16]
736     mova      m5, [bilinear_filter_vw+r5-16]
737 .nextrow
738     movh      m0, [r2+r3*0+0]
739     movh      m1, [r2+r3*0+1]
740     movh      m2, [r2+r3*1+0]
741     movh      m3, [r2+r3*1+1]
742     punpcklbw m0, m6
743     punpcklbw m1, m6
744     punpcklbw m2, m6
745     punpcklbw m3, m6
746     pmullw    m0, m4
747     pmullw    m1, m5
748     pmullw    m2, m4
749     pmullw    m3, m5
750     paddsw    m0, m1
751     paddsw    m2, m3
752     psraw     m0, 2
753     psraw     m2, 2
754     pavgw     m0, m6
755     pavgw     m2, m6
756 %ifidn %1, mmxext
757     packuswb  m0, m0
758     packuswb  m2, m2
759     movh [r0+r1*0], m0
760     movh [r0+r1*1], m2
761 %else
762     packuswb  m0, m2
763     movh   [r0+r1*0], m0
764     movhps [r0+r1*1], m0
765 %endif
766
767     lea       r0, [r0+r1*2]
768     lea       r2, [r2+r3*2]
769     sub       r4, 2
770     jg .nextrow
771     REP_RET
772 %endmacro
773
774 INIT_MMX
775 FILTER_BILINEAR mmxext, 4, 0
776 INIT_XMM
777 FILTER_BILINEAR   sse2, 8, 7
778
779 %macro FILTER_BILINEAR_SSSE3 1
780 cglobal put_vp8_bilinear%1_v_ssse3, 7,7
781     shl      r6d, 4
782 %ifdef PIC
783     lea      r11, [bilinear_filter_vb_m]
784 %endif
785     pxor      m4, m4
786     mova      m3, [bilinear_filter_vb+r6-16]
787 .nextrow
788     movh      m0, [r2+r3*0]
789     movh      m1, [r2+r3*1]
790     movh      m2, [r2+r3*2]
791     punpcklbw m0, m1
792     punpcklbw m1, m2
793     pmaddubsw m0, m3
794     pmaddubsw m1, m3
795     psraw     m0, 2
796     psraw     m1, 2
797     pavgw     m0, m4
798     pavgw     m1, m4
799 %if mmsize==8
800     packuswb  m0, m0
801     packuswb  m1, m1
802     movh [r0+r1*0], m0
803     movh [r0+r1*1], m1
804 %else
805     packuswb  m0, m1
806     movh   [r0+r1*0], m0
807     movhps [r0+r1*1], m0
808 %endif
809
810     lea       r0, [r0+r1*2]
811     lea       r2, [r2+r3*2]
812     sub       r4, 2
813     jg .nextrow
814     REP_RET
815
816 cglobal put_vp8_bilinear%1_h_ssse3, 7,7
817     shl      r5d, 4
818 %ifdef PIC
819     lea      r11, [bilinear_filter_vb_m]
820 %endif
821     pxor      m4, m4
822     mova      m2, [filter_h2_shuf]
823     mova      m3, [bilinear_filter_vb+r5-16]
824 .nextrow
825     movu      m0, [r2+r3*0]
826     movu      m1, [r2+r3*1]
827     pshufb    m0, m2
828     pshufb    m1, m2
829     pmaddubsw m0, m3
830     pmaddubsw m1, m3
831     psraw     m0, 2
832     psraw     m1, 2
833     pavgw     m0, m4
834     pavgw     m1, m4
835 %if mmsize==8
836     packuswb  m0, m0
837     packuswb  m1, m1
838     movh [r0+r1*0], m0
839     movh [r0+r1*1], m1
840 %else
841     packuswb  m0, m1
842     movh   [r0+r1*0], m0
843     movhps [r0+r1*1], m0
844 %endif
845
846     lea       r0, [r0+r1*2]
847     lea       r2, [r2+r3*2]
848     sub       r4, 2
849     jg .nextrow
850     REP_RET
851 %endmacro
852
853 INIT_MMX
854 FILTER_BILINEAR_SSSE3 4
855 INIT_XMM
856 FILTER_BILINEAR_SSSE3 8
857
858 cglobal put_vp8_pixels8_mmx, 5,5
859 .nextrow:
860     movq  mm0, [r2+r3*0]
861     movq  mm1, [r2+r3*1]
862     lea    r2, [r2+r3*2]
863     movq [r0+r1*0], mm0
864     movq [r0+r1*1], mm1
865     lea    r0, [r0+r1*2]
866     sub   r4d, 2
867     jg .nextrow
868     REP_RET
869
870 cglobal put_vp8_pixels16_mmx, 5,5
871 .nextrow:
872     movq  mm0, [r2+r3*0+0]
873     movq  mm1, [r2+r3*0+8]
874     movq  mm2, [r2+r3*1+0]
875     movq  mm3, [r2+r3*1+8]
876     lea    r2, [r2+r3*2]
877     movq [r0+r1*0+0], mm0
878     movq [r0+r1*0+8], mm1
879     movq [r0+r1*1+0], mm2
880     movq [r0+r1*1+8], mm3
881     lea    r0, [r0+r1*2]
882     sub   r4d, 2
883     jg .nextrow
884     REP_RET
885
886 cglobal put_vp8_pixels16_sse, 5,5,2
887 .nextrow:
888     movups xmm0, [r2+r3*0]
889     movups xmm1, [r2+r3*1]
890     lea     r2, [r2+r3*2]
891     movaps [r0+r1*0], xmm0
892     movaps [r0+r1*1], xmm1
893     lea     r0, [r0+r1*2]
894     sub    r4d, 2
895     jg .nextrow
896     REP_RET
897
898 ;-----------------------------------------------------------------------------
899 ; IDCT functions:
900 ;
901 ; void vp8_idct_dc_add_<opt>(uint8_t *dst, DCTELEM block[16], int stride);
902 ;-----------------------------------------------------------------------------
903
904 cglobal vp8_idct_dc_add_mmx, 3, 3
905     ; load data
906     movd       mm0, [r1]
907
908     ; calculate DC
909     paddw      mm0, [pw_4]
910     pxor       mm1, mm1
911     psraw      mm0, 3
912     psubw      mm1, mm0
913     packuswb   mm0, mm0
914     packuswb   mm1, mm1
915     punpcklbw  mm0, mm0
916     punpcklbw  mm1, mm1
917     punpcklwd  mm0, mm0
918     punpcklwd  mm1, mm1
919
920     ; add DC
921     lea         r1, [r0+r2*2]
922     movd       mm2, [r0]
923     movd       mm3, [r0+r2]
924     movd       mm4, [r1]
925     movd       mm5, [r1+r2]
926     paddusb    mm2, mm0
927     paddusb    mm3, mm0
928     paddusb    mm4, mm0
929     paddusb    mm5, mm0
930     psubusb    mm2, mm1
931     psubusb    mm3, mm1
932     psubusb    mm4, mm1
933     psubusb    mm5, mm1
934     movd      [r0], mm2
935     movd   [r0+r2], mm3
936     movd      [r1], mm4
937     movd   [r1+r2], mm5
938     RET
939
940 cglobal vp8_idct_dc_add_sse4, 3, 3, 6
941     ; load data
942     movd       xmm0, [r1]
943     lea          r1, [r0+r2*2]
944     pxor       xmm1, xmm1
945     movq       xmm2, [pw_4]
946
947     ; calculate DC
948     paddw      xmm0, xmm2
949     movd       xmm2, [r0]
950     movd       xmm3, [r0+r2]
951     movd       xmm4, [r1]
952     movd       xmm5, [r1+r2]
953     psraw      xmm0, 3
954     pshuflw    xmm0, xmm0, 0
955     punpcklqdq xmm0, xmm0
956     punpckldq  xmm2, xmm3
957     punpckldq  xmm4, xmm5
958     punpcklbw  xmm2, xmm1
959     punpcklbw  xmm4, xmm1
960     paddw      xmm2, xmm0
961     paddw      xmm4, xmm0
962     packuswb   xmm2, xmm4
963     movd       [r0], xmm2
964     pextrd  [r0+r2], xmm2, 1
965     pextrd     [r1], xmm2, 2
966     pextrd  [r1+r2], xmm2, 3
967     RET
968
969 ;-----------------------------------------------------------------------------
970 ; void vp8_idct_add_<opt>(uint8_t *dst, DCTELEM block[16], int stride);
971 ;-----------------------------------------------------------------------------
972
973 ; calculate %1=mul_35468(%1)-mul_20091(%2); %2=mul_20091(%1)+mul_35468(%2)
974 ;           this macro assumes that m6/m7 have words for 20091/17734 loaded
975 %macro VP8_MULTIPLY_SUMSUB 4
976     mova      %3, %1
977     mova      %4, %2
978     pmulhw    %3, m6 ;20091(1)
979     pmulhw    %4, m6 ;20091(2)
980     paddw     %3, %1
981     paddw     %4, %2
982     paddw     %1, %1
983     paddw     %2, %2
984     pmulhw    %1, m7 ;35468(1)
985     pmulhw    %2, m7 ;35468(2)
986     psubw     %1, %4
987     paddw     %2, %3
988 %endmacro
989
990 ; calculate x0=%1+%3; x1=%1-%3
991 ;           x2=mul_35468(%2)-mul_20091(%4); x3=mul_20091(%2)+mul_35468(%4)
992 ;           %1=x0+x3 (tmp0); %2=x1+x2 (tmp1); %3=x1-x2 (tmp2); %4=x0-x3 (tmp3)
993 ;           %5/%6 are temporary registers
994 ;           we assume m6/m7 have constant words 20091/17734 loaded in them
995 %macro VP8_IDCT_TRANSFORM4x4_1D 6
996     SUMSUB_BA           m%3, m%1, m%5     ;t0, t1
997     VP8_MULTIPLY_SUMSUB m%2, m%4, m%5,m%6 ;t2, t3
998     SUMSUB_BA           m%4, m%3, m%5     ;tmp0, tmp3
999     SUMSUB_BA           m%2, m%1, m%5     ;tmp1, tmp2
1000     SWAP                 %4,  %1
1001     SWAP                 %4,  %3
1002 %endmacro
1003
1004 INIT_MMX
1005 cglobal vp8_idct_add_mmx, 3, 3
1006     ; load block data
1007     movq         m0, [r1]
1008     movq         m1, [r1+8]
1009     movq         m2, [r1+16]
1010     movq         m3, [r1+24]
1011     movq         m6, [pw_20091]
1012     movq         m7, [pw_17734]
1013
1014     ; actual IDCT
1015     VP8_IDCT_TRANSFORM4x4_1D 0, 1, 2, 3, 4, 5
1016     TRANSPOSE4x4W            0, 1, 2, 3, 4
1017     paddw        m0, [pw_4]
1018     VP8_IDCT_TRANSFORM4x4_1D 0, 1, 2, 3, 4, 5
1019     TRANSPOSE4x4W            0, 1, 2, 3, 4
1020
1021     ; store
1022     pxor         m4, m4
1023     lea          r1, [r0+2*r2]
1024     STORE_DIFFx2 m0, m1, m6, m7, m4, 3, r0, r2
1025     STORE_DIFFx2 m2, m3, m6, m7, m4, 3, r1, r2
1026
1027     RET
1028
1029 ;-----------------------------------------------------------------------------
1030 ; void vp8_luma_dc_wht_mmxext(DCTELEM block[4][4][16], DCTELEM dc[16])
1031 ;-----------------------------------------------------------------------------
1032
1033 %macro SCATTER_WHT 1
1034     pextrw r1d, m0, %1
1035     pextrw r2d, m1, %1
1036     mov [r0+2*16*0], r1w
1037     mov [r0+2*16*1], r2w
1038     pextrw r1d, m2, %1
1039     pextrw r2d, m3, %1
1040     mov [r0+2*16*2], r1w
1041     mov [r0+2*16*3], r2w
1042 %endmacro
1043
1044 %macro HADAMARD4_1D 4
1045     SUMSUB_BADC m%2, m%1, m%4, m%3
1046     SUMSUB_BADC m%4, m%2, m%3, m%1
1047     SWAP %1, %4, %3
1048 %endmacro
1049
1050 INIT_MMX
1051 cglobal vp8_luma_dc_wht_mmxext, 2,3
1052     movq          m0, [r1]
1053     movq          m1, [r1+8]
1054     movq          m2, [r1+16]
1055     movq          m3, [r1+24]
1056     HADAMARD4_1D  0, 1, 2, 3
1057     TRANSPOSE4x4W 0, 1, 2, 3, 4
1058     paddw         m0, [pw_3]
1059     HADAMARD4_1D  0, 1, 2, 3
1060     psraw         m0, 3
1061     psraw         m1, 3
1062     psraw         m2, 3
1063     psraw         m3, 3
1064     SCATTER_WHT   0
1065     add           r0, 2*16*4
1066     SCATTER_WHT   1
1067     add           r0, 2*16*4
1068     SCATTER_WHT   2
1069     add           r0, 2*16*4
1070     SCATTER_WHT   3
1071     RET
1072
1073 ;-----------------------------------------------------------------------------
1074 ; void vp8_h/v_loop_filter_simple_<opt>(uint8_t *dst, int stride, int flim);
1075 ;-----------------------------------------------------------------------------
1076
1077 ; macro called with 7 mm register indexes as argument, and 4 regular registers
1078 ;
1079 ; first 4 mm registers will carry the transposed pixel data
1080 ; the other three are scratchspace (one would be sufficient, but this allows
1081 ; for more spreading/pipelining and thus faster execution on OOE CPUs)
1082 ;
1083 ; first two regular registers are buf+4*stride and buf+5*stride
1084 ; third is -stride, fourth is +stride
1085 %macro READ_8x4_INTERLEAVED 11
1086     ; interleave 8 (A-H) rows of 4 pixels each
1087     movd          m%1, [%8+%10*4]   ; A0-3
1088     movd          m%5, [%9+%10*4]   ; B0-3
1089     movd          m%2, [%8+%10*2]   ; C0-3
1090     movd          m%6, [%8+%10]     ; D0-3
1091     movd          m%3, [%8]         ; E0-3
1092     movd          m%7, [%9]         ; F0-3
1093     movd          m%4, [%9+%11]     ; G0-3
1094     punpcklbw     m%1, m%5          ; A/B interleaved
1095     movd          m%5, [%9+%11*2]   ; H0-3
1096     punpcklbw     m%2, m%6          ; C/D interleaved
1097     punpcklbw     m%3, m%7          ; E/F interleaved
1098     punpcklbw     m%4, m%5          ; G/H interleaved
1099 %endmacro
1100
1101 ; macro called with 7 mm register indexes as argument, and 5 regular registers
1102 ; first 11 mean the same as READ_8x4_TRANSPOSED above
1103 ; fifth regular register is scratchspace to reach the bottom 8 rows, it
1104 ; will be set to second regular register + 8*stride at the end
1105 %macro READ_16x4_INTERLEAVED 12
1106     ; transpose 16 (A-P) rows of 4 pixels each
1107     lea           %12, [r0+8*r2]
1108
1109     ; read (and interleave) those addressable by %8 (=r0), A/C/D/E/I/K/L/M
1110     movd          m%1, [%8+%10*4]   ; A0-3
1111     movd          m%3, [%12+%10*4]  ; I0-3
1112     movd          m%2, [%8+%10*2]   ; C0-3
1113     movd          m%4, [%12+%10*2]  ; K0-3
1114     movd          m%6, [%8+%10]     ; D0-3
1115     movd          m%5, [%12+%10]    ; L0-3
1116     movd          m%7, [%12]        ; M0-3
1117     add           %12, %11
1118     punpcklbw     m%1, m%3          ; A/I
1119     movd          m%3, [%8]         ; E0-3
1120     punpcklbw     m%2, m%4          ; C/K
1121     punpcklbw     m%6, m%5          ; D/L
1122     punpcklbw     m%3, m%7          ; E/M
1123     punpcklbw     m%2, m%6          ; C/D/K/L interleaved
1124
1125     ; read (and interleave) those addressable by %9 (=r4), B/F/G/H/J/N/O/P
1126     movd         m%5, [%9+%10*4]   ; B0-3
1127     movd         m%4, [%12+%10*4]  ; J0-3
1128     movd         m%7, [%9]         ; F0-3
1129     movd         m%6, [%12]        ; N0-3
1130     punpcklbw    m%5, m%4          ; B/J
1131     punpcklbw    m%7, m%6          ; F/N
1132     punpcklbw    m%1, m%5          ; A/B/I/J interleaved
1133     punpcklbw    m%3, m%7          ; E/F/M/N interleaved
1134     movd         m%4, [%9+%11]     ; G0-3
1135     movd         m%6, [%12+%11]    ; O0-3
1136     movd         m%5, [%9+%11*2]   ; H0-3
1137     movd         m%7, [%12+%11*2]  ; P0-3
1138     punpcklbw    m%4, m%6          ; G/O
1139     punpcklbw    m%5, m%7          ; H/P
1140     punpcklbw    m%4, m%5          ; G/H/O/P interleaved
1141 %endmacro
1142
1143 ; write 4 mm registers of 2 dwords each
1144 ; first four arguments are mm register indexes containing source data
1145 ; last four are registers containing buf+4*stride, buf+5*stride,
1146 ; -stride and +stride
1147 %macro WRITE_4x2D 8
1148     ; write out (2 dwords per register)
1149     movd    [%5+%7*4], m%1
1150     movd    [%5+%7*2], m%2
1151     movd         [%5], m%3
1152     movd      [%6+%8], m%4
1153     punpckhdq     m%1, m%1
1154     punpckhdq     m%2, m%2
1155     punpckhdq     m%3, m%3
1156     punpckhdq     m%4, m%4
1157     movd    [%6+%7*4], m%1
1158     movd      [%5+%7], m%2
1159     movd         [%6], m%3
1160     movd    [%6+%8*2], m%4
1161 %endmacro
1162
1163 ; write 4 xmm registers of 4 dwords each
1164 ; arguments same as WRITE_2x4D, but with an extra register, so that the 5 regular
1165 ; registers contain buf+4*stride, buf+5*stride, buf+12*stride, -stride and +stride
1166 ; we add 1*stride to the third regular registry in the process
1167 %macro WRITE_4x4D 9
1168     ; write out (4 dwords per register), start with dwords zero
1169     movd    [%5+%8*4], m%1
1170     movd         [%5], m%2
1171     movd    [%5+%9*4], m%3
1172     movd    [%5+%9*8], m%4
1173
1174     ; store dwords 1
1175     psrldq        m%1, 4
1176     psrldq        m%2, 4
1177     psrldq        m%3, 4
1178     psrldq        m%4, 4
1179     movd    [%6+%8*4], m%1
1180     movd         [%6], m%2
1181     movd    [%6+%9*4], m%3
1182     movd    [%6+%9*8], m%4
1183
1184     ; write dwords 2
1185     psrldq        m%1, 4
1186     psrldq        m%2, 4
1187     psrldq        m%3, 4
1188     psrldq        m%4, 4
1189     movd    [%5+%8*2], m%1
1190     movd      [%6+%9], m%2
1191     movd    [%7+%8*2], m%3
1192     movd    [%7+%9*2], m%4
1193     add            %7, %9
1194
1195     ; store dwords 3
1196     psrldq        m%1, 4
1197     psrldq        m%2, 4
1198     psrldq        m%3, 4
1199     psrldq        m%4, 4
1200     movd      [%5+%8], m%1
1201     movd    [%6+%9*2], m%2
1202     movd    [%7+%8*2], m%3
1203     movd    [%7+%9*2], m%4
1204 %endmacro
1205
1206 %macro SPLATB_REG 3
1207     movd           %1, %2
1208     punpcklbw      %1, %1
1209 %if mmsize == 16 ; sse2
1210     punpcklwd      %1, %1
1211     pshufd         %1, %1, 0x0
1212 %elifidn %3, mmx
1213     punpcklwd      %1, %1
1214     punpckldq      %1, %1
1215 %else ; mmxext
1216     pshufw         %1, %1, 0x0
1217 %endif
1218 %endmacro
1219
1220 %macro SIMPLE_LOOPFILTER 3
1221 cglobal vp8_%2_loop_filter_simple_%1, 3, %3
1222 %ifidn %2, h
1223     mov            r5, rsp          ; backup stack pointer
1224     and           rsp, ~(mmsize-1)  ; align stack
1225 %endif
1226 %if mmsize == 8 ; mmx/mmxext
1227     mov            r3, 2
1228 %endif
1229     SPLATB_REG     m7, r2, %1       ; splat "flim" into register
1230
1231     ; set up indexes to address 4 rows
1232     mov            r2, r1
1233     neg            r1
1234 %ifidn %2, h
1235     lea            r0, [r0+4*r2-2]
1236     sub           rsp, mmsize*2     ; (aligned) storage space for saving p1/q1
1237 %endif
1238
1239 %if mmsize == 8 ; mmx / mmxext
1240 .next8px
1241 %endif
1242 %ifidn %2, v
1243     ; read 4 half/full rows of pixels
1244     mova           m0, [r0+r1*2]    ; p1
1245     mova           m1, [r0+r1]      ; p0
1246     mova           m2, [r0]         ; q0
1247     mova           m3, [r0+r2]      ; q1
1248 %else ; h
1249     lea            r4, [r0+r2]
1250
1251 %if mmsize == 8 ; mmx/mmxext
1252     READ_8x4_INTERLEAVED  0, 1, 2, 3, 4, 5, 6, r0, r4, r1, r2
1253 %else ; sse2
1254     READ_16x4_INTERLEAVED 0, 1, 2, 3, 4, 5, 6, r0, r4, r1, r2, r3
1255 %endif
1256     TRANSPOSE4x4W         0, 1, 2, 3, 4
1257
1258     mova        [rsp], m0           ; store p1
1259     mova [rsp+mmsize], m3           ; store q1
1260 %endif
1261
1262     ; simple_limit
1263     mova           m5, m2           ; m5=backup of q0
1264     mova           m6, m1           ; m6=backup of p0
1265     psubusb        m1, m2           ; p0-q0
1266     psubusb        m2, m6           ; q0-p0
1267     por            m1, m2           ; FFABS(p0-q0)
1268     paddusb        m1, m1           ; m1=FFABS(p0-q0)*2
1269
1270     mova           m4, m3
1271     mova           m2, m0
1272     psubusb        m3, m0           ; q1-p1
1273     psubusb        m0, m4           ; p1-q1
1274     por            m3, m0           ; FFABS(p1-q1)
1275     mova           m0, [pb_80]
1276     pxor           m2, m0
1277     pxor           m4, m0
1278     psubsb         m2, m4           ; m2=p1-q1 (signed) backup for below
1279     pand           m3, [pb_FE]
1280     psrlq          m3, 1            ; m3=FFABS(p1-q1)/2, this can be used signed
1281     paddusb        m3, m1
1282     psubusb        m3, m7
1283     pxor           m1, m1
1284     pcmpeqb        m3, m1           ; abs(p0-q0)*2+abs(p1-q1)/2<=flim mask(0xff/0x0)
1285
1286     ; filter_common (use m2/p1-q1, m4=q0, m6=p0, m5/q0-p0 and m3/mask)
1287     mova           m4, m5
1288     pxor           m5, m0
1289     pxor           m0, m6
1290     psubsb         m5, m0           ; q0-p0 (signed)
1291     paddsb         m2, m5
1292     paddsb         m2, m5
1293     paddsb         m2, m5           ; a=(p1-q1) + 3*(q0-p0)
1294     pand           m2, m3           ; apply filter mask (m3)
1295
1296     mova           m3, [pb_F8]
1297     mova           m1, m2
1298     paddsb         m2, [pb_4]       ; f1<<3=a+4
1299     paddsb         m1, [pb_3]       ; f2<<3=a+3
1300     pand           m2, m3
1301     pand           m1, m3           ; cache f2<<3
1302
1303     pxor           m0, m0
1304     pxor           m3, m3
1305     pcmpgtb        m0, m2           ; which values are <0?
1306     psubb          m3, m2           ; -f1<<3
1307     psrlq          m2, 3            ; +f1
1308     psrlq          m3, 3            ; -f1
1309     pand           m3, m0
1310     pandn          m0, m2
1311     psubusb        m4, m0
1312     paddusb        m4, m3           ; q0-f1
1313
1314     pxor           m0, m0
1315     pxor           m3, m3
1316     pcmpgtb        m0, m1           ; which values are <0?
1317     psubb          m3, m1           ; -f2<<3
1318     psrlq          m1, 3            ; +f2
1319     psrlq          m3, 3            ; -f2
1320     pand           m3, m0
1321     pandn          m0, m1
1322     paddusb        m6, m0
1323     psubusb        m6, m3           ; p0+f2
1324
1325     ; store
1326 %ifidn %2, v
1327     mova         [r0], m4
1328     mova      [r0+r1], m6
1329 %else ; h
1330     mova           m0, [rsp]        ; p1
1331     SWAP            2, 4            ; p0
1332     SWAP            1, 6            ; q0
1333     mova           m3, [rsp+mmsize] ; q1
1334
1335     TRANSPOSE4x4B  0, 1, 2, 3, 4
1336 %if mmsize == 16 ; sse2
1337     add            r3, r1           ; change from r4*8*stride to r0+8*stride
1338     WRITE_4x4D 0, 1, 2, 3, r0, r4, r3, r1, r2
1339 %else ; mmx/mmxext
1340     WRITE_4x2D 0, 1, 2, 3, r0, r4, r1, r2
1341 %endif
1342 %endif
1343
1344 %if mmsize == 8 ; mmx/mmxext
1345     ; next 8 pixels
1346 %ifidn %2, v
1347     add            r0, 8            ; advance 8 cols = pixels
1348 %else ; h
1349     lea            r0, [r0+r2*8]    ; advance 8 rows = lines
1350 %endif
1351     dec            r3
1352     jg .next8px
1353 %ifidn %2, v
1354     REP_RET
1355 %else ; h
1356     mov           rsp, r5           ; restore stack pointer
1357     RET
1358 %endif
1359 %else ; sse2
1360 %ifidn %2, h
1361     mov           rsp, r5           ; restore stack pointer
1362 %endif
1363     RET
1364 %endif
1365 %endmacro
1366
1367 INIT_MMX
1368 SIMPLE_LOOPFILTER mmx,    v, 4
1369 SIMPLE_LOOPFILTER mmx,    h, 6
1370 SIMPLE_LOOPFILTER mmxext, v, 4
1371 SIMPLE_LOOPFILTER mmxext, h, 6
1372 INIT_XMM
1373 SIMPLE_LOOPFILTER sse2,   v, 3
1374 SIMPLE_LOOPFILTER sse2,   h, 6
1375
1376 ;-----------------------------------------------------------------------------
1377 ; void vp8_h/v_loop_filter<size>_inner_<opt>(uint8_t *dst, int stride,
1378 ;                                            int flimE, int flimI, int hev_thr);
1379 ;-----------------------------------------------------------------------------
1380
1381 %macro INNER_LOOPFILTER 4
1382 cglobal vp8_%2_loop_filter16_inner_%1, 5, %3, %4
1383 %ifndef m8 ; mmx/mmxext or sse2 on x86-32
1384     ; splat function arguments
1385     SPLATB_REG       m0, r2, %1      ; E
1386     SPLATB_REG       m1, r3, %1      ; I
1387     SPLATB_REG       m2, r4, %1      ; hev_thresh
1388
1389     ; align stack
1390     mov              r4, rsp         ; backup stack pointer
1391     and             rsp, ~(mmsize-1) ; align stack
1392 %ifidn %2, v
1393     sub             rsp, mmsize * 4  ; stack layout: [0]=E, [1]=I, [2]=hev_thr
1394                                      ;               [3]=hev() result
1395 %else ; h
1396     sub             rsp, mmsize * 6  ; extra storage space for transposes
1397 %endif
1398
1399 %define flim_E   [rsp]
1400 %define flim_I   [rsp+mmsize]
1401 %define hev_thr  [rsp+mmsize*2]
1402 %define mask_res [rsp+mmsize*3]
1403
1404     mova         flim_E, m0
1405     mova         flim_I, m1
1406     mova        hev_thr, m2
1407
1408 %else ; sse2 on x86-64
1409
1410 %define flim_E   m9
1411 %define flim_I   m10
1412 %define hev_thr  m11
1413 %define mask_res m12
1414
1415     ; splat function arguments
1416     SPLATB_REG   flim_E, r2, %1      ; E
1417     SPLATB_REG   flim_I, r3, %1      ; I
1418     SPLATB_REG  hev_thr, r4, %1      ; hev_thresh
1419 %endif
1420
1421 %if mmsize == 8 ; mmx/mmxext
1422     mov              r5, 2
1423 %endif
1424     mov              r2, r1
1425     neg              r1
1426 %ifidn %2, h
1427     lea              r0, [r0+4*r2-4]
1428 %endif
1429
1430 %if mmsize == 8
1431 .next8px
1432 %endif
1433     ; read
1434     lea              r3, [r0+r2]
1435 %ifidn %2, v
1436     mova             m0, [r0+r1*4]   ; p3
1437     mova             m1, [r3+r1*4]   ; p2
1438     mova             m2, [r0+r1*2]   ; p1
1439     mova             m5, [r3]        ; q1
1440     mova             m6, [r3+r2]     ; q2
1441     mova             m7, [r3+r2*2]   ; q3
1442 %elif mmsize == 8 ; mmx/mmxext (h)
1443     ; read 8 rows of 8px each
1444     movu             m0, [r0+r1*4]
1445     movu             m1, [r3+r1*4]
1446     movu             m2, [r0+r1*2]
1447     movu             m3, [r0+r1]
1448     movu             m4, [r0]
1449     movu             m5, [r3]
1450     movu             m6, [r3+r2]
1451
1452     ; 8x8 transpose
1453     TRANSPOSE4x4B     0, 1, 2, 3, 7
1454 %ifdef m13
1455     SWAP              1, 13
1456 %else
1457     mova [rsp+mmsize*4], m1
1458 %endif
1459     movu             m7, [r3+r2*2]
1460     TRANSPOSE4x4B     4, 5, 6, 7, 1
1461     SBUTTERFLY       dq, 0, 4, 1     ; p3/p2
1462     SBUTTERFLY       dq, 2, 6, 1     ; q0/q1
1463     SBUTTERFLY       dq, 3, 7, 1     ; q2/q3
1464 %ifdef m13
1465     SWAP              1, 13
1466     SWAP              2, 13
1467 %else
1468     mova             m1, [rsp+mmsize*4]
1469     mova [rsp+mmsize*4], m2          ; store q0
1470 %endif
1471     SBUTTERFLY       dq, 1, 5, 2     ; p1/p0
1472 %ifdef m14
1473     SWAP              5, 14
1474 %else
1475     mova [rsp+mmsize*5], m5          ; store p0
1476 %endif
1477     SWAP              1, 4
1478     SWAP              2, 4
1479     SWAP              6, 3
1480     SWAP              5, 3
1481 %else ; sse2 (h)
1482     lea              r5, [r0+r2*8]
1483
1484     ; read 16 rows of 8px each, interleave
1485     movh             m0, [r0+r1*4]
1486     movh             m1, [r5+r1*4]
1487     movh             m2, [r0+r1*2]
1488     movh             m5, [r5+r1*2]
1489     movh             m3, [r0+r1]
1490     movh             m6, [r5+r1]
1491     movh             m4, [r0]
1492     movh             m7, [r5]
1493     punpcklbw        m0, m1          ; A/I
1494     punpcklbw        m2, m5          ; C/K
1495     punpcklbw        m3, m6          ; D/L
1496     punpcklbw        m4, m7          ; E/M
1497
1498     add              r5, r2
1499     movh             m1, [r3+r1*4]
1500     movh             m6, [r5+r1*4]
1501     movh             m5, [r3]
1502     movh             m7, [r5]
1503     punpcklbw        m1, m6          ; B/J
1504     punpcklbw        m5, m7          ; F/N
1505     movh             m6, [r3+r2]
1506     movh             m7, [r5+r2]
1507     punpcklbw        m6, m7          ; G/O
1508
1509     ; 8x16 transpose
1510     TRANSPOSE4x4B     0, 1, 2, 3, 7
1511 %ifdef m13
1512     SWAP              1, 13
1513 %else
1514     mova [rsp+mmsize*4], m1
1515 %endif
1516     movh             m7, [r3+r2*2]
1517     movh             m1, [r5+r2*2]
1518     punpcklbw        m7, m1          ; H/P
1519     TRANSPOSE4x4B     4, 5, 6, 7, 1
1520     SBUTTERFLY       dq, 0, 4, 1     ; p3/p2
1521     SBUTTERFLY       dq, 2, 6, 1     ; q0/q1
1522     SBUTTERFLY       dq, 3, 7, 1     ; q2/q3
1523 %ifdef m13
1524     SWAP              1, 13
1525     SWAP              2, 13
1526 %else
1527     mova             m1, [rsp+mmsize*4]
1528     mova [rsp+mmsize*4], m2          ; store q0
1529 %endif
1530     SBUTTERFLY       dq, 1, 5, 2     ; p1/p0
1531 %ifdef m14
1532     SWAP              5, 14
1533 %else
1534     mova [rsp+mmsize*5], m5          ; store p0
1535 %endif
1536     SWAP              1, 4
1537     SWAP              2, 4
1538     SWAP              6, 3
1539     SWAP              5, 3
1540 %endif
1541
1542     ; normal_limit for p3-p2, p2-p1, q3-q2 and q2-q1
1543     mova             m4, m1
1544     SWAP              4, 1
1545     psubusb          m4, m0          ; p2-p3
1546     psubusb          m0, m1          ; p3-p2
1547     por              m0, m4          ; abs(p3-p2)
1548
1549     mova             m4, m2
1550     SWAP              4, 2
1551     psubusb          m4, m1          ; p1-p2
1552     psubusb          m1, m2          ; p2-p1
1553     por              m1, m4          ; abs(p2-p1)
1554
1555     mova             m4, m6
1556     SWAP              4, 6
1557     psubusb          m4, m7          ; q2-q3
1558     psubusb          m7, m6          ; q3-q2
1559     por              m7, m4          ; abs(q3-q2)
1560
1561     mova             m4, m5
1562     SWAP              4, 5
1563     psubusb          m4, m6          ; q1-q2
1564     psubusb          m6, m5          ; q2-q1
1565     por              m6, m4          ; abs(q2-q1)
1566
1567 %ifidn %1, mmx
1568 %ifdef m10
1569     SWAP              4, 10
1570 %else
1571     mova             m4, [rsp+mmsize]
1572 %endif
1573     pxor             m3, m3
1574     psubusb          m0, m4
1575     psubusb          m1, m4
1576     psubusb          m7, m4
1577     psubusb          m6, m4
1578     pcmpeqb          m0, m3          ; abs(p3-p2) <= I
1579     pcmpeqb          m1, m3          ; abs(p2-p1) <= I
1580     pcmpeqb          m7, m3          ; abs(q3-q2) <= I
1581     pcmpeqb          m6, m3          ; abs(q2-q1) <= I
1582     pand             m0, m1
1583     pand             m7, m6
1584     pand             m0, m7
1585 %else ; mmxext/sse2
1586     pmaxub           m0, m1
1587     pmaxub           m6, m7
1588     pmaxub           m0, m6
1589 %endif
1590
1591     ; normal_limit and high_edge_variance for p1-p0, q1-q0
1592     SWAP              7, 3           ; now m7 is zero
1593 %ifidn %2, v
1594     mova             m3, [r0+r1]     ; p0
1595 %elifdef m14
1596     SWAP              3, 14
1597 %else
1598     mova             m3, [rsp+mmsize*5]
1599 %endif
1600
1601     mova             m1, m2
1602     SWAP              1, 2
1603     mova             m6, m3
1604     SWAP              3, 6
1605     psubusb          m1, m3          ; p1-p0
1606     psubusb          m6, m2          ; p0-p1
1607     por              m1, m6          ; abs(p1-p0)
1608 %ifidn %1, mmx
1609     mova             m6, m1
1610     psubusb          m1, m4
1611     psubusb          m6, hev_thr
1612     pcmpeqb          m1, m7          ; abs(p1-p0) <= I
1613     pcmpeqb          m6, m7          ; abs(p1-p0) <= hev_thresh
1614     pand             m0, m1
1615 %ifdef m12
1616     SWAP              6, 12
1617 %else
1618     mova [rsp+mmsize*3], m6
1619 %endif
1620 %else ; mmxext/sse2
1621     pmaxub           m0, m1          ; max_I
1622     SWAP              1, 4           ; max_hev_thresh
1623 %endif
1624
1625     SWAP              6, 4           ; now m6 is I
1626 %ifidn %2, v
1627     mova             m4, [r0]        ; q0
1628 %elifdef m13
1629     SWAP              4, 13
1630 %else
1631     mova             m4, [rsp+mmsize*4]
1632 %endif
1633     mova             m1, m4
1634     SWAP              1, 4
1635     mova             m7, m5
1636     SWAP              7, 5
1637     psubusb          m1, m5          ; q0-q1
1638     psubusb          m7, m4          ; q1-q0
1639     por              m1, m7          ; abs(q1-q0)
1640 %ifidn %1, mmx
1641     mova             m7, m1
1642     psubusb          m1, m6
1643     psubusb          m7, hev_thr
1644     pxor             m6, m6
1645     pcmpeqb          m1, m6          ; abs(q1-q0) <= I
1646     pcmpeqb          m7, m6          ; abs(q1-q0) <= hev_thresh
1647 %ifdef m12
1648     SWAP              6, 12
1649 %else
1650     mova             m6, [rsp+mmsize*3]
1651 %endif
1652     pand             m0, m1          ; abs([pq][321]-[pq][210]) <= I
1653     pand             m6, m7
1654 %else ; mmxext/sse2
1655     pxor             m7, m7
1656     pmaxub           m0, m1
1657     pmaxub           m6, m1
1658     psubusb          m0, flim_I
1659     psubusb          m6, hev_thr
1660     pcmpeqb          m0, m7          ; max(abs(..)) <= I
1661     pcmpeqb          m6, m7          ; !(max(abs..) > thresh)
1662 %endif
1663 %ifdef m12
1664     SWAP              6, 12
1665 %else
1666     mova [rsp+mmsize*3], m6          ; !(abs(p1-p0) > hev_t || abs(q1-q0) > hev_t)
1667 %endif
1668
1669     ; simple_limit
1670     mova             m1, m3
1671     SWAP              1, 3
1672     mova             m6, m4          ; keep copies of p0/q0 around for later use
1673     SWAP              6, 4
1674     psubusb          m1, m4          ; p0-q0
1675     psubusb          m6, m3          ; q0-p0
1676     por              m1, m6          ; abs(q0-p0)
1677     paddusb          m1, m1          ; m1=2*abs(q0-p0)
1678
1679     mova             m7, m2
1680     SWAP              7, 2
1681     mova             m6, m5
1682     SWAP              6, 5
1683     psubusb          m7, m5          ; p1-q1
1684     psubusb          m6, m2          ; q1-p1
1685     por              m7, m6          ; abs(q1-p1)
1686     pxor             m6, m6
1687     pand             m7, [pb_FE]
1688     psrlq            m7, 1           ; abs(q1-p1)/2
1689     paddusb          m7, m1          ; abs(q0-p0)*2+abs(q1-p1)/2
1690     psubusb          m7, flim_E
1691     pcmpeqb          m7, m6          ; abs(q0-p0)*2+abs(q1-p1)/2 <= E
1692     pand             m0, m7          ; normal_limit result
1693
1694     ; filter_common; at this point, m2-m5=p1-q1 and m0 is filter_mask
1695 %ifdef m8 ; x86-64 && sse2
1696     mova             m8, [pb_80]
1697 %define pb_80_var m8
1698 %else ; x86-32 or mmx/mmxext
1699 %define pb_80_var [pb_80]
1700 %endif
1701     mova             m1, m4
1702     mova             m7, m3
1703     pxor             m1, pb_80_var
1704     pxor             m7, pb_80_var
1705     psubsb           m1, m7          ; (signed) q0-p0
1706     mova             m6, m2
1707     mova             m7, m5
1708     pxor             m6, pb_80_var
1709     pxor             m7, pb_80_var
1710     psubsb           m6, m7          ; (signed) p1-q1
1711     mova             m7, mask_res
1712     pandn            m7, m6
1713     paddsb           m7, m1
1714     paddsb           m7, m1
1715     paddsb           m7, m1          ; 3*(q0-p0)+is4tap?(p1-q1)
1716
1717     pand             m7, m0
1718     mova             m1, [pb_F8]
1719     mova             m6, m7
1720     paddsb           m7, [pb_3]
1721     paddsb           m6, [pb_4]
1722     pand             m7, m1
1723     pand             m6, m1
1724
1725     pxor             m1, m1
1726     pxor             m0, m0
1727     pcmpgtb          m1, m7
1728     psubb            m0, m7
1729     psrlq            m7, 3           ; +f2
1730     psrlq            m0, 3           ; -f2
1731     pand             m0, m1
1732     pandn            m1, m7
1733     psubusb          m3, m0
1734     paddusb          m3, m1          ; p0+f2
1735
1736     pxor             m1, m1
1737     pxor             m0, m0
1738     pcmpgtb          m0, m6
1739     psubb            m1, m6
1740     psrlq            m6, 3           ; +f1
1741     psrlq            m1, 3           ; -f1
1742     pand             m1, m0
1743     pandn            m0, m6
1744     psubusb          m4, m0
1745     paddusb          m4, m1          ; q0-f1
1746
1747 %ifdef m12
1748     SWAP              6, 12
1749 %else
1750     mova             m6, [rsp+mmsize*3]
1751 %endif
1752 %ifidn %1, mmx
1753     mova             m7, [pb_1]
1754 %else ; mmxext/sse2
1755     pxor             m7, m7
1756 %endif
1757     pand             m0, m6
1758     pand             m1, m6
1759 %ifidn %1, mmx
1760     paddusb          m0, m7
1761     pand             m1, [pb_FE]
1762     pandn            m7, m0
1763     psrlq            m1, 1
1764     psrlq            m7, 1
1765     SWAP              0, 7
1766 %else ; mmxext/sse2
1767     psubusb          m1, [pb_1]
1768     pavgb            m0, m7          ; a
1769     pavgb            m1, m7          ; -a
1770 %endif
1771     psubusb          m5, m0
1772     psubusb          m2, m1
1773     paddusb          m5, m1          ; q1-a
1774     paddusb          m2, m0          ; p1+a
1775
1776     ; store
1777 %ifidn %2, v
1778     mova      [r0+r1*2], m2
1779     mova        [r0+r1], m3
1780     mova           [r0], m4
1781     mova        [r0+r2], m5
1782 %else ; h
1783     add               r0, 2
1784     add               r3, 2
1785
1786     ; 4x8/16 transpose
1787     TRANSPOSE4x4B     2, 3, 4, 5, 6
1788
1789 %if mmsize == 8 ; mmx/mmxext (h)
1790     WRITE_4x2D        2, 3, 4, 5, r0, r3, r1, r2
1791 %else ; sse2 (h)
1792     lea              r5, [r5+r1+2]
1793     WRITE_4x4D        2, 3, 4, 5, r0, r3, r5, r1, r2
1794 %endif
1795 %endif
1796
1797 %if mmsize == 8
1798 %ifidn %2, h
1799     lea              r0, [r0+8*r2-2]
1800 %else ; v
1801     add              r0, 8
1802 %endif
1803     dec              r5
1804     jg .next8px
1805 %endif
1806
1807 %ifndef m8 ; sse2 on x86-32 or mmx/mmxext
1808     mov             rsp, r4          ; restore stack pointer
1809 %endif
1810     RET
1811 %endmacro
1812
1813 INIT_MMX
1814 INNER_LOOPFILTER mmx,    v, 6, 8
1815 INNER_LOOPFILTER mmx,    h, 6, 8
1816 INNER_LOOPFILTER mmxext, v, 6, 8
1817 INNER_LOOPFILTER mmxext, h, 6, 8
1818 INIT_XMM
1819 INNER_LOOPFILTER sse2,   v, 5, 13
1820 INNER_LOOPFILTER sse2,   h, 6, 15