vp9: add subpel MC SIMD for 10/12bpp.
[ffmpeg.git] / libavcodec / x86 / vp9mc_16bpp.asm
1 ;******************************************************************************
2 ;* VP9 MC SIMD optimizations
3 ;*
4 ;* Copyright (c) 2015 Ronald S. Bultje <rsbultje gmail com>
5 ;*
6 ;* This file is part of FFmpeg.
7 ;*
8 ;* FFmpeg is free software; you can redistribute it and/or
9 ;* modify it under the terms of the GNU Lesser General Public
10 ;* License as published by the Free Software Foundation; either
11 ;* version 2.1 of the License, or (at your option) any later version.
12 ;*
13 ;* FFmpeg is distributed in the hope that it will be useful,
14 ;* but WITHOUT ANY WARRANTY; without even the implied warranty of
15 ;* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16 ;* Lesser General Public License for more details.
17 ;*
18 ;* You should have received a copy of the GNU Lesser General Public
19 ;* License along with FFmpeg; if not, write to the Free Software
20 ;* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
21 ;******************************************************************************
22
23 %include "libavutil/x86/x86util.asm"
24
25 SECTION_RODATA 32
26
27 pw_4095: times 16 dw 0xfff
28 pd_64: times 8 dd 64
29
30 cextern pw_1023
31
32 SECTION .text
33
34 %macro filter_h4_fn 1-2 12
35 cglobal vp9_%1_8tap_1d_h_4_10, 6, 6, %2, dst, dstride, src, sstride, h, filtery
36     mova        m5, [pw_1023]
37 .body:
38 %if notcpuflag(sse4) && ARCH_X86_64
39     pxor       m11, m11
40 %endif
41     mova        m6, [pd_64]
42     mova        m7, [filteryq+ 0]
43 %if ARCH_X86_64 && mmsize > 8
44     mova        m8, [filteryq+32]
45     mova        m9, [filteryq+64]
46     mova       m10, [filteryq+96]
47 %endif
48 .loop:
49     movh        m0, [srcq-6]
50     movh        m1, [srcq-4]
51     movh        m2, [srcq-2]
52     movh        m3, [srcq+0]
53     movh        m4, [srcq+2]
54     punpcklwd   m0, m1
55     punpcklwd   m2, m3
56     pmaddwd     m0, m7
57 %if ARCH_X86_64 && mmsize > 8
58     pmaddwd     m2, m8
59 %else
60     pmaddwd     m2, [filteryq+32]
61 %endif
62     movu        m1, [srcq+4]
63     movu        m3, [srcq+6]
64     paddd       m0, m2
65     movu        m2, [srcq+8]
66     add       srcq, sstrideq
67     punpcklwd   m4, m1
68     punpcklwd   m3, m2
69 %if ARCH_X86_64 && mmsize > 8
70     pmaddwd     m4, m9
71     pmaddwd     m3, m10
72 %else
73     pmaddwd     m4, [filteryq+64]
74     pmaddwd     m3, [filteryq+96]
75 %endif
76     paddd       m0, m4
77     paddd       m0, m3
78     paddd       m0, m6
79     psrad       m0, 7
80 %if cpuflag(sse4)
81     packusdw    m0, m0
82 %else
83     packssdw    m0, m0
84 %endif
85 %ifidn %1, avg
86     movh        m1, [dstq]
87 %endif
88     pminsw      m0, m5
89 %if notcpuflag(sse4)
90 %if ARCH_X86_64
91     pmaxsw      m0, m11
92 %else
93     pxor        m2, m2
94     pmaxsw      m0, m2
95 %endif
96 %endif
97 %ifidn %1, avg
98     pavgw       m0, m1
99 %endif
100     movh    [dstq], m0
101     add       dstq, dstrideq
102     dec         hd
103     jg .loop
104     RET
105
106 cglobal vp9_%1_8tap_1d_h_4_12, 6, 6, %2, dst, dstride, src, sstride, h, filtery
107     mova        m5, [pw_4095]
108     jmp mangle(private_prefix %+ _ %+ vp9_%1_8tap_1d_h_4_10 %+ SUFFIX).body
109 %endmacro
110
111 INIT_XMM sse2
112 filter_h4_fn put
113 filter_h4_fn avg
114
115 %macro filter_h_fn 1-2 12
116 %assign %%px mmsize/2
117 cglobal vp9_%1_8tap_1d_h_ %+ %%px %+ _10, 6, 6, %2, dst, dstride, src, sstride, h, filtery
118     mova        m5, [pw_1023]
119 .body:
120 %if notcpuflag(sse4) && ARCH_X86_64
121     pxor       m11, m11
122 %endif
123     mova        m6, [pd_64]
124     mova        m7, [filteryq+ 0]
125 %if ARCH_X86_64 && mmsize > 8
126     mova        m8, [filteryq+32]
127     mova        m9, [filteryq+64]
128     mova       m10, [filteryq+96]
129 %endif
130 .loop:
131     movu        m0, [srcq-6]
132     movu        m1, [srcq-4]
133     movu        m2, [srcq-2]
134     movu        m3, [srcq+0]
135     movu        m4, [srcq+2]
136     pmaddwd     m0, m7
137     pmaddwd     m1, m7
138 %if ARCH_X86_64 && mmsize > 8
139     pmaddwd     m2, m8
140     pmaddwd     m3, m8
141     pmaddwd     m4, m9
142 %else
143     pmaddwd     m2, [filteryq+32]
144     pmaddwd     m3, [filteryq+32]
145     pmaddwd     m4, [filteryq+64]
146 %endif
147     paddd       m0, m2
148     paddd       m1, m3
149     paddd       m0, m4
150     movu        m2, [srcq+4]
151     movu        m3, [srcq+6]
152     movu        m4, [srcq+8]
153     add       srcq, sstrideq
154 %if ARCH_X86_64 && mmsize > 8
155     pmaddwd     m2, m9
156     pmaddwd     m3, m10
157     pmaddwd     m4, m10
158 %else
159     pmaddwd     m2, [filteryq+64]
160     pmaddwd     m3, [filteryq+96]
161     pmaddwd     m4, [filteryq+96]
162 %endif
163     paddd       m1, m2
164     paddd       m0, m3
165     paddd       m1, m4
166     paddd       m0, m6
167     paddd       m1, m6
168     psrad       m0, 7
169     psrad       m1, 7
170 %if cpuflag(sse4)
171     packusdw    m0, m0
172     packusdw    m1, m1
173 %else
174     packssdw    m0, m0
175     packssdw    m1, m1
176 %endif
177     punpcklwd   m0, m1
178     pminsw      m0, m5
179 %if notcpuflag(sse4)
180 %if ARCH_X86_64
181     pmaxsw      m0, m11
182 %else
183     pxor        m2, m2
184     pmaxsw      m0, m2
185 %endif
186 %endif
187 %ifidn %1, avg
188     pavgw       m0, [dstq]
189 %endif
190     mova    [dstq], m0
191     add       dstq, dstrideq
192     dec         hd
193     jg .loop
194     RET
195
196 cglobal vp9_%1_8tap_1d_h_ %+ %%px %+ _12, 6, 6, %2, dst, dstride, src, sstride, h, filtery
197     mova        m5, [pw_4095]
198     jmp mangle(private_prefix %+ _ %+ vp9_%1_8tap_1d_h_ %+ %%px %+ _10 %+ SUFFIX).body
199 %endmacro
200
201 INIT_XMM sse2
202 filter_h_fn put
203 filter_h_fn avg
204
205 %macro filter_v4_fn 1-2 12
206 %if ARCH_X86_64
207 cglobal vp9_%1_8tap_1d_v_4_10, 6, 8, %2, dst, dstride, src, sstride, h, filtery, src4, sstride3
208 %else
209 cglobal vp9_%1_8tap_1d_v_4_10, 4, 7, %2, dst, dstride, src, sstride, filtery, src4, sstride3
210     mov   filteryq, r5mp
211 %define hd r4mp
212 %endif
213     mova        m5, [pw_1023]
214 .body:
215 %if notcpuflag(sse4) && ARCH_X86_64
216     pxor       m11, m11
217 %endif
218     mova        m6, [pd_64]
219     lea  sstride3q, [sstrideq*3]
220     lea      src4q, [srcq+sstrideq]
221     sub       srcq, sstride3q
222     mova        m7, [filteryq+  0]
223 %if ARCH_X86_64 && mmsize > 8
224     mova        m8, [filteryq+ 32]
225     mova        m9, [filteryq+ 64]
226     mova       m10, [filteryq+ 96]
227 %endif
228 .loop:
229     ; FIXME maybe reuse loads from previous rows, or just
230     ; more generally unroll this to prevent multiple loads of
231     ; the same data?
232     movh        m0, [srcq]
233     movh        m1, [srcq+sstrideq]
234     movh        m2, [srcq+sstrideq*2]
235     movh        m3, [srcq+sstride3q]
236     add       srcq, sstrideq
237     movh        m4, [src4q]
238     punpcklwd   m0, m1
239     punpcklwd   m2, m3
240     pmaddwd     m0, m7
241 %if ARCH_X86_64 && mmsize > 8
242     pmaddwd     m2, m8
243 %else
244     pmaddwd     m2, [filteryq+ 32]
245 %endif
246     movh        m1, [src4q+sstrideq]
247     movh        m3, [src4q+sstrideq*2]
248     paddd       m0, m2
249     movh        m2, [src4q+sstride3q]
250     add      src4q, sstrideq
251     punpcklwd   m4, m1
252     punpcklwd   m3, m2
253 %if ARCH_X86_64 && mmsize > 8
254     pmaddwd     m4, m9
255     pmaddwd     m3, m10
256 %else
257     pmaddwd     m4, [filteryq+ 64]
258     pmaddwd     m3, [filteryq+ 96]
259 %endif
260     paddd       m0, m4
261     paddd       m0, m3
262     paddd       m0, m6
263     psrad       m0, 7
264 %if cpuflag(sse4)
265     packusdw    m0, m0
266 %else
267     packssdw    m0, m0
268 %endif
269 %ifidn %1, avg
270     movh        m1, [dstq]
271 %endif
272     pminsw      m0, m5
273 %if notcpuflag(sse4)
274 %if ARCH_X86_64
275     pmaxsw      m0, m11
276 %else
277     pxor        m2, m2
278     pmaxsw      m0, m2
279 %endif
280 %endif
281 %ifidn %1, avg
282     pavgw       m0, m1
283 %endif
284     movh    [dstq], m0
285     add       dstq, dstrideq
286     dec         hd
287     jg .loop
288     RET
289
290 %if ARCH_X86_64
291 cglobal vp9_%1_8tap_1d_v_4_12, 6, 8, %2, dst, dstride, src, sstride, h, filtery, src4, sstride3
292 %else
293 cglobal vp9_%1_8tap_1d_v_4_12, 4, 7, %2, dst, dstride, src, sstride, filtery, src4, sstride3
294     mov   filteryq, r5mp
295 %endif
296     mova        m5, [pw_4095]
297     jmp mangle(private_prefix %+ _ %+ vp9_%1_8tap_1d_v_4_10 %+ SUFFIX).body
298 %endmacro
299
300 INIT_XMM sse2
301 filter_v4_fn put
302 filter_v4_fn avg
303
304 %macro filter_v_fn 1-2 13
305 %assign %%px mmsize/2
306 %if ARCH_X86_64
307 cglobal vp9_%1_8tap_1d_v_ %+ %%px %+ _10, 6, 8, %2, dst, dstride, src, sstride, h, filtery, src4, sstride3
308 %else
309 cglobal vp9_%1_8tap_1d_v_ %+ %%px %+ _10, 4, 7, %2, dst, dstride, src, sstride, filtery, src4, sstride3
310     mov   filteryq, r5mp
311 %define hd r4mp
312 %endif
313     mova        m5, [pw_1023]
314 .body:
315 %if notcpuflag(sse4) && ARCH_X86_64
316     pxor       m12, m12
317 %endif
318 %if ARCH_X86_64
319     mova       m11, [pd_64]
320 %endif
321     lea  sstride3q, [sstrideq*3]
322     lea      src4q, [srcq+sstrideq]
323     sub       srcq, sstride3q
324     mova        m7, [filteryq+  0]
325 %if ARCH_X86_64 && mmsize > 8
326     mova        m8, [filteryq+ 32]
327     mova        m9, [filteryq+ 64]
328     mova       m10, [filteryq+ 96]
329 %endif
330 .loop:
331     ; FIXME maybe reuse loads from previous rows, or just
332     ; more generally unroll this to prevent multiple loads of
333     ; the same data?
334     movu        m0, [srcq]
335     movu        m1, [srcq+sstrideq]
336     movu        m2, [srcq+sstrideq*2]
337     movu        m3, [srcq+sstride3q]
338     add       srcq, sstrideq
339     movu        m4, [src4q]
340     SBUTTERFLY  wd, 0, 1, 6
341     SBUTTERFLY  wd, 2, 3, 6
342     pmaddwd     m0, m7
343     pmaddwd     m1, m7
344 %if ARCH_X86_64 && mmsize > 8
345     pmaddwd     m2, m8
346     pmaddwd     m3, m8
347 %else
348     pmaddwd     m2, [filteryq+ 32]
349     pmaddwd     m3, [filteryq+ 32]
350 %endif
351     paddd       m0, m2
352     paddd       m1, m3
353     movu        m2, [src4q+sstrideq]
354     movu        m3, [src4q+sstrideq*2]
355     SBUTTERFLY  wd, 4, 2, 6
356 %if ARCH_X86_64 && mmsize > 8
357     pmaddwd     m4, m9
358     pmaddwd     m2, m9
359 %else
360     pmaddwd     m4, [filteryq+ 64]
361     pmaddwd     m2, [filteryq+ 64]
362 %endif
363     paddd       m0, m4
364     paddd       m1, m2
365     movu        m4, [src4q+sstride3q]
366     add      src4q, sstrideq
367     SBUTTERFLY  wd, 3, 4, 6
368 %if ARCH_X86_64 && mmsize > 8
369     pmaddwd     m3, m10
370     pmaddwd     m4, m10
371 %else
372     pmaddwd     m3, [filteryq+ 96]
373     pmaddwd     m4, [filteryq+ 96]
374 %endif
375     paddd       m0, m3
376     paddd       m1, m4
377 %if ARCH_X86_64
378     paddd       m0, m11
379     paddd       m1, m11
380 %else
381     paddd       m0, [pd_64]
382     paddd       m1, [pd_64]
383 %endif
384     psrad       m0, 7
385     psrad       m1, 7
386 %if cpuflag(sse4)
387     packusdw    m0, m1
388 %else
389     packssdw    m0, m1
390 %endif
391     pminsw      m0, m5
392 %if notcpuflag(sse4)
393 %if ARCH_X86_64
394     pmaxsw      m0, m12
395 %else
396     pxor        m2, m2
397     pmaxsw      m0, m2
398 %endif
399 %endif
400 %ifidn %1, avg
401     pavgw       m0, [dstq]
402 %endif
403     mova    [dstq], m0
404     add       dstq, dstrideq
405     dec         hd
406     jg .loop
407     RET
408
409 %if ARCH_X86_64
410 cglobal vp9_%1_8tap_1d_v_ %+ %%px %+ _12, 6, 8, %2, dst, dstride, src, sstride, h, filtery, src4, sstride3
411 %else
412 cglobal vp9_%1_8tap_1d_v_ %+ %%px %+ _12, 4, 7, %2, dst, dstride, src, sstride, filtery, src4, sstride3
413     mov   filteryq, r5mp
414 %endif
415     mova        m5, [pw_4095]
416     jmp mangle(private_prefix %+ _ %+ vp9_%1_8tap_1d_v_ %+ %%px %+ _10 %+ SUFFIX).body
417 %endmacro
418
419 INIT_XMM sse2
420 filter_v_fn put
421 filter_v_fn avg