]> git.sesse.net Git - ffmpeg/blob - libavcodec/arm/vp9itxfm_neon.S
Merge commit '99cf943339a2e5171863c48cd1a73dd43dc243e1'
[ffmpeg] / libavcodec / arm / vp9itxfm_neon.S
1 /*
2  * Copyright (c) 2016 Google Inc.
3  *
4  * This file is part of FFmpeg.
5  *
6  * FFmpeg 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  * FFmpeg 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 FFmpeg; 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\()_\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 .macro 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 .endm
584
585 .macro iadst16
586         movrel          r12, iadst16_coeffs
587         vld1.16         {q0-q1}, [r12,:128]
588
589         mbutterfly_l    q3,  q2,  d31, d16, d0[1], d0[0] @ q3  = t1,   q2  = t0
590         mbutterfly_l    q5,  q4,  d23, d24, d2[1], d2[0] @ q5  = t9,   q4  = t8
591         butterfly_n     d31, d24, q3,  q5,  q6,  q5      @ d31 = t1a,  d24 = t9a
592         mbutterfly_l    q7,  q6,  d29, d18, d0[3], d0[2] @ q7  = t3,   q6  = t2
593         butterfly_n     d16, d23, q2,  q4,  q3,  q4      @ d16 = t0a,  d23 = t8a
594
595         mbutterfly_l    q3,  q2,  d21, d26, d2[3], d2[2] @ q3  = t11,  q2  = t10
596         butterfly_n     d29, d26, q7,  q3,  q4,  q3      @ d29 = t3a,  d26 = t11a
597         mbutterfly_l    q5,  q4,  d27, d20, d1[1], d1[0] @ q5  = t5,   q4  = t4
598         butterfly_n     d18, d21, q6,  q2,  q3,  q2      @ d18 = t2a,  d21 = t10a
599
600         mbutterfly_l    q7,  q6,  d19, d28, d3[1], d3[0] @ q7  = t13,  q6  = t12
601         butterfly_n     d20, d28, q5,  q7,  q2,  q7      @ d20 = t5a,  d28 = t13a
602         mbutterfly_l    q3,  q2,  d25, d22, d1[3], d1[2] @ q3  = t7,   q2  = t6
603         butterfly_n     d27, d19, q4,  q6,  q5,  q6      @ d27 = t4a,  d19 = t12a
604
605         mbutterfly_l    q5,  q4,  d17, d30, d3[3], d3[2] @ q5  = t15,  q4  = t14
606         movrel          r12, idct_coeffs
607         vld1.16         {q0}, [r12,:128]
608         butterfly_n     d22, d30, q3,  q5,  q6,  q5      @ d22 = t7a,  d30 = t15a
609         mbutterfly_l    q7,  q6,  d23, d24, d0[3], d1[0] @ q7  = t9,   q6  = t8
610         butterfly_n     d25, d17, q2,  q4,  q3,  q4      @ d25 = t6a,  d17 = t14a
611
612         mbutterfly_l    q2,  q3,  d28, d19, d1[0], d0[3] @ q2  = t12,  q3  = t13
613         butterfly_n     d23, d19, q6,  q2,  q4,  q2      @ d23 = t8a,  d19 = t12a
614         mbutterfly_l    q5,  q4,  d21, d26, d1[1], d1[2] @ q5  = t11,  q4  = t10
615         butterfly_r     d4,  d27, d16, d27               @ d4  = t4,   d27 = t0
616         butterfly_n     d24, d28, q7,  q3,  q6,  q3      @ d24 = t9a,  d28 = t13a
617
618         mbutterfly_l    q6,  q7,  d30, d17, d1[2], d1[1] @ q6  = t14,  q7  = t15
619         butterfly_r     d5,  d20, d31, d20               @ d5  = t5,   d20 = t1
620         butterfly_n     d21, d17, q4,  q6,  q3,  q6      @ d21 = t10a, d17 = t14a
621         butterfly_n     d26, d30, q5,  q7,  q4,  q7      @ d26 = t11a, d30 = t15a
622
623         butterfly_r     d6,  d25, d18, d25               @ d6  = t6,   d25 = t2
624         butterfly_r     d7,  d22, d29, d22               @ d7  = t7,   d22 = t3
625
626         mbutterfly_l    q5,  q4,  d19, d28, d0[1], d0[2] @ q5  = t13,  q4  = t12
627         mbutterfly_l    q6,  q7,  d30, d17, d0[2], d0[1] @ q6  = t14,  q7  = t15
628
629         butterfly_n     d18, d30, q4,  q6,  q8,  q6      @ d18 = out[2],   d30 = t14a
630         butterfly_n     d29, d17, q5,  q7,  q6,  q7      @ d29 = -out[13], d17 = t15a
631         vneg.s16        d29, d29                         @ d29 = out[13]
632
633         mbutterfly_l    q5,  q4,  d4,  d5,  d0[1], d0[2] @ q5  = t5a,  q4  = t4a
634         mbutterfly_l    q6,  q7,  d7,  d6,  d0[2], d0[1] @ q6  = t6a,  q7  = t7a
635
636         butterfly       d2,  d6,  d27, d25               @ d2 = out[0], d6 = t2a
637         butterfly       d3,  d7,  d23, d21               @ d3 =-out[1], d7 = t10
638
639         butterfly_n     d19, d31, q4,  q6,  q2,  q4      @ d19 = -out[3],  d31 = t6
640         vneg.s16        d19, d19                         @ d19 = out[3]
641         butterfly_n     d28, d16, q5,  q7,  q2,  q5      @ d28 = out[12],  d16 = t7
642
643         butterfly       d5,  d8,  d20, d22               @ d5 =-out[15],d8 = t3a
644         butterfly       d4,  d9,  d24, d26               @ d4 = out[14],d9 = t11
645
646         mbutterfly0     d23, d24, d6,  d8,  d10, d11, q6,  q7, 1 @ d23 = out[7], d24 = out[8]
647         mbutterfly0     d20, d27, d16, d31, d10, d11, q6,  q7    @ d20 = out[4], d27 = out[11]
648         mbutterfly0     d22, d25, d9,  d7,  d10, d11, q6,  q7    @ d22 = out[6], d25 = out[9]
649         mbutterfly0     d21, d26, d30, d17, d10, d11, q6,  q7, 1 @ d21 = out[5], d26 = out[10]
650
651         vneg.s16        d31, d5                          @ d31 = out[15]
652         vneg.s16        d17, d3                          @ d17 = out[1]
653
654         vmov            d16, d2
655         vmov            d30, d4
656 .endm
657
658 .macro itxfm16_1d_funcs txfm
659 @ Read a vertical 4x16 slice out of a 16x16 matrix, do a transform on it,
660 @ transpose into a horizontal 16x4 slice and store.
661 @ r0 = dst (temp buffer)
662 @ r1 = unused
663 @ r2 = src
664 @ r3 = slice offset
665 function \txfm\()16_1d_4x16_pass1_neon
666         mov             r12, #32
667         vmov.s16        q2, #0
668 .irp i, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31
669         vld1.16         {d\i}, [r2,:64]
670         vst1.16         {d4},  [r2,:64], r12
671 .endr
672
673         \txfm\()16
674
675         @ Do four 4x4 transposes. Originally, d16-d31 contain the
676         @ 16 rows. Afterwards, d16-d19, d20-d23, d24-d27, d28-d31
677         @ contain the transposed 4x4 blocks.
678         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
679
680         @ Store the transposed 4x4 blocks horizontally.
681         cmp             r3,  #12
682         beq             1f
683 .irp i, 16, 20, 24, 28, 17, 21, 25, 29, 18, 22, 26, 30, 19, 23, 27, 31
684         vst1.16         {d\i}, [r0,:64]!
685 .endr
686         bx              lr
687 1:
688         @ Special case: For the last input column (r3 == 12),
689         @ which would be stored as the last row in the temp buffer,
690         @ don't store the first 4x4 block, but keep it in registers
691         @ for the first slice of the second pass (where it is the
692         @ last 4x4 block).
693         add             r0,  r0,  #8
694 .irp i, 20, 24, 28
695         vst1.16         {d\i}, [r0,:64]!
696 .endr
697         add             r0,  r0,  #8
698 .irp i, 21, 25, 29
699         vst1.16         {d\i}, [r0,:64]!
700 .endr
701         add             r0,  r0,  #8
702 .irp i, 22, 26, 30
703         vst1.16         {d\i}, [r0,:64]!
704 .endr
705         add             r0,  r0,  #8
706 .irp i, 23, 27, 31
707         vst1.16         {d\i}, [r0,:64]!
708 .endr
709         vmov            d28, d16
710         vmov            d29, d17
711         vmov            d30, d18
712         vmov            d31, d19
713         bx              lr
714 endfunc
715
716 @ Read a vertical 4x16 slice out of a 16x16 matrix, do a transform on it,
717 @ load the destination pixels (from a similar 4x16 slice), add and store back.
718 @ r0 = dst
719 @ r1 = dst stride
720 @ r2 = src (temp buffer)
721 @ r3 = slice offset
722 function \txfm\()16_1d_4x16_pass2_neon
723         mov             r12, #32
724 .irp i, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27
725         vld1.16         {d\i}, [r2,:64], r12
726 .endr
727         cmp             r3,  #0
728         beq             1f
729 .irp i, 28, 29, 30, 31
730         vld1.16         {d\i}, [r2,:64], r12
731 .endr
732 1:
733
734         add             r3,  r0,  r1
735         lsl             r1,  r1,  #1
736         \txfm\()16
737
738 .macro load_add_store coef0, coef1, coef2, coef3
739         vrshr.s16       \coef0, \coef0, #6
740         vrshr.s16       \coef1, \coef1, #6
741
742         vld1.32         {d4[]},   [r0,:32], r1
743         vld1.32         {d4[1]},  [r3,:32], r1
744         vrshr.s16       \coef2, \coef2, #6
745         vrshr.s16       \coef3, \coef3, #6
746         vld1.32         {d5[]},   [r0,:32], r1
747         vld1.32         {d5[1]},  [r3,:32], r1
748         vaddw.u8        \coef0, \coef0, d4
749         vld1.32         {d6[]},   [r0,:32], r1
750         vld1.32         {d6[1]},  [r3,:32], r1
751         vaddw.u8        \coef1, \coef1, d5
752         vld1.32         {d7[]},   [r0,:32], r1
753         vld1.32         {d7[1]},  [r3,:32], r1
754
755         vqmovun.s16     d4,  \coef0
756         vqmovun.s16     d5,  \coef1
757         sub             r0,  r0,  r1, lsl #2
758         sub             r3,  r3,  r1, lsl #2
759         vaddw.u8        \coef2, \coef2, d6
760         vaddw.u8        \coef3, \coef3, d7
761         vst1.32         {d4[0]},  [r0,:32], r1
762         vst1.32         {d4[1]},  [r3,:32], r1
763         vqmovun.s16     d6,  \coef2
764         vst1.32         {d5[0]},  [r0,:32], r1
765         vst1.32         {d5[1]},  [r3,:32], r1
766         vqmovun.s16     d7,  \coef3
767
768         vst1.32         {d6[0]},  [r0,:32], r1
769         vst1.32         {d6[1]},  [r3,:32], r1
770         vst1.32         {d7[0]},  [r0,:32], r1
771         vst1.32         {d7[1]},  [r3,:32], r1
772 .endm
773         load_add_store  q8,  q9,  q10, q11
774         load_add_store  q12, q13, q14, q15
775 .purgem load_add_store
776
777         bx              lr
778 endfunc
779 .endm
780
781 itxfm16_1d_funcs idct
782 itxfm16_1d_funcs iadst
783
784 .macro itxfm_func16x16 txfm1, txfm2
785 function ff_vp9_\txfm1\()_\txfm2\()_16x16_add_neon, export=1
786 .ifc \txfm1\()_\txfm2,idct_idct
787         cmp             r3,  #1
788         beq             idct16x16_dc_add_neon
789 .endif
790         push            {r4-r7,lr}
791 .ifnc \txfm1\()_\txfm2,idct_idct
792         vpush           {q4-q7}
793 .endif
794         mov             r7,  sp
795
796         @ Align the stack, allocate a temp buffer
797 T       mov             r12, sp
798 T       bic             r12, r12, #15
799 T       sub             r12, r12, #512
800 T       mov             sp,  r12
801 A       bic             sp,  sp,  #15
802 A       sub             sp,  sp,  #512
803
804         mov             r4,  r0
805         mov             r5,  r1
806         mov             r6,  r2
807
808 .ifc \txfm1,idct
809         movrel          r12, idct_coeffs
810         vld1.16         {q0-q1}, [r12,:128]
811 .endif
812
813 .irp i, 0, 4, 8, 12
814         add             r0,  sp,  #(\i*32)
815         add             r2,  r6,  #(\i*2)
816         mov             r3,  #\i
817         bl              \txfm1\()16_1d_4x16_pass1_neon
818 .endr
819 .ifc \txfm2,idct
820         movrel          r12, idct_coeffs
821         vld1.16         {q0-q1}, [r12,:128]
822 .endif
823 .irp i, 0, 4, 8, 12
824         add             r0,  r4,  #(\i)
825         mov             r1,  r5
826         add             r2,  sp,  #(\i*2)
827         mov             r3,  #\i
828         bl              \txfm2\()16_1d_4x16_pass2_neon
829 .endr
830
831         mov             sp,  r7
832 .ifnc \txfm1\()_\txfm2,idct_idct
833         vpop            {q4-q7}
834 .endif
835         pop             {r4-r7,pc}
836 endfunc
837 .endm
838
839 itxfm_func16x16 idct,  idct
840 itxfm_func16x16 iadst, idct
841 itxfm_func16x16 idct,  iadst
842 itxfm_func16x16 iadst, iadst
843 .ltorg
844
845
846 function idct32x32_dc_add_neon
847         movrel          r12, idct_coeffs
848         vld1.16         {d0}, [r12,:64]
849
850         vmov.i16        q2, #0
851
852         vld1.16         {d16[]}, [r2,:16]
853         vmull.s16       q8,  d16, d0[0]
854         vrshrn.s32      d16, q8,  #14
855         vmull.s16       q8,  d16, d0[0]
856         vrshrn.s32      d16, q8,  #14
857         vdup.16         q8,  d16[0]
858         vst1.16         {d4[0]}, [r2,:16]
859
860         vrshr.s16       q8,  q8,  #6
861
862         mov             r12, #32
863 1:
864         @ Loop to add the constant from q8 into all 32x32 outputs
865         vld1.8          {q2-q3},  [r0,:128]
866         vaddw.u8        q10, q8,  d4
867         vaddw.u8        q11, q8,  d5
868         vaddw.u8        q12, q8,  d6
869         vaddw.u8        q13, q8,  d7
870         vqmovun.s16     d4,  q10
871         vqmovun.s16     d5,  q11
872         vqmovun.s16     d6,  q12
873         vqmovun.s16     d7,  q13
874         vst1.8          {q2-q3},  [r0,:128], r1
875         subs            r12, r12, #1
876         bne             1b
877
878         bx              lr
879 endfunc
880
881 .macro idct32_odd
882         movrel          r12, idct_coeffs
883         add             r12, r12, #32
884         vld1.16         {q0-q1}, [r12,:128]
885
886         mbutterfly      d16, d31, d0[0], d0[1], q2, q3 @ d16 = t16a, d31 = t31a
887         mbutterfly      d24, d23, d0[2], d0[3], q2, q3 @ d24 = t17a, d23 = t30a
888         mbutterfly      d20, d27, d1[0], d1[1], q2, q3 @ d20 = t18a, d27 = t29a
889         mbutterfly      d28, d19, d1[2], d1[3], q2, q3 @ d28 = t19a, d19 = t28a
890         mbutterfly      d18, d29, d2[0], d2[1], q2, q3 @ d18 = t20a, d29 = t27a
891         mbutterfly      d26, d21, d2[2], d2[3], q2, q3 @ d26 = t21a, d21 = t26a
892         mbutterfly      d22, d25, d3[0], d3[1], q2, q3 @ d22 = t22a, d25 = t25a
893         mbutterfly      d30, d17, d3[2], d3[3], q2, q3 @ d30 = t23a, d17 = t24a
894
895         sub             r12, r12, #32
896         vld1.16         {q0}, [r12,:128]
897
898         butterfly       d4,  d24, d16, d24 @ d4  = t16, d24 = t17
899         butterfly       d5,  d20, d28, d20 @ d5  = t19, d20 = t18
900         butterfly       d6,  d26, d18, d26 @ d6  = t20, d26 = t21
901         butterfly       d7,  d22, d30, d22 @ d7  = t23, d22 = t22
902         butterfly       d28, d25, d17, d25 @ d28 = t24, d25 = t25
903         butterfly       d30, d21, d29, d21 @ d30 = t27, d21 = t26
904         butterfly       d29, d23, d31, d23 @ d29 = t31, d23 = t30
905         butterfly       d31, d27, d19, d27 @ d31 = t28, d27 = t29
906
907         mbutterfly      d23, d24, d0[3], d1[0], q8, q9        @ d23 = t17a, d24 = t30a
908         mbutterfly      d27, d20, d0[3], d1[0], q8, q9, neg=1 @ d27 = t29a, d20 = t18a
909         mbutterfly      d21, d26, d1[1], d1[2], q8, q9        @ d21 = t21a, d26 = t26a
910         mbutterfly      d25, d22, d1[1], d1[2], q8, q9, neg=1 @ d25 = t25a, d22 = t22a
911
912         butterfly       d16, d5,  d4,  d5  @ d16 = t16a, d5  = t19a
913         butterfly       d17, d20, d23, d20 @ d17 = t17,  d20 = t18
914         butterfly       d18, d6,  d7,  d6  @ d18 = t23a, d6  = t20a
915         butterfly       d19, d21, d22, d21 @ d19 = t22,  d21 = t21
916         butterfly       d4,  d28, d28, d30 @ d4  = t24a, d28 = t27a
917         butterfly       d23, d26, d25, d26 @ d23 = t25,  d26 = t26
918         butterfly       d7,  d29, d29, d31 @ d7  = t31a, d29 = t28a
919         butterfly       d22, d27, d24, d27 @ d22 = t30,  d27 = t29
920
921         mbutterfly      d27, d20, d0[1], d0[2], q12, q15        @ d27 = t18a, d20 = t29a
922         mbutterfly      d29, d5,  d0[1], d0[2], q12, q15        @ d29 = t19,  d5  = t28
923         mbutterfly      d28, d6,  d0[1], d0[2], q12, q15, neg=1 @ d28 = t27,  d6  = t20
924         mbutterfly      d26, d21, d0[1], d0[2], q12, q15, neg=1 @ d26 = t26a, d21 = t21a
925
926         butterfly       d31, d24, d7,  d4  @ d31 = t31,  d24 = t24
927         butterfly       d30, d25, d22, d23 @ d30 = t30a, d25 = t25a
928         butterfly_r     d23, d16, d16, d18 @ d23 = t23,  d16 = t16
929         butterfly_r     d22, d17, d17, d19 @ d22 = t22a, d17 = t17a
930         butterfly       d18, d21, d27, d21 @ d18 = t18,  d21 = t21
931         butterfly_r     d27, d28, d5,  d28 @ d27 = t27a, d28 = t28a
932         butterfly       d4,  d26, d20, d26 @ d4  = t29,  d26 = t26
933         butterfly       d19, d20, d29, d6  @ d19 = t19a, d20 = t20
934         vmov            d29, d4            @ d29 = t29
935
936         mbutterfly0     d27, d20, d27, d20, d4, d6, q2, q3 @ d27 = t27,  d20 = t20
937         mbutterfly0     d26, d21, d26, d21, d4, d6, q2, q3 @ d26 = t26a, d21 = t21a
938         mbutterfly0     d25, d22, d25, d22, d4, d6, q2, q3 @ d25 = t25,  d22 = t22
939         mbutterfly0     d24, d23, d24, d23, d4, d6, q2, q3 @ d24 = t24a, d23 = t23a
940 .endm
941
942 @ Do an 32-point IDCT of a 4x32 slice out of a 32x32 matrix.
943 @ We don't have register space to do a single pass IDCT of 4x32 though,
944 @ but the 32-point IDCT can be decomposed into two 16-point IDCTs;
945 @ a normal IDCT16 with every other input component (the even ones, with
946 @ each output written twice), followed by a separate 16-point IDCT
947 @ of the odd inputs, added/subtracted onto the outputs of the first idct16.
948 @ r0 = dst (temp buffer)
949 @ r1 = unused
950 @ r2 = src
951 function idct32_1d_4x32_pass1_neon
952         movrel          r12, idct_coeffs
953         vld1.16         {q0-q1}, [r12,:128]
954
955         @ Double stride of the input, since we only read every other line
956         mov             r12, #128
957         vmov.s16        d4, #0
958
959         @ d16 = IN(0), d17 = IN(2) ... d31 = IN(30)
960 .irp i, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31
961         vld1.16         {d\i}, [r2,:64]
962         vst1.16         {d4},  [r2,:64], r12
963 .endr
964
965         idct16
966
967         @ Do four 4x4 transposes. Originally, d16-d31 contain the
968         @ 16 rows. Afterwards, d16-d19, d20-d23, d24-d27, d28-d31
969         @ contain the transposed 4x4 blocks.
970         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
971         @ Store the registers a, b, c, d horizontally, followed
972         @ by the same registers d, c, b, a mirrored.
973 .macro store_rev a, b, c, d
974 .irp i, \a, \b, \c, \d
975         vst1.16         {d\i}, [r0,:64]!
976         vrev64.16       d\i, d\i
977 .endr
978 .irp i, \d, \c, \b, \a
979         vst1.16         {d\i}, [r0,:64]!
980 .endr
981 .endm
982         store_rev       16, 20, 24, 28
983         store_rev       17, 21, 25, 29
984         store_rev       18, 22, 26, 30
985         store_rev       19, 23, 27, 31
986         sub             r0,  r0,  #256
987 .purgem store_rev
988
989         @ Move r2 back to the start of the input, and move
990         @ to the first odd row
991         sub             r2,  r2,  r12, lsl #4
992         add             r2,  r2,  #64
993
994         vmov.s16        d4, #0
995         @ d16 = IN(1), d17 = IN(3) ... d31 = IN(31)
996 .irp i, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31
997         vld1.16         {d\i}, [r2,:64]
998         vst1.16         {d4},  [r2,:64], r12
999 .endr
1000
1001         idct32_odd
1002
1003         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
1004
1005         @ Store the registers a, b, c, d horizontally,
1006         @ adding into the output first, and then mirrored, subtracted
1007         @ from the output.
1008 .macro store_rev a, b, c, d
1009 .irp i, \a, \b, \c, \d
1010         vld1.16         {d4},  [r0,:64]
1011         vadd.s16        d4, d4, d\i
1012         vst1.16         {d4},  [r0,:64]!
1013         vrev64.16       d\i, d\i
1014 .endr
1015 .irp i, \d, \c, \b, \a
1016         vld1.16         {d4},  [r0,:64]
1017         vsub.s16        d4, d4, d\i
1018         vst1.16         {d4},  [r0,:64]!
1019 .endr
1020 .endm
1021
1022         store_rev 31, 27, 23, 19
1023         store_rev 30, 26, 22, 18
1024         store_rev 29, 25, 21, 17
1025         store_rev 28, 24, 20, 16
1026 .purgem store_rev
1027         bx              lr
1028 endfunc
1029 .ltorg
1030
1031 @ This is mostly the same as 4x32_pass1, but without the transpose,
1032 @ and use the source as temp buffer between the two idct passes, and
1033 @ add into the destination.
1034 @ r0 = dst
1035 @ r1 = dst stride
1036 @ r2 = src (temp buffer)
1037 function idct32_1d_4x32_pass2_neon
1038         movrel          r12, idct_coeffs
1039         vld1.16         {q0-q1}, [r12,:128]
1040
1041         mov             r12, #128
1042         @ d16 = IN(0), d17 = IN(2) ... d31 = IN(30)
1043 .irp i, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31
1044         vld1.16         {d\i}, [r2,:64], r12
1045 .endr
1046         sub             r2,  r2,  r12, lsl #4
1047
1048         idct16
1049
1050 .irp i, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31
1051         vst1.16         {d\i}, [r2,:64], r12
1052 .endr
1053
1054         sub             r2,  r2,  r12, lsl #4
1055         add             r2,  r2,  #64
1056
1057         @ d16 = IN(1), d17 = IN(3) ... d31 = IN(31)
1058 .irp i, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31
1059         vld1.16         {d\i}, [r2,:64], r12
1060 .endr
1061         sub             r2,  r2,  r12, lsl #4
1062         sub             r2,  r2,  #64
1063
1064         idct32_odd
1065
1066         mov             r12, #128
1067 .macro load_acc_store a, b, c, d, neg=0
1068         vld1.16         {d4},  [r2,:64], r12
1069         vld1.16         {d5},  [r2,:64], r12
1070 .if \neg == 0
1071         vadd.s16        d4, d4, d\a
1072         vld1.16         {d6},  [r2,:64], r12
1073         vadd.s16        d5, d5, d\b
1074         vld1.16         {d7},  [r2,:64], r12
1075         vadd.s16        d6, d6, d\c
1076         vadd.s16        d7, d7, d\d
1077 .else
1078         vsub.s16        d4, d4, d\a
1079         vld1.16         {d6},  [r2,:64], r12
1080         vsub.s16        d5, d5, d\b
1081         vld1.16         {d7},  [r2,:64], r12
1082         vsub.s16        d6, d6, d\c
1083         vsub.s16        d7, d7, d\d
1084 .endif
1085         vld1.32         {d2[]},   [r0,:32], r1
1086         vld1.32         {d2[1]},  [r0,:32], r1
1087         vrshr.s16       q2, q2, #6
1088         vld1.32         {d3[]},   [r0,:32], r1
1089         vrshr.s16       q3, q3, #6
1090         vld1.32         {d3[1]},  [r0,:32], r1
1091         sub             r0,  r0,  r1, lsl #2
1092         vaddw.u8        q2,  q2,  d2
1093         vaddw.u8        q3,  q3,  d3
1094         vqmovun.s16     d4,  q2
1095         vqmovun.s16     d5,  q3
1096         vst1.32         {d4[0]},  [r0,:32], r1
1097         vst1.32         {d4[1]},  [r0,:32], r1
1098         vst1.32         {d5[0]},  [r0,:32], r1
1099         vst1.32         {d5[1]},  [r0,:32], r1
1100 .endm
1101         load_acc_store  31, 30, 29, 28
1102         load_acc_store  27, 26, 25, 24
1103         load_acc_store  23, 22, 21, 20
1104         load_acc_store  19, 18, 17, 16
1105         sub             r2,  r2,  r12
1106         neg             r12, r12
1107         load_acc_store  16, 17, 18, 19, 1
1108         load_acc_store  20, 21, 22, 23, 1
1109         load_acc_store  24, 25, 26, 27, 1
1110         load_acc_store  28, 29, 30, 31, 1
1111 .purgem load_acc_store
1112         bx              lr
1113 endfunc
1114
1115 function ff_vp9_idct_idct_32x32_add_neon, export=1
1116         cmp             r3,  #1
1117         beq             idct32x32_dc_add_neon
1118         push            {r4-r7,lr}
1119         vpush           {q4-q7}
1120         mov             r7,  sp
1121
1122         @ Align the stack, allocate a temp buffer
1123 T       mov             r12, sp
1124 T       bic             r12, r12, #15
1125 T       sub             r12, r12, #2048
1126 T       mov             sp,  r12
1127 A       bic             sp,  sp,  #15
1128 A       sub             sp,  sp,  #2048
1129
1130         mov             r4,  r0
1131         mov             r5,  r1
1132         mov             r6,  r2
1133
1134 .irp i, 0, 4, 8, 12, 16, 20, 24, 28
1135         add             r0,  sp,  #(\i*64)
1136         add             r2,  r6,  #(\i*2)
1137         bl              idct32_1d_4x32_pass1_neon
1138 .endr
1139 .irp i, 0, 4, 8, 12, 16, 20, 24, 28
1140         add             r0,  r4,  #(\i)
1141         mov             r1,  r5
1142         add             r2,  sp,  #(\i*2)
1143         bl              idct32_1d_4x32_pass2_neon
1144 .endr
1145
1146         mov             sp,  r7
1147         vpop            {q4-q7}
1148         pop             {r4-r7,pc}
1149 endfunc