arm: vp9: Add NEON itxfm routines
[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 @ in1 = (in1 * coef1 - in2 * coef2 + (1 << 13)) >> 14
129 @ in2 = (in1 * coef2 + in2 * coef1 + (1 << 13)) >> 14
130 @ in are 2 d registers, tmp are 2 q registers
131 .macro mbutterfly in1, in2, coef1, coef2, tmp1, tmp2, neg=0
132         mbutterfly_l    \tmp1, \tmp2, \in1, \in2, \coef1, \coef2
133 .if \neg > 0
134         vneg.s32        \tmp2, \tmp2
135 .endif
136         vrshrn.s32      \in1, \tmp1,  #14
137         vrshrn.s32      \in2, \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,idct
262 .ifc \txfm2,idct
263         cmp             r3,  #1
264         bne             1f
265         @ DC-only for idct/idct
266         vld1.16         {d4[]},   [r2,:16]
267         vmull.s16       q2,  d4,  d0[0]
268         vrshrn.s32      d4,  q2,  #14
269         vmull.s16       q2,  d4,  d0[0]
270         vrshrn.s32      d4,  q2,  #14
271         vst1.16         {d30[0]}, [r2,:16]
272         vdup.16         q2,  d4[0]
273         vmov            q3,  q2
274         b               2f
275 .endif
276 .endif
277
278 1:
279         vld1.16         {d4-d7},  [r2,:128]
280         vst1.16         {q15}, [r2,:128]!
281
282 .ifc \txfm1,iwht
283         vshr.s16        q2,  q2,  #2
284         vshr.s16        q3,  q3,  #2
285 .endif
286
287         \txfm1\()4      d4,  d5,  d6,  d7
288
289         vst1.16         {q15}, [r2,:128]!
290         @ Transpose 4x4 with 16 bit elements
291         vtrn.16         d4,  d5
292         vtrn.16         d6,  d7
293         vtrn.32         q2,  q3
294
295         \txfm2\()4      d4,  d5,  d6,  d7
296 2:
297         vld1.32         {d0[]},   [r0,:32], r1
298         vld1.32         {d0[1]},  [r0,:32], r1
299 .ifnc \txfm1,iwht
300         vrshr.s16       q2,  q2,  #4
301         vrshr.s16       q3,  q3,  #4
302 .endif
303         vaddw.u8        q2,  q2,  d0
304         vld1.32         {d1[]},   [r0,:32], r1
305         vld1.32         {d1[1]},  [r0,:32], r1
306         vqmovun.s16     d0,  q2
307         sub             r0,  r0,  r1, lsl #2
308
309         vaddw.u8        q3,  q3,  d1
310         vst1.32         {d0[0]},  [r0,:32], r1
311         vqmovun.s16     d1,  q3
312
313         vst1.32         {d0[1]},  [r0,:32], r1
314         vst1.32         {d1[0]},  [r0,:32], r1
315         vst1.32         {d1[1]},  [r0,:32], r1
316
317         bx              lr
318 endfunc
319 .endm
320
321 itxfm_func4x4 idct,  idct
322 itxfm_func4x4 iadst, idct
323 itxfm_func4x4 idct,  iadst
324 itxfm_func4x4 iadst, iadst
325 itxfm_func4x4 iwht,  iwht
326
327
328 .macro idct8
329         dmbutterfly0    d16, d17, d24, d25, q8,  q12, q2, q4, d4, d5, d8, d9, q3, q2, q5, q4 @ q8 = t0a, q12 = t1a
330         dmbutterfly     d20, d21, d28, d29, d0[1], d0[2], q2,  q3,  q4,  q5 @ q10 = t2a, q14 = t3a
331         dmbutterfly     d18, d19, d30, d31, d0[3], d1[0], q2,  q3,  q4,  q5 @ q9  = t4a, q15 = t7a
332         dmbutterfly     d26, d27, d22, d23, d1[1], d1[2], q2,  q3,  q4,  q5 @ q13 = t5a, q11 = t6a
333
334         butterfly       q2,  q14, q8,  q14 @ q2 = t0, q14 = t3
335         butterfly       q3,  q10, q12, q10 @ q3 = t1, q10 = t2
336         butterfly       q4,  q13, q9,  q13 @ q4 = t4, q13 = t5a
337         butterfly       q5,  q11, q15, q11 @ q5 = t7, q11 = t6a
338
339         butterfly       q8,  q15, q2,  q5  @ q8 = out[0], q15 = out[7]
340
341         dmbutterfly0    d4,  d5,  d10, d11, q11, q13, q9,  q13, d18, d19, d26, d27, q2,  q5, q11, q12 @ q2 = t6, q5 = t5
342
343         butterfly       q11, q12, q14, q4  @ q11 = out[3], q12 = out[4]
344         butterfly       q9,  q14, q3,  q2  @ q9 = out[1],  q14 = out[6]
345         butterfly_r     q13, q10, q10, q5  @ q13 = out[5], q10 = out[2]
346 .endm
347
348 .macro iadst8
349         dmbutterfly_l   q4,  q5,  q2,  q3,  d30, d31, d16, d17, d2[1], d2[0] @ q4,q5  = t1a, q2,q3 = t0a
350         dmbutterfly_l   q8,  q15, q6,  q7,  d22, d23, d24, d25, d3[1], d3[0] @ q8,q15 = t5a, q6,q7 = t4a
351
352         dbutterfly_n    d22, d23, d4,  d5,  q2,  q3,  q6,  q7,  q11, q12, q2,  q3 @ q11 = t0, q2 = t4
353
354         dbutterfly_n    d24, d25, d6,  d7,  q4,  q5,  q8,  q15, q12, q3,  q6,  q7 @ q12 = t1, q3 = t5
355
356         dmbutterfly_l   q6,  q7,  q4,  q5,  d26, d27, d20, d21, d2[3], d2[2] @ q6,q7 = t3a, q4,q5 = t2a
357         dmbutterfly_l   q10, q13, q8,  q15, d18, d19, d28, d29, d3[3], d3[2] @ q10,q13 = t7a, q8,q15 = t6a
358
359         dbutterfly_n    d18, d19, d8,  d9,  q4,  q5,  q8,  q15, q9,  q14, q4, q5 @ q9 = t2, q4 = t6
360         dbutterfly_n    d16, d17, d12, d13, q6,  q7,  q10, q13, q8,  q15, q6, q7 @ q8 = t3, q6 = t7
361
362         butterfly       q15, q12, q12, q8 @ q15 = -out[7], q12 = t3
363         vneg.s16        q15, q15          @ q15 = out[7]
364         butterfly       q8,  q9,  q11, q9 @ q8 = out[0], q9 = t2
365
366         dmbutterfly_l   q10, q11, q5,  q7,  d4,  d5,  d6,  d7,  d0[1], d0[2] @ q10,q11 = t5a, q5,q7 = t4a
367         dmbutterfly_l   q2,  q3,  q13, q14, d12, d13, d8,  d9,  d0[2], d0[1] @ q2,q3 = t6a, q13,q14 = t7a
368
369         dbutterfly_n    d28, d29, d8,  d9,  q10, q11, q13, q14, q4,  q6,  q10, q11 @ q14 = out[6], q4 = t7
370
371         dmbutterfly0    d22, d23, d24, d25, q9,  q12, q6, q13, d12, d13, d26, d27, q9, q10 @ q11 = -out[3], q12 = out[4]
372         vneg.s16        q11, q11      @ q11 = out[3]
373
374         dbutterfly_n    d18, d19, d4,  d5,  q5,  q7,  q2,  q3,  q9, q10, q2,  q3 @ q9 = -out[1], q2 = t6
375         vneg.s16        q9,  q9       @ q9 = out[1]
376
377         dmbutterfly0    d20, d21, d26, d27, q2,  q4,  q3, q5,  d6,  d7,  d10, d11, q6,  q7 @ q10 = out[2], q13 = -out[5]
378         vneg.s16        q13, q13      @ q13 = out[5]
379 .endm
380
381
382 .macro itxfm_func8x8 txfm1, txfm2
383 function ff_vp9_\txfm1\()_\txfm2\()_8x8_add_neon, export=1
384         @ Push q4-q7 if iadst is used, idct requires
385         @ a few scratch registers less, so only push q4-q5
386         @ if only idct is involved.
387         @ The iadst also uses a few coefficients from
388         @ idct, so those always need to be loaded.
389 .ifc \txfm1,iadst
390         movrel          r12, iadst8_coeffs
391         vld1.16         {q1}, [r12,:128]!
392         vpush           {q4-q7}
393         vld1.16         {q0}, [r12,:128]
394 .else
395 .ifc \txfm2,iadst
396         movrel          r12, iadst8_coeffs
397         vld1.16         {q1}, [r12,:128]!
398         vpush           {q4-q7}
399         vld1.16         {q0}, [r12,:128]
400 .else
401         movrel          r12, idct_coeffs
402         vpush           {q4-q5}
403         vld1.16         {q0}, [r12,:128]
404 .endif
405 .endif
406
407         vmov.i16        q2, #0
408         vmov.i16        q3, #0
409
410 .ifc \txfm1,idct
411 .ifc \txfm2,idct
412         cmp             r3,  #1
413         bne             1f
414         @ DC-only for idct/idct
415         vld1.16         {d16[]}, [r2,:16]
416         vmull.s16       q8,  d16, d0[0]
417         vrshrn.s32      d16, q8,  #14
418         vmull.s16       q8,  d16, d0[0]
419         vrshrn.s32      d16, q8,  #14
420         vdup.16         q8,  d16[0]
421         vmov            q9,  q8
422         vmov            q10, q8
423         vmov            q11, q8
424         vmov            q12, q8
425         vmov            q13, q8
426         vmov            q14, q8
427         vmov            q15, q8
428         vst1.16         {d4[0]}, [r2,:16]
429         b               2f
430 .endif
431 .endif
432 1:
433         vld1.16         {q8-q9},    [r2,:128]!
434         vld1.16         {q10-q11},  [r2,:128]!
435         vld1.16         {q12-q13},  [r2,:128]!
436         vld1.16         {q14-q15},  [r2,:128]!
437         sub             r2,  r2,  #128
438         vst1.16         {q2-q3}, [r2,:128]!
439         vst1.16         {q2-q3}, [r2,:128]!
440         vst1.16         {q2-q3}, [r2,:128]!
441         vst1.16         {q2-q3}, [r2,:128]!
442
443         \txfm1\()8
444
445         @ Transpose 8x8 with 16 bit elements
446         vswp            d17, d24
447         vswp            d19, d26
448         vswp            d21, d28
449         vswp            d23, d30
450         transpose16_4x4 q8, q9, q10, q11, q12, q13, q14, q15
451
452         \txfm2\()8
453 2:
454         mov             r3,  r0
455         @ Add into the destination
456         vld1.8          {d4},  [r0,:64], r1
457         vrshr.s16       q8,  q8,  #5
458         vld1.8          {d5},  [r0,:64], r1
459         vrshr.s16       q9,  q9,  #5
460         vld1.8          {d6},  [r0,:64], r1
461         vrshr.s16       q10, q10, #5
462         vaddw.u8        q8,  q8,  d4
463         vld1.8          {d7},  [r0,:64], r1
464         vrshr.s16       q11, q11, #5
465         vaddw.u8        q9,  q9,  d5
466         vld1.8          {d8},  [r0,:64], r1
467         vrshr.s16       q12, q12, #5
468         vaddw.u8        q10, q10, d6
469         vqmovun.s16     d4,  q8
470         vld1.8          {d9},  [r0,:64], r1
471         vrshr.s16       q13, q13, #5
472         vaddw.u8        q11, q11, d7
473         vqmovun.s16     d5,  q9
474         vld1.8          {d10}, [r0,:64], r1
475         vrshr.s16       q14, q14, #5
476         vaddw.u8        q12, q12, d8
477         vqmovun.s16     d6,  q10
478         vld1.8          {d11}, [r0,:64], r1
479         vrshr.s16       q15, q15, #5
480         vaddw.u8        q13, q13, d9
481         vqmovun.s16     d7,  q11
482
483
484         vst1.8          {d4},  [r3,:64], r1
485         vaddw.u8        q14, q14, d10
486         vst1.8          {d5},  [r3,:64], r1
487         vqmovun.s16     d8,  q12
488         vst1.8          {d6},  [r3,:64], r1
489         vaddw.u8        q15, q15, d11
490         vst1.8          {d7},  [r3,:64], r1
491         vqmovun.s16     d9,  q13
492         vst1.8          {d8},  [r3,:64], r1
493         vqmovun.s16     d10, q14
494         vst1.8          {d9},  [r3,:64], r1
495         vqmovun.s16     d11, q15
496
497         vst1.8          {d10}, [r3,:64], r1
498         vst1.8          {d11}, [r3,:64], r1
499
500 .ifc \txfm1,iadst
501         vpop            {q4-q7}
502 .else
503 .ifc \txfm2,iadst
504         vpop            {q4-q7}
505 .else
506         vpop            {q4-q5}
507 .endif
508 .endif
509         bx              lr
510 endfunc
511 .endm
512
513 itxfm_func8x8 idct,  idct
514 itxfm_func8x8 iadst, idct
515 .ltorg
516 itxfm_func8x8 idct,  iadst
517 itxfm_func8x8 iadst, iadst
518
519
520 function idct16x16_dc_add_neon
521         movrel          r12, idct_coeffs
522         vld1.16         {d0}, [r12,:64]
523
524         vmov.i16        q2, #0
525
526         vld1.16         {d16[]}, [r2,:16]
527         vmull.s16       q8,  d16, d0[0]
528         vrshrn.s32      d16, q8,  #14
529         vmull.s16       q8,  d16, d0[0]
530         vrshrn.s32      d16, q8,  #14
531         vdup.16         q8,  d16[0]
532         vst1.16         {d4[0]}, [r2,:16]
533
534         vrshr.s16       q8,  q8,  #6
535
536         mov             r12, #16
537 1:
538         @ Loop to add the constant from q8 into all 16x16 outputs
539         vld1.8          {q3},  [r0,:128]
540         vaddw.u8        q10, q8,  d6
541         vaddw.u8        q11, q8,  d7
542         vqmovun.s16     d6,  q10
543         vqmovun.s16     d7,  q11
544         vst1.8          {q3},  [r0,:128], r1
545         subs            r12, r12, #1
546         bne             1b
547
548         bx              lr
549 endfunc
550 .ltorg
551
552 .macro idct16
553         mbutterfly0     d16, d24, d16, d24, d4, d6,  q2,  q3 @ d16 = t0a,  d24 = t1a
554         mbutterfly      d20, d28, d0[1], d0[2], q2,  q3  @ d20 = t2a,  d28 = t3a
555         mbutterfly      d18, d30, d0[3], d1[0], q2,  q3  @ d18 = t4a,  d30 = t7a
556         mbutterfly      d26, d22, d1[1], d1[2], q2,  q3  @ d26 = t5a,  d22 = t6a
557         mbutterfly      d17, d31, d1[3], d2[0], q2,  q3  @ d17 = t8a,  d31 = t15a
558         mbutterfly      d25, d23, d2[1], d2[2], q2,  q3  @ d25 = t9a,  d23 = t14a
559         mbutterfly      d21, d27, d2[3], d3[0], q2,  q3  @ d21 = t10a, d27 = t13a
560         mbutterfly      d29, d19, d3[1], d3[2], q2,  q3  @ d29 = t11a, d19 = t12a
561
562         butterfly       d4,  d28, d16, d28               @ d4  = t0,   d28 = t3
563         butterfly       d5,  d20, d24, d20               @ d5  = t1,   d20 = t2
564         butterfly       d6,  d26, d18, d26               @ d6  = t4,   d26 = t5
565         butterfly       d7,  d22, d30, d22               @ d7  = t7,   d22 = t6
566         butterfly       d16, d25, d17, d25               @ d16 = t8,   d25 = t9
567         butterfly       d24, d21, d29, d21               @ d24 = t11,  d21 = t10
568         butterfly       d17, d27, d19, d27               @ d17 = t12,  d27 = t13
569         butterfly       d29, d23, d31, d23               @ d29 = t15,  d23 = t14
570
571         mbutterfly0     d22, d26, d22, d26, d18, d30, q9,  q15  @ d22 = t6a, d26 = t5a
572         mbutterfly      d23, d25, d0[1], d0[2], q9,  q15        @ d23 = t9a,  d25 = t14a
573         mbutterfly      d27, d21, d0[1], d0[2], q9,  q15, neg=1 @ d27 = t13a, d21 = t10a
574
575         butterfly       d18, d7,  d4,  d7                @ d18 = t0a,  d7  = t7a
576         butterfly       d19, d22, d5,  d22               @ d19 = t1a,  d22 = t6
577         butterfly       d4,  d26, d20, d26               @ d4  = t2a,  d26 = t5
578         butterfly       d5,  d6,  d28, d6                @ d5  = t3a,  d6  = t4
579         butterfly       d20, d28, d16, d24               @ d20 = t8a,  d28 = t11a
580         butterfly       d24, d21, d23, d21               @ d24 = t9,   d21 = t10
581         butterfly       d23, d27, d25, d27               @ d23 = t14,  d27 = t13
582         butterfly       d25, d29, d29, d17               @ d25 = t15a, d29 = t12a
583
584         mbutterfly0     d27, d21, d27, d21, d16, d30, q8, q15 @ d27 = t13a, d21 = t10a
585         mbutterfly0     d29, d28, d29, d28, d16, d30, q8, q15 @ d29 = t12,  d28 = t11
586
587         vswp            d27, d29                         @ d27 = t12, d29 = t13a
588         vswp            d28, d27                         @ d28 = t12, d27 = t11
589         butterfly       d16, d31, d18, d25               @ d16 = out[0], d31 = out[15]
590         butterfly       d17, d30, d19, d23               @ d17 = out[1], d30 = out[14]
591         butterfly_r     d25, d22, d22, d24               @ d25 = out[9], d22 = out[6]
592         butterfly       d23, d24, d7,  d20               @ d23 = out[7], d24 = out[8]
593         butterfly       d18, d29, d4,  d29               @ d18 = out[2], d29 = out[13]
594         butterfly       d19, d28, d5,  d28               @ d19 = out[3], d28 = out[12]
595         vmov            d4,  d21                         @ d4  = t10a
596         butterfly       d20, d27, d6,  d27               @ d20 = out[4], d27 = out[11]
597         butterfly       d21, d26, d26, d4                @ d21 = out[5], d26 = out[10]
598 .endm
599
600 .macro iadst16
601         movrel          r12, iadst16_coeffs
602         vld1.16         {q0-q1}, [r12,:128]
603
604         mbutterfly_l    q3,  q2,  d31, d16, d0[1], d0[0] @ q3  = t1,   q2  = t0
605         mbutterfly_l    q5,  q4,  d23, d24, d2[1], d2[0] @ q5  = t9,   q4  = t8
606         butterfly_n     d31, d24, q3,  q5,  q6,  q5      @ d31 = t1a,  d24 = t9a
607         mbutterfly_l    q7,  q6,  d29, d18, d0[3], d0[2] @ q7  = t3,   q6  = t2
608         butterfly_n     d16, d23, q2,  q4,  q3,  q4      @ d16 = t0a,  d23 = t8a
609
610         mbutterfly_l    q3,  q2,  d21, d26, d2[3], d2[2] @ q3  = t11,  q2  = t10
611         butterfly_n     d29, d26, q7,  q3,  q4,  q3      @ d29 = t3a,  d26 = t11a
612         mbutterfly_l    q5,  q4,  d27, d20, d1[1], d1[0] @ q5  = t5,   q4  = t4
613         butterfly_n     d18, d21, q6,  q2,  q3,  q2      @ d18 = t2a,  d21 = t10a
614
615         mbutterfly_l    q7,  q6,  d19, d28, d3[1], d3[0] @ q7  = t13,  q6  = t12
616         butterfly_n     d20, d28, q5,  q7,  q2,  q7      @ d20 = t5a,  d28 = t13a
617         mbutterfly_l    q3,  q2,  d25, d22, d1[3], d1[2] @ q3  = t7,   q2  = t6
618         butterfly_n     d27, d19, q4,  q6,  q5,  q6      @ d27 = t4a,  d19 = t12a
619
620         mbutterfly_l    q5,  q4,  d17, d30, d3[3], d3[2] @ q5  = t15,  q4  = t14
621         movrel          r12, idct_coeffs
622         vld1.16         {q0}, [r12,:128]
623         butterfly_n     d22, d30, q3,  q5,  q6,  q5      @ d22 = t7a,  d30 = t15a
624         mbutterfly_l    q7,  q6,  d23, d24, d0[3], d1[0] @ q7  = t9,   q6  = t8
625         butterfly_n     d25, d17, q2,  q4,  q3,  q4      @ d25 = t6a,  d17 = t14a
626
627         mbutterfly_l    q2,  q3,  d28, d19, d1[0], d0[3] @ q2  = t12,  q3  = t13
628         butterfly_n     d23, d19, q6,  q2,  q4,  q2      @ d23 = t8a,  d19 = t12a
629         mbutterfly_l    q5,  q4,  d21, d26, d1[1], d1[2] @ q5  = t11,  q4  = t10
630         butterfly_r     d4,  d27, d16, d27               @ d4  = t4,   d27 = t0
631         butterfly_n     d24, d28, q7,  q3,  q6,  q3      @ d24 = t9a,  d28 = t13a
632
633         mbutterfly_l    q6,  q7,  d30, d17, d1[2], d1[1] @ q6  = t14,  q7  = t15
634         butterfly_r     d5,  d20, d31, d20               @ d5  = t5,   d20 = t1
635         butterfly_n     d21, d17, q4,  q6,  q3,  q6      @ d21 = t10a, d17 = t14a
636         butterfly_n     d26, d30, q5,  q7,  q4,  q7      @ d26 = t11a, d30 = t15a
637
638         butterfly_r     d6,  d25, d18, d25               @ d6  = t6,   d25 = t2
639         butterfly_r     d7,  d22, d29, d22               @ d7  = t7,   d22 = t3
640
641         mbutterfly_l    q5,  q4,  d19, d28, d0[1], d0[2] @ q5  = t13,  q4  = t12
642         mbutterfly_l    q6,  q7,  d30, d17, d0[2], d0[1] @ q6  = t14,  q7  = t15
643
644         butterfly_n     d18, d30, q4,  q6,  q8,  q6      @ d18 = out[2],   d30 = t14a
645         butterfly_n     d29, d17, q5,  q7,  q6,  q7      @ d29 = -out[13], d17 = t15a
646         vneg.s16        d29, d29                         @ d29 = out[13]
647
648         mbutterfly_l    q5,  q4,  d4,  d5,  d0[1], d0[2] @ q5  = t5a,  q4  = t4a
649         mbutterfly_l    q6,  q7,  d7,  d6,  d0[2], d0[1] @ q6  = t6a,  q7  = t7a
650
651         butterfly       d2,  d6,  d27, d25               @ d2 = out[0], d6 = t2a
652         butterfly       d3,  d7,  d23, d21               @ d3 =-out[1], d7 = t10
653
654         butterfly_n     d19, d31, q4,  q6,  q2,  q4      @ d19 = -out[3],  d31 = t6
655         vneg.s16        d19, d19                         @ d19 = out[3]
656         butterfly_n     d28, d16, q5,  q7,  q2,  q5      @ d28 = out[12],  d16 = t7
657
658         butterfly       d5,  d8,  d20, d22               @ d5 =-out[15],d8 = t3a
659         butterfly       d4,  d9,  d24, d26               @ d4 = out[14],d9 = t11
660
661         mbutterfly0     d23, d24, d6,  d8,  d10, d11, q6,  q7, 1 @ d23 = out[7], d24 = out[8]
662         mbutterfly0     d20, d27, d16, d31, d10, d11, q6,  q7    @ d20 = out[4], d27 = out[11]
663         mbutterfly0     d22, d25, d9,  d7,  d10, d11, q6,  q7    @ d22 = out[6], d25 = out[9]
664         mbutterfly0     d21, d26, d30, d17, d10, d11, q6,  q7, 1 @ d21 = out[5], d26 = out[10]
665
666         vneg.s16        d31, d5                          @ d31 = out[15]
667         vneg.s16        d17, d3                          @ d17 = out[1]
668
669         vmov            d16, d2
670         vmov            d30, d4
671 .endm
672
673 .macro itxfm16_1d_funcs txfm
674 @ Read a vertical 4x16 slice out of a 16x16 matrix, do a transform on it,
675 @ transpose into a horizontal 16x4 slice and store.
676 @ r0 = dst (temp buffer)
677 @ r1 = unused
678 @ r2 = src
679 @ r3 = slice offset
680 function \txfm\()16_1d_4x16_pass1_neon
681         mov             r12, #32
682         vmov.s16        q2, #0
683 .irp i, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31
684         vld1.16         {d\i}, [r2,:64]
685         vst1.16         {d4},  [r2,:64], r12
686 .endr
687
688         \txfm\()16
689
690         @ Do four 4x4 transposes. Originally, d16-d31 contain the
691         @ 16 rows. Afterwards, d16-d19, d20-d23, d24-d27, d28-d31
692         @ contain the transposed 4x4 blocks.
693         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
694
695         @ Store the transposed 4x4 blocks horizontally.
696         cmp             r3,  #12
697         beq             1f
698 .irp i, 16, 20, 24, 28, 17, 21, 25, 29, 18, 22, 26, 30, 19, 23, 27, 31
699         vst1.16         {d\i}, [r0,:64]!
700 .endr
701         bx              lr
702 1:
703         @ Special case: For the last input column (r3 == 12),
704         @ which would be stored as the last row in the temp buffer,
705         @ don't store the first 4x4 block, but keep it in registers
706         @ for the first slice of the second pass (where it is the
707         @ last 4x4 block).
708         add             r0,  r0,  #8
709 .irp i, 20, 24, 28
710         vst1.16         {d\i}, [r0,:64]!
711 .endr
712         add             r0,  r0,  #8
713 .irp i, 21, 25, 29
714         vst1.16         {d\i}, [r0,:64]!
715 .endr
716         add             r0,  r0,  #8
717 .irp i, 22, 26, 30
718         vst1.16         {d\i}, [r0,:64]!
719 .endr
720         add             r0,  r0,  #8
721 .irp i, 23, 27, 31
722         vst1.16         {d\i}, [r0,:64]!
723 .endr
724         vmov            d28, d16
725         vmov            d29, d17
726         vmov            d30, d18
727         vmov            d31, d19
728         bx              lr
729 endfunc
730
731 @ Read a vertical 4x16 slice out of a 16x16 matrix, do a transform on it,
732 @ load the destination pixels (from a similar 4x16 slice), add and store back.
733 @ r0 = dst
734 @ r1 = dst stride
735 @ r2 = src (temp buffer)
736 @ r3 = slice offset
737 function \txfm\()16_1d_4x16_pass2_neon
738         mov             r12, #32
739 .irp i, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27
740         vld1.16         {d\i}, [r2,:64], r12
741 .endr
742         cmp             r3,  #0
743         beq             1f
744 .irp i, 28, 29, 30, 31
745         vld1.16         {d\i}, [r2,:64], r12
746 .endr
747 1:
748
749         add             r3,  r0,  r1
750         lsl             r1,  r1,  #1
751         \txfm\()16
752
753 .macro load_add_store coef0, coef1, coef2, coef3
754         vrshr.s16       \coef0, \coef0, #6
755         vrshr.s16       \coef1, \coef1, #6
756
757         vld1.32         {d4[]},   [r0,:32], r1
758         vld1.32         {d4[1]},  [r3,:32], r1
759         vrshr.s16       \coef2, \coef2, #6
760         vrshr.s16       \coef3, \coef3, #6
761         vld1.32         {d5[]},   [r0,:32], r1
762         vld1.32         {d5[1]},  [r3,:32], r1
763         vaddw.u8        \coef0, \coef0, d4
764         vld1.32         {d6[]},   [r0,:32], r1
765         vld1.32         {d6[1]},  [r3,:32], r1
766         vaddw.u8        \coef1, \coef1, d5
767         vld1.32         {d7[]},   [r0,:32], r1
768         vld1.32         {d7[1]},  [r3,:32], r1
769
770         vqmovun.s16     d4,  \coef0
771         vqmovun.s16     d5,  \coef1
772         sub             r0,  r0,  r1, lsl #2
773         sub             r3,  r3,  r1, lsl #2
774         vaddw.u8        \coef2, \coef2, d6
775         vaddw.u8        \coef3, \coef3, d7
776         vst1.32         {d4[0]},  [r0,:32], r1
777         vst1.32         {d4[1]},  [r3,:32], r1
778         vqmovun.s16     d6,  \coef2
779         vst1.32         {d5[0]},  [r0,:32], r1
780         vst1.32         {d5[1]},  [r3,:32], r1
781         vqmovun.s16     d7,  \coef3
782
783         vst1.32         {d6[0]},  [r0,:32], r1
784         vst1.32         {d6[1]},  [r3,:32], r1
785         vst1.32         {d7[0]},  [r0,:32], r1
786         vst1.32         {d7[1]},  [r3,:32], r1
787 .endm
788         load_add_store  q8,  q9,  q10, q11
789         load_add_store  q12, q13, q14, q15
790 .purgem load_add_store
791
792         bx              lr
793 endfunc
794 .endm
795
796 itxfm16_1d_funcs idct
797 itxfm16_1d_funcs iadst
798
799 .macro itxfm_func16x16 txfm1, txfm2
800 function ff_vp9_\txfm1\()_\txfm2\()_16x16_add_neon, export=1
801 .ifc \txfm1,idct
802 .ifc \txfm2,idct
803         cmp             r3,  #1
804         beq             idct16x16_dc_add_neon
805 .endif
806 .endif
807         push            {r4-r7,lr}
808 .ifc \txfm1,iadst
809         vpush           {q4-q7}
810 .else
811 .ifc \txfm2,iadst
812         vpush           {q4-q7}
813 .endif
814 .endif
815         mov             r7,  sp
816
817         @ Align the stack, allocate a temp buffer
818 T       mov             r12, sp
819 T       bic             r12, r12, #15
820 T       sub             r12, r12, #512
821 T       mov             sp,  r12
822 A       bic             sp,  sp,  #15
823 A       sub             sp,  sp,  #512
824
825         mov             r4,  r0
826         mov             r5,  r1
827         mov             r6,  r2
828
829 .ifc \txfm1,idct
830         movrel          r12, idct_coeffs
831         vld1.16         {q0-q1}, [r12,:128]
832 .endif
833
834 .irp i, 0, 4, 8, 12
835         add             r0,  sp,  #(\i*32)
836         add             r2,  r6,  #(\i*2)
837         mov             r3,  #\i
838         bl              \txfm1\()16_1d_4x16_pass1_neon
839 .endr
840 .ifc \txfm2,idct
841         movrel          r12, idct_coeffs
842         vld1.16         {q0-q1}, [r12,:128]
843 .endif
844 .irp i, 0, 4, 8, 12
845         add             r0,  r4,  #(\i)
846         mov             r1,  r5
847         add             r2,  sp,  #(\i*2)
848         mov             r3,  #\i
849         bl              \txfm2\()16_1d_4x16_pass2_neon
850 .endr
851
852         mov             sp,  r7
853 .ifc \txfm1,iadst
854         vpop            {q4-q7}
855 .else
856 .ifc \txfm2,iadst
857         vpop            {q4-q7}
858 .endif
859 .endif
860         pop             {r4-r7,pc}
861 endfunc
862 .endm
863
864 itxfm_func16x16 idct,  idct
865 itxfm_func16x16 iadst, idct
866 itxfm_func16x16 idct,  iadst
867 itxfm_func16x16 iadst, iadst
868 .ltorg
869
870
871 function idct32x32_dc_add_neon
872         movrel          r12, idct_coeffs
873         vld1.16         {d0}, [r12,:64]
874
875         vmov.i16        q2, #0
876
877         vld1.16         {d16[]}, [r2,:16]
878         vmull.s16       q8,  d16, d0[0]
879         vrshrn.s32      d16, q8,  #14
880         vmull.s16       q8,  d16, d0[0]
881         vrshrn.s32      d16, q8,  #14
882         vdup.16         q8,  d16[0]
883         vst1.16         {d4[0]}, [r2,:16]
884
885         vrshr.s16       q8,  q8,  #6
886
887         mov             r12, #32
888 1:
889         @ Loop to add the constant from q8 into all 32x32 outputs
890         vld1.8          {q2-q3},  [r0,:128]
891         vaddw.u8        q10, q8,  d4
892         vaddw.u8        q11, q8,  d5
893         vaddw.u8        q12, q8,  d6
894         vaddw.u8        q13, q8,  d7
895         vqmovun.s16     d4,  q10
896         vqmovun.s16     d5,  q11
897         vqmovun.s16     d6,  q12
898         vqmovun.s16     d7,  q13
899         vst1.8          {q2-q3},  [r0,:128], r1
900         subs            r12, r12, #1
901         bne             1b
902
903         bx              lr
904 endfunc
905
906 .macro idct32_odd
907         movrel          r12, idct_coeffs
908         add             r12, r12, #32
909         vld1.16         {q0-q1}, [r12,:128]
910
911         mbutterfly      d16, d31, d0[0], d0[1], q2, q3 @ d16 = t16a, d31 = t31a
912         mbutterfly      d24, d23, d0[2], d0[3], q2, q3 @ d24 = t17a, d23 = t30a
913         mbutterfly      d20, d27, d1[0], d1[1], q2, q3 @ d20 = t18a, d27 = t29a
914         mbutterfly      d28, d19, d1[2], d1[3], q2, q3 @ d28 = t19a, d19 = t28a
915         mbutterfly      d18, d29, d2[0], d2[1], q2, q3 @ d18 = t20a, d29 = t27a
916         mbutterfly      d26, d21, d2[2], d2[3], q2, q3 @ d26 = t21a, d21 = t26a
917         mbutterfly      d22, d25, d3[0], d3[1], q2, q3 @ d22 = t22a, d25 = t25a
918         mbutterfly      d30, d17, d3[2], d3[3], q2, q3 @ d30 = t23a, d17 = t24a
919
920         sub             r12, r12, #32
921         vld1.16         {q0}, [r12,:128]
922
923         butterfly       d4,  d24, d16, d24 @ d4  = t16, d24 = t17
924         butterfly       d5,  d20, d28, d20 @ d5  = t19, d20 = t18
925         butterfly       d6,  d26, d18, d26 @ d6  = t20, d26 = t21
926         butterfly       d7,  d22, d30, d22 @ d7  = t23, d22 = t22
927         butterfly       d28, d25, d17, d25 @ d28 = t24, d25 = t25
928         butterfly       d30, d21, d29, d21 @ d30 = t27, d21 = t26
929         butterfly       d29, d23, d31, d23 @ d29 = t31, d23 = t30
930         butterfly       d31, d27, d19, d27 @ d31 = t28, d27 = t29
931
932         mbutterfly      d23, d24, d0[3], d1[0], q8, q9        @ d23 = t17a, d24 = t30a
933         mbutterfly      d27, d20, d0[3], d1[0], q8, q9, neg=1 @ d27 = t29a, d20 = t18a
934         mbutterfly      d21, d26, d1[1], d1[2], q8, q9        @ d21 = t21a, d26 = t26a
935         mbutterfly      d25, d22, d1[1], d1[2], q8, q9, neg=1 @ d25 = t25a, d22 = t22a
936
937         butterfly       d16, d5,  d4,  d5  @ d16 = t16a, d5  = t19a
938         butterfly       d17, d20, d23, d20 @ d17 = t17,  d20 = t18
939         butterfly       d18, d6,  d7,  d6  @ d18 = t23a, d6  = t20a
940         butterfly       d19, d21, d22, d21 @ d19 = t22,  d21 = t21
941         butterfly       d4,  d28, d28, d30 @ d4  = t24a, d28 = t27a
942         butterfly       d23, d26, d25, d26 @ d23 = t25,  d26 = t26
943         butterfly       d7,  d29, d29, d31 @ d7  = t31a, d29 = t28a
944         butterfly       d22, d27, d24, d27 @ d22 = t30,  d27 = t29
945
946         mbutterfly      d27, d20, d0[1], d0[2], q12, q15        @ d27 = t18a, d20 = t29a
947         mbutterfly      d29, d5,  d0[1], d0[2], q12, q15        @ d29 = t19,  d5  = t28
948         mbutterfly      d28, d6,  d0[1], d0[2], q12, q15, neg=1 @ d28 = t27,  d6  = t20
949         mbutterfly      d26, d21, d0[1], d0[2], q12, q15, neg=1 @ d26 = t26a, d21 = t21a
950
951         butterfly       d31, d24, d7,  d4  @ d31 = t31,  d24 = t24
952         butterfly       d30, d25, d22, d23 @ d30 = t30a, d25 = t25a
953         butterfly_r     d23, d16, d16, d18 @ d23 = t23,  d16 = t16
954         butterfly_r     d22, d17, d17, d19 @ d22 = t22a, d17 = t17a
955         butterfly       d18, d21, d27, d21 @ d18 = t18,  d21 = t21
956         butterfly_r     d27, d28, d5,  d28 @ d27 = t27a, d28 = t28a
957         butterfly       d4,  d26, d20, d26 @ d4  = t29,  d26 = t26
958         butterfly       d19, d20, d29, d6  @ d19 = t19a, d20 = t20
959         vmov            d29, d4            @ d29 = t29
960
961         mbutterfly0     d27, d20, d27, d20, d4, d6, q2, q3 @ d27 = t27,  d20 = t20
962         mbutterfly0     d26, d21, d26, d21, d4, d6, q2, q3 @ d26 = t26a, d21 = t21a
963         mbutterfly0     d25, d22, d25, d22, d4, d6, q2, q3 @ d25 = t25,  d22 = t22
964         mbutterfly0     d24, d23, d24, d23, d4, d6, q2, q3 @ d24 = t24a, d23 = t23a
965 .endm
966
967 @ Do an 32-point IDCT of a 4x32 slice out of a 32x32 matrix.
968 @ We don't have register space to do a single pass IDCT of 4x32 though,
969 @ but the 32-point IDCT can be decomposed into two 16-point IDCTs;
970 @ a normal IDCT16 with every other input component (the even ones, with
971 @ each output written twice), followed by a separate 16-point IDCT
972 @ of the odd inputs, added/subtracted onto the outputs of the first idct16.
973 @ r0 = dst (temp buffer)
974 @ r1 = unused
975 @ r2 = src
976 function idct32_1d_4x32_pass1_neon
977         movrel          r12, idct_coeffs
978         vld1.16         {q0-q1}, [r12,:128]
979
980         @ Double stride of the input, since we only read every other line
981         mov             r12, #128
982         vmov.s16        d4, #0
983
984         @ d16 = IN(0), d17 = IN(2) ... d31 = IN(30)
985 .irp i, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31
986         vld1.16         {d\i}, [r2,:64]
987         vst1.16         {d4},  [r2,:64], r12
988 .endr
989
990         idct16
991
992         @ Do four 4x4 transposes. Originally, d16-d31 contain the
993         @ 16 rows. Afterwards, d16-d19, d20-d23, d24-d27, d28-d31
994         @ contain the transposed 4x4 blocks.
995         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
996         @ Store the registers a, b, c, d horizontally, followed
997         @ by the same registers d, c, b, a mirrored.
998 .macro store_rev a, b, c, d
999 .irp i, \a, \b, \c, \d
1000         vst1.16         {d\i}, [r0,:64]!
1001         vrev64.16       d\i, d\i
1002 .endr
1003 .irp i, \d, \c, \b, \a
1004         vst1.16         {d\i}, [r0,:64]!
1005 .endr
1006 .endm
1007         store_rev       16, 20, 24, 28
1008         store_rev       17, 21, 25, 29
1009         store_rev       18, 22, 26, 30
1010         store_rev       19, 23, 27, 31
1011         sub             r0,  r0,  #256
1012 .purgem store_rev
1013
1014         @ Move r2 back to the start of the input, and move
1015         @ to the first odd row
1016         sub             r2,  r2,  r12, lsl #4
1017         add             r2,  r2,  #64
1018
1019         vmov.s16        d4, #0
1020         @ d16 = IN(1), d17 = IN(3) ... d31 = IN(31)
1021 .irp i, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31
1022         vld1.16         {d\i}, [r2,:64]
1023         vst1.16         {d4},  [r2,:64], r12
1024 .endr
1025
1026         idct32_odd
1027
1028         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
1029
1030         @ Store the registers a, b, c, d horizontally,
1031         @ adding into the output first, and then mirrored, subtracted
1032         @ from the output.
1033 .macro store_rev a, b, c, d
1034 .irp i, \a, \b, \c, \d
1035         vld1.16         {d4},  [r0,:64]
1036         vadd.s16        d4, d4, d\i
1037         vst1.16         {d4},  [r0,:64]!
1038         vrev64.16       d\i, d\i
1039 .endr
1040 .irp i, \d, \c, \b, \a
1041         vld1.16         {d4},  [r0,:64]
1042         vsub.s16        d4, d4, d\i
1043         vst1.16         {d4},  [r0,:64]!
1044 .endr
1045 .endm
1046
1047         store_rev 31, 27, 23, 19
1048         store_rev 30, 26, 22, 18
1049         store_rev 29, 25, 21, 17
1050         store_rev 28, 24, 20, 16
1051 .purgem store_rev
1052         bx              lr
1053 endfunc
1054 .ltorg
1055
1056 @ This is mostly the same as 4x32_pass1, but without the transpose,
1057 @ and use the source as temp buffer between the two idct passes, and
1058 @ add into the destination.
1059 @ r0 = dst
1060 @ r1 = dst stride
1061 @ r2 = src (temp buffer)
1062 function idct32_1d_4x32_pass2_neon
1063         movrel          r12, idct_coeffs
1064         vld1.16         {q0-q1}, [r12,:128]
1065
1066         mov             r12, #128
1067         @ d16 = IN(0), d17 = IN(2) ... d31 = IN(30)
1068 .irp i, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31
1069         vld1.16         {d\i}, [r2,:64], r12
1070 .endr
1071         sub             r2,  r2,  r12, lsl #4
1072
1073         idct16
1074
1075 .irp i, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31
1076         vst1.16         {d\i}, [r2,:64], r12
1077 .endr
1078
1079         sub             r2,  r2,  r12, lsl #4
1080         add             r2,  r2,  #64
1081
1082         @ d16 = IN(1), d17 = IN(3) ... d31 = IN(31)
1083 .irp i, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31
1084         vld1.16         {d\i}, [r2,:64], r12
1085 .endr
1086         sub             r2,  r2,  r12, lsl #4
1087         sub             r2,  r2,  #64
1088
1089         idct32_odd
1090
1091         mov             r12, #128
1092 .macro load_acc_store a, b, c, d, neg=0
1093         vld1.16         {d4},  [r2,:64], r12
1094         vld1.16         {d5},  [r2,:64], r12
1095 .if \neg == 0
1096         vadd.s16        d4, d4, d\a
1097         vld1.16         {d6},  [r2,:64], r12
1098         vadd.s16        d5, d5, d\b
1099         vld1.16         {d7},  [r2,:64], r12
1100         vadd.s16        d6, d6, d\c
1101         vadd.s16        d7, d7, d\d
1102 .else
1103         vsub.s16        d4, d4, d\a
1104         vld1.16         {d6},  [r2,:64], r12
1105         vsub.s16        d5, d5, d\b
1106         vld1.16         {d7},  [r2,:64], r12
1107         vsub.s16        d6, d6, d\c
1108         vsub.s16        d7, d7, d\d
1109 .endif
1110         vld1.32         {d2[]},   [r0,:32], r1
1111         vld1.32         {d2[1]},  [r0,:32], r1
1112         vrshr.s16       q2, q2, #6
1113         vld1.32         {d3[]},   [r0,:32], r1
1114         vrshr.s16       q3, q3, #6
1115         vld1.32         {d3[1]},  [r0,:32], r1
1116         sub             r0,  r0,  r1, lsl #2
1117         vaddw.u8        q2,  q2,  d2
1118         vaddw.u8        q3,  q3,  d3
1119         vqmovun.s16     d4,  q2
1120         vqmovun.s16     d5,  q3
1121         vst1.32         {d4[0]},  [r0,:32], r1
1122         vst1.32         {d4[1]},  [r0,:32], r1
1123         vst1.32         {d5[0]},  [r0,:32], r1
1124         vst1.32         {d5[1]},  [r0,:32], r1
1125 .endm
1126         load_acc_store  31, 30, 29, 28
1127         load_acc_store  27, 26, 25, 24
1128         load_acc_store  23, 22, 21, 20
1129         load_acc_store  19, 18, 17, 16
1130         sub             r2,  r2,  r12
1131         neg             r12, r12
1132         load_acc_store  16, 17, 18, 19, 1
1133         load_acc_store  20, 21, 22, 23, 1
1134         load_acc_store  24, 25, 26, 27, 1
1135         load_acc_store  28, 29, 30, 31, 1
1136 .purgem load_acc_store
1137         bx              lr
1138 endfunc
1139
1140 function ff_vp9_idct_idct_32x32_add_neon, export=1
1141         cmp             r3,  #1
1142         beq             idct32x32_dc_add_neon
1143         push            {r4-r7,lr}
1144         vpush           {q4-q7}
1145         mov             r7,  sp
1146
1147         @ Align the stack, allocate a temp buffer
1148 T       mov             r12, sp
1149 T       bic             r12, r12, #15
1150 T       sub             r12, r12, #2048
1151 T       mov             sp,  r12
1152 A       bic             sp,  sp,  #15
1153 A       sub             sp,  sp,  #2048
1154
1155         mov             r4,  r0
1156         mov             r5,  r1
1157         mov             r6,  r2
1158
1159 .irp i, 0, 4, 8, 12, 16, 20, 24, 28
1160         add             r0,  sp,  #(\i*64)
1161         add             r2,  r6,  #(\i*2)
1162         bl              idct32_1d_4x32_pass1_neon
1163 .endr
1164 .irp i, 0, 4, 8, 12, 16, 20, 24, 28
1165         add             r0,  r4,  #(\i)
1166         mov             r1,  r5
1167         add             r2,  sp,  #(\i*2)
1168         bl              idct32_1d_4x32_pass2_neon
1169 .endr
1170
1171         mov             sp,  r7
1172         vpop            {q4-q7}
1173         pop             {r4-r7,pc}
1174 endfunc