d97e4abddbc49cb631614b1ab927db3d65869c2f
[ffmpeg.git] / libavcodec / x86 / hevc_add_res.asm
1 ; *****************************************************************************
2 ; * Provide SIMD optimizations for add_residual functions for HEVC decoding
3 ; * Copyright (c) 2014 Pierre-Edouard LEPERE
4 ; *
5 ; * This file is part of FFmpeg.
6 ; *
7 ; * FFmpeg is free software; you can redistribute it and/or
8 ; * modify it under the terms of the GNU Lesser General Public
9 ; * License as published by the Free Software Foundation; either
10 ; * version 2.1 of the License, or (at your option) any later version.
11 ; *
12 ; * FFmpeg is distributed in the hope that it will be useful,
13 ; * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 ; * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15 ; * Lesser General Public License for more details.
16 ; *
17 ; * You should have received a copy of the GNU Lesser General Public
18 ; * License along with FFmpeg; if not, write to the Free Software
19 ; * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20 ; ******************************************************************************
21
22 %include "libavutil/x86/x86util.asm"
23
24 SECTION .text
25
26 cextern pw_1023
27 %define max_pixels_10 pw_1023
28
29 ; the add_res macros and functions were largely inspired by h264_idct.asm from the x264 project
30 %macro ADD_RES_MMX_4_8 0
31     mova              m2, [r1]
32     mova              m4, [r1+8]
33     pxor              m3, m3
34     psubw             m3, m2
35     packuswb          m2, m2
36     packuswb          m3, m3
37     pxor              m5, m5
38     psubw             m5, m4
39     packuswb          m4, m4
40     packuswb          m5, m5
41
42     movh              m0, [r0]
43     movh              m1, [r0+r2]
44     paddusb           m0, m2
45     paddusb           m1, m4
46     psubusb           m0, m3
47     psubusb           m1, m5
48     movh            [r0], m0
49     movh         [r0+r2], m1
50 %endmacro
51
52
53 INIT_MMX mmxext
54 ; void ff_hevc_add_residual_4_8_mmxext(uint8_t *dst, int16_t *res, ptrdiff_t stride)
55 cglobal hevc_add_residual_4_8, 3, 3, 6
56     ADD_RES_MMX_4_8
57     add               r1, 16
58     lea               r0, [r0+r2*2]
59     ADD_RES_MMX_4_8
60     RET
61
62 %macro ADD_RES_SSE_8_8 0
63     pxor              m3, m3
64     mova              m4, [r1]
65     mova              m6, [r1+16]
66     mova              m0, [r1+32]
67     mova              m2, [r1+48]
68     psubw             m5, m3, m4
69     psubw             m7, m3, m6
70     psubw             m1, m3, m0
71     packuswb          m4, m0
72     packuswb          m5, m1
73     psubw             m3, m2
74     packuswb          m6, m2
75     packuswb          m7, m3
76
77     movq              m0, [r0]
78     movq              m1, [r0+r2]
79     movhps            m0, [r0+r2*2]
80     movhps            m1, [r0+r3]
81     paddusb           m0, m4
82     paddusb           m1, m6
83     psubusb           m0, m5
84     psubusb           m1, m7
85     movq            [r0], m0
86     movq         [r0+r2], m1
87     movhps     [r0+2*r2], m0
88     movhps       [r0+r3], m1
89 %endmacro
90
91 %macro ADD_RES_SSE_16_32_8 3
92     mova             xm2, [r1+%1]
93     mova             xm6, [r1+%1+16]
94 %if cpuflag(avx2)
95     vinserti128       m2, m2, [r1+%1+32], 1
96     vinserti128       m6, m6, [r1+%1+48], 1
97 %endif
98 %if cpuflag(avx)
99     psubw             m1, m0, m2
100     psubw             m5, m0, m6
101 %else
102     mova              m1, m0
103     mova              m5, m0
104     psubw             m1, m2
105     psubw             m5, m6
106 %endif
107     packuswb          m2, m6
108     packuswb          m1, m5
109
110     mova             xm4, [r1+%1+mmsize*2]
111     mova             xm6, [r1+%1+mmsize*2+16]
112 %if cpuflag(avx2)
113     vinserti128       m4, m4, [r1+%1+96 ], 1
114     vinserti128       m6, m6, [r1+%1+112], 1
115 %endif
116 %if cpuflag(avx)
117     psubw             m3, m0, m4
118     psubw             m5, m0, m6
119 %else
120     mova              m3, m0
121     mova              m5, m0
122     psubw             m3, m4
123     psubw             m5, m6
124 %endif
125     packuswb          m4, m6
126     packuswb          m3, m5
127
128     paddusb           m2, [%2]
129     paddusb           m4, [%3]
130     psubusb           m2, m1
131     psubusb           m4, m3
132     mova            [%2], m2
133     mova            [%3], m4
134 %endmacro
135
136
137 %macro TRANSFORM_ADD_8 0
138 ; void ff_hevc_add_residual_8_8_<opt>(uint8_t *dst, int16_t *res, ptrdiff_t stride)
139 cglobal hevc_add_residual_8_8, 3, 4, 8
140     lea               r3, [r2*3]
141     ADD_RES_SSE_8_8
142     add               r1, 64
143     lea               r0, [r0+r2*4]
144     ADD_RES_SSE_8_8
145     RET
146
147 ; void ff_hevc_add_residual_16_8_<opt>(uint8_t *dst, int16_t *res, ptrdiff_t stride)
148 cglobal hevc_add_residual_16_8, 3, 5, 7
149     pxor                m0, m0
150     lea                 r3, [r2*3]
151     mov                r4d, 4
152 .loop:
153     ADD_RES_SSE_16_32_8  0, r0,      r0+r2
154     ADD_RES_SSE_16_32_8 64, r0+r2*2, r0+r3
155     add                 r1, 128
156     lea                 r0, [r0+r2*4]
157     dec                r4d
158     jg .loop
159     RET
160
161 ; void ff_hevc_add_residual_32_8_<opt>(uint8_t *dst, int16_t *res, ptrdiff_t stride)
162 cglobal hevc_add_residual_32_8, 3, 5, 7
163     pxor                m0, m0
164     mov                r4d, 16
165 .loop:
166     ADD_RES_SSE_16_32_8  0, r0,    r0+16
167     ADD_RES_SSE_16_32_8 64, r0+r2, r0+r2+16
168     add                 r1, 128
169     lea                 r0, [r0+r2*2]
170     dec                r4d
171     jg .loop
172     RET
173 %endmacro
174
175 INIT_XMM sse2
176 TRANSFORM_ADD_8
177 INIT_XMM avx
178 TRANSFORM_ADD_8
179
180 %if HAVE_AVX2_EXTERNAL
181 INIT_YMM avx2
182 ; void ff_hevc_add_residual_32_8_avx2(uint8_t *dst, int16_t *res, ptrdiff_t stride)
183 cglobal hevc_add_residual_32_8, 3, 5, 7
184     pxor                 m0, m0
185     lea                  r3, [r2*3]
186     mov                 r4d, 8
187 .loop:
188     ADD_RES_SSE_16_32_8   0, r0,      r0+r2
189     ADD_RES_SSE_16_32_8 128, r0+r2*2, r0+r3
190     add                  r1, 256
191     lea                  r0, [r0+r2*4]
192     dec                 r4d
193     jg .loop
194     RET
195 %endif
196
197 %macro ADD_RES_SSE_8_10 4
198     mova              m0, [%4]
199     mova              m1, [%4+16]
200     mova              m2, [%4+32]
201     mova              m3, [%4+48]
202     paddw             m0, [%1+0]
203     paddw             m1, [%1+%2]
204     paddw             m2, [%1+%2*2]
205     paddw             m3, [%1+%3]
206     CLIPW             m0, m4, m5
207     CLIPW             m1, m4, m5
208     CLIPW             m2, m4, m5
209     CLIPW             m3, m4, m5
210     mova          [%1+0], m0
211     mova         [%1+%2], m1
212     mova       [%1+%2*2], m2
213     mova         [%1+%3], m3
214 %endmacro
215
216 %macro ADD_RES_MMX_4_10 3
217     mova              m0, [%1+0]
218     mova              m1, [%1+%2]
219     paddw             m0, [%3]
220     paddw             m1, [%3+8]
221     CLIPW             m0, m2, m3
222     CLIPW             m1, m2, m3
223     mova          [%1+0], m0
224     mova         [%1+%2], m1
225 %endmacro
226
227 %macro ADD_RES_SSE_16_10 3
228     mova              m0, [%3]
229     mova              m1, [%3+16]
230     mova              m2, [%3+32]
231     mova              m3, [%3+48]
232     paddw             m0, [%1]
233     paddw             m1, [%1+16]
234     paddw             m2, [%1+%2]
235     paddw             m3, [%1+%2+16]
236     CLIPW             m0, m4, m5
237     CLIPW             m1, m4, m5
238     CLIPW             m2, m4, m5
239     CLIPW             m3, m4, m5
240     mova            [%1], m0
241     mova         [%1+16], m1
242     mova         [%1+%2], m2
243     mova      [%1+%2+16], m3
244 %endmacro
245
246 %macro ADD_RES_SSE_32_10 2
247     mova              m0, [%2]
248     mova              m1, [%2+16]
249     mova              m2, [%2+32]
250     mova              m3, [%2+48]
251
252     paddw             m0, [%1]
253     paddw             m1, [%1+16]
254     paddw             m2, [%1+32]
255     paddw             m3, [%1+48]
256     CLIPW             m0, m4, m5
257     CLIPW             m1, m4, m5
258     CLIPW             m2, m4, m5
259     CLIPW             m3, m4, m5
260     mova            [%1], m0
261     mova         [%1+16], m1
262     mova         [%1+32], m2
263     mova         [%1+48], m3
264 %endmacro
265
266 %macro ADD_RES_AVX2_16_10 4
267     mova              m0, [%4]
268     mova              m1, [%4+32]
269     mova              m2, [%4+64]
270     mova              m3, [%4+96]
271
272     paddw             m0, [%1+0]
273     paddw             m1, [%1+%2]
274     paddw             m2, [%1+%2*2]
275     paddw             m3, [%1+%3]
276
277     CLIPW             m0, m4, m5
278     CLIPW             m1, m4, m5
279     CLIPW             m2, m4, m5
280     CLIPW             m3, m4, m5
281     mova          [%1+0], m0
282     mova         [%1+%2], m1
283     mova       [%1+%2*2], m2
284     mova         [%1+%3], m3
285 %endmacro
286
287 %macro ADD_RES_AVX2_32_10 3
288     mova              m0, [%3]
289     mova              m1, [%3+32]
290     mova              m2, [%3+64]
291     mova              m3, [%3+96]
292
293     paddw             m0, [%1]
294     paddw             m1, [%1+32]
295     paddw             m2, [%1+%2]
296     paddw             m3, [%1+%2+32]
297
298     CLIPW             m0, m4, m5
299     CLIPW             m1, m4, m5
300     CLIPW             m2, m4, m5
301     CLIPW             m3, m4, m5
302     mova            [%1], m0
303     mova         [%1+32], m1
304     mova         [%1+%2], m2
305     mova      [%1+%2+32], m3
306 %endmacro
307
308 ; void ff_hevc_add_residual_<4|8|16|32>_10(pixel *dst, int16_t *block, ptrdiff_t stride)
309 INIT_MMX mmxext
310 cglobal hevc_add_residual_4_10, 3, 3, 6
311     pxor              m2, m2
312     mova              m3, [max_pixels_10]
313     ADD_RES_MMX_4_10  r0, r2, r1
314     add               r1, 16
315     lea               r0, [r0+2*r2]
316     ADD_RES_MMX_4_10  r0, r2, r1
317     RET
318
319 INIT_XMM sse2
320 cglobal hevc_add_residual_8_10, 3, 4, 6
321     pxor              m4, m4
322     mova              m5, [max_pixels_10]
323     lea               r3, [r2*3]
324
325     ADD_RES_SSE_8_10  r0, r2, r3, r1
326     lea               r0, [r0+r2*4]
327     add               r1, 64
328     ADD_RES_SSE_8_10  r0, r2, r3, r1
329     RET
330
331 cglobal hevc_add_residual_16_10, 3, 5, 6
332     pxor              m4, m4
333     mova              m5, [max_pixels_10]
334
335     mov              r4d, 8
336 .loop:
337     ADD_RES_SSE_16_10 r0, r2, r1
338     lea               r0, [r0+r2*2]
339     add               r1, 64
340     dec              r4d
341     jg .loop
342     RET
343
344 cglobal hevc_add_residual_32_10, 3, 5, 6
345     pxor              m4, m4
346     mova              m5, [max_pixels_10]
347
348     mov              r4d, 32
349 .loop:
350     ADD_RES_SSE_32_10 r0, r1
351     lea               r0, [r0+r2]
352     add               r1, 64
353     dec              r4d
354     jg .loop
355     RET
356
357 %if HAVE_AVX2_EXTERNAL
358 INIT_YMM avx2
359 cglobal hevc_add_residual_16_10, 3, 5, 6
360     pxor               m4, m4
361     mova               m5, [max_pixels_10]
362     lea                r3, [r2*3]
363
364     mov               r4d, 4
365 .loop:
366     ADD_RES_AVX2_16_10 r0, r2, r3, r1
367     lea                r0, [r0+r2*4]
368     add                r1, 128
369     dec               r4d
370     jg .loop
371     RET
372
373 cglobal hevc_add_residual_32_10, 3, 5, 6
374     pxor               m4, m4
375     mova               m5, [max_pixels_10]
376
377     mov               r4d, 16
378 .loop:
379     ADD_RES_AVX2_32_10 r0, r2, r1
380     lea                r0, [r0+r2*2]
381     add                r1, 128
382     dec               r4d
383     jg .loop
384     RET
385 %endif ;HAVE_AVX2_EXTERNAL