]> git.sesse.net Git - ffmpeg/blob - libavcodec/arm/vp9itxfm_neon.S
vaapi_encode: Fix GOP sizing
[ffmpeg] / libavcodec / arm / vp9itxfm_neon.S
1 /*
2  * Copyright (c) 2016 Google Inc.
3  *
4  * This file is part of Libav.
5  *
6  * Libav is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2.1 of the License, or (at your option) any later version.
10  *
11  * Libav is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with Libav; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19  */
20
21 #include "libavutil/arm/asm.S"
22 #include "neon.S"
23
24 const itxfm4_coeffs, align=4
25         .short  11585, 6270, 15137, 0
26 iadst4_coeffs:
27         .short  5283, 15212, 9929, 13377
28 endconst
29
30 const iadst8_coeffs, align=4
31         .short  16305, 1606, 14449, 7723, 10394, 12665, 4756, 15679
32 idct_coeffs:
33         .short  11585, 6270, 15137, 3196, 16069, 13623, 9102, 1606
34         .short  16305, 12665, 10394, 7723, 14449, 15679, 4756, 0
35         .short  804, 16364, 12140, 11003, 7005, 14811, 15426, 5520
36         .short  3981, 15893, 14053, 8423, 9760, 13160, 16207, 2404
37 endconst
38
39 const iadst16_coeffs, align=4
40         .short  16364, 804, 15893, 3981, 14811, 7005, 13160, 9760
41         .short  11003, 12140, 8423, 14053, 5520, 15426, 2404, 16207
42 endconst
43
44 @ Do four 4x4 transposes, using q registers for the subtransposes that don't
45 @ need to address the individual d registers.
46 @ r0,r1 == rq1, r2,r3 == rq1, etc
47 .macro transpose16_q_4x_4x4 rq0, rq1, rq2, rq3, rq4, rq5, rq6, rq7, r0, r1, r2, r3, r4, r5, r6, r7, r8, r9, r10, r11, r12, r13, r14, r15
48         vtrn.32          \rq0, \rq1
49         vtrn.32          \rq2, \rq3
50         vtrn.32          \rq4, \rq5
51         vtrn.32          \rq6, \rq7
52         vtrn.16          \r0,  \r1
53         vtrn.16          \r2,  \r3
54         vtrn.16          \r4,  \r5
55         vtrn.16          \r6,  \r7
56         vtrn.16          \r8,  \r9
57         vtrn.16          \r10, \r11
58         vtrn.16          \r12, \r13
59         vtrn.16          \r14, \r15
60 .endm
61
62 @ out1 = ((in1 + in2) * d0[0] + (1 << 13)) >> 14
63 @ out2 = ((in1 - in2) * d0[0] + (1 << 13)) >> 14
64 @ in/out are d registers
65 .macro mbutterfly0 out1, out2, in1, in2, tmpd1, tmpd2, tmpq3, tmpq4, neg=0
66         vadd.s16        \tmpd1, \in1,  \in2
67         vsub.s16        \tmpd2, \in1,  \in2
68         vmull.s16       \tmpq3, \tmpd1, d0[0]
69         vmull.s16       \tmpq4, \tmpd2, d0[0]
70 .if \neg > 0
71         vneg.s32        \tmpq3, \tmpq3
72 .endif
73         vrshrn.s32      \out1, \tmpq3, #14
74         vrshrn.s32      \out2, \tmpq4, #14
75 .endm
76
77 @ out1,out2 = ((in1 + in2) * d0[0] + (1 << 13)) >> 14
78 @ out3,out4 = ((in1 - in2) * d0[0] + (1 << 13)) >> 14
79 @ Same as mbutterfly0, but with input being 2 q registers, output
80 @ being 4 d registers.
81 @ This can do with either 4 or 6 temporary q registers.
82 .macro dmbutterfly0 out1, out2, out3, out4, in1, in2, tmpq1, tmpq2, tmpd11, tmpd12, tmpd21, tmpd22, tmpq3, tmpq4, tmpq5, tmpq6
83         vadd.s16        \tmpq1, \in1,  \in2
84         vsub.s16        \tmpq2, \in1,  \in2
85         vmull.s16       \tmpq3, \tmpd11, d0[0]
86         vmull.s16       \tmpq4, \tmpd12, d0[0]
87 .ifb \tmpq5
88         vrshrn.s32      \out1, \tmpq3, #14
89         vrshrn.s32      \out2, \tmpq4, #14
90         vmull.s16       \tmpq3, \tmpd21, d0[0]
91         vmull.s16       \tmpq4, \tmpd22, d0[0]
92         vrshrn.s32      \out3, \tmpq3, #14
93         vrshrn.s32      \out4, \tmpq4, #14
94 .else
95         vmull.s16       \tmpq5, \tmpd21, d0[0]
96         vmull.s16       \tmpq6, \tmpd22, d0[0]
97         vrshrn.s32      \out1, \tmpq3, #14
98         vrshrn.s32      \out2, \tmpq4, #14
99         vrshrn.s32      \out3, \tmpq5, #14
100         vrshrn.s32      \out4, \tmpq6, #14
101 .endif
102 .endm
103
104 @ out1 = in1 * coef1 - in2 * coef2
105 @ out2 = in1 * coef2 + in2 * coef1
106 @ out are 2 q registers, in are 2 d registers
107 .macro mbutterfly_l out1, out2, in1, in2, coef1, coef2
108         vmull.s16       \out1, \in1, \coef1
109         vmlsl.s16       \out1, \in2, \coef2
110         vmull.s16       \out2, \in1, \coef2
111         vmlal.s16       \out2, \in2, \coef1
112 .endm
113
114 @ out1,out2 = in1,in2 * coef1 - in3,in4 * coef2
115 @ out3,out4 = in1,in2 * coef2 + in3,in4 * coef1
116 @ out are 4 q registers, in are 4 d registers
117 .macro dmbutterfly_l out1, out2, out3, out4, in1, in2, in3, in4, coef1, coef2
118         vmull.s16       \out1, \in1, \coef1
119         vmull.s16       \out2, \in2, \coef1
120         vmull.s16       \out3, \in1, \coef2
121         vmull.s16       \out4, \in2, \coef2
122         vmlsl.s16       \out1, \in3, \coef2
123         vmlsl.s16       \out2, \in4, \coef2
124         vmlal.s16       \out3, \in3, \coef1
125         vmlal.s16       \out4, \in4, \coef1
126 .endm
127
128 @ inout1 = (inout1 * coef1 - inout2 * coef2 + (1 << 13)) >> 14
129 @ inout2 = (inout1 * coef2 + inout2 * coef1 + (1 << 13)) >> 14
130 @ inout are 2 d registers, tmp are 2 q registers
131 .macro mbutterfly inout1, inout2, coef1, coef2, tmp1, tmp2, neg=0
132         mbutterfly_l    \tmp1, \tmp2, \inout1, \inout2, \coef1, \coef2
133 .if \neg > 0
134         vneg.s32        \tmp2, \tmp2
135 .endif
136         vrshrn.s32      \inout1, \tmp1,  #14
137         vrshrn.s32      \inout2, \tmp2,  #14
138 .endm
139
140 @ inout1,inout2 = (inout1,inout2 * coef1 - inout3,inout4 * coef2 + (1 << 13)) >> 14
141 @ inout3,inout4 = (inout1,inout2 * coef2 + inout3,inout4 * coef1 + (1 << 13)) >> 14
142 @ inout are 4 d registers, tmp are 4 q registers
143 .macro dmbutterfly inout1, inout2, inout3, inout4, coef1, coef2, tmp1, tmp2, tmp3, tmp4
144         dmbutterfly_l   \tmp1, \tmp2, \tmp3, \tmp4, \inout1, \inout2, \inout3, \inout4, \coef1, \coef2
145         vrshrn.s32      \inout1, \tmp1,  #14
146         vrshrn.s32      \inout2, \tmp2,  #14
147         vrshrn.s32      \inout3, \tmp3,  #14
148         vrshrn.s32      \inout4, \tmp4,  #14
149 .endm
150
151 @ out1 = in1 + in2
152 @ out2 = in1 - in2
153 .macro butterfly out1, out2, in1, in2
154         vadd.s16        \out1, \in1, \in2
155         vsub.s16        \out2, \in1, \in2
156 .endm
157
158 @ out1 = in1 - in2
159 @ out2 = in1 + in2
160 .macro butterfly_r out1, out2, in1, in2
161         vsub.s16        \out1, \in1, \in2
162         vadd.s16        \out2, \in1, \in2
163 .endm
164
165 @ out1 = (in1 + in2 + (1 << 13)) >> 14
166 @ out2 = (in1 - in2 + (1 << 13)) >> 14
167 @ out are 2 d registers, in are 2 q registers, tmp are 2 q registers
168 .macro butterfly_n out1, out2, in1, in2, tmp1, tmp2
169         vadd.s32        \tmp1, \in1, \in2
170         vsub.s32        \tmp2, \in1, \in2
171         vrshrn.s32      \out1, \tmp1,  #14
172         vrshrn.s32      \out2, \tmp2,  #14
173 .endm
174
175 @ out1,out2 = (in1,in2 + in3,in4 + (1 << 13)) >> 14
176 @ out3,out4 = (in1,in2 - in3,in4 + (1 << 13)) >> 14
177 @ out are 4 d registers, in are 4 q registers, tmp are 4 q registers
178 .macro dbutterfly_n out1, out2, out3, out4, in1, in2, in3, in4, tmp1, tmp2, tmp3, tmp4
179         vadd.s32        \tmp1, \in1, \in3
180         vadd.s32        \tmp2, \in2, \in4
181         vsub.s32        \tmp3, \in1, \in3
182         vsub.s32        \tmp4, \in2, \in4
183         vrshrn.s32      \out1, \tmp1,  #14
184         vrshrn.s32      \out2, \tmp2,  #14
185         vrshrn.s32      \out3, \tmp3,  #14
186         vrshrn.s32      \out4, \tmp4,  #14
187 .endm
188
189
190 .macro iwht4 c0, c1, c2, c3
191         vadd.i16        \c0,  \c0,  \c1
192         vsub.i16        d17,  \c2,  \c3
193         vsub.i16        d16,  \c0,  d17
194         vshr.s16        d16,  d16,  #1
195         vsub.i16        \c2,  d16,  \c1
196         vsub.i16        \c1,  d16,  \c3
197         vadd.i16        \c3,  d17,  \c2
198         vsub.i16        \c0,  \c0,  \c1
199 .endm
200
201 .macro idct4 c0, c1, c2, c3
202         vmull.s16       q13,  \c1,  d0[2]
203         vmull.s16       q11,  \c1,  d0[1]
204         vadd.i16        d16,  \c0,  \c2
205         vsub.i16        d17,  \c0,  \c2
206         vmlal.s16       q13,  \c3,  d0[1]
207         vmull.s16       q9,   d16,  d0[0]
208         vmull.s16       q10,  d17,  d0[0]
209         vmlsl.s16       q11,  \c3,  d0[2]
210         vrshrn.s32      d26,  q13,  #14
211         vrshrn.s32      d18,  q9,   #14
212         vrshrn.s32      d20,  q10,  #14
213         vrshrn.s32      d22,  q11,  #14
214         vadd.i16        \c0,  d18,  d26
215         vsub.i16        \c3,  d18,  d26
216         vadd.i16        \c1,  d20,  d22
217         vsub.i16        \c2,  d20,  d22
218 .endm
219
220 .macro iadst4 c0, c1, c2, c3
221         vmull.s16       q10,  \c0,  d1[0]
222         vmlal.s16       q10,  \c2,  d1[1]
223         vmlal.s16       q10,  \c3,  d1[2]
224         vmull.s16       q11,  \c0,  d1[2]
225         vmlsl.s16       q11,  \c2,  d1[0]
226         vsub.s16        \c0,  \c0,  \c2
227         vmlsl.s16       q11,  \c3,  d1[1]
228         vadd.s16        \c0,  \c0,  \c3
229         vmull.s16       q13,  \c1,  d1[3]
230         vmull.s16       q12,  \c0,  d1[3]
231         vadd.s32        q14,  q10,  q13
232         vadd.s32        q1,   q11,  q13
233         vrshrn.s32      \c0,  q14,  #14
234         vadd.s32        q10,  q10,  q11
235         vrshrn.s32      \c1,  q1,   #14
236         vsub.s32        q10,  q10,  q13
237         vrshrn.s32      \c2,  q12,  #14
238         vrshrn.s32      \c3,  q10,  #14
239 .endm
240
241 @ The public functions in this file have got the following signature:
242 @ void itxfm_add(uint8_t *dst, ptrdiff_t stride, int16_t *block, int eob);
243
244 .macro itxfm_func4x4 txfm1, txfm2
245 function ff_vp9_\txfm1\()_\txfm2\()_4x4_add_neon, export=1
246 .ifc \txfm1,\txfm2
247 .ifc \txfm1,idct
248         movrel          r12, itxfm4_coeffs
249         vld1.16         {d0}, [r12,:64]
250 .endif
251 .ifc \txfm1,iadst
252         movrel          r12, iadst4_coeffs
253         vld1.16         {d1}, [r12,:64]
254 .endif
255 .else
256         movrel          r12, itxfm4_coeffs
257         vld1.16         {q0}, [r12,:128]
258 .endif
259
260         vmov.i16        q15, #0
261 .ifc \txfm1\()_\txfm2,idct_idct
262         cmp             r3,  #1
263         bne             1f
264         @ DC-only for idct/idct
265         vld1.16         {d4[]},   [r2,:16]
266         vmull.s16       q2,  d4,  d0[0]
267         vrshrn.s32      d4,  q2,  #14
268         vmull.s16       q2,  d4,  d0[0]
269         vrshrn.s32      d4,  q2,  #14
270         vst1.16         {d30[0]}, [r2,:16]
271         vdup.16         q2,  d4[0]
272         vmov            q3,  q2
273         b               2f
274 .endif
275
276 1:
277         vld1.16         {d4-d7},  [r2,:128]
278         vst1.16         {q15}, [r2,:128]!
279
280 .ifc \txfm1,iwht
281         vshr.s16        q2,  q2,  #2
282         vshr.s16        q3,  q3,  #2
283 .endif
284
285         \txfm1\()4      d4,  d5,  d6,  d7
286
287         vst1.16         {q15}, [r2,:128]!
288         @ Transpose 4x4 with 16 bit elements
289         vtrn.16         d4,  d5
290         vtrn.16         d6,  d7
291         vtrn.32         q2,  q3
292
293         \txfm2\()4      d4,  d5,  d6,  d7
294 2:
295         vld1.32         {d0[]},   [r0,:32], r1
296         vld1.32         {d0[1]},  [r0,:32], r1
297 .ifnc \txfm1,iwht
298         vrshr.s16       q2,  q2,  #4
299         vrshr.s16       q3,  q3,  #4
300 .endif
301         vaddw.u8        q2,  q2,  d0
302         vld1.32         {d1[]},   [r0,:32], r1
303         vld1.32         {d1[1]},  [r0,:32], r1
304         vqmovun.s16     d0,  q2
305         sub             r0,  r0,  r1, lsl #2
306
307         vaddw.u8        q3,  q3,  d1
308         vst1.32         {d0[0]},  [r0,:32], r1
309         vqmovun.s16     d1,  q3
310
311         vst1.32         {d0[1]},  [r0,:32], r1
312         vst1.32         {d1[0]},  [r0,:32], r1
313         vst1.32         {d1[1]},  [r0,:32], r1
314
315         bx              lr
316 endfunc
317 .endm
318
319 itxfm_func4x4 idct,  idct
320 itxfm_func4x4 iadst, idct
321 itxfm_func4x4 idct,  iadst
322 itxfm_func4x4 iadst, iadst
323 itxfm_func4x4 iwht,  iwht
324
325
326 .macro idct8
327         dmbutterfly0    d16, d17, d24, d25, q8,  q12, q2, q4, d4, d5, d8, d9, q3, q2, q5, q4 @ q8 = t0a, q12 = t1a
328         dmbutterfly     d20, d21, d28, d29, d0[1], d0[2], q2,  q3,  q4,  q5 @ q10 = t2a, q14 = t3a
329         dmbutterfly     d18, d19, d30, d31, d0[3], d1[0], q2,  q3,  q4,  q5 @ q9  = t4a, q15 = t7a
330         dmbutterfly     d26, d27, d22, d23, d1[1], d1[2], q2,  q3,  q4,  q5 @ q13 = t5a, q11 = t6a
331
332         butterfly       q2,  q14, q8,  q14 @ q2 = t0, q14 = t3
333         butterfly       q3,  q10, q12, q10 @ q3 = t1, q10 = t2
334         butterfly       q4,  q13, q9,  q13 @ q4 = t4, q13 = t5a
335         butterfly       q5,  q11, q15, q11 @ q5 = t7, q11 = t6a
336
337         butterfly       q8,  q15, q2,  q5  @ q8 = out[0], q15 = out[7]
338
339         dmbutterfly0    d4,  d5,  d10, d11, q11, q13, q9,  q13, d18, d19, d26, d27, q2,  q5, q11, q12 @ q2 = t6, q5 = t5
340
341         butterfly       q11, q12, q14, q4  @ q11 = out[3], q12 = out[4]
342         butterfly       q9,  q14, q3,  q2  @ q9 = out[1],  q14 = out[6]
343         butterfly_r     q13, q10, q10, q5  @ q13 = out[5], q10 = out[2]
344 .endm
345
346 .macro iadst8
347         dmbutterfly_l   q4,  q5,  q2,  q3,  d30, d31, d16, d17, d2[1], d2[0] @ q4,q5  = t1a, q2,q3 = t0a
348         dmbutterfly_l   q8,  q15, q6,  q7,  d22, d23, d24, d25, d3[1], d3[0] @ q8,q15 = t5a, q6,q7 = t4a
349
350         dbutterfly_n    d22, d23, d4,  d5,  q2,  q3,  q6,  q7,  q11, q12, q2,  q3 @ q11 = t0, q2 = t4
351
352         dbutterfly_n    d24, d25, d6,  d7,  q4,  q5,  q8,  q15, q12, q3,  q6,  q7 @ q12 = t1, q3 = t5
353
354         dmbutterfly_l   q6,  q7,  q4,  q5,  d26, d27, d20, d21, d2[3], d2[2] @ q6,q7 = t3a, q4,q5 = t2a
355         dmbutterfly_l   q10, q13, q8,  q15, d18, d19, d28, d29, d3[3], d3[2] @ q10,q13 = t7a, q8,q15 = t6a
356
357         dbutterfly_n    d18, d19, d8,  d9,  q4,  q5,  q8,  q15, q9,  q14, q4, q5 @ q9 = t2, q4 = t6
358         dbutterfly_n    d16, d17, d12, d13, q6,  q7,  q10, q13, q8,  q15, q6, q7 @ q8 = t3, q6 = t7
359
360         butterfly       q15, q12, q12, q8 @ q15 = -out[7], q12 = t3
361         vneg.s16        q15, q15          @ q15 = out[7]
362         butterfly       q8,  q9,  q11, q9 @ q8 = out[0], q9 = t2
363
364         dmbutterfly_l   q10, q11, q5,  q7,  d4,  d5,  d6,  d7,  d0[1], d0[2] @ q10,q11 = t5a, q5,q7 = t4a
365         dmbutterfly_l   q2,  q3,  q13, q14, d12, d13, d8,  d9,  d0[2], d0[1] @ q2,q3 = t6a, q13,q14 = t7a
366
367         dbutterfly_n    d28, d29, d8,  d9,  q10, q11, q13, q14, q4,  q6,  q10, q11 @ q14 = out[6], q4 = t7
368
369         dmbutterfly0    d22, d23, d24, d25, q9,  q12, q6, q13, d12, d13, d26, d27, q9, q10 @ q11 = -out[3], q12 = out[4]
370         vneg.s16        q11, q11      @ q11 = out[3]
371
372         dbutterfly_n    d18, d19, d4,  d5,  q5,  q7,  q2,  q3,  q9, q10, q2,  q3 @ q9 = -out[1], q2 = t6
373         vneg.s16        q9,  q9       @ q9 = out[1]
374
375         dmbutterfly0    d20, d21, d26, d27, q2,  q4,  q3, q5,  d6,  d7,  d10, d11, q6,  q7 @ q10 = out[2], q13 = -out[5]
376         vneg.s16        q13, q13      @ q13 = out[5]
377 .endm
378
379
380 .macro itxfm_func8x8 txfm1, txfm2
381 function ff_vp9_\txfm1\()_\txfm2\()_8x8_add_neon, export=1
382         @ Push q4-q7 if iadst is used, idct requires
383         @ a few scratch registers less, so only push q4-q5
384         @ if only idct is involved.
385         @ The iadst also uses a few coefficients from
386         @ idct, so those always need to be loaded.
387 .ifc \txfm1\()_\txfm2,idct_idct
388         movrel          r12, idct_coeffs
389         vpush           {q4-q5}
390         vld1.16         {q0}, [r12,:128]
391 .else
392         movrel          r12, iadst8_coeffs
393         vld1.16         {q1}, [r12,:128]!
394         vpush           {q4-q7}
395         vld1.16         {q0}, [r12,:128]
396 .endif
397
398         vmov.i16        q2, #0
399         vmov.i16        q3, #0
400
401 .ifc \txfm1\()_\txfm2,idct_idct
402         cmp             r3,  #1
403         bne             1f
404         @ DC-only for idct/idct
405         vld1.16         {d16[]}, [r2,:16]
406         vmull.s16       q8,  d16, d0[0]
407         vrshrn.s32      d16, q8,  #14
408         vmull.s16       q8,  d16, d0[0]
409         vrshrn.s32      d16, q8,  #14
410         vdup.16         q8,  d16[0]
411         vmov            q9,  q8
412         vmov            q10, q8
413         vmov            q11, q8
414         vmov            q12, q8
415         vmov            q13, q8
416         vmov            q14, q8
417         vmov            q15, q8
418         vst1.16         {d4[0]}, [r2,:16]
419         b               2f
420 .endif
421 1:
422         vld1.16         {q8-q9},    [r2,:128]!
423         vld1.16         {q10-q11},  [r2,:128]!
424         vld1.16         {q12-q13},  [r2,:128]!
425         vld1.16         {q14-q15},  [r2,:128]!
426         sub             r2,  r2,  #128
427         vst1.16         {q2-q3}, [r2,:128]!
428         vst1.16         {q2-q3}, [r2,:128]!
429         vst1.16         {q2-q3}, [r2,:128]!
430         vst1.16         {q2-q3}, [r2,:128]!
431
432         \txfm1\()8
433
434         @ Transpose 8x8 with 16 bit elements
435         vswp            d17, d24
436         vswp            d19, d26
437         vswp            d21, d28
438         vswp            d23, d30
439         transpose16_4x4 q8, q9, q10, q11, q12, q13, q14, q15
440
441         \txfm2\()8
442 2:
443         mov             r3,  r0
444         @ Add into the destination
445         vld1.8          {d4},  [r0,:64], r1
446         vrshr.s16       q8,  q8,  #5
447         vld1.8          {d5},  [r0,:64], r1
448         vrshr.s16       q9,  q9,  #5
449         vld1.8          {d6},  [r0,:64], r1
450         vrshr.s16       q10, q10, #5
451         vaddw.u8        q8,  q8,  d4
452         vld1.8          {d7},  [r0,:64], r1
453         vrshr.s16       q11, q11, #5
454         vaddw.u8        q9,  q9,  d5
455         vld1.8          {d8},  [r0,:64], r1
456         vrshr.s16       q12, q12, #5
457         vaddw.u8        q10, q10, d6
458         vqmovun.s16     d4,  q8
459         vld1.8          {d9},  [r0,:64], r1
460         vrshr.s16       q13, q13, #5
461         vaddw.u8        q11, q11, d7
462         vqmovun.s16     d5,  q9
463         vld1.8          {d10}, [r0,:64], r1
464         vrshr.s16       q14, q14, #5
465         vaddw.u8        q12, q12, d8
466         vqmovun.s16     d6,  q10
467         vld1.8          {d11}, [r0,:64], r1
468         vrshr.s16       q15, q15, #5
469         vaddw.u8        q13, q13, d9
470         vqmovun.s16     d7,  q11
471
472
473         vst1.8          {d4},  [r3,:64], r1
474         vaddw.u8        q14, q14, d10
475         vst1.8          {d5},  [r3,:64], r1
476         vqmovun.s16     d8,  q12
477         vst1.8          {d6},  [r3,:64], r1
478         vaddw.u8        q15, q15, d11
479         vst1.8          {d7},  [r3,:64], r1
480         vqmovun.s16     d9,  q13
481         vst1.8          {d8},  [r3,:64], r1
482         vqmovun.s16     d10, q14
483         vst1.8          {d9},  [r3,:64], r1
484         vqmovun.s16     d11, q15
485
486         vst1.8          {d10}, [r3,:64], r1
487         vst1.8          {d11}, [r3,:64], r1
488
489 .ifc \txfm1\()_\txfm2,idct_idct
490         vpop            {q4-q5}
491 .else
492         vpop            {q4-q7}
493 .endif
494         bx              lr
495 endfunc
496 .endm
497
498 itxfm_func8x8 idct,  idct
499 itxfm_func8x8 iadst, idct
500 .ltorg
501 itxfm_func8x8 idct,  iadst
502 itxfm_func8x8 iadst, iadst
503
504
505 function idct16x16_dc_add_neon
506         movrel          r12, idct_coeffs
507         vld1.16         {d0}, [r12,:64]
508
509         vmov.i16        q2, #0
510
511         vld1.16         {d16[]}, [r2,:16]
512         vmull.s16       q8,  d16, d0[0]
513         vrshrn.s32      d16, q8,  #14
514         vmull.s16       q8,  d16, d0[0]
515         vrshrn.s32      d16, q8,  #14
516         vdup.16         q8,  d16[0]
517         vst1.16         {d4[0]}, [r2,:16]
518
519         vrshr.s16       q8,  q8,  #6
520
521         mov             r12, #16
522 1:
523         @ Loop to add the constant from q8 into all 16x16 outputs
524         vld1.8          {q3},  [r0,:128]
525         vaddw.u8        q10, q8,  d6
526         vaddw.u8        q11, q8,  d7
527         vqmovun.s16     d6,  q10
528         vqmovun.s16     d7,  q11
529         vst1.8          {q3},  [r0,:128], r1
530         subs            r12, r12, #1
531         bne             1b
532
533         bx              lr
534 endfunc
535 .ltorg
536
537 .macro idct16
538         mbutterfly0     d16, d24, d16, d24, d4, d6,  q2,  q3 @ d16 = t0a,  d24 = t1a
539         mbutterfly      d20, d28, d0[1], d0[2], q2,  q3  @ d20 = t2a,  d28 = t3a
540         mbutterfly      d18, d30, d0[3], d1[0], q2,  q3  @ d18 = t4a,  d30 = t7a
541         mbutterfly      d26, d22, d1[1], d1[2], q2,  q3  @ d26 = t5a,  d22 = t6a
542         mbutterfly      d17, d31, d1[3], d2[0], q2,  q3  @ d17 = t8a,  d31 = t15a
543         mbutterfly      d25, d23, d2[1], d2[2], q2,  q3  @ d25 = t9a,  d23 = t14a
544         mbutterfly      d21, d27, d2[3], d3[0], q2,  q3  @ d21 = t10a, d27 = t13a
545         mbutterfly      d29, d19, d3[1], d3[2], q2,  q3  @ d29 = t11a, d19 = t12a
546
547         butterfly       d4,  d28, d16, d28               @ d4  = t0,   d28 = t3
548         butterfly       d5,  d20, d24, d20               @ d5  = t1,   d20 = t2
549         butterfly       d6,  d26, d18, d26               @ d6  = t4,   d26 = t5
550         butterfly       d7,  d22, d30, d22               @ d7  = t7,   d22 = t6
551         butterfly       d16, d25, d17, d25               @ d16 = t8,   d25 = t9
552         butterfly       d24, d21, d29, d21               @ d24 = t11,  d21 = t10
553         butterfly       d17, d27, d19, d27               @ d17 = t12,  d27 = t13
554         butterfly       d29, d23, d31, d23               @ d29 = t15,  d23 = t14
555
556         mbutterfly0     d22, d26, d22, d26, d18, d30, q9,  q15  @ d22 = t6a, d26 = t5a
557         mbutterfly      d23, d25, d0[1], d0[2], q9,  q15        @ d23 = t9a,  d25 = t14a
558         mbutterfly      d27, d21, d0[1], d0[2], q9,  q15, neg=1 @ d27 = t13a, d21 = t10a
559
560         butterfly       d18, d7,  d4,  d7                @ d18 = t0a,  d7  = t7a
561         butterfly       d19, d22, d5,  d22               @ d19 = t1a,  d22 = t6
562         butterfly       d4,  d26, d20, d26               @ d4  = t2a,  d26 = t5
563         butterfly       d5,  d6,  d28, d6                @ d5  = t3a,  d6  = t4
564         butterfly       d20, d28, d16, d24               @ d20 = t8a,  d28 = t11a
565         butterfly       d24, d21, d23, d21               @ d24 = t9,   d21 = t10
566         butterfly       d23, d27, d25, d27               @ d23 = t14,  d27 = t13
567         butterfly       d25, d29, d29, d17               @ d25 = t15a, d29 = t12a
568
569         mbutterfly0     d27, d21, d27, d21, d16, d30, q8, q15 @ d27 = t13a, d21 = t10a
570         mbutterfly0     d29, d28, d29, d28, d16, d30, q8, q15 @ d29 = t12,  d28 = t11
571
572         vswp            d27, d29                         @ d27 = t12, d29 = t13a
573         vswp            d28, d27                         @ d28 = t12, d27 = t11
574         butterfly       d16, d31, d18, d25               @ d16 = out[0], d31 = out[15]
575         butterfly       d17, d30, d19, d23               @ d17 = out[1], d30 = out[14]
576         butterfly_r     d25, d22, d22, d24               @ d25 = out[9], d22 = out[6]
577         butterfly       d23, d24, d7,  d20               @ d23 = out[7], d24 = out[8]
578         butterfly       d18, d29, d4,  d29               @ d18 = out[2], d29 = out[13]
579         butterfly       d19, d28, d5,  d28               @ d19 = out[3], d28 = out[12]
580         vmov            d4,  d21                         @ d4  = t10a
581         butterfly       d20, d27, d6,  d27               @ d20 = out[4], d27 = out[11]
582         butterfly       d21, d26, d26, d4                @ d21 = out[5], d26 = out[10]
583 .endm
584
585 .macro iadst16
586         movrel          r12, iadst16_coeffs
587         vld1.16         {q0-q1}, [r12,:128]
588
589         mbutterfly_l    q3,  q2,  d31, d16, d0[1], d0[0] @ q3  = t1,   q2  = t0
590         mbutterfly_l    q5,  q4,  d23, d24, d2[1], d2[0] @ q5  = t9,   q4  = t8
591         butterfly_n     d31, d24, q3,  q5,  q6,  q5      @ d31 = t1a,  d24 = t9a
592         mbutterfly_l    q7,  q6,  d29, d18, d0[3], d0[2] @ q7  = t3,   q6  = t2
593         butterfly_n     d16, d23, q2,  q4,  q3,  q4      @ d16 = t0a,  d23 = t8a
594
595         mbutterfly_l    q3,  q2,  d21, d26, d2[3], d2[2] @ q3  = t11,  q2  = t10
596         butterfly_n     d29, d26, q7,  q3,  q4,  q3      @ d29 = t3a,  d26 = t11a
597         mbutterfly_l    q5,  q4,  d27, d20, d1[1], d1[0] @ q5  = t5,   q4  = t4
598         butterfly_n     d18, d21, q6,  q2,  q3,  q2      @ d18 = t2a,  d21 = t10a
599
600         mbutterfly_l    q7,  q6,  d19, d28, d3[1], d3[0] @ q7  = t13,  q6  = t12
601         butterfly_n     d20, d28, q5,  q7,  q2,  q7      @ d20 = t5a,  d28 = t13a
602         mbutterfly_l    q3,  q2,  d25, d22, d1[3], d1[2] @ q3  = t7,   q2  = t6
603         butterfly_n     d27, d19, q4,  q6,  q5,  q6      @ d27 = t4a,  d19 = t12a
604
605         mbutterfly_l    q5,  q4,  d17, d30, d3[3], d3[2] @ q5  = t15,  q4  = t14
606         movrel          r12, idct_coeffs
607         vld1.16         {q0}, [r12,:128]
608         butterfly_n     d22, d30, q3,  q5,  q6,  q5      @ d22 = t7a,  d30 = t15a
609         mbutterfly_l    q7,  q6,  d23, d24, d0[3], d1[0] @ q7  = t9,   q6  = t8
610         butterfly_n     d25, d17, q2,  q4,  q3,  q4      @ d25 = t6a,  d17 = t14a
611
612         mbutterfly_l    q2,  q3,  d28, d19, d1[0], d0[3] @ q2  = t12,  q3  = t13
613         butterfly_n     d23, d19, q6,  q2,  q4,  q2      @ d23 = t8a,  d19 = t12a
614         mbutterfly_l    q5,  q4,  d21, d26, d1[1], d1[2] @ q5  = t11,  q4  = t10
615         butterfly_r     d4,  d27, d16, d27               @ d4  = t4,   d27 = t0
616         butterfly_n     d24, d28, q7,  q3,  q6,  q3      @ d24 = t9a,  d28 = t13a
617
618         mbutterfly_l    q6,  q7,  d30, d17, d1[2], d1[1] @ q6  = t14,  q7  = t15
619         butterfly_r     d5,  d20, d31, d20               @ d5  = t5,   d20 = t1
620         butterfly_n     d21, d17, q4,  q6,  q3,  q6      @ d21 = t10a, d17 = t14a
621         butterfly_n     d26, d30, q5,  q7,  q4,  q7      @ d26 = t11a, d30 = t15a
622
623         butterfly_r     d6,  d25, d18, d25               @ d6  = t6,   d25 = t2
624         butterfly_r     d7,  d22, d29, d22               @ d7  = t7,   d22 = t3
625
626         mbutterfly_l    q5,  q4,  d19, d28, d0[1], d0[2] @ q5  = t13,  q4  = t12
627         mbutterfly_l    q6,  q7,  d30, d17, d0[2], d0[1] @ q6  = t14,  q7  = t15
628
629         butterfly_n     d18, d30, q4,  q6,  q8,  q6      @ d18 = out[2],   d30 = t14a
630         butterfly_n     d29, d17, q5,  q7,  q6,  q7      @ d29 = -out[13], d17 = t15a
631         vneg.s16        d29, d29                         @ d29 = out[13]
632
633         mbutterfly_l    q5,  q4,  d4,  d5,  d0[1], d0[2] @ q5  = t5a,  q4  = t4a
634         mbutterfly_l    q6,  q7,  d7,  d6,  d0[2], d0[1] @ q6  = t6a,  q7  = t7a
635
636         butterfly       d2,  d6,  d27, d25               @ d2 = out[0], d6 = t2a
637         butterfly       d3,  d7,  d23, d21               @ d3 =-out[1], d7 = t10
638
639         butterfly_n     d19, d31, q4,  q6,  q2,  q4      @ d19 = -out[3],  d31 = t6
640         vneg.s16        d19, d19                         @ d19 = out[3]
641         butterfly_n     d28, d16, q5,  q7,  q2,  q5      @ d28 = out[12],  d16 = t7
642
643         butterfly       d5,  d8,  d20, d22               @ d5 =-out[15],d8 = t3a
644         butterfly       d4,  d9,  d24, d26               @ d4 = out[14],d9 = t11
645
646         mbutterfly0     d23, d24, d6,  d8,  d10, d11, q6,  q7, 1 @ d23 = out[7], d24 = out[8]
647         mbutterfly0     d20, d27, d16, d31, d10, d11, q6,  q7    @ d20 = out[4], d27 = out[11]
648         mbutterfly0     d22, d25, d9,  d7,  d10, d11, q6,  q7    @ d22 = out[6], d25 = out[9]
649         mbutterfly0     d21, d26, d30, d17, d10, d11, q6,  q7, 1 @ d21 = out[5], d26 = out[10]
650
651         vneg.s16        d31, d5                          @ d31 = out[15]
652         vneg.s16        d17, d3                          @ d17 = out[1]
653
654         vmov            d16, d2
655         vmov            d30, d4
656 .endm
657
658 .macro itxfm16_1d_funcs txfm
659 @ Read a vertical 4x16 slice out of a 16x16 matrix, do a transform on it,
660 @ transpose into a horizontal 16x4 slice and store.
661 @ r0 = dst (temp buffer)
662 @ r1 = slice offset
663 @ r2 = src
664 function \txfm\()16_1d_4x16_pass1_neon
665         mov             r12, #32
666         vmov.s16        q2, #0
667 .irp i, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31
668         vld1.16         {d\i}, [r2,:64]
669         vst1.16         {d4},  [r2,:64], r12
670 .endr
671
672         \txfm\()16
673
674         @ Do four 4x4 transposes. Originally, d16-d31 contain the
675         @ 16 rows. Afterwards, d16-d19, d20-d23, d24-d27, d28-d31
676         @ contain the transposed 4x4 blocks.
677         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
678
679         @ Store the transposed 4x4 blocks horizontally.
680         cmp             r1,  #12
681         beq             1f
682 .irp i, 16, 20, 24, 28, 17, 21, 25, 29, 18, 22, 26, 30, 19, 23, 27, 31
683         vst1.16         {d\i}, [r0,:64]!
684 .endr
685         bx              lr
686 1:
687         @ Special case: For the last input column (r1 == 12),
688         @ which would be stored as the last row in the temp buffer,
689         @ don't store the first 4x4 block, but keep it in registers
690         @ for the first slice of the second pass (where it is the
691         @ last 4x4 block).
692         add             r0,  r0,  #8
693 .irp i, 20, 24, 28
694         vst1.16         {d\i}, [r0,:64]!
695 .endr
696         add             r0,  r0,  #8
697 .irp i, 21, 25, 29
698         vst1.16         {d\i}, [r0,:64]!
699 .endr
700         add             r0,  r0,  #8
701 .irp i, 22, 26, 30
702         vst1.16         {d\i}, [r0,:64]!
703 .endr
704         add             r0,  r0,  #8
705 .irp i, 23, 27, 31
706         vst1.16         {d\i}, [r0,:64]!
707 .endr
708         vmov            d28, d16
709         vmov            d29, d17
710         vmov            d30, d18
711         vmov            d31, d19
712         bx              lr
713 endfunc
714
715 @ Read a vertical 4x16 slice out of a 16x16 matrix, do a transform on it,
716 @ load the destination pixels (from a similar 4x16 slice), add and store back.
717 @ r0 = dst
718 @ r1 = dst stride
719 @ r2 = src (temp buffer)
720 @ r3 = slice offset
721 function \txfm\()16_1d_4x16_pass2_neon
722         mov             r12, #32
723 .irp i, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27
724         vld1.16         {d\i}, [r2,:64], r12
725 .endr
726         cmp             r3,  #0
727         beq             1f
728 .irp i, 28, 29, 30, 31
729         vld1.16         {d\i}, [r2,:64], r12
730 .endr
731 1:
732
733         add             r3,  r0,  r1
734         lsl             r1,  r1,  #1
735         \txfm\()16
736
737 .macro load_add_store coef0, coef1, coef2, coef3
738         vrshr.s16       \coef0, \coef0, #6
739         vrshr.s16       \coef1, \coef1, #6
740
741         vld1.32         {d4[]},   [r0,:32], r1
742         vld1.32         {d4[1]},  [r3,:32], r1
743         vrshr.s16       \coef2, \coef2, #6
744         vrshr.s16       \coef3, \coef3, #6
745         vld1.32         {d5[]},   [r0,:32], r1
746         vld1.32         {d5[1]},  [r3,:32], r1
747         vaddw.u8        \coef0, \coef0, d4
748         vld1.32         {d6[]},   [r0,:32], r1
749         vld1.32         {d6[1]},  [r3,:32], r1
750         vaddw.u8        \coef1, \coef1, d5
751         vld1.32         {d7[]},   [r0,:32], r1
752         vld1.32         {d7[1]},  [r3,:32], r1
753
754         vqmovun.s16     d4,  \coef0
755         vqmovun.s16     d5,  \coef1
756         sub             r0,  r0,  r1, lsl #2
757         sub             r3,  r3,  r1, lsl #2
758         vaddw.u8        \coef2, \coef2, d6
759         vaddw.u8        \coef3, \coef3, d7
760         vst1.32         {d4[0]},  [r0,:32], r1
761         vst1.32         {d4[1]},  [r3,:32], r1
762         vqmovun.s16     d6,  \coef2
763         vst1.32         {d5[0]},  [r0,:32], r1
764         vst1.32         {d5[1]},  [r3,:32], r1
765         vqmovun.s16     d7,  \coef3
766
767         vst1.32         {d6[0]},  [r0,:32], r1
768         vst1.32         {d6[1]},  [r3,:32], r1
769         vst1.32         {d7[0]},  [r0,:32], r1
770         vst1.32         {d7[1]},  [r3,:32], r1
771 .endm
772         load_add_store  q8,  q9,  q10, q11
773         load_add_store  q12, q13, q14, q15
774 .purgem load_add_store
775
776         bx              lr
777 endfunc
778 .endm
779
780 itxfm16_1d_funcs idct
781 itxfm16_1d_funcs iadst
782
783 @ This is the minimum eob value for each subpartition, in increments of 4
784 const min_eob_idct_idct_16, align=4
785         .short  0, 10, 38, 89
786 endconst
787
788 .macro itxfm_func16x16 txfm1, txfm2
789 function ff_vp9_\txfm1\()_\txfm2\()_16x16_add_neon, export=1
790 .ifc \txfm1\()_\txfm2,idct_idct
791         cmp             r3,  #1
792         beq             idct16x16_dc_add_neon
793 .endif
794         push            {r4-r8,lr}
795 .ifnc \txfm1\()_\txfm2,idct_idct
796         vpush           {q4-q7}
797 .else
798         movrel          r8,  min_eob_idct_idct_16 + 2
799 .endif
800
801         @ Align the stack, allocate a temp buffer
802 T       mov             r7,  sp
803 T       and             r7,  r7,  #15
804 A       and             r7,  sp,  #15
805         add             r7,  r7,  #512
806         sub             sp,  sp,  r7
807
808         mov             r4,  r0
809         mov             r5,  r1
810         mov             r6,  r2
811
812 .ifc \txfm1,idct
813         movrel          r12, idct_coeffs
814         vld1.16         {q0-q1}, [r12,:128]
815 .endif
816
817 .irp i, 0, 4, 8, 12
818         add             r0,  sp,  #(\i*32)
819 .ifc \txfm1\()_\txfm2,idct_idct
820 .if \i > 0
821         ldrh_post       r1,  r8,  #2
822         cmp             r3,  r1
823         it              le
824         movle           r1,  #(16 - \i)/4
825         ble             1f
826 .endif
827 .endif
828         mov             r1,  #\i
829         add             r2,  r6,  #(\i*2)
830         bl              \txfm1\()16_1d_4x16_pass1_neon
831 .endr
832
833 .ifc \txfm1\()_\txfm2,idct_idct
834         b               3f
835 1:
836         @ For all-zero slices in pass 1, set d28-d31 to zero, for the in-register
837         @ passthrough of coefficients to pass 2 and clear the end of the temp buffer
838         vmov.i16        q14, #0
839         vmov.i16        q15, #0
840 2:
841         subs            r1,  r1,  #1
842 .rept 4
843         vst1.16         {q14-q15}, [r0,:128]!
844 .endr
845         bne             2b
846 3:
847 .endif
848
849 .ifc \txfm1\()_\txfm2,iadst_idct
850         movrel          r12, idct_coeffs
851         vld1.16         {q0-q1}, [r12,:128]
852 .endif
853 .irp i, 0, 4, 8, 12
854         add             r0,  r4,  #(\i)
855         mov             r1,  r5
856         add             r2,  sp,  #(\i*2)
857         mov             r3,  #\i
858         bl              \txfm2\()16_1d_4x16_pass2_neon
859 .endr
860
861         add             sp,  sp,  r7
862 .ifnc \txfm1\()_\txfm2,idct_idct
863         vpop            {q4-q7}
864 .endif
865         pop             {r4-r8,pc}
866 endfunc
867 .endm
868
869 itxfm_func16x16 idct,  idct
870 itxfm_func16x16 iadst, idct
871 itxfm_func16x16 idct,  iadst
872 itxfm_func16x16 iadst, iadst
873 .ltorg
874
875
876 function idct32x32_dc_add_neon
877         movrel          r12, idct_coeffs
878         vld1.16         {d0}, [r12,:64]
879
880         vmov.i16        q2, #0
881
882         vld1.16         {d16[]}, [r2,:16]
883         vmull.s16       q8,  d16, d0[0]
884         vrshrn.s32      d16, q8,  #14
885         vmull.s16       q8,  d16, d0[0]
886         vrshrn.s32      d16, q8,  #14
887         vdup.16         q8,  d16[0]
888         vst1.16         {d4[0]}, [r2,:16]
889
890         vrshr.s16       q8,  q8,  #6
891
892         mov             r12, #32
893 1:
894         @ Loop to add the constant from q8 into all 32x32 outputs
895         vld1.8          {q2-q3},  [r0,:128]
896         vaddw.u8        q10, q8,  d4
897         vaddw.u8        q11, q8,  d5
898         vaddw.u8        q12, q8,  d6
899         vaddw.u8        q13, q8,  d7
900         vqmovun.s16     d4,  q10
901         vqmovun.s16     d5,  q11
902         vqmovun.s16     d6,  q12
903         vqmovun.s16     d7,  q13
904         vst1.8          {q2-q3},  [r0,:128], r1
905         subs            r12, r12, #1
906         bne             1b
907
908         bx              lr
909 endfunc
910
911 .macro idct32_odd
912         movrel          r12, idct_coeffs
913         add             r12, r12, #32
914         vld1.16         {q0-q1}, [r12,:128]
915
916         mbutterfly      d16, d31, d0[0], d0[1], q2, q3 @ d16 = t16a, d31 = t31a
917         mbutterfly      d24, d23, d0[2], d0[3], q2, q3 @ d24 = t17a, d23 = t30a
918         mbutterfly      d20, d27, d1[0], d1[1], q2, q3 @ d20 = t18a, d27 = t29a
919         mbutterfly      d28, d19, d1[2], d1[3], q2, q3 @ d28 = t19a, d19 = t28a
920         mbutterfly      d18, d29, d2[0], d2[1], q2, q3 @ d18 = t20a, d29 = t27a
921         mbutterfly      d26, d21, d2[2], d2[3], q2, q3 @ d26 = t21a, d21 = t26a
922         mbutterfly      d22, d25, d3[0], d3[1], q2, q3 @ d22 = t22a, d25 = t25a
923         mbutterfly      d30, d17, d3[2], d3[3], q2, q3 @ d30 = t23a, d17 = t24a
924
925         sub             r12, r12, #32
926         vld1.16         {q0}, [r12,:128]
927
928         butterfly       d4,  d24, d16, d24 @ d4  = t16, d24 = t17
929         butterfly       d5,  d20, d28, d20 @ d5  = t19, d20 = t18
930         butterfly       d6,  d26, d18, d26 @ d6  = t20, d26 = t21
931         butterfly       d7,  d22, d30, d22 @ d7  = t23, d22 = t22
932         butterfly       d28, d25, d17, d25 @ d28 = t24, d25 = t25
933         butterfly       d30, d21, d29, d21 @ d30 = t27, d21 = t26
934         butterfly       d29, d23, d31, d23 @ d29 = t31, d23 = t30
935         butterfly       d31, d27, d19, d27 @ d31 = t28, d27 = t29
936
937         mbutterfly      d23, d24, d0[3], d1[0], q8, q9        @ d23 = t17a, d24 = t30a
938         mbutterfly      d27, d20, d0[3], d1[0], q8, q9, neg=1 @ d27 = t29a, d20 = t18a
939         mbutterfly      d21, d26, d1[1], d1[2], q8, q9        @ d21 = t21a, d26 = t26a
940         mbutterfly      d25, d22, d1[1], d1[2], q8, q9, neg=1 @ d25 = t25a, d22 = t22a
941
942         butterfly       d16, d5,  d4,  d5  @ d16 = t16a, d5  = t19a
943         butterfly       d17, d20, d23, d20 @ d17 = t17,  d20 = t18
944         butterfly       d18, d6,  d7,  d6  @ d18 = t23a, d6  = t20a
945         butterfly       d19, d21, d22, d21 @ d19 = t22,  d21 = t21
946         butterfly       d4,  d28, d28, d30 @ d4  = t24a, d28 = t27a
947         butterfly       d23, d26, d25, d26 @ d23 = t25,  d26 = t26
948         butterfly       d7,  d29, d29, d31 @ d7  = t31a, d29 = t28a
949         butterfly       d22, d27, d24, d27 @ d22 = t30,  d27 = t29
950
951         mbutterfly      d27, d20, d0[1], d0[2], q12, q15        @ d27 = t18a, d20 = t29a
952         mbutterfly      d29, d5,  d0[1], d0[2], q12, q15        @ d29 = t19,  d5  = t28
953         mbutterfly      d28, d6,  d0[1], d0[2], q12, q15, neg=1 @ d28 = t27,  d6  = t20
954         mbutterfly      d26, d21, d0[1], d0[2], q12, q15, neg=1 @ d26 = t26a, d21 = t21a
955
956         butterfly       d31, d24, d7,  d4  @ d31 = t31,  d24 = t24
957         butterfly       d30, d25, d22, d23 @ d30 = t30a, d25 = t25a
958         butterfly_r     d23, d16, d16, d18 @ d23 = t23,  d16 = t16
959         butterfly_r     d22, d17, d17, d19 @ d22 = t22a, d17 = t17a
960         butterfly       d18, d21, d27, d21 @ d18 = t18,  d21 = t21
961         butterfly_r     d27, d28, d5,  d28 @ d27 = t27a, d28 = t28a
962         butterfly       d4,  d26, d20, d26 @ d4  = t29,  d26 = t26
963         butterfly       d19, d20, d29, d6  @ d19 = t19a, d20 = t20
964         vmov            d29, d4            @ d29 = t29
965
966         mbutterfly0     d27, d20, d27, d20, d4, d6, q2, q3 @ d27 = t27,  d20 = t20
967         mbutterfly0     d26, d21, d26, d21, d4, d6, q2, q3 @ d26 = t26a, d21 = t21a
968         mbutterfly0     d25, d22, d25, d22, d4, d6, q2, q3 @ d25 = t25,  d22 = t22
969         mbutterfly0     d24, d23, d24, d23, d4, d6, q2, q3 @ d24 = t24a, d23 = t23a
970 .endm
971
972 @ Do an 32-point IDCT of a 4x32 slice out of a 32x32 matrix.
973 @ We don't have register space to do a single pass IDCT of 4x32 though,
974 @ but the 32-point IDCT can be decomposed into two 16-point IDCTs;
975 @ a normal IDCT16 with every other input component (the even ones, with
976 @ each output written twice), followed by a separate 16-point IDCT
977 @ of the odd inputs, added/subtracted onto the outputs of the first idct16.
978 @ r0 = dst (temp buffer)
979 @ r1 = unused
980 @ r2 = src
981 function idct32_1d_4x32_pass1_neon
982         movrel          r12, idct_coeffs
983         vld1.16         {q0-q1}, [r12,:128]
984
985         @ Double stride of the input, since we only read every other line
986         mov             r12, #128
987         vmov.s16        d4, #0
988
989         @ d16 = IN(0), d17 = IN(2) ... d31 = IN(30)
990 .irp i, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31
991         vld1.16         {d\i}, [r2,:64]
992         vst1.16         {d4},  [r2,:64], r12
993 .endr
994
995         idct16
996
997         @ Do four 4x4 transposes. Originally, d16-d31 contain the
998         @ 16 rows. Afterwards, d16-d19, d20-d23, d24-d27, d28-d31
999         @ contain the transposed 4x4 blocks.
1000         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
1001         @ Store the registers a, b, c, d horizontally, followed
1002         @ by the same registers d, c, b, a mirrored.
1003 .macro store_rev a, b, c, d
1004 .irp i, \a, \b, \c, \d
1005         vst1.16         {d\i}, [r0,:64]!
1006         vrev64.16       d\i, d\i
1007 .endr
1008 .irp i, \d, \c, \b, \a
1009         vst1.16         {d\i}, [r0,:64]!
1010 .endr
1011 .endm
1012         store_rev       16, 20, 24, 28
1013         store_rev       17, 21, 25, 29
1014         store_rev       18, 22, 26, 30
1015         store_rev       19, 23, 27, 31
1016         sub             r0,  r0,  #256
1017 .purgem store_rev
1018
1019         @ Move r2 back to the start of the input, and move
1020         @ to the first odd row
1021         sub             r2,  r2,  r12, lsl #4
1022         add             r2,  r2,  #64
1023
1024         vmov.s16        d4, #0
1025         @ d16 = IN(1), d17 = IN(3) ... d31 = IN(31)
1026 .irp i, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31
1027         vld1.16         {d\i}, [r2,:64]
1028         vst1.16         {d4},  [r2,:64], r12
1029 .endr
1030
1031         idct32_odd
1032
1033         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
1034
1035         @ Store the registers a, b, c, d horizontally,
1036         @ adding into the output first, and then mirrored, subtracted
1037         @ from the output.
1038 .macro store_rev a, b, c, d
1039 .irp i, \a, \b, \c, \d
1040         vld1.16         {d4},  [r0,:64]
1041         vadd.s16        d4, d4, d\i
1042         vst1.16         {d4},  [r0,:64]!
1043         vrev64.16       d\i, d\i
1044 .endr
1045 .irp i, \d, \c, \b, \a
1046         vld1.16         {d4},  [r0,:64]
1047         vsub.s16        d4, d4, d\i
1048         vst1.16         {d4},  [r0,:64]!
1049 .endr
1050 .endm
1051
1052         store_rev       31, 27, 23, 19
1053         store_rev       30, 26, 22, 18
1054         store_rev       29, 25, 21, 17
1055         store_rev       28, 24, 20, 16
1056 .purgem store_rev
1057         bx              lr
1058 endfunc
1059 .ltorg
1060
1061 @ This is mostly the same as 4x32_pass1, but without the transpose,
1062 @ and use the source as temp buffer between the two idct passes, and
1063 @ add into the destination.
1064 @ r0 = dst
1065 @ r1 = dst stride
1066 @ r2 = src (temp buffer)
1067 function idct32_1d_4x32_pass2_neon
1068         movrel          r12, idct_coeffs
1069         vld1.16         {q0-q1}, [r12,:128]
1070
1071         mov             r12, #128
1072         @ d16 = IN(0), d17 = IN(2) ... d31 = IN(30)
1073 .irp i, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31
1074         vld1.16         {d\i}, [r2,:64], r12
1075 .endr
1076         sub             r2,  r2,  r12, lsl #4
1077
1078         idct16
1079
1080 .irp i, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31
1081         vst1.16         {d\i}, [r2,:64], r12
1082 .endr
1083
1084         sub             r2,  r2,  r12, lsl #4
1085         add             r2,  r2,  #64
1086
1087         @ d16 = IN(1), d17 = IN(3) ... d31 = IN(31)
1088 .irp i, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31
1089         vld1.16         {d\i}, [r2,:64], r12
1090 .endr
1091         sub             r2,  r2,  r12, lsl #4
1092         sub             r2,  r2,  #64
1093
1094         idct32_odd
1095
1096         mov             r12, #128
1097 .macro load_acc_store a, b, c, d, neg=0
1098         vld1.16         {d4},  [r2,:64], r12
1099         vld1.16         {d5},  [r2,:64], r12
1100 .if \neg == 0
1101         vadd.s16        d4, d4, d\a
1102         vld1.16         {d6},  [r2,:64], r12
1103         vadd.s16        d5, d5, d\b
1104         vld1.16         {d7},  [r2,:64], r12
1105         vadd.s16        d6, d6, d\c
1106         vadd.s16        d7, d7, d\d
1107 .else
1108         vsub.s16        d4, d4, d\a
1109         vld1.16         {d6},  [r2,:64], r12
1110         vsub.s16        d5, d5, d\b
1111         vld1.16         {d7},  [r2,:64], r12
1112         vsub.s16        d6, d6, d\c
1113         vsub.s16        d7, d7, d\d
1114 .endif
1115         vld1.32         {d2[]},   [r0,:32], r1
1116         vld1.32         {d2[1]},  [r0,:32], r1
1117         vrshr.s16       q2, q2, #6
1118         vld1.32         {d3[]},   [r0,:32], r1
1119         vrshr.s16       q3, q3, #6
1120         vld1.32         {d3[1]},  [r0,:32], r1
1121         sub             r0,  r0,  r1, lsl #2
1122         vaddw.u8        q2,  q2,  d2
1123         vaddw.u8        q3,  q3,  d3
1124         vqmovun.s16     d4,  q2
1125         vqmovun.s16     d5,  q3
1126         vst1.32         {d4[0]},  [r0,:32], r1
1127         vst1.32         {d4[1]},  [r0,:32], r1
1128         vst1.32         {d5[0]},  [r0,:32], r1
1129         vst1.32         {d5[1]},  [r0,:32], r1
1130 .endm
1131         load_acc_store  31, 30, 29, 28
1132         load_acc_store  27, 26, 25, 24
1133         load_acc_store  23, 22, 21, 20
1134         load_acc_store  19, 18, 17, 16
1135         sub             r2,  r2,  r12
1136         neg             r12, r12
1137         load_acc_store  16, 17, 18, 19, 1
1138         load_acc_store  20, 21, 22, 23, 1
1139         load_acc_store  24, 25, 26, 27, 1
1140         load_acc_store  28, 29, 30, 31, 1
1141 .purgem load_acc_store
1142         bx              lr
1143 endfunc
1144
1145 const min_eob_idct_idct_32, align=4
1146         .short  0, 9, 34, 70, 135, 240, 336, 448
1147 endconst
1148
1149 function ff_vp9_idct_idct_32x32_add_neon, export=1
1150         cmp             r3,  #1
1151         beq             idct32x32_dc_add_neon
1152         push            {r4-r8,lr}
1153         vpush           {q4-q7}
1154         movrel          r8,  min_eob_idct_idct_32 + 2
1155
1156         @ Align the stack, allocate a temp buffer
1157 T       mov             r7,  sp
1158 T       and             r7,  r7,  #15
1159 A       and             r7,  sp,  #15
1160         add             r7,  r7,  #2048
1161         sub             sp,  sp,  r7
1162
1163         mov             r4,  r0
1164         mov             r5,  r1
1165         mov             r6,  r2
1166
1167 .irp i, 0, 4, 8, 12, 16, 20, 24, 28
1168         add             r0,  sp,  #(\i*64)
1169 .if \i > 0
1170         ldrh_post       r1,  r8,  #2
1171         cmp             r3,  r1
1172         it              le
1173         movle           r1,  #(32 - \i)/2
1174         ble             1f
1175 .endif
1176         add             r2,  r6,  #(\i*2)
1177         bl              idct32_1d_4x32_pass1_neon
1178 .endr
1179         b               3f
1180
1181 1:
1182         @ Write zeros to the temp buffer for pass 2
1183         vmov.i16        q14, #0
1184         vmov.i16        q15, #0
1185 2:
1186         subs            r1,  r1,  #1
1187 .rept 4
1188         vst1.16         {q14-q15}, [r0,:128]!
1189 .endr
1190         bne             2b
1191 3:
1192 .irp i, 0, 4, 8, 12, 16, 20, 24, 28
1193         add             r0,  r4,  #(\i)
1194         mov             r1,  r5
1195         add             r2,  sp,  #(\i*2)
1196         bl              idct32_1d_4x32_pass2_neon
1197 .endr
1198
1199         add             sp,  sp,  r7
1200         vpop            {q4-q7}
1201         pop             {r4-r8,pc}
1202 endfunc