xref: /aosp_15_r20/external/libdav1d/src/arm/32/itx.S (revision c09093415860a1c2373dacd84c4fde00c507cdfd)
1/******************************************************************************
2 * Copyright © 2018, VideoLAN and dav1d authors
3 * Copyright © 2020, Martin Storsjo
4 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions are met:
8 *
9 * 1. Redistributions of source code must retain the above copyright notice, this
10 *    list of conditions and the following disclaimer.
11 *
12 * 2. Redistributions in binary form must reproduce the above copyright notice,
13 *    this list of conditions and the following disclaimer in the documentation
14 *    and/or other materials provided with the distribution.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
17 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
20 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 *****************************************************************************/
27
28#include "src/arm/asm.S"
29#include "util.S"
30
31// The exported functions in this file have got the following signature:
32// void itxfm_add(pixel *dst, ptrdiff_t dst_stride, coef *coeff, int eob);
33
34// Most of the functions use the following register layout:
35// r0-r3   external parameters
36// r4      function pointer to first transform
37// r5      function pointer to second transform
38// r6      output parameter for helper function
39// r7      input parameter for helper function
40// r8      input stride for helper function
41// r9      scratch variable for helper functions
42// r10-r11 pointer to list of eob thresholds, eob threshold value,
43//         scratch variables within helper functions (backed up)
44
45// The SIMD registers most often use the following layout:
46// d0-d3   multiplication coefficients
47// d4-d7   scratch registers
48// d8-d15  unused in some transforms, used for scratch registers in others
49// d16-v31 inputs/outputs of transforms
50
51// Potential further optimizations, that are left unimplemented for now:
52// - Trying to keep multiplication coefficients in registers across multiple
53//   transform functions. (The register layout is designed to potentially
54//   allow this.)
55// - Use a simplified version of the transforms themselves for cases where
56//   we know a significant number of inputs are zero. E.g. if the eob value
57//   indicates only a quarter of input values are set, for idct16 and up,
58//   a significant amount of calculation can be skipped, at the cost of more
59//   code duplication and special casing.
60
61const idct_coeffs, align=4
62        // idct4
63        .short          2896, 2896*8, 1567, 3784
64        // idct8
65        .short          799, 4017, 3406, 2276
66        // idct16
67        .short          401, 4076, 3166, 2598
68        .short          1931, 3612, 3920, 1189
69        // idct32
70        .short          201, 4091, 3035, 2751
71        .short          1751, 3703, 3857, 1380
72        .short          995, 3973, 3513, 2106
73        .short          2440, 3290, 4052, 601
74endconst
75
76const idct64_coeffs, align=4
77        .short          101*8, 4095*8, 2967*8, -2824*8
78        .short          1660*8, 3745*8, 3822*8, -1474*8
79        .short          4076, 401, 4017, 799
80
81        .short          4036*8, -700*8, 2359*8, 3349*8
82        .short          3461*8, -2191*8, 897*8, 3996*8
83        .short          -3166, -2598, -799, -4017
84
85        .short          501*8, 4065*8, 3229*8, -2520*8
86        .short          2019*8, 3564*8, 3948*8, -1092*8
87        .short          3612, 1931, 2276, 3406
88
89        .short          4085*8, -301*8, 2675*8, 3102*8
90        .short          3659*8, -1842*8, 1285*8, 3889*8
91        .short          -3920, -1189, -3406, -2276
92endconst
93
94const iadst4_coeffs, align=4
95        // .h[4-5] can be interpreted as .s[2]
96        .short          1321, 3803, 2482, 3344, 3344, 0
97endconst
98
99const iadst8_coeffs, align=4
100        .short          4076, 401, 3612, 1931
101        .short          2598, 3166, 1189, 3920
102        // idct_coeffs
103        .short          2896, 0, 1567, 3784, 0, 0, 0, 0
104endconst
105
106const iadst16_coeffs, align=4
107        .short          4091, 201, 3973, 995
108        .short          3703, 1751, 3290, 2440
109        .short          2751, 3035, 2106, 3513
110        .short          1380, 3857, 601, 4052
111endconst
112
113.macro vmull_vmlal d0, s0, s1, c0, c1
114        vmull.s16       \d0, \s0, \c0
115        vmlal.s16       \d0, \s1, \c1
116.endm
117
118.macro vmull_vmlal_8h d0, d1, s0, s1, s2, s3, c0, c1
119        vmull.s16       \d0, \s0, \c0
120        vmlal.s16       \d0, \s2, \c1
121        vmull.s16       \d1, \s1, \c0
122        vmlal.s16       \d1, \s3, \c1
123.endm
124
125.macro vmull_vmlsl d0, s0, s1, c0, c1
126        vmull.s16       \d0, \s0, \c0
127        vmlsl.s16       \d0, \s1, \c1
128.endm
129
130.macro vmull_vmlsl_8h d0, d1, s0, s1, s2, s3, c0, c1
131        vmull.s16       \d0, \s0, \c0
132        vmlsl.s16       \d0, \s2, \c1
133        vmull.s16       \d1, \s1, \c0
134        vmlsl.s16       \d1, \s3, \c1
135.endm
136
137.macro vqrshrn_8h d0, d1, s0, s1, shift
138        vqrshrn.s32     \d0, \s0, \shift
139        vqrshrn.s32     \d1, \s1, \shift
140.endm
141
142.macro scale_input c, r0, r1, r2 r3, r4, r5, r6, r7
143        vqrdmulh.s16    \r0, \r0, \c
144        vqrdmulh.s16    \r1, \r1, \c
145.ifnb \r2
146        vqrdmulh.s16    \r2, \r2, \c
147        vqrdmulh.s16    \r3, \r3, \c
148.endif
149.ifnb \r4
150        vqrdmulh.s16    \r4, \r4, \c
151        vqrdmulh.s16    \r5, \r5, \c
152        vqrdmulh.s16    \r6, \r6, \c
153        vqrdmulh.s16    \r7, \r7, \c
154.endif
155.endm
156
157.macro load_add_store load, shift, addsrc, adddst, narrowsrc, narrowdst, store, dst, src, shiftbits=4
158.ifnb \load
159        vld1.8          {\load},  [\src, :64], r1
160.endif
161.ifnb \shift
162        vrshr.s16       \shift,  \shift,  #\shiftbits
163.endif
164.ifnb \addsrc
165        vaddw.u8        \adddst, \adddst, \addsrc
166.endif
167.ifnb \narrowsrc
168        vqmovun.s16     \narrowdst, \narrowsrc
169.endif
170.ifnb \store
171        vst1.8          {\store},  [\dst, :64], r1
172.endif
173.endm
174.macro load_add_store_8x8 dst, src, shiftbits=4
175        mov             \src, \dst
176        load_add_store  d2,  q8,    ,    ,    ,    ,    , \dst, \src, \shiftbits
177        load_add_store  d3,  q9,    ,    ,    ,    ,    , \dst, \src, \shiftbits
178        load_add_store  d4,  q10, d2,  q8,    ,    ,    , \dst, \src, \shiftbits
179        load_add_store  d5,  q11, d3,  q9,  q8,  d2,    , \dst, \src, \shiftbits
180        load_add_store  d6,  q12, d4,  q10, q9,  d3,  d2, \dst, \src, \shiftbits
181        load_add_store  d7,  q13, d5,  q11, q10, d4,  d3, \dst, \src, \shiftbits
182        load_add_store  d2,  q14, d6,  q12, q11, d5,  d4, \dst, \src, \shiftbits
183        load_add_store  d3,  q15, d7,  q13, q12, d6,  d5, \dst, \src, \shiftbits
184        load_add_store    ,     , d2,  q14, q13, d7,  d6, \dst, \src, \shiftbits
185        load_add_store    ,     , d3,  q15, q14, d2,  d7, \dst, \src, \shiftbits
186        load_add_store    ,     ,   ,     , q15, d3,  d2, \dst, \src, \shiftbits
187        load_add_store    ,     ,   ,     ,    ,   ,  d3, \dst, \src, \shiftbits
188.endm
189.macro load_add_store_8x4 dst, src
190        mov             \src, \dst
191        load_add_store  d2,  q8,    ,    ,    ,    ,    ,  \dst, \src
192        load_add_store  d3,  q9,    ,    ,    ,    ,    ,  \dst, \src
193        load_add_store  d4,  q10, d2,  q8,    ,    ,    ,  \dst, \src
194        load_add_store  d5,  q11, d3,  q9,  q8,  d2,    ,  \dst, \src
195        load_add_store    ,     , d4,  q10, q9,  d3,  d2,  \dst, \src
196        load_add_store    ,     , d5,  q11, q10, d4,  d3,  \dst, \src
197        load_add_store    ,     ,   ,     , q11, d5,  d4,  \dst, \src
198        load_add_store    ,     ,   ,     ,    ,   ,  d5,  \dst, \src
199.endm
200.macro load_add_store4 load, shift, addsrc, adddst, narrowsrc, narrowdst, store, dst, src
201.ifnb \load
202        vld1.32         {\load[0]},  [\src, :32], r1
203.endif
204.ifnb \shift
205        vrshr.s16       \shift,  \shift,  #4
206.endif
207.ifnb \load
208        vld1.32         {\load[1]},  [\src, :32], r1
209.endif
210.ifnb \addsrc
211        vaddw.u8        \adddst, \adddst, \addsrc
212.endif
213.ifnb \store
214        vst1.32         {\store[0]},  [\dst, :32], r1
215.endif
216.ifnb \narrowsrc
217        vqmovun.s16     \narrowdst, \narrowsrc
218.endif
219.ifnb \store
220        vst1.32         {\store[1]},  [\dst, :32], r1
221.endif
222.endm
223.macro load_add_store_4x16 dst, src
224        mov             \src, \dst
225        load_add_store4 d0,    ,    ,    ,    ,    ,    ,  \dst, \src
226        load_add_store4 d1,  q8,    ,    ,    ,    ,    ,  \dst, \src
227        load_add_store4 d2,  q9,  d0,  q8,    ,    ,    ,  \dst, \src
228        load_add_store4 d3,  q10, d1,  q9,  q8,  d0,    ,  \dst, \src
229        load_add_store4 d4,  q11, d2,  q10, q9,  d1,  d0,  \dst, \src
230        load_add_store4 d5,  q12, d3,  q11, q10, d2,  d1,  \dst, \src
231        load_add_store4 d6,  q13, d4,  q12, q11, d3,  d2,  \dst, \src
232        load_add_store4 d7,  q14, d5,  q13, q12, d4,  d3,  \dst, \src
233        load_add_store4   ,  q15, d6,  q14, q13, d5,  d4,  \dst, \src
234        load_add_store4   ,     , d7,  q15, q14, d6,  d5,  \dst, \src
235        load_add_store4   ,     ,   ,     , q15, d7,  d6,  \dst, \src
236        load_add_store4   ,     ,   ,     ,    ,   ,  d7,  \dst, \src
237.endm
238.macro load_add_store_4x8 dst, src
239        mov             \src, \dst
240        load_add_store4 d0,    ,    ,    ,    ,    ,    ,  \dst, \src
241        load_add_store4 d1,  q8,    ,    ,    ,    ,    ,  \dst, \src
242        load_add_store4 d2,  q9,  d0,  q8,    ,    ,    ,  \dst, \src
243        load_add_store4 d3,  q10, d1,  q9,  q8,  d0,    ,  \dst, \src
244        load_add_store4   ,  q11, d2,  q10, q9,  d1,  d0,  \dst, \src
245        load_add_store4   ,     , d3,  q11, q10, d2,  d1,  \dst, \src
246        load_add_store4   ,     ,   ,     , q11, d3,  d2,  \dst, \src
247        load_add_store4   ,     ,   ,     ,    ,   ,  d3,  \dst, \src
248.endm
249
250.macro idct_dc w, h, shift
251        cmp             r3,  #0
252        bne             1f
253        vmov.i16        d30, #0
254        movw            r12, #2896*8
255        vld1.16         {d16[]},  [r2, :16]
256        vdup.16         d0,  r12
257        vqrdmulh.s16    d16, d16, d0[0]
258        vst1.16         {d30[0]}, [r2, :16]
259.if (\w == 2*\h) || (2*\w == \h)
260        vqrdmulh.s16    d16, d16, d0[0]
261.endif
262.if \shift > 0
263        vrshr.s16       d16, d16, #\shift
264.endif
265        vqrdmulh.s16    d20, d16, d0[0]
266        mov             r3,  #\h
267        vrshr.s16       d16, d20, #4
268        vrshr.s16       d17, d20, #4
269        b               idct_dc_w\w\()_neon
2701:
271.endm
272
273function idct_dc_w4_neon
2741:
275        vld1.32         {d0[0]}, [r0, :32], r1
276        vld1.32         {d0[1]}, [r0, :32], r1
277        vld1.32         {d1[0]}, [r0, :32], r1
278        vld1.32         {d1[1]}, [r0, :32], r1
279        subs            r3,  r3,  #4
280        sub             r0,  r0,  r1, lsl #2
281        vaddw.u8        q10, q8,  d0
282        vqmovun.s16     d0,  q10
283        vaddw.u8        q11, q8,  d1
284        vst1.32         {d0[0]}, [r0, :32], r1
285        vqmovun.s16     d1,  q11
286        vst1.32         {d0[1]}, [r0, :32], r1
287        vst1.32         {d1[0]}, [r0, :32], r1
288        vst1.32         {d1[1]}, [r0, :32], r1
289        bgt             1b
290        bx              lr
291endfunc
292
293function idct_dc_w8_neon
2941:
295        vld1.8          {d0}, [r0, :64], r1
296        vld1.8          {d1}, [r0, :64], r1
297        vld1.8          {d2}, [r0, :64], r1
298        vaddw.u8        q10, q8,  d0
299        vld1.8          {d3}, [r0, :64], r1
300        sub             r0,  r0,  r1, lsl #2
301        subs            r3,  r3,  #4
302        vaddw.u8        q11, q8,  d1
303        vqmovun.s16     d0,  q10
304        vaddw.u8        q12, q8,  d2
305        vqmovun.s16     d1,  q11
306        vaddw.u8        q13, q8,  d3
307        vst1.8          {d0}, [r0, :64], r1
308        vqmovun.s16     d2,  q12
309        vst1.8          {d1}, [r0, :64], r1
310        vqmovun.s16     d3,  q13
311        vst1.8          {d2}, [r0, :64], r1
312        vst1.8          {d3}, [r0, :64], r1
313        bgt             1b
314        bx              lr
315endfunc
316
317function idct_dc_w16_neon
3181:
319        vld1.8          {q0}, [r0, :128], r1
320        vld1.8          {q1}, [r0, :128], r1
321        vld1.8          {q2}, [r0, :128], r1
322        subs            r3,  r3,  #4
323        vaddw.u8        q10, q8,  d0
324        vaddw.u8        q11, q8,  d1
325        vld1.8          {q3}, [r0, :128], r1
326        vaddw.u8        q12, q8,  d2
327        vaddw.u8        q13, q8,  d3
328        sub             r0,  r0,  r1, lsl #2
329        vaddw.u8        q14, q8,  d4
330        vaddw.u8        q15, q8,  d5
331        vqmovun.s16     d0,  q10
332        vqmovun.s16     d1,  q11
333        vaddw.u8        q10, q8,  d6
334        vaddw.u8        q11, q8,  d7
335        vqmovun.s16     d2,  q12
336        vqmovun.s16     d3,  q13
337        vqmovun.s16     d4,  q14
338        vqmovun.s16     d5,  q15
339        vst1.8          {q0}, [r0, :128], r1
340        vqmovun.s16     d6,  q10
341        vqmovun.s16     d7,  q11
342        vst1.8          {q1}, [r0, :128], r1
343        vst1.8          {q2}, [r0, :128], r1
344        vst1.8          {q3}, [r0, :128], r1
345        bgt             1b
346        bx              lr
347endfunc
348
349function idct_dc_w32_neon
3501:
351        vld1.8          {q0, q1}, [r0, :128], r1
352        subs            r3,  r3,  #2
353        vld1.8          {q2, q3}, [r0, :128], r1
354        vaddw.u8        q10, q8,  d0
355        vaddw.u8        q11, q8,  d1
356        vaddw.u8        q12, q8,  d2
357        vaddw.u8        q13, q8,  d3
358        sub             r0,  r0,  r1, lsl #1
359        vaddw.u8        q14, q8,  d4
360        vaddw.u8        q15, q8,  d5
361        vqmovun.s16     d0,  q10
362        vqmovun.s16     d1,  q11
363        vaddw.u8        q10, q8,  d6
364        vaddw.u8        q11, q8,  d7
365        vqmovun.s16     d2,  q12
366        vqmovun.s16     d3,  q13
367        vqmovun.s16     d4,  q14
368        vqmovun.s16     d5,  q15
369        vst1.8          {q0, q1}, [r0, :128], r1
370        vqmovun.s16     d6,  q10
371        vqmovun.s16     d7,  q11
372        vst1.8          {q2, q3}, [r0, :128], r1
373        bgt             1b
374        bx              lr
375endfunc
376
377function idct_dc_w64_neon
378        sub             r1,  r1,  #32
3791:
380        vld1.8          {q0, q1}, [r0, :128]!
381        subs            r3,  r3,  #1
382        vld1.8          {q2, q3}, [r0, :128]
383        vaddw.u8        q10, q8,  d0
384        vaddw.u8        q11, q8,  d1
385        vaddw.u8        q12, q8,  d2
386        vaddw.u8        q13, q8,  d3
387        sub             r0,  r0,  #32
388        vaddw.u8        q14, q8,  d4
389        vaddw.u8        q15, q8,  d5
390        vqmovun.s16     d0,  q10
391        vqmovun.s16     d1,  q11
392        vaddw.u8        q10, q8,  d6
393        vaddw.u8        q11, q8,  d7
394        vqmovun.s16     d2,  q12
395        vqmovun.s16     d3,  q13
396        vqmovun.s16     d4,  q14
397        vqmovun.s16     d5,  q15
398        vst1.8          {q0, q1}, [r0, :128]!
399        vqmovun.s16     d6,  q10
400        vqmovun.s16     d7,  q11
401        vst1.8          {q2, q3}, [r0, :128], r1
402        bgt             1b
403        bx              lr
404endfunc
405
406.macro iwht4
407        vadd.i16        d16, d16, d17
408        vsub.i16        d21, d18, d19
409        vsub.i16        d20, d16, d21
410        vshr.s16        d20, d20, #1
411        vsub.i16        d18, d20, d17
412        vsub.i16        d17, d20, d19
413        vadd.i16        d19, d21, d18
414        vsub.i16        d16, d16, d17
415.endm
416
417.macro idct_4h_x4 r0, r1, r2, r3
418        vmull_vmlal     q3,  \r1, \r3, d0[3], d0[2]
419        vmull_vmlsl     q2,  \r1, \r3, d0[2], d0[3]
420        vmull_vmlal     q1,  \r0, \r2, d0[0], d0[0]
421        vqrshrn.s32     d6,  q3,  #12
422        vqrshrn.s32     d7,  q2,  #12
423        vmull_vmlsl     q2,  \r0, \r2, d0[0], d0[0]
424        vqrshrn.s32     d2,  q1,  #12
425        vqrshrn.s32     d3,  q2,  #12
426        vqadd.s16       \r0, d2,  d6
427        vqsub.s16       \r3, d2,  d6
428        vqadd.s16       \r1, d3,  d7
429        vqsub.s16       \r2, d3,  d7
430.endm
431
432.macro idct_8h_x4 q0, q1, q2, q3, r0, r1, r2, r3, r4, r5, r6, r7
433        vmull_vmlal_8h  q6,  q7,  \r2, \r3, \r6, \r7, d0[3], d0[2]
434        vmull_vmlsl_8h  q4,  q5,  \r2, \r3, \r6, \r7, d0[2], d0[3]
435        vmull_vmlal_8h  q2,  q3,  \r0, \r1, \r4, \r5, d0[0], d0[0]
436        vqrshrn_8h      d12, d13, q6,  q7,  #12
437        vqrshrn_8h      d14, d15, q4,  q5,  #12
438        vmull_vmlsl_8h  q4,  q5,  \r0, \r1, \r4, \r5, d0[0], d0[0]
439        vqrshrn_8h      d4,  d5,  q2,  q3,  #12
440        vqrshrn_8h      d6,  d7,  q4,  q5,  #12
441        vqadd.s16       \q0, q2,  q6
442        vqsub.s16       \q3, q2,  q6
443        vqadd.s16       \q1, q3,  q7
444        vqsub.s16       \q2, q3,  q7
445.endm
446
447function inv_dct_4h_x4_neon, export=1
448        movrel_local    r12, idct_coeffs
449        vld1.16         {d0}, [r12, :64]
450        idct_4h_x4      d16, d17, d18, d19
451        bx              lr
452endfunc
453
454function inv_dct_8h_x4_neon, export=1
455        movrel_local    r12, idct_coeffs
456        vld1.16         {d0}, [r12, :64]
457        idct_8h_x4      q8,  q9,  q10, q11, d16, d17, d18, d19, d20, d21, d22, d23
458        bx              lr
459endfunc
460
461.macro iadst_4x4 o0, o1, o2, o3
462        movrel_local    r12, iadst4_coeffs
463        vld1.16         {d0, d1}, [r12, :128]
464
465        vsubl.s16       q1,  d16, d18
466        vmull.s16       q2,  d16, d0[0]
467        vmlal.s16       q2,  d18, d0[1]
468        vmlal.s16       q2,  d19, d0[2]
469        vmull.s16       q10, d17, d0[3]
470        vaddw.s16       q1,  q1,  d19
471        vmull.s16       q3,  d16, d0[2]
472        vmlsl.s16       q3,  d18, d0[0]
473        vmlsl.s16       q3,  d19, d0[1]
474
475        vadd.s32        q11, q2,  q3
476        vmul.s32        q1,  q1,  d1[0]
477        vadd.s32        q2,  q2,  q10
478        vadd.s32        q3,  q3,  q10
479        vsub.s32        q11, q11, q10
480
481        vqrshrn.s32     \o0, q2,  #12
482        vqrshrn.s32     \o2, q1,  #12
483        vqrshrn.s32     \o1, q3,  #12
484        vqrshrn.s32     \o3, q11, #12
485.endm
486
487function inv_adst_4h_x4_neon, export=1
488        iadst_4x4       d16, d17, d18, d19
489        bx              lr
490endfunc
491
492function inv_flipadst_4h_x4_neon, export=1
493        iadst_4x4       d19, d18, d17, d16
494        bx              lr
495endfunc
496
497.macro iadst_8x4 o0, o1, o2, o3, o4, o5, o6, o7
498        movrel_local    r12, iadst4_coeffs
499        vld1.16         {d0, d1}, [r12, :128]
500
501        vsubl.s16       q2,  d16, d20
502        vsubl.s16       q3,  d17, d21
503        vmull.s16       q4,  d16, d0[0]
504        vmlal.s16       q4,  d20, d0[1]
505        vmlal.s16       q4,  d22, d0[2]
506        vmull.s16       q5,  d17, d0[0]
507        vmlal.s16       q5,  d21, d0[1]
508        vmlal.s16       q5,  d23, d0[2]
509        vaddw.s16       q2,  q2,  d22
510        vaddw.s16       q3,  q3,  d23
511        vmull.s16       q6,  d16, d0[2]
512        vmlsl.s16       q6,  d20, d0[0]
513        vmlsl.s16       q6,  d22, d0[1]
514        vmull.s16       q7,  d17, d0[2]
515        vmlsl.s16       q7,  d21, d0[0]
516        vmlsl.s16       q7,  d23, d0[1]
517
518        vmul.s32        q10, q2,  d1[0]
519        vmul.s32        q11, q3,  d1[0]
520
521        vmull.s16       q2,  d18, d0[3]
522        vmull.s16       q3,  d19, d0[3]
523
524        vadd.s32        q8,  q4,  q2 // out0
525        vadd.s32        q9,  q5,  q3
526
527        vadd.s32        q4,  q4,  q6 // out3
528        vadd.s32        q5,  q5,  q7
529
530        vadd.s32        q6,  q6,  q2 // out1
531        vadd.s32        q7,  q7,  q3
532
533        vsub.s32        q4,  q4,  q2 // out3
534        vsub.s32        q5,  q5,  q3
535
536        vqrshrn.s32     d20, q10, #12
537        vqrshrn.s32     d21, q11, #12
538
539        vqrshrn.s32     \o0, q8,  #12
540        vqrshrn.s32     \o1, q9,  #12
541
542.ifc \o4, d18
543        vmov            q9,  q10
544.endif
545
546        vqrshrn.s32     \o2, q6,  #12
547        vqrshrn.s32     \o3, q7,  #12
548
549        vqrshrn.s32     \o6, q4,  #12
550        vqrshrn.s32     \o7, q5,  #12
551.endm
552
553function inv_adst_8h_x4_neon, export=1
554        iadst_8x4       d16, d17, d18, d19, d20, d21, d22, d23
555        bx              lr
556endfunc
557
558function inv_flipadst_8h_x4_neon, export=1
559        iadst_8x4       d22, d23, d20, d21, d18, d19, d16, d17
560        bx              lr
561endfunc
562
563function inv_identity_4h_x4_neon, export=1
564        movw            r12, #(5793-4096)*8
565        vdup.16         d0,  r12
566        vqrdmulh.s16    q2,  q8,  d0[0]
567        vqrdmulh.s16    q3,  q9,  d0[0]
568        vqadd.s16       q8,  q8,  q2
569        vqadd.s16       q9,  q9,  q3
570        bx              lr
571endfunc
572
573function inv_identity_8h_x4_neon, export=1
574        movw            r12, #(5793-4096)*8
575        vdup.16         d0,  r12
576        vqrdmulh.s16    q1,  q8,  d0[0]
577        vqrdmulh.s16    q2,  q9,  d0[0]
578        vqrdmulh.s16    q3,  q10, d0[0]
579        vqadd.s16       q8,  q8,  q1
580        vqrdmulh.s16    q1,  q11, d0[0]
581        vqadd.s16       q9,  q9,  q2
582        vqadd.s16       q10, q10, q3
583        vqadd.s16       q11, q11, q1
584        bx              lr
585endfunc
586
587.macro identity_8x4_shift1 r0, r1, r2, r3, c
588.irp i, \r0, \r1, \r2, \r3
589        vqrdmulh.s16    q1,  \i,  \c
590        vrhadd.s16      \i,  \i,  q1
591.endr
592.endm
593
594function inv_txfm_add_wht_wht_4x4_8bpc_neon, export=1
595        push            {r4-r5,lr}
596        vmov.i16        q15, #0
597        vld1.16         {d16, d17, d18, d19}, [r2, :128]
598        vst1.16         {q15}, [r2, :128]!
599
600        vshr.s16        q8,  q8,  #2
601        vshr.s16        q9,  q9,  #2
602
603        iwht4
604
605        vst1.16         {q15}, [r2, :128]!
606        transpose_4x4h  q8,  q9,  d16, d17, d18, d19
607
608        iwht4
609
610        vld1.32         {d0[]},  [r0, :32], r1
611        vld1.32         {d0[1]}, [r0, :32], r1
612        vld1.32         {d1[]},  [r0, :32], r1
613        vld1.32         {d1[1]}, [r0, :32], r1
614
615        b               L(itx_4x4_end)
616endfunc
617
618function inv_txfm_add_4x4_neon
619        vmov.i16        q15, #0
620        vld1.16         {d16, d17, d18, d19}, [r2, :128]
621        vst1.16         {q15}, [r2, :128]!
622
623        blx             r4
624
625        vst1.16         {q15}, [r2, :128]!
626        transpose_4x4h  q8,  q9,  d16, d17, d18, d19
627
628        blx             r5
629
630        vld1.32         {d0[]},  [r0, :32], r1
631        vld1.32         {d0[1]}, [r0, :32], r1
632        vld1.32         {d1[]},  [r0, :32], r1
633        vld1.32         {d1[1]}, [r0, :32], r1
634        vrshr.s16       q8,  q8,  #4
635        vrshr.s16       q9,  q9,  #4
636
637L(itx_4x4_end):
638        sub             r0,  r0,  r1, lsl #2
639        vaddw.u8        q8,  q8,  d0
640        vqmovun.s16     d0,  q8
641        vaddw.u8        q9,  q9,  d1
642        vst1.32         {d0[0]}, [r0, :32], r1
643        vqmovun.s16     d1,  q9
644        vst1.32         {d0[1]}, [r0, :32], r1
645        vst1.32         {d1[0]}, [r0, :32], r1
646        vst1.32         {d1[1]}, [r0, :32], r1
647
648        pop             {r4-r5,pc}
649endfunc
650
651.macro def_fn_4x4 txfm1, txfm2
652function inv_txfm_add_\txfm1\()_\txfm2\()_4x4_8bpc_neon, export=1
653        push            {r4-r5,lr}
654
655.ifc \txfm1\()_\txfm2, dct_dct
656        cmp             r3,  #0
657        bne             1f
658        vmov.i16        d30, #0
659        movw            r12, #2896*8
660        vld1.16         {d16[]},  [r2, :16]
661        vdup.16         d4,  r12
662        vst1.16         {d30[0]}, [r2, :16]
663        vqrdmulh.s16    d16, d16, d4[0]
664        vld1.32         {d0[0]},  [r0, :32], r1
665        vqrdmulh.s16    d20, d16, d4[0]
666        vld1.32         {d0[1]},  [r0, :32], r1
667        vrshr.s16       d16, d20, #4
668        vrshr.s16       d17, d20, #4
669        vld1.32         {d1[0]},  [r0, :32], r1
670        vmov            q9,  q8
671        vld1.32         {d1[1]}, [r0, :32], r1
672        b               L(itx_4x4_end)
6731:
674.endif
675        movrel_local    r4,  inv_\txfm1\()_4h_x4_neon
676        movrel_local    r5,  inv_\txfm2\()_4h_x4_neon
677        b               inv_txfm_add_4x4_neon
678endfunc
679.endm
680
681def_fn_4x4 dct, dct
682def_fn_4x4 identity, identity
683def_fn_4x4 dct, adst
684def_fn_4x4 dct, flipadst
685def_fn_4x4 dct, identity
686def_fn_4x4 adst, dct
687def_fn_4x4 adst, adst
688def_fn_4x4 adst, flipadst
689def_fn_4x4 flipadst, dct
690def_fn_4x4 flipadst, adst
691def_fn_4x4 flipadst, flipadst
692def_fn_4x4 identity, dct
693
694def_fn_4x4 adst, identity
695def_fn_4x4 flipadst, identity
696def_fn_4x4 identity, adst
697def_fn_4x4 identity, flipadst
698
699.macro idct_8h_x8 q0, q1, q2, q3, q4, q5, q6, q7, r0, r1, r2, r3, r4, r5, r6, r7, r8, r9, r10, r11, r12, r13, r14, r15
700        idct_8h_x4      \q0, \q2, \q4, \q6, \r0, \r1, \r4, \r5, \r8, \r9, \r12, \r13
701
702        vmull_vmlsl_8h  q2,   q3,   \r2,  \r3,  \r14, \r15, d1[0], d1[1] // -> t4a
703        vmull_vmlal_8h  q4,   q5,   \r2,  \r3,  \r14, \r15, d1[1], d1[0] // -> t7a
704        vmull_vmlsl_8h  q6,   q7,   \r10, \r11, \r6,  \r7,  d1[2], d1[3] // -> t5a
705        vqrshrn_8h      \r2,  \r3,  q2,   q3,   #12         // t4a
706        vqrshrn_8h      \r14, \r15, q4,   q5,   #12         // t7a
707        vmull_vmlal_8h  q2,   q3,   \r10, \r11, \r6,  \r7,  d1[3], d1[2] // -> t6a
708        vqrshrn_8h      \r6,  \r7,  q6,   q7,   #12         // t5a
709        vqrshrn_8h      \r10, \r11, q2,   q3,   #12         // t6a
710
711        vqadd.s16       q2,   \q1,  \q3 // t4
712        vqsub.s16       \q1,  \q1,  \q3 // t5a
713        vqadd.s16       q3,   \q7,  \q5 // t7
714        vqsub.s16       \q3,  \q7,  \q5 // t6a
715
716        vmull_vmlsl_8h  q4,   q5,   \r6,  \r7,  \r2,  \r3,  d0[0], d0[0] // -> t5
717        vmull_vmlal_8h  q6,   q7,   \r6,  \r7,  \r2,  \r3,  d0[0], d0[0] // -> t6
718        vqrshrn_8h      d8,   d9,   q4,   q5,  #12 // t5
719        vqrshrn_8h      d10,  d11,  q6,   q7,  #12 // t6
720
721        vqsub.s16       \q7,  \q0,  q3 // out7
722        vqadd.s16       \q0,  \q0,  q3 // out0
723        vqadd.s16       \q1,  \q2,  q5 // out1
724        vqsub.s16       q6,   \q2,  q5 // out6
725        vqadd.s16       \q2,  \q4,  q4 // out2
726        vqsub.s16       \q5,  \q4,  q4 // out5
727        vqadd.s16       \q3,  \q6,  q2 // out3
728        vqsub.s16       \q4,  \q6,  q2 // out4
729        vmov            \q6,  q6       // out6
730.endm
731
732.macro idct_4h_x8 r0, r1, r2, r3, r4, r5, r6, r7
733        idct_4h_x4      \r0, \r2, \r4, \r6
734
735        vmull_vmlsl     q1,   \r1,  \r7, d1[0], d1[1] // -> t4a
736        vmull_vmlal     q2,   \r1,  \r7, d1[1], d1[0] // -> t7a
737        vmull_vmlsl     q3,   \r5,  \r3, d1[2], d1[3] // -> t5a
738        vqrshrn.s32     \r1,  q1,   #12               // t4a
739        vmull_vmlal     q1,   \r5,  \r3, d1[3], d1[2] // -> t6a
740        vqrshrn.s32     \r7,  q2,   #12               // t7a
741        vqrshrn.s32     \r3,  q3,   #12               // t5a
742        vqrshrn.s32     \r5,  q1,   #12               // taa
743
744        vqadd.s16       d2,   \r1,  \r3 // t4
745        vqsub.s16       \r1,  \r1,  \r3 // t5a
746        vqadd.s16       d3,   \r7,  \r5 // t7
747        vqsub.s16       \r3,  \r7,  \r5 // t6a
748
749        vmull_vmlsl     q2,   \r3,  \r1, d0[0], d0[0] // -> t5
750        vmull_vmlal     q3,   \r3,  \r1, d0[0], d0[0] // -> t6
751        vqrshrn.s32     d4,   q2,   #12               // t5
752        vqrshrn.s32     d5,   q3,   #12               // t6
753
754        vqsub.s16       \r7,  \r0,  d3 // out7
755        vqadd.s16       \r0,  \r0,  d3 // out0
756        vqadd.s16       \r1,  \r2,  d5 // out1
757        vqsub.s16       d6,   \r2,  d5 // out6
758        vqadd.s16       \r2,  \r4,  d4 // out2
759        vqsub.s16       \r5,  \r4,  d4 // out5
760        vqadd.s16       \r3,  \r6,  d2 // out3
761        vqsub.s16       \r4,  \r6,  d2 // out4
762        vmov            \r6,  d6       // out6
763.endm
764
765function inv_dct_8h_x8_neon, export=1
766        movrel_local    r12, idct_coeffs
767        vld1.16         {q0}, [r12, :128]
768        idct_8h_x8      q8,  q9,  q10, q11, q12, q13, q14, q15, d16, d17, d18, d19, d20, d21, d22, d23, d24, d25, d26, d27, d28, d29, d30, d31
769        bx              lr
770endfunc
771
772function inv_dct_4h_x8_neon, export=1
773        movrel_local    r12, idct_coeffs
774        vld1.16         {q0}, [r12, :128]
775        idct_4h_x8      d16, d17, d18, d19, d20, d21, d22, d23
776        bx              lr
777endfunc
778
779.macro iadst_8h_x8 q0, q1, q2, q3, q4, q5, q6, q7, r0, r1, r2, r3, r4, r5, r6, r7, r8, r9, r10, r11, r12, r13, r14, r15
780        movrel_local    r12, iadst8_coeffs
781        vld1.16         {d0, d1, d2}, [r12, :64]
782
783        vmull_vmlal_8h  q2,  q3,  d30, d31, d16, d17, d0[0], d0[1]
784        vmull_vmlsl_8h  q4,  q5,  d30, d31, d16, d17, d0[1], d0[0]
785        vmull_vmlal_8h  q6,  q7,  d26, d27, d20, d21, d0[2], d0[3]
786        vqrshrn_8h      d16, d17, q2,  q3,  #12  // t0a
787        vqrshrn_8h      d30, d31, q4,  q5,  #12  // t1a
788        vmull_vmlsl_8h  q2,  q3,  d26, d27, d20, d21, d0[3], d0[2]
789        vmull_vmlal_8h  q4,  q5,  d22, d23, d24, d25, d1[0], d1[1]
790        vqrshrn_8h      d20, d21, q6,  q7,  #12  // t2a
791        vqrshrn_8h      d26, d27, q2,  q3,  #12  // t3a
792        vmull_vmlsl_8h  q6,  q7,  d22, d23, d24, d25, d1[1], d1[0]
793        vmull_vmlal_8h  q2,  q3,  d18, d19, d28, d29, d1[2], d1[3]
794        vqrshrn_8h      d24, d25, q4,  q5,  #12  // t4a
795        vqrshrn_8h      d22, d23, q6,  q7,  #12  // t5a
796        vmull_vmlsl_8h  q4,  q5,  d18, d19, d28, d29, d1[3], d1[2]
797        vqrshrn_8h      d28, d29, q2,  q3,  #12  // t6a
798        vqrshrn_8h      d18, d19, q4,  q5,  #12  // t7a
799
800        vqadd.s16       q2,  q8,  q12 // t0
801        vqsub.s16       q3,  q8,  q12 // t4
802        vqadd.s16       q4,  q15, q11 // t1
803        vqsub.s16       q5,  q15, q11 // t5
804        vqadd.s16       q6,  q10, q14 // t2
805        vqsub.s16       q7,  q10, q14 // t6
806        vqadd.s16       q10, q13, q9  // t3
807        vqsub.s16       q11, q13, q9  // t7
808
809        vmull_vmlal_8h  q8,  q9,  d6,  d7,  d10, d11, d2[3], d2[2]
810        vmull_vmlsl_8h  q12, q13, d6,  d7,  d10, d11, d2[2], d2[3]
811        vmull_vmlsl_8h  q14, q15, d22, d23, d14, d15, d2[3], d2[2]
812
813        vqrshrn_8h      d6,  d7,  q8,  q9,  #12  // t4a
814        vqrshrn_8h      d10, d11, q12, q13, #12  // t5a
815
816        vmull_vmlal_8h  q8,  q9,  d22, d23, d14, d15, d2[2], d2[3]
817
818        vqrshrn_8h      d14, d15, q14, q15, #12  // t6a
819        vqrshrn_8h      d22, d23, q8,  q9,  #12  // t7a
820
821        vqadd.s16       \q0, q2,  q6  // out0
822        vqsub.s16       q2,  q2,  q6  // t2
823        vqadd.s16       \q7, q4,  q10 // out7
824        vqsub.s16       q4,  q4,  q10 // t3
825        vqneg.s16       \q7, \q7     // out7
826
827        vqadd.s16       \q1, q3,  q7  // out1
828        vqsub.s16       q3,  q3,  q7  // t6
829        vqadd.s16       \q6, q5,  q11 // out6
830        vqsub.s16       q5,  q5,  q11 // t7
831        vqneg.s16       \q1, \q1     // out1
832
833        vmull_vmlal_8h  q10, q11, d4,  d5,  d8,  d9,  d2[0], d2[0] // -> out3 (q11 or q12)
834        vmull_vmlsl_8h  q6,  q7,  d4,  d5,  d8,  d9,  d2[0], d2[0] // -> out4 (q12 or q11)
835        vmull_vmlsl_8h  q12, q13, d6,  d7,  d10, d11, d2[0], d2[0] // -> out5 (q13 or q10)
836        vqrshrn_8h      d4,  d5,  q10, q11, #12 // out3
837        vmull_vmlal_8h  q10, q11, d6,  d7,  d10, d11, d2[0], d2[0] // -> out2 (q10 or q13)
838        vqrshrn_8h      d6,  d7,  q12, q13, #12 // out5
839        vqrshrn_8h      \r4, \r5, q10, q11, #12 // out2 (q10 or q13)
840        vqrshrn_8h      \r8, \r9, q6,  q7,  #12 // out4 (q12 or q11)
841
842        vqneg.s16       \q3, q2     // out3
843        vqneg.s16       \q5, q3     // out5
844.endm
845
846.macro iadst_4h_x8 r0, r1, r2, r3, r4, r5, r6, r7
847        movrel_local    r12, iadst8_coeffs
848        vld1.16         {d0, d1, d2}, [r12, :64]
849
850        vmull_vmlal     q2,  d23, d16, d0[0], d0[1]
851        vmull_vmlsl     q3,  d23, d16, d0[1], d0[0]
852        vmull_vmlal     q4,  d21, d18, d0[2], d0[3]
853        vqrshrn.s32     d16, q2,  #12 // t0a
854        vqrshrn.s32     d23, q3,  #12 // t1a
855        vmull_vmlsl     q5,  d21, d18, d0[3], d0[2]
856        vmull_vmlal     q6,  d19, d20, d1[0], d1[1]
857        vqrshrn.s32     d18, q4,  #12 // t2a
858        vqrshrn.s32     d21, q5,  #12 // t3a
859        vmull_vmlsl     q7,  d19, d20, d1[1], d1[0]
860        vmull_vmlal     q2,  d17, d22, d1[2], d1[3]
861        vqrshrn.s32     d20, q6,  #12 // t4a
862        vqrshrn.s32     d19, q7,  #12 // t5a
863        vmull_vmlsl     q3,  d17, d22, d1[3], d1[2]
864        vqrshrn.s32     d22, q2,  #12 // t6a
865        vqrshrn.s32     d17, q3,  #12 // t7a
866
867        vqadd.s16       d4,  d16, d20 // t0
868        vqsub.s16       d5,  d16, d20 // t4
869        vqadd.s16       d6,  d23, d19 // t1
870        vqsub.s16       d7,  d23, d19 // t5
871        vqadd.s16       d8,  d18, d22 // t2
872        vqsub.s16       d9,  d18, d22 // t6
873        vqadd.s16       d18, d21, d17 // t3
874        vqsub.s16       d19, d21, d17 // t7
875
876        vmull_vmlal     q8,  d5,  d7,  d2[3], d2[2]
877        vmull_vmlsl     q10, d5,  d7,  d2[2], d2[3]
878        vmull_vmlsl     q11, d19, d9,  d2[3], d2[2]
879
880        vqrshrn.s32     d5,  q8,  #12 // t4a
881        vqrshrn.s32     d7,  q10, #12 // t5a
882
883        vmull_vmlal     q8,  d19, d9,  d2[2], d2[3]
884
885        vqrshrn.s32     d9,  q11, #12 // t6a
886        vqrshrn.s32     d19, q8,  #12 // t7a
887
888        vqadd.s16       \r0, d4,  d8  // out0
889        vqsub.s16       d4,  d4,  d8  // t2
890        vqadd.s16       \r7, d6,  d18 // out7
891        vqsub.s16       d6,  d6,  d18 // t3
892        vqneg.s16       \r7, \r7      // out7
893
894        vqadd.s16       \r1, d5,  d9  // out1
895        vqsub.s16       d5,  d5,  d9  // t6
896        vqadd.s16       \r6, d7,  d19 // out6
897        vqsub.s16       d7,  d7,  d19 // t7
898        vqneg.s16       \r1, \r1      // out1
899
900        vmull_vmlal     q9,  d4,  d6,  d2[0], d2[0] // -> out3 (d19 or d20)
901        vmull_vmlsl     q4,  d4,  d6,  d2[0], d2[0] // -> out4 (d20 or d19)
902        vmull_vmlsl     q10, d5,  d7,  d2[0], d2[0] // -> out5 (d21 or d18)
903        vqrshrn.s32     d4,  q9,  #12 // out3
904        vmull_vmlal     q9,  d5,  d7,  d2[0], d2[0] // -> out2 (d18 or d21)
905        vqrshrn.s32     d5,  q10, #12 // out5
906        vqrshrn.s32     \r2, q9,  #12 // out2 (d18 or d21)
907        vqrshrn.s32     \r4, q4,  #12 // out4 (d20 or d19)
908
909        vqneg.s16       \r3, d4       // out3
910        vqneg.s16       \r5, d5       // out5
911.endm
912
913function inv_adst_8h_x8_neon, export=1
914        iadst_8h_x8     q8,  q9,  q10, q11, q12, q13, q14, q15, d16, d17, d18, d19, d20, d21, d22, d23, d24, d25, d26, d27, d28, d29, d30, d31
915        bx              lr
916endfunc
917
918function inv_flipadst_8h_x8_neon, export=1
919        iadst_8h_x8     q15, q14, q13, q12, q11, q10, q9,  q8,  d30, d31, d28, d29, d26, d27, d24, d25, d22, d23, d20, d21, d18, d19, d16, d17
920        bx              lr
921endfunc
922
923function inv_adst_4h_x8_neon, export=1
924        iadst_4h_x8     d16, d17, d18, d19, d20, d21, d22, d23
925        bx              lr
926endfunc
927
928function inv_flipadst_4h_x8_neon, export=1
929        iadst_4h_x8     d23, d22, d21, d20, d19, d18, d17, d16
930        bx              lr
931endfunc
932
933function inv_identity_8h_x8_neon, export=1
934        vqshl.s16       q8,  q8,  #1
935        vqshl.s16       q9,  q9,  #1
936        vqshl.s16       q10, q10, #1
937        vqshl.s16       q11, q11, #1
938        vqshl.s16       q12, q12, #1
939        vqshl.s16       q13, q13, #1
940        vqshl.s16       q14, q14, #1
941        vqshl.s16       q15, q15, #1
942        bx              lr
943endfunc
944
945function inv_identity_4h_x8_neon, export=1
946        vqshl.s16       q8,  q8,  #1
947        vqshl.s16       q9,  q9,  #1
948        vqshl.s16       q10, q10, #1
949        vqshl.s16       q11, q11, #1
950        bx              lr
951endfunc
952
953.macro def_fn_8x8_base variant
954function inv_txfm_\variant\()add_8x8_neon
955        vmov.i16        q0,  #0
956        vmov.i16        q1,  #0
957        vld1.16         {q8,  q9},  [r2, :128]
958        vst1.16         {q0,  q1},  [r2, :128]!
959        vld1.16         {q10, q11}, [r2, :128]
960        vst1.16         {q0,  q1},  [r2, :128]!
961        vld1.16         {q12, q13}, [r2, :128]
962        vst1.16         {q0,  q1},  [r2, :128]!
963        vld1.16         {q14, q15}, [r2, :128]
964        vst1.16         {q0,  q1},  [r2, :128]
965
966.ifc \variant, identity_
967        // The identity shl #1 and downshift srshr #1 cancel out
968
969        b               L(itx_8x8_epilog)
970.else
971        blx             r4
972
973        vrshr.s16       q8,  q8,  #1
974        vrshr.s16       q9,  q9,  #1
975        vrshr.s16       q10, q10, #1
976        vrshr.s16       q11, q11, #1
977        vrshr.s16       q12, q12, #1
978        vrshr.s16       q13, q13, #1
979        vrshr.s16       q14, q14, #1
980        vrshr.s16       q15, q15, #1
981
982L(itx_8x8_epilog):
983        transpose_8x8h  q8,  q9,  q10, q11, q12, q13, q14, q15, d17, d19, d21, d23, d24, d26, d28, d30
984
985        blx             r5
986
987        load_add_store_8x8 r0, r7
988        vpop            {q4-q7}
989        pop             {r4-r5,r7,pc}
990.endif
991endfunc
992.endm
993
994def_fn_8x8_base identity_
995def_fn_8x8_base
996
997.macro def_fn_8x8 txfm1, txfm2
998function inv_txfm_add_\txfm1\()_\txfm2\()_8x8_8bpc_neon, export=1
999.ifc \txfm1\()_\txfm2, dct_dct
1000        idct_dc         8,   8,   1
1001.endif
1002        push            {r4-r5,r7,lr}
1003        vpush           {q4-q7}
1004        movrel_local    r5,  inv_\txfm2\()_8h_x8_neon
1005.ifc \txfm1, identity
1006        b               inv_txfm_identity_add_8x8_neon
1007.else
1008        movrel_local    r4,  inv_\txfm1\()_8h_x8_neon
1009        b               inv_txfm_add_8x8_neon
1010.endif
1011endfunc
1012.endm
1013
1014def_fn_8x8 dct, dct
1015def_fn_8x8 identity, identity
1016def_fn_8x8 dct, adst
1017def_fn_8x8 dct, flipadst
1018def_fn_8x8 dct, identity
1019def_fn_8x8 adst, dct
1020def_fn_8x8 adst, adst
1021def_fn_8x8 adst, flipadst
1022def_fn_8x8 flipadst, dct
1023def_fn_8x8 flipadst, adst
1024def_fn_8x8 flipadst, flipadst
1025def_fn_8x8 identity, dct
1026def_fn_8x8 adst, identity
1027def_fn_8x8 flipadst, identity
1028def_fn_8x8 identity, adst
1029def_fn_8x8 identity, flipadst
1030
1031function inv_txfm_add_8x4_neon
1032        vmov.i16        q14, #0
1033        vmov.i16        q15, #0
1034        movw            r12, #2896*8
1035        vdup.16         d0,  r12
1036        vld1.16         {d16, d17, d18, d19}, [r2, :128]
1037        vst1.16         {q14, q15}, [r2, :128]!
1038        vld1.16         {d20, d21, d22, d23}, [r2, :128]
1039        vst1.16         {q14, q15}, [r2, :128]
1040
1041        scale_input     d0[0], q8,  q9, q10, q11
1042
1043        blx             r4
1044
1045        transpose_4x4h  q8,  q9,  d16, d17, d18, d19
1046        transpose_4x4h  q10, q11, d20, d21, d22, d23
1047        vswp            d17, d20
1048        vswp            d19, d21
1049        vswp            d18, d20
1050        vswp            d21, d22
1051
1052        blx             r5
1053
1054        load_add_store_8x4 r0, r7
1055        vpop            {q4-q7}
1056        pop             {r4-r5,r7,pc}
1057endfunc
1058
1059function inv_txfm_add_4x8_neon
1060        vmov.i16        q14, #0
1061        vmov.i16        q15, #0
1062        movw            r12, #2896*8
1063        vdup.16         d0,  r12
1064        vld1.16         {q8,  q9},  [r2, :128]
1065        vst1.16         {q14, q15}, [r2, :128]!
1066        vld1.16         {q10, q11}, [r2, :128]
1067        vst1.16         {q14, q15}, [r2, :128]
1068
1069        scale_input     d0[0], q8,  q9, q10, q11
1070
1071        blx             r4
1072
1073        transpose_4x8h  q8,  q9,  q10, q11
1074        vswp            d17, d20
1075        vswp            d19, d21
1076        vswp            d17, d18
1077        vswp            d19, d22
1078
1079        blx             r5
1080
1081        load_add_store_4x8 r0, r7
1082        vpop            {q4-q7}
1083        pop             {r4-r5,r7,pc}
1084endfunc
1085
1086.macro def_fn_48 w, h, txfm1, txfm2
1087function inv_txfm_add_\txfm1\()_\txfm2\()_\w\()x\h\()_8bpc_neon, export=1
1088.ifc \txfm1\()_\txfm2, dct_dct
1089        idct_dc         \w,  \h,  0
1090.endif
1091        push            {r4-r5,r7,lr}
1092        vpush           {q4-q7}
1093        movrel_local    r4,  inv_\txfm1\()_\h\()h_x\w\()_neon
1094        movrel_local    r5,  inv_\txfm2\()_\w\()h_x\h\()_neon
1095        b               inv_txfm_add_\w\()x\h\()_neon
1096endfunc
1097.endm
1098
1099.macro def_fns_48 w, h
1100def_fn_48 \w, \h, dct, dct
1101def_fn_48 \w, \h, identity, identity
1102def_fn_48 \w, \h, dct, adst
1103def_fn_48 \w, \h, dct, flipadst
1104def_fn_48 \w, \h, dct, identity
1105def_fn_48 \w, \h, adst, dct
1106def_fn_48 \w, \h, adst, adst
1107def_fn_48 \w, \h, adst, flipadst
1108def_fn_48 \w, \h, flipadst, dct
1109def_fn_48 \w, \h, flipadst, adst
1110def_fn_48 \w, \h, flipadst, flipadst
1111def_fn_48 \w, \h, identity, dct
1112def_fn_48 \w, \h, adst, identity
1113def_fn_48 \w, \h, flipadst, identity
1114def_fn_48 \w, \h, identity, adst
1115def_fn_48 \w, \h, identity, flipadst
1116.endm
1117
1118def_fns_48 4, 8
1119def_fns_48 8, 4
1120
1121function inv_dct_4h_x16_neon, export=1
1122        movrel_local    r12, idct_coeffs
1123        vld1.16         {q0, q1}, [r12, :128]
1124
1125        vmull_vmlsl     q2,  d17, d31, d2[0], d2[1]  // -> t8a
1126        vmull_vmlal     q3,  d17, d31, d2[1], d2[0]  // -> t15a
1127        vmull_vmlsl     q4,  d25, d23, d2[2], d2[3]  // -> t9a
1128        vqrshrn.s32     d17, q2,  #12                // t8a
1129        vqrshrn.s32     d31, q3,  #12                // t15a
1130        vmull_vmlal     q2,  d25, d23, d2[3], d2[2]  // -> t14a
1131        vmull_vmlsl     q3,  d21, d27, d3[0], d3[1]  // -> t10a
1132        vqrshrn.s32     d23, q4,  #12                // t9a
1133        vqrshrn.s32     d25, q2,  #12                // t14a
1134        vmull_vmlal     q4,  d21, d27, d3[1], d3[0]  // -> t13a
1135        vmull_vmlsl     q2,  d29, d19, d3[2], d3[3]  // -> t11a
1136        vqrshrn.s32     d21, q3,  #12                // t10a
1137        vqrshrn.s32     d27, q4,  #12                // t13a
1138        vmull_vmlal     q3,  d29, d19, d3[3], d3[2]  // -> t12a
1139        vqrshrn.s32     d19, q2,  #12                // t11a
1140        vqrshrn.s32     d29, q3,  #12                // t12a
1141
1142        idct_4h_x8      d16, d18, d20, d22, d24, d26, d28, d30
1143
1144        vqsub.s16       d4,  d17, d23  // t9
1145        vqadd.s16       d17, d17, d23  // t8
1146        vqsub.s16       d5,  d31, d25  // t14
1147        vqadd.s16       d31, d31, d25  // t15
1148        vqsub.s16       d23, d19, d21  // t10
1149        vqadd.s16       d19, d19, d21  // t11
1150        vqadd.s16       d25, d29, d27  // t12
1151        vqsub.s16       d29, d29, d27  // t13
1152
1153        vmull_vmlsl     q3,  d5,  d4,  d0[2], d0[3]  // -> t9a
1154        vmull_vmlal     q4,  d5,  d4,  d0[3], d0[2]  // -> t14a
1155        vqrshrn.s32     d21, q3,  #12                // t9a
1156        vqrshrn.s32     d27, q4,  #12                // t14a
1157
1158        vmull_vmlsl     q3,  d29, d23, d0[2], d0[3]  // -> t13a
1159        vmull_vmlal     q4,  d29, d23, d0[3], d0[2]  // -> t10a
1160        vqrshrn.s32     d29, q3,  #12                // t13a
1161        vneg.s32        q4,  q4
1162        vqrshrn.s32     d23, q4,  #12                // t10a
1163
1164        vqsub.s16       d4,  d17, d19  // t11a
1165        vqadd.s16       d17, d17, d19  // t8a
1166        vqsub.s16       d5,  d31, d25  // t12a
1167        vqadd.s16       d31, d31, d25  // t15a
1168        vqadd.s16       d19, d21, d23  // t9
1169        vqsub.s16       d21, d21, d23  // t10
1170        vqsub.s16       d25, d27, d29  // t13
1171        vqadd.s16       d27, d27, d29  // t14
1172
1173        vmull_vmlsl     q3,  d5,  d4,  d0[0], d0[0]  // -> t11
1174        vmull_vmlal     q4,  d5,  d4,  d0[0], d0[0]  // -> t12
1175        vmull_vmlsl     q2,  d25, d21, d0[0], d0[0]  // -> t10a
1176
1177        vqrshrn.s32     d6,  q3,  #12  // t11
1178        vqrshrn.s32     d7,  q4,  #12  // t12
1179        vmull_vmlal     q4,  d25, d21, d0[0], d0[0]  // -> t13a
1180        vqrshrn.s32     d4,  q2,  #12  // t10a
1181        vqrshrn.s32     d5,  q4,  #12  // t13a
1182
1183        vqadd.s16       d8,  d16, d31  // out0
1184        vqsub.s16       d31, d16, d31  // out15
1185        vmov            d16, d8
1186        vqadd.s16       d23, d30, d17  // out7
1187        vqsub.s16       d9,  d30, d17  // out8
1188        vqadd.s16       d17, d18, d27  // out1
1189        vqsub.s16       d30, d18, d27  // out14
1190        vqadd.s16       d18, d20, d5   // out2
1191        vqsub.s16       d29, d20, d5   // out13
1192        vqadd.s16       d5,  d28, d19  // out6
1193        vqsub.s16       d25, d28, d19  // out9
1194        vqadd.s16       d19, d22, d7   // out3
1195        vqsub.s16       d28, d22, d7   // out12
1196        vqadd.s16       d20, d24, d6   // out4
1197        vqsub.s16       d27, d24, d6   // out11
1198        vqadd.s16       d21, d26, d4   // out5
1199        vqsub.s16       d26, d26, d4   // out10
1200        vmov            d24, d9
1201        vmov            d22, d5
1202
1203        bx              lr
1204endfunc
1205
1206.macro iadst_16 o0, o1, o2, o3, o4, o5, o6, o7, o8, o9, o10, o11, o12, o13, o14, o15
1207        movrel_local    r12, iadst16_coeffs
1208        vld1.16         {q0, q1}, [r12, :128]
1209        movrel_local    r12, idct_coeffs
1210
1211        vmull_vmlal     q2,  d31, d16, d0[0], d0[1] // -> t0
1212        vmull_vmlsl     q3,  d31, d16, d0[1], d0[0] // -> t1
1213        vmull_vmlal     q4,  d29, d18, d0[2], d0[3] // -> t2
1214        vqrshrn.s32     d16, q2,  #12               // t0
1215        vqrshrn.s32     d31, q3,  #12               // t1
1216        vmull_vmlsl     q2,  d29, d18, d0[3], d0[2] // -> t3
1217        vmull_vmlal     q3,  d27, d20, d1[0], d1[1] // -> t4
1218        vqrshrn.s32     d18, q4,  #12               // t2
1219        vqrshrn.s32     d29, q2,  #12               // t3
1220        vmull_vmlsl     q4,  d27, d20, d1[1], d1[0] // -> t5
1221        vmull_vmlal     q2,  d25, d22, d1[2], d1[3] // -> t6
1222        vqrshrn.s32     d20, q3,  #12               // t4
1223        vqrshrn.s32     d27, q4,  #12               // t5
1224        vmull_vmlsl     q3,  d25, d22, d1[3], d1[2] // -> t7
1225        vmull_vmlal     q4,  d23, d24, d2[0], d2[1] // -> t8
1226        vqrshrn.s32     d22, q2,  #12               // t6
1227        vqrshrn.s32     d25, q3,  #12               // t7
1228        vmull_vmlsl     q2,  d23, d24, d2[1], d2[0] // -> t9
1229        vmull_vmlal     q3,  d21, d26, d2[2], d2[3] // -> t10
1230        vqrshrn.s32     d23, q4,  #12               // t8
1231        vqrshrn.s32     d24, q2,  #12               // t9
1232        vmull_vmlsl     q4,  d21, d26, d2[3], d2[2] // -> t11
1233        vmull_vmlal     q2,  d19, d28, d3[0], d3[1] // -> t12
1234        vqrshrn.s32     d21, q3,  #12               // t10
1235        vqrshrn.s32     d26, q4,  #12               // t11
1236        vmull_vmlsl     q3,  d19, d28, d3[1], d3[0] // -> t13
1237        vmull_vmlal     q4,  d17, d30, d3[2], d3[3] // -> t14
1238        vqrshrn.s32     d19, q2,  #12               // t12
1239        vqrshrn.s32     d28, q3,  #12               // t13
1240        vmull_vmlsl     q2,  d17, d30, d3[3], d3[2] // -> t15
1241        vqrshrn.s32     d17, q4,  #12               // t14
1242        vqrshrn.s32     d30, q2,  #12               // t15
1243
1244        vld1.16         {q0}, [r12, :128]
1245
1246        vqsub.s16       d2,  d16, d23 // t8a
1247        vqadd.s16       d16, d16, d23 // t0a
1248        vqsub.s16       d3,  d31, d24 // t9a
1249        vqadd.s16       d31, d31, d24 // t1a
1250        vqadd.s16       d23, d18, d21 // t2a
1251        vqsub.s16       d18, d18, d21 // t10a
1252        vqadd.s16       d24, d29, d26 // t3a
1253        vqsub.s16       d29, d29, d26 // t11a
1254        vqadd.s16       d21, d20, d19 // t4a
1255        vqsub.s16       d20, d20, d19 // t12a
1256        vqadd.s16       d26, d27, d28 // t5a
1257        vqsub.s16       d27, d27, d28 // t13a
1258        vqadd.s16       d19, d22, d17 // t6a
1259        vqsub.s16       d22, d22, d17 // t14a
1260        vqadd.s16       d28, d25, d30 // t7a
1261        vqsub.s16       d25, d25, d30 // t15a
1262
1263        vmull_vmlal     q2,  d2,  d3,  d1[1], d1[0] // -> t8
1264        vmull_vmlsl     q3,  d2,  d3,  d1[0], d1[1] // -> t9
1265        vmull_vmlal     q4,  d18, d29, d1[3], d1[2] // -> t10
1266        vqrshrn.s32     d17, q2,  #12               // t8
1267        vqrshrn.s32     d30, q3,  #12               // t9
1268        vmull_vmlsl     q2,  d18, d29, d1[2], d1[3] // -> t11
1269        vmull_vmlsl     q3,  d27, d20, d1[1], d1[0] // -> t12
1270        vqrshrn.s32     d18, q4,  #12               // t10
1271        vqrshrn.s32     d29, q2,  #12               // t11
1272        vmull_vmlal     q4,  d27, d20, d1[0], d1[1] // -> t13
1273        vmull_vmlsl     q2,  d25, d22, d1[3], d1[2] // -> t14
1274        vqrshrn.s32     d27, q3,  #12               // t12
1275        vqrshrn.s32     d20, q4,  #12               // t13
1276        vmull_vmlal     q3,  d25, d22, d1[2], d1[3] // -> t15
1277        vqrshrn.s32     d25, q2,  #12               // t14
1278        vqrshrn.s32     d22, q3,  #12               // t15
1279
1280        vqsub.s16       d2,  d16, d21 // t4
1281        vqadd.s16       d16, d16, d21 // t0
1282        vqsub.s16       d3,  d31, d26 // t5
1283        vqadd.s16       d31, d31, d26 // t1
1284        vqadd.s16       d21, d23, d19 // t2
1285        vqsub.s16       d23, d23, d19 // t6
1286        vqadd.s16       d26, d24, d28 // t3
1287        vqsub.s16       d24, d24, d28 // t7
1288        vqadd.s16       d19, d17, d27 // t8a
1289        vqsub.s16       d17, d17, d27 // t12a
1290        vqadd.s16       d28, d30, d20 // t9a
1291        vqsub.s16       d30, d30, d20 // t13a
1292        vqadd.s16       d27, d18, d25 // t10a
1293        vqsub.s16       d18, d18, d25 // t14a
1294        vqadd.s16       d20, d29, d22 // t11a
1295        vqsub.s16       d29, d29, d22 // t15a
1296
1297        vmull_vmlal     q2,  d2,  d3,  d0[3], d0[2] // -> t4a
1298        vmull_vmlsl     q3,  d2,  d3,  d0[2], d0[3] // -> t5a
1299        vmull_vmlsl     q4,  d24, d23, d0[3], d0[2] // -> t6a
1300        vqrshrn.s32     d22, q2,  #12               // t4a
1301        vqrshrn.s32     d25, q3,  #12               // t5a
1302        vmull_vmlal     q2,  d24, d23, d0[2], d0[3] // -> t7a
1303        vmull_vmlal     q3,  d17, d30, d0[3], d0[2] // -> t12
1304        vqrshrn.s32     d24, q4,  #12               // t6a
1305        vqrshrn.s32     d23, q2,  #12               // t7a
1306        vmull_vmlsl     q4,  d17, d30, d0[2], d0[3] // -> t13
1307        vmull_vmlsl     q2,  d29, d18, d0[3], d0[2] // -> t14
1308        vqrshrn.s32     d17, q3,  #12               // t12
1309        vmull_vmlal     q3,  d29, d18, d0[2], d0[3] // -> t15
1310        vqrshrn.s32     d29, q4,  #12               // t13
1311        vqrshrn.s32     d30, q2,  #12               // t14
1312        vqrshrn.s32     d18, q3,  #12               // t15
1313
1314        vqsub.s16       d2,  d16, d21 // t2a
1315.ifc \o0, d16
1316        vqadd.s16       \o0, d16, d21 // out0
1317        vqsub.s16       d21, d31, d26 // t3a
1318        vqadd.s16       \o15,d31, d26 // out15
1319.else
1320        vqadd.s16       d4,  d16, d21 // out0
1321        vqsub.s16       d21, d31, d26 // t3a
1322        vqadd.s16       \o15,d31, d26 // out15
1323        vmov            \o0, d4
1324.endif
1325        vqneg.s16       \o15, \o15    // out15
1326
1327        vqsub.s16       d3,  d29, d18 // t15a
1328        vqadd.s16       \o13,d29, d18 // out13
1329        vqadd.s16       \o2, d17, d30 // out2
1330        vqsub.s16       d26, d17, d30 // t14a
1331        vqneg.s16       \o13,\o13     // out13
1332
1333        vqadd.s16       \o1, d19, d27 // out1
1334        vqsub.s16       d27, d19, d27 // t10
1335        vqadd.s16       \o14,d28, d20 // out14
1336        vqsub.s16       d20, d28, d20 // t11
1337        vqneg.s16       \o1, \o1      // out1
1338
1339        vqadd.s16       \o3, d22, d24 // out3
1340        vqsub.s16       d22, d22, d24 // t6
1341        vqadd.s16       \o12,d25, d23 // out12
1342        vqsub.s16       d23, d25, d23 // t7
1343        vqneg.s16       \o3, \o3      // out3
1344
1345        vmull_vmlsl     q12, d2,  d21, d0[0], d0[0] // -> out8 (d24 or d23)
1346        vmull_vmlal     q2,  d2,  d21, d0[0], d0[0] // -> out7 (d23 or d24)
1347        vmull_vmlal     q3,  d26, d3,  d0[0], d0[0] // -> out5 (d21 or d26)
1348
1349        vqrshrn.s32     d24, q12, #12 // out8
1350        vqrshrn.s32     d4,  q2,  #12 // out7
1351        vqrshrn.s32     d5,  q3,  #12 // out5
1352        vmull_vmlsl     q4,  d26, d3,  d0[0], d0[0] // -> out10 (d26 or d21)
1353        vmull_vmlal     q1,  d22, d23, d0[0], d0[0] // -> out4 (d20 or d27)
1354        vqrshrn.s32     d26, q4,  #12 // out10
1355
1356        vmull_vmlsl     q4,  d22, d23, d0[0], d0[0] // -> out11 (d27 or d20)
1357        vmull_vmlal     q11, d27, d20, d0[0], d0[0] // -> out6 (d22 or d25)
1358        vmull_vmlsl     q3,  d27, d20, d0[0], d0[0] // -> out9 (d25 or d22)
1359
1360        vqrshrn.s32     \o4, q1,  #12 // out4
1361        vqrshrn.s32     d7,  q3,  #12 // out9
1362        vqrshrn.s32     d6,  q4,  #12 // out11
1363        vqrshrn.s32     \o6, q11, #12 // out6
1364
1365.ifc \o8, d23
1366        vmov            \o8, d24
1367        vmov            \o10,d26
1368.endif
1369
1370        vqneg.s16       \o7, d4  // out7
1371        vqneg.s16       \o5, d5  // out5
1372        vqneg.s16       \o11,d6  // out11
1373        vqneg.s16       \o9, d7  // out9
1374.endm
1375
1376function inv_adst_4h_x16_neon, export=1
1377        iadst_16        d16, d17, d18, d19, d20, d21, d22, d23, d24, d25, d26, d27, d28, d29, d30, d31
1378        bx              lr
1379endfunc
1380
1381function inv_flipadst_4h_x16_neon, export=1
1382        iadst_16        d31, d30, d29, d28, d27, d26, d25, d24, d23, d22, d21, d20, d19, d18, d17, d16
1383        bx              lr
1384endfunc
1385
1386function inv_identity_4h_x16_neon, export=1
1387        movw            r12, #2*(5793-4096)*8
1388        vdup.16         d0,  r12
1389.irp i, q8, q9, q10, q11, q12, q13, q14, q15
1390        vqrdmulh.s16    q1,  \i,  d0[0]
1391        vqadd.s16       \i,  \i,  \i
1392        vqadd.s16       \i,  \i,  q1
1393.endr
1394        bx              lr
1395endfunc
1396
1397.macro identity_4x16_shift2 c
1398.irp i, q8, q9, q10, q11, q12, q13, q14, q15
1399        vqrdmulh.s16    q2,  \i,  \c
1400        vshr.s16        q2,  q2,  #1
1401        vrhadd.s16      \i,  \i,  q2
1402.endr
1403.endm
1404
1405.macro identity_4x16_shift1 c
1406.irp i, q8, q9, q10, q11, q12, q13, q14, q15
1407        vqrdmulh.s16    q2,  \i,  \c
1408        vrshr.s16       q2,  q2,  #1
1409        vqadd.s16       \i,  \i,  q2
1410.endr
1411.endm
1412
1413.macro identity_8x8_shift1 c
1414        identity_4x16_shift1 \c
1415.endm
1416
1417.macro identity_8x8 c
1418.irp i, q8, q9, q10, q11, q12, q13, q14, q15
1419        vqrdmulh.s16    q2,  \i,  \c
1420        vqadd.s16       \i,  \i,  \i
1421        vqadd.s16       \i,  \i,  q2
1422.endr
1423.endm
1424
1425.macro def_horz_16 scale=0, identity=0, shift=2, suffix
1426function inv_txfm_horz\suffix\()_16x4_neon
1427        push            {lr}
1428        vmov.i16        d7,  #0
1429.if \identity
1430        movw            r12, #2*(5793-4096)*8
1431        vdup.16         d0,  r12
1432.endif
1433.if \scale
1434        movw            r12, #2896*8
1435        vdup.16         d1,  r12
1436.endif
1437.irp i, d16, d17, d18, d19, d20, d21, d22, d23, d24, d25, d26, d27, d28, d29, d30, d31
1438        vld1.16         {\i}, [r7, :64]
1439        vst1.16         {d7}, [r7, :64], r8
1440.endr
1441.if \scale
1442        scale_input     d1[0], q8,  q9, q10, q11, q12, q13, q14, q15
1443.endif
1444.if \identity
1445.if \shift == -2
1446        identity_4x16_shift2 d0[0]
1447.else
1448        identity_4x16_shift1 d0[0]
1449.endif
1450        b               L(horz_16x4_epilog)
1451.else
1452        blx             r4
1453.irp i, q8, q9, q10, q11, q12, q13, q14, q15
1454        vrshr.s16       \i,  \i,  #\shift
1455.endr
1456.if \shift == 1
1457        b               L(horz_16x4_epilog)
1458.else
1459L(horz_16x4_epilog):
1460        transpose_4x4h  q8,  q9,  d16, d17, d18, d19
1461        transpose_4x4h  q10, q11, d20, d21, d22, d23
1462        transpose_4x4h  q12, q13, d24, d25, d26, d27
1463        transpose_4x4h  q14, q15, d28, d29, d30, d31
1464
1465.irp i, d16, d20, d24, d28, d17, d21, d25, d29, d18, d22, d26, d30, d19, d23, d27, d31
1466        vst1.16         {\i}, [r6, :64]!
1467.endr
1468
1469        pop             {pc}
1470.endif
1471.endif
1472endfunc
1473.endm
1474
1475def_horz_16 scale=1, identity=1, shift=-1, suffix=_scale_identity
1476def_horz_16 scale=0, identity=1, shift=-2, suffix=_identity
1477def_horz_16 scale=1, identity=0, shift=1, suffix=_scale
1478def_horz_16 scale=0, identity=0, shift=2
1479
1480function inv_txfm_add_vert_4x16_neon
1481        push            {lr}
1482.irp i, d16, d17, d18, d19, d20, d21, d22, d23, d24, d25, d26, d27, d28, d29, d30, d31
1483        vld1.16         {\i}, [r7, :64], r8
1484.endr
1485        blx             r5
1486        load_add_store_4x16 r6, r7
1487        pop             {pc}
1488endfunc
1489
1490function inv_txfm_add_16x16_neon
1491        sub_sp_align    512
1492        ldrh            r11, [r10], #2
1493.irp i, 0, 4, 8, 12
1494        add             r6,  sp,  #(\i*16*2)
1495.if \i > 0
1496        mov             r8,  #(16 - \i)
1497        cmp             r3,  r11
1498        blt             1f
1499.if \i < 12
1500        ldrh            r11, [r10], #2
1501.endif
1502.endif
1503        add             r7,  r2,  #(\i*2)
1504        mov             r8,  #16*2
1505        blx             r9
1506.endr
1507        b               3f
15081:
1509        vmov.i16        q2,  #0
1510        vmov.i16        q3,  #0
15112:
1512        subs            r8,  r8,  #4
1513.rept 4
1514        vst1.16         {q2, q3}, [r6, :128]!
1515.endr
1516        bgt             2b
15173:
1518.irp i, 0, 4, 8, 12
1519        add             r6,  r0,  #(\i)
1520        add             r7,  sp,  #(\i*2)
1521        mov             r8,  #32
1522        bl              inv_txfm_add_vert_4x16_neon
1523.endr
1524
1525        add_sp_align    512
1526        vpop            {q4}
1527        pop             {r4-r11,pc}
1528endfunc
1529
1530const eob_16x16
1531        .short 10, 36, 78, 256
1532endconst
1533
1534const eob_16x16_identity
1535        .short 4, 8, 12, 256
1536endconst
1537
1538.macro def_fn_16x16 txfm1, txfm2
1539function inv_txfm_add_\txfm1\()_\txfm2\()_16x16_8bpc_neon, export=1
1540.ifc \txfm1\()_\txfm2, dct_dct
1541        idct_dc         16,  16,  2
1542.endif
1543        push            {r4-r11,lr}
1544        vpush           {q4}
1545.ifc \txfm1, identity
1546        movrel_local    r9,  inv_txfm_horz_identity_16x4_neon
1547.else
1548        movrel_local    r9,  inv_txfm_horz_16x4_neon
1549        movrel_local    r4,  inv_\txfm1\()_4h_x16_neon
1550.endif
1551        movrel_local    r5,  inv_\txfm2\()_4h_x16_neon
1552.ifc \txfm1, identity
1553.ifc \txfm2, identity
1554        movrel_local    r10, eob_16x16
1555.else
1556        movrel_local    r10, eob_16x16_identity
1557.endif
1558.else
1559.ifc \txfm2, identity
1560        movrel_local    r10, eob_16x16_identity
1561.else
1562        movrel_local    r10, eob_16x16
1563.endif
1564.endif
1565        b               inv_txfm_add_16x16_neon
1566endfunc
1567.endm
1568
1569def_fn_16x16 dct, dct
1570def_fn_16x16 identity, identity
1571def_fn_16x16 dct, adst
1572def_fn_16x16 dct, flipadst
1573def_fn_16x16 dct, identity
1574def_fn_16x16 adst, dct
1575def_fn_16x16 adst, adst
1576def_fn_16x16 adst, flipadst
1577def_fn_16x16 flipadst, dct
1578def_fn_16x16 flipadst, adst
1579def_fn_16x16 flipadst, flipadst
1580def_fn_16x16 identity, dct
1581
1582.macro def_fn_416_base variant
1583function inv_txfm_\variant\()add_16x4_neon
1584
1585.ifc \variant, identity_
1586        vmov.i16        d4,  #0
1587.irp i, d16, d18, d20, d22
1588        vld1.16         {\i}, [r2, :64]
1589        vst1.16         {d4}, [r2, :64]!
1590.endr
1591.irp i, d17, d19, d21, d23
1592        vld1.16         {\i}, [r2, :64]
1593        vst1.16         {d4}, [r2, :64]!
1594.endr
1595        movw            r12, #2*(5793-4096)*8
1596        vdup.16         d0,  r12
1597.irp i, d24, d26, d28, d30
1598        vld1.16         {\i}, [r2, :64]
1599        vst1.16         {d4}, [r2, :64]!
1600.endr
1601.irp i, d25, d27, d29, d31
1602        vld1.16         {\i}, [r2, :64]
1603        vst1.16         {d4}, [r2, :64]!
1604.endr
1605
1606        identity_4x16_shift1 d0[0]
1607
1608        b               L(itx_16x4_epilog)
1609.else
1610        vmov.i16        q2,  #0
1611        vmov.i16        q3,  #0
1612        vld1.16         {d16, d17, d18, d19}, [r2, :128]
1613        vst1.16         {q2,  q3}, [r2, :128]!
1614        vld1.16         {d20, d21, d22, d23}, [r2, :128]
1615        vst1.16         {q2,  q3}, [r2, :128]!
1616        vld1.16         {d24, d25, d26, d27}, [r2, :128]
1617        vst1.16         {q2,  q3}, [r2, :128]!
1618        vld1.16         {d28, d29, d30, d31}, [r2, :128]
1619        vst1.16         {q2,  q3}, [r2, :128]!
1620
1621        blx             r4
1622
1623        vswp            d17, d20
1624        vswp            d19, d22
1625        vswp            d18, d20
1626        vswp            d19, d21
1627        vswp            d25, d28
1628        vswp            d27, d30
1629        vswp            d26, d28
1630        vswp            d27, d29
1631.irp i, q8, q9, q10, q11, q12, q13, q14, q15
1632        vrshr.s16       \i,  \i,  #1
1633.endr
1634
1635L(itx_16x4_epilog):
1636        transpose_4x8h  q8,  q9,  q10, q11
1637        blx             r5
1638        mov             r6,  r0
1639        load_add_store_8x4 r6, r7
1640
1641        vmov            q8,  q12
1642        vmov            q9,  q13
1643        vmov            q10, q14
1644        vmov            q11, q15
1645
1646        transpose_4x8h  q8,  q9,  q10, q11
1647        blx             r5
1648        add             r6,  r0,  #8
1649        load_add_store_8x4 r6, r7
1650
1651        vpop            {q4-q7}
1652        pop             {r4-r11,pc}
1653.endif
1654endfunc
1655
1656function inv_txfm_\variant\()add_4x16_neon
1657        vmov.i16        q2,  #0
1658
1659        mov             r11, #32
1660        cmp             r3,  r10
1661        blt             1f
1662
1663        add             r6,  r2,  #16
1664.ifc \variant, identity_
1665.irp i, q12, q13, q14, q15
1666        vld1.16         {\i}, [r6, :128]
1667        vst1.16         {q2}, [r6, :128], r11
1668.endr
1669        movw            r12, #(5793-4096)*8
1670        vdup.16         d0,  r12
1671        identity_8x4_shift1 q12, q13, q14, q15, d0[0]
1672.else
1673.irp i, q8,  q9,  q10, q11
1674        vld1.16         {\i}, [r6, :128]
1675        vst1.16         {q2}, [r6, :128], r11
1676.endr
1677        blx             r4
1678        vrshr.s16       q12, q8,  #1
1679        vrshr.s16       q13, q9,  #1
1680        vrshr.s16       q14, q10, #1
1681        vrshr.s16       q15, q11, #1
1682.endif
1683        transpose_4x8h  q12, q13, q14, q15
1684        vswp            d27, d29
1685        vswp            d26, d28
1686        vswp            d27, d30
1687        vswp            d25, d28
1688
1689        b               2f
16901:
1691.irp i, q12, q13, q14, q15
1692        vmov.i16        \i,  #0
1693.endr
16942:
1695        vmov.i16        q2,  #0
1696.irp i, q8,  q9,  q10, q11
1697        vld1.16         {\i}, [r2, :128]
1698        vst1.16         {q2}, [r2, :128], r11
1699.endr
1700.ifc \variant, identity_
1701        movw            r12, #(5793-4096)*8
1702        vdup.16         d0,  r12
1703        identity_8x4_shift1 q8,  q9,  q10, q11, d0[0]
1704
1705        b               L(itx_4x16_epilog)
1706.else
1707        blx             r4
1708.irp i, q8, q9, q10, q11
1709        vrshr.s16       \i,  \i,  #1
1710.endr
1711L(itx_4x16_epilog):
1712        transpose_4x8h  q8,  q9,  q10, q11
1713        vswp            d19, d21
1714        vswp            d18, d20
1715        vswp            d19, d22
1716        vswp            d17, d20
1717
1718        blx             r5
1719
1720        load_add_store_4x16 r0, r6
1721
1722        vpop            {q4-q7}
1723        pop             {r4-r11,pc}
1724.endif
1725endfunc
1726.endm
1727
1728def_fn_416_base identity_
1729def_fn_416_base
1730
1731.macro def_fn_416 w, h, txfm1, txfm2, eob_half
1732function inv_txfm_add_\txfm1\()_\txfm2\()_\w\()x\h\()_8bpc_neon, export=1
1733.ifc \txfm1\()_\txfm2, dct_dct
1734        idct_dc         \w,  \h,  1
1735.endif
1736        push            {r4-r11,lr}
1737        vpush           {q4-q7}
1738.if \w == 4
1739.ifnc \txfm1, identity
1740        movrel_local    r4,  inv_\txfm1\()_8h_x\w\()_neon
1741.endif
1742        movrel_local    r5,  inv_\txfm2\()_4h_x\h\()_neon
1743        mov             r10, #\eob_half
1744.else
1745.ifnc \txfm1, identity
1746        movrel_local    r4,  inv_\txfm1\()_4h_x\w\()_neon
1747.endif
1748        movrel_local    r5,  inv_\txfm2\()_8h_x\h\()_neon
1749.endif
1750.ifc \txfm1, identity
1751        b               inv_txfm_identity_add_\w\()x\h\()_neon
1752.else
1753        b               inv_txfm_add_\w\()x\h\()_neon
1754.endif
1755endfunc
1756.endm
1757
1758.macro def_fns_416 w, h
1759def_fn_416 \w, \h, dct, dct, 29
1760def_fn_416 \w, \h, identity, identity, 29
1761def_fn_416 \w, \h, dct, adst, 29
1762def_fn_416 \w, \h, dct, flipadst, 29
1763def_fn_416 \w, \h, dct, identity, 8
1764def_fn_416 \w, \h, adst, dct, 29
1765def_fn_416 \w, \h, adst, adst, 29
1766def_fn_416 \w, \h, adst, flipadst, 29
1767def_fn_416 \w, \h, flipadst, dct, 29
1768def_fn_416 \w, \h, flipadst, adst, 29
1769def_fn_416 \w, \h, flipadst, flipadst, 29
1770def_fn_416 \w, \h, identity, dct, 32
1771def_fn_416 \w, \h, adst, identity, 8
1772def_fn_416 \w, \h, flipadst, identity, 8
1773def_fn_416 \w, \h, identity, adst, 32
1774def_fn_416 \w, \h, identity, flipadst, 32
1775.endm
1776
1777def_fns_416 4, 16
1778def_fns_416 16, 4
1779
1780function inv_txfm_add_16x8_neon
1781        sub_sp_align    256
1782
1783.irp i, 0, 4
1784        add             r6,  sp,  #(\i*16*2)
1785.if \i > 0
1786        cmp             r3,  r10
1787        blt             1f
1788.endif
1789        add             r7,  r2,  #(\i*2)
1790        mov             r8,  #8*2
1791        blx             r9
1792.endr
1793        b               2f
17941:
1795        vmov.i16        q2,  #0
1796        vmov.i16        q3,  #0
1797.rept 4
1798        vst1.16         {q2, q3}, [r6, :128]!
1799.endr
18002:
1801
1802.irp i, 0, 8
1803        add             r7,  sp,  #(\i*2)
1804        mov             r8,  #32
1805.irp j, q8, q9, q10, q11, q12, q13, q14, q15
1806        vld1.16         {\j}, [r7, :128], r8
1807.endr
1808        blx             r5
1809
1810        add             r6,  r0,  #(\i)
1811        load_add_store_8x8 r6, r7
1812.endr
1813
1814        add_sp_align    256
1815        vpop            {q4-q7}
1816        pop             {r4-r11,pc}
1817endfunc
1818
1819.macro def_fn_816_base variant
1820function inv_txfm_\variant\()add_8x16_neon
1821        sub_sp_align    256
1822
1823.irp i, 0, 8
1824        add             r6,  sp,  #(\i*8*2)
1825.if \i > 0
1826        cmp             r3,  r10
1827        blt             1f
1828.endif
1829        add             r7,  r2,  #(\i*2)
1830        mov             r8,  #16*2
1831
1832        vmov.i16        q2,  #0
1833        movw            r12, #2896*8
1834        vdup.16         d0,  r12
1835
1836.irp j, q8, q9, q10, q11, q12, q13, q14, q15
1837        vld1.16         {\j}, [r7, :128]
1838        vst1.16         {q2}, [r7, :128], r8
1839.endr
1840        scale_input     d0[0], q8,  q9,  q10, q11, q12, q13, q14, q15
1841.ifc \variant, identity_
1842        // The identity shl #1 and downshift vrshr #1 cancel out
1843.else
1844        blx             r4
1845.irp j, q8, q9, q10, q11, q12, q13, q14, q15
1846        vrshr.s16       \j,  \j,  #1
1847.endr
1848.endif
1849        transpose_8x8h  q8,  q9,  q10, q11, q12, q13, q14, q15, d17, d19, d21, d23, d24, d26, d28, d30
1850        vst1.16         {q8,  q9},  [r6, :128]!
1851        vst1.16         {q10, q11}, [r6, :128]!
1852        vst1.16         {q12, q13}, [r6, :128]!
1853        vst1.16         {q14, q15}, [r6, :128]!
1854.endr
1855        b               2f
18561:
1857        vmov.i16        q2,  #0
1858        vmov.i16        q3,  #0
1859.rept 4
1860        vst1.16         {q2, q3}, [r6, :128]!
1861.endr
18622:
1863
1864.ifc \variant, identity_
1865        b               L(itx_8x16_epilog)
1866.else
1867L(itx_8x16_epilog):
1868.irp i, 0, 4
1869        add             r6,  r0,  #(\i)
1870        add             r7,  sp,  #(\i*2)
1871        mov             r8,  #16
1872        bl              inv_txfm_add_vert_4x16_neon
1873.endr
1874
1875        add_sp_align    256
1876        vpop            {q4-q7}
1877        pop             {r4-r11,pc}
1878.endif
1879endfunc
1880.endm
1881
1882def_fn_816_base identity_
1883def_fn_816_base
1884
1885/* Define symbols used in .if statement */
1886.equ dct, 1
1887.equ identity, 2
1888.equ adst, 3
1889.equ flipadst, 4
1890
1891.macro def_fn_816 w, h, txfm1, txfm2, eob_8x8, eob_4x4
1892function inv_txfm_add_\txfm1\()_\txfm2\()_\w\()x\h\()_8bpc_neon, export=1
1893.ifc \txfm1\()_\txfm2, dct_dct
1894        idct_dc         \w,  \h,  1
1895.endif
1896        push            {r4-r11,lr}
1897        vpush           {q4-q7}
1898.if \w == 8
1899.ifnc \txfm1, identity
1900        movrel_local    r4,  inv_\txfm1\()_8h_x8_neon
1901.endif
1902        movrel_local    r5,  inv_\txfm2\()_4h_x16_neon
1903.else
1904.ifc \txfm1, identity
1905        movrel_local    r9,  inv_txfm_horz_scale_identity_16x4_neon
1906.else
1907        movrel_local    r4,  inv_\txfm1\()_4h_x16_neon
1908        movrel_local    r9,  inv_txfm_horz_scale_16x4_neon
1909.endif
1910        movrel_local    r5,  inv_\txfm2\()_8h_x8_neon
1911.endif
1912.if \w == 8
1913        mov             r10, #\eob_8x8
1914.else
1915        mov             r10, #\eob_4x4
1916.endif
1917.if \w == 8 && \txfm1 == identity
1918        b               inv_txfm_identity_add_\w\()x\h\()_neon
1919.else
1920        b               inv_txfm_add_\w\()x\h\()_neon
1921.endif
1922endfunc
1923.endm
1924
1925.macro def_fns_816 w, h
1926def_fn_816 \w, \h, dct, dct, 43, 10
1927def_fn_816 \w, \h, identity, identity, 43, 10
1928def_fn_816 \w, \h, dct, adst, 43, 10
1929def_fn_816 \w, \h, dct, flipadst, 43, 10
1930def_fn_816 \w, \h, dct, identity, 8, 4
1931def_fn_816 \w, \h, adst, dct, 43, 10
1932def_fn_816 \w, \h, adst, adst, 43, 10
1933def_fn_816 \w, \h, adst, flipadst, 43, 10
1934def_fn_816 \w, \h, flipadst, dct, 43, 10
1935def_fn_816 \w, \h, flipadst, adst, 43, 10
1936def_fn_816 \w, \h, flipadst, flipadst, 43, 10
1937def_fn_816 \w, \h, identity, dct, 64, 4
1938def_fn_816 \w, \h, adst, identity, 8, 4
1939def_fn_816 \w, \h, flipadst, identity, 8, 4
1940def_fn_816 \w, \h, identity, adst, 64, 4
1941def_fn_816 \w, \h, identity, flipadst, 64, 4
1942.endm
1943
1944def_fns_816 8, 16
1945def_fns_816 16, 8
1946
1947function inv_dct32_odd_4h_x16_neon, export=1
1948        movrel_local    r12, idct_coeffs, 2*16
1949        vld1.16         {q0, q1}, [r12, :128]
1950        sub             r12, r12, #2*16
1951
1952        vmull_vmlsl     q2,  d16, d31, d0[0], d0[1] // -> t16a
1953        vmull_vmlal     q3,  d16, d31, d0[1], d0[0] // -> t31a
1954        vmull_vmlsl     q4,  d24, d23, d0[2], d0[3] // -> t17a
1955        vqrshrn.s32     d16, q2,  #12               // t16a
1956        vqrshrn.s32     d31, q3,  #12               // t31a
1957        vmull_vmlal     q2,  d24, d23, d0[3], d0[2] // -> t30a
1958        vmull_vmlsl     q3,  d20, d27, d1[0], d1[1] // -> t18a
1959        vqrshrn.s32     d24, q4,  #12               // t17a
1960        vqrshrn.s32     d23, q2,  #12               // t30a
1961        vmull_vmlal     q4,  d20, d27, d1[1], d1[0] // -> t29a
1962        vmull_vmlsl     q2,  d28, d19, d1[2], d1[3] // -> t19a
1963        vqrshrn.s32     d20, q3,  #12               // t18a
1964        vqrshrn.s32     d27, q4,  #12               // t29a
1965        vmull_vmlal     q3,  d28, d19, d1[3], d1[2] // -> t28a
1966        vmull_vmlsl     q4,  d18, d29, d2[0], d2[1] // -> t20a
1967        vqrshrn.s32     d28, q2,  #12               // t19a
1968        vqrshrn.s32     d19, q3,  #12               // t28a
1969        vmull_vmlal     q2,  d18, d29, d2[1], d2[0] // -> t27a
1970        vmull_vmlsl     q3,  d26, d21, d2[2], d2[3] // -> t21a
1971        vqrshrn.s32     d18, q4,  #12               // t20a
1972        vqrshrn.s32     d29, q2,  #12               // t27a
1973        vmull_vmlal     q4,  d26, d21, d2[3], d2[2] // -> t26a
1974        vmull_vmlsl     q2,  d22, d25, d3[0], d3[1] // -> t22a
1975        vqrshrn.s32     d26, q3,  #12               // t21a
1976        vqrshrn.s32     d21, q4,  #12               // t26a
1977        vmull_vmlal     q3,  d22, d25, d3[1], d3[0] // -> t25a
1978        vmull_vmlsl     q4,  d30, d17, d3[2], d3[3] // -> t23a
1979        vqrshrn.s32     d22, q2,  #12               // t22a
1980        vqrshrn.s32     d25, q3,  #12               // t25a
1981        vmull_vmlal     q2,  d30, d17, d3[3], d3[2] // -> t24a
1982        vqrshrn.s32     d30, q4,  #12               // t23a
1983        vqrshrn.s32     d17, q2,  #12               // t24a
1984
1985        vld1.16         {q0}, [r12, :128]
1986
1987        vqsub.s16       d2,  d16, d24 // t17
1988        vqadd.s16       d16, d16, d24 // t16
1989        vqsub.s16       d3,  d31, d23 // t30
1990        vqadd.s16       d31, d31, d23 // t31
1991        vqsub.s16       d24, d28, d20 // t18
1992        vqadd.s16       d28, d28, d20 // t19
1993        vqadd.s16       d23, d18, d26 // t20
1994        vqsub.s16       d18, d18, d26 // t21
1995        vqsub.s16       d20, d30, d22 // t22
1996        vqadd.s16       d30, d30, d22 // t23
1997        vqadd.s16       d26, d17, d25 // t24
1998        vqsub.s16       d17, d17, d25 // t25
1999        vqsub.s16       d22, d29, d21 // t26
2000        vqadd.s16       d29, d29, d21 // t27
2001        vqadd.s16       d25, d19, d27 // t28
2002        vqsub.s16       d19, d19, d27 // t29
2003
2004        vmull_vmlsl     q2,  d3,  d2,  d1[0], d1[1] // -> t17a
2005        vmull_vmlal     q3,  d3,  d2,  d1[1], d1[0] // -> t30a
2006        vmull_vmlal     q4,  d19, d24, d1[1], d1[0] // -> t18a
2007        vqrshrn.s32     d21, q2,  #12               // t17a
2008        vqrshrn.s32     d27, q3,  #12               // t30a
2009        vneg.s32        q4,  q4                     // -> t18a
2010        vmull_vmlsl     q1,  d19, d24, d1[0], d1[1] // -> t29a
2011        vmull_vmlsl     q2,  d22, d18, d1[2], d1[3] // -> t21a
2012        vqrshrn.s32     d19, q4,  #12               // t18a
2013        vqrshrn.s32     d24, q1,  #12               // t29a
2014        vmull_vmlal     q3,  d22, d18, d1[3], d1[2] // -> t26a
2015        vmull_vmlal     q4,  d17, d20, d1[3], d1[2] // -> t22a
2016        vqrshrn.s32     d22, q2,  #12               // t21a
2017        vqrshrn.s32     d18, q3,  #12               // t26a
2018        vneg.s32        q4,  q4                     // -> t22a
2019        vmull_vmlsl     q1,  d17, d20, d1[2], d1[3] // -> t25a
2020        vqrshrn.s32     d17, q4,  #12               // t22a
2021        vqrshrn.s32     d20, q1,  #12               // t25a
2022
2023        vqsub.s16       d2,  d27, d24 // t29
2024        vqadd.s16       d27, d27, d24 // t30
2025        vqsub.s16       d3,  d21, d19 // t18
2026        vqadd.s16       d21, d21, d19 // t17
2027        vqsub.s16       d24, d16, d28 // t19a
2028        vqadd.s16       d16, d16, d28 // t16a
2029        vqsub.s16       d19, d30, d23 // t20a
2030        vqadd.s16       d30, d30, d23 // t23a
2031        vqsub.s16       d28, d17, d22 // t21
2032        vqadd.s16       d17, d17, d22 // t22
2033        vqadd.s16       d23, d26, d29 // t24a
2034        vqsub.s16       d26, d26, d29 // t27a
2035        vqadd.s16       d22, d20, d18 // t25
2036        vqsub.s16       d20, d20, d18 // t26
2037        vqsub.s16       d29, d31, d25 // t28a
2038        vqadd.s16       d31, d31, d25 // t31a
2039
2040        vmull_vmlsl     q2,  d2,  d3,  d0[2], d0[3] // -> t18a
2041        vmull_vmlal     q3,  d2,  d3,  d0[3], d0[2] // -> t29a
2042        vmull_vmlsl     q4,  d29, d24, d0[2], d0[3] // -> t19
2043        vqrshrn.s32     d18, q2,  #12               // t18a
2044        vqrshrn.s32     d25, q3,  #12               // t29a
2045        vmull_vmlal     q1,  d29, d24, d0[3], d0[2] // -> t28
2046        vmull_vmlal     q2,  d26, d19, d0[3], d0[2] // -> t20
2047        vqrshrn.s32     d29, q4,  #12               // t19
2048        vqrshrn.s32     d24, q1,  #12               // t28
2049        vneg.s32        q2,  q2                     // -> t20
2050        vmull_vmlsl     q3,  d26, d19, d0[2], d0[3] // -> t27
2051        vmull_vmlal     q4,  d20, d28, d0[3], d0[2] // -> t21a
2052        vqrshrn.s32     d26, q2,  #12               // t20
2053        vqrshrn.s32     d19, q3,  #12               // t27
2054        vneg.s32        q4,  q4                     // -> t21a
2055        vmull_vmlsl     q1,  d20, d28, d0[2], d0[3] // -> t26a
2056        vqrshrn.s32     d20, q4,  #12               // t21a
2057        vqrshrn.s32     d28, q1,  #12               // t26a
2058
2059        vqsub.s16       d2,  d16, d30 // t23
2060        vqadd.s16       d16, d16, d30 // t16 = out16
2061        vqsub.s16       d3,  d31, d23 // t24
2062        vqadd.s16       d31, d31, d23 // t31 = out31
2063        vqsub.s16       d23, d21, d17 // t22a
2064        vqadd.s16       d17, d21, d17 // t17a = out17
2065        vqadd.s16       d30, d27, d22 // t30a = out30
2066        vqsub.s16       d21, d27, d22 // t25a
2067        vqsub.s16       d27, d18, d20 // t21
2068        vqadd.s16       d18, d18, d20 // t18 = out18
2069        vqadd.s16       d4,  d29, d26 // t19a = out19
2070        vqsub.s16       d26, d29, d26 // t20a
2071        vqadd.s16       d29, d25, d28 // t29 = out29
2072        vqsub.s16       d25, d25, d28 // t26
2073        vqadd.s16       d28, d24, d19 // t28a = out28
2074        vqsub.s16       d24, d24, d19 // t27a
2075        vmov            d19, d4       // out19
2076
2077        vmull_vmlsl     q2,  d24, d26, d0[0], d0[0] // -> t20
2078        vmull_vmlal     q3,  d24, d26, d0[0], d0[0] // -> t27
2079        vqrshrn.s32     d20, q2,  #12   // t20
2080        vqrshrn.s32     d22, q3,  #12   // t27
2081
2082        vmull_vmlal     q2,  d25, d27, d0[0], d0[0] // -> t26a
2083        vmull_vmlsl     q3,  d25, d27, d0[0], d0[0] // -> t21a
2084        vmov            d27, d22        // t27
2085        vqrshrn.s32     d26, q2,  #12   // t26a
2086
2087        vmull_vmlsl     q12, d21, d23, d0[0], d0[0] // -> t22
2088        vmull_vmlal     q2,  d21, d23, d0[0], d0[0] // -> t25
2089        vqrshrn.s32     d21, q3,  #12   // t21a
2090        vqrshrn.s32     d22, q12, #12   // t22
2091        vqrshrn.s32     d25, q2,  #12   // t25
2092
2093        vmull_vmlsl     q2,  d3,  d2,  d0[0], d0[0] // -> t23a
2094        vmull_vmlal     q3,  d3,  d2,  d0[0], d0[0] // -> t24a
2095        vqrshrn.s32     d23, q2,  #12   // t23a
2096        vqrshrn.s32     d24, q3,  #12   // t24a
2097
2098        bx              lr
2099endfunc
2100
2101.macro def_horz_32 scale=0, shift=2, suffix
2102function inv_txfm_horz\suffix\()_dct_32x4_neon
2103        push            {lr}
2104        vmov.i16        d7,  #0
2105        lsl             r8,  r8,  #1
2106.if \scale
2107        movw            r12, #2896*8
2108        vdup.16         d0,  r12
2109.endif
2110
2111.irp i, d16, d17, d18, d19, d20, d21, d22, d23, d24, d25, d26, d27, d28, d29, d30, d31
2112        vld1.16         {\i}, [r7, :64]
2113        vst1.16         {d7}, [r7, :64], r8
2114.endr
2115        sub             r7,  r7,  r8, lsl #4
2116        add             r7,  r7,  r8, lsr #1
2117.if \scale
2118        scale_input     d0[0], q8,  q9,  q10, q11, q12, q13, q14, q15
2119.endif
2120        bl              inv_dct_4h_x16_neon
2121        transpose_4x4h  q8,  q9,  d16, d17, d18, d19
2122        transpose_4x4h  q10, q11, d20, d21, d22, d23
2123        transpose_4x4h  q12, q13, d24, d25, d26, d27
2124        transpose_4x4h  q14, q15, d28, d29, d30, d31
2125
2126.macro store1 r0, r1, r2, r3
2127        vst1.16         {\r0}, [r6, :64]!
2128        vst1.16         {\r1}, [r6, :64]!
2129        vst1.16         {\r2}, [r6, :64]!
2130        vst1.16         {\r3}, [r6, :64]!
2131        add             r6,  r6,  #32
2132.endm
2133        store1          d16, d20, d24, d28
2134        store1          d17, d21, d25, d29
2135        store1          d18, d22, d26, d30
2136        store1          d19, d23, d27, d31
2137.purgem store1
2138        sub             r6,  r6,  #64*4
2139
2140        vmov.i16        d7,  #0
2141.irp i, d16, d17, d18, d19, d20, d21, d22, d23, d24, d25, d26, d27, d28, d29, d30, d31
2142        vld1.16         {\i}, [r7, :64]
2143        vst1.16         {d7}, [r7, :64], r8
2144.endr
2145.if \scale
2146        // This relies on the fact that the idct also leaves the right coeff in d0[1]
2147        scale_input     d0[1], q8,  q9,  q10, q11, q12, q13, q14, q15
2148.endif
2149        bl              inv_dct32_odd_4h_x16_neon
2150        transpose_4x4h  q15, q14, d31, d30, d29, d28
2151        transpose_4x4h  q13, q12, d27, d26, d25, d24
2152        transpose_4x4h  q11, q10, d23, d22, d21, d20
2153        transpose_4x4h  q9,  q8,  d19, d18, d17, d16
2154.macro store2 r0, r1, r2, r3, shift
2155        vld1.16         {q0, q1}, [r6, :128]
2156        vqsub.s16       d7,  d0,  \r0
2157        vqadd.s16       d0,  d0,  \r0
2158        vqsub.s16       d6,  d1,  \r1
2159        vqadd.s16       d1,  d1,  \r1
2160        vqsub.s16       d5,  d2,  \r2
2161        vqadd.s16       d2,  d2,  \r2
2162        vqsub.s16       d4,  d3,  \r3
2163        vqadd.s16       d3,  d3,  \r3
2164        vrev64.16       q2,  q2
2165        vrev64.16       q3,  q3
2166        vrshr.s16       q0,  q0,  #\shift
2167        vrshr.s16       q1,  q1,  #\shift
2168        vrshr.s16       q2,  q2,  #\shift
2169        vrshr.s16       q3,  q3,  #\shift
2170        vst1.16         {q0, q1}, [r6, :128]!
2171        vst1.16         {q2, q3}, [r6, :128]!
2172.endm
2173
2174        store2          d31, d27, d23, d19, \shift
2175        store2          d30, d26, d22, d18, \shift
2176        store2          d29, d25, d21, d17, \shift
2177        store2          d28, d24, d20, d16, \shift
2178.purgem store2
2179        pop             {pc}
2180endfunc
2181.endm
2182
2183def_horz_32 scale=0, shift=2
2184def_horz_32 scale=1, shift=1, suffix=_scale
2185
2186function inv_txfm_add_vert_dct_4x32_neon
2187        push            {r10-r11,lr}
2188        lsl             r8,  r8,  #1
2189
2190.irp i, d16, d17, d18, d19, d20, d21, d22, d23, d24, d25, d26, d27, d28, d29, d30, d31
2191        vld1.16         {\i}, [r7, :64], r8
2192.endr
2193        sub             r7,  r7,  r8, lsl #4
2194
2195        bl              inv_dct_4h_x16_neon
2196
2197.irp i, d16, d17, d18, d19, d20, d21, d22, d23, d24, d25, d26, d27, d28, d29, d30, d31
2198        vst1.16         {\i}, [r7, :64], r8
2199.endr
2200        sub             r7,  r7,  r8, lsl #4
2201        add             r7,  r7,  r8, lsr #1
2202
2203.irp i, d16, d17, d18, d19, d20, d21, d22, d23, d24, d25, d26, d27, d28, d29, d30, d31
2204        vld1.16         {\i}, [r7, :64], r8
2205.endr
2206        sub             r7,  r7,  r8, lsl #4
2207        sub             r7,  r7,  r8, lsr #1
2208        bl              inv_dct32_odd_4h_x16_neon
2209
2210        neg             r9,  r8
2211        mov             r10, r6
2212.macro combine r0, r1, r2, r3, op, stride
2213        vld1.16         {d4},    [r7,  :64], \stride
2214        vld1.32         {d2[0]}, [r10, :32], r1
2215        vld1.16         {d5},    [r7,  :64],  \stride
2216        vld1.32         {d2[1]}, [r10, :32], r1
2217        \op\().s16      d4,  d4,  \r0
2218        vld1.16         {d6},    [r7,  :64], \stride
2219        vld1.32         {d3[0]}, [r10, :32], r1
2220        \op\().s16      d5,  d5,  \r1
2221        vld1.32         {d3[1]}, [r10, :32], r1
2222        vrshr.s16       q2,  q2,  #4
2223        \op\().s16      d6,  d6,  \r2
2224        vld1.16         {d7},    [r7,  :64], \stride
2225        vaddw.u8        q2,  q2,  d2
2226        \op\().s16      d7,  d7,  \r3
2227        vqmovun.s16     d2,  q2
2228        vrshr.s16       q3,  q3,  #4
2229        vst1.32         {d2[0]}, [r6,  :32], r1
2230        vaddw.u8        q3,  q3,  d3
2231        vst1.32         {d2[1]}, [r6,  :32], r1
2232        vqmovun.s16     d3,  q3
2233        vst1.32         {d3[0]}, [r6,  :32], r1
2234        vst1.32         {d3[1]}, [r6,  :32], r1
2235.endm
2236        combine         d31, d30, d29, d28, vqadd, r8
2237        combine         d27, d26, d25, d24, vqadd, r8
2238        combine         d23, d22, d21, d20, vqadd, r8
2239        combine         d19, d18, d17, d16, vqadd, r8
2240        sub             r7,  r7,  r8
2241        combine         d16, d17, d18, d19, vqsub, r9
2242        combine         d20, d21, d22, d23, vqsub, r9
2243        combine         d24, d25, d26, d27, vqsub, r9
2244        combine         d28, d29, d30, d31, vqsub, r9
2245.purgem combine
2246
2247        pop             {r10-r11,pc}
2248endfunc
2249
2250const eob_32x32
2251        .short 10, 36, 78, 136, 210, 300, 406, 1024
2252endconst
2253
2254const eob_16x32
2255        .short 10, 36, 78, 151, 215, 279, 343, 512
2256endconst
2257
2258const eob_16x32_shortside
2259        .short 10, 36, 78, 512
2260endconst
2261
2262const eob_8x32
2263        // Contrary to the others, this one is only ever used in increments of 8x8
2264        .short 43, 107, 171, 256
2265endconst
2266
2267function inv_txfm_add_identity_identity_32x32_8bpc_neon, export=1
2268        push            {r4-r7,lr}
2269        vmov.i16        q0,  #0
2270        movrel_local    r5,  eob_32x32, 2
2271
2272        mov             r6,  #2*32
22731:
2274        mov             r12, #0
2275        movrel_local    r4,  eob_32x32, 2
22762:
2277        add             r12, r12, #8
2278.irp i, q8, q9, q10, q11, q12, q13, q14, q15
2279        vld1.16         {\i}, [r2, :128]
2280        vst1.16         {q0}, [r2, :128], r6
2281.endr
2282        transpose_8x8h  q8,  q9,  q10, q11, q12, q13, q14, q15, d17, d19, d21, d23, d24, d26, d28, d30
2283
2284        load_add_store_8x8 r0, r7, shiftbits=2
2285        ldrh            lr,  [r4], #4
2286        sub             r0,  r0,  r1, lsl #3
2287        cmp             r3,  lr
2288        add             r0,  r0,  #8
2289        bge             2b
2290
2291        ldrh            lr,  [r5], #4
2292        cmp             r3,  lr
2293        blt             9f
2294
2295        sub             r0,  r0,  r12
2296        add             r0,  r0,  r1, lsl #3
2297        mls             r2,  r6,  r12, r2
2298        add             r2,  r2,  #2*8
2299        b               1b
23009:
2301        pop             {r4-r7,pc}
2302endfunc
2303
2304.macro shift_8_regs op, shift
2305.irp i, q8, q9, q10, q11, q12, q13, q14, q15
2306        \op             \i,  \i,  #\shift
2307.endr
2308.endm
2309
2310.macro def_identity_1632 w, h, wshort, hshort
2311function inv_txfm_add_identity_identity_\w\()x\h\()_8bpc_neon, export=1
2312        push            {r4-r7,lr}
2313        movw            r6,  #2896*8
2314        movw            r7,  #2*(5793-4096)*8
2315        vdup.i16        d0,  r6
2316        movrel_local    r5,  eob_16x32\hshort, 2
2317        vmov.16         d0[1], r7
2318
2319        mov             r6,  #2*\h
23201:
2321        mov             r12, #0
2322        movrel_local    r4,  eob_16x32\wshort, 2
23232:
2324        vmov.i16        q1,  #0
2325        add             r12, r12, #8
2326.irp i, q8, q9, q10, q11, q12, q13, q14, q15
2327        vld1.16         {\i}, [r2, :128]
2328        vst1.16         {q1}, [r2, :128], r6
2329.endr
2330        scale_input     d0[0], q8,  q9, q10, q11, q12, q13, q14, q15
2331
2332.if \w == 16
2333        // 16x32
2334        identity_8x8_shift1 d0[1]
2335.else
2336        // 32x16
2337        shift_8_regs    vqshl.s16, 1
2338        identity_8x8    d0[1]
2339.endif
2340
2341        transpose_8x8h  q8,  q9,  q10, q11, q12, q13, q14, q15, d17, d19, d21, d23, d24, d26, d28, d30
2342
2343.if \w == 16
2344        load_add_store_8x8 r0, r7, shiftbits=2
2345.else
2346        load_add_store_8x8 r0, r7, shiftbits=4
2347.endif
2348        ldrh            lr,  [r4], #4
2349        sub             r0,  r0,  r1, lsl #3
2350        cmp             r3,  lr
2351        add             r0,  r0,  #8
2352        bge             2b
2353
2354        ldrh            lr,  [r5], #4
2355        cmp             r3,  lr
2356        blt             9f
2357
2358        sub             r0,  r0,  r12
2359        add             r0,  r0,  r1, lsl #3
2360        mls             r2,  r6,  r12, r2
2361        add             r2,  r2,  #2*8
2362        b               1b
23639:
2364        pop             {r4-r7,pc}
2365endfunc
2366.endm
2367
2368def_identity_1632 16, 32, _shortside,
2369def_identity_1632 32, 16, , _shortside
2370
2371.macro def_identity_832 w, h
2372function inv_txfm_add_identity_identity_\w\()x\h\()_8bpc_neon, export=1
2373        push            {r4-r5,lr}
2374        vmov.i16        q0,  #0
2375        movrel_local    r4,  eob_8x32
2376
2377        mov             r12, #2*\h
23781:
2379        ldrh            lr,  [r4], #2
2380.irp i, q8, q9, q10, q11, q12, q13, q14, q15
2381        vld1.16         {\i}, [r2, :128]
2382        vst1.16         {q0}, [r2, :128], r12
2383.endr
2384
2385.if \w == 8
2386        // 8x32
2387        shift_8_regs    vrshr.s16, 1
2388.endif
2389
2390        transpose_8x8h  q8,  q9,  q10, q11, q12, q13, q14, q15, d17, d19, d21, d23, d24, d26, d28, d30
2391
2392        cmp             r3,  lr
2393.if \w == 8
2394        load_add_store_8x8 r0, r5, shiftbits=2
2395.else
2396        load_add_store_8x8 r0, r5, shiftbits=3
2397.endif
2398
2399        blt             9f
2400.if \w == 8
2401        sub             r2,  r2,  r12, lsl #3
2402        add             r2,  r2,  #2*8
2403.else
2404        sub             r0,  r0,  r1, lsl #3
2405        add             r0,  r0,  #8
2406.endif
2407        b               1b
2408
24099:
2410        pop             {r4-r5,pc}
2411endfunc
2412.endm
2413
2414def_identity_832 8, 32
2415def_identity_832 32, 8
2416
2417function inv_txfm_add_dct_dct_32x32_8bpc_neon, export=1
2418        idct_dc         32,  32,  2
2419
2420        push            {r4-r11,lr}
2421        vpush           {q4}
2422        sub_sp_align    2048
2423        movrel_local    r10, eob_32x32
2424        ldrh            r11, [r10], #2
2425
2426.irp i, 0, 4, 8, 12, 16, 20, 24, 28
2427        add             r6,  sp,  #(\i*32*2)
2428.if \i > 0
2429        mov             r8,  #(32 - \i)
2430        cmp             r3,  r11
2431        blt             1f
2432.if \i < 28
2433        ldrh            r11, [r10], #2
2434.endif
2435.endif
2436        add             r7,  r2,  #(\i*2)
2437        mov             r8,  #32*2
2438        bl              inv_txfm_horz_dct_32x4_neon
2439.endr
2440        b               3f
2441
24421:
2443        vmov.i16        q2,  #0
2444        vmov.i16        q3,  #0
24452:
2446        subs            r8,  r8,  #2
2447.rept 4
2448        vst1.16         {q2, q3}, [r6, :128]!
2449.endr
2450        bgt             2b
2451
24523:
2453.irp i, 0, 4, 8, 12, 16, 20, 24, 28
2454        add             r6,  r0,  #(\i)
2455        add             r7,  sp,  #(\i*2)
2456        mov             r8,  #32*2
2457        bl              inv_txfm_add_vert_dct_4x32_neon
2458.endr
2459
2460        add_sp_align    2048
2461        vpop            {q4}
2462        pop             {r4-r11,pc}
2463endfunc
2464
2465function inv_txfm_add_dct_dct_16x32_8bpc_neon, export=1
2466        idct_dc         16,  32,  1
2467
2468        push            {r4-r11,lr}
2469        vpush           {q4}
2470        sub_sp_align    1024
2471        movrel_local    r10, eob_16x32
2472        ldrh            r11, [r10], #2
2473        movrel_local    r4,  inv_dct_4h_x16_neon
2474
2475.irp i, 0, 4, 8, 12, 16, 20, 24, 28
2476        add             r6,  sp,  #(\i*16*2)
2477        add             r7,  r2,  #(\i*2)
2478.if \i > 0
2479        mov             r8,  #(32 - \i)
2480        cmp             r3,  r11
2481        blt             1f
2482.if \i < 28
2483        ldrh            r11, [r10], #2
2484.endif
2485.endif
2486        mov             r8,  #2*32
2487        bl              inv_txfm_horz_scale_16x4_neon
2488.endr
2489        b               3f
2490
24911:
2492        vmov.i16        q2,  #0
2493        vmov.i16        q3,  #0
24942:
2495        subs            r8,  r8,  #4
2496.rept 4
2497        vst1.16         {q2, q3}, [r6, :128]!
2498.endr
2499        bgt             2b
2500
25013:
2502.irp i, 0, 4, 8, 12
2503        add             r6,  r0,  #(\i)
2504        add             r7,  sp,  #(\i*2)
2505        mov             r8,  #16*2
2506        bl              inv_txfm_add_vert_dct_4x32_neon
2507.endr
2508
2509        add_sp_align    1024
2510        vpop            {q4}
2511        pop             {r4-r11,pc}
2512endfunc
2513
2514function inv_txfm_add_dct_dct_32x16_8bpc_neon, export=1
2515        idct_dc         32,  16,  1
2516
2517        push            {r4-r11,lr}
2518        vpush           {q4}
2519        sub_sp_align    1024
2520        movrel_local    r10, eob_16x32
2521        ldrh            r11, [r10], #2
2522        movrel_local    r5,  inv_dct_4h_x16_neon
2523
2524.irp i, 0, 4, 8, 12
2525        add             r6,  sp,  #(\i*32*2)
2526        add             r7,  r2,  #(\i*2)
2527.if \i > 0
2528        mov             r8,  #(16 - \i)
2529        cmp             r3,  r11
2530        blt             1f
2531.if \i < 12
2532        ldrh            r11, [r10], #2
2533.endif
2534.endif
2535        mov             r8,  #2*16
2536        bl              inv_txfm_horz_scale_dct_32x4_neon
2537.endr
2538        b               3f
2539
25401:
2541        vmov.i16        q2,  #0
2542        vmov.i16        q3,  #0
25432:
2544        subs            r8,  r8,  #2
2545.rept 4
2546        vst1.16         {q2, q3}, [r6, :128]!
2547.endr
2548        bgt             2b
2549
25503:
2551.irp i, 0, 4, 8, 12, 16, 20, 24, 28
2552        add             r6,  r0,  #(\i)
2553        add             r7,  sp,  #(\i*2)
2554        mov             r8,  #32*2
2555        bl              inv_txfm_add_vert_4x16_neon
2556.endr
2557
2558        add_sp_align    1024
2559        vpop            {q4}
2560        pop             {r4-r11,pc}
2561endfunc
2562
2563function inv_txfm_add_dct_dct_8x32_8bpc_neon, export=1
2564        idct_dc         8,   32,  2
2565
2566        push            {r4-r11,lr}
2567        vpush           {q4-q7}
2568        sub_sp_align    512
2569
2570        movrel_local    r10, eob_8x32
2571
2572        mov             r8,  #2*32
2573        mov             r9,  #32
2574        mov             r6,  sp
25751:
2576        vmov.i16        q0,  #0
2577.irp i, q8, q9, q10, q11, q12, q13, q14, q15
2578        vld1.16         {\i}, [r2, :128]
2579        vst1.16         {q0}, [r2, :128], r8
2580.endr
2581        ldrh            r11, [r10], #2
2582        sub             r2,  r2,  r8, lsl #3
2583        sub             r9,  r9,  #8
2584        add             r2,  r2,  #2*8
2585
2586        bl              inv_dct_8h_x8_neon
2587
2588.irp i, q8, q9, q10, q11, q12, q13, q14, q15
2589        vrshr.s16       \i,  \i,  #2
2590.endr
2591
2592        transpose_8x8h  q8,  q9,  q10, q11, q12, q13, q14, q15, d17, d19, d21, d23, d24, d26, d28, d30
2593
2594        vst1.16         {q8,  q9},  [r6, :128]!
2595        cmp             r3,  r11
2596        vst1.16         {q10, q11}, [r6, :128]!
2597        vst1.16         {q12, q13}, [r6, :128]!
2598        vst1.16         {q14, q15}, [r6, :128]!
2599
2600        bge             1b
2601        cmp             r9,  #0
2602        beq             3f
2603
2604        vmov.i16        q2,  #0
2605        vmov.i16        q3,  #0
26062:
2607        subs            r9,  r9,  #8
2608.rept 4
2609        vst1.16         {q2, q3}, [r6, :128]!
2610.endr
2611        bgt             2b
2612
26133:
2614.irp i, 0, 4
2615        add             r6,  r0,  #(\i)
2616        add             r7,  sp,  #(\i*2)
2617        mov             r8,  #8*2
2618        bl              inv_txfm_add_vert_dct_4x32_neon
2619.endr
2620
2621        add_sp_align    512
2622        vpop            {q4-q7}
2623        pop             {r4-r11,pc}
2624endfunc
2625
2626function inv_txfm_add_dct_dct_32x8_8bpc_neon, export=1
2627        idct_dc         32,  8,   2
2628
2629        push            {r4-r11,lr}
2630        vpush           {q4-q7}
2631        sub_sp_align    512
2632
2633.irp i, 0, 4
2634        add             r6,  sp,  #(\i*32*2)
2635        add             r7,  r2,  #(\i*2)
2636.if \i > 0
2637        cmp             r3,  #10
2638        blt             1f
2639.endif
2640        mov             r8,  #8*2
2641        bl              inv_txfm_horz_dct_32x4_neon
2642.endr
2643        b               2f
2644
26451:
2646        vmov.i16        q2,  #0
2647        vmov.i16        q3,  #0
2648.rept 8
2649        vst1.16         {q2, q3}, [r6, :128]!
2650.endr
2651
26522:
2653        mov             r8,  #2*32
2654        mov             r9,  #0
26551:
2656        add             r6,  r0,  r9
2657        add             r7,  sp,  r9, lsl #1 // #(\i*2)
2658
2659.irp i, q8, q9, q10, q11, q12, q13, q14, q15
2660        vld1.16         {\i}, [r7, :128], r8
2661.endr
2662        add             r9,  r9,  #8
2663
2664        bl              inv_dct_8h_x8_neon
2665
2666        cmp             r9,  #32
2667
2668        load_add_store_8x8 r6, r7
2669
2670        blt             1b
2671
2672        add_sp_align    512
2673        vpop            {q4-q7}
2674        pop             {r4-r11,pc}
2675endfunc
2676
2677function inv_dct64_step1_neon
2678        // in1/31/17/15 -> t32a/33/34a/35/60/61a/62/63a
2679        // in7/25/23/ 9 -> t56a/57/58a/59/36/37a/38/39a
2680        // in5/27/21/11 -> t40a/41/42a/43/52/53a/54/55a
2681        // in3/29/19/13 -> t48a/49/50a/51/44/45a/46/47a
2682
2683        vld1.16         {d0, d1, d2}, [r12, :64]!
2684
2685        vqrdmulh.s16    d23, d16, d0[1]  // t63a
2686        vqrdmulh.s16    d16, d16, d0[0]  // t32a
2687        vqrdmulh.s16    d22, d17, d0[2]  // t62a
2688        vqrdmulh.s16    d17, d17, d0[3]  // t33a
2689        vqrdmulh.s16    d21, d18, d1[1]  // t61a
2690        vqrdmulh.s16    d18, d18, d1[0]  // t34a
2691        vqrdmulh.s16    d20, d19, d1[2]  // t60a
2692        vqrdmulh.s16    d19, d19, d1[3]  // t35a
2693
2694        vqadd.s16       d24, d16, d17    // t32
2695        vqsub.s16       d25, d16, d17    // t33
2696        vqsub.s16       d26, d19, d18    // t34
2697        vqadd.s16       d27, d19, d18    // t35
2698        vqadd.s16       d28, d20, d21    // t60
2699        vqsub.s16       d29, d20, d21    // t61
2700        vqsub.s16       d30, d23, d22    // t62
2701        vqadd.s16       d31, d23, d22    // t63
2702
2703        vmull_vmlal     q2,  d29, d26, d2[0], d2[1] // -> t34a
2704        vmull_vmlsl     q3,  d29, d26, d2[1], d2[0] // -> t61a
2705        vneg.s32        q2,  q2                     // t34a
2706        vmull_vmlsl     q4,  d30, d25, d2[1], d2[0] // -> t33a
2707        vqrshrn.s32     d26, q2,  #12               // t34a
2708        vmull_vmlal     q2,  d30, d25, d2[0], d2[1] // -> t62a
2709        vqrshrn.s32     d29, q3,  #12               // t61a
2710        vqrshrn.s32     d25, q4,  #12               // t33a
2711        vqrshrn.s32     d30, q2,  #12               // t62a
2712
2713        vqadd.s16       d16, d24, d27    // t32a
2714        vqsub.s16       d19, d24, d27    // t35a
2715        vqadd.s16       d17, d25, d26    // t33
2716        vqsub.s16       d18, d25, d26    // t34
2717        vqsub.s16       d20, d31, d28    // t60a
2718        vqadd.s16       d23, d31, d28    // t63a
2719        vqsub.s16       d21, d30, d29    // t61
2720        vqadd.s16       d22, d30, d29    // t62
2721
2722        vmull_vmlal     q2,  d21, d18, d2[2], d2[3] // -> t61a
2723        vmull_vmlsl     q3,  d21, d18, d2[3], d2[2] // -> t34a
2724        vmull_vmlal     q4,  d20, d19, d2[2], d2[3] // -> t60
2725        vqrshrn.s32     d21, q2,  #12               // t61a
2726        vqrshrn.s32     d18, q3,  #12               // t34a
2727        vmull_vmlsl     q2,  d20, d19, d2[3], d2[2] // -> t35
2728        vqrshrn.s32     d20, q4,  #12               // t60
2729        vqrshrn.s32     d19, q2,  #12               // t35
2730
2731        vst1.16         {d16, d17, d18, d19}, [r6, :128]!
2732        vst1.16         {d20, d21, d22, d23}, [r6, :128]!
2733
2734        bx              lr
2735endfunc
2736
2737function inv_dct64_step2_neon
2738        movrel_local    r12, idct_coeffs
2739        vld1.16         {d0}, [r12, :64]
27401:
2741        // t32a/33/34a/35/60/61a/62/63a
2742        // t56a/57/58a/59/36/37a/38/39a
2743        // t40a/41/42a/43/52/53a/54/55a
2744        // t48a/49/50a/51/44/45a/46/47a
2745        vldr            d16, [r6, #2*4*0]  // t32a
2746        vldr            d17, [r9, #2*4*8]  // t39a
2747        vldr            d18, [r9, #2*4*0]  // t63a
2748        vldr            d19, [r6, #2*4*8]  // t56a
2749        vldr            d20, [r6, #2*4*16] // t40a
2750        vldr            d21, [r9, #2*4*24] // t47a
2751        vldr            d22, [r9, #2*4*16] // t55a
2752        vldr            d23, [r6, #2*4*24] // t48a
2753
2754        vqadd.s16       d24, d16, d17      // t32
2755        vqsub.s16       d25, d16, d17      // t39
2756        vqadd.s16       d26, d18, d19      // t63
2757        vqsub.s16       d27, d18, d19      // t56
2758        vqsub.s16       d28, d21, d20      // t40
2759        vqadd.s16       d29, d21, d20      // t47
2760        vqadd.s16       d30, d23, d22      // t48
2761        vqsub.s16       d31, d23, d22      // t55
2762
2763        vmull_vmlal     q2,  d27, d25, d0[3], d0[2] // -> t56a
2764        vmull_vmlsl     q3,  d27, d25, d0[2], d0[3] // -> t39a
2765        vmull_vmlal     q4,  d31, d28, d0[3], d0[2] // -> t40a
2766        vqrshrn.s32     d25, q2,  #12               // t56a
2767        vqrshrn.s32     d27, q3,  #12               // t39a
2768        vneg.s32        q4,  q4                     // t40a
2769        vmull_vmlsl     q2,  d31, d28, d0[2], d0[3] // -> t55a
2770        vqrshrn.s32     d31, q4,  #12               // t40a
2771        vqrshrn.s32     d28, q2,  #12               // t55a
2772
2773        vqadd.s16       d16, d24, d29      // t32a
2774        vqsub.s16       d19, d24, d29      // t47a
2775        vqadd.s16       d17, d27, d31      // t39
2776        vqsub.s16       d18, d27, d31      // t40
2777        vqsub.s16       d20, d26, d30      // t48a
2778        vqadd.s16       d23, d26, d30      // t63a
2779        vqsub.s16       d21, d25, d28      // t55
2780        vqadd.s16       d22, d25, d28      // t56
2781
2782        vmull_vmlsl     q2,  d21, d18, d0[0], d0[0] // -> t40a
2783        vmull_vmlal     q3,  d21, d18, d0[0], d0[0] // -> t55a
2784        vmull_vmlsl     q4,  d20, d19, d0[0], d0[0] // -> t47
2785        vqrshrn.s32     d18, q2,  #12               // t40a
2786        vqrshrn.s32     d21, q3,  #12               // t55a
2787        vmull_vmlal     q2,  d20, d19, d0[0], d0[0] // -> t48
2788        vqrshrn.s32     d19, q4,  #12               // t47
2789        vqrshrn.s32     d20, q2,  #12               // t48
2790
2791        vstr            d16, [r6, #2*4*0]  // t32a
2792        vstr            d17, [r9, #2*4*0]  // t39
2793        vstr            d18, [r6, #2*4*8]  // t40a
2794        vstr            d19, [r9, #2*4*8]  // t47
2795        vstr            d20, [r6, #2*4*16] // t48
2796        vstr            d21, [r9, #2*4*16] // t55a
2797        vstr            d22, [r6, #2*4*24] // t56
2798        vstr            d23, [r9, #2*4*24] // t63a
2799
2800        add             r6,  r6,  #2*4
2801        sub             r9,  r9,  #2*4
2802        cmp             r6,  r9
2803        blt             1b
2804        bx              lr
2805endfunc
2806
2807.macro load8 src, strd, zero, clear
2808.irp i, d16, d17, d18, d19, d20, d21, d22, d23
2809.if \clear
2810        vld1.16         {\i}, [\src, :64]
2811        vst1.16         {\zero}, [\src, :64], \strd
2812.else
2813        vld1.16         {\i}, [\src, :64], \strd
2814.endif
2815.endr
2816.endm
2817
2818.macro store16 dst
2819        vst1.16         {q8,  q9},  [\dst, :128]!
2820        vst1.16         {q10, q11}, [\dst, :128]!
2821        vst1.16         {q12, q13}, [\dst, :128]!
2822        vst1.16         {q14, q15}, [\dst, :128]!
2823.endm
2824
2825.macro clear_upper8
2826.irp i, q12, q13, q14, q15
2827        vmov.i16        \i,  #0
2828.endr
2829.endm
2830
2831.macro vmov_if reg, val, cond
2832.if \cond
2833        vmov.i16        \reg, \val
2834.endif
2835.endm
2836
2837.macro movdup_if reg, gpr, val, cond
2838.if \cond
2839        movw            \gpr, \val
2840        vdup.16         \reg, \gpr
2841.endif
2842.endm
2843
2844.macro vst1_if regs, dst, dstalign, cond
2845.if \cond
2846        vst1.16         \regs, \dst, \dstalign
2847.endif
2848.endm
2849
2850.macro scale_if cond, c, r0, r1, r2, r3, r4, r5, r6, r7
2851.if \cond
2852        scale_input     \c, \r0, \r1, \r2, \r3, \r4, \r5, \r6, \r7
2853.endif
2854.endm
2855
2856.macro def_dct64_func suffix, clear=0, scale=0
2857function inv_txfm_dct\suffix\()_4h_x64_neon, export=1
2858        mov             r6,  sp
2859
2860        push            {r10-r11,lr}
2861
2862        lsl             r8,  r8,  #2
2863
2864        movdup_if       d0,  r12, #2896*8, \scale
2865        vmov_if         d7,  #0,  \clear
2866        load8           r7,  r8,  d7,  \clear
2867        clear_upper8
2868        sub             r7,  r7,  r8, lsl #3
2869        add             r7,  r7,  r8, lsr #1
2870        scale_if        \scale, d0[0], q8, q9, q10, q11
2871
2872        bl              inv_dct_4h_x16_neon
2873
2874        store16         r6
2875
2876        movdup_if       d0,  r12, #2896*8, \scale
2877        vmov_if         d7,  #0,  \clear
2878        load8           r7,  r8,  d7,  \clear
2879        clear_upper8
2880        sub             r7,  r7,  r8, lsl #3
2881        lsr             r8,  r8,  #1
2882        sub             r7,  r7,  r8, lsr #1
2883        scale_if        \scale, d0[0], q8, q9, q10, q11
2884
2885        bl              inv_dct32_odd_4h_x16_neon
2886
2887        add             r10, r6,  #8*15
2888        sub             r6,  r6,  #8*16
2889
2890        mov             r9,  #-8
2891
2892.macro store_addsub r0, r1, r2, r3
2893        vld1.16         {d2},  [r6, :64]!
2894        vld1.16         {d3},  [r6, :64]!
2895        vqadd.s16       d6,  d2,  \r0
2896        vqsub.s16       \r0, d2,  \r0
2897        vld1.16         {d4},  [r6, :64]!
2898        vqadd.s16       d7,  d3,  \r1
2899        vqsub.s16       \r1, d3,  \r1
2900        vld1.16         {d5},  [r6, :64]!
2901        vqadd.s16       d2,  d4,  \r2
2902        sub             r6,  r6,  #8*4
2903        vqsub.s16       \r2, d4,  \r2
2904        vst1.16         {d6},  [r6,  :64]!
2905        vst1.16         {\r0}, [r10, :64], r9
2906        vqadd.s16       d3,  d5,  \r3
2907        vqsub.s16       \r3, d5,  \r3
2908        vst1.16         {d7},  [r6,  :64]!
2909        vst1.16         {\r1}, [r10, :64], r9
2910        vst1.16         {d2},  [r6,  :64]!
2911        vst1.16         {\r2}, [r10, :64], r9
2912        vst1.16         {d3},  [r6,  :64]!
2913        vst1.16         {\r3}, [r10, :64], r9
2914.endm
2915        store_addsub    d31, d30, d29, d28
2916        store_addsub    d27, d26, d25, d24
2917        store_addsub    d23, d22, d21, d20
2918        store_addsub    d19, d18, d17, d16
2919.purgem store_addsub
2920
2921        add             r6,  r6,  #2*4*16
2922
2923        movrel_local    r12, idct64_coeffs
2924        movdup_if       d0,  lr,  #2896*8, \scale
2925        vmov_if         d7,  #0,  \clear
2926        add             r9,  r7,  r8, lsl #4 // offset 16
2927        add             r10, r7,  r8, lsl #3 // offset 8
2928        sub             r9,  r9,  r8         // offset 15
2929        sub             r11, r10, r8         // offset 7
2930        vld1.16         {d16}, [r7,  :64]    // in1  (offset 0)
2931        vld1.16         {d17}, [r9,  :64]    // in31 (offset 15)
2932        vld1.16         {d18}, [r10, :64]    // in17 (offset 8)
2933        vld1.16         {d19}, [r11, :64]    // in15 (offset 7)
2934        vst1_if         {d7},  [r7,  :64], \clear
2935        vst1_if         {d7},  [r9,  :64], \clear
2936        vst1_if         {d7},  [r10, :64], \clear
2937        vst1_if         {d7},  [r11, :64], \clear
2938        scale_if        \scale, d0[0], q8, q9
2939        bl              inv_dct64_step1_neon
2940        movdup_if       d0,  lr,  #2896*8, \scale
2941        vmov_if         d7,  #0,  \clear
2942        add             r7,  r7,  r8, lsl #2 // offset 4
2943        sub             r9,  r9,  r8, lsl #2 // offset 11
2944        sub             r10, r7,  r8         // offset 3
2945        add             r11, r9,  r8         // offset 12
2946        vld1.16         {d16}, [r10, :64]    // in7  (offset 3)
2947        vld1.16         {d17}, [r11, :64]    // in25 (offset 12)
2948        vld1.16         {d18}, [r9,  :64]    // in23 (offset 11)
2949        vld1.16         {d19}, [r7,  :64]    // in9  (offset 4)
2950        vst1_if         {d7},  [r7,  :64], \clear
2951        vst1_if         {d7},  [r9,  :64], \clear
2952        vst1_if         {d7},  [r10, :64], \clear
2953        vst1_if         {d7},  [r11, :64], \clear
2954        scale_if        \scale, d0[0], q8, q9
2955        bl              inv_dct64_step1_neon
2956        movdup_if       d0,  lr,  #2896*8, \scale
2957        vmov_if         d7,  #0,  \clear
2958        sub             r10, r10, r8, lsl #1 // offset 1
2959        sub             r9,  r9,  r8, lsl #1 // offset 9
2960        add             r10, r10, r8         // offset 2
2961        add             r9,  r9,  r8         // offset 10
2962        add             r7,  r7,  r8         // offset 5
2963        add             r11, r11, r8         // offset 13
2964        vld1.16         d16, [r10, :64]      // in5  (offset 2)
2965        vld1.16         d17, [r11, :64]      // in27 (offset 13)
2966        vld1.16         d18, [r9,  :64]      // in21 (offset 10)
2967        vld1.16         d19, [r7,  :64]      // in11 (offset 5)
2968        vst1_if         d7,  [r10, :64], \clear
2969        vst1_if         d7,  [r11, :64], \clear
2970        vst1_if         d7,  [r9,  :64], \clear
2971        vst1_if         d7,  [r7,  :64], \clear
2972        scale_if        \scale, d0[0], q8, q9
2973        bl              inv_dct64_step1_neon
2974        movdup_if       d0,  lr,  #2896*8, \scale
2975        vmov_if         d7,  #0,  \clear
2976        sub             r10, r10, r8         // offset 1
2977        sub             r9,  r9,  r8         // offset 9
2978        add             r11, r11, r8         // offset 14
2979        add             r7,  r7,  r8         // offset 6
2980        vld1.16         d16, [r10, :64]      // in3  (offset 1)
2981        vld1.16         d17, [r11, :64]      // in29 (offset 14)
2982        vld1.16         d18, [r9,  :64]      // in19 (offset 9)
2983        vld1.16         d19, [r7,  :64]      // in13 (offset 6)
2984        vst1_if         d7,  [r10, :64], \clear
2985        vst1_if         d7,  [r11, :64], \clear
2986        vst1_if         d7,  [r9,  :64], \clear
2987        vst1_if         d7,  [r7,  :64], \clear
2988        scale_if        \scale, d0[0], q8, q9
2989        bl              inv_dct64_step1_neon
2990
2991        sub             r6,  r6,  #2*4*32
2992        add             r9,  r6,  #2*4*7
2993
2994        bl              inv_dct64_step2_neon
2995
2996        pop             {r10-r11,pc}
2997endfunc
2998.endm
2999
3000def_dct64_func
3001def_dct64_func _clear, clear=1
3002def_dct64_func _clear_scale, clear=1, scale=1
3003
3004function inv_txfm_horz_dct_64x4_neon
3005        vdup.16         q3,  r9
3006
3007        mov             r7,  sp
3008        add             r8,  sp,  #2*4*(64 - 4)
3009        add             r9,  r6,  #2*56
3010
3011        push            {r10-r11,lr}
3012
3013        mov             r10, #2*64
3014        mov             r11, #-2*4*4
3015
30161:
3017        vld1.16         {d16, d17, d18, d19}, [r7, :128]!
3018        vld1.16         {d28, d29, d30, d31}, [r8, :128], r11
3019        vld1.16         {d20, d21, d22, d23}, [r7, :128]!
3020        vld1.16         {d24, d25, d26, d27}, [r8, :128], r11
3021        transpose_4x4h  q8,  q9,  d16, d17, d18, d19
3022        transpose_4x4h  q15, q14, d31, d30, d29, d28
3023        transpose_4x4h  q10, q11, d20, d21, d22, d23
3024        transpose_4x4h  q13, q12, d27, d26, d25, d24
3025
3026.macro store_addsub src0, src1, src2, src3
3027        vqsub.s16       d3,  \src0,  \src1
3028        vqsub.s16       d2,  \src2,  \src3
3029        vqadd.s16       d0,  \src0,  \src1
3030        vqadd.s16       d1,  \src2,  \src3
3031        vrshl.s16       q1,  q1,  q3
3032        vrshl.s16       q0,  q0,  q3
3033        vrev64.16       q1,  q1
3034        vst1.16         {q0},  [r6, :128], r10
3035        vst1.16         {q1},  [r9, :128], r10
3036.endm
3037        store_addsub    d16, d31, d20, d27
3038        store_addsub    d17, d30, d21, d26
3039        store_addsub    d18, d29, d22, d25
3040        store_addsub    d19, d28, d23, d24
3041.purgem store_addsub
3042        sub             r6,  r6,  r10, lsl #2
3043        sub             r9,  r9,  r10, lsl #2
3044        add             r6,  r6,  #16
3045        sub             r9,  r9,  #16
3046
3047        cmp             r7,  r8
3048        blt             1b
3049        pop             {r10-r11,pc}
3050endfunc
3051
3052function inv_txfm_add_vert_dct_4x64_neon
3053        lsl             r8,  r8,  #1
3054
3055        mov             r7,  sp
3056        add             r8,  sp,  #2*4*(64 - 4)
3057        add             r9,  r6,  r1, lsl #6
3058        sub             r9,  r9,  r1
3059
3060        push            {r10-r11,lr}
3061
3062        neg             r10, r1
3063        mov             r11, #-2*4*4
3064
30651:
3066        vld1.16         {d16, d17, d18, d19}, [r7, :128]!
3067        vld1.16         {d28, d29, d30, d31}, [r8, :128], r11
3068        vld1.16         {d20, d21, d22, d23}, [r7, :128]!
3069        vld1.16         {d24, d25, d26, d27}, [r8, :128], r11
3070
3071.macro add_dest_addsub src0, src1, src2, src3
3072        vld1.32         {d0[0]}, [r6, :32], r1
3073        vld1.32         {d1[0]}, [r9, :32], r10
3074        vqadd.s16       d4,  \src0,  \src1
3075        vld1.32         {d0[1]}, [r6, :32]
3076        vqadd.s16       d5,  \src2,  \src3
3077        vld1.32         {d1[1]}, [r9, :32]
3078        vqsub.s16       d6,  \src0,  \src1
3079        vqsub.s16       d7,  \src2,  \src3
3080        sub             r6,  r6,  r1
3081        sub             r9,  r9,  r10
3082        vrshr.s16       q2,  q2,  #4
3083        vrshr.s16       q3,  q3,  #4
3084        vaddw.u8        q2,  q2,  d0
3085        vaddw.u8        q3,  q3,  d1
3086        vqmovun.s16     d0,  q2
3087        vqmovun.s16     d1,  q3
3088        vst1.32         {d0[0]}, [r6, :32], r1
3089        vst1.32         {d1[0]}, [r9, :32], r10
3090        vst1.32         {d0[1]}, [r6, :32], r1
3091        vst1.32         {d1[1]}, [r9, :32], r10
3092.endm
3093        add_dest_addsub d16, d31, d17, d30
3094        add_dest_addsub d18, d29, d19, d28
3095        add_dest_addsub d20, d27, d21, d26
3096        add_dest_addsub d22, d25, d23, d24
3097.purgem add_dest_addsub
3098        cmp             r7,  r8
3099        blt             1b
3100
3101        pop             {r10-r11,pc}
3102endfunc
3103
3104function inv_txfm_add_dct_dct_64x64_8bpc_neon, export=1
3105        idct_dc         64,  64,  2
3106
3107        push            {r4-r11,lr}
3108        vpush           {q4}
3109
3110        sub_sp_align    64*32*2+64*4*2
3111        add             r5,  sp,  #64*4*2
3112
3113        movrel_local    r10, eob_32x32
3114
3115.irp i, 0, 4, 8, 12, 16, 20, 24, 28
3116        add             r6,  r5,  #(\i*64*2)
3117.if \i > 0
3118        mov             r8,  #(32 - \i)
3119        cmp             r3,  r11
3120        blt             1f
3121.endif
3122        add             r7,  r2,  #(\i*2)
3123        mov             r8,  #32*2
3124        bl              inv_txfm_dct_clear_4h_x64_neon
3125        add             r6,  r5,  #(\i*64*2)
3126        mov             r9,  #-2 // shift
3127        bl              inv_txfm_horz_dct_64x4_neon
3128.if \i < 28
3129        ldrh            r11, [r10], #2
3130.endif
3131.endr
3132        b               3f
3133
31341:
3135        vmov.i16        q2,  #0
3136        vmov.i16        q3,  #0
31372:
3138        subs            r8,  r8,  #2
3139.rept 8
3140        vst1.16         {q2, q3}, [r6, :128]!
3141.endr
3142        bgt             2b
3143
31443:
3145.irp i, 0, 4, 8, 12, 16, 20, 24, 28, 32, 36, 40, 44, 48, 52, 56, 60
3146        add             r7,  r5,  #(\i*2)
3147        mov             r8,  #64*2
3148        bl              inv_txfm_dct_4h_x64_neon
3149        add             r6,  r0,  #(\i)
3150        bl              inv_txfm_add_vert_dct_4x64_neon
3151.endr
3152
3153        add_sp_align    64*32*2+64*4*2
3154        vpop            {q4}
3155        pop             {r4-r11,pc}
3156endfunc
3157
3158function inv_txfm_add_dct_dct_64x32_8bpc_neon, export=1
3159        idct_dc         64,  32,  1
3160
3161        push            {r4-r11,lr}
3162        vpush           {q4}
3163
3164        sub_sp_align    64*32*2+64*4*2
3165        add             r5,  sp,  #64*4*2
3166
3167        movrel_local    r10, eob_32x32
3168
3169.irp i, 0, 4, 8, 12, 16, 20, 24, 28
3170        add             r6,  r5,  #(\i*64*2)
3171.if \i > 0
3172        mov             r8,  #(32 - \i)
3173        cmp             r3,  r11
3174        blt             1f
3175.endif
3176        add             r7,  r2,  #(\i*2)
3177        mov             r8,  #32*2
3178        bl              inv_txfm_dct_clear_scale_4h_x64_neon
3179        add             r6,  r5,  #(\i*64*2)
3180        mov             r9,  #-1 // shift
3181        bl              inv_txfm_horz_dct_64x4_neon
3182.if \i < 28
3183        ldrh            r11, [r10], #2
3184.endif
3185.endr
3186        b               3f
3187
31881:
3189        vmov.i16        q2,  #0
3190        vmov.i16        q3,  #0
31912:
3192        subs            r8,  r8,  #2
3193.rept 8
3194        vst1.16         {q2, q3}, [r6, :128]!
3195.endr
3196        bgt             2b
3197
31983:
3199.irp i, 0, 4, 8, 12, 16, 20, 24, 28, 32, 36, 40, 44, 48, 52, 56, 60
3200        add             r6,  r0,  #(\i)
3201        add             r7,  r5,  #(\i*2)
3202        mov             r8,  #64*2
3203        bl              inv_txfm_add_vert_dct_4x32_neon
3204.endr
3205
3206        add_sp_align    64*32*2+64*4*2
3207        vpop            {q4}
3208        pop             {r4-r11,pc}
3209endfunc
3210
3211function inv_txfm_add_dct_dct_32x64_8bpc_neon, export=1
3212        idct_dc         32,  64,  1
3213
3214        push            {r4-r11,lr}
3215        vpush           {q4}
3216
3217        sub_sp_align    32*32*2+64*4*2
3218        add             r5,  sp,  #64*4*2
3219
3220        movrel_local    r10, eob_32x32
3221        ldrh            r11, [r10], #2
3222
3223.irp i, 0, 4, 8, 12, 16, 20, 24, 28
3224        add             r6,  r5,  #(\i*32*2)
3225.if \i > 0
3226        mov             r8,  #(32 - \i)
3227        cmp             r3,  r11
3228        blt             1f
3229.if \i < 28
3230        ldrh            r11, [r10], #2
3231.endif
3232.endif
3233        add             r7,  r2,  #(\i*2)
3234        mov             r8,  #32*2
3235        bl              inv_txfm_horz_scale_dct_32x4_neon
3236.endr
3237        b               3f
3238
32391:
3240        vmov.i16        q2,  #0
3241        vmov.i16        q3,  #0
32422:
3243        subs            r8,  r8,  #2
3244.rept 4
3245        vst1.16         {q2, q3}, [r6, :128]!
3246.endr
3247        bgt             2b
3248
32493:
3250.irp i, 0, 4, 8, 12, 16, 20, 24, 28
3251        add             r7,  r5,  #(\i*2)
3252        mov             r8,  #32*2
3253        bl              inv_txfm_dct_4h_x64_neon
3254        add             r6,  r0,  #(\i)
3255        bl              inv_txfm_add_vert_dct_4x64_neon
3256.endr
3257
3258        add_sp_align    32*32*2+64*4*2
3259        vpop            {q4}
3260        pop             {r4-r11,pc}
3261endfunc
3262
3263function inv_txfm_add_dct_dct_64x16_8bpc_neon, export=1
3264        idct_dc         64,  16,  2
3265
3266        push            {r4-r11,lr}
3267        vpush           {q4}
3268
3269        sub_sp_align    64*16*2+64*4*2
3270        add             r4,  sp,  #64*4*2
3271
3272        movrel_local    r10, eob_16x32
3273
3274.irp i, 0, 4, 8, 12
3275        add             r6,  r4,  #(\i*64*2)
3276.if \i > 0
3277        mov             r8,  #(16 - \i)
3278        cmp             r3,  r11
3279        blt             1f
3280.endif
3281        add             r7,  r2,  #(\i*2)
3282        mov             r8,  #16*2
3283        bl              inv_txfm_dct_clear_4h_x64_neon
3284        add             r6,  r4,  #(\i*64*2)
3285        mov             r9,  #-2 // shift
3286        bl              inv_txfm_horz_dct_64x4_neon
3287.if \i < 12
3288        ldrh            r11, [r10], #2
3289.endif
3290.endr
3291        b               3f
3292
32931:
3294        vmov.i16        q2,  #0
3295        vmov.i16        q3,  #0
32962:
3297        subs            r8,  r8,  #2
3298.rept 8
3299        vst1.16         {q2, q3}, [r6, :128]!
3300.endr
3301        bgt             2b
3302
33033:
3304        movrel_local    r5,  inv_dct_4h_x16_neon
3305.irp i, 0, 4, 8, 12, 16, 20, 24, 28, 32, 36, 40, 44, 48, 52, 56, 60
3306        add             r6,  r0,  #(\i)
3307        add             r7,  r4,  #(\i*2)
3308        mov             r8,  #64*2
3309        bl              inv_txfm_add_vert_4x16_neon
3310.endr
3311
3312        add_sp_align    64*16*2+64*4*2
3313        vpop            {q4}
3314        pop             {r4-r11,pc}
3315endfunc
3316
3317function inv_txfm_add_dct_dct_16x64_8bpc_neon, export=1
3318        idct_dc         16,  64,  2
3319
3320        push            {r4-r11,lr}
3321        vpush           {q4}
3322
3323        sub_sp_align    16*32*2+64*4*2
3324        add             r5,  sp,  #64*4*2
3325
3326        movrel_local    r10, eob_16x32
3327        ldrh            r11, [r10], #2
3328
3329        movrel_local    r4,  inv_dct_4h_x16_neon
3330.irp i, 0, 4, 8, 12, 16, 20, 24, 28
3331        add             r6,  r5,  #(\i*16*2)
3332.if \i > 0
3333        mov             r8,  #(32 - \i)
3334        cmp             r3,  r11
3335        blt             1f
3336.if \i < 28
3337        ldrh            r11, [r10], #2
3338.endif
3339.endif
3340        add             r7,  r2,  #(\i*2)
3341        mov             r8,  #32*2
3342        bl              inv_txfm_horz_16x4_neon
3343.endr
3344        b               3f
3345
33461:
3347        vmov.i16        q2,  #0
3348        vmov.i16        q3,  #0
33492:
3350        subs            r8,  r8,  #4
3351.rept 4
3352        vst1.16         {q2, q3}, [r6, :128]!
3353.endr
3354        bgt             2b
3355
33563:
3357.irp i, 0, 4, 8, 12
3358        add             r7,  r5,  #(\i*2)
3359        mov             r8,  #16*2
3360        bl              inv_txfm_dct_4h_x64_neon
3361        add             r6,  r0,  #(\i)
3362        bl              inv_txfm_add_vert_dct_4x64_neon
3363.endr
3364
3365        add_sp_align    16*32*2+64*4*2
3366        vpop            {q4}
3367        pop             {r4-r11,pc}
3368endfunc
3369