• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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
25const 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
34endconst
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
43function 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
61endfunc
62
63function 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
80endfunc
81
82function ff_hevc_add_residual_8x8_8_neon, export=1
83        add             r12, r0, r2
84        add             r2,  r2, r2
85        mov             r3,   #8
861:      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
100endfunc
101
102function 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
1081:      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
119endfunc
120
121function ff_hevc_add_residual_16x16_8_neon, export=1
122        mov             r3,  #16
123        add             r12, r0, r2
124        add             r2,  r2, r2
1251:      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
146endfunc
147
148function 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
1541:      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
169endfunc
170
171function 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
1761:      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
209endfunc
210
211function 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
2161:      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
230endfunc
231
232.macro idct_4x4_dc bitdepth
233function ff_hevc_idct_4x4_dc_\bitdepth\()_neon, export=1
234        ldrsh           r1, [r0]
235        ldr             r2, =(1 << (13 - \bitdepth))
236        add             r1, #1
237        asr             r1, #1
238        add             r1, r2
239        asr             r1, #(14 - \bitdepth)
240        vdup.16         q0, r1
241        vdup.16         q1, r1
242        vst1.16         {q0, q1}, [r0, :128]
243        bx              lr
244endfunc
245.endm
246
247.macro idct_8x8_dc bitdepth
248function ff_hevc_idct_8x8_dc_\bitdepth\()_neon, export=1
249        ldrsh           r1, [r0]
250        ldr             r2, =(1 << (13 - \bitdepth))
251        add             r1, #1
252        asr             r1, #1
253        add             r1, r2
254        asr             r1, #(14 - \bitdepth)
255        vdup.16         q8, r1
256        vdup.16         q9, r1
257        vmov.16         q10, q8
258        vmov.16         q11, q8
259        vmov.16         q12, q8
260        vmov.16         q13, q8
261        vmov.16         q14, q8
262        vmov.16         q15, q8
263        vstm            r0, {q8-q15}
264        bx              lr
265endfunc
266.endm
267
268.macro idct_16x16_dc bitdepth
269function ff_hevc_idct_16x16_dc_\bitdepth\()_neon, export=1
270        ldrsh           r1, [r0]
271        ldr             r2, =(1 << (13 - \bitdepth))
272        add             r1, #1
273        asr             r1, #1
274        add             r1, r2
275        asr             r1, #(14 - \bitdepth)
276        vdup.16         q8, r1
277        vdup.16         q9, r1
278        vmov.16         q10, q8
279        vmov.16         q11, q8
280        vmov.16         q12, q8
281        vmov.16         q13, q8
282        vmov.16         q14, q8
283        vmov.16         q15, q8
284        vstm            r0!, {q8-q15}
285        vstm            r0!, {q8-q15}
286        vstm            r0!, {q8-q15}
287        vstm            r0, {q8-q15}
288        bx              lr
289endfunc
290.endm
291
292.macro idct_32x32_dc bitdepth
293function ff_hevc_idct_32x32_dc_\bitdepth\()_neon, export=1
294        ldrsh           r1, [r0]
295        ldr             r2, =(1 << (13 - \bitdepth))
296        add             r1, #1
297        asr             r1, #1
298        add             r1, r2
299        asr             r1, #(14 - \bitdepth)
300        mov             r3, #16
301        vdup.16         q8, r1
302        vdup.16         q9, r1
303        vmov.16         q10, q8
304        vmov.16         q11, q8
305        vmov.16         q12, q8
306        vmov.16         q13, q8
307        vmov.16         q14, q8
308        vmov.16         q15, q8
3091:      subs            r3, #1
310        vstm            r0!, {q8-q15}
311        bne             1b
312        bx              lr
313endfunc
314.endm
315
316.macro sum_sub out, in, c, op
317  .ifc \op, +
318        vmlal.s16       \out, \in, \c
319  .else
320        vmlsl.s16       \out, \in, \c
321  .endif
322.endm
323
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]
327         vmov           \tmp1, \tmp0
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
333
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
342.endm
343
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]!
347         vmov           \tmp1, \tmp0
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
354
355         vld1.s16       {\in0}, [r1, :64]
356
357         vadd.s32       \out0, \tmp0, \tmp2
358         vadd.s32       \out1, \tmp1, \tmp3
359         vsub.s32       \out2, \tmp1, \tmp3
360         vsub.s32       \out3, \tmp0, \tmp2
361
362         sub            r1,  r1,  #8
363.endm
364
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
369        vtrn.32         \rq0, \rq1
370        vtrn.16         \r0,  \r1
371        vtrn.16         \r2,  \r3
372.endm
373
374.macro idct_4x4 bitdepth
375function ff_hevc_idct_4x4_\bitdepth\()_neon, export=1
376@r0 - coeffs
377        vld1.s16        {q0-q1}, [r0, :128]
378
379        movrel          r1, trans
380        vld1.s16        {d4}, [r1, :64]
381
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
384
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]
388        bx lr
389endfunc
390.endm
391
392.macro transpose8_4x4 r0, r1, r2, r3
393        vtrn.16         \r0,  \r1
394        vtrn.16         \r2,  \r3
395        vtrn.32         \r0,  \r2
396        vtrn.32         \r1,  \r3
397.endm
398
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
402
403        transpose8_4x4  \l0, \l1, \l2, \l3
404        transpose8_4x4  \l4, \l5, \l6, \l7
405.endm
406
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
409
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], -
416
417        sum_sub         q14, \in5, \in0[3], +
418        sum_sub         q12, \in5, \in0[2], +
419        sum_sub         q13, \in5, \in0[0], -
420
421        sum_sub         q14, \in7, \in0[1], +
422        sum_sub         q12, \in7, \in0[3], +
423        sum_sub         q13, \in7, \in0[2], -
424
425        vadd.s32        q15, q10, q14
426        vsub.s32        q10, q10, q14
427        vqrshrn.s32     \in2, q15, \shift
428
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], -
433
434        vqrshrn.s32     \in5, q10,  \shift
435
436        vadd.s32        q10, q8, q12
437        vsub.s32        q8,  q8, q12
438        vadd.s32        q12, q9, q13
439        vsub.s32        q9,  q9, q13
440        vadd.s32        q14, q11, q15
441        vsub.s32        q11, q11, q15
442
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
449.endm
450
451.macro idct_8x8 bitdepth
452function ff_hevc_idct_8x8_\bitdepth\()_neon, export=1
453@r0 - coeffs
454        vpush           {q4-q7}
455
456        mov             r1,  r0
457        mov             r2,  #64
458        add             r3,  r0,  #32
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
463
464        movrel          r1, trans
465
466        tr_8x4          7, d0, d2, d4, d6, d8, d10, d12, d14
467        tr_8x4          7, d1, d3, d5, d7, d9, d11, d13, d15
468
469        @ Transpose each 4x4 block, and swap how d4-d7 and d8-d11 are used.
470        @ Layout before:
471        @ d0  d1
472        @ d2  d3
473        @ d4  d5
474        @ d6  d7
475        @ d8  d9
476        @ d10 d11
477        @ d12 d13
478        @ d14 d15
479        transpose_8x8   d0, d2, d4, d6, d8, d10, d12, d14, d1, d3, d5, d7, d9, d11, d13, d15
480        @ Now the layout is:
481        @ d0  d8
482        @ d2  d10
483        @ d4  d12
484        @ d6  d14
485        @ d1  d9
486        @ d3  d11
487        @ d5  d13
488        @ d7  d15
489
490        tr_8x4          20 - \bitdepth, d0, d2, d4, d6, d1, d3, d5, d7
491        vswp            d0, d8
492        tr_8x4          20 - \bitdepth, d0, d10, d12, d14, d9, d11, d13, d15
493        vswp            d0, d8
494
495        transpose_8x8   d0, d2, d4, d6, d8, d10, d12, d14, d1, d3, d5, d7, d9, d11, d13, d15
496
497        mov             r1,  r0
498        mov             r2,  #64
499        add             r3,  r0,  #32
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
504
505        vpop            {q4-q7}
506        bx              lr
507endfunc
508.endm
509
510.macro butterfly e, o, tmp_p, tmp_m
511        vadd.s32        \tmp_p, \e, \o
512        vsub.s32        \tmp_m, \e, \o
513.endm
514
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
517
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], -
526
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], +
531
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], -
536
537        butterfly       q8,  q12, q0, q7
538        butterfly       q9,  q13, q1, q6
539        butterfly       q10, q14, q2, q5
540        butterfly       q11, q15, q3, q4
541        add             r4,  sp,  #\offset
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]
546.endm
547
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
557.endm
558
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
568.endm
569
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
579.endm
580
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
590.endm
591
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
601.endm
602
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
606        add             r1, sp, #\off1
607        add             r3, sp, #\off2
608        mov             r2, #-16
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]
617.endm
618
619.macro tr_16x4 name, shift, offset, step
620function func_tr_16x4_\name
621        mov             r1,  r5
622        add             r3, r5, #(\step * 64)
623        mov             r2, #(\step * 128)
624        load16          d0, d1, d2, d3, d4, d5, d6, d7
625        movrel          r1, trans
626
627        tr16_8x4        d0, d1, d2, d3, d4, d5, d6, d7, \offset
628
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]
643
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], +, -, +, -, +, -, +, -
651
652        add             r4, sp, #\offset
653        vld1.s32        {q0-q1}, [r4, :128]!
654        vld1.s32        {q2-q3}, [r4, :128]!
655
656        butterfly16     q0, q5, q1, q6, q2, q7, q3, q8
657    .if \shift > 0
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
661        mov             r1, r6
662        add             r3, r6, #(24 +3*32)
663        mov             r2, #32
664        mov             r4, #-32
665        store16         d26, d27, d28, d29, d30, d31, d16, d17, r4
666    .else
667        store_to_stack  \offset, (\offset + 240), q4, q5, q6, q7, q3, q2, q1, q0
668    .endif
669
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
674    .if \shift > 0
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
678
679        add             r1, r6, #8
680        add             r3, r6, #(16 + 3 * 32)
681        mov             r2, #32
682        mov             r4, #-32
683        store16         d26, d27, d28, d29, d30, d31, d8, d9, r4
684    .else
685        store_to_stack (\offset + 64), (\offset + 176), q4, q9, q10, q11, q3, q2, q1, q0
686    .endif
687
688        bx              lr
689endfunc
690.endm
691
692.macro idct_16x16 bitdepth
693function ff_hevc_idct_16x16_\bitdepth\()_neon, export=1
694@r0 - coeffs
695        push            {r4-r7, lr}
696        vpush           {q4-q7}
697
698        @ Align the stack, allocate a temp buffer
699T       mov             r7,  sp
700T       and             r7,  r7,  #15
701A       and             r7,  sp,  #15
702        add             r7,  r7,  #640
703        sub             sp,  sp,  r7
704
705.irp i, 0, 1, 2, 3
706        add             r5, r0, #(8 * \i)
707        add             r6, sp, #(8 * \i * 16)
708        bl              func_tr_16x4_firstpass
709.endr
710
711.irp i, 0, 1, 2, 3
712        add             r5, sp, #(8 * \i)
713        add             r6, r0, #(8 * \i * 16)
714        bl              func_tr_16x4_secondpass_\bitdepth
715.endr
716
717        add             sp,  sp,  r7
718
719        vpop            {q4-q7}
720        pop             {r4-r7, pc}
721endfunc
722.endm
723
724.macro load32
725        add             r1,  r5, #64
726        add             r3,  r1, #128
727        mov             r2,  #256
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
744.endm
745
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
751.endm
752
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
758.endm
759
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
765.endm
766
767.macro multiply in
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]
772.endm
773
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
778
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
785
786        @ reload multiplication coefficiens to q1
787        vld1.s16        {q1}, [r9, :128]
788.endm
789
790function tr_block1
791        multiply        d0
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], +, -, +, -
807        bx              lr
808endfunc
809
810function tr_block2
811        multiply        d1
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], +, -, +, -
827        bx              lr
828endfunc
829
830function tr_block3
831        multiply        d2
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], +, -, +, -
847        bx              lr
848endfunc
849
850function tr_block4
851        multiply        d3
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], +, -, +, -
867        bx              lr
868endfunc
869
870.macro tr_32x4 name, shift
871function func_tr_32x4_\name
872        mov             r10, lr
873        bl              func_tr_16x4_noscale
874
875        load32
876        movrel          r9, trans + 32
877        vld1.s16        {q0}, [r9, :128]!
878        vld1.s16        {q1}, [r9, :128]
879
880        bl              tr_block1
881
882        add             r4, sp, #2048
883        vld1.s16        {q14-q15}, [r4, :128]!
884        butterfly32     q14, q10, q15, q11
885        scale32         d22, d23, d20, d21, q1, q14, q10, q15, \shift
886
887        vld1.s16        {q14-q15}, [r4, :128]!
888        butterfly32     q14, q12, q15, q13
889        scale32         d2, d3, d28, d29, q1, q14, q12, q15, \shift
890
891        transpose8_4x4  d22, d20, d2, d28
892        transpose8_4x4  d29, d3, d21, d23
893        mov             r1, r11
894        mov             r2, #64
895        mov             r8, #-64
896        add             r3, r11, #(56 + 3 * 64)
897        store16         d22, d23, d20, d21, d2, d3, d28, d29, r8
898
899        @ reload multiplication coefficiens to q1
900        vld1.s16        {q1}, [r9, :128]
901
902        bl              tr_block2
903        add             r1, r11, #8
904        add             r3, r11, #(48 + 3 * 64)
905        mov             r2, #64
906        mov             r8, #-64
907        scale_store     \shift
908
909        bl              tr_block3
910        add             r1, r11, #16
911        add             r3, r11, #(40 + 3 * 64)
912        mov             r2, #64
913        mov             r8, #-64
914        scale_store     \shift
915
916        bl              tr_block4
917        add             r1, r11, #24
918        add             r3, r11, #(32 + 3 * 64)
919        mov             r2, #64
920        mov             r8, #-64
921        scale_store     \shift
922
923        bx               r10
924endfunc
925.endm
926
927.macro idct_32x32 bitdepth
928function ff_hevc_idct_32x32_\bitdepth\()_neon, export=1
929@r0 - coeffs
930        push            {r4-r11, lr}
931        vpush           {q4-q7}
932
933        @ Align the stack, allocate a temp buffer
934T       mov             r7,  sp
935T       and             r7,  r7,  #15
936A       and             r7,  sp,  #15
937        add             r7,  r7,  #2432
938        sub             sp,  sp,  r7
939
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
944.endr
945
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
950.endr
951
952        add             sp,  sp,  r7
953        vpop            {q4-q7}
954        pop             {r4-r11, pc}
955endfunc
956.endm
957
958tr_16x4 firstpass, 7, 512, 1
959tr_16x4 secondpass_8, 20 - 8, 512, 1
960tr_16x4 secondpass_10, 20 - 10, 512, 1
961tr_16x4 noscale, 0, 2048, 4
962.ltorg
963tr_32x4 firstpass, 7
964tr_32x4 secondpass_8, 20 - 8
965tr_32x4 secondpass_10, 20 - 10
966.ltorg
967
968idct_4x4 8
969idct_4x4_dc 8
970idct_4x4 10
971idct_4x4_dc 10
972idct_8x8 8
973idct_8x8_dc 8
974idct_8x8 10
975idct_8x8_dc 10
976idct_16x16 8
977idct_16x16_dc 8
978idct_16x16 10
979idct_16x16_dc 10
980idct_32x32 8
981idct_32x32_dc 8
982idct_32x32 10
983idct_32x32_dc 10
984
985/* uses registers q2 - q9 for temp values */
986/* TODO: reorder */
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
992
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)
996
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
1001
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
1006
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
1011
1012        vqrshrn.s32   \r0, q8, \shift
1013        vqrshrn.s32   \r1, q9, \shift
1014        vqrshrn.s32   \r2, q7, \shift
1015        vqrshrn.s32   \r3, q5, \shift
1016.endm
1017
1018.ltorg
1019function ff_hevc_transform_luma_4x4_neon_8, export=1
1020        vpush       {d8-d15}
1021        vld1.16     {q14, q15}, [r0]  // coeffs
1022        ldr         r3, =0x4a  // 74
1023        vmov.32     d0[0], r3
1024        ldr         r3, =0x1d  // 29
1025        vmov.32     d0[1], r3
1026        ldr         r3, =0x37  // 55
1027        vmov.32     d1[0], r3
1028
1029        tr4_luma_shift d28, d29, d30, d31, #7
1030
1031        vtrn.16     d28, d29
1032        vtrn.16     d30, d31
1033        vtrn.32     q14, q15
1034
1035        tr4_luma_shift d28, d29, d30, d31, #12
1036
1037        vtrn.16     d28, d29
1038        vtrn.16     d30, d31
1039        vtrn.32     q14, q15
1040        vst1.16     {q14, q15}, [r0]
1041        vpop        {d8-d15}
1042        bx lr
1043endfunc
1044