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á
6 * This file is part of FFmpeg.
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.
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.
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
23 #include "libavutil/arm/asm.S"
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
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
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
63 function ff_hevc_add_residual_4x4_10_neon, export=1
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
70 vld1.16 d7, [r12, :64], r2
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
82 function ff_hevc_add_residual_8x8_8_neon, export=1
87 vld1.8 {d16}, [r0, :64]
88 vld1.8 {d17}, [r12, :64]
90 vld1.16 {q0-q1}, [r1, :128]!
96 vst1.8 d0, [r0, :64], r2
97 vst1.8 d1, [r12, :64], r2
102 function ff_hevc_add_residual_8x8_10_neon, export=1
107 vmvn.s16 q13, #0xFC00 @ vmov.s16 #0x3FF
109 vld1.16 {q0-q1}, [r1, :128]!
110 vld1.16 {q8}, [r0, :128]
112 vld1.16 {q9}, [r12, :128]
114 clip10 q0, q1, q12, q13
115 vst1.16 {q0}, [r0, :128], r2
116 vst1.16 {q1}, [r12, :128], r2
121 function ff_hevc_add_residual_16x16_8_neon, export=1
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]!
142 vst1.8 {q0}, [r0, :128], r2
143 vst1.8 {q1}, [r12, :128], r2
148 function ff_hevc_add_residual_16x16_10_neon, export=1
151 vmvn.s16 q13, #0xFC00 @ vmov.s16 #0x3FF
155 vld1.16 {q8-q9}, [r0, :128]
156 vld1.16 {q0, q1}, [r1, :128]!
158 vld1.16 {q10-q11}, [r12, :128]
160 vld1.16 {q2, q3}, [r1, :128]!
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
171 function ff_hevc_add_residual_32x32_8_neon, export=1
177 vld1.8 {q12, q13}, [r0, :128]
180 vld1.8 {q14, q15}, [r12, :128]
202 vst1.8 {q0, q1}, [r0, :128], r2
205 vst1.8 {q2, q3}, [r12, :128], r2
211 function ff_hevc_add_residual_32x32_10_neon, export=1
215 vmvn.s16 q13, #0xFC00 @ vmov.s16 #0x3FF
218 vld1.16 {q8, q9}, [r0, :128]
219 vld1.16 {q10, q11}, [r12, :128]
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
232 /* uses registers q2 - q9 for temp values */
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
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)
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
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
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
259 vqrshrn.s32 \r0, q8, \shift
260 vqrshrn.s32 \r1, q9, \shift
261 vqrshrn.s32 \r2, q7, \shift
262 vqrshrn.s32 \r3, q5, \shift
265 function ff_hevc_transform_luma_4x4_neon_8, export=1
267 vld1.16 {q14, q15}, [r0] // coeffs
275 tr4_luma_shift d28, d29, d30, d31, #7
281 tr4_luma_shift d28, d29, d30, d31, #12
286 vst1.16 {q14, q15}, [r0]
291 .macro idct_4x4_dc bitdepth
292 function ff_hevc_idct_4x4_dc_\bitdepth\()_neon, export=1
294 ldr r2, =(1 << (13 - \bitdepth))
298 asr r1, #(14 - \bitdepth)
301 vst1.16 {q0, q1}, [r0, :128]
306 .macro idct_8x8_dc bitdepth
307 function ff_hevc_idct_8x8_dc_\bitdepth\()_neon, export=1
309 ldr r2, =(1 << (13 - \bitdepth))
313 asr r1, #(14 - \bitdepth)
327 .macro idct_16x16_dc bitdepth
328 function ff_hevc_idct_16x16_dc_\bitdepth\()_neon, export=1
330 ldr r2, =(1 << (13 - \bitdepth))
334 asr r1, #(14 - \bitdepth)
351 .macro idct_32x32_dc bitdepth
352 function ff_hevc_idct_32x32_dc_\bitdepth\()_neon, export=1
354 ldr r2, =(1 << (13 - \bitdepth))
358 asr r1, #(14 - \bitdepth)
375 .macro sum_sub out, in, c, op
377 vmlal.s16 \out, \in, \c
379 vmlsl.s16 \out, \in, \c
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]
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
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
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]!
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
414 vld1.s16 {\in0}, [r1, :64]
416 vadd.s32 \out0, \tmp0, \tmp2
417 vadd.s32 \out1, \tmp1, \tmp3
418 vsub.s32 \out2, \tmp1, \tmp3
419 vsub.s32 \out3, \tmp0, \tmp2
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
433 .macro idct_4x4 bitdepth
434 function ff_hevc_idct_4x4_\bitdepth\()_neon, export=1
436 vld1.s16 {q0-q1}, [r0, :128]
439 vld1.s16 {d4}, [r1, :64]
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
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]
451 .macro transpose8_4x4 r0, r1, r2, r3
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
462 transpose8_4x4 \l0, \l1, \l2, \l3
463 transpose8_4x4 \l4, \l5, \l6, \l7
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
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], -
476 sum_sub q14, \in5, \in0[3], +
477 sum_sub q12, \in5, \in0[2], +
478 sum_sub q13, \in5, \in0[0], -
480 sum_sub q14, \in7, \in0[1], +
481 sum_sub q12, \in7, \in0[3], +
482 sum_sub q13, \in7, \in0[2], -
484 vadd.s32 q15, q10, q14
485 vsub.s32 q10, q10, q14
486 vqrshrn.s32 \in2, q15, \shift
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], -
493 vqrshrn.s32 \in5, q10, \shift
495 vadd.s32 q10, q8, q12
497 vadd.s32 q12, q9, q13
499 vadd.s32 q14, q11, q15
500 vsub.s32 q11, q11, q15
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
510 .macro idct_8x8 bitdepth
511 function ff_hevc_idct_8x8_\bitdepth\()_neon, export=1
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
525 tr_8x4 7, d0, d2, d4, d6, d8, d10, d12, d14
526 tr_8x4 7, d1, d3, d5, d7, d9, d11, d13, d15
528 @ Transpose each 4x4 block, and swap how d4-d7 and d8-d11 are used.
538 transpose_8x8 d0, d2, d4, d6, d8, d10, d12, d14, d1, d3, d5, d7, d9, d11, d13, d15
549 tr_8x4 20 - \bitdepth, d0, d2, d4, d6, d1, d3, d5, d7
551 tr_8x4 20 - \bitdepth, d0, d10, d12, d14, d9, d11, d13, d15
554 transpose_8x8 d0, d2, d4, d6, d8, d10, d12, d14, d1, d3, d5, d7, d9, d11, d13, d15
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
569 .macro butterfly e, o, tmp_p, tmp_m
570 vadd.s32 \tmp_p, \e, \o
571 vsub.s32 \tmp_m, \e, \o
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
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], -
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], +
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], -
596 butterfly q8, q12, q0, q7
597 butterfly q9, q13, q1, q6
598 butterfly q10, q14, q2, q5
599 butterfly q11, q15, q3, q4
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]
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
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
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
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
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
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
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]
678 .macro tr_16x4 name, shift, offset, step
679 function func_tr_16x4_\name
681 add r3, r5, #(\step * 64)
682 mov r2, #(\step * 128)
683 load16 d0, d1, d2, d3, d4, d5, d6, d7
686 tr16_8x4 d0, d1, d2, d3, d4, d5, d6, d7, \offset
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]
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], +, -, +, -, +, -, +, -
712 vld1.s32 {q0-q1}, [r4, :128]!
713 vld1.s32 {q2-q3}, [r4, :128]!
715 butterfly16 q0, q5, q1, q6, q2, q7, q3, q8
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
721 add r3, r6, #(24 +3*32)
724 store16 d26, d27, d28, d29, d30, d31, d16, d17, r4
726 store_to_stack \offset, (\offset + 240), q4, q5, q6, q7, q3, q2, q1, q0
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
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
739 add r3, r6, #(16 + 3 * 32)
742 store16 d26, d27, d28, d29, d30, d31, d8, d9, r4
744 store_to_stack (\offset + 64), (\offset + 176), q4, q9, q10, q11, q3, q2, q1, q0
751 .macro idct_16x16 bitdepth
752 function ff_hevc_idct_16x16_\bitdepth\()_neon, export=1
757 @ Align the stack, allocate a temp buffer
765 add r5, r0, #(8 * \i)
766 add r6, sp, #(8 * \i * 16)
767 bl func_tr_16x4_firstpass
771 add r5, sp, #(8 * \i)
772 add r6, r0, #(8 * \i * 16)
773 bl func_tr_16x4_secondpass_\bitdepth
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
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
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
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
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]
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
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
845 @ reload multiplication coefficiens to q1
846 vld1.s16 {q1}, [r9, :128]
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], +, -, +, -
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], +, -, +, -
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], +, -, +, -
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], +, -, +, -
929 .macro tr_32x4 name, shift
930 function func_tr_32x4_\name
932 bl func_tr_16x4_noscale
935 movrel r9, trans + 32
936 vld1.s16 {q0}, [r9, :128]!
937 vld1.s16 {q1}, [r9, :128]
942 vld1.s16 {q14-q15}, [r4, :128]!
943 butterfly32 q14, q10, q15, q11
944 scale32 d22, d23, d20, d21, q1, q14, q10, q15, \shift
946 vld1.s16 {q14-q15}, [r4, :128]!
947 butterfly32 q14, q12, q15, q13
948 scale32 d2, d3, d28, d29, q1, q14, q12, q15, \shift
950 transpose8_4x4 d22, d20, d2, d28
951 transpose8_4x4 d29, d3, d21, d23
955 add r3, r11, #(56 + 3 * 64)
956 store16 d22, d23, d20, d21, d2, d3, d28, d29, r8
958 @ reload multiplication coefficiens to q1
959 vld1.s16 {q1}, [r9, :128]
963 add r3, r11, #(48 + 3 * 64)
970 add r3, r11, #(40 + 3 * 64)
977 add r3, r11, #(32 + 3 * 64)
986 .macro idct_32x32 bitdepth
987 function ff_hevc_idct_32x32_\bitdepth\()_neon, export=1
992 @ Align the stack, allocate a temp buffer
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
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
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
1022 tr_32x4 firstpass, 7
1023 tr_32x4 secondpass_8, 20 - 8
1024 tr_32x4 secondpass_10, 20 - 10