arm: vp9itxfm: Share instructions for loading idct coeffs in the 8x8 function
[ffmpeg.git] / libavcodec / arm / vp9itxfm_neon.S
1 /*
2  * Copyright (c) 2016 Google Inc.
3  *
4  * This file is part of Libav.
5  *
6  * Libav is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2.1 of the License, or (at your option) any later version.
10  *
11  * Libav is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with Libav; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19  */
20
21 #include "libavutil/arm/asm.S"
22 #include "neon.S"
23
24 const itxfm4_coeffs, align=4
25         .short  11585, 6270, 15137, 0
26 iadst4_coeffs:
27         .short  5283, 15212, 9929, 13377
28 endconst
29
30 const iadst8_coeffs, align=4
31         .short  16305, 1606, 14449, 7723, 10394, 12665, 4756, 15679
32 idct_coeffs:
33         .short  11585, 6270, 15137, 3196, 16069, 13623, 9102, 1606
34         .short  16305, 12665, 10394, 7723, 14449, 15679, 4756, 0
35         .short  804, 16364, 12140, 11003, 7005, 14811, 15426, 5520
36         .short  3981, 15893, 14053, 8423, 9760, 13160, 16207, 2404
37 endconst
38
39 const iadst16_coeffs, align=4
40         .short  16364, 804, 15893, 3981, 14811, 7005, 13160, 9760
41         .short  11003, 12140, 8423, 14053, 5520, 15426, 2404, 16207
42 endconst
43
44 @ Do four 4x4 transposes, using q registers for the subtransposes that don't
45 @ need to address the individual d registers.
46 @ r0,r1 == rq1, r2,r3 == rq1, etc
47 .macro transpose16_q_4x_4x4 rq0, rq1, rq2, rq3, rq4, rq5, rq6, rq7, r0, r1, r2, r3, r4, r5, r6, r7, r8, r9, r10, r11, r12, r13, r14, r15
48         vtrn.32          \rq0, \rq1
49         vtrn.32          \rq2, \rq3
50         vtrn.32          \rq4, \rq5
51         vtrn.32          \rq6, \rq7
52         vtrn.16          \r0,  \r1
53         vtrn.16          \r2,  \r3
54         vtrn.16          \r4,  \r5
55         vtrn.16          \r6,  \r7
56         vtrn.16          \r8,  \r9
57         vtrn.16          \r10, \r11
58         vtrn.16          \r12, \r13
59         vtrn.16          \r14, \r15
60 .endm
61
62 @ out1 = ((in1 + in2) * d0[0] + (1 << 13)) >> 14
63 @ out2 = ((in1 - in2) * d0[0] + (1 << 13)) >> 14
64 @ in/out are d registers
65 .macro mbutterfly0 out1, out2, in1, in2, tmpd1, tmpd2, tmpq3, tmpq4, neg=0
66         vadd.s16        \tmpd1, \in1,  \in2
67         vsub.s16        \tmpd2, \in1,  \in2
68         vmull.s16       \tmpq3, \tmpd1, d0[0]
69         vmull.s16       \tmpq4, \tmpd2, d0[0]
70 .if \neg > 0
71         vneg.s32        \tmpq3, \tmpq3
72 .endif
73         vrshrn.s32      \out1, \tmpq3, #14
74         vrshrn.s32      \out2, \tmpq4, #14
75 .endm
76
77 @ Same as mbutterfly0 above, but treating the input in in2 as zero,
78 @ writing the same output into both out1 and out2.
79 .macro mbutterfly0_h out1, out2, in1, in2, tmpd1, tmpd2, tmpq3, tmpq4
80         vmull.s16       \tmpq3, \in1, d0[0]
81         vrshrn.s32      \out1,  \tmpq3, #14
82         vrshrn.s32      \out2,  \tmpq3, #14
83 .endm
84
85 @ out1,out2 = ((in1 + in2) * d0[0] + (1 << 13)) >> 14
86 @ out3,out4 = ((in1 - in2) * d0[0] + (1 << 13)) >> 14
87 @ Same as mbutterfly0, but with input being 2 q registers, output
88 @ being 4 d registers.
89 @ This can do with either 4 or 6 temporary q registers.
90 .macro dmbutterfly0 out1, out2, out3, out4, in1, in2, tmpq1, tmpq2, tmpd11, tmpd12, tmpd21, tmpd22, tmpq3, tmpq4, tmpq5, tmpq6
91         vadd.s16        \tmpq1, \in1,  \in2
92         vsub.s16        \tmpq2, \in1,  \in2
93         vmull.s16       \tmpq3, \tmpd11, d0[0]
94         vmull.s16       \tmpq4, \tmpd12, d0[0]
95 .ifb \tmpq5
96         vrshrn.s32      \out1, \tmpq3, #14
97         vrshrn.s32      \out2, \tmpq4, #14
98         vmull.s16       \tmpq3, \tmpd21, d0[0]
99         vmull.s16       \tmpq4, \tmpd22, d0[0]
100         vrshrn.s32      \out3, \tmpq3, #14
101         vrshrn.s32      \out4, \tmpq4, #14
102 .else
103         vmull.s16       \tmpq5, \tmpd21, d0[0]
104         vmull.s16       \tmpq6, \tmpd22, d0[0]
105         vrshrn.s32      \out1, \tmpq3, #14
106         vrshrn.s32      \out2, \tmpq4, #14
107         vrshrn.s32      \out3, \tmpq5, #14
108         vrshrn.s32      \out4, \tmpq6, #14
109 .endif
110 .endm
111
112 @ out1 = in1 * coef1 - in2 * coef2
113 @ out2 = in1 * coef2 + in2 * coef1
114 @ out are 2 q registers, in are 2 d registers
115 .macro mbutterfly_l out1, out2, in1, in2, coef1, coef2
116         vmull.s16       \out1, \in1, \coef1
117         vmlsl.s16       \out1, \in2, \coef2
118         vmull.s16       \out2, \in1, \coef2
119         vmlal.s16       \out2, \in2, \coef1
120 .endm
121
122 @ out1,out2 = in1,in2 * coef1 - in3,in4 * coef2
123 @ out3,out4 = in1,in2 * coef2 + in3,in4 * coef1
124 @ out are 4 q registers, in are 4 d registers
125 .macro dmbutterfly_l out1, out2, out3, out4, in1, in2, in3, in4, coef1, coef2
126         vmull.s16       \out1, \in1, \coef1
127         vmull.s16       \out2, \in2, \coef1
128         vmull.s16       \out3, \in1, \coef2
129         vmull.s16       \out4, \in2, \coef2
130         vmlsl.s16       \out1, \in3, \coef2
131         vmlsl.s16       \out2, \in4, \coef2
132         vmlal.s16       \out3, \in3, \coef1
133         vmlal.s16       \out4, \in4, \coef1
134 .endm
135
136 @ inout1 = (inout1 * coef1 - inout2 * coef2 + (1 << 13)) >> 14
137 @ inout2 = (inout1 * coef2 + inout2 * coef1 + (1 << 13)) >> 14
138 @ inout are 2 d registers, tmp are 2 q registers
139 .macro mbutterfly inout1, inout2, coef1, coef2, tmp1, tmp2, neg=0
140         mbutterfly_l    \tmp1, \tmp2, \inout1, \inout2, \coef1, \coef2
141 .if \neg > 0
142         vneg.s32        \tmp2, \tmp2
143 .endif
144         vrshrn.s32      \inout1, \tmp1,  #14
145         vrshrn.s32      \inout2, \tmp2,  #14
146 .endm
147
148 @ Same as mbutterfly above, but treating the input in inout2 as zero
149 .macro mbutterfly_h1 inout1, inout2, coef1, coef2, tmp1, tmp2
150         vmull.s16       \tmp1,   \inout1, \coef1
151         vmull.s16       \tmp2,   \inout1, \coef2
152         vrshrn.s32      \inout1, \tmp1,   #14
153         vrshrn.s32      \inout2, \tmp2,   #14
154 .endm
155
156 @ Same as mbutterfly above, but treating the input in inout1 as zero
157 .macro mbutterfly_h2 inout1, inout2, coef1, coef2, tmp1, tmp2
158         vmull.s16       \tmp1,   \inout2, \coef2
159         vmull.s16       \tmp2,   \inout2, \coef1
160         vneg.s32        \tmp1,   \tmp1
161         vrshrn.s32      \inout2, \tmp2,   #14
162         vrshrn.s32      \inout1, \tmp1,   #14
163 .endm
164
165 @ inout1,inout2 = (inout1,inout2 * coef1 - inout3,inout4 * coef2 + (1 << 13)) >> 14
166 @ inout3,inout4 = (inout1,inout2 * coef2 + inout3,inout4 * coef1 + (1 << 13)) >> 14
167 @ inout are 4 d registers, tmp are 4 q registers
168 .macro dmbutterfly inout1, inout2, inout3, inout4, coef1, coef2, tmp1, tmp2, tmp3, tmp4
169         dmbutterfly_l   \tmp1, \tmp2, \tmp3, \tmp4, \inout1, \inout2, \inout3, \inout4, \coef1, \coef2
170         vrshrn.s32      \inout1, \tmp1,  #14
171         vrshrn.s32      \inout2, \tmp2,  #14
172         vrshrn.s32      \inout3, \tmp3,  #14
173         vrshrn.s32      \inout4, \tmp4,  #14
174 .endm
175
176 @ out1 = in1 + in2
177 @ out2 = in1 - in2
178 .macro butterfly out1, out2, in1, in2
179         vadd.s16        \out1, \in1, \in2
180         vsub.s16        \out2, \in1, \in2
181 .endm
182
183 @ out1 = in1 - in2
184 @ out2 = in1 + in2
185 .macro butterfly_r out1, out2, in1, in2
186         vsub.s16        \out1, \in1, \in2
187         vadd.s16        \out2, \in1, \in2
188 .endm
189
190 @ out1 = (in1 + in2 + (1 << 13)) >> 14
191 @ out2 = (in1 - in2 + (1 << 13)) >> 14
192 @ out are 2 d registers, in are 2 q registers, tmp are 2 q registers
193 .macro butterfly_n out1, out2, in1, in2, tmp1, tmp2
194         vadd.s32        \tmp1, \in1, \in2
195         vsub.s32        \tmp2, \in1, \in2
196         vrshrn.s32      \out1, \tmp1,  #14
197         vrshrn.s32      \out2, \tmp2,  #14
198 .endm
199
200 @ out1,out2 = (in1,in2 + in3,in4 + (1 << 13)) >> 14
201 @ out3,out4 = (in1,in2 - in3,in4 + (1 << 13)) >> 14
202 @ out are 4 d registers, in are 4 q registers, tmp are 4 q registers
203 .macro dbutterfly_n out1, out2, out3, out4, in1, in2, in3, in4, tmp1, tmp2, tmp3, tmp4
204         vadd.s32        \tmp1, \in1, \in3
205         vadd.s32        \tmp2, \in2, \in4
206         vsub.s32        \tmp3, \in1, \in3
207         vsub.s32        \tmp4, \in2, \in4
208         vrshrn.s32      \out1, \tmp1,  #14
209         vrshrn.s32      \out2, \tmp2,  #14
210         vrshrn.s32      \out3, \tmp3,  #14
211         vrshrn.s32      \out4, \tmp4,  #14
212 .endm
213
214
215 .macro iwht4 c0, c1, c2, c3
216         vadd.i16        \c0,  \c0,  \c1
217         vsub.i16        d17,  \c2,  \c3
218         vsub.i16        d16,  \c0,  d17
219         vshr.s16        d16,  d16,  #1
220         vsub.i16        \c2,  d16,  \c1
221         vsub.i16        \c1,  d16,  \c3
222         vadd.i16        \c3,  d17,  \c2
223         vsub.i16        \c0,  \c0,  \c1
224 .endm
225
226 .macro idct4 c0, c1, c2, c3
227         vmull.s16       q13,  \c1,  d0[2]
228         vmull.s16       q11,  \c1,  d0[1]
229         vadd.i16        d16,  \c0,  \c2
230         vsub.i16        d17,  \c0,  \c2
231         vmlal.s16       q13,  \c3,  d0[1]
232         vmull.s16       q9,   d16,  d0[0]
233         vmull.s16       q10,  d17,  d0[0]
234         vmlsl.s16       q11,  \c3,  d0[2]
235         vrshrn.s32      d26,  q13,  #14
236         vrshrn.s32      d18,  q9,   #14
237         vrshrn.s32      d20,  q10,  #14
238         vrshrn.s32      d22,  q11,  #14
239         vadd.i16        \c0,  d18,  d26
240         vsub.i16        \c3,  d18,  d26
241         vadd.i16        \c1,  d20,  d22
242         vsub.i16        \c2,  d20,  d22
243 .endm
244
245 .macro iadst4 c0, c1, c2, c3
246         vmull.s16       q10,  \c0,  d1[0]
247         vmlal.s16       q10,  \c2,  d1[1]
248         vmlal.s16       q10,  \c3,  d1[2]
249         vmull.s16       q11,  \c0,  d1[2]
250         vmlsl.s16       q11,  \c2,  d1[0]
251         vsub.s16        \c0,  \c0,  \c2
252         vmlsl.s16       q11,  \c3,  d1[1]
253         vadd.s16        \c0,  \c0,  \c3
254         vmull.s16       q13,  \c1,  d1[3]
255         vmull.s16       q12,  \c0,  d1[3]
256         vadd.s32        q14,  q10,  q13
257         vadd.s32        q1,   q11,  q13
258         vrshrn.s32      \c0,  q14,  #14
259         vadd.s32        q10,  q10,  q11
260         vrshrn.s32      \c1,  q1,   #14
261         vsub.s32        q10,  q10,  q13
262         vrshrn.s32      \c2,  q12,  #14
263         vrshrn.s32      \c3,  q10,  #14
264 .endm
265
266 @ The public functions in this file have got the following signature:
267 @ void itxfm_add(uint8_t *dst, ptrdiff_t stride, int16_t *block, int eob);
268
269 .macro itxfm_func4x4 txfm1, txfm2
270 function ff_vp9_\txfm1\()_\txfm2\()_4x4_add_neon, export=1
271 .ifc \txfm1,\txfm2
272 .ifc \txfm1,idct
273         movrel          r12, itxfm4_coeffs
274         vld1.16         {d0}, [r12,:64]
275 .endif
276 .ifc \txfm1,iadst
277         movrel          r12, iadst4_coeffs
278         vld1.16         {d1}, [r12,:64]
279 .endif
280 .else
281         movrel          r12, itxfm4_coeffs
282         vld1.16         {q0}, [r12,:128]
283 .endif
284
285         vmov.i16        q15, #0
286 .ifc \txfm1\()_\txfm2,idct_idct
287         cmp             r3,  #1
288         bne             1f
289         @ DC-only for idct/idct
290         vld1.16         {d4[]},   [r2,:16]
291         vmull.s16       q2,  d4,  d0[0]
292         vrshrn.s32      d4,  q2,  #14
293         vmull.s16       q2,  d4,  d0[0]
294         vrshrn.s32      d4,  q2,  #14
295         vst1.16         {d30[0]}, [r2,:16]
296         vdup.16         q2,  d4[0]
297         vmov            q3,  q2
298         b               2f
299 .endif
300
301 1:
302         vld1.16         {d4-d7},  [r2,:128]
303         vst1.16         {q15}, [r2,:128]!
304
305 .ifc \txfm1,iwht
306         vshr.s16        q2,  q2,  #2
307         vshr.s16        q3,  q3,  #2
308 .endif
309
310         \txfm1\()4      d4,  d5,  d6,  d7
311
312         vst1.16         {q15}, [r2,:128]!
313         @ Transpose 4x4 with 16 bit elements
314         vtrn.16         d4,  d5
315         vtrn.16         d6,  d7
316         vtrn.32         q2,  q3
317
318         \txfm2\()4      d4,  d5,  d6,  d7
319 2:
320         vld1.32         {d0[]},   [r0,:32], r1
321         vld1.32         {d0[1]},  [r0,:32], r1
322 .ifnc \txfm1,iwht
323         vrshr.s16       q2,  q2,  #4
324         vrshr.s16       q3,  q3,  #4
325 .endif
326         vaddw.u8        q2,  q2,  d0
327         vld1.32         {d1[]},   [r0,:32], r1
328         vld1.32         {d1[1]},  [r0,:32], r1
329         vqmovun.s16     d0,  q2
330         sub             r0,  r0,  r1, lsl #2
331
332         vaddw.u8        q3,  q3,  d1
333         vst1.32         {d0[0]},  [r0,:32], r1
334         vqmovun.s16     d1,  q3
335
336         vst1.32         {d0[1]},  [r0,:32], r1
337         vst1.32         {d1[0]},  [r0,:32], r1
338         vst1.32         {d1[1]},  [r0,:32], r1
339
340         bx              lr
341 endfunc
342 .endm
343
344 itxfm_func4x4 idct,  idct
345 itxfm_func4x4 iadst, idct
346 itxfm_func4x4 idct,  iadst
347 itxfm_func4x4 iadst, iadst
348 itxfm_func4x4 iwht,  iwht
349
350
351 .macro idct8
352         dmbutterfly0    d16, d17, d24, d25, q8,  q12, q2, q4, d4, d5, d8, d9, q3, q2, q5, q4 @ q8 = t0a, q12 = t1a
353         dmbutterfly     d20, d21, d28, d29, d0[1], d0[2], q2,  q3,  q4,  q5 @ q10 = t2a, q14 = t3a
354         dmbutterfly     d18, d19, d30, d31, d0[3], d1[0], q2,  q3,  q4,  q5 @ q9  = t4a, q15 = t7a
355         dmbutterfly     d26, d27, d22, d23, d1[1], d1[2], q2,  q3,  q4,  q5 @ q13 = t5a, q11 = t6a
356
357         butterfly       q2,  q14, q8,  q14 @ q2 = t0, q14 = t3
358         butterfly       q3,  q10, q12, q10 @ q3 = t1, q10 = t2
359         butterfly       q4,  q13, q9,  q13 @ q4 = t4, q13 = t5a
360         butterfly       q5,  q11, q15, q11 @ q5 = t7, q11 = t6a
361
362         butterfly       q8,  q15, q2,  q5  @ q8 = out[0], q15 = out[7]
363
364         dmbutterfly0    d4,  d5,  d10, d11, q11, q13, q9,  q13, d18, d19, d26, d27, q2,  q5, q11, q12 @ q2 = t6, q5 = t5
365
366         butterfly       q11, q12, q14, q4  @ q11 = out[3], q12 = out[4]
367         butterfly       q9,  q14, q3,  q2  @ q9 = out[1],  q14 = out[6]
368         butterfly_r     q13, q10, q10, q5  @ q13 = out[5], q10 = out[2]
369 .endm
370
371 .macro iadst8
372         dmbutterfly_l   q4,  q5,  q2,  q3,  d30, d31, d16, d17, d2[1], d2[0] @ q4,q5  = t1a, q2,q3 = t0a
373         dmbutterfly_l   q8,  q15, q6,  q7,  d22, d23, d24, d25, d3[1], d3[0] @ q8,q15 = t5a, q6,q7 = t4a
374
375         dbutterfly_n    d22, d23, d4,  d5,  q2,  q3,  q6,  q7,  q11, q12, q2,  q3 @ q11 = t0, q2 = t4
376
377         dbutterfly_n    d24, d25, d6,  d7,  q4,  q5,  q8,  q15, q12, q3,  q6,  q7 @ q12 = t1, q3 = t5
378
379         dmbutterfly_l   q6,  q7,  q4,  q5,  d26, d27, d20, d21, d2[3], d2[2] @ q6,q7 = t3a, q4,q5 = t2a
380         dmbutterfly_l   q10, q13, q8,  q15, d18, d19, d28, d29, d3[3], d3[2] @ q10,q13 = t7a, q8,q15 = t6a
381
382         dbutterfly_n    d18, d19, d8,  d9,  q4,  q5,  q8,  q15, q9,  q14, q4, q5 @ q9 = t2, q4 = t6
383         dbutterfly_n    d16, d17, d12, d13, q6,  q7,  q10, q13, q8,  q15, q6, q7 @ q8 = t3, q6 = t7
384
385         butterfly       q15, q12, q12, q8 @ q15 = -out[7], q12 = t3
386         vneg.s16        q15, q15          @ q15 = out[7]
387         butterfly       q8,  q9,  q11, q9 @ q8 = out[0], q9 = t2
388
389         dmbutterfly_l   q10, q11, q5,  q7,  d4,  d5,  d6,  d7,  d0[1], d0[2] @ q10,q11 = t5a, q5,q7 = t4a
390         dmbutterfly_l   q2,  q3,  q13, q14, d12, d13, d8,  d9,  d0[2], d0[1] @ q2,q3 = t6a, q13,q14 = t7a
391
392         dbutterfly_n    d28, d29, d8,  d9,  q10, q11, q13, q14, q4,  q6,  q10, q11 @ q14 = out[6], q4 = t7
393
394         dmbutterfly0    d22, d23, d24, d25, q9,  q12, q6, q13, d12, d13, d26, d27, q9, q10 @ q11 = -out[3], q12 = out[4]
395         vneg.s16        q11, q11      @ q11 = out[3]
396
397         dbutterfly_n    d18, d19, d4,  d5,  q5,  q7,  q2,  q3,  q9, q10, q2,  q3 @ q9 = -out[1], q2 = t6
398         vneg.s16        q9,  q9       @ q9 = out[1]
399
400         dmbutterfly0    d20, d21, d26, d27, q2,  q4,  q3, q5,  d6,  d7,  d10, d11, q6,  q7 @ q10 = out[2], q13 = -out[5]
401         vneg.s16        q13, q13      @ q13 = out[5]
402 .endm
403
404
405 .macro itxfm_func8x8 txfm1, txfm2
406 function ff_vp9_\txfm1\()_\txfm2\()_8x8_add_neon, export=1
407         @ Push q4-q7 if iadst is used, idct requires
408         @ a few scratch registers less, so only push q4-q5
409         @ if only idct is involved.
410         @ The iadst also uses a few coefficients from
411         @ idct, so those always need to be loaded.
412 .ifc \txfm1\()_\txfm2,idct_idct
413         movrel          r12, idct_coeffs
414         vpush           {q4-q5}
415 .else
416         movrel          r12, iadst8_coeffs
417         vld1.16         {q1}, [r12,:128]!
418         vpush           {q4-q7}
419 .endif
420         vld1.16         {q0}, [r12,:128]
421
422         vmov.i16        q2, #0
423         vmov.i16        q3, #0
424
425 .ifc \txfm1\()_\txfm2,idct_idct
426         cmp             r3,  #1
427         bne             1f
428         @ DC-only for idct/idct
429         vld1.16         {d16[]}, [r2,:16]
430         vmull.s16       q8,  d16, d0[0]
431         vrshrn.s32      d16, q8,  #14
432         vmull.s16       q8,  d16, d0[0]
433         vrshrn.s32      d16, q8,  #14
434         vdup.16         q8,  d16[0]
435         vmov            q9,  q8
436         vmov            q10, q8
437         vmov            q11, q8
438         vmov            q12, q8
439         vmov            q13, q8
440         vmov            q14, q8
441         vmov            q15, q8
442         vst1.16         {d4[0]}, [r2,:16]
443         b               2f
444 .endif
445 1:
446         vld1.16         {q8-q9},    [r2,:128]!
447         vld1.16         {q10-q11},  [r2,:128]!
448         vld1.16         {q12-q13},  [r2,:128]!
449         vld1.16         {q14-q15},  [r2,:128]!
450         sub             r2,  r2,  #128
451         vst1.16         {q2-q3}, [r2,:128]!
452         vst1.16         {q2-q3}, [r2,:128]!
453         vst1.16         {q2-q3}, [r2,:128]!
454         vst1.16         {q2-q3}, [r2,:128]!
455
456         \txfm1\()8
457
458         @ Transpose 8x8 with 16 bit elements
459         vswp            d17, d24
460         vswp            d19, d26
461         vswp            d21, d28
462         vswp            d23, d30
463         transpose16_4x4 q8, q9, q10, q11, q12, q13, q14, q15
464
465         \txfm2\()8
466 2:
467         mov             r3,  r0
468         @ Add into the destination
469         vld1.8          {d4},  [r0,:64], r1
470         vrshr.s16       q8,  q8,  #5
471         vld1.8          {d5},  [r0,:64], r1
472         vrshr.s16       q9,  q9,  #5
473         vld1.8          {d6},  [r0,:64], r1
474         vrshr.s16       q10, q10, #5
475         vaddw.u8        q8,  q8,  d4
476         vld1.8          {d7},  [r0,:64], r1
477         vrshr.s16       q11, q11, #5
478         vaddw.u8        q9,  q9,  d5
479         vld1.8          {d8},  [r0,:64], r1
480         vrshr.s16       q12, q12, #5
481         vaddw.u8        q10, q10, d6
482         vqmovun.s16     d4,  q8
483         vld1.8          {d9},  [r0,:64], r1
484         vrshr.s16       q13, q13, #5
485         vaddw.u8        q11, q11, d7
486         vqmovun.s16     d5,  q9
487         vld1.8          {d10}, [r0,:64], r1
488         vrshr.s16       q14, q14, #5
489         vaddw.u8        q12, q12, d8
490         vqmovun.s16     d6,  q10
491         vld1.8          {d11}, [r0,:64], r1
492         vrshr.s16       q15, q15, #5
493         vaddw.u8        q13, q13, d9
494         vqmovun.s16     d7,  q11
495
496
497         vst1.8          {d4},  [r3,:64], r1
498         vaddw.u8        q14, q14, d10
499         vst1.8          {d5},  [r3,:64], r1
500         vqmovun.s16     d8,  q12
501         vst1.8          {d6},  [r3,:64], r1
502         vaddw.u8        q15, q15, d11
503         vst1.8          {d7},  [r3,:64], r1
504         vqmovun.s16     d9,  q13
505         vst1.8          {d8},  [r3,:64], r1
506         vqmovun.s16     d10, q14
507         vst1.8          {d9},  [r3,:64], r1
508         vqmovun.s16     d11, q15
509
510         vst1.8          {d10}, [r3,:64], r1
511         vst1.8          {d11}, [r3,:64], r1
512
513 .ifc \txfm1\()_\txfm2,idct_idct
514         vpop            {q4-q5}
515 .else
516         vpop            {q4-q7}
517 .endif
518         bx              lr
519 endfunc
520 .endm
521
522 itxfm_func8x8 idct,  idct
523 itxfm_func8x8 iadst, idct
524 .ltorg
525 itxfm_func8x8 idct,  iadst
526 itxfm_func8x8 iadst, iadst
527
528
529 function idct16x16_dc_add_neon
530         movrel          r12, idct_coeffs
531         vld1.16         {d0}, [r12,:64]
532
533         vmov.i16        q2, #0
534
535         vld1.16         {d16[]}, [r2,:16]
536         vmull.s16       q8,  d16, d0[0]
537         vrshrn.s32      d16, q8,  #14
538         vmull.s16       q8,  d16, d0[0]
539         vrshrn.s32      d16, q8,  #14
540         vdup.16         q8,  d16[0]
541         vst1.16         {d4[0]}, [r2,:16]
542
543         vrshr.s16       q8,  q8,  #6
544
545         mov             r12, #16
546 1:
547         @ Loop to add the constant from q8 into all 16x16 outputs
548         vld1.8          {q3},  [r0,:128]
549         vaddw.u8        q10, q8,  d6
550         vaddw.u8        q11, q8,  d7
551         vqmovun.s16     d6,  q10
552         vqmovun.s16     d7,  q11
553         vst1.8          {q3},  [r0,:128], r1
554         subs            r12, r12, #1
555         bne             1b
556
557         bx              lr
558 endfunc
559 .ltorg
560
561 .macro idct16_end
562         butterfly       d18, d7,  d4,  d7                @ d18 = t0a,  d7  = t7a
563         butterfly       d19, d22, d5,  d22               @ d19 = t1a,  d22 = t6
564         butterfly       d4,  d26, d20, d26               @ d4  = t2a,  d26 = t5
565         butterfly       d5,  d6,  d28, d6                @ d5  = t3a,  d6  = t4
566         butterfly       d20, d28, d16, d24               @ d20 = t8a,  d28 = t11a
567         butterfly       d24, d21, d23, d21               @ d24 = t9,   d21 = t10
568         butterfly       d23, d27, d25, d27               @ d23 = t14,  d27 = t13
569         butterfly       d25, d29, d29, d17               @ d25 = t15a, d29 = t12a
570
571         mbutterfly0     d27, d21, d27, d21, d16, d30, q8, q15 @ d27 = t13a, d21 = t10a
572         mbutterfly0     d29, d28, d29, d28, d16, d30, q8, q15 @ d29 = t12,  d28 = t11
573
574         vswp            d27, d29                         @ d27 = t12, d29 = t13a
575         vswp            d28, d27                         @ d28 = t12, d27 = t11
576         butterfly       d16, d31, d18, d25               @ d16 = out[0], d31 = out[15]
577         butterfly       d17, d30, d19, d23               @ d17 = out[1], d30 = out[14]
578         butterfly_r     d25, d22, d22, d24               @ d25 = out[9], d22 = out[6]
579         butterfly       d23, d24, d7,  d20               @ d23 = out[7], d24 = out[8]
580         butterfly       d18, d29, d4,  d29               @ d18 = out[2], d29 = out[13]
581         butterfly       d19, d28, d5,  d28               @ d19 = out[3], d28 = out[12]
582         vmov            d4,  d21                         @ d4  = t10a
583         butterfly       d20, d27, d6,  d27               @ d20 = out[4], d27 = out[11]
584         butterfly       d21, d26, d26, d4                @ d21 = out[5], d26 = out[10]
585         bx              lr
586 .endm
587
588 function idct16
589         mbutterfly0     d16, d24, d16, d24, d4, d6,  q2,  q3 @ d16 = t0a,  d24 = t1a
590         mbutterfly      d20, d28, d0[1], d0[2], q2,  q3  @ d20 = t2a,  d28 = t3a
591         mbutterfly      d18, d30, d0[3], d1[0], q2,  q3  @ d18 = t4a,  d30 = t7a
592         mbutterfly      d26, d22, d1[1], d1[2], q2,  q3  @ d26 = t5a,  d22 = t6a
593         mbutterfly      d17, d31, d1[3], d2[0], q2,  q3  @ d17 = t8a,  d31 = t15a
594         mbutterfly      d25, d23, d2[1], d2[2], q2,  q3  @ d25 = t9a,  d23 = t14a
595         mbutterfly      d21, d27, d2[3], d3[0], q2,  q3  @ d21 = t10a, d27 = t13a
596         mbutterfly      d29, d19, d3[1], d3[2], q2,  q3  @ d29 = t11a, d19 = t12a
597
598         butterfly       d4,  d28, d16, d28               @ d4  = t0,   d28 = t3
599         butterfly       d5,  d20, d24, d20               @ d5  = t1,   d20 = t2
600         butterfly       d6,  d26, d18, d26               @ d6  = t4,   d26 = t5
601         butterfly       d7,  d22, d30, d22               @ d7  = t7,   d22 = t6
602         butterfly       d16, d25, d17, d25               @ d16 = t8,   d25 = t9
603         butterfly       d24, d21, d29, d21               @ d24 = t11,  d21 = t10
604         butterfly       d17, d27, d19, d27               @ d17 = t12,  d27 = t13
605         butterfly       d29, d23, d31, d23               @ d29 = t15,  d23 = t14
606
607         mbutterfly0     d22, d26, d22, d26, d18, d30, q9,  q15  @ d22 = t6a, d26 = t5a
608         mbutterfly      d23, d25, d0[1], d0[2], q9,  q15        @ d23 = t9a,  d25 = t14a
609         mbutterfly      d27, d21, d0[1], d0[2], q9,  q15, neg=1 @ d27 = t13a, d21 = t10a
610         idct16_end
611 endfunc
612
613 function idct16_half
614         mbutterfly0_h   d16, d24, d16, d24, d4, d6,  q2,  q3 @ d16 = t0a,  d24 = t1a
615         mbutterfly_h1   d20, d28, d0[1], d0[2], q2,  q3  @ d20 = t2a,  d28 = t3a
616         mbutterfly_h1   d18, d30, d0[3], d1[0], q2,  q3  @ d18 = t4a,  d30 = t7a
617         mbutterfly_h2   d26, d22, d1[1], d1[2], q2,  q3  @ d26 = t5a,  d22 = t6a
618         mbutterfly_h1   d17, d31, d1[3], d2[0], q2,  q3  @ d17 = t8a,  d31 = t15a
619         mbutterfly_h2   d25, d23, d2[1], d2[2], q2,  q3  @ d25 = t9a,  d23 = t14a
620         mbutterfly_h1   d21, d27, d2[3], d3[0], q2,  q3  @ d21 = t10a, d27 = t13a
621         mbutterfly_h2   d29, d19, d3[1], d3[2], q2,  q3  @ d29 = t11a, d19 = t12a
622
623         butterfly       d4,  d28, d16, d28               @ d4  = t0,   d28 = t3
624         butterfly       d5,  d20, d24, d20               @ d5  = t1,   d20 = t2
625         butterfly       d6,  d26, d18, d26               @ d6  = t4,   d26 = t5
626         butterfly       d7,  d22, d30, d22               @ d7  = t7,   d22 = t6
627         butterfly       d16, d25, d17, d25               @ d16 = t8,   d25 = t9
628         butterfly       d24, d21, d29, d21               @ d24 = t11,  d21 = t10
629         butterfly       d17, d27, d19, d27               @ d17 = t12,  d27 = t13
630         butterfly       d29, d23, d31, d23               @ d29 = t15,  d23 = t14
631
632         mbutterfly0     d22, d26, d22, d26, d18, d30, q9,  q15  @ d22 = t6a, d26 = t5a
633         mbutterfly      d23, d25, d0[1], d0[2], q9,  q15        @ d23 = t9a,  d25 = t14a
634         mbutterfly      d27, d21, d0[1], d0[2], q9,  q15, neg=1 @ d27 = t13a, d21 = t10a
635         idct16_end
636 endfunc
637
638 function idct16_quarter
639         vmull.s16       q12, d19, d3[2]
640         vmull.s16       q2,  d17, d1[3]
641         vmull.s16       q3,  d18, d1[0]
642         vmull.s16       q15, d18, d0[3]
643         vneg.s32        q12, q12
644         vmull.s16       q14, d17, d2[0]
645         vmull.s16       q13, d19, d3[1]
646         vmull.s16       q11, d16, d0[0]
647         vrshrn.s32      d24, q12, #14
648         vrshrn.s32      d16, q2,  #14
649         vrshrn.s32      d7,  q3,  #14
650         vrshrn.s32      d6,  q15, #14
651         vrshrn.s32      d29, q14, #14
652         vrshrn.s32      d17, q13, #14
653         vrshrn.s32      d28, q11, #14
654
655         mbutterfly_l    q10, q11, d17, d24, d0[1], d0[2]
656         mbutterfly_l    q9,  q15, d29, d16, d0[1], d0[2]
657         vneg.s32        q11, q11
658         vrshrn.s32      d27, q10, #14
659         vrshrn.s32      d21, q11, #14
660         vrshrn.s32      d23, q9,  #14
661         vrshrn.s32      d25, q15, #14
662         vmov            d4,  d28
663         vmov            d5,  d28
664         mbutterfly0     d22, d26, d7,  d6,  d18, d30, q9,  q15
665         vmov            d20, d28
666         idct16_end
667 endfunc
668
669 function iadst16
670         movrel          r12, iadst16_coeffs
671         vld1.16         {q0-q1}, [r12,:128]
672
673         mbutterfly_l    q3,  q2,  d31, d16, d0[1], d0[0] @ q3  = t1,   q2  = t0
674         mbutterfly_l    q5,  q4,  d23, d24, d2[1], d2[0] @ q5  = t9,   q4  = t8
675         butterfly_n     d31, d24, q3,  q5,  q6,  q5      @ d31 = t1a,  d24 = t9a
676         mbutterfly_l    q7,  q6,  d29, d18, d0[3], d0[2] @ q7  = t3,   q6  = t2
677         butterfly_n     d16, d23, q2,  q4,  q3,  q4      @ d16 = t0a,  d23 = t8a
678
679         mbutterfly_l    q3,  q2,  d21, d26, d2[3], d2[2] @ q3  = t11,  q2  = t10
680         butterfly_n     d29, d26, q7,  q3,  q4,  q3      @ d29 = t3a,  d26 = t11a
681         mbutterfly_l    q5,  q4,  d27, d20, d1[1], d1[0] @ q5  = t5,   q4  = t4
682         butterfly_n     d18, d21, q6,  q2,  q3,  q2      @ d18 = t2a,  d21 = t10a
683
684         mbutterfly_l    q7,  q6,  d19, d28, d3[1], d3[0] @ q7  = t13,  q6  = t12
685         butterfly_n     d20, d28, q5,  q7,  q2,  q7      @ d20 = t5a,  d28 = t13a
686         mbutterfly_l    q3,  q2,  d25, d22, d1[3], d1[2] @ q3  = t7,   q2  = t6
687         butterfly_n     d27, d19, q4,  q6,  q5,  q6      @ d27 = t4a,  d19 = t12a
688
689         mbutterfly_l    q5,  q4,  d17, d30, d3[3], d3[2] @ q5  = t15,  q4  = t14
690         movrel          r12, idct_coeffs
691         vld1.16         {q0}, [r12,:128]
692         butterfly_n     d22, d30, q3,  q5,  q6,  q5      @ d22 = t7a,  d30 = t15a
693         mbutterfly_l    q7,  q6,  d23, d24, d0[3], d1[0] @ q7  = t9,   q6  = t8
694         butterfly_n     d25, d17, q2,  q4,  q3,  q4      @ d25 = t6a,  d17 = t14a
695
696         mbutterfly_l    q2,  q3,  d28, d19, d1[0], d0[3] @ q2  = t12,  q3  = t13
697         butterfly_n     d23, d19, q6,  q2,  q4,  q2      @ d23 = t8a,  d19 = t12a
698         mbutterfly_l    q5,  q4,  d21, d26, d1[1], d1[2] @ q5  = t11,  q4  = t10
699         butterfly_r     d4,  d27, d16, d27               @ d4  = t4,   d27 = t0
700         butterfly_n     d24, d28, q7,  q3,  q6,  q3      @ d24 = t9a,  d28 = t13a
701
702         mbutterfly_l    q6,  q7,  d30, d17, d1[2], d1[1] @ q6  = t14,  q7  = t15
703         butterfly_r     d5,  d20, d31, d20               @ d5  = t5,   d20 = t1
704         butterfly_n     d21, d17, q4,  q6,  q3,  q6      @ d21 = t10a, d17 = t14a
705         butterfly_n     d26, d30, q5,  q7,  q4,  q7      @ d26 = t11a, d30 = t15a
706
707         butterfly_r     d6,  d25, d18, d25               @ d6  = t6,   d25 = t2
708         butterfly_r     d7,  d22, d29, d22               @ d7  = t7,   d22 = t3
709
710         mbutterfly_l    q5,  q4,  d19, d28, d0[1], d0[2] @ q5  = t13,  q4  = t12
711         mbutterfly_l    q6,  q7,  d30, d17, d0[2], d0[1] @ q6  = t14,  q7  = t15
712
713         butterfly_n     d18, d30, q4,  q6,  q8,  q6      @ d18 = out[2],   d30 = t14a
714         butterfly_n     d29, d17, q5,  q7,  q6,  q7      @ d29 = -out[13], d17 = t15a
715         vneg.s16        d29, d29                         @ d29 = out[13]
716
717         mbutterfly_l    q5,  q4,  d4,  d5,  d0[1], d0[2] @ q5  = t5a,  q4  = t4a
718         mbutterfly_l    q6,  q7,  d7,  d6,  d0[2], d0[1] @ q6  = t6a,  q7  = t7a
719
720         butterfly       d2,  d6,  d27, d25               @ d2 = out[0], d6 = t2a
721         butterfly       d3,  d7,  d23, d21               @ d3 =-out[1], d7 = t10
722
723         butterfly_n     d19, d31, q4,  q6,  q2,  q4      @ d19 = -out[3],  d31 = t6
724         vneg.s16        d19, d19                         @ d19 = out[3]
725         butterfly_n     d28, d16, q5,  q7,  q2,  q5      @ d28 = out[12],  d16 = t7
726
727         butterfly       d5,  d8,  d20, d22               @ d5 =-out[15],d8 = t3a
728         butterfly       d4,  d9,  d24, d26               @ d4 = out[14],d9 = t11
729
730         mbutterfly0     d23, d24, d6,  d8,  d10, d11, q6,  q7, 1 @ d23 = out[7], d24 = out[8]
731         mbutterfly0     d20, d27, d16, d31, d10, d11, q6,  q7    @ d20 = out[4], d27 = out[11]
732         mbutterfly0     d22, d25, d9,  d7,  d10, d11, q6,  q7    @ d22 = out[6], d25 = out[9]
733         mbutterfly0     d21, d26, d30, d17, d10, d11, q6,  q7, 1 @ d21 = out[5], d26 = out[10]
734
735         vneg.s16        d31, d5                          @ d31 = out[15]
736         vneg.s16        d17, d3                          @ d17 = out[1]
737
738         vmov            d16, d2
739         vmov            d30, d4
740         bx              lr
741 endfunc
742
743 .macro load_add_store coef0, coef1, coef2, coef3
744         vrshr.s16       \coef0, \coef0, #6
745         vrshr.s16       \coef1, \coef1, #6
746
747         vld1.32         {d4[]},   [r0,:32], r1
748         vld1.32         {d4[1]},  [r3,:32], r1
749         vrshr.s16       \coef2, \coef2, #6
750         vrshr.s16       \coef3, \coef3, #6
751         vld1.32         {d5[]},   [r0,:32], r1
752         vld1.32         {d5[1]},  [r3,:32], r1
753         vaddw.u8        \coef0, \coef0, d4
754         vld1.32         {d6[]},   [r0,:32], r1
755         vld1.32         {d6[1]},  [r3,:32], r1
756         vaddw.u8        \coef1, \coef1, d5
757         vld1.32         {d7[]},   [r0,:32], r1
758         vld1.32         {d7[1]},  [r3,:32], r1
759
760         vqmovun.s16     d4,  \coef0
761         vqmovun.s16     d5,  \coef1
762         sub             r0,  r0,  r1, lsl #2
763         sub             r3,  r3,  r1, lsl #2
764         vaddw.u8        \coef2, \coef2, d6
765         vaddw.u8        \coef3, \coef3, d7
766         vst1.32         {d4[0]},  [r0,:32], r1
767         vst1.32         {d4[1]},  [r3,:32], r1
768         vqmovun.s16     d6,  \coef2
769         vst1.32         {d5[0]},  [r0,:32], r1
770         vst1.32         {d5[1]},  [r3,:32], r1
771         vqmovun.s16     d7,  \coef3
772
773         vst1.32         {d6[0]},  [r0,:32], r1
774         vst1.32         {d6[1]},  [r3,:32], r1
775         vst1.32         {d7[0]},  [r0,:32], r1
776         vst1.32         {d7[1]},  [r3,:32], r1
777 .endm
778
779 .macro itxfm16_1d_funcs txfm
780 @ Read a vertical 4x16 slice out of a 16x16 matrix, do a transform on it,
781 @ transpose into a horizontal 16x4 slice and store.
782 @ r0 = dst (temp buffer)
783 @ r1 = slice offset
784 @ r2 = src
785 function \txfm\()16_1d_4x16_pass1_neon
786         push            {lr}
787
788         mov             r12, #32
789         vmov.s16        q2, #0
790 .irp i, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31
791         vld1.16         {d\i}, [r2,:64]
792         vst1.16         {d4},  [r2,:64], r12
793 .endr
794
795         bl              \txfm\()16
796
797         @ Do four 4x4 transposes. Originally, d16-d31 contain the
798         @ 16 rows. Afterwards, d16-d19, d20-d23, d24-d27, d28-d31
799         @ contain the transposed 4x4 blocks.
800         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
801
802         @ Store the transposed 4x4 blocks horizontally.
803         cmp             r1,  #12
804         beq             1f
805 .irp i, 16, 20, 24, 28, 17, 21, 25, 29, 18, 22, 26, 30, 19, 23, 27, 31
806         vst1.16         {d\i}, [r0,:64]!
807 .endr
808         pop             {pc}
809 1:
810         @ Special case: For the last input column (r1 == 12),
811         @ which would be stored as the last row in the temp buffer,
812         @ don't store the first 4x4 block, but keep it in registers
813         @ for the first slice of the second pass (where it is the
814         @ last 4x4 block).
815         add             r0,  r0,  #8
816         vst1.16         {d20}, [r0,:64]!
817         vst1.16         {d24}, [r0,:64]!
818         vst1.16         {d28}, [r0,:64]!
819         add             r0,  r0,  #8
820         vst1.16         {d21}, [r0,:64]!
821         vst1.16         {d25}, [r0,:64]!
822         vst1.16         {d29}, [r0,:64]!
823         add             r0,  r0,  #8
824         vst1.16         {d22}, [r0,:64]!
825         vst1.16         {d26}, [r0,:64]!
826         vst1.16         {d30}, [r0,:64]!
827         add             r0,  r0,  #8
828         vst1.16         {d23}, [r0,:64]!
829         vst1.16         {d27}, [r0,:64]!
830         vst1.16         {d31}, [r0,:64]!
831         vmov            d28, d16
832         vmov            d29, d17
833         vmov            d30, d18
834         vmov            d31, d19
835         pop             {pc}
836 endfunc
837
838 @ Read a vertical 4x16 slice out of a 16x16 matrix, do a transform on it,
839 @ load the destination pixels (from a similar 4x16 slice), add and store back.
840 @ r0 = dst
841 @ r1 = dst stride
842 @ r2 = src (temp buffer)
843 @ r3 = slice offset
844 function \txfm\()16_1d_4x16_pass2_neon
845         push            {lr}
846         mov             r12, #32
847 .irp i, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27
848         vld1.16         {d\i}, [r2,:64], r12
849 .endr
850         cmp             r3,  #0
851         beq             1f
852 .irp i, 28, 29, 30, 31
853         vld1.16         {d\i}, [r2,:64], r12
854 .endr
855 1:
856
857         add             r3,  r0,  r1
858         lsl             r1,  r1,  #1
859         bl              \txfm\()16
860
861         load_add_store  q8,  q9,  q10, q11
862         load_add_store  q12, q13, q14, q15
863
864         pop             {pc}
865 endfunc
866 .endm
867
868 itxfm16_1d_funcs idct
869 itxfm16_1d_funcs iadst
870
871 @ This is the minimum eob value for each subpartition, in increments of 4
872 const min_eob_idct_idct_16, align=4
873         .short  0, 10, 38, 89
874 endconst
875
876 .macro itxfm_func16x16 txfm1, txfm2
877 function ff_vp9_\txfm1\()_\txfm2\()_16x16_add_neon, export=1
878 .ifc \txfm1\()_\txfm2,idct_idct
879         cmp             r3,  #1
880         beq             idct16x16_dc_add_neon
881 .endif
882         push            {r4-r8,lr}
883 .ifnc \txfm1\()_\txfm2,idct_idct
884         vpush           {q4-q7}
885 .else
886         movrel          r8,  min_eob_idct_idct_16 + 2
887 .endif
888
889         @ Align the stack, allocate a temp buffer
890 T       mov             r7,  sp
891 T       and             r7,  r7,  #15
892 A       and             r7,  sp,  #15
893         add             r7,  r7,  #512
894         sub             sp,  sp,  r7
895
896         mov             r4,  r0
897         mov             r5,  r1
898         mov             r6,  r2
899
900 .ifc \txfm1,idct
901         movrel          r12, idct_coeffs
902         vld1.16         {q0-q1}, [r12,:128]
903 .endif
904
905 .ifc \txfm1\()_\txfm2,idct_idct
906         cmp             r3,  #10
907         ble             idct16x16_quarter_add_neon
908         cmp             r3,  #38
909         ble             idct16x16_half_add_neon
910 .endif
911
912 .irp i, 0, 4, 8, 12
913         add             r0,  sp,  #(\i*32)
914 .ifc \txfm1\()_\txfm2,idct_idct
915 .if \i > 0
916         ldrh_post       r1,  r8,  #2
917         cmp             r3,  r1
918         it              le
919         movle           r1,  #(16 - \i)/4
920         ble             1f
921 .endif
922 .endif
923         mov             r1,  #\i
924         add             r2,  r6,  #(\i*2)
925         bl              \txfm1\()16_1d_4x16_pass1_neon
926 .endr
927
928 .ifc \txfm1\()_\txfm2,idct_idct
929         b               3f
930 1:
931         @ For all-zero slices in pass 1, set d28-d31 to zero, for the in-register
932         @ passthrough of coefficients to pass 2 and clear the end of the temp buffer
933         vmov.i16        q14, #0
934         vmov.i16        q15, #0
935 2:
936         subs            r1,  r1,  #1
937 .rept 4
938         vst1.16         {q14-q15}, [r0,:128]!
939 .endr
940         bne             2b
941 3:
942 .endif
943
944 .ifc \txfm1\()_\txfm2,iadst_idct
945         movrel          r12, idct_coeffs
946         vld1.16         {q0-q1}, [r12,:128]
947 .endif
948 .irp i, 0, 4, 8, 12
949         add             r0,  r4,  #(\i)
950         mov             r1,  r5
951         add             r2,  sp,  #(\i*2)
952         mov             r3,  #\i
953         bl              \txfm2\()16_1d_4x16_pass2_neon
954 .endr
955
956         add             sp,  sp,  r7
957 .ifnc \txfm1\()_\txfm2,idct_idct
958         vpop            {q4-q7}
959 .endif
960         pop             {r4-r8,pc}
961 endfunc
962 .endm
963
964 itxfm_func16x16 idct,  idct
965 itxfm_func16x16 iadst, idct
966 itxfm_func16x16 idct,  iadst
967 itxfm_func16x16 iadst, iadst
968 .ltorg
969
970 function idct16_1d_4x16_pass1_quarter_neon
971         push            {lr}
972         mov             r12, #32
973         vmov.s16        q2, #0
974 .irp i, 16, 17, 18, 19
975         vld1.16         {d\i}, [r2,:64]
976         vst1.16         {d4},  [r2,:64], r12
977 .endr
978
979         bl              idct16_quarter
980
981         @ Do four 4x4 transposes. Originally, d16-d31 contain the
982         @ 16 rows. Afterwards, d16-d19, d20-d23, d24-d27, d28-d31
983         @ contain the transposed 4x4 blocks.
984         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
985
986         @ Store the transposed 4x4 blocks horizontally.
987         @ The first 4x4 block is kept in registers for the second pass,
988         @ store the rest in the temp buffer.
989         add             r0,  r0,  #8
990         vst1.16         {d20}, [r0,:64]!
991         vst1.16         {d24}, [r0,:64]!
992         vst1.16         {d28}, [r0,:64]!
993         add             r0,  r0,  #8
994         vst1.16         {d21}, [r0,:64]!
995         vst1.16         {d25}, [r0,:64]!
996         vst1.16         {d29}, [r0,:64]!
997         add             r0,  r0,  #8
998         vst1.16         {d22}, [r0,:64]!
999         vst1.16         {d26}, [r0,:64]!
1000         vst1.16         {d30}, [r0,:64]!
1001         add             r0,  r0,  #8
1002         vst1.16         {d23}, [r0,:64]!
1003         vst1.16         {d27}, [r0,:64]!
1004         vst1.16         {d31}, [r0,:64]!
1005         pop             {pc}
1006 endfunc
1007
1008 function idct16_1d_4x16_pass2_quarter_neon
1009         push            {lr}
1010         @ Only load the top 4 lines, and only do it for the later slices.
1011         @ For the first slice, d16-d19 is kept in registers from the first pass.
1012         cmp             r3,  #0
1013         beq             1f
1014         mov             r12, #32
1015 .irp i, 16, 17, 18, 19
1016         vld1.16         {d\i}, [r2,:64], r12
1017 .endr
1018 1:
1019
1020         add             r3,  r0,  r1
1021         lsl             r1,  r1,  #1
1022         bl              idct16_quarter
1023
1024         load_add_store  q8,  q9,  q10, q11
1025         load_add_store  q12, q13, q14, q15
1026
1027         pop             {pc}
1028 endfunc
1029
1030 function idct16_1d_4x16_pass1_half_neon
1031         push            {lr}
1032         mov             r12, #32
1033         vmov.s16        q2, #0
1034 .irp i, 16, 17, 18, 19, 20, 21, 22, 23
1035         vld1.16         {d\i}, [r2,:64]
1036         vst1.16         {d4},  [r2,:64], r12
1037 .endr
1038
1039         bl              idct16_half
1040
1041         @ Do four 4x4 transposes. Originally, d16-d31 contain the
1042         @ 16 rows. Afterwards, d16-d19, d20-d23, d24-d27, d28-d31
1043         @ contain the transposed 4x4 blocks.
1044         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
1045
1046         @ Store the transposed 4x4 blocks horizontally.
1047         cmp             r1,  #4
1048         beq             1f
1049 .irp i, 16, 20, 24, 28, 17, 21, 25, 29, 18, 22, 26, 30, 19, 23, 27, 31
1050         vst1.16         {d\i}, [r0,:64]!
1051 .endr
1052         pop             {pc}
1053 1:
1054         @ Special case: For the second input column (r1 == 4),
1055         @ which would be stored as the second row in the temp buffer,
1056         @ don't store the first 4x4 block, but keep it in registers
1057         @ for the first slice of the second pass (where it is the
1058         @ second 4x4 block).
1059         add             r0,  r0,  #8
1060         vst1.16         {d20}, [r0,:64]!
1061         vst1.16         {d24}, [r0,:64]!
1062         vst1.16         {d28}, [r0,:64]!
1063         add             r0,  r0,  #8
1064         vst1.16         {d21}, [r0,:64]!
1065         vst1.16         {d25}, [r0,:64]!
1066         vst1.16         {d29}, [r0,:64]!
1067         add             r0,  r0,  #8
1068         vst1.16         {d22}, [r0,:64]!
1069         vst1.16         {d26}, [r0,:64]!
1070         vst1.16         {d30}, [r0,:64]!
1071         add             r0,  r0,  #8
1072         vst1.16         {d23}, [r0,:64]!
1073         vst1.16         {d27}, [r0,:64]!
1074         vst1.16         {d31}, [r0,:64]!
1075         vmov            d20, d16
1076         vmov            d21, d17
1077         vmov            d22, d18
1078         vmov            d23, d19
1079         pop             {pc}
1080 endfunc
1081
1082 function idct16_1d_4x16_pass2_half_neon
1083         push            {lr}
1084         mov             r12, #32
1085         cmp             r3,  #0
1086 .irp i, 16, 17, 18, 19
1087         vld1.16         {d\i}, [r2,:64], r12
1088 .endr
1089         beq             1f
1090 .irp i, 20, 21, 22, 23
1091         vld1.16         {d\i}, [r2,:64], r12
1092 .endr
1093 1:
1094
1095         add             r3,  r0,  r1
1096         lsl             r1,  r1,  #1
1097         bl              idct16_half
1098
1099         load_add_store  q8,  q9,  q10, q11
1100         load_add_store  q12, q13, q14, q15
1101
1102         pop             {pc}
1103 endfunc
1104 .purgem load_add_store
1105
1106 .macro idct16_partial size
1107 function idct16x16_\size\()_add_neon
1108         add             r0,  sp,  #(0*32)
1109         mov             r1,  #0
1110         add             r2,  r6,  #(0*2)
1111         bl              idct16_1d_4x16_pass1_\size\()_neon
1112 .ifc \size,half
1113         add             r0,  sp,  #(4*32)
1114         mov             r1,  #4
1115         add             r2,  r6,  #(4*2)
1116         bl              idct16_1d_4x16_pass1_\size\()_neon
1117 .endif
1118 .irp i, 0, 4, 8, 12
1119         add             r0,  r4,  #(\i)
1120         mov             r1,  r5
1121         add             r2,  sp,  #(\i*2)
1122         mov             r3,  #\i
1123         bl              idct16_1d_4x16_pass2_\size\()_neon
1124 .endr
1125
1126         add             sp,  sp,  r7
1127         pop             {r4-r8,pc}
1128 endfunc
1129 .endm
1130
1131 idct16_partial quarter
1132 idct16_partial half
1133
1134 function idct32x32_dc_add_neon
1135         movrel          r12, idct_coeffs
1136         vld1.16         {d0}, [r12,:64]
1137
1138         vmov.i16        q2, #0
1139
1140         vld1.16         {d16[]}, [r2,:16]
1141         vmull.s16       q8,  d16, d0[0]
1142         vrshrn.s32      d16, q8,  #14
1143         vmull.s16       q8,  d16, d0[0]
1144         vrshrn.s32      d16, q8,  #14
1145         vdup.16         q8,  d16[0]
1146         vst1.16         {d4[0]}, [r2,:16]
1147
1148         vrshr.s16       q8,  q8,  #6
1149
1150         mov             r12, #32
1151 1:
1152         @ Loop to add the constant from q8 into all 32x32 outputs
1153         vld1.8          {q2-q3},  [r0,:128]
1154         vaddw.u8        q10, q8,  d4
1155         vaddw.u8        q11, q8,  d5
1156         vaddw.u8        q12, q8,  d6
1157         vaddw.u8        q13, q8,  d7
1158         vqmovun.s16     d4,  q10
1159         vqmovun.s16     d5,  q11
1160         vqmovun.s16     d6,  q12
1161         vqmovun.s16     d7,  q13
1162         vst1.8          {q2-q3},  [r0,:128], r1
1163         subs            r12, r12, #1
1164         bne             1b
1165
1166         bx              lr
1167 endfunc
1168
1169 .macro idct32_end
1170         butterfly       d16, d5,  d4,  d5  @ d16 = t16a, d5  = t19a
1171         butterfly       d17, d20, d23, d20 @ d17 = t17,  d20 = t18
1172         butterfly       d18, d6,  d7,  d6  @ d18 = t23a, d6  = t20a
1173         butterfly       d19, d21, d22, d21 @ d19 = t22,  d21 = t21
1174         butterfly       d4,  d28, d28, d30 @ d4  = t24a, d28 = t27a
1175         butterfly       d23, d26, d25, d26 @ d23 = t25,  d26 = t26
1176         butterfly       d7,  d29, d29, d31 @ d7  = t31a, d29 = t28a
1177         butterfly       d22, d27, d24, d27 @ d22 = t30,  d27 = t29
1178
1179         mbutterfly      d27, d20, d0[1], d0[2], q12, q15        @ d27 = t18a, d20 = t29a
1180         mbutterfly      d29, d5,  d0[1], d0[2], q12, q15        @ d29 = t19,  d5  = t28
1181         mbutterfly      d28, d6,  d0[1], d0[2], q12, q15, neg=1 @ d28 = t27,  d6  = t20
1182         mbutterfly      d26, d21, d0[1], d0[2], q12, q15, neg=1 @ d26 = t26a, d21 = t21a
1183
1184         butterfly       d31, d24, d7,  d4  @ d31 = t31,  d24 = t24
1185         butterfly       d30, d25, d22, d23 @ d30 = t30a, d25 = t25a
1186         butterfly_r     d23, d16, d16, d18 @ d23 = t23,  d16 = t16
1187         butterfly_r     d22, d17, d17, d19 @ d22 = t22a, d17 = t17a
1188         butterfly       d18, d21, d27, d21 @ d18 = t18,  d21 = t21
1189         butterfly_r     d27, d28, d5,  d28 @ d27 = t27a, d28 = t28a
1190         butterfly       d4,  d26, d20, d26 @ d4  = t29,  d26 = t26
1191         butterfly       d19, d20, d29, d6  @ d19 = t19a, d20 = t20
1192         vmov            d29, d4            @ d29 = t29
1193
1194         mbutterfly0     d27, d20, d27, d20, d4, d6, q2, q3 @ d27 = t27,  d20 = t20
1195         mbutterfly0     d26, d21, d26, d21, d4, d6, q2, q3 @ d26 = t26a, d21 = t21a
1196         mbutterfly0     d25, d22, d25, d22, d4, d6, q2, q3 @ d25 = t25,  d22 = t22
1197         mbutterfly0     d24, d23, d24, d23, d4, d6, q2, q3 @ d24 = t24a, d23 = t23a
1198         bx              lr
1199 .endm
1200
1201 function idct32_odd
1202         movrel          r12, idct_coeffs
1203         add             r12, r12, #32
1204         vld1.16         {q0-q1}, [r12,:128]
1205
1206         mbutterfly      d16, d31, d0[0], d0[1], q2, q3 @ d16 = t16a, d31 = t31a
1207         mbutterfly      d24, d23, d0[2], d0[3], q2, q3 @ d24 = t17a, d23 = t30a
1208         mbutterfly      d20, d27, d1[0], d1[1], q2, q3 @ d20 = t18a, d27 = t29a
1209         mbutterfly      d28, d19, d1[2], d1[3], q2, q3 @ d28 = t19a, d19 = t28a
1210         mbutterfly      d18, d29, d2[0], d2[1], q2, q3 @ d18 = t20a, d29 = t27a
1211         mbutterfly      d26, d21, d2[2], d2[3], q2, q3 @ d26 = t21a, d21 = t26a
1212         mbutterfly      d22, d25, d3[0], d3[1], q2, q3 @ d22 = t22a, d25 = t25a
1213         mbutterfly      d30, d17, d3[2], d3[3], q2, q3 @ d30 = t23a, d17 = t24a
1214
1215         sub             r12, r12, #32
1216         vld1.16         {q0}, [r12,:128]
1217
1218         butterfly       d4,  d24, d16, d24 @ d4  = t16, d24 = t17
1219         butterfly       d5,  d20, d28, d20 @ d5  = t19, d20 = t18
1220         butterfly       d6,  d26, d18, d26 @ d6  = t20, d26 = t21
1221         butterfly       d7,  d22, d30, d22 @ d7  = t23, d22 = t22
1222         butterfly       d28, d25, d17, d25 @ d28 = t24, d25 = t25
1223         butterfly       d30, d21, d29, d21 @ d30 = t27, d21 = t26
1224         butterfly       d29, d23, d31, d23 @ d29 = t31, d23 = t30
1225         butterfly       d31, d27, d19, d27 @ d31 = t28, d27 = t29
1226
1227         mbutterfly      d23, d24, d0[3], d1[0], q8, q9        @ d23 = t17a, d24 = t30a
1228         mbutterfly      d27, d20, d0[3], d1[0], q8, q9, neg=1 @ d27 = t29a, d20 = t18a
1229         mbutterfly      d21, d26, d1[1], d1[2], q8, q9        @ d21 = t21a, d26 = t26a
1230         mbutterfly      d25, d22, d1[1], d1[2], q8, q9, neg=1 @ d25 = t25a, d22 = t22a
1231         idct32_end
1232 endfunc
1233
1234 function idct32_odd_half
1235         movrel          r12, idct_coeffs
1236         add             r12, r12, #32
1237         vld1.16         {q0-q1}, [r12,:128]
1238
1239         mbutterfly_h1   d16, d31, d0[0], d0[1], q2, q3 @ d16 = t16a, d31 = t31a
1240         mbutterfly_h2   d24, d23, d0[2], d0[3], q2, q3 @ d24 = t17a, d23 = t30a
1241         mbutterfly_h1   d20, d27, d1[0], d1[1], q2, q3 @ d20 = t18a, d27 = t29a
1242         mbutterfly_h2   d28, d19, d1[2], d1[3], q2, q3 @ d28 = t19a, d19 = t28a
1243         mbutterfly_h1   d18, d29, d2[0], d2[1], q2, q3 @ d18 = t20a, d29 = t27a
1244         mbutterfly_h2   d26, d21, d2[2], d2[3], q2, q3 @ d26 = t21a, d21 = t26a
1245         mbutterfly_h1   d22, d25, d3[0], d3[1], q2, q3 @ d22 = t22a, d25 = t25a
1246         mbutterfly_h2   d30, d17, d3[2], d3[3], q2, q3 @ d30 = t23a, d17 = t24a
1247
1248         sub             r12, r12, #32
1249         vld1.16         {q0}, [r12,:128]
1250
1251         butterfly       d4,  d24, d16, d24 @ d4  = t16, d24 = t17
1252         butterfly       d5,  d20, d28, d20 @ d5  = t19, d20 = t18
1253         butterfly       d6,  d26, d18, d26 @ d6  = t20, d26 = t21
1254         butterfly       d7,  d22, d30, d22 @ d7  = t23, d22 = t22
1255         butterfly       d28, d25, d17, d25 @ d28 = t24, d25 = t25
1256         butterfly       d30, d21, d29, d21 @ d30 = t27, d21 = t26
1257         butterfly       d29, d23, d31, d23 @ d29 = t31, d23 = t30
1258         butterfly       d31, d27, d19, d27 @ d31 = t28, d27 = t29
1259
1260         mbutterfly      d23, d24, d0[3], d1[0], q8, q9        @ d23 = t17a, d24 = t30a
1261         mbutterfly      d27, d20, d0[3], d1[0], q8, q9, neg=1 @ d27 = t29a, d20 = t18a
1262         mbutterfly      d21, d26, d1[1], d1[2], q8, q9        @ d21 = t21a, d26 = t26a
1263         mbutterfly      d25, d22, d1[1], d1[2], q8, q9, neg=1 @ d25 = t25a, d22 = t22a
1264
1265         idct32_end
1266 endfunc
1267
1268 function idct32_odd_quarter
1269         movrel          r12, idct_coeffs
1270         add             r12, r12, #32
1271         vld1.16         {q0-q1}, [r12,:128]
1272
1273         vmull.s16       q2,  d16, d0[0]
1274         vmull.s16       q14, d19, d1[3]
1275         vmull.s16       q15, d16, d0[1]
1276         vmull.s16       q11, d17, d3[2]
1277         vmull.s16       q3,  d17, d3[3]
1278         vmull.s16       q13, d19, d1[2]
1279         vmull.s16       q10, d18, d2[0]
1280         vmull.s16       q12, d18, d2[1]
1281
1282         sub             r12, r12, #32
1283         vld1.16         {q0}, [r12,:128]
1284
1285         vneg.s32        q14, q14
1286         vneg.s32        q3,  q3
1287
1288         vrshrn.s32      d4,  q2,  #14
1289         vrshrn.s32      d5,  q14, #14
1290         vrshrn.s32      d29, q15, #14
1291         vrshrn.s32      d28, q11, #14
1292         vrshrn.s32      d7,  q3,  #14
1293         vrshrn.s32      d31, q13, #14
1294         vrshrn.s32      d6,  q10, #14
1295         vrshrn.s32      d30, q12, #14
1296
1297         mbutterfly_l    q8,  q9,  d29, d4,  d0[3], d1[0]
1298         mbutterfly_l    q13, q10, d31, d5,  d0[3], d1[0]
1299         vrshrn.s32      d23, q8,  #14
1300         vrshrn.s32      d24, q9,  #14
1301         vneg.s32        q10, q10
1302         vrshrn.s32      d27, q13, #14
1303         vrshrn.s32      d20, q10, #14
1304         mbutterfly_l    q8,  q9,  d30, d6,  d1[1], d1[2]
1305         vrshrn.s32      d21, q8,  #14
1306         vrshrn.s32      d26, q9,  #14
1307         mbutterfly_l    q8,  q9,  d28, d7,  d1[1], d1[2]
1308         vrshrn.s32      d25, q8,  #14
1309         vneg.s32        q9,  q9
1310         vrshrn.s32      d22, q9,  #14
1311
1312         idct32_end
1313 endfunc
1314
1315 .macro idct32_funcs suffix
1316 @ Do an 32-point IDCT of a 4x32 slice out of a 32x32 matrix.
1317 @ We don't have register space to do a single pass IDCT of 4x32 though,
1318 @ but the 32-point IDCT can be decomposed into two 16-point IDCTs;
1319 @ a normal IDCT16 with every other input component (the even ones, with
1320 @ each output written twice), followed by a separate 16-point IDCT
1321 @ of the odd inputs, added/subtracted onto the outputs of the first idct16.
1322 @ r0 = dst (temp buffer)
1323 @ r1 = unused
1324 @ r2 = src
1325 function idct32_1d_4x32_pass1\suffix\()_neon
1326         push            {lr}
1327
1328         movrel          r12, idct_coeffs
1329         vld1.16         {q0-q1}, [r12,:128]
1330
1331         @ Double stride of the input, since we only read every other line
1332         mov             r12, #128
1333         vmov.s16        d4, #0
1334
1335         @ d16 = IN(0), d17 = IN(2) ... d31 = IN(30)
1336 .ifb \suffix
1337 .irp i, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31
1338         vld1.16         {d\i}, [r2,:64]
1339         vst1.16         {d4},  [r2,:64], r12
1340 .endr
1341 .endif
1342 .ifc \suffix,_quarter
1343 .irp i, 16, 17, 18, 19
1344         vld1.16         {d\i}, [r2,:64]
1345         vst1.16         {d4},  [r2,:64], r12
1346 .endr
1347 .endif
1348 .ifc \suffix,_half
1349 .irp i, 16, 17, 18, 19, 20, 21, 22, 23
1350         vld1.16         {d\i}, [r2,:64]
1351         vst1.16         {d4},  [r2,:64], r12
1352 .endr
1353 .endif
1354
1355         bl              idct16\suffix
1356
1357         @ Do four 4x4 transposes. Originally, d16-d31 contain the
1358         @ 16 rows. Afterwards, d16-d19, d20-d23, d24-d27, d28-d31
1359         @ contain the transposed 4x4 blocks.
1360         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
1361         @ Store the registers a, b, c, d horizontally, followed
1362         @ by the same registers d, c, b, a mirrored.
1363 .macro store_rev a, b, c, d
1364 .irp i, \a, \b, \c, \d
1365         vst1.16         {d\i}, [r0,:64]!
1366         vrev64.16       d\i, d\i
1367 .endr
1368 .irp i, \d, \c, \b, \a
1369         vst1.16         {d\i}, [r0,:64]!
1370 .endr
1371 .endm
1372         store_rev       16, 20, 24, 28
1373         store_rev       17, 21, 25, 29
1374         store_rev       18, 22, 26, 30
1375         store_rev       19, 23, 27, 31
1376         sub             r0,  r0,  #256
1377 .purgem store_rev
1378
1379         @ Move r2 back to the start of the input, and move
1380         @ to the first odd row
1381 .ifb \suffix
1382         sub             r2,  r2,  r12, lsl #4
1383 .endif
1384 .ifc \suffix,_quarter
1385         sub             r2,  r2,  r12, lsl #2
1386 .endif
1387 .ifc \suffix,_half
1388         sub             r2,  r2,  r12, lsl #3
1389 .endif
1390         add             r2,  r2,  #64
1391
1392         vmov.s16        d4, #0
1393         @ d16 = IN(1), d17 = IN(3) ... d31 = IN(31)
1394 .ifb \suffix
1395 .irp i, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31
1396         vld1.16         {d\i}, [r2,:64]
1397         vst1.16         {d4},  [r2,:64], r12
1398 .endr
1399 .endif
1400 .ifc \suffix,_quarter
1401 .irp i, 16, 17, 18, 19
1402         vld1.16         {d\i}, [r2,:64]
1403         vst1.16         {d4},  [r2,:64], r12
1404 .endr
1405 .endif
1406 .ifc \suffix,_half
1407 .irp i, 16, 17, 18, 19, 20, 21, 22, 23
1408         vld1.16         {d\i}, [r2,:64]
1409         vst1.16         {d4},  [r2,:64], r12
1410 .endr
1411 .endif
1412
1413         bl              idct32_odd\suffix
1414
1415         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
1416
1417         @ Store the registers a, b, c, d horizontally,
1418         @ adding into the output first, and then mirrored, subtracted
1419         @ from the output.
1420 .macro store_rev a, b, c, d
1421 .irp i, \a, \b, \c, \d
1422         vld1.16         {d4},  [r0,:64]
1423         vadd.s16        d4, d4, d\i
1424         vst1.16         {d4},  [r0,:64]!
1425         vrev64.16       d\i, d\i
1426 .endr
1427 .irp i, \d, \c, \b, \a
1428         vld1.16         {d4},  [r0,:64]
1429         vsub.s16        d4, d4, d\i
1430         vst1.16         {d4},  [r0,:64]!
1431 .endr
1432 .endm
1433
1434         store_rev       31, 27, 23, 19
1435         store_rev       30, 26, 22, 18
1436         store_rev       29, 25, 21, 17
1437         store_rev       28, 24, 20, 16
1438 .purgem store_rev
1439         pop             {pc}
1440 endfunc
1441 .ltorg
1442
1443 @ This is mostly the same as 4x32_pass1, but without the transpose,
1444 @ and use the source as temp buffer between the two idct passes, and
1445 @ add into the destination.
1446 @ r0 = dst
1447 @ r1 = dst stride
1448 @ r2 = src (temp buffer)
1449 function idct32_1d_4x32_pass2\suffix\()_neon
1450         push            {lr}
1451         movrel          r12, idct_coeffs
1452         vld1.16         {q0-q1}, [r12,:128]
1453
1454         mov             r12, #128
1455         @ d16 = IN(0), d17 = IN(2) ... d31 = IN(30)
1456 .ifb \suffix
1457 .irp i, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31
1458         vld1.16         {d\i}, [r2,:64], r12
1459 .endr
1460         sub             r2,  r2,  r12, lsl #4
1461 .endif
1462 .ifc \suffix,_quarter
1463 .irp i, 16, 17, 18, 19
1464         vld1.16         {d\i}, [r2,:64], r12
1465 .endr
1466         sub             r2,  r2,  r12, lsl #2
1467 .endif
1468 .ifc \suffix,_half
1469 .irp i, 16, 17, 18, 19, 20, 21, 22, 23
1470         vld1.16         {d\i}, [r2,:64], r12
1471 .endr
1472         sub             r2,  r2,  r12, lsl #3
1473 .endif
1474
1475         bl              idct16\suffix
1476
1477 .irp i, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31
1478         vst1.16         {d\i}, [r2,:64], r12
1479 .endr
1480
1481         sub             r2,  r2,  r12, lsl #4
1482         add             r2,  r2,  #64
1483
1484         @ d16 = IN(1), d17 = IN(3) ... d31 = IN(31)
1485 .ifb \suffix
1486 .irp i, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31
1487         vld1.16         {d\i}, [r2,:64], r12
1488 .endr
1489         sub             r2,  r2,  r12, lsl #4
1490 .endif
1491 .ifc \suffix,_quarter
1492 .irp i, 16, 17, 18, 19
1493         vld1.16         {d\i}, [r2,:64], r12
1494 .endr
1495         sub             r2,  r2,  r12, lsl #2
1496 .endif
1497 .ifc \suffix,_half
1498 .irp i, 16, 17, 18, 19, 20, 21, 22, 23
1499         vld1.16         {d\i}, [r2,:64], r12
1500 .endr
1501         sub             r2,  r2,  r12, lsl #3
1502 .endif
1503         sub             r2,  r2,  #64
1504
1505         bl              idct32_odd\suffix
1506
1507         mov             r12, #128
1508 .macro load_acc_store a, b, c, d, neg=0
1509         vld1.16         {d4},  [r2,:64], r12
1510         vld1.16         {d5},  [r2,:64], r12
1511 .if \neg == 0
1512         vadd.s16        d4, d4, d\a
1513         vld1.16         {d6},  [r2,:64], r12
1514         vadd.s16        d5, d5, d\b
1515         vld1.16         {d7},  [r2,:64], r12
1516         vadd.s16        d6, d6, d\c
1517         vadd.s16        d7, d7, d\d
1518 .else
1519         vsub.s16        d4, d4, d\a
1520         vld1.16         {d6},  [r2,:64], r12
1521         vsub.s16        d5, d5, d\b
1522         vld1.16         {d7},  [r2,:64], r12
1523         vsub.s16        d6, d6, d\c
1524         vsub.s16        d7, d7, d\d
1525 .endif
1526         vld1.32         {d2[]},   [r0,:32], r1
1527         vld1.32         {d2[1]},  [r0,:32], r1
1528         vrshr.s16       q2, q2, #6
1529         vld1.32         {d3[]},   [r0,:32], r1
1530         vrshr.s16       q3, q3, #6
1531         vld1.32         {d3[1]},  [r0,:32], r1
1532         sub             r0,  r0,  r1, lsl #2
1533         vaddw.u8        q2,  q2,  d2
1534         vaddw.u8        q3,  q3,  d3
1535         vqmovun.s16     d4,  q2
1536         vqmovun.s16     d5,  q3
1537         vst1.32         {d4[0]},  [r0,:32], r1
1538         vst1.32         {d4[1]},  [r0,:32], r1
1539         vst1.32         {d5[0]},  [r0,:32], r1
1540         vst1.32         {d5[1]},  [r0,:32], r1
1541 .endm
1542         load_acc_store  31, 30, 29, 28
1543         load_acc_store  27, 26, 25, 24
1544         load_acc_store  23, 22, 21, 20
1545         load_acc_store  19, 18, 17, 16
1546         sub             r2,  r2,  r12
1547         neg             r12, r12
1548         load_acc_store  16, 17, 18, 19, 1
1549         load_acc_store  20, 21, 22, 23, 1
1550         load_acc_store  24, 25, 26, 27, 1
1551         load_acc_store  28, 29, 30, 31, 1
1552 .purgem load_acc_store
1553         pop             {pc}
1554 endfunc
1555 .endm
1556
1557 idct32_funcs
1558 idct32_funcs _quarter
1559 idct32_funcs _half
1560
1561 const min_eob_idct_idct_32, align=4
1562         .short  0, 9, 34, 70, 135, 240, 336, 448
1563 endconst
1564
1565 function ff_vp9_idct_idct_32x32_add_neon, export=1
1566         cmp             r3,  #1
1567         beq             idct32x32_dc_add_neon
1568         push            {r4-r8,lr}
1569         vpush           {q4-q7}
1570         movrel          r8,  min_eob_idct_idct_32 + 2
1571
1572         @ Align the stack, allocate a temp buffer
1573 T       mov             r7,  sp
1574 T       and             r7,  r7,  #15
1575 A       and             r7,  sp,  #15
1576         add             r7,  r7,  #2048
1577         sub             sp,  sp,  r7
1578
1579         mov             r4,  r0
1580         mov             r5,  r1
1581         mov             r6,  r2
1582
1583         cmp             r3,  #34
1584         ble             idct32x32_quarter_add_neon
1585         cmp             r3,  #135
1586         ble             idct32x32_half_add_neon
1587
1588 .irp i, 0, 4, 8, 12, 16, 20, 24, 28
1589         add             r0,  sp,  #(\i*64)
1590 .if \i > 0
1591         ldrh_post       r1,  r8,  #2
1592         cmp             r3,  r1
1593         it              le
1594         movle           r1,  #(32 - \i)/2
1595         ble             1f
1596 .endif
1597         add             r2,  r6,  #(\i*2)
1598         bl              idct32_1d_4x32_pass1_neon
1599 .endr
1600         b               3f
1601
1602 1:
1603         @ Write zeros to the temp buffer for pass 2
1604         vmov.i16        q14, #0
1605         vmov.i16        q15, #0
1606 2:
1607         subs            r1,  r1,  #1
1608 .rept 4
1609         vst1.16         {q14-q15}, [r0,:128]!
1610 .endr
1611         bne             2b
1612 3:
1613 .irp i, 0, 4, 8, 12, 16, 20, 24, 28
1614         add             r0,  r4,  #(\i)
1615         mov             r1,  r5
1616         add             r2,  sp,  #(\i*2)
1617         bl              idct32_1d_4x32_pass2_neon
1618 .endr
1619
1620         add             sp,  sp,  r7
1621         vpop            {q4-q7}
1622         pop             {r4-r8,pc}
1623 endfunc
1624
1625 function idct32x32_quarter_add_neon
1626 .irp i, 0, 4
1627         add             r0,  sp,  #(\i*64)
1628 .if \i == 4
1629         cmp             r3,  #9
1630         ble             1f
1631 .endif
1632         add             r2,  r6,  #(\i*2)
1633         bl              idct32_1d_4x32_pass1_quarter_neon
1634 .endr
1635         b               3f
1636
1637 1:
1638         @ Write zeros to the temp buffer for pass 2
1639         vmov.i16        q14, #0
1640         vmov.i16        q15, #0
1641 .rept 8
1642         vst1.16         {q14-q15}, [r0,:128]!
1643 .endr
1644 3:
1645 .irp i, 0, 4, 8, 12, 16, 20, 24, 28
1646         add             r0,  r4,  #(\i)
1647         mov             r1,  r5
1648         add             r2,  sp,  #(\i*2)
1649         bl              idct32_1d_4x32_pass2_quarter_neon
1650 .endr
1651
1652         add             sp,  sp,  r7
1653         vpop            {q4-q7}
1654         pop             {r4-r8,pc}
1655 endfunc
1656
1657 function idct32x32_half_add_neon
1658 .irp i, 0, 4, 8, 12
1659         add             r0,  sp,  #(\i*64)
1660 .if \i > 0
1661         ldrh_post       r1,  r8,  #2
1662         cmp             r3,  r1
1663         it              le
1664         movle           r1,  #(16 - \i)/2
1665         ble             1f
1666 .endif
1667         add             r2,  r6,  #(\i*2)
1668         bl              idct32_1d_4x32_pass1_half_neon
1669 .endr
1670         b               3f
1671
1672 1:
1673         @ Write zeros to the temp buffer for pass 2
1674         vmov.i16        q14, #0
1675         vmov.i16        q15, #0
1676 2:
1677         subs            r1,  r1,  #1
1678 .rept 4
1679         vst1.16         {q14-q15}, [r0,:128]!
1680 .endr
1681         bne             2b
1682 3:
1683 .irp i, 0, 4, 8, 12, 16, 20, 24, 28
1684         add             r0,  r4,  #(\i)
1685         mov             r1,  r5
1686         add             r2,  sp,  #(\i*2)
1687         bl              idct32_1d_4x32_pass2_half_neon
1688 .endr
1689
1690         add             sp,  sp,  r7
1691         vpop            {q4-q7}
1692         pop             {r4-r8,pc}
1693 endfunc