]> git.sesse.net Git - ffmpeg/blob - libavcodec/arm/hevcdsp_idct_neon.S
avcodec/hapdec : reorganize code before adding multi-texture decoding
[ffmpeg] / libavcodec / arm / hevcdsp_idct_neon.S
1 /*
2  * ARM NEON optimised IDCT functions for HEVC decoding
3  * Copyright (c) 2014 Seppo Tomperi <seppo.tomperi@vtt.fi>
4  * Copyright (c) 2017 Alexandra Hájková
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/arm/asm.S"
24
25 const trans, align=4
26         .short 64, 83, 64, 36
27         .short 89, 75, 50, 18
28         .short 90, 87, 80, 70
29         .short 57, 43, 25, 9
30         .short 90, 90, 88, 85
31         .short 82, 78, 73, 67
32         .short 61, 54, 46, 38
33         .short 31, 22, 13, 4
34 endconst
35
36 .macro clip10 in1, in2, c1, c2
37         vmax.s16        \in1, \in1, \c1
38         vmax.s16        \in2, \in2, \c1
39         vmin.s16        \in1, \in1, \c2
40         vmin.s16        \in2, \in2, \c2
41 .endm
42
43 function ff_hevc_add_residual_4x4_8_neon, export=1
44         vld1.16         {q0-q1}, [r1, :128]
45         vld1.32         d4[0], [r0, :32], r2
46         vld1.32         d4[1], [r0, :32], r2
47         vld1.32         d5[0], [r0, :32], r2
48         vld1.32         d5[1], [r0, :32], r2
49         sub             r0, r0, r2, lsl #2
50         vmovl.u8        q8, d4
51         vmovl.u8        q9, d5
52         vqadd.s16       q0, q0, q8
53         vqadd.s16       q1, q1, q9
54         vqmovun.s16     d0, q0
55         vqmovun.s16     d1, q1
56         vst1.32         d0[0], [r0, :32], r2
57         vst1.32         d0[1], [r0, :32], r2
58         vst1.32         d1[0], [r0, :32], r2
59         vst1.32         d1[1], [r0, :32], r2
60         bx              lr
61 endfunc
62
63 function ff_hevc_add_residual_4x4_10_neon, export=1
64         mov             r12, r0
65         vld1.16         {q0-q1}, [r1, :128]
66         vld1.16         d4, [r12, :64], r2
67         vld1.16         d5, [r12, :64], r2
68         vld1.16         d6, [r12, :64], r2
69         vqadd.s16       q0, q2
70         vld1.16         d7, [r12, :64], r2
71         vmov.s16        q12, #0
72         vqadd.s16       q1, q3
73         vmvn.s16        q13, #0xFC00 @ vmov.s16 #0x3FF
74         clip10          q0, q1, q12, q13
75         vst1.16         d0, [r0, :64], r2
76         vst1.16         d1, [r0, :64], r2
77         vst1.16         d2, [r0, :64], r2
78         vst1.16         d3, [r0, :64], r2
79         bx              lr
80 endfunc
81
82 function ff_hevc_add_residual_8x8_8_neon, export=1
83         add             r12, r0, r2
84         add             r2,  r2, r2
85         mov             r3,   #8
86 1:      subs            r3,   #2
87         vld1.8          {d16},   [r0,  :64]
88         vld1.8          {d17},   [r12, :64]
89         vmovl.u8        q9,   d16
90         vld1.16         {q0-q1}, [r1,  :128]!
91         vmovl.u8        q8,   d17
92         vqadd.s16       q0,   q9
93         vqadd.s16       q1,   q8
94         vqmovun.s16     d0,   q0
95         vqmovun.s16     d1,   q1
96         vst1.8          d0,   [r0,  :64], r2
97         vst1.8          d1,   [r12, :64], r2
98         bne             1b
99         bx              lr
100 endfunc
101
102 function ff_hevc_add_residual_8x8_10_neon, export=1
103         add             r12, r0, r2
104         add             r2,  r2, r2
105         mov             r3,  #8
106         vmov.s16        q12, #0
107         vmvn.s16        q13, #0xFC00 @ vmov.s16 #0x3FF
108 1:      subs            r3,  #2
109         vld1.16         {q0-q1}, [r1, :128]!
110         vld1.16         {q8},    [r0, :128]
111         vqadd.s16       q0, q8
112         vld1.16         {q9},    [r12, :128]
113         vqadd.s16       q1, q9
114         clip10          q0, q1, q12, q13
115         vst1.16         {q0}, [r0, :128], r2
116         vst1.16         {q1}, [r12, :128], r2
117         bne             1b
118         bx              lr
119 endfunc
120
121 function ff_hevc_add_residual_16x16_8_neon, export=1
122         mov             r3,  #16
123         add             r12, r0, r2
124         add             r2,  r2, r2
125 1:      subs            r3,  #2
126         vld1.8          {q8},     [r0, :128]
127         vld1.16         {q0, q1}, [r1, :128]!
128         vld1.8          {q11},    [r12, :128]
129         vld1.16         {q2, q3}, [r1, :128]!
130         vmovl.u8        q9,  d16
131         vmovl.u8        q10, d17
132         vmovl.u8        q12, d22
133         vmovl.u8        q13, d23
134         vqadd.s16       q0,  q9
135         vqadd.s16       q1,  q10
136         vqadd.s16       q2,  q12
137         vqadd.s16       q3,  q13
138         vqmovun.s16     d0,  q0
139         vqmovun.s16     d1,  q1
140         vqmovun.s16     d2,  q2
141         vqmovun.s16     d3,  q3
142         vst1.8          {q0},     [r0, :128], r2
143         vst1.8          {q1},     [r12, :128], r2
144         bne             1b
145         bx              lr
146 endfunc
147
148 function ff_hevc_add_residual_16x16_10_neon, export=1
149         mov             r3,  #16
150         vmov.s16        q12, #0
151         vmvn.s16        q13, #0xFC00 @ vmov.s16 #0x3FF
152         add             r12, r0, r2
153         add             r2,  r2, r2
154 1:      subs            r3,  #2
155         vld1.16         {q8-q9},   [r0, :128]
156         vld1.16         {q0, q1},  [r1, :128]!
157         vqadd.s16       q0, q8
158         vld1.16         {q10-q11}, [r12, :128]
159         vqadd.s16       q1, q9
160         vld1.16         {q2, q3},  [r1, :128]!
161         vqadd.s16       q2, q10
162         vqadd.s16       q3, q11
163         clip10          q0, q1, q12, q13
164         clip10          q2, q3, q12, q13
165         vst1.16         {q0-q1},   [r0, :128], r2
166         vst1.16         {q2-q3},   [r12, :128], r2
167         bne             1b
168         bx              lr
169 endfunc
170
171 function ff_hevc_add_residual_32x32_8_neon, export=1
172         vpush           {q4-q7}
173         add             r12, r0, r2
174         add             r2,  r2, r2
175         mov             r3,  #32
176 1:      subs            r3,  #2
177         vld1.8          {q12, q13}, [r0,  :128]
178         vmovl.u8        q8,  d24
179         vmovl.u8        q9,  d25
180         vld1.8          {q14, q15}, [r12, :128]
181         vmovl.u8        q10, d26
182         vmovl.u8        q11, d27
183         vmovl.u8        q12, d28
184         vldm            r1!, {q0-q7}
185         vmovl.u8        q13, d29
186         vmovl.u8        q14, d30
187         vmovl.u8        q15, d31
188         vqadd.s16       q0,  q8
189         vqadd.s16       q1,  q9
190         vqadd.s16       q2,  q10
191         vqadd.s16       q3,  q11
192         vqadd.s16       q4,  q12
193         vqadd.s16       q5,  q13
194         vqadd.s16       q6,  q14
195         vqadd.s16       q7,  q15
196         vqmovun.s16     d0,  q0
197         vqmovun.s16     d1,  q1
198         vqmovun.s16     d2,  q2
199         vqmovun.s16     d3,  q3
200         vqmovun.s16     d4,  q4
201         vqmovun.s16     d5,  q5
202         vst1.8          {q0, q1}, [r0, :128], r2
203         vqmovun.s16     d6,  q6
204         vqmovun.s16     d7,  q7
205         vst1.8          {q2, q3}, [r12, :128], r2
206         bne             1b
207         vpop            {q4-q7}
208         bx              lr
209 endfunc
210
211 function ff_hevc_add_residual_32x32_10_neon, export=1
212         mov             r3,  #32
213         add             r12, r0, #32
214         vmov.s16        q12, #0
215         vmvn.s16        q13, #0xFC00 @ vmov.s16 #0x3FF
216 1:      subs            r3,  #1
217         vldm            r1!, {q0-q3}
218         vld1.16         {q8, q9},   [r0, :128]
219         vld1.16         {q10, q11}, [r12, :128]
220         vqadd.s16       q0, q8
221         vqadd.s16       q1, q9
222         vqadd.s16       q2, q10
223         vqadd.s16       q3, q11
224         clip10          q0, q1, q12, q13
225         clip10          q2, q3, q12, q13
226         vst1.16         {q0-q1},   [r0, :128], r2
227         vst1.16         {q2-q3},   [r12, :128], r2
228         bne             1b
229         bx              lr
230 endfunc
231
232 /* uses registers q2 - q9 for temp values */
233 /* TODO: reorder */
234 .macro tr4_luma_shift r0, r1, r2, r3, shift
235         vaddl.s16   q5, \r0, \r2    // c0 = src0 + src2
236         vaddl.s16   q2, \r2, \r3    // c1 = src2 + src3
237         vsubl.s16   q4, \r0, \r3    // c2 = src0 - src3
238         vmull.s16   q6, \r1, d0[0]  // c3 = 74 * src1
239
240         vaddl.s16   q7, \r0, \r3    // src0 + src3
241         vsubw.s16   q7, q7, \r2     // src0 - src2 + src3
242         vmul.s32    q7, q7, d0[0]   // dst2 = 74 * (src0 - src2 + src3)
243
244         vmul.s32    q8, q5, d0[1]   // 29 * c0
245         vmul.s32    q9, q2, d1[0]   // 55 * c1
246         vadd.s32    q8, q9          // 29 * c0 + 55 * c1
247         vadd.s32    q8, q6          // dst0 = 29 * c0 + 55 * c1 + c3
248
249         vmul.s32    q2, q2, d0[1]   // 29 * c1
250         vmul.s32    q9, q4, d1[0]   // 55 * c2
251         vsub.s32    q9, q2          // 55 * c2 - 29 * c1
252         vadd.s32    q9, q6          // dst1 = 55 * c2 - 29 * c1 + c3
253
254         vmul.s32    q5, q5, d1[0]   // 55 * c0
255         vmul.s32    q4, q4, d0[1]   // 29 * c2
256         vadd.s32    q5, q4          // 55 * c0 + 29 * c2
257         vsub.s32    q5, q6          // dst3 = 55 * c0 + 29 * c2 - c3
258
259         vqrshrn.s32   \r0, q8, \shift
260         vqrshrn.s32   \r1, q9, \shift
261         vqrshrn.s32   \r2, q7, \shift
262         vqrshrn.s32   \r3, q5, \shift
263 .endm
264
265 function ff_hevc_transform_luma_4x4_neon_8, export=1
266         vpush       {d8-d15}
267         vld1.16     {q14, q15}, [r0]  // coeffs
268         ldr         r3, =0x4a  // 74
269         vmov.32     d0[0], r3
270         ldr         r3, =0x1d  // 29
271         vmov.32     d0[1], r3
272         ldr         r3, =0x37  // 55
273         vmov.32     d1[0], r3
274
275         tr4_luma_shift d28, d29, d30, d31, #7
276
277         vtrn.16     d28, d29
278         vtrn.16     d30, d31
279         vtrn.32     q14, q15
280
281         tr4_luma_shift d28, d29, d30, d31, #12
282
283         vtrn.16     d28, d29
284         vtrn.16     d30, d31
285         vtrn.32     q14, q15
286         vst1.16     {q14, q15}, [r0]
287         vpop        {d8-d15}
288         bx lr
289 endfunc
290
291 .macro idct_4x4_dc bitdepth
292 function ff_hevc_idct_4x4_dc_\bitdepth\()_neon, export=1
293         ldrsh           r1, [r0]
294         ldr             r2, =(1 << (13 - \bitdepth))
295         add             r1, #1
296         asr             r1, #1
297         add             r1, r2
298         asr             r1, #(14 - \bitdepth)
299         vdup.16         q0, r1
300         vdup.16         q1, r1
301         vst1.16         {q0, q1}, [r0, :128]
302         bx              lr
303 endfunc
304 .endm
305
306 .macro idct_8x8_dc bitdepth
307 function ff_hevc_idct_8x8_dc_\bitdepth\()_neon, export=1
308         ldrsh           r1, [r0]
309         ldr             r2, =(1 << (13 - \bitdepth))
310         add             r1, #1
311         asr             r1, #1
312         add             r1, r2
313         asr             r1, #(14 - \bitdepth)
314         vdup.16         q8, r1
315         vdup.16         q9, r1
316         vmov.16         q10, q8
317         vmov.16         q11, q8
318         vmov.16         q12, q8
319         vmov.16         q13, q8
320         vmov.16         q14, q8
321         vmov.16         q15, q8
322         vstm            r0, {q8-q15}
323         bx              lr
324 endfunc
325 .endm
326
327 .macro idct_16x16_dc bitdepth
328 function ff_hevc_idct_16x16_dc_\bitdepth\()_neon, export=1
329         ldrsh           r1, [r0]
330         ldr             r2, =(1 << (13 - \bitdepth))
331         add             r1, #1
332         asr             r1, #1
333         add             r1, r2
334         asr             r1, #(14 - \bitdepth)
335         vdup.16         q8, r1
336         vdup.16         q9, r1
337         vmov.16         q10, q8
338         vmov.16         q11, q8
339         vmov.16         q12, q8
340         vmov.16         q13, q8
341         vmov.16         q14, q8
342         vmov.16         q15, q8
343         vstm            r0!, {q8-q15}
344         vstm            r0!, {q8-q15}
345         vstm            r0!, {q8-q15}
346         vstm            r0, {q8-q15}
347         bx              lr
348 endfunc
349 .endm
350
351 .macro idct_32x32_dc bitdepth
352 function ff_hevc_idct_32x32_dc_\bitdepth\()_neon, export=1
353         ldrsh           r1, [r0]
354         ldr             r2, =(1 << (13 - \bitdepth))
355         add             r1, #1
356         asr             r1, #1
357         add             r1, r2
358         asr             r1, #(14 - \bitdepth)
359         mov             r3, #16
360         vdup.16         q8, r1
361         vdup.16         q9, r1
362         vmov.16         q10, q8
363         vmov.16         q11, q8
364         vmov.16         q12, q8
365         vmov.16         q13, q8
366         vmov.16         q14, q8
367         vmov.16         q15, q8
368 1:      subs            r3, #1
369         vstm            r0!, {q8-q15}
370         bne             1b
371         bx              lr
372 endfunc
373 .endm
374
375 .macro sum_sub out, in, c, op
376   .ifc \op, +
377         vmlal.s16       \out, \in, \c
378   .else
379         vmlsl.s16       \out, \in, \c
380   .endif
381 .endm
382
383 .macro tr_4x4 in0, in1, in2, in3, out0, out1, out2, out3, shift, tmp0, tmp1, tmp2, tmp3, tmp4
384          vshll.s16      \tmp0, \in0, #6
385          vmull.s16      \tmp2, \in1, d4[1]
386          vmov           \tmp1, \tmp0
387          vmull.s16      \tmp3, \in1, d4[3]
388          vmlal.s16      \tmp0, \in2, d4[0] @e0
389          vmlsl.s16      \tmp1, \in2, d4[0] @e1
390          vmlal.s16      \tmp2, \in3, d4[3] @o0
391          vmlsl.s16      \tmp3, \in3, d4[1] @o1
392
393          vadd.s32       \tmp4, \tmp0, \tmp2
394          vsub.s32       \tmp0, \tmp0, \tmp2
395          vadd.s32       \tmp2, \tmp1, \tmp3
396          vsub.s32       \tmp1, \tmp1, \tmp3
397          vqrshrn.s32    \out0, \tmp4, #\shift
398          vqrshrn.s32    \out3, \tmp0, #\shift
399          vqrshrn.s32    \out1, \tmp2, #\shift
400          vqrshrn.s32    \out2, \tmp1, #\shift
401 .endm
402
403 .macro tr_4x4_8 in0, in1, in2, in3, out0, out1, out2, out3, tmp0, tmp1, tmp2, tmp3
404          vshll.s16      \tmp0, \in0, #6
405          vld1.s16       {\in0}, [r1, :64]!
406          vmov           \tmp1, \tmp0
407          vmull.s16      \tmp2, \in1, \in0[1]
408          vmull.s16      \tmp3, \in1, \in0[3]
409          vmlal.s16      \tmp0, \in2, \in0[0] @e0
410          vmlsl.s16      \tmp1, \in2, \in0[0] @e1
411          vmlal.s16      \tmp2, \in3, \in0[3] @o0
412          vmlsl.s16      \tmp3, \in3, \in0[1] @o1
413
414          vld1.s16       {\in0}, [r1, :64]
415
416          vadd.s32       \out0, \tmp0, \tmp2
417          vadd.s32       \out1, \tmp1, \tmp3
418          vsub.s32       \out2, \tmp1, \tmp3
419          vsub.s32       \out3, \tmp0, \tmp2
420
421          sub            r1,  r1,  #8
422 .endm
423
424 @ Do a 4x4 transpose, using q registers for the subtransposes that don't
425 @ need to address the indiviudal d registers.
426 @ r0,r1 == rq0, r2,r3 == rq1
427 .macro transpose_4x4 rq0, rq1, r0, r1, r2, r3
428         vtrn.32         \rq0, \rq1
429         vtrn.16         \r0,  \r1
430         vtrn.16         \r2,  \r3
431 .endm
432
433 .macro idct_4x4 bitdepth
434 function ff_hevc_idct_4x4_\bitdepth\()_neon, export=1
435 @r0 - coeffs
436         vld1.s16        {q0-q1}, [r0, :128]
437
438         movrel          r1, trans
439         vld1.s16        {d4}, [r1, :64]
440
441         tr_4x4          d0, d1, d2, d3, d16, d17, d18, d19, 7, q10, q11, q12, q13, q0
442         transpose_4x4   q8, q9, d16, d17, d18, d19
443
444         tr_4x4          d16, d17, d18, d19, d0, d1, d2, d3, 20 - \bitdepth, q10, q11, q12, q13, q0
445         transpose_4x4   q0, q1, d0, d1, d2, d3
446         vst1.s16        {d0-d3}, [r0, :128]
447         bx lr
448 endfunc
449 .endm
450
451 .macro transpose8_4x4 r0, r1, r2, r3
452         vtrn.16         \r0,  \r1
453         vtrn.16         \r2,  \r3
454         vtrn.32         \r0,  \r2
455         vtrn.32         \r1,  \r3
456 .endm
457
458 .macro transpose_8x8 r0, r1, r2, r3, r4, r5, r6, r7, l0, l1, l2, l3, l4, l5, l6, l7
459         transpose8_4x4  \r0, \r1, \r2, \r3
460         transpose8_4x4  \r4, \r5, \r6, \r7
461
462         transpose8_4x4  \l0, \l1, \l2, \l3
463         transpose8_4x4  \l4, \l5, \l6, \l7
464 .endm
465
466 .macro tr_8x4 shift, in0, in1, in2, in3, in4, in5, in6, in7
467         tr_4x4_8        \in0, \in2, \in4, \in6, q8, q9, q10, q11, q12, q13, q14, q15
468
469         vmull.s16       q14, \in1, \in0[2]
470         vmull.s16       q12, \in1, \in0[0]
471         vmull.s16       q13, \in1, \in0[1]
472         sum_sub         q14, \in3, \in0[0], -
473         sum_sub         q12, \in3, \in0[1], +
474         sum_sub         q13, \in3, \in0[3], -
475
476         sum_sub         q14, \in5, \in0[3], +
477         sum_sub         q12, \in5, \in0[2], +
478         sum_sub         q13, \in5, \in0[0], -
479
480         sum_sub         q14, \in7, \in0[1], +
481         sum_sub         q12, \in7, \in0[3], +
482         sum_sub         q13, \in7, \in0[2], -
483
484         vadd.s32        q15, q10, q14
485         vsub.s32        q10, q10, q14
486         vqrshrn.s32     \in2, q15, \shift
487
488         vmull.s16       q15, \in1, \in0[3]
489         sum_sub         q15, \in3, \in0[2], -
490         sum_sub         q15, \in5, \in0[1], +
491         sum_sub         q15, \in7, \in0[0], -
492
493         vqrshrn.s32     \in5, q10,  \shift
494
495         vadd.s32        q10, q8, q12
496         vsub.s32        q8,  q8, q12
497         vadd.s32        q12, q9, q13
498         vsub.s32        q9,  q9, q13
499         vadd.s32        q14, q11, q15
500         vsub.s32        q11, q11, q15
501
502         vqrshrn.s32     \in0, q10, \shift
503         vqrshrn.s32     \in7, q8,  \shift
504         vqrshrn.s32     \in1, q12, \shift
505         vqrshrn.s32     \in6, q9,  \shift
506         vqrshrn.s32     \in3, q14, \shift
507         vqrshrn.s32     \in4, q11, \shift
508 .endm
509
510 .macro idct_8x8 bitdepth
511 function ff_hevc_idct_8x8_\bitdepth\()_neon, export=1
512 @r0 - coeffs
513         vpush           {q4-q7}
514
515         mov             r1,  r0
516         mov             r2,  #64
517         add             r3,  r0,  #32
518         vld1.s16        {q0-q1}, [r1,:128], r2
519         vld1.s16        {q2-q3}, [r3,:128], r2
520         vld1.s16        {q4-q5}, [r1,:128], r2
521         vld1.s16        {q6-q7}, [r3,:128], r2
522
523         movrel          r1, trans
524
525         tr_8x4          7, d0, d2, d4, d6, d8, d10, d12, d14
526         tr_8x4          7, d1, d3, d5, d7, d9, d11, d13, d15
527
528         @ Transpose each 4x4 block, and swap how d4-d7 and d8-d11 are used.
529         @ Layout before:
530         @ d0  d1
531         @ d2  d3
532         @ d4  d5
533         @ d6  d7
534         @ d8  d9
535         @ d10 d11
536         @ d12 d13
537         @ d14 d15
538         transpose_8x8   d0, d2, d4, d6, d8, d10, d12, d14, d1, d3, d5, d7, d9, d11, d13, d15
539         @ Now the layout is:
540         @ d0  d8
541         @ d2  d10
542         @ d4  d12
543         @ d6  d14
544         @ d1  d9
545         @ d3  d11
546         @ d5  d13
547         @ d7  d15
548
549         tr_8x4          20 - \bitdepth, d0, d2, d4, d6, d1, d3, d5, d7
550         vswp            d0, d8
551         tr_8x4          20 - \bitdepth, d0, d10, d12, d14, d9, d11, d13, d15
552         vswp            d0, d8
553
554         transpose_8x8   d0, d2, d4, d6, d8, d10, d12, d14, d1, d3, d5, d7, d9, d11, d13, d15
555
556         mov             r1,  r0
557         mov             r2,  #64
558         add             r3,  r0,  #32
559         vst1.s16        {q0-q1}, [r1,:128], r2
560         vst1.s16        {q2-q3}, [r3,:128], r2
561         vst1.s16        {q4-q5}, [r1,:128], r2
562         vst1.s16        {q6-q7}, [r3,:128], r2
563
564         vpop            {q4-q7}
565         bx              lr
566 endfunc
567 .endm
568
569 .macro butterfly e, o, tmp_p, tmp_m
570         vadd.s32        \tmp_p, \e, \o
571         vsub.s32        \tmp_m, \e, \o
572 .endm
573
574 .macro tr16_8x4 in0, in1, in2, in3, in4, in5, in6, in7, offset
575         tr_4x4_8        \in0, \in2, \in4, \in6, q8, q9, q10, q11, q12, q13, q14, q15
576
577         vmull.s16       q12, \in1, \in0[0]
578         vmull.s16       q13, \in1, \in0[1]
579         vmull.s16       q14, \in1, \in0[2]
580         vmull.s16       q15, \in1, \in0[3]
581         sum_sub         q12, \in3, \in0[1], +
582         sum_sub         q13, \in3, \in0[3], -
583         sum_sub         q14, \in3, \in0[0], -
584         sum_sub         q15, \in3, \in0[2], -
585
586         sum_sub         q12, \in5, \in0[2], +
587         sum_sub         q13, \in5, \in0[0], -
588         sum_sub         q14, \in5, \in0[3], +
589         sum_sub         q15, \in5, \in0[1], +
590
591         sum_sub         q12, \in7, \in0[3], +
592         sum_sub         q13, \in7, \in0[2], -
593         sum_sub         q14, \in7, \in0[1], +
594         sum_sub         q15, \in7, \in0[0], -
595
596         butterfly       q8,  q12, q0, q7
597         butterfly       q9,  q13, q1, q6
598         butterfly       q10, q14, q2, q5
599         butterfly       q11, q15, q3, q4
600         add             r4,  sp,  #\offset
601         vst1.s32        {q0-q1}, [r4, :128]!
602         vst1.s32        {q2-q3}, [r4, :128]!
603         vst1.s32        {q4-q5}, [r4, :128]!
604         vst1.s32        {q6-q7}, [r4, :128]
605 .endm
606
607 .macro load16 in0, in1, in2, in3, in4, in5, in6, in7
608         vld1.s16        {\in0}, [r1, :64], r2
609         vld1.s16        {\in1}, [r3, :64], r2
610         vld1.s16        {\in2}, [r1, :64], r2
611         vld1.s16        {\in3}, [r3, :64], r2
612         vld1.s16        {\in4}, [r1, :64], r2
613         vld1.s16        {\in5}, [r3, :64], r2
614         vld1.s16        {\in6}, [r1, :64], r2
615         vld1.s16        {\in7}, [r3, :64], r2
616 .endm
617
618 .macro add_member in, t0, t1, t2, t3, t4, t5, t6, t7, op0, op1, op2, op3, op4, op5, op6, op7
619         sum_sub q5,     \in, \t0, \op0
620         sum_sub q6,     \in, \t1, \op1
621         sum_sub q7,     \in, \t2, \op2
622         sum_sub q8,     \in, \t3, \op3
623         sum_sub q9,     \in, \t4, \op4
624         sum_sub q10,    \in, \t5, \op5
625         sum_sub q11,    \in, \t6, \op6
626         sum_sub q12,    \in, \t7, \op7
627 .endm
628
629 .macro butterfly16 in0, in1, in2, in3, in4, in5, in6, in7
630         vadd.s32        q4, \in0, \in1
631         vsub.s32        \in0, \in0, \in1
632         vadd.s32        \in1, \in2, \in3
633         vsub.s32        \in2, \in2, \in3
634         vadd.s32        \in3, \in4, \in5
635         vsub.s32        \in4, \in4, \in5
636         vadd.s32        \in5, \in6, \in7
637         vsub.s32        \in6, \in6, \in7
638 .endm
639
640 .macro store16 in0, in1, in2, in3, in4, in5, in6, in7, rx
641         vst1.s16        \in0, [r1, :64], r2
642         vst1.s16        \in1, [r3, :64], \rx
643         vst1.s16        \in2, [r1, :64], r2
644         vst1.s16        \in3, [r3, :64], \rx
645         vst1.s16        \in4, [r1, :64], r2
646         vst1.s16        \in5, [r3, :64], \rx
647         vst1.s16        \in6, [r1, :64], r2
648         vst1.s16        \in7, [r3, :64], \rx
649 .endm
650
651 .macro scale out0, out1, out2, out3, out4, out5, out6, out7, in0, in1, in2, in3, in4, in5, in6, in7, shift
652         vqrshrn.s32     \out0, \in0, \shift
653         vqrshrn.s32     \out1, \in1, \shift
654         vqrshrn.s32     \out2, \in2, \shift
655         vqrshrn.s32     \out3, \in3, \shift
656         vqrshrn.s32     \out4, \in4, \shift
657         vqrshrn.s32     \out5, \in5, \shift
658         vqrshrn.s32     \out6, \in6, \shift
659         vqrshrn.s32     \out7, \in7, \shift
660 .endm
661
662 @stores in1, in2, in4, in6 ascending from off1 and
663 @stores in1, in3, in5, in7 descending from off2
664 .macro store_to_stack off1, off2, in0, in2, in4, in6, in7, in5, in3, in1
665         add             r1, sp, #\off1
666         add             r3, sp, #\off2
667         mov             r2, #-16
668         vst1.s32        {\in0}, [r1, :128]!
669         vst1.s32        {\in1}, [r3, :128], r2
670         vst1.s32        {\in2}, [r1, :128]!
671         vst1.s32        {\in3}, [r3, :128], r2
672         vst1.s32        {\in4}, [r1, :128]!
673         vst1.s32        {\in5}, [r3, :128], r2
674         vst1.s32        {\in6}, [r1, :128]
675         vst1.s32        {\in7}, [r3, :128]
676 .endm
677
678 .macro tr_16x4 name, shift, offset, step
679 function func_tr_16x4_\name
680         mov             r1,  r5
681         add             r3, r5, #(\step * 64)
682         mov             r2, #(\step * 128)
683         load16          d0, d1, d2, d3, d4, d5, d6, d7
684         movrel          r1, trans
685
686         tr16_8x4        d0, d1, d2, d3, d4, d5, d6, d7, \offset
687
688         add             r1,  r5, #(\step * 32)
689         add             r3,  r5, #(\step * 3 *32)
690         mov             r2,  #(\step * 128)
691         load16          d8, d9, d2, d3, d4, d5, d6, d7
692         movrel          r1, trans + 16
693         vld1.s16        {q0}, [r1, :128]
694         vmull.s16       q5, d8, d0[0]
695         vmull.s16       q6, d8, d0[1]
696         vmull.s16       q7, d8, d0[2]
697         vmull.s16       q8, d8, d0[3]
698         vmull.s16       q9, d8, d1[0]
699         vmull.s16       q10, d8, d1[1]
700         vmull.s16       q11, d8, d1[2]
701         vmull.s16       q12, d8, d1[3]
702
703         add_member      d9, d0[1], d1[0], d1[3], d1[1], d0[2], d0[0], d0[3], d1[2], +, +, +, -, -, -, -, -
704         add_member      d2, d0[2], d1[3], d0[3], d0[1], d1[2], d1[0], d0[0], d1[1], +, +, -, -, -, +, +, +
705         add_member      d3, d0[3], d1[1], d0[1], d1[3], d0[0], d1[2], d0[2], d1[0], +, -, -, +, +, +, -, -
706         add_member      d4, d1[0], d0[2], d1[2], d0[0], d1[3], d0[1], d1[1], d0[3], +, -, -, +, -, -, +, +
707         add_member      d5, d1[1], d0[0], d1[0], d1[2], d0[1], d0[3], d1[3], d0[2], +, -, +, +, -, +, +, -
708         add_member      d6, d1[2], d0[3], d0[0], d0[2], d1[1], d1[3], d1[0], d0[1], +, -, +, -, +, +, -, +
709         add_member      d7, d1[3], d1[2], d1[1], d1[0], d0[3], d0[2], d0[1], d0[0], +, -, +, -, +, -, +, -
710
711         add             r4, sp, #\offset
712         vld1.s32        {q0-q1}, [r4, :128]!
713         vld1.s32        {q2-q3}, [r4, :128]!
714
715         butterfly16     q0, q5, q1, q6, q2, q7, q3, q8
716     .if \shift > 0
717         scale           d26, d27, d28, d29, d30, d31, d16, d17, q4, q0, q5, q1, q6, q2, q7, q3, \shift
718         transpose8_4x4  d26, d28, d30, d16
719         transpose8_4x4  d17, d31, d29, d27
720         mov             r1, r6
721         add             r3, r6, #(24 +3*32)
722         mov             r2, #32
723         mov             r4, #-32
724         store16         d26, d27, d28, d29, d30, d31, d16, d17, r4
725     .else
726         store_to_stack  \offset, (\offset + 240), q4, q5, q6, q7, q3, q2, q1, q0
727     .endif
728
729         add             r4, sp, #(\offset + 64)
730         vld1.s32        {q0-q1}, [r4, :128]!
731         vld1.s32        {q2-q3}, [r4, :128]
732         butterfly16     q0, q9, q1, q10, q2, q11, q3, q12
733     .if \shift > 0
734         scale           d26, d27, d28, d29, d30, d31, d8, d9, q4, q0, q9, q1, q10, q2, q11, q3, \shift
735         transpose8_4x4  d26, d28, d30, d8
736         transpose8_4x4  d9, d31, d29, d27
737
738         add             r1, r6, #8
739         add             r3, r6, #(16 + 3 * 32)
740         mov             r2, #32
741         mov             r4, #-32
742         store16         d26, d27, d28, d29, d30, d31, d8, d9, r4
743     .else
744         store_to_stack (\offset + 64), (\offset + 176), q4, q9, q10, q11, q3, q2, q1, q0
745     .endif
746
747         bx              lr
748 endfunc
749 .endm
750
751 .macro idct_16x16 bitdepth
752 function ff_hevc_idct_16x16_\bitdepth\()_neon, export=1
753 @r0 - coeffs
754         push            {r4-r7, lr}
755         vpush           {q4-q7}
756
757         @ Align the stack, allocate a temp buffer
758 T       mov             r7,  sp
759 T       and             r7,  r7,  #15
760 A       and             r7,  sp,  #15
761         add             r7,  r7,  #640
762         sub             sp,  sp,  r7
763
764 .irp i, 0, 1, 2, 3
765         add             r5, r0, #(8 * \i)
766         add             r6, sp, #(8 * \i * 16)
767         bl              func_tr_16x4_firstpass
768 .endr
769
770 .irp i, 0, 1, 2, 3
771         add             r5, sp, #(8 * \i)
772         add             r6, r0, #(8 * \i * 16)
773         bl              func_tr_16x4_secondpass_\bitdepth
774 .endr
775
776         add             sp,  sp,  r7
777
778         vpop            {q4-q7}
779         pop             {r4-r7, pc}
780 endfunc
781 .endm
782
783 .macro load32
784         add             r1,  r5, #64
785         add             r3,  r1, #128
786         mov             r2,  #256
787         vld1.s16        {d4}, [r1, :64], r2
788         vld1.s16        {d5}, [r3, :64], r2
789         vld1.s16        {d6}, [r1, :64], r2
790         vld1.s16        {d7}, [r3, :64], r2
791         vld1.s16        {d8}, [r1, :64], r2
792         vld1.s16        {d9}, [r3, :64], r2
793         vld1.s16        {d10}, [r1, :64], r2
794         vld1.s16        {d11}, [r3, :64], r2
795         vld1.s16        {d12}, [r1, :64], r2
796         vld1.s16        {d13}, [r3, :64], r2
797         vld1.s16        {d14}, [r1, :64], r2
798         vld1.s16        {d15}, [r3, :64], r2
799         vld1.s16        {d16}, [r1, :64], r2
800         vld1.s16        {d17}, [r3, :64], r2
801         vld1.s16        {d18}, [r1, :64], r2
802         vld1.s16        {d19}, [r3, :64], r2
803 .endm
804
805 .macro add_member32 in, t0, t1, t2, t3, op0, op1, op2, op3
806         sum_sub q10,     \in, \t0, \op0
807         sum_sub q11,     \in, \t1, \op1
808         sum_sub q12,     \in, \t2, \op2
809         sum_sub q13,     \in, \t3, \op3
810 .endm
811
812 .macro butterfly32 in0, in1, in2, in3
813         vadd.s32        q1, \in0, \in1
814         vsub.s32        \in0, \in0, \in1
815         vadd.s32        \in1, \in2, \in3
816         vsub.s32        \in2, \in2, \in3
817 .endm
818
819 .macro scale32 out0, out1, out2, out3, in0, in1, in2, in3, shift
820         vqrshrn.s32     \out0, \in0, \shift
821         vqrshrn.s32     \out1, \in1, \shift
822         vqrshrn.s32     \out2, \in2, \shift
823         vqrshrn.s32     \out3, \in3, \shift
824 .endm
825
826 .macro multiply in
827         vmull.s16       q10, d4, \in[0]
828         vmull.s16       q11, d4, \in[1]
829         vmull.s16       q12, d4, \in[2]
830         vmull.s16       q13, d4, \in[3]
831 .endm
832
833 .macro scale_store shift
834         vld1.s16        {q14-q15}, [r4, :128]!
835         butterfly32     q14, q10, q15, q11
836         scale32         d22, d23, d20, d21, q1, q14, q10, q15, \shift
837
838         vld1.s16        {q14-q15}, [r4, :128]!
839         butterfly32     q14, q12, q15, q13
840         scale32         d2, d3, d28, d29, q1, q14, q12, q15, \shift
841         transpose8_4x4  d22, d20, d2, d28
842         transpose8_4x4  d29, d3, d21, d23
843         store16         d22, d23, d20, d21, d2, d3, d28, d29, r8
844
845         @ reload multiplication coefficiens to q1
846         vld1.s16        {q1}, [r9, :128]
847 .endm
848
849 function tr_block1
850         multiply        d0
851         add_member32    d5,  d0[1], d1[0], d1[3], d2[2], +, +, +, +
852         add_member32    d6,  d0[2], d1[3], d3[0], d3[2], +, +, +, -
853         add_member32    d7,  d0[3], d2[2], d3[2], d1[3], +, +, -, -
854         add_member32    d8,  d1[0], d3[1], d2[1], d0[0], +, +, -, -
855         add_member32    d9,  d1[1], d3[3], d1[0], d1[2], +, -, -, -
856         add_member32    d10, d1[2], d3[0], d0[0], d3[1], +, -, -, -
857         add_member32    d11, d1[3], d2[1], d1[1], d2[3], +, -, -, +
858         add_member32    d12, d2[0], d1[2], d2[2], d1[0], +, -, -, +
859         add_member32    d13, d2[1], d0[3], d3[3], d0[2], +, -, -, +
860         add_member32    d14, d2[2], d0[1], d2[3], d2[1], +, -, +, +
861         add_member32    d15, d2[3], d0[2], d1[2], d3[3], +, -, +, -
862         add_member32    d16, d3[0], d1[1], d0[1], d2[0], +, -, +, -
863         add_member32    d17, d3[1], d2[0], d0[3], d0[1], +, -, +, -
864         add_member32    d18, d3[2], d2[3], d2[0], d1[1], +, -, +, -
865         add_member32    d19, d3[3], d3[2], d3[1], d3[0], +, -, +, -
866         bx              lr
867 endfunc
868
869 function tr_block2
870         multiply        d1
871         add_member32    d5,  d3[1], d3[3], d3[0], d2[1], +, -, -, -
872         add_member32    d6,  d2[1], d1[0], d0[0], d1[1], -, -, -, -
873         add_member32    d7,  d0[0], d1[2], d3[1], d2[3], -, -, -, +
874         add_member32    d8,  d2[0], d3[2], d1[1], d0[3], -, +, +, +
875         add_member32    d9,  d3[2], d0[3], d1[3], d3[1], +, +, +, -
876         add_member32    d10, d1[1], d1[3], d2[3], d0[0], +, +, -, -
877         add_member32    d11, d0[3], d3[1], d0[1], d3[3], +, -, -, +
878         add_member32    d12, d3[0], d0[2], d3[2], d0[1], +, -, -, +
879         add_member32    d13, d2[2], d2[0], d1[0], d3[2], -, -, +, +
880         add_member32    d14, d0[1], d3[0], d2[0], d0[2], -, +, +, -
881         add_member32    d15, d1[3], d0[1], d2[2], d3[0], -, +, -, -
882         add_member32    d16, d3[3], d2[1], d0[2], d1[0], +, +, -, +
883         add_member32    d17, d1[2], d2[3], d3[3], d2[2], +, -, -, +
884         add_member32    d18, d0[2], d0[1], d0[3], d1[2], +, -, +, -
885         add_member32    d19, d2[3], d2[2], d2[1], d2[0], +, -, +, -
886         bx              lr
887 endfunc
888
889 function tr_block3
890         multiply        d2
891         add_member32    d5,  d1[2], d0[3], d0[0], d0[2], -, -, -, -
892         add_member32    d6,  d2[2], d3[3], d2[3], d1[2], -, -, +, +
893         add_member32    d7,  d1[0], d0[2], d2[1], d3[3], +, +, +, -
894         add_member32    d8,  d3[0], d2[2], d0[1], d1[3], +, -, -, -
895         add_member32    d9,  d0[2], d2[0], d3[0], d0[0], -, -, +, +
896         add_member32    d10, d3[2], d1[0], d2[0], d2[2], -, +, +, -
897         add_member32    d11, d0[0], d3[2], d0[2], d3[0], +, +, -, -
898         add_member32    d12, d3[3], d0[1], d3[1], d0[3], -, -, +, +
899         add_member32    d13, d0[1], d2[3], d1[3], d1[1], -, +, +, -
900         add_member32    d14, d3[1], d1[3], d0[3], d3[2], +, +, -, +
901         add_member32    d15, d0[3], d1[1], d3[2], d2[0], +, -, +, +
902         add_member32    d16, d2[3], d3[1], d1[2], d0[1], -, -, +, -
903         add_member32    d17, d1[1], d0[0], d1[0], d2[1], -, +, -, +
904         add_member32    d18, d2[1], d3[0], d3[3], d3[1], +, -, +, +
905         add_member32    d19, d1[3], d1[2], d1[1], d1[0], +, -, +, -
906         bx              lr
907 endfunc
908
909 function tr_block4
910         multiply        d3
911         add_member32    d5,  d1[1], d2[0], d2[3], d3[2], -, -, -, -
912         add_member32    d6,  d0[0], d0[3], d2[0], d3[1], +, +, +, +
913         add_member32    d7,  d2[0], d0[0], d1[1], d3[0], -, -, -, -
914         add_member32    d8,  d3[3], d1[2], d0[2], d2[3], +, +, +, +
915         add_member32    d9,  d2[1], d2[3], d0[0], d2[2], +, -, -, -
916         add_member32    d10, d0[2], d3[3], d0[3], d2[1], -, -, +, +
917         add_member32    d11, d1[0], d2[2], d1[2], d2[0], +, +, -, -
918         add_member32    d12, d2[3], d1[1], d2[1], d1[3], -, -, +, +
919         add_member32    d13, d3[1], d0[1], d3[0], d1[2], -, +, -, -
920         add_member32    d14, d1[2], d1[0], d3[3], d1[1], +, -, +, +
921         add_member32    d15, d0[1], d2[1], d3[1], d1[0], -, +, +, -
922         add_member32    d16, d1[3], d3[2], d2[2], d0[3], +, -, -, +
923         add_member32    d17, d3[2], d3[0], d1[3], d0[2], -, -, +, -
924         add_member32    d18, d2[2], d1[3], d1[0], d0[1], -, +, -, +
925         add_member32    d19, d0[3], d0[2], d0[1], d0[0], +, -, +, -
926         bx              lr
927 endfunc
928
929 .macro tr_32x4 name, shift
930 function func_tr_32x4_\name
931         mov             r10, lr
932         bl              func_tr_16x4_noscale
933
934         load32
935         movrel          r9, trans + 32
936         vld1.s16        {q0}, [r9, :128]!
937         vld1.s16        {q1}, [r9, :128]
938
939         bl              tr_block1
940
941         add             r4, sp, #2048
942         vld1.s16        {q14-q15}, [r4, :128]!
943         butterfly32     q14, q10, q15, q11
944         scale32         d22, d23, d20, d21, q1, q14, q10, q15, \shift
945
946         vld1.s16        {q14-q15}, [r4, :128]!
947         butterfly32     q14, q12, q15, q13
948         scale32         d2, d3, d28, d29, q1, q14, q12, q15, \shift
949
950         transpose8_4x4  d22, d20, d2, d28
951         transpose8_4x4  d29, d3, d21, d23
952         mov             r1, r11
953         mov             r2, #64
954         mov             r8, #-64
955         add             r3, r11, #(56 + 3 * 64)
956         store16         d22, d23, d20, d21, d2, d3, d28, d29, r8
957
958         @ reload multiplication coefficiens to q1
959         vld1.s16        {q1}, [r9, :128]
960
961         bl              tr_block2
962         add             r1, r11, #8
963         add             r3, r11, #(48 + 3 * 64)
964         mov             r2, #64
965         mov             r8, #-64
966         scale_store     \shift
967
968         bl              tr_block3
969         add             r1, r11, #16
970         add             r3, r11, #(40 + 3 * 64)
971         mov             r2, #64
972         mov             r8, #-64
973         scale_store     \shift
974
975         bl              tr_block4
976         add             r1, r11, #24
977         add             r3, r11, #(32 + 3 * 64)
978         mov             r2, #64
979         mov             r8, #-64
980         scale_store     \shift
981
982         bx               r10
983 endfunc
984 .endm
985
986 .macro idct_32x32 bitdepth
987 function ff_hevc_idct_32x32_\bitdepth\()_neon, export=1
988 @r0 - coeffs
989         push            {r4-r11, lr}
990         vpush           {q4-q7}
991
992         @ Align the stack, allocate a temp buffer
993 T       mov             r7,  sp
994 T       and             r7,  r7,  #15
995 A       and             r7,  sp,  #15
996         add             r7,  r7,  #2432
997         sub             sp,  sp,  r7
998
999 .irp i, 0, 1, 2, 3, 4, 5, 6, 7
1000         add             r5, r0, #(8 * \i)
1001         add             r11, sp, #(8 * \i * 32)
1002         bl              func_tr_32x4_firstpass
1003 .endr
1004
1005 .irp i, 0, 1, 2, 3, 4, 5, 6, 7
1006         add             r5, sp, #(8 * \i)
1007         add             r11, r0, #(8 * \i * 32)
1008         bl              func_tr_32x4_secondpass_\bitdepth
1009 .endr
1010
1011         add             sp,  sp,  r7
1012         vpop            {q4-q7}
1013         pop             {r4-r11, pc}
1014 endfunc
1015 .endm
1016
1017 tr_16x4 firstpass, 7, 512, 1
1018 tr_16x4 secondpass_8, 20 - 8, 512, 1
1019 tr_16x4 secondpass_10, 20 - 10, 512, 1
1020 tr_16x4 noscale, 0, 2048, 4
1021 .ltorg
1022 tr_32x4 firstpass, 7
1023 tr_32x4 secondpass_8, 20 - 8
1024 tr_32x4 secondpass_10, 20 - 10
1025 .ltorg
1026
1027 idct_4x4 8
1028 idct_4x4_dc 8
1029 idct_4x4 10
1030 idct_4x4_dc 10
1031 idct_8x8 8
1032 idct_8x8_dc 8
1033 idct_8x8 10
1034 idct_8x8_dc 10
1035 idct_16x16 8
1036 idct_16x16_dc 8
1037 idct_16x16 10
1038 idct_16x16_dc 10
1039 idct_32x32 8
1040 idct_32x32_dc 8
1041 idct_32x32 10
1042 idct_32x32_dc 10