b3188bc7118d540a626c2b7d810e16c4179f6fd5
[ffmpeg.git] / libavcodec / arm / vp9itxfm_neon.S
1 /*
2  * Copyright (c) 2016 Google Inc.
3  *
4  * This file is part of Libav.
5  *
6  * Libav is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2.1 of the License, or (at your option) any later version.
10  *
11  * Libav is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with Libav; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19  */
20
21 #include "libavutil/arm/asm.S"
22 #include "neon.S"
23
24 const itxfm4_coeffs, align=4
25         .short  11585, 6270, 15137, 0
26 iadst4_coeffs:
27         .short  5283, 15212, 9929, 13377
28 endconst
29
30 const iadst8_coeffs, align=4
31         .short  16305, 1606, 14449, 7723, 10394, 12665, 4756, 15679
32 idct_coeffs:
33         .short  11585, 6270, 15137, 3196, 16069, 13623, 9102, 1606
34         .short  16305, 12665, 10394, 7723, 14449, 15679, 4756, 0
35         .short  804, 16364, 12140, 11003, 7005, 14811, 15426, 5520
36         .short  3981, 15893, 14053, 8423, 9760, 13160, 16207, 2404
37 endconst
38
39 const iadst16_coeffs, align=4
40         .short  16364, 804, 15893, 3981, 14811, 7005, 13160, 9760
41         .short  11003, 12140, 8423, 14053, 5520, 15426, 2404, 16207
42 endconst
43
44 @ Do four 4x4 transposes, using q registers for the subtransposes that don't
45 @ need to address the individual d registers.
46 @ r0,r1 == rq1, r2,r3 == rq1, etc
47 .macro transpose16_q_4x_4x4 rq0, rq1, rq2, rq3, rq4, rq5, rq6, rq7, r0, r1, r2, r3, r4, r5, r6, r7, r8, r9, r10, r11, r12, r13, r14, r15
48         vtrn.32          \rq0, \rq1
49         vtrn.32          \rq2, \rq3
50         vtrn.32          \rq4, \rq5
51         vtrn.32          \rq6, \rq7
52         vtrn.16          \r0,  \r1
53         vtrn.16          \r2,  \r3
54         vtrn.16          \r4,  \r5
55         vtrn.16          \r6,  \r7
56         vtrn.16          \r8,  \r9
57         vtrn.16          \r10, \r11
58         vtrn.16          \r12, \r13
59         vtrn.16          \r14, \r15
60 .endm
61
62 @ out1 = ((in1 + in2) * d0[0] + (1 << 13)) >> 14
63 @ out2 = ((in1 - in2) * d0[0] + (1 << 13)) >> 14
64 @ in/out are d registers
65 .macro mbutterfly0 out1, out2, in1, in2, tmpd1, tmpd2, tmpq3, tmpq4, neg=0
66         vadd.s16        \tmpd1, \in1,  \in2
67         vsub.s16        \tmpd2, \in1,  \in2
68         vmull.s16       \tmpq3, \tmpd1, d0[0]
69         vmull.s16       \tmpq4, \tmpd2, d0[0]
70 .if \neg > 0
71         vneg.s32        \tmpq3, \tmpq3
72 .endif
73         vrshrn.s32      \out1, \tmpq3, #14
74         vrshrn.s32      \out2, \tmpq4, #14
75 .endm
76
77 @ out1,out2 = ((in1 + in2) * d0[0] + (1 << 13)) >> 14
78 @ out3,out4 = ((in1 - in2) * d0[0] + (1 << 13)) >> 14
79 @ Same as mbutterfly0, but with input being 2 q registers, output
80 @ being 4 d registers.
81 @ This can do with either 4 or 6 temporary q registers.
82 .macro dmbutterfly0 out1, out2, out3, out4, in1, in2, tmpq1, tmpq2, tmpd11, tmpd12, tmpd21, tmpd22, tmpq3, tmpq4, tmpq5, tmpq6
83         vadd.s16        \tmpq1, \in1,  \in2
84         vsub.s16        \tmpq2, \in1,  \in2
85         vmull.s16       \tmpq3, \tmpd11, d0[0]
86         vmull.s16       \tmpq4, \tmpd12, d0[0]
87 .ifb \tmpq5
88         vrshrn.s32      \out1, \tmpq3, #14
89         vrshrn.s32      \out2, \tmpq4, #14
90         vmull.s16       \tmpq3, \tmpd21, d0[0]
91         vmull.s16       \tmpq4, \tmpd22, d0[0]
92         vrshrn.s32      \out3, \tmpq3, #14
93         vrshrn.s32      \out4, \tmpq4, #14
94 .else
95         vmull.s16       \tmpq5, \tmpd21, d0[0]
96         vmull.s16       \tmpq6, \tmpd22, d0[0]
97         vrshrn.s32      \out1, \tmpq3, #14
98         vrshrn.s32      \out2, \tmpq4, #14
99         vrshrn.s32      \out3, \tmpq5, #14
100         vrshrn.s32      \out4, \tmpq6, #14
101 .endif
102 .endm
103
104 @ out1 = in1 * coef1 - in2 * coef2
105 @ out2 = in1 * coef2 + in2 * coef1
106 @ out are 2 q registers, in are 2 d registers
107 .macro mbutterfly_l out1, out2, in1, in2, coef1, coef2
108         vmull.s16       \out1, \in1, \coef1
109         vmlsl.s16       \out1, \in2, \coef2
110         vmull.s16       \out2, \in1, \coef2
111         vmlal.s16       \out2, \in2, \coef1
112 .endm
113
114 @ out1,out2 = in1,in2 * coef1 - in3,in4 * coef2
115 @ out3,out4 = in1,in2 * coef2 + in3,in4 * coef1
116 @ out are 4 q registers, in are 4 d registers
117 .macro dmbutterfly_l out1, out2, out3, out4, in1, in2, in3, in4, coef1, coef2
118         vmull.s16       \out1, \in1, \coef1
119         vmull.s16       \out2, \in2, \coef1
120         vmull.s16       \out3, \in1, \coef2
121         vmull.s16       \out4, \in2, \coef2
122         vmlsl.s16       \out1, \in3, \coef2
123         vmlsl.s16       \out2, \in4, \coef2
124         vmlal.s16       \out3, \in3, \coef1
125         vmlal.s16       \out4, \in4, \coef1
126 .endm
127
128 @ inout1 = (inout1 * coef1 - inout2 * coef2 + (1 << 13)) >> 14
129 @ inout2 = (inout1 * coef2 + inout2 * coef1 + (1 << 13)) >> 14
130 @ inout are 2 d registers, tmp are 2 q registers
131 .macro mbutterfly inout1, inout2, coef1, coef2, tmp1, tmp2, neg=0
132         mbutterfly_l    \tmp1, \tmp2, \inout1, \inout2, \coef1, \coef2
133 .if \neg > 0
134         vneg.s32        \tmp2, \tmp2
135 .endif
136         vrshrn.s32      \inout1, \tmp1,  #14
137         vrshrn.s32      \inout2, \tmp2,  #14
138 .endm
139
140 @ inout1,inout2 = (inout1,inout2 * coef1 - inout3,inout4 * coef2 + (1 << 13)) >> 14
141 @ inout3,inout4 = (inout1,inout2 * coef2 + inout3,inout4 * coef1 + (1 << 13)) >> 14
142 @ inout are 4 d registers, tmp are 4 q registers
143 .macro dmbutterfly inout1, inout2, inout3, inout4, coef1, coef2, tmp1, tmp2, tmp3, tmp4
144         dmbutterfly_l   \tmp1, \tmp2, \tmp3, \tmp4, \inout1, \inout2, \inout3, \inout4, \coef1, \coef2
145         vrshrn.s32      \inout1, \tmp1,  #14
146         vrshrn.s32      \inout2, \tmp2,  #14
147         vrshrn.s32      \inout3, \tmp3,  #14
148         vrshrn.s32      \inout4, \tmp4,  #14
149 .endm
150
151 @ out1 = in1 + in2
152 @ out2 = in1 - in2
153 .macro butterfly out1, out2, in1, in2
154         vadd.s16        \out1, \in1, \in2
155         vsub.s16        \out2, \in1, \in2
156 .endm
157
158 @ out1 = in1 - in2
159 @ out2 = in1 + in2
160 .macro butterfly_r out1, out2, in1, in2
161         vsub.s16        \out1, \in1, \in2
162         vadd.s16        \out2, \in1, \in2
163 .endm
164
165 @ out1 = (in1 + in2 + (1 << 13)) >> 14
166 @ out2 = (in1 - in2 + (1 << 13)) >> 14
167 @ out are 2 d registers, in are 2 q registers, tmp are 2 q registers
168 .macro butterfly_n out1, out2, in1, in2, tmp1, tmp2
169         vadd.s32        \tmp1, \in1, \in2
170         vsub.s32        \tmp2, \in1, \in2
171         vrshrn.s32      \out1, \tmp1,  #14
172         vrshrn.s32      \out2, \tmp2,  #14
173 .endm
174
175 @ out1,out2 = (in1,in2 + in3,in4 + (1 << 13)) >> 14
176 @ out3,out4 = (in1,in2 - in3,in4 + (1 << 13)) >> 14
177 @ out are 4 d registers, in are 4 q registers, tmp are 4 q registers
178 .macro dbutterfly_n out1, out2, out3, out4, in1, in2, in3, in4, tmp1, tmp2, tmp3, tmp4
179         vadd.s32        \tmp1, \in1, \in3
180         vadd.s32        \tmp2, \in2, \in4
181         vsub.s32        \tmp3, \in1, \in3
182         vsub.s32        \tmp4, \in2, \in4
183         vrshrn.s32      \out1, \tmp1,  #14
184         vrshrn.s32      \out2, \tmp2,  #14
185         vrshrn.s32      \out3, \tmp3,  #14
186         vrshrn.s32      \out4, \tmp4,  #14
187 .endm
188
189
190 .macro iwht4 c0, c1, c2, c3
191         vadd.i16        \c0,  \c0,  \c1
192         vsub.i16        d17,  \c2,  \c3
193         vsub.i16        d16,  \c0,  d17
194         vshr.s16        d16,  d16,  #1
195         vsub.i16        \c2,  d16,  \c1
196         vsub.i16        \c1,  d16,  \c3
197         vadd.i16        \c3,  d17,  \c2
198         vsub.i16        \c0,  \c0,  \c1
199 .endm
200
201 .macro idct4 c0, c1, c2, c3
202         vmull.s16       q13,  \c1,  d0[2]
203         vmull.s16       q11,  \c1,  d0[1]
204         vadd.i16        d16,  \c0,  \c2
205         vsub.i16        d17,  \c0,  \c2
206         vmlal.s16       q13,  \c3,  d0[1]
207         vmull.s16       q9,   d16,  d0[0]
208         vmull.s16       q10,  d17,  d0[0]
209         vmlsl.s16       q11,  \c3,  d0[2]
210         vrshrn.s32      d26,  q13,  #14
211         vrshrn.s32      d18,  q9,   #14
212         vrshrn.s32      d20,  q10,  #14
213         vrshrn.s32      d22,  q11,  #14
214         vadd.i16        \c0,  d18,  d26
215         vsub.i16        \c3,  d18,  d26
216         vadd.i16        \c1,  d20,  d22
217         vsub.i16        \c2,  d20,  d22
218 .endm
219
220 .macro iadst4 c0, c1, c2, c3
221         vmull.s16       q10,  \c0,  d1[0]
222         vmlal.s16       q10,  \c2,  d1[1]
223         vmlal.s16       q10,  \c3,  d1[2]
224         vmull.s16       q11,  \c0,  d1[2]
225         vmlsl.s16       q11,  \c2,  d1[0]
226         vsub.s16        \c0,  \c0,  \c2
227         vmlsl.s16       q11,  \c3,  d1[1]
228         vadd.s16        \c0,  \c0,  \c3
229         vmull.s16       q13,  \c1,  d1[3]
230         vmull.s16       q12,  \c0,  d1[3]
231         vadd.s32        q14,  q10,  q13
232         vadd.s32        q1,   q11,  q13
233         vrshrn.s32      \c0,  q14,  #14
234         vadd.s32        q10,  q10,  q11
235         vrshrn.s32      \c1,  q1,   #14
236         vsub.s32        q10,  q10,  q13
237         vrshrn.s32      \c2,  q12,  #14
238         vrshrn.s32      \c3,  q10,  #14
239 .endm
240
241 @ The public functions in this file have got the following signature:
242 @ void itxfm_add(uint8_t *dst, ptrdiff_t stride, int16_t *block, int eob);
243
244 .macro itxfm_func4x4 txfm1, txfm2
245 function ff_vp9_\txfm1\()_\txfm2\()_4x4_add_neon, export=1
246 .ifc \txfm1,\txfm2
247 .ifc \txfm1,idct
248         movrel          r12, itxfm4_coeffs
249         vld1.16         {d0}, [r12,:64]
250 .endif
251 .ifc \txfm1,iadst
252         movrel          r12, iadst4_coeffs
253         vld1.16         {d1}, [r12,:64]
254 .endif
255 .else
256         movrel          r12, itxfm4_coeffs
257         vld1.16         {q0}, [r12,:128]
258 .endif
259
260         vmov.i16        q15, #0
261 .ifc \txfm1\()_\txfm2,idct_idct
262         cmp             r3,  #1
263         bne             1f
264         @ DC-only for idct/idct
265         vld1.16         {d4[]},   [r2,:16]
266         vmull.s16       q2,  d4,  d0[0]
267         vrshrn.s32      d4,  q2,  #14
268         vmull.s16       q2,  d4,  d0[0]
269         vrshrn.s32      d4,  q2,  #14
270         vst1.16         {d30[0]}, [r2,:16]
271         vdup.16         q2,  d4[0]
272         vmov            q3,  q2
273         b               2f
274 .endif
275
276 1:
277         vld1.16         {d4-d7},  [r2,:128]
278         vst1.16         {q15}, [r2,:128]!
279
280 .ifc \txfm1,iwht
281         vshr.s16        q2,  q2,  #2
282         vshr.s16        q3,  q3,  #2
283 .endif
284
285         \txfm1\()4      d4,  d5,  d6,  d7
286
287         vst1.16         {q15}, [r2,:128]!
288         @ Transpose 4x4 with 16 bit elements
289         vtrn.16         d4,  d5
290         vtrn.16         d6,  d7
291         vtrn.32         q2,  q3
292
293         \txfm2\()4      d4,  d5,  d6,  d7
294 2:
295         vld1.32         {d0[]},   [r0,:32], r1
296         vld1.32         {d0[1]},  [r0,:32], r1
297 .ifnc \txfm1,iwht
298         vrshr.s16       q2,  q2,  #4
299         vrshr.s16       q3,  q3,  #4
300 .endif
301         vaddw.u8        q2,  q2,  d0
302         vld1.32         {d1[]},   [r0,:32], r1
303         vld1.32         {d1[1]},  [r0,:32], r1
304         vqmovun.s16     d0,  q2
305         sub             r0,  r0,  r1, lsl #2
306
307         vaddw.u8        q3,  q3,  d1
308         vst1.32         {d0[0]},  [r0,:32], r1
309         vqmovun.s16     d1,  q3
310
311         vst1.32         {d0[1]},  [r0,:32], r1
312         vst1.32         {d1[0]},  [r0,:32], r1
313         vst1.32         {d1[1]},  [r0,:32], r1
314
315         bx              lr
316 endfunc
317 .endm
318
319 itxfm_func4x4 idct,  idct
320 itxfm_func4x4 iadst, idct
321 itxfm_func4x4 idct,  iadst
322 itxfm_func4x4 iadst, iadst
323 itxfm_func4x4 iwht,  iwht
324
325
326 .macro idct8
327         dmbutterfly0    d16, d17, d24, d25, q8,  q12, q2, q4, d4, d5, d8, d9, q3, q2, q5, q4 @ q8 = t0a, q12 = t1a
328         dmbutterfly     d20, d21, d28, d29, d0[1], d0[2], q2,  q3,  q4,  q5 @ q10 = t2a, q14 = t3a
329         dmbutterfly     d18, d19, d30, d31, d0[3], d1[0], q2,  q3,  q4,  q5 @ q9  = t4a, q15 = t7a
330         dmbutterfly     d26, d27, d22, d23, d1[1], d1[2], q2,  q3,  q4,  q5 @ q13 = t5a, q11 = t6a
331
332         butterfly       q2,  q14, q8,  q14 @ q2 = t0, q14 = t3
333         butterfly       q3,  q10, q12, q10 @ q3 = t1, q10 = t2
334         butterfly       q4,  q13, q9,  q13 @ q4 = t4, q13 = t5a
335         butterfly       q5,  q11, q15, q11 @ q5 = t7, q11 = t6a
336
337         butterfly       q8,  q15, q2,  q5  @ q8 = out[0], q15 = out[7]
338
339         dmbutterfly0    d4,  d5,  d10, d11, q11, q13, q9,  q13, d18, d19, d26, d27, q2,  q5, q11, q12 @ q2 = t6, q5 = t5
340
341         butterfly       q11, q12, q14, q4  @ q11 = out[3], q12 = out[4]
342         butterfly       q9,  q14, q3,  q2  @ q9 = out[1],  q14 = out[6]
343         butterfly_r     q13, q10, q10, q5  @ q13 = out[5], q10 = out[2]
344 .endm
345
346 .macro iadst8
347         dmbutterfly_l   q4,  q5,  q2,  q3,  d30, d31, d16, d17, d2[1], d2[0] @ q4,q5  = t1a, q2,q3 = t0a
348         dmbutterfly_l   q8,  q15, q6,  q7,  d22, d23, d24, d25, d3[1], d3[0] @ q8,q15 = t5a, q6,q7 = t4a
349
350         dbutterfly_n    d22, d23, d4,  d5,  q2,  q3,  q6,  q7,  q11, q12, q2,  q3 @ q11 = t0, q2 = t4
351
352         dbutterfly_n    d24, d25, d6,  d7,  q4,  q5,  q8,  q15, q12, q3,  q6,  q7 @ q12 = t1, q3 = t5
353
354         dmbutterfly_l   q6,  q7,  q4,  q5,  d26, d27, d20, d21, d2[3], d2[2] @ q6,q7 = t3a, q4,q5 = t2a
355         dmbutterfly_l   q10, q13, q8,  q15, d18, d19, d28, d29, d3[3], d3[2] @ q10,q13 = t7a, q8,q15 = t6a
356
357         dbutterfly_n    d18, d19, d8,  d9,  q4,  q5,  q8,  q15, q9,  q14, q4, q5 @ q9 = t2, q4 = t6
358         dbutterfly_n    d16, d17, d12, d13, q6,  q7,  q10, q13, q8,  q15, q6, q7 @ q8 = t3, q6 = t7
359
360         butterfly       q15, q12, q12, q8 @ q15 = -out[7], q12 = t3
361         vneg.s16        q15, q15          @ q15 = out[7]
362         butterfly       q8,  q9,  q11, q9 @ q8 = out[0], q9 = t2
363
364         dmbutterfly_l   q10, q11, q5,  q7,  d4,  d5,  d6,  d7,  d0[1], d0[2] @ q10,q11 = t5a, q5,q7 = t4a
365         dmbutterfly_l   q2,  q3,  q13, q14, d12, d13, d8,  d9,  d0[2], d0[1] @ q2,q3 = t6a, q13,q14 = t7a
366
367         dbutterfly_n    d28, d29, d8,  d9,  q10, q11, q13, q14, q4,  q6,  q10, q11 @ q14 = out[6], q4 = t7
368
369         dmbutterfly0    d22, d23, d24, d25, q9,  q12, q6, q13, d12, d13, d26, d27, q9, q10 @ q11 = -out[3], q12 = out[4]
370         vneg.s16        q11, q11      @ q11 = out[3]
371
372         dbutterfly_n    d18, d19, d4,  d5,  q5,  q7,  q2,  q3,  q9, q10, q2,  q3 @ q9 = -out[1], q2 = t6
373         vneg.s16        q9,  q9       @ q9 = out[1]
374
375         dmbutterfly0    d20, d21, d26, d27, q2,  q4,  q3, q5,  d6,  d7,  d10, d11, q6,  q7 @ q10 = out[2], q13 = -out[5]
376         vneg.s16        q13, q13      @ q13 = out[5]
377 .endm
378
379
380 .macro itxfm_func8x8 txfm1, txfm2
381 function ff_vp9_\txfm1\()_\txfm2\()_8x8_add_neon, export=1
382         @ Push q4-q7 if iadst is used, idct requires
383         @ a few scratch registers less, so only push q4-q5
384         @ if only idct is involved.
385         @ The iadst also uses a few coefficients from
386         @ idct, so those always need to be loaded.
387 .ifc \txfm1\()_\txfm2,idct_idct
388         movrel          r12, idct_coeffs
389         vpush           {q4-q5}
390         vld1.16         {q0}, [r12,:128]
391 .else
392         movrel          r12, iadst8_coeffs
393         vld1.16         {q1}, [r12,:128]!
394         vpush           {q4-q7}
395         vld1.16         {q0}, [r12,:128]
396 .endif
397
398         vmov.i16        q2, #0
399         vmov.i16        q3, #0
400
401 .ifc \txfm1\()_\txfm2,idct_idct
402         cmp             r3,  #1
403         bne             1f
404         @ DC-only for idct/idct
405         vld1.16         {d16[]}, [r2,:16]
406         vmull.s16       q8,  d16, d0[0]
407         vrshrn.s32      d16, q8,  #14
408         vmull.s16       q8,  d16, d0[0]
409         vrshrn.s32      d16, q8,  #14
410         vdup.16         q8,  d16[0]
411         vmov            q9,  q8
412         vmov            q10, q8
413         vmov            q11, q8
414         vmov            q12, q8
415         vmov            q13, q8
416         vmov            q14, q8
417         vmov            q15, q8
418         vst1.16         {d4[0]}, [r2,:16]
419         b               2f
420 .endif
421 1:
422         vld1.16         {q8-q9},    [r2,:128]!
423         vld1.16         {q10-q11},  [r2,:128]!
424         vld1.16         {q12-q13},  [r2,:128]!
425         vld1.16         {q14-q15},  [r2,:128]!
426         sub             r2,  r2,  #128
427         vst1.16         {q2-q3}, [r2,:128]!
428         vst1.16         {q2-q3}, [r2,:128]!
429         vst1.16         {q2-q3}, [r2,:128]!
430         vst1.16         {q2-q3}, [r2,:128]!
431
432         \txfm1\()8
433
434         @ Transpose 8x8 with 16 bit elements
435         vswp            d17, d24
436         vswp            d19, d26
437         vswp            d21, d28
438         vswp            d23, d30
439         transpose16_4x4 q8, q9, q10, q11, q12, q13, q14, q15
440
441         \txfm2\()8
442 2:
443         mov             r3,  r0
444         @ Add into the destination
445         vld1.8          {d4},  [r0,:64], r1
446         vrshr.s16       q8,  q8,  #5
447         vld1.8          {d5},  [r0,:64], r1
448         vrshr.s16       q9,  q9,  #5
449         vld1.8          {d6},  [r0,:64], r1
450         vrshr.s16       q10, q10, #5
451         vaddw.u8        q8,  q8,  d4
452         vld1.8          {d7},  [r0,:64], r1
453         vrshr.s16       q11, q11, #5
454         vaddw.u8        q9,  q9,  d5
455         vld1.8          {d8},  [r0,:64], r1
456         vrshr.s16       q12, q12, #5
457         vaddw.u8        q10, q10, d6
458         vqmovun.s16     d4,  q8
459         vld1.8          {d9},  [r0,:64], r1
460         vrshr.s16       q13, q13, #5
461         vaddw.u8        q11, q11, d7
462         vqmovun.s16     d5,  q9
463         vld1.8          {d10}, [r0,:64], r1
464         vrshr.s16       q14, q14, #5
465         vaddw.u8        q12, q12, d8
466         vqmovun.s16     d6,  q10
467         vld1.8          {d11}, [r0,:64], r1
468         vrshr.s16       q15, q15, #5
469         vaddw.u8        q13, q13, d9
470         vqmovun.s16     d7,  q11
471
472
473         vst1.8          {d4},  [r3,:64], r1
474         vaddw.u8        q14, q14, d10
475         vst1.8          {d5},  [r3,:64], r1
476         vqmovun.s16     d8,  q12
477         vst1.8          {d6},  [r3,:64], r1
478         vaddw.u8        q15, q15, d11
479         vst1.8          {d7},  [r3,:64], r1
480         vqmovun.s16     d9,  q13
481         vst1.8          {d8},  [r3,:64], r1
482         vqmovun.s16     d10, q14
483         vst1.8          {d9},  [r3,:64], r1
484         vqmovun.s16     d11, q15
485
486         vst1.8          {d10}, [r3,:64], r1
487         vst1.8          {d11}, [r3,:64], r1
488
489 .ifc \txfm1\()_\txfm2,idct_idct
490         vpop            {q4-q5}
491 .else
492         vpop            {q4-q7}
493 .endif
494         bx              lr
495 endfunc
496 .endm
497
498 itxfm_func8x8 idct,  idct
499 itxfm_func8x8 iadst, idct
500 .ltorg
501 itxfm_func8x8 idct,  iadst
502 itxfm_func8x8 iadst, iadst
503
504
505 function idct16x16_dc_add_neon
506         movrel          r12, idct_coeffs
507         vld1.16         {d0}, [r12,:64]
508
509         vmov.i16        q2, #0
510
511         vld1.16         {d16[]}, [r2,:16]
512         vmull.s16       q8,  d16, d0[0]
513         vrshrn.s32      d16, q8,  #14
514         vmull.s16       q8,  d16, d0[0]
515         vrshrn.s32      d16, q8,  #14
516         vdup.16         q8,  d16[0]
517         vst1.16         {d4[0]}, [r2,:16]
518
519         vrshr.s16       q8,  q8,  #6
520
521         mov             r12, #16
522 1:
523         @ Loop to add the constant from q8 into all 16x16 outputs
524         vld1.8          {q3},  [r0,:128]
525         vaddw.u8        q10, q8,  d6
526         vaddw.u8        q11, q8,  d7
527         vqmovun.s16     d6,  q10
528         vqmovun.s16     d7,  q11
529         vst1.8          {q3},  [r0,:128], r1
530         subs            r12, r12, #1
531         bne             1b
532
533         bx              lr
534 endfunc
535 .ltorg
536
537 function idct16
538         mbutterfly0     d16, d24, d16, d24, d4, d6,  q2,  q3 @ d16 = t0a,  d24 = t1a
539         mbutterfly      d20, d28, d0[1], d0[2], q2,  q3  @ d20 = t2a,  d28 = t3a
540         mbutterfly      d18, d30, d0[3], d1[0], q2,  q3  @ d18 = t4a,  d30 = t7a
541         mbutterfly      d26, d22, d1[1], d1[2], q2,  q3  @ d26 = t5a,  d22 = t6a
542         mbutterfly      d17, d31, d1[3], d2[0], q2,  q3  @ d17 = t8a,  d31 = t15a
543         mbutterfly      d25, d23, d2[1], d2[2], q2,  q3  @ d25 = t9a,  d23 = t14a
544         mbutterfly      d21, d27, d2[3], d3[0], q2,  q3  @ d21 = t10a, d27 = t13a
545         mbutterfly      d29, d19, d3[1], d3[2], q2,  q3  @ d29 = t11a, d19 = t12a
546
547         butterfly       d4,  d28, d16, d28               @ d4  = t0,   d28 = t3
548         butterfly       d5,  d20, d24, d20               @ d5  = t1,   d20 = t2
549         butterfly       d6,  d26, d18, d26               @ d6  = t4,   d26 = t5
550         butterfly       d7,  d22, d30, d22               @ d7  = t7,   d22 = t6
551         butterfly       d16, d25, d17, d25               @ d16 = t8,   d25 = t9
552         butterfly       d24, d21, d29, d21               @ d24 = t11,  d21 = t10
553         butterfly       d17, d27, d19, d27               @ d17 = t12,  d27 = t13
554         butterfly       d29, d23, d31, d23               @ d29 = t15,  d23 = t14
555
556         mbutterfly0     d22, d26, d22, d26, d18, d30, q9,  q15  @ d22 = t6a, d26 = t5a
557         mbutterfly      d23, d25, d0[1], d0[2], q9,  q15        @ d23 = t9a,  d25 = t14a
558         mbutterfly      d27, d21, d0[1], d0[2], q9,  q15, neg=1 @ d27 = t13a, d21 = t10a
559
560         butterfly       d18, d7,  d4,  d7                @ d18 = t0a,  d7  = t7a
561         butterfly       d19, d22, d5,  d22               @ d19 = t1a,  d22 = t6
562         butterfly       d4,  d26, d20, d26               @ d4  = t2a,  d26 = t5
563         butterfly       d5,  d6,  d28, d6                @ d5  = t3a,  d6  = t4
564         butterfly       d20, d28, d16, d24               @ d20 = t8a,  d28 = t11a
565         butterfly       d24, d21, d23, d21               @ d24 = t9,   d21 = t10
566         butterfly       d23, d27, d25, d27               @ d23 = t14,  d27 = t13
567         butterfly       d25, d29, d29, d17               @ d25 = t15a, d29 = t12a
568
569         mbutterfly0     d27, d21, d27, d21, d16, d30, q8, q15 @ d27 = t13a, d21 = t10a
570         mbutterfly0     d29, d28, d29, d28, d16, d30, q8, q15 @ d29 = t12,  d28 = t11
571
572         vswp            d27, d29                         @ d27 = t12, d29 = t13a
573         vswp            d28, d27                         @ d28 = t12, d27 = t11
574         butterfly       d16, d31, d18, d25               @ d16 = out[0], d31 = out[15]
575         butterfly       d17, d30, d19, d23               @ d17 = out[1], d30 = out[14]
576         butterfly_r     d25, d22, d22, d24               @ d25 = out[9], d22 = out[6]
577         butterfly       d23, d24, d7,  d20               @ d23 = out[7], d24 = out[8]
578         butterfly       d18, d29, d4,  d29               @ d18 = out[2], d29 = out[13]
579         butterfly       d19, d28, d5,  d28               @ d19 = out[3], d28 = out[12]
580         vmov            d4,  d21                         @ d4  = t10a
581         butterfly       d20, d27, d6,  d27               @ d20 = out[4], d27 = out[11]
582         butterfly       d21, d26, d26, d4                @ d21 = out[5], d26 = out[10]
583         bx              lr
584 endfunc
585
586 function iadst16
587         movrel          r12, iadst16_coeffs
588         vld1.16         {q0-q1}, [r12,:128]
589
590         mbutterfly_l    q3,  q2,  d31, d16, d0[1], d0[0] @ q3  = t1,   q2  = t0
591         mbutterfly_l    q5,  q4,  d23, d24, d2[1], d2[0] @ q5  = t9,   q4  = t8
592         butterfly_n     d31, d24, q3,  q5,  q6,  q5      @ d31 = t1a,  d24 = t9a
593         mbutterfly_l    q7,  q6,  d29, d18, d0[3], d0[2] @ q7  = t3,   q6  = t2
594         butterfly_n     d16, d23, q2,  q4,  q3,  q4      @ d16 = t0a,  d23 = t8a
595
596         mbutterfly_l    q3,  q2,  d21, d26, d2[3], d2[2] @ q3  = t11,  q2  = t10
597         butterfly_n     d29, d26, q7,  q3,  q4,  q3      @ d29 = t3a,  d26 = t11a
598         mbutterfly_l    q5,  q4,  d27, d20, d1[1], d1[0] @ q5  = t5,   q4  = t4
599         butterfly_n     d18, d21, q6,  q2,  q3,  q2      @ d18 = t2a,  d21 = t10a
600
601         mbutterfly_l    q7,  q6,  d19, d28, d3[1], d3[0] @ q7  = t13,  q6  = t12
602         butterfly_n     d20, d28, q5,  q7,  q2,  q7      @ d20 = t5a,  d28 = t13a
603         mbutterfly_l    q3,  q2,  d25, d22, d1[3], d1[2] @ q3  = t7,   q2  = t6
604         butterfly_n     d27, d19, q4,  q6,  q5,  q6      @ d27 = t4a,  d19 = t12a
605
606         mbutterfly_l    q5,  q4,  d17, d30, d3[3], d3[2] @ q5  = t15,  q4  = t14
607         movrel          r12, idct_coeffs
608         vld1.16         {q0}, [r12,:128]
609         butterfly_n     d22, d30, q3,  q5,  q6,  q5      @ d22 = t7a,  d30 = t15a
610         mbutterfly_l    q7,  q6,  d23, d24, d0[3], d1[0] @ q7  = t9,   q6  = t8
611         butterfly_n     d25, d17, q2,  q4,  q3,  q4      @ d25 = t6a,  d17 = t14a
612
613         mbutterfly_l    q2,  q3,  d28, d19, d1[0], d0[3] @ q2  = t12,  q3  = t13
614         butterfly_n     d23, d19, q6,  q2,  q4,  q2      @ d23 = t8a,  d19 = t12a
615         mbutterfly_l    q5,  q4,  d21, d26, d1[1], d1[2] @ q5  = t11,  q4  = t10
616         butterfly_r     d4,  d27, d16, d27               @ d4  = t4,   d27 = t0
617         butterfly_n     d24, d28, q7,  q3,  q6,  q3      @ d24 = t9a,  d28 = t13a
618
619         mbutterfly_l    q6,  q7,  d30, d17, d1[2], d1[1] @ q6  = t14,  q7  = t15
620         butterfly_r     d5,  d20, d31, d20               @ d5  = t5,   d20 = t1
621         butterfly_n     d21, d17, q4,  q6,  q3,  q6      @ d21 = t10a, d17 = t14a
622         butterfly_n     d26, d30, q5,  q7,  q4,  q7      @ d26 = t11a, d30 = t15a
623
624         butterfly_r     d6,  d25, d18, d25               @ d6  = t6,   d25 = t2
625         butterfly_r     d7,  d22, d29, d22               @ d7  = t7,   d22 = t3
626
627         mbutterfly_l    q5,  q4,  d19, d28, d0[1], d0[2] @ q5  = t13,  q4  = t12
628         mbutterfly_l    q6,  q7,  d30, d17, d0[2], d0[1] @ q6  = t14,  q7  = t15
629
630         butterfly_n     d18, d30, q4,  q6,  q8,  q6      @ d18 = out[2],   d30 = t14a
631         butterfly_n     d29, d17, q5,  q7,  q6,  q7      @ d29 = -out[13], d17 = t15a
632         vneg.s16        d29, d29                         @ d29 = out[13]
633
634         mbutterfly_l    q5,  q4,  d4,  d5,  d0[1], d0[2] @ q5  = t5a,  q4  = t4a
635         mbutterfly_l    q6,  q7,  d7,  d6,  d0[2], d0[1] @ q6  = t6a,  q7  = t7a
636
637         butterfly       d2,  d6,  d27, d25               @ d2 = out[0], d6 = t2a
638         butterfly       d3,  d7,  d23, d21               @ d3 =-out[1], d7 = t10
639
640         butterfly_n     d19, d31, q4,  q6,  q2,  q4      @ d19 = -out[3],  d31 = t6
641         vneg.s16        d19, d19                         @ d19 = out[3]
642         butterfly_n     d28, d16, q5,  q7,  q2,  q5      @ d28 = out[12],  d16 = t7
643
644         butterfly       d5,  d8,  d20, d22               @ d5 =-out[15],d8 = t3a
645         butterfly       d4,  d9,  d24, d26               @ d4 = out[14],d9 = t11
646
647         mbutterfly0     d23, d24, d6,  d8,  d10, d11, q6,  q7, 1 @ d23 = out[7], d24 = out[8]
648         mbutterfly0     d20, d27, d16, d31, d10, d11, q6,  q7    @ d20 = out[4], d27 = out[11]
649         mbutterfly0     d22, d25, d9,  d7,  d10, d11, q6,  q7    @ d22 = out[6], d25 = out[9]
650         mbutterfly0     d21, d26, d30, d17, d10, d11, q6,  q7, 1 @ d21 = out[5], d26 = out[10]
651
652         vneg.s16        d31, d5                          @ d31 = out[15]
653         vneg.s16        d17, d3                          @ d17 = out[1]
654
655         vmov            d16, d2
656         vmov            d30, d4
657         bx              lr
658 endfunc
659
660 .macro load_add_store coef0, coef1, coef2, coef3
661         vrshr.s16       \coef0, \coef0, #6
662         vrshr.s16       \coef1, \coef1, #6
663
664         vld1.32         {d4[]},   [r0,:32], r1
665         vld1.32         {d4[1]},  [r3,:32], r1
666         vrshr.s16       \coef2, \coef2, #6
667         vrshr.s16       \coef3, \coef3, #6
668         vld1.32         {d5[]},   [r0,:32], r1
669         vld1.32         {d5[1]},  [r3,:32], r1
670         vaddw.u8        \coef0, \coef0, d4
671         vld1.32         {d6[]},   [r0,:32], r1
672         vld1.32         {d6[1]},  [r3,:32], r1
673         vaddw.u8        \coef1, \coef1, d5
674         vld1.32         {d7[]},   [r0,:32], r1
675         vld1.32         {d7[1]},  [r3,:32], r1
676
677         vqmovun.s16     d4,  \coef0
678         vqmovun.s16     d5,  \coef1
679         sub             r0,  r0,  r1, lsl #2
680         sub             r3,  r3,  r1, lsl #2
681         vaddw.u8        \coef2, \coef2, d6
682         vaddw.u8        \coef3, \coef3, d7
683         vst1.32         {d4[0]},  [r0,:32], r1
684         vst1.32         {d4[1]},  [r3,:32], r1
685         vqmovun.s16     d6,  \coef2
686         vst1.32         {d5[0]},  [r0,:32], r1
687         vst1.32         {d5[1]},  [r3,:32], r1
688         vqmovun.s16     d7,  \coef3
689
690         vst1.32         {d6[0]},  [r0,:32], r1
691         vst1.32         {d6[1]},  [r3,:32], r1
692         vst1.32         {d7[0]},  [r0,:32], r1
693         vst1.32         {d7[1]},  [r3,:32], r1
694 .endm
695
696 .macro itxfm16_1d_funcs txfm
697 @ Read a vertical 4x16 slice out of a 16x16 matrix, do a transform on it,
698 @ transpose into a horizontal 16x4 slice and store.
699 @ r0 = dst (temp buffer)
700 @ r1 = slice offset
701 @ r2 = src
702 function \txfm\()16_1d_4x16_pass1_neon
703         push            {lr}
704
705         mov             r12, #32
706         vmov.s16        q2, #0
707 .irp i, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31
708         vld1.16         {d\i}, [r2,:64]
709         vst1.16         {d4},  [r2,:64], r12
710 .endr
711
712         bl              \txfm\()16
713
714         @ Do four 4x4 transposes. Originally, d16-d31 contain the
715         @ 16 rows. Afterwards, d16-d19, d20-d23, d24-d27, d28-d31
716         @ contain the transposed 4x4 blocks.
717         transpose16_q_4x_4x4 q8,  q9,  q10, q11, q12, q13, q14, q15, d16, d17, d18, d19, d20, d21, d22, d23, d24, d25, d26, d27, d28, d29, d30, d31
718
719         @ Store the transposed 4x4 blocks horizontally.
720         cmp             r1,  #12
721         beq             1f
722 .irp i, 16, 20, 24, 28, 17, 21, 25, 29, 18, 22, 26, 30, 19, 23, 27, 31
723         vst1.16         {d\i}, [r0,:64]!
724 .endr
725         pop             {pc}
726 1:
727         @ Special case: For the last input column (r1 == 12),
728         @ which would be stored as the last row in the temp buffer,
729         @ don't store the first 4x4 block, but keep it in registers
730         @ for the first slice of the second pass (where it is the
731         @ last 4x4 block).
732         add             r0,  r0,  #8
733         vst1.16         {d20}, [r0,:64]!
734         vst1.16         {d24}, [r0,:64]!
735         vst1.16         {d28}, [r0,:64]!
736         add             r0,  r0,  #8
737         vst1.16         {d21}, [r0,:64]!
738         vst1.16         {d25}, [r0,:64]!
739         vst1.16         {d29}, [r0,:64]!
740         add             r0,  r0,  #8
741         vst1.16         {d22}, [r0,:64]!
742         vst1.16         {d26}, [r0,:64]!
743         vst1.16         {d30}, [r0,:64]!
744         add             r0,  r0,  #8
745         vst1.16         {d23}, [r0,:64]!
746         vst1.16         {d27}, [r0,:64]!
747         vst1.16         {d31}, [r0,:64]!
748         vmov            d28, d16
749         vmov            d29, d17
750         vmov            d30, d18
751         vmov            d31, d19
752         pop             {pc}
753 endfunc
754
755 @ Read a vertical 4x16 slice out of a 16x16 matrix, do a transform on it,
756 @ load the destination pixels (from a similar 4x16 slice), add and store back.
757 @ r0 = dst
758 @ r1 = dst stride
759 @ r2 = src (temp buffer)
760 @ r3 = slice offset
761 function \txfm\()16_1d_4x16_pass2_neon
762         push            {lr}
763         mov             r12, #32
764 .irp i, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27
765         vld1.16         {d\i}, [r2,:64], r12
766 .endr
767         cmp             r3,  #0
768         beq             1f
769 .irp i, 28, 29, 30, 31
770         vld1.16         {d\i}, [r2,:64], r12
771 .endr
772 1:
773
774         add             r3,  r0,  r1
775         lsl             r1,  r1,  #1
776         bl              \txfm\()16
777
778         load_add_store  q8,  q9,  q10, q11
779         load_add_store  q12, q13, q14, q15
780
781         pop             {pc}
782 endfunc
783 .endm
784
785 itxfm16_1d_funcs idct
786 itxfm16_1d_funcs iadst
787
788 @ This is the minimum eob value for each subpartition, in increments of 4
789 const min_eob_idct_idct_16, align=4
790         .short  0, 10, 38, 89
791 endconst
792
793 .macro itxfm_func16x16 txfm1, txfm2
794 function ff_vp9_\txfm1\()_\txfm2\()_16x16_add_neon, export=1
795 .ifc \txfm1\()_\txfm2,idct_idct
796         cmp             r3,  #1
797         beq             idct16x16_dc_add_neon
798 .endif
799         push            {r4-r8,lr}
800 .ifnc \txfm1\()_\txfm2,idct_idct
801         vpush           {q4-q7}
802 .else
803         movrel          r8,  min_eob_idct_idct_16 + 2
804 .endif
805
806         @ Align the stack, allocate a temp buffer
807 T       mov             r7,  sp
808 T       and             r7,  r7,  #15
809 A       and             r7,  sp,  #15
810         add             r7,  r7,  #512
811         sub             sp,  sp,  r7
812
813         mov             r4,  r0
814         mov             r5,  r1
815         mov             r6,  r2
816
817 .ifc \txfm1,idct
818         movrel          r12, idct_coeffs
819         vld1.16         {q0-q1}, [r12,:128]
820 .endif
821
822 .irp i, 0, 4, 8, 12
823         add             r0,  sp,  #(\i*32)
824 .ifc \txfm1\()_\txfm2,idct_idct
825 .if \i > 0
826         ldrh_post       r1,  r8,  #2
827         cmp             r3,  r1
828         it              le
829         movle           r1,  #(16 - \i)/4
830         ble             1f
831 .endif
832 .endif
833         mov             r1,  #\i
834         add             r2,  r6,  #(\i*2)
835         bl              \txfm1\()16_1d_4x16_pass1_neon
836 .endr
837
838 .ifc \txfm1\()_\txfm2,idct_idct
839         b               3f
840 1:
841         @ For all-zero slices in pass 1, set d28-d31 to zero, for the in-register
842         @ passthrough of coefficients to pass 2 and clear the end of the temp buffer
843         vmov.i16        q14, #0
844         vmov.i16        q15, #0
845 2:
846         subs            r1,  r1,  #1
847 .rept 4
848         vst1.16         {q14-q15}, [r0,:128]!
849 .endr
850         bne             2b
851 3:
852 .endif
853
854 .ifc \txfm1\()_\txfm2,iadst_idct
855         movrel          r12, idct_coeffs
856         vld1.16         {q0-q1}, [r12,:128]
857 .endif
858 .irp i, 0, 4, 8, 12
859         add             r0,  r4,  #(\i)
860         mov             r1,  r5
861         add             r2,  sp,  #(\i*2)
862         mov             r3,  #\i
863         bl              \txfm2\()16_1d_4x16_pass2_neon
864 .endr
865
866         add             sp,  sp,  r7
867 .ifnc \txfm1\()_\txfm2,idct_idct
868         vpop            {q4-q7}
869 .endif
870         pop             {r4-r8,pc}
871 endfunc
872 .endm
873
874 itxfm_func16x16 idct,  idct
875 itxfm_func16x16 iadst, idct
876 itxfm_func16x16 idct,  iadst
877 itxfm_func16x16 iadst, iadst
878 .ltorg
879
880
881 function idct32x32_dc_add_neon
882         movrel          r12, idct_coeffs
883         vld1.16         {d0}, [r12,:64]
884
885         vmov.i16        q2, #0
886
887         vld1.16         {d16[]}, [r2,:16]
888         vmull.s16       q8,  d16, d0[0]
889         vrshrn.s32      d16, q8,  #14
890         vmull.s16       q8,  d16, d0[0]
891         vrshrn.s32      d16, q8,  #14
892         vdup.16         q8,  d16[0]
893         vst1.16         {d4[0]}, [r2,:16]
894
895         vrshr.s16       q8,  q8,  #6
896
897         mov             r12, #32
898 1:
899         @ Loop to add the constant from q8 into all 32x32 outputs
900         vld1.8          {q2-q3},  [r0,:128]
901         vaddw.u8        q10, q8,  d4
902         vaddw.u8        q11, q8,  d5
903         vaddw.u8        q12, q8,  d6
904         vaddw.u8        q13, q8,  d7
905         vqmovun.s16     d4,  q10
906         vqmovun.s16     d5,  q11
907         vqmovun.s16     d6,  q12
908         vqmovun.s16     d7,  q13
909         vst1.8          {q2-q3},  [r0,:128], r1
910         subs            r12, r12, #1
911         bne             1b
912
913         bx              lr
914 endfunc
915
916 function idct32_odd
917         movrel          r12, idct_coeffs
918         add             r12, r12, #32
919         vld1.16         {q0-q1}, [r12,:128]
920
921         mbutterfly      d16, d31, d0[0], d0[1], q2, q3 @ d16 = t16a, d31 = t31a
922         mbutterfly      d24, d23, d0[2], d0[3], q2, q3 @ d24 = t17a, d23 = t30a
923         mbutterfly      d20, d27, d1[0], d1[1], q2, q3 @ d20 = t18a, d27 = t29a
924         mbutterfly      d28, d19, d1[2], d1[3], q2, q3 @ d28 = t19a, d19 = t28a
925         mbutterfly      d18, d29, d2[0], d2[1], q2, q3 @ d18 = t20a, d29 = t27a
926         mbutterfly      d26, d21, d2[2], d2[3], q2, q3 @ d26 = t21a, d21 = t26a
927         mbutterfly      d22, d25, d3[0], d3[1], q2, q3 @ d22 = t22a, d25 = t25a
928         mbutterfly      d30, d17, d3[2], d3[3], q2, q3 @ d30 = t23a, d17 = t24a
929
930         sub             r12, r12, #32
931         vld1.16         {q0}, [r12,:128]
932
933         butterfly       d4,  d24, d16, d24 @ d4  = t16, d24 = t17
934         butterfly       d5,  d20, d28, d20 @ d5  = t19, d20 = t18
935         butterfly       d6,  d26, d18, d26 @ d6  = t20, d26 = t21
936         butterfly       d7,  d22, d30, d22 @ d7  = t23, d22 = t22
937         butterfly       d28, d25, d17, d25 @ d28 = t24, d25 = t25
938         butterfly       d30, d21, d29, d21 @ d30 = t27, d21 = t26
939         butterfly       d29, d23, d31, d23 @ d29 = t31, d23 = t30
940         butterfly       d31, d27, d19, d27 @ d31 = t28, d27 = t29
941
942         mbutterfly      d23, d24, d0[3], d1[0], q8, q9        @ d23 = t17a, d24 = t30a
943         mbutterfly      d27, d20, d0[3], d1[0], q8, q9, neg=1 @ d27 = t29a, d20 = t18a
944         mbutterfly      d21, d26, d1[1], d1[2], q8, q9        @ d21 = t21a, d26 = t26a
945         mbutterfly      d25, d22, d1[1], d1[2], q8, q9, neg=1 @ d25 = t25a, d22 = t22a
946
947         butterfly       d16, d5,  d4,  d5  @ d16 = t16a, d5  = t19a
948         butterfly       d17, d20, d23, d20 @ d17 = t17,  d20 = t18
949         butterfly       d18, d6,  d7,  d6  @ d18 = t23a, d6  = t20a
950         butterfly       d19, d21, d22, d21 @ d19 = t22,  d21 = t21
951         butterfly       d4,  d28, d28, d30 @ d4  = t24a, d28 = t27a
952         butterfly       d23, d26, d25, d26 @ d23 = t25,  d26 = t26
953         butterfly       d7,  d29, d29, d31 @ d7  = t31a, d29 = t28a
954         butterfly       d22, d27, d24, d27 @ d22 = t30,  d27 = t29
955
956         mbutterfly      d27, d20, d0[1], d0[2], q12, q15        @ d27 = t18a, d20 = t29a
957         mbutterfly      d29, d5,  d0[1], d0[2], q12, q15        @ d29 = t19,  d5  = t28
958         mbutterfly      d28, d6,  d0[1], d0[2], q12, q15, neg=1 @ d28 = t27,  d6  = t20
959         mbutterfly      d26, d21, d0[1], d0[2], q12, q15, neg=1 @ d26 = t26a, d21 = t21a
960
961         butterfly       d31, d24, d7,  d4  @ d31 = t31,  d24 = t24
962         butterfly       d30, d25, d22, d23 @ d30 = t30a, d25 = t25a
963         butterfly_r     d23, d16, d16, d18 @ d23 = t23,  d16 = t16
964         butterfly_r     d22, d17, d17, d19 @ d22 = t22a, d17 = t17a
965         butterfly       d18, d21, d27, d21 @ d18 = t18,  d21 = t21
966         butterfly_r     d27, d28, d5,  d28 @ d27 = t27a, d28 = t28a
967         butterfly       d4,  d26, d20, d26 @ d4  = t29,  d26 = t26
968         butterfly       d19, d20, d29, d6  @ d19 = t19a, d20 = t20
969         vmov            d29, d4            @ d29 = t29
970
971         mbutterfly0     d27, d20, d27, d20, d4, d6, q2, q3 @ d27 = t27,  d20 = t20
972         mbutterfly0     d26, d21, d26, d21, d4, d6, q2, q3 @ d26 = t26a, d21 = t21a
973         mbutterfly0     d25, d22, d25, d22, d4, d6, q2, q3 @ d25 = t25,  d22 = t22
974         mbutterfly0     d24, d23, d24, d23, d4, d6, q2, q3 @ d24 = t24a, d23 = t23a
975         bx              lr
976 endfunc
977
978 @ Do an 32-point IDCT of a 4x32 slice out of a 32x32 matrix.
979 @ We don't have register space to do a single pass IDCT of 4x32 though,
980 @ but the 32-point IDCT can be decomposed into two 16-point IDCTs;
981 @ a normal IDCT16 with every other input component (the even ones, with
982 @ each output written twice), followed by a separate 16-point IDCT
983 @ of the odd inputs, added/subtracted onto the outputs of the first idct16.
984 @ r0 = dst (temp buffer)
985 @ r1 = unused
986 @ r2 = src
987 function idct32_1d_4x32_pass1_neon
988         push            {lr}
989
990         movrel          r12, idct_coeffs
991         vld1.16         {q0-q1}, [r12,:128]
992
993         @ Double stride of the input, since we only read every other line
994         mov             r12, #128
995         vmov.s16        d4, #0
996
997         @ d16 = IN(0), d17 = IN(2) ... d31 = IN(30)
998 .irp i, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31
999         vld1.16         {d\i}, [r2,:64]
1000         vst1.16         {d4},  [r2,:64], r12
1001 .endr
1002
1003         bl              idct16
1004
1005         @ Do four 4x4 transposes. Originally, d16-d31 contain the
1006         @ 16 rows. Afterwards, d16-d19, d20-d23, d24-d27, d28-d31
1007         @ contain the transposed 4x4 blocks.
1008         transpose16_q_4x_4x4 q8,  q9,  q10, q11, q12, q13, q14, q15, d16, d17, d18, d19, d20, d21, d22, d23, d24, d25, d26, d27, d28, d29, d30, d31
1009         @ Store the registers a, b, c, d horizontally, followed
1010         @ by the same registers d, c, b, a mirrored.
1011 .macro store_rev a, b, c, d
1012 .irp i, \a, \b, \c, \d
1013         vst1.16         {d\i}, [r0,:64]!
1014         vrev64.16       d\i, d\i
1015 .endr
1016 .irp i, \d, \c, \b, \a
1017         vst1.16         {d\i}, [r0,:64]!
1018 .endr
1019 .endm
1020         store_rev       16, 20, 24, 28
1021         store_rev       17, 21, 25, 29
1022         store_rev       18, 22, 26, 30
1023         store_rev       19, 23, 27, 31
1024         sub             r0,  r0,  #256
1025 .purgem store_rev
1026
1027         @ Move r2 back to the start of the input, and move
1028         @ to the first odd row
1029         sub             r2,  r2,  r12, lsl #4
1030         add             r2,  r2,  #64
1031
1032         vmov.s16        d4, #0
1033         @ d16 = IN(1), d17 = IN(3) ... d31 = IN(31)
1034 .irp i, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31
1035         vld1.16         {d\i}, [r2,:64]
1036         vst1.16         {d4},  [r2,:64], r12
1037 .endr
1038
1039         bl              idct32_odd
1040
1041         transpose16_q_4x_4x4 q15, q14, q13, q12, q11, q10, q9,  q8,  d31, d30, d29, d28, d27, d26, d25, d24, d23, d22, d21, d20, d19, d18, d17, d16
1042
1043         @ Store the registers a, b, c, d horizontally,
1044         @ adding into the output first, and then mirrored, subtracted
1045         @ from the output.
1046 .macro store_rev a, b, c, d
1047 .irp i, \a, \b, \c, \d
1048         vld1.16         {d4},  [r0,:64]
1049         vadd.s16        d4, d4, d\i
1050         vst1.16         {d4},  [r0,:64]!
1051         vrev64.16       d\i, d\i
1052 .endr
1053 .irp i, \d, \c, \b, \a
1054         vld1.16         {d4},  [r0,:64]
1055         vsub.s16        d4, d4, d\i
1056         vst1.16         {d4},  [r0,:64]!
1057 .endr
1058 .endm
1059
1060         store_rev       31, 27, 23, 19
1061         store_rev       30, 26, 22, 18
1062         store_rev       29, 25, 21, 17
1063         store_rev       28, 24, 20, 16
1064 .purgem store_rev
1065         pop             {pc}
1066 endfunc
1067 .ltorg
1068
1069 @ This is mostly the same as 4x32_pass1, but without the transpose,
1070 @ and use the source as temp buffer between the two idct passes, and
1071 @ add into the destination.
1072 @ r0 = dst
1073 @ r1 = dst stride
1074 @ r2 = src (temp buffer)
1075 function idct32_1d_4x32_pass2_neon
1076         push            {lr}
1077         movrel          r12, idct_coeffs
1078         vld1.16         {q0-q1}, [r12,:128]
1079
1080         mov             r12, #128
1081         @ d16 = IN(0), d17 = IN(2) ... d31 = IN(30)
1082 .irp i, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31
1083         vld1.16         {d\i}, [r2,:64], r12
1084 .endr
1085         sub             r2,  r2,  r12, lsl #4
1086
1087         bl              idct16
1088
1089 .irp i, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31
1090         vst1.16         {d\i}, [r2,:64], r12
1091 .endr
1092
1093         sub             r2,  r2,  r12, lsl #4
1094         add             r2,  r2,  #64
1095
1096         @ d16 = IN(1), d17 = IN(3) ... d31 = IN(31)
1097 .irp i, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31
1098         vld1.16         {d\i}, [r2,:64], r12
1099 .endr
1100         sub             r2,  r2,  r12, lsl #4
1101         sub             r2,  r2,  #64
1102
1103         bl              idct32_odd
1104
1105         mov             r12, #128
1106 .macro load_acc_store a, b, c, d, neg=0
1107         vld1.16         {d4},  [r2,:64], r12
1108         vld1.16         {d5},  [r2,:64], r12
1109 .if \neg == 0
1110         vadd.s16        d4, d4, d\a
1111         vld1.16         {d6},  [r2,:64], r12
1112         vadd.s16        d5, d5, d\b
1113         vld1.16         {d7},  [r2,:64], r12
1114         vadd.s16        d6, d6, d\c
1115         vadd.s16        d7, d7, d\d
1116 .else
1117         vsub.s16        d4, d4, d\a
1118         vld1.16         {d6},  [r2,:64], r12
1119         vsub.s16        d5, d5, d\b
1120         vld1.16         {d7},  [r2,:64], r12
1121         vsub.s16        d6, d6, d\c
1122         vsub.s16        d7, d7, d\d
1123 .endif
1124         vld1.32         {d2[]},   [r0,:32], r1
1125         vld1.32         {d2[1]},  [r0,:32], r1
1126         vrshr.s16       q2, q2, #6
1127         vld1.32         {d3[]},   [r0,:32], r1
1128         vrshr.s16       q3, q3, #6
1129         vld1.32         {d3[1]},  [r0,:32], r1
1130         sub             r0,  r0,  r1, lsl #2
1131         vaddw.u8        q2,  q2,  d2
1132         vaddw.u8        q3,  q3,  d3
1133         vqmovun.s16     d4,  q2
1134         vqmovun.s16     d5,  q3
1135         vst1.32         {d4[0]},  [r0,:32], r1
1136         vst1.32         {d4[1]},  [r0,:32], r1
1137         vst1.32         {d5[0]},  [r0,:32], r1
1138         vst1.32         {d5[1]},  [r0,:32], r1
1139 .endm
1140         load_acc_store  31, 30, 29, 28
1141         load_acc_store  27, 26, 25, 24
1142         load_acc_store  23, 22, 21, 20
1143         load_acc_store  19, 18, 17, 16
1144         sub             r2,  r2,  r12
1145         neg             r12, r12
1146         load_acc_store  16, 17, 18, 19, 1
1147         load_acc_store  20, 21, 22, 23, 1
1148         load_acc_store  24, 25, 26, 27, 1
1149         load_acc_store  28, 29, 30, 31, 1
1150 .purgem load_acc_store
1151         pop             {pc}
1152 endfunc
1153
1154 const min_eob_idct_idct_32, align=4
1155         .short  0, 9, 34, 70, 135, 240, 336, 448
1156 endconst
1157
1158 function ff_vp9_idct_idct_32x32_add_neon, export=1
1159         cmp             r3,  #1
1160         beq             idct32x32_dc_add_neon
1161         push            {r4-r8,lr}
1162         vpush           {q4-q7}
1163         movrel          r8,  min_eob_idct_idct_32 + 2
1164
1165         @ Align the stack, allocate a temp buffer
1166 T       mov             r7,  sp
1167 T       and             r7,  r7,  #15
1168 A       and             r7,  sp,  #15
1169         add             r7,  r7,  #2048
1170         sub             sp,  sp,  r7
1171
1172         mov             r4,  r0
1173         mov             r5,  r1
1174         mov             r6,  r2
1175
1176 .irp i, 0, 4, 8, 12, 16, 20, 24, 28
1177         add             r0,  sp,  #(\i*64)
1178 .if \i > 0
1179         ldrh_post       r1,  r8,  #2
1180         cmp             r3,  r1
1181         it              le
1182         movle           r1,  #(32 - \i)/2
1183         ble             1f
1184 .endif
1185         add             r2,  r6,  #(\i*2)
1186         bl              idct32_1d_4x32_pass1_neon
1187 .endr
1188         b               3f
1189
1190 1:
1191         @ Write zeros to the temp buffer for pass 2
1192         vmov.i16        q14, #0
1193         vmov.i16        q15, #0
1194 2:
1195         subs            r1,  r1,  #1
1196 .rept 4
1197         vst1.16         {q14-q15}, [r0,:128]!
1198 .endr
1199         bne             2b
1200 3:
1201 .irp i, 0, 4, 8, 12, 16, 20, 24, 28
1202         add             r0,  r4,  #(\i)
1203         mov             r1,  r5
1204         add             r2,  sp,  #(\i*2)
1205         bl              idct32_1d_4x32_pass2_neon
1206 .endr
1207
1208         add             sp,  sp,  r7
1209         vpop            {q4-q7}
1210         pop             {r4-r8,pc}
1211 endfunc