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