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 .macro idct_4x4_dc bitdepth
233 function ff_hevc_idct_4x4_dc_\bitdepth\()_neon, export=1
235 ldr r2, =(1 << (13 - \bitdepth))
239 asr r1, #(14 - \bitdepth)
242 vst1.16 {q0, q1}, [r0, :128]
247 .macro idct_8x8_dc bitdepth
248 function ff_hevc_idct_8x8_dc_\bitdepth\()_neon, export=1
250 ldr r2, =(1 << (13 - \bitdepth))
254 asr r1, #(14 - \bitdepth)
268 .macro idct_16x16_dc bitdepth
269 function ff_hevc_idct_16x16_dc_\bitdepth\()_neon, export=1
271 ldr r2, =(1 << (13 - \bitdepth))
275 asr r1, #(14 - \bitdepth)
292 .macro idct_32x32_dc bitdepth
293 function ff_hevc_idct_32x32_dc_\bitdepth\()_neon, export=1
295 ldr r2, =(1 << (13 - \bitdepth))
299 asr r1, #(14 - \bitdepth)
316 .macro sum_sub out, in, c, op
318 vmlal.s16 \out, \in, \c
320 vmlsl.s16 \out, \in, \c
324 .macro tr_4x4 in0, in1, in2, in3, out0, out1, out2, out3, shift, tmp0, tmp1, tmp2, tmp3, tmp4
325 vshll.s16 \tmp0, \in0, #6
326 vmull.s16 \tmp2, \in1, d4[1]
328 vmull.s16 \tmp3, \in1, d4[3]
329 vmlal.s16 \tmp0, \in2, d4[0] @e0
330 vmlsl.s16 \tmp1, \in2, d4[0] @e1
331 vmlal.s16 \tmp2, \in3, d4[3] @o0
332 vmlsl.s16 \tmp3, \in3, d4[1] @o1
334 vadd.s32 \tmp4, \tmp0, \tmp2
335 vsub.s32 \tmp0, \tmp0, \tmp2
336 vadd.s32 \tmp2, \tmp1, \tmp3
337 vsub.s32 \tmp1, \tmp1, \tmp3
338 vqrshrn.s32 \out0, \tmp4, #\shift
339 vqrshrn.s32 \out3, \tmp0, #\shift
340 vqrshrn.s32 \out1, \tmp2, #\shift
341 vqrshrn.s32 \out2, \tmp1, #\shift
344 .macro tr_4x4_8 in0, in1, in2, in3, out0, out1, out2, out3, tmp0, tmp1, tmp2, tmp3
345 vshll.s16 \tmp0, \in0, #6
346 vld1.s16 {\in0}, [r1, :64]!
348 vmull.s16 \tmp2, \in1, \in0[1]
349 vmull.s16 \tmp3, \in1, \in0[3]
350 vmlal.s16 \tmp0, \in2, \in0[0] @e0
351 vmlsl.s16 \tmp1, \in2, \in0[0] @e1
352 vmlal.s16 \tmp2, \in3, \in0[3] @o0
353 vmlsl.s16 \tmp3, \in3, \in0[1] @o1
355 vld1.s16 {\in0}, [r1, :64]
357 vadd.s32 \out0, \tmp0, \tmp2
358 vadd.s32 \out1, \tmp1, \tmp3
359 vsub.s32 \out2, \tmp1, \tmp3
360 vsub.s32 \out3, \tmp0, \tmp2
365 @ Do a 4x4 transpose, using q registers for the subtransposes that don't
366 @ need to address the indiviudal d registers.
367 @ r0,r1 == rq0, r2,r3 == rq1
368 .macro transpose_4x4 rq0, rq1, r0, r1, r2, r3
374 .macro idct_4x4 bitdepth
375 function ff_hevc_idct_4x4_\bitdepth\()_neon, export=1
377 vld1.s16 {q0-q1}, [r0, :128]
380 vld1.s16 {d4}, [r1, :64]
382 tr_4x4 d0, d1, d2, d3, d16, d17, d18, d19, 7, q10, q11, q12, q13, q0
383 transpose_4x4 q8, q9, d16, d17, d18, d19
385 tr_4x4 d16, d17, d18, d19, d0, d1, d2, d3, 20 - \bitdepth, q10, q11, q12, q13, q0
386 transpose_4x4 q0, q1, d0, d1, d2, d3
387 vst1.s16 {d0-d3}, [r0, :128]
392 .macro transpose8_4x4 r0, r1, r2, r3
399 .macro transpose_8x8 r0, r1, r2, r3, r4, r5, r6, r7, l0, l1, l2, l3, l4, l5, l6, l7
400 transpose8_4x4 \r0, \r1, \r2, \r3
401 transpose8_4x4 \r4, \r5, \r6, \r7
403 transpose8_4x4 \l0, \l1, \l2, \l3
404 transpose8_4x4 \l4, \l5, \l6, \l7
407 .macro tr_8x4 shift, in0, in1, in2, in3, in4, in5, in6, in7
408 tr_4x4_8 \in0, \in2, \in4, \in6, q8, q9, q10, q11, q12, q13, q14, q15
410 vmull.s16 q14, \in1, \in0[2]
411 vmull.s16 q12, \in1, \in0[0]
412 vmull.s16 q13, \in1, \in0[1]
413 sum_sub q14, \in3, \in0[0], -
414 sum_sub q12, \in3, \in0[1], +
415 sum_sub q13, \in3, \in0[3], -
417 sum_sub q14, \in5, \in0[3], +
418 sum_sub q12, \in5, \in0[2], +
419 sum_sub q13, \in5, \in0[0], -
421 sum_sub q14, \in7, \in0[1], +
422 sum_sub q12, \in7, \in0[3], +
423 sum_sub q13, \in7, \in0[2], -
425 vadd.s32 q15, q10, q14
426 vsub.s32 q10, q10, q14
427 vqrshrn.s32 \in2, q15, \shift
429 vmull.s16 q15, \in1, \in0[3]
430 sum_sub q15, \in3, \in0[2], -
431 sum_sub q15, \in5, \in0[1], +
432 sum_sub q15, \in7, \in0[0], -
434 vqrshrn.s32 \in5, q10, \shift
436 vadd.s32 q10, q8, q12
438 vadd.s32 q12, q9, q13
440 vadd.s32 q14, q11, q15
441 vsub.s32 q11, q11, q15
443 vqrshrn.s32 \in0, q10, \shift
444 vqrshrn.s32 \in7, q8, \shift
445 vqrshrn.s32 \in1, q12, \shift
446 vqrshrn.s32 \in6, q9, \shift
447 vqrshrn.s32 \in3, q14, \shift
448 vqrshrn.s32 \in4, q11, \shift
451 .macro idct_8x8 bitdepth
452 function ff_hevc_idct_8x8_\bitdepth\()_neon, export=1
459 vld1.s16 {q0-q1}, [r1,:128], r2
460 vld1.s16 {q2-q3}, [r3,:128], r2
461 vld1.s16 {q4-q5}, [r1,:128], r2
462 vld1.s16 {q6-q7}, [r3,:128], r2
466 tr_8x4 7, d0, d2, d4, d6, d8, d10, d12, d14
467 tr_8x4 7, d1, d3, d5, d7, d9, d11, d13, d15
469 @ Transpose each 4x4 block, and swap how d4-d7 and d8-d11 are used.
479 transpose_8x8 d0, d2, d4, d6, d8, d10, d12, d14, d1, d3, d5, d7, d9, d11, d13, d15
490 tr_8x4 20 - \bitdepth, d0, d2, d4, d6, d1, d3, d5, d7
492 tr_8x4 20 - \bitdepth, d0, d10, d12, d14, d9, d11, d13, d15
495 transpose_8x8 d0, d2, d4, d6, d8, d10, d12, d14, d1, d3, d5, d7, d9, d11, d13, d15
500 vst1.s16 {q0-q1}, [r1,:128], r2
501 vst1.s16 {q2-q3}, [r3,:128], r2
502 vst1.s16 {q4-q5}, [r1,:128], r2
503 vst1.s16 {q6-q7}, [r3,:128], r2
510 .macro butterfly e, o, tmp_p, tmp_m
511 vadd.s32 \tmp_p, \e, \o
512 vsub.s32 \tmp_m, \e, \o
515 .macro tr16_8x4 in0, in1, in2, in3, in4, in5, in6, in7, offset
516 tr_4x4_8 \in0, \in2, \in4, \in6, q8, q9, q10, q11, q12, q13, q14, q15
518 vmull.s16 q12, \in1, \in0[0]
519 vmull.s16 q13, \in1, \in0[1]
520 vmull.s16 q14, \in1, \in0[2]
521 vmull.s16 q15, \in1, \in0[3]
522 sum_sub q12, \in3, \in0[1], +
523 sum_sub q13, \in3, \in0[3], -
524 sum_sub q14, \in3, \in0[0], -
525 sum_sub q15, \in3, \in0[2], -
527 sum_sub q12, \in5, \in0[2], +
528 sum_sub q13, \in5, \in0[0], -
529 sum_sub q14, \in5, \in0[3], +
530 sum_sub q15, \in5, \in0[1], +
532 sum_sub q12, \in7, \in0[3], +
533 sum_sub q13, \in7, \in0[2], -
534 sum_sub q14, \in7, \in0[1], +
535 sum_sub q15, \in7, \in0[0], -
537 butterfly q8, q12, q0, q7
538 butterfly q9, q13, q1, q6
539 butterfly q10, q14, q2, q5
540 butterfly q11, q15, q3, q4
542 vst1.s32 {q0-q1}, [r4, :128]!
543 vst1.s32 {q2-q3}, [r4, :128]!
544 vst1.s32 {q4-q5}, [r4, :128]!
545 vst1.s32 {q6-q7}, [r4, :128]
548 .macro load16 in0, in1, in2, in3, in4, in5, in6, in7
549 vld1.s16 {\in0}, [r1, :64], r2
550 vld1.s16 {\in1}, [r3, :64], r2
551 vld1.s16 {\in2}, [r1, :64], r2
552 vld1.s16 {\in3}, [r3, :64], r2
553 vld1.s16 {\in4}, [r1, :64], r2
554 vld1.s16 {\in5}, [r3, :64], r2
555 vld1.s16 {\in6}, [r1, :64], r2
556 vld1.s16 {\in7}, [r3, :64], r2
559 .macro add_member in, t0, t1, t2, t3, t4, t5, t6, t7, op0, op1, op2, op3, op4, op5, op6, op7
560 sum_sub q5, \in, \t0, \op0
561 sum_sub q6, \in, \t1, \op1
562 sum_sub q7, \in, \t2, \op2
563 sum_sub q8, \in, \t3, \op3
564 sum_sub q9, \in, \t4, \op4
565 sum_sub q10, \in, \t5, \op5
566 sum_sub q11, \in, \t6, \op6
567 sum_sub q12, \in, \t7, \op7
570 .macro butterfly16 in0, in1, in2, in3, in4, in5, in6, in7
571 vadd.s32 q4, \in0, \in1
572 vsub.s32 \in0, \in0, \in1
573 vadd.s32 \in1, \in2, \in3
574 vsub.s32 \in2, \in2, \in3
575 vadd.s32 \in3, \in4, \in5
576 vsub.s32 \in4, \in4, \in5
577 vadd.s32 \in5, \in6, \in7
578 vsub.s32 \in6, \in6, \in7
581 .macro store16 in0, in1, in2, in3, in4, in5, in6, in7, rx
582 vst1.s16 \in0, [r1, :64], r2
583 vst1.s16 \in1, [r3, :64], \rx
584 vst1.s16 \in2, [r1, :64], r2
585 vst1.s16 \in3, [r3, :64], \rx
586 vst1.s16 \in4, [r1, :64], r2
587 vst1.s16 \in5, [r3, :64], \rx
588 vst1.s16 \in6, [r1, :64], r2
589 vst1.s16 \in7, [r3, :64], \rx
592 .macro scale out0, out1, out2, out3, out4, out5, out6, out7, in0, in1, in2, in3, in4, in5, in6, in7, shift
593 vqrshrn.s32 \out0, \in0, \shift
594 vqrshrn.s32 \out1, \in1, \shift
595 vqrshrn.s32 \out2, \in2, \shift
596 vqrshrn.s32 \out3, \in3, \shift
597 vqrshrn.s32 \out4, \in4, \shift
598 vqrshrn.s32 \out5, \in5, \shift
599 vqrshrn.s32 \out6, \in6, \shift
600 vqrshrn.s32 \out7, \in7, \shift
603 @stores in1, in2, in4, in6 ascending from off1 and
604 @stores in1, in3, in5, in7 descending from off2
605 .macro store_to_stack off1, off2, in0, in2, in4, in6, in7, in5, in3, in1
609 vst1.s32 {\in0}, [r1, :128]!
610 vst1.s32 {\in1}, [r3, :128], r2
611 vst1.s32 {\in2}, [r1, :128]!
612 vst1.s32 {\in3}, [r3, :128], r2
613 vst1.s32 {\in4}, [r1, :128]!
614 vst1.s32 {\in5}, [r3, :128], r2
615 vst1.s32 {\in6}, [r1, :128]
616 vst1.s32 {\in7}, [r3, :128]
619 .macro tr_16x4 name, shift, offset, step
620 function func_tr_16x4_\name
622 add r3, r5, #(\step * 64)
623 mov r2, #(\step * 128)
624 load16 d0, d1, d2, d3, d4, d5, d6, d7
627 tr16_8x4 d0, d1, d2, d3, d4, d5, d6, d7, \offset
629 add r1, r5, #(\step * 32)
630 add r3, r5, #(\step * 3 *32)
631 mov r2, #(\step * 128)
632 load16 d8, d9, d2, d3, d4, d5, d6, d7
633 movrel r1, trans + 16
634 vld1.s16 {q0}, [r1, :128]
635 vmull.s16 q5, d8, d0[0]
636 vmull.s16 q6, d8, d0[1]
637 vmull.s16 q7, d8, d0[2]
638 vmull.s16 q8, d8, d0[3]
639 vmull.s16 q9, d8, d1[0]
640 vmull.s16 q10, d8, d1[1]
641 vmull.s16 q11, d8, d1[2]
642 vmull.s16 q12, d8, d1[3]
644 add_member d9, d0[1], d1[0], d1[3], d1[1], d0[2], d0[0], d0[3], d1[2], +, +, +, -, -, -, -, -
645 add_member d2, d0[2], d1[3], d0[3], d0[1], d1[2], d1[0], d0[0], d1[1], +, +, -, -, -, +, +, +
646 add_member d3, d0[3], d1[1], d0[1], d1[3], d0[0], d1[2], d0[2], d1[0], +, -, -, +, +, +, -, -
647 add_member d4, d1[0], d0[2], d1[2], d0[0], d1[3], d0[1], d1[1], d0[3], +, -, -, +, -, -, +, +
648 add_member d5, d1[1], d0[0], d1[0], d1[2], d0[1], d0[3], d1[3], d0[2], +, -, +, +, -, +, +, -
649 add_member d6, d1[2], d0[3], d0[0], d0[2], d1[1], d1[3], d1[0], d0[1], +, -, +, -, +, +, -, +
650 add_member d7, d1[3], d1[2], d1[1], d1[0], d0[3], d0[2], d0[1], d0[0], +, -, +, -, +, -, +, -
653 vld1.s32 {q0-q1}, [r4, :128]!
654 vld1.s32 {q2-q3}, [r4, :128]!
656 butterfly16 q0, q5, q1, q6, q2, q7, q3, q8
658 scale d26, d27, d28, d29, d30, d31, d16, d17, q4, q0, q5, q1, q6, q2, q7, q3, \shift
659 transpose8_4x4 d26, d28, d30, d16
660 transpose8_4x4 d17, d31, d29, d27
662 add r3, r6, #(24 +3*32)
665 store16 d26, d27, d28, d29, d30, d31, d16, d17, r4
667 store_to_stack \offset, (\offset + 240), q4, q5, q6, q7, q3, q2, q1, q0
670 add r4, sp, #(\offset + 64)
671 vld1.s32 {q0-q1}, [r4, :128]!
672 vld1.s32 {q2-q3}, [r4, :128]
673 butterfly16 q0, q9, q1, q10, q2, q11, q3, q12
675 scale d26, d27, d28, d29, d30, d31, d8, d9, q4, q0, q9, q1, q10, q2, q11, q3, \shift
676 transpose8_4x4 d26, d28, d30, d8
677 transpose8_4x4 d9, d31, d29, d27
680 add r3, r6, #(16 + 3 * 32)
683 store16 d26, d27, d28, d29, d30, d31, d8, d9, r4
685 store_to_stack (\offset + 64), (\offset + 176), q4, q9, q10, q11, q3, q2, q1, q0
692 .macro idct_16x16 bitdepth
693 function ff_hevc_idct_16x16_\bitdepth\()_neon, export=1
698 @ Align the stack, allocate a temp buffer
706 add r5, r0, #(8 * \i)
707 add r6, sp, #(8 * \i * 16)
708 bl func_tr_16x4_firstpass
712 add r5, sp, #(8 * \i)
713 add r6, r0, #(8 * \i * 16)
714 bl func_tr_16x4_secondpass_\bitdepth
728 vld1.s16 {d4}, [r1, :64], r2
729 vld1.s16 {d5}, [r3, :64], r2
730 vld1.s16 {d6}, [r1, :64], r2
731 vld1.s16 {d7}, [r3, :64], r2
732 vld1.s16 {d8}, [r1, :64], r2
733 vld1.s16 {d9}, [r3, :64], r2
734 vld1.s16 {d10}, [r1, :64], r2
735 vld1.s16 {d11}, [r3, :64], r2
736 vld1.s16 {d12}, [r1, :64], r2
737 vld1.s16 {d13}, [r3, :64], r2
738 vld1.s16 {d14}, [r1, :64], r2
739 vld1.s16 {d15}, [r3, :64], r2
740 vld1.s16 {d16}, [r1, :64], r2
741 vld1.s16 {d17}, [r3, :64], r2
742 vld1.s16 {d18}, [r1, :64], r2
743 vld1.s16 {d19}, [r3, :64], r2
746 .macro add_member32 in, t0, t1, t2, t3, op0, op1, op2, op3
747 sum_sub q10, \in, \t0, \op0
748 sum_sub q11, \in, \t1, \op1
749 sum_sub q12, \in, \t2, \op2
750 sum_sub q13, \in, \t3, \op3
753 .macro butterfly32 in0, in1, in2, in3
754 vadd.s32 q1, \in0, \in1
755 vsub.s32 \in0, \in0, \in1
756 vadd.s32 \in1, \in2, \in3
757 vsub.s32 \in2, \in2, \in3
760 .macro scale32 out0, out1, out2, out3, in0, in1, in2, in3, shift
761 vqrshrn.s32 \out0, \in0, \shift
762 vqrshrn.s32 \out1, \in1, \shift
763 vqrshrn.s32 \out2, \in2, \shift
764 vqrshrn.s32 \out3, \in3, \shift
768 vmull.s16 q10, d4, \in[0]
769 vmull.s16 q11, d4, \in[1]
770 vmull.s16 q12, d4, \in[2]
771 vmull.s16 q13, d4, \in[3]
774 .macro scale_store shift
775 vld1.s16 {q14-q15}, [r4, :128]!
776 butterfly32 q14, q10, q15, q11
777 scale32 d22, d23, d20, d21, q1, q14, q10, q15, \shift
779 vld1.s16 {q14-q15}, [r4, :128]!
780 butterfly32 q14, q12, q15, q13
781 scale32 d2, d3, d28, d29, q1, q14, q12, q15, \shift
782 transpose8_4x4 d22, d20, d2, d28
783 transpose8_4x4 d29, d3, d21, d23
784 store16 d22, d23, d20, d21, d2, d3, d28, d29, r8
786 @ reload multiplication coefficiens to q1
787 vld1.s16 {q1}, [r9, :128]
792 add_member32 d5, d0[1], d1[0], d1[3], d2[2], +, +, +, +
793 add_member32 d6, d0[2], d1[3], d3[0], d3[2], +, +, +, -
794 add_member32 d7, d0[3], d2[2], d3[2], d1[3], +, +, -, -
795 add_member32 d8, d1[0], d3[1], d2[1], d0[0], +, +, -, -
796 add_member32 d9, d1[1], d3[3], d1[0], d1[2], +, -, -, -
797 add_member32 d10, d1[2], d3[0], d0[0], d3[1], +, -, -, -
798 add_member32 d11, d1[3], d2[1], d1[1], d2[3], +, -, -, +
799 add_member32 d12, d2[0], d1[2], d2[2], d1[0], +, -, -, +
800 add_member32 d13, d2[1], d0[3], d3[3], d0[2], +, -, -, +
801 add_member32 d14, d2[2], d0[1], d2[3], d2[1], +, -, +, +
802 add_member32 d15, d2[3], d0[2], d1[2], d3[3], +, -, +, -
803 add_member32 d16, d3[0], d1[1], d0[1], d2[0], +, -, +, -
804 add_member32 d17, d3[1], d2[0], d0[3], d0[1], +, -, +, -
805 add_member32 d18, d3[2], d2[3], d2[0], d1[1], +, -, +, -
806 add_member32 d19, d3[3], d3[2], d3[1], d3[0], +, -, +, -
812 add_member32 d5, d3[1], d3[3], d3[0], d2[1], +, -, -, -
813 add_member32 d6, d2[1], d1[0], d0[0], d1[1], -, -, -, -
814 add_member32 d7, d0[0], d1[2], d3[1], d2[3], -, -, -, +
815 add_member32 d8, d2[0], d3[2], d1[1], d0[3], -, +, +, +
816 add_member32 d9, d3[2], d0[3], d1[3], d3[1], +, +, +, -
817 add_member32 d10, d1[1], d1[3], d2[3], d0[0], +, +, -, -
818 add_member32 d11, d0[3], d3[1], d0[1], d3[3], +, -, -, +
819 add_member32 d12, d3[0], d0[2], d3[2], d0[1], +, -, -, +
820 add_member32 d13, d2[2], d2[0], d1[0], d3[2], -, -, +, +
821 add_member32 d14, d0[1], d3[0], d2[0], d0[2], -, +, +, -
822 add_member32 d15, d1[3], d0[1], d2[2], d3[0], -, +, -, -
823 add_member32 d16, d3[3], d2[1], d0[2], d1[0], +, +, -, +
824 add_member32 d17, d1[2], d2[3], d3[3], d2[2], +, -, -, +
825 add_member32 d18, d0[2], d0[1], d0[3], d1[2], +, -, +, -
826 add_member32 d19, d2[3], d2[2], d2[1], d2[0], +, -, +, -
832 add_member32 d5, d1[2], d0[3], d0[0], d0[2], -, -, -, -
833 add_member32 d6, d2[2], d3[3], d2[3], d1[2], -, -, +, +
834 add_member32 d7, d1[0], d0[2], d2[1], d3[3], +, +, +, -
835 add_member32 d8, d3[0], d2[2], d0[1], d1[3], +, -, -, -
836 add_member32 d9, d0[2], d2[0], d3[0], d0[0], -, -, +, +
837 add_member32 d10, d3[2], d1[0], d2[0], d2[2], -, +, +, -
838 add_member32 d11, d0[0], d3[2], d0[2], d3[0], +, +, -, -
839 add_member32 d12, d3[3], d0[1], d3[1], d0[3], -, -, +, +
840 add_member32 d13, d0[1], d2[3], d1[3], d1[1], -, +, +, -
841 add_member32 d14, d3[1], d1[3], d0[3], d3[2], +, +, -, +
842 add_member32 d15, d0[3], d1[1], d3[2], d2[0], +, -, +, +
843 add_member32 d16, d2[3], d3[1], d1[2], d0[1], -, -, +, -
844 add_member32 d17, d1[1], d0[0], d1[0], d2[1], -, +, -, +
845 add_member32 d18, d2[1], d3[0], d3[3], d3[1], +, -, +, +
846 add_member32 d19, d1[3], d1[2], d1[1], d1[0], +, -, +, -
852 add_member32 d5, d1[1], d2[0], d2[3], d3[2], -, -, -, -
853 add_member32 d6, d0[0], d0[3], d2[0], d3[1], +, +, +, +
854 add_member32 d7, d2[0], d0[0], d1[1], d3[0], -, -, -, -
855 add_member32 d8, d3[3], d1[2], d0[2], d2[3], +, +, +, +
856 add_member32 d9, d2[1], d2[3], d0[0], d2[2], +, -, -, -
857 add_member32 d10, d0[2], d3[3], d0[3], d2[1], -, -, +, +
858 add_member32 d11, d1[0], d2[2], d1[2], d2[0], +, +, -, -
859 add_member32 d12, d2[3], d1[1], d2[1], d1[3], -, -, +, +
860 add_member32 d13, d3[1], d0[1], d3[0], d1[2], -, +, -, -
861 add_member32 d14, d1[2], d1[0], d3[3], d1[1], +, -, +, +
862 add_member32 d15, d0[1], d2[1], d3[1], d1[0], -, +, +, -
863 add_member32 d16, d1[3], d3[2], d2[2], d0[3], +, -, -, +
864 add_member32 d17, d3[2], d3[0], d1[3], d0[2], -, -, +, -
865 add_member32 d18, d2[2], d1[3], d1[0], d0[1], -, +, -, +
866 add_member32 d19, d0[3], d0[2], d0[1], d0[0], +, -, +, -
870 .macro tr_32x4 name, shift
871 function func_tr_32x4_\name
873 bl func_tr_16x4_noscale
876 movrel r9, trans + 32
877 vld1.s16 {q0}, [r9, :128]!
878 vld1.s16 {q1}, [r9, :128]
883 vld1.s16 {q14-q15}, [r4, :128]!
884 butterfly32 q14, q10, q15, q11
885 scale32 d22, d23, d20, d21, q1, q14, q10, q15, \shift
887 vld1.s16 {q14-q15}, [r4, :128]!
888 butterfly32 q14, q12, q15, q13
889 scale32 d2, d3, d28, d29, q1, q14, q12, q15, \shift
891 transpose8_4x4 d22, d20, d2, d28
892 transpose8_4x4 d29, d3, d21, d23
896 add r3, r11, #(56 + 3 * 64)
897 store16 d22, d23, d20, d21, d2, d3, d28, d29, r8
899 @ reload multiplication coefficiens to q1
900 vld1.s16 {q1}, [r9, :128]
904 add r3, r11, #(48 + 3 * 64)
911 add r3, r11, #(40 + 3 * 64)
918 add r3, r11, #(32 + 3 * 64)
927 .macro idct_32x32 bitdepth
928 function ff_hevc_idct_32x32_\bitdepth\()_neon, export=1
933 @ Align the stack, allocate a temp buffer
940 .irp i, 0, 1, 2, 3, 4, 5, 6, 7
941 add r5, r0, #(8 * \i)
942 add r11, sp, #(8 * \i * 32)
943 bl func_tr_32x4_firstpass
946 .irp i, 0, 1, 2, 3, 4, 5, 6, 7
947 add r5, sp, #(8 * \i)
948 add r11, r0, #(8 * \i * 32)
949 bl func_tr_32x4_secondpass_\bitdepth
958 tr_16x4 firstpass, 7, 512, 1
959 tr_16x4 secondpass_8, 20 - 8, 512, 1
960 tr_16x4 secondpass_10, 20 - 10, 512, 1
961 tr_16x4 noscale, 0, 2048, 4
964 tr_32x4 secondpass_8, 20 - 8
965 tr_32x4 secondpass_10, 20 - 10
985 /* uses registers q2 - q9 for temp values */
987 .macro tr4_luma_shift r0, r1, r2, r3, shift
988 vaddl.s16 q5, \r0, \r2 // c0 = src0 + src2
989 vaddl.s16 q2, \r2, \r3 // c1 = src2 + src3
990 vsubl.s16 q4, \r0, \r3 // c2 = src0 - src3
991 vmull.s16 q6, \r1, d0[0] // c3 = 74 * src1
993 vaddl.s16 q7, \r0, \r3 // src0 + src3
994 vsubw.s16 q7, q7, \r2 // src0 - src2 + src3
995 vmul.s32 q7, q7, d0[0] // dst2 = 74 * (src0 - src2 + src3)
997 vmul.s32 q8, q5, d0[1] // 29 * c0
998 vmul.s32 q9, q2, d1[0] // 55 * c1
999 vadd.s32 q8, q9 // 29 * c0 + 55 * c1
1000 vadd.s32 q8, q6 // dst0 = 29 * c0 + 55 * c1 + c3
1002 vmul.s32 q2, q2, d0[1] // 29 * c1
1003 vmul.s32 q9, q4, d1[0] // 55 * c2
1004 vsub.s32 q9, q2 // 55 * c2 - 29 * c1
1005 vadd.s32 q9, q6 // dst1 = 55 * c2 - 29 * c1 + c3
1007 vmul.s32 q5, q5, d1[0] // 55 * c0
1008 vmul.s32 q4, q4, d0[1] // 29 * c2
1009 vadd.s32 q5, q4 // 55 * c0 + 29 * c2
1010 vsub.s32 q5, q6 // dst3 = 55 * c0 + 29 * c2 - c3
1012 vqrshrn.s32 \r0, q8, \shift
1013 vqrshrn.s32 \r1, q9, \shift
1014 vqrshrn.s32 \r2, q7, \shift
1015 vqrshrn.s32 \r3, q5, \shift
1019 function ff_hevc_transform_luma_4x4_neon_8, export=1
1021 vld1.16 {q14, q15}, [r0] // coeffs
1029 tr4_luma_shift d28, d29, d30, d31, #7
1035 tr4_luma_shift d28, d29, d30, d31, #12
1040 vst1.16 {q14, q15}, [r0]