]> git.sesse.net Git - ffmpeg/blob - libavcodec/arm/vp9itxfm_neon.S
arm: vp9itxfm: Simplify the stack alignment code
[ffmpeg] / 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\()_\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
795         @ Align the stack, allocate a temp buffer
796 T       mov             r7,  sp
797 T       and             r7,  r7,  #15
798 A       and             r7,  sp,  #15
799         add             r7,  r7,  #512
800         sub             sp,  sp,  r7
801
802         mov             r4,  r0
803         mov             r5,  r1
804         mov             r6,  r2
805
806 .ifc \txfm1,idct
807         movrel          r12, idct_coeffs
808         vld1.16         {q0-q1}, [r12,:128]
809 .endif
810
811 .irp i, 0, 4, 8, 12
812         add             r0,  sp,  #(\i*32)
813         add             r2,  r6,  #(\i*2)
814         mov             r3,  #\i
815         bl              \txfm1\()16_1d_4x16_pass1_neon
816 .endr
817 .ifc \txfm2,idct
818         movrel          r12, idct_coeffs
819         vld1.16         {q0-q1}, [r12,:128]
820 .endif
821 .irp i, 0, 4, 8, 12
822         add             r0,  r4,  #(\i)
823         mov             r1,  r5
824         add             r2,  sp,  #(\i*2)
825         mov             r3,  #\i
826         bl              \txfm2\()16_1d_4x16_pass2_neon
827 .endr
828
829         add             sp,  sp,  r7
830 .ifnc \txfm1\()_\txfm2,idct_idct
831         vpop            {q4-q7}
832 .endif
833         pop             {r4-r7,pc}
834 endfunc
835 .endm
836
837 itxfm_func16x16 idct,  idct
838 itxfm_func16x16 iadst, idct
839 itxfm_func16x16 idct,  iadst
840 itxfm_func16x16 iadst, iadst
841 .ltorg
842
843
844 function idct32x32_dc_add_neon
845         movrel          r12, idct_coeffs
846         vld1.16         {d0}, [r12,:64]
847
848         vmov.i16        q2, #0
849
850         vld1.16         {d16[]}, [r2,:16]
851         vmull.s16       q8,  d16, d0[0]
852         vrshrn.s32      d16, q8,  #14
853         vmull.s16       q8,  d16, d0[0]
854         vrshrn.s32      d16, q8,  #14
855         vdup.16         q8,  d16[0]
856         vst1.16         {d4[0]}, [r2,:16]
857
858         vrshr.s16       q8,  q8,  #6
859
860         mov             r12, #32
861 1:
862         @ Loop to add the constant from q8 into all 32x32 outputs
863         vld1.8          {q2-q3},  [r0,:128]
864         vaddw.u8        q10, q8,  d4
865         vaddw.u8        q11, q8,  d5
866         vaddw.u8        q12, q8,  d6
867         vaddw.u8        q13, q8,  d7
868         vqmovun.s16     d4,  q10
869         vqmovun.s16     d5,  q11
870         vqmovun.s16     d6,  q12
871         vqmovun.s16     d7,  q13
872         vst1.8          {q2-q3},  [r0,:128], r1
873         subs            r12, r12, #1
874         bne             1b
875
876         bx              lr
877 endfunc
878
879 .macro idct32_odd
880         movrel          r12, idct_coeffs
881         add             r12, r12, #32
882         vld1.16         {q0-q1}, [r12,:128]
883
884         mbutterfly      d16, d31, d0[0], d0[1], q2, q3 @ d16 = t16a, d31 = t31a
885         mbutterfly      d24, d23, d0[2], d0[3], q2, q3 @ d24 = t17a, d23 = t30a
886         mbutterfly      d20, d27, d1[0], d1[1], q2, q3 @ d20 = t18a, d27 = t29a
887         mbutterfly      d28, d19, d1[2], d1[3], q2, q3 @ d28 = t19a, d19 = t28a
888         mbutterfly      d18, d29, d2[0], d2[1], q2, q3 @ d18 = t20a, d29 = t27a
889         mbutterfly      d26, d21, d2[2], d2[3], q2, q3 @ d26 = t21a, d21 = t26a
890         mbutterfly      d22, d25, d3[0], d3[1], q2, q3 @ d22 = t22a, d25 = t25a
891         mbutterfly      d30, d17, d3[2], d3[3], q2, q3 @ d30 = t23a, d17 = t24a
892
893         sub             r12, r12, #32
894         vld1.16         {q0}, [r12,:128]
895
896         butterfly       d4,  d24, d16, d24 @ d4  = t16, d24 = t17
897         butterfly       d5,  d20, d28, d20 @ d5  = t19, d20 = t18
898         butterfly       d6,  d26, d18, d26 @ d6  = t20, d26 = t21
899         butterfly       d7,  d22, d30, d22 @ d7  = t23, d22 = t22
900         butterfly       d28, d25, d17, d25 @ d28 = t24, d25 = t25
901         butterfly       d30, d21, d29, d21 @ d30 = t27, d21 = t26
902         butterfly       d29, d23, d31, d23 @ d29 = t31, d23 = t30
903         butterfly       d31, d27, d19, d27 @ d31 = t28, d27 = t29
904
905         mbutterfly      d23, d24, d0[3], d1[0], q8, q9        @ d23 = t17a, d24 = t30a
906         mbutterfly      d27, d20, d0[3], d1[0], q8, q9, neg=1 @ d27 = t29a, d20 = t18a
907         mbutterfly      d21, d26, d1[1], d1[2], q8, q9        @ d21 = t21a, d26 = t26a
908         mbutterfly      d25, d22, d1[1], d1[2], q8, q9, neg=1 @ d25 = t25a, d22 = t22a
909
910         butterfly       d16, d5,  d4,  d5  @ d16 = t16a, d5  = t19a
911         butterfly       d17, d20, d23, d20 @ d17 = t17,  d20 = t18
912         butterfly       d18, d6,  d7,  d6  @ d18 = t23a, d6  = t20a
913         butterfly       d19, d21, d22, d21 @ d19 = t22,  d21 = t21
914         butterfly       d4,  d28, d28, d30 @ d4  = t24a, d28 = t27a
915         butterfly       d23, d26, d25, d26 @ d23 = t25,  d26 = t26
916         butterfly       d7,  d29, d29, d31 @ d7  = t31a, d29 = t28a
917         butterfly       d22, d27, d24, d27 @ d22 = t30,  d27 = t29
918
919         mbutterfly      d27, d20, d0[1], d0[2], q12, q15        @ d27 = t18a, d20 = t29a
920         mbutterfly      d29, d5,  d0[1], d0[2], q12, q15        @ d29 = t19,  d5  = t28
921         mbutterfly      d28, d6,  d0[1], d0[2], q12, q15, neg=1 @ d28 = t27,  d6  = t20
922         mbutterfly      d26, d21, d0[1], d0[2], q12, q15, neg=1 @ d26 = t26a, d21 = t21a
923
924         butterfly       d31, d24, d7,  d4  @ d31 = t31,  d24 = t24
925         butterfly       d30, d25, d22, d23 @ d30 = t30a, d25 = t25a
926         butterfly_r     d23, d16, d16, d18 @ d23 = t23,  d16 = t16
927         butterfly_r     d22, d17, d17, d19 @ d22 = t22a, d17 = t17a
928         butterfly       d18, d21, d27, d21 @ d18 = t18,  d21 = t21
929         butterfly_r     d27, d28, d5,  d28 @ d27 = t27a, d28 = t28a
930         butterfly       d4,  d26, d20, d26 @ d4  = t29,  d26 = t26
931         butterfly       d19, d20, d29, d6  @ d19 = t19a, d20 = t20
932         vmov            d29, d4            @ d29 = t29
933
934         mbutterfly0     d27, d20, d27, d20, d4, d6, q2, q3 @ d27 = t27,  d20 = t20
935         mbutterfly0     d26, d21, d26, d21, d4, d6, q2, q3 @ d26 = t26a, d21 = t21a
936         mbutterfly0     d25, d22, d25, d22, d4, d6, q2, q3 @ d25 = t25,  d22 = t22
937         mbutterfly0     d24, d23, d24, d23, d4, d6, q2, q3 @ d24 = t24a, d23 = t23a
938 .endm
939
940 @ Do an 32-point IDCT of a 4x32 slice out of a 32x32 matrix.
941 @ We don't have register space to do a single pass IDCT of 4x32 though,
942 @ but the 32-point IDCT can be decomposed into two 16-point IDCTs;
943 @ a normal IDCT16 with every other input component (the even ones, with
944 @ each output written twice), followed by a separate 16-point IDCT
945 @ of the odd inputs, added/subtracted onto the outputs of the first idct16.
946 @ r0 = dst (temp buffer)
947 @ r1 = unused
948 @ r2 = src
949 function idct32_1d_4x32_pass1_neon
950         movrel          r12, idct_coeffs
951         vld1.16         {q0-q1}, [r12,:128]
952
953         @ Double stride of the input, since we only read every other line
954         mov             r12, #128
955         vmov.s16        d4, #0
956
957         @ d16 = IN(0), d17 = IN(2) ... d31 = IN(30)
958 .irp i, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31
959         vld1.16         {d\i}, [r2,:64]
960         vst1.16         {d4},  [r2,:64], r12
961 .endr
962
963         idct16
964
965         @ Do four 4x4 transposes. Originally, d16-d31 contain the
966         @ 16 rows. Afterwards, d16-d19, d20-d23, d24-d27, d28-d31
967         @ contain the transposed 4x4 blocks.
968         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
969         @ Store the registers a, b, c, d horizontally, followed
970         @ by the same registers d, c, b, a mirrored.
971 .macro store_rev a, b, c, d
972 .irp i, \a, \b, \c, \d
973         vst1.16         {d\i}, [r0,:64]!
974         vrev64.16       d\i, d\i
975 .endr
976 .irp i, \d, \c, \b, \a
977         vst1.16         {d\i}, [r0,:64]!
978 .endr
979 .endm
980         store_rev       16, 20, 24, 28
981         store_rev       17, 21, 25, 29
982         store_rev       18, 22, 26, 30
983         store_rev       19, 23, 27, 31
984         sub             r0,  r0,  #256
985 .purgem store_rev
986
987         @ Move r2 back to the start of the input, and move
988         @ to the first odd row
989         sub             r2,  r2,  r12, lsl #4
990         add             r2,  r2,  #64
991
992         vmov.s16        d4, #0
993         @ d16 = IN(1), d17 = IN(3) ... d31 = IN(31)
994 .irp i, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31
995         vld1.16         {d\i}, [r2,:64]
996         vst1.16         {d4},  [r2,:64], r12
997 .endr
998
999         idct32_odd
1000
1001         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
1002
1003         @ Store the registers a, b, c, d horizontally,
1004         @ adding into the output first, and then mirrored, subtracted
1005         @ from the output.
1006 .macro store_rev a, b, c, d
1007 .irp i, \a, \b, \c, \d
1008         vld1.16         {d4},  [r0,:64]
1009         vadd.s16        d4, d4, d\i
1010         vst1.16         {d4},  [r0,:64]!
1011         vrev64.16       d\i, d\i
1012 .endr
1013 .irp i, \d, \c, \b, \a
1014         vld1.16         {d4},  [r0,:64]
1015         vsub.s16        d4, d4, d\i
1016         vst1.16         {d4},  [r0,:64]!
1017 .endr
1018 .endm
1019
1020         store_rev 31, 27, 23, 19
1021         store_rev 30, 26, 22, 18
1022         store_rev 29, 25, 21, 17
1023         store_rev 28, 24, 20, 16
1024 .purgem store_rev
1025         bx              lr
1026 endfunc
1027 .ltorg
1028
1029 @ This is mostly the same as 4x32_pass1, but without the transpose,
1030 @ and use the source as temp buffer between the two idct passes, and
1031 @ add into the destination.
1032 @ r0 = dst
1033 @ r1 = dst stride
1034 @ r2 = src (temp buffer)
1035 function idct32_1d_4x32_pass2_neon
1036         movrel          r12, idct_coeffs
1037         vld1.16         {q0-q1}, [r12,:128]
1038
1039         mov             r12, #128
1040         @ d16 = IN(0), d17 = IN(2) ... d31 = IN(30)
1041 .irp i, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31
1042         vld1.16         {d\i}, [r2,:64], r12
1043 .endr
1044         sub             r2,  r2,  r12, lsl #4
1045
1046         idct16
1047
1048 .irp i, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31
1049         vst1.16         {d\i}, [r2,:64], r12
1050 .endr
1051
1052         sub             r2,  r2,  r12, lsl #4
1053         add             r2,  r2,  #64
1054
1055         @ d16 = IN(1), d17 = IN(3) ... d31 = IN(31)
1056 .irp i, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31
1057         vld1.16         {d\i}, [r2,:64], r12
1058 .endr
1059         sub             r2,  r2,  r12, lsl #4
1060         sub             r2,  r2,  #64
1061
1062         idct32_odd
1063
1064         mov             r12, #128
1065 .macro load_acc_store a, b, c, d, neg=0
1066         vld1.16         {d4},  [r2,:64], r12
1067         vld1.16         {d5},  [r2,:64], r12
1068 .if \neg == 0
1069         vadd.s16        d4, d4, d\a
1070         vld1.16         {d6},  [r2,:64], r12
1071         vadd.s16        d5, d5, d\b
1072         vld1.16         {d7},  [r2,:64], r12
1073         vadd.s16        d6, d6, d\c
1074         vadd.s16        d7, d7, d\d
1075 .else
1076         vsub.s16        d4, d4, d\a
1077         vld1.16         {d6},  [r2,:64], r12
1078         vsub.s16        d5, d5, d\b
1079         vld1.16         {d7},  [r2,:64], r12
1080         vsub.s16        d6, d6, d\c
1081         vsub.s16        d7, d7, d\d
1082 .endif
1083         vld1.32         {d2[]},   [r0,:32], r1
1084         vld1.32         {d2[1]},  [r0,:32], r1
1085         vrshr.s16       q2, q2, #6
1086         vld1.32         {d3[]},   [r0,:32], r1
1087         vrshr.s16       q3, q3, #6
1088         vld1.32         {d3[1]},  [r0,:32], r1
1089         sub             r0,  r0,  r1, lsl #2
1090         vaddw.u8        q2,  q2,  d2
1091         vaddw.u8        q3,  q3,  d3
1092         vqmovun.s16     d4,  q2
1093         vqmovun.s16     d5,  q3
1094         vst1.32         {d4[0]},  [r0,:32], r1
1095         vst1.32         {d4[1]},  [r0,:32], r1
1096         vst1.32         {d5[0]},  [r0,:32], r1
1097         vst1.32         {d5[1]},  [r0,:32], r1
1098 .endm
1099         load_acc_store  31, 30, 29, 28
1100         load_acc_store  27, 26, 25, 24
1101         load_acc_store  23, 22, 21, 20
1102         load_acc_store  19, 18, 17, 16
1103         sub             r2,  r2,  r12
1104         neg             r12, r12
1105         load_acc_store  16, 17, 18, 19, 1
1106         load_acc_store  20, 21, 22, 23, 1
1107         load_acc_store  24, 25, 26, 27, 1
1108         load_acc_store  28, 29, 30, 31, 1
1109 .purgem load_acc_store
1110         bx              lr
1111 endfunc
1112
1113 function ff_vp9_idct_idct_32x32_add_neon, export=1
1114         cmp             r3,  #1
1115         beq             idct32x32_dc_add_neon
1116         push            {r4-r7,lr}
1117         vpush           {q4-q7}
1118
1119         @ Align the stack, allocate a temp buffer
1120 T       mov             r7,  sp
1121 T       and             r7,  r7,  #15
1122 A       and             r7,  sp,  #15
1123         add             r7,  r7,  #2048
1124         sub             sp,  sp,  r7
1125
1126         mov             r4,  r0
1127         mov             r5,  r1
1128         mov             r6,  r2
1129
1130 .irp i, 0, 4, 8, 12, 16, 20, 24, 28
1131         add             r0,  sp,  #(\i*64)
1132         add             r2,  r6,  #(\i*2)
1133         bl              idct32_1d_4x32_pass1_neon
1134 .endr
1135 .irp i, 0, 4, 8, 12, 16, 20, 24, 28
1136         add             r0,  r4,  #(\i)
1137         mov             r1,  r5
1138         add             r2,  sp,  #(\i*2)
1139         bl              idct32_1d_4x32_pass2_neon
1140 .endr
1141
1142         add             sp,  sp,  r7
1143         vpop            {q4-q7}
1144         pop             {r4-r7,pc}
1145 endfunc