arm: vp9itxfm: Only reload the idct coeffs for the iadst_idct combination
[libav.git] / libavcodec / arm / vp9itxfm_neon.S
1 /*
2 * Copyright (c) 2016 Google Inc.
3 *
4 * This file is part of Libav.
5 *
6 * Libav is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
10 *
11 * Libav is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with Libav; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19 */
20
21 #include "libavutil/arm/asm.S"
22 #include "neon.S"
23
24 const itxfm4_coeffs, align=4
25 .short 11585, 6270, 15137, 0
26 iadst4_coeffs:
27 .short 5283, 15212, 9929, 13377
28 endconst
29
30 const iadst8_coeffs, align=4
31 .short 16305, 1606, 14449, 7723, 10394, 12665, 4756, 15679
32 idct_coeffs:
33 .short 11585, 6270, 15137, 3196, 16069, 13623, 9102, 1606
34 .short 16305, 12665, 10394, 7723, 14449, 15679, 4756, 0
35 .short 804, 16364, 12140, 11003, 7005, 14811, 15426, 5520
36 .short 3981, 15893, 14053, 8423, 9760, 13160, 16207, 2404
37 endconst
38
39 const iadst16_coeffs, align=4
40 .short 16364, 804, 15893, 3981, 14811, 7005, 13160, 9760
41 .short 11003, 12140, 8423, 14053, 5520, 15426, 2404, 16207
42 endconst
43
44 @ Do four 4x4 transposes, using q registers for the subtransposes that don't
45 @ need to address the individual d registers.
46 @ r0,r1 == rq1, r2,r3 == rq1, etc
47 .macro transpose16_q_4x_4x4 rq0, rq1, rq2, rq3, rq4, rq5, rq6, rq7, r0, r1, r2, r3, r4, r5, r6, r7, r8, r9, r10, r11, r12, r13, r14, r15
48 vtrn.32 \rq0, \rq1
49 vtrn.32 \rq2, \rq3
50 vtrn.32 \rq4, \rq5
51 vtrn.32 \rq6, \rq7
52 vtrn.16 \r0, \r1
53 vtrn.16 \r2, \r3
54 vtrn.16 \r4, \r5
55 vtrn.16 \r6, \r7
56 vtrn.16 \r8, \r9
57 vtrn.16 \r10, \r11
58 vtrn.16 \r12, \r13
59 vtrn.16 \r14, \r15
60 .endm
61
62 @ out1 = ((in1 + in2) * d0[0] + (1 << 13)) >> 14
63 @ out2 = ((in1 - in2) * d0[0] + (1 << 13)) >> 14
64 @ in/out are d registers
65 .macro mbutterfly0 out1, out2, in1, in2, tmpd1, tmpd2, tmpq3, tmpq4, neg=0
66 vadd.s16 \tmpd1, \in1, \in2
67 vsub.s16 \tmpd2, \in1, \in2
68 vmull.s16 \tmpq3, \tmpd1, d0[0]
69 vmull.s16 \tmpq4, \tmpd2, d0[0]
70 .if \neg > 0
71 vneg.s32 \tmpq3, \tmpq3
72 .endif
73 vrshrn.s32 \out1, \tmpq3, #14
74 vrshrn.s32 \out2, \tmpq4, #14
75 .endm
76
77 @ 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 = unused
663 @ r2 = src
664 @ r3 = slice offset
665 function \txfm\()16_1d_4x16_pass1_neon
666 mov r12, #32
667 vmov.s16 q2, #0
668 .irp i, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31
669 vld1.16 {d\i}, [r2,:64]
670 vst1.16 {d4}, [r2,:64], r12
671 .endr
672
673 \txfm\()16
674
675 @ Do four 4x4 transposes. Originally, d16-d31 contain the
676 @ 16 rows. Afterwards, d16-d19, d20-d23, d24-d27, d28-d31
677 @ contain the transposed 4x4 blocks.
678 transpose16_q_4x_4x4 q8, q9, q10, q11, q12, q13, q14, q15, d16, d17, d18, d19, d20, d21, d22, d23, d24, d25, d26, d27, d28, d29, d30, d31
679
680 @ Store the transposed 4x4 blocks horizontally.
681 cmp r3, #12
682 beq 1f
683 .irp i, 16, 20, 24, 28, 17, 21, 25, 29, 18, 22, 26, 30, 19, 23, 27, 31
684 vst1.16 {d\i}, [r0,:64]!
685 .endr
686 bx lr
687 1:
688 @ Special case: For the last input column (r3 == 12),
689 @ which would be stored as the last row in the temp buffer,
690 @ don't store the first 4x4 block, but keep it in registers
691 @ for the first slice of the second pass (where it is the
692 @ last 4x4 block).
693 add r0, r0, #8
694 .irp i, 20, 24, 28
695 vst1.16 {d\i}, [r0,:64]!
696 .endr
697 add r0, r0, #8
698 .irp i, 21, 25, 29
699 vst1.16 {d\i}, [r0,:64]!
700 .endr
701 add r0, r0, #8
702 .irp i, 22, 26, 30
703 vst1.16 {d\i}, [r0,:64]!
704 .endr
705 add r0, r0, #8
706 .irp i, 23, 27, 31
707 vst1.16 {d\i}, [r0,:64]!
708 .endr
709 vmov d28, d16
710 vmov d29, d17
711 vmov d30, d18
712 vmov d31, d19
713 bx lr
714 endfunc
715
716 @ Read a vertical 4x16 slice out of a 16x16 matrix, do a transform on it,
717 @ load the destination pixels (from a similar 4x16 slice), add and store back.
718 @ r0 = dst
719 @ r1 = dst stride
720 @ r2 = src (temp buffer)
721 @ r3 = slice offset
722 function \txfm\()16_1d_4x16_pass2_neon
723 mov r12, #32
724 .irp i, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27
725 vld1.16 {d\i}, [r2,:64], r12
726 .endr
727 cmp r3, #0
728 beq 1f
729 .irp i, 28, 29, 30, 31
730 vld1.16 {d\i}, [r2,:64], r12
731 .endr
732 1:
733
734 add r3, r0, r1
735 lsl r1, r1, #1
736 \txfm\()16
737
738 .macro load_add_store coef0, coef1, coef2, coef3
739 vrshr.s16 \coef0, \coef0, #6
740 vrshr.s16 \coef1, \coef1, #6
741
742 vld1.32 {d4[]}, [r0,:32], r1
743 vld1.32 {d4[1]}, [r3,:32], r1
744 vrshr.s16 \coef2, \coef2, #6
745 vrshr.s16 \coef3, \coef3, #6
746 vld1.32 {d5[]}, [r0,:32], r1
747 vld1.32 {d5[1]}, [r3,:32], r1
748 vaddw.u8 \coef0, \coef0, d4
749 vld1.32 {d6[]}, [r0,:32], r1
750 vld1.32 {d6[1]}, [r3,:32], r1
751 vaddw.u8 \coef1, \coef1, d5
752 vld1.32 {d7[]}, [r0,:32], r1
753 vld1.32 {d7[1]}, [r3,:32], r1
754
755 vqmovun.s16 d4, \coef0
756 vqmovun.s16 d5, \coef1
757 sub r0, r0, r1, lsl #2
758 sub r3, r3, r1, lsl #2
759 vaddw.u8 \coef2, \coef2, d6
760 vaddw.u8 \coef3, \coef3, d7
761 vst1.32 {d4[0]}, [r0,:32], r1
762 vst1.32 {d4[1]}, [r3,:32], r1
763 vqmovun.s16 d6, \coef2
764 vst1.32 {d5[0]}, [r0,:32], r1
765 vst1.32 {d5[1]}, [r3,:32], r1
766 vqmovun.s16 d7, \coef3
767
768 vst1.32 {d6[0]}, [r0,:32], r1
769 vst1.32 {d6[1]}, [r3,:32], r1
770 vst1.32 {d7[0]}, [r0,:32], r1
771 vst1.32 {d7[1]}, [r3,:32], r1
772 .endm
773 load_add_store q8, q9, q10, q11
774 load_add_store q12, q13, q14, q15
775 .purgem load_add_store
776
777 bx lr
778 endfunc
779 .endm
780
781 itxfm16_1d_funcs idct
782 itxfm16_1d_funcs iadst
783
784 .macro itxfm_func16x16 txfm1, txfm2
785 function ff_vp9_\txfm1\()_\txfm2\()_16x16_add_neon, export=1
786 .ifc \txfm1\()_\txfm2,idct_idct
787 cmp r3, #1
788 beq idct16x16_dc_add_neon
789 .endif
790 push {r4-r7,lr}
791 .ifnc \txfm1\()_\txfm2,idct_idct
792 vpush {q4-q7}
793 .endif
794
795 @ Align the stack, allocate a temp buffer
796 T mov r7, sp
797 T and r7, r7, #15
798 A and r7, sp, #15
799 add r7, r7, #512
800 sub sp, sp, r7
801
802 mov r4, r0
803 mov r5, r1
804 mov r6, r2
805
806 .ifc \txfm1,idct
807 movrel r12, idct_coeffs
808 vld1.16 {q0-q1}, [r12,:128]
809 .endif
810
811 .irp i, 0, 4, 8, 12
812 add r0, sp, #(\i*32)
813 add r2, r6, #(\i*2)
814 mov r3, #\i
815 bl \txfm1\()16_1d_4x16_pass1_neon
816 .endr
817 .ifc \txfm1\()_\txfm2,iadst_idct
818 movrel r12, idct_coeffs
819 vld1.16 {q0-q1}, [r12,:128]
820 .endif
821 .irp i, 0, 4, 8, 12
822 add r0, r4, #(\i)
823 mov r1, r5
824 add r2, sp, #(\i*2)
825 mov r3, #\i
826 bl \txfm2\()16_1d_4x16_pass2_neon
827 .endr
828
829 add sp, sp, r7
830 .ifnc \txfm1\()_\txfm2,idct_idct
831 vpop {q4-q7}
832 .endif
833 pop {r4-r7,pc}
834 endfunc
835 .endm
836
837 itxfm_func16x16 idct, idct
838 itxfm_func16x16 iadst, idct
839 itxfm_func16x16 idct, iadst
840 itxfm_func16x16 iadst, iadst
841 .ltorg
842
843
844 function idct32x32_dc_add_neon
845 movrel r12, idct_coeffs
846 vld1.16 {d0}, [r12,:64]
847
848 vmov.i16 q2, #0
849
850 vld1.16 {d16[]}, [r2,:16]
851 vmull.s16 q8, d16, d0[0]
852 vrshrn.s32 d16, q8, #14
853 vmull.s16 q8, d16, d0[0]
854 vrshrn.s32 d16, q8, #14
855 vdup.16 q8, d16[0]
856 vst1.16 {d4[0]}, [r2,:16]
857
858 vrshr.s16 q8, q8, #6
859
860 mov r12, #32
861 1:
862 @ Loop to add the constant from q8 into all 32x32 outputs
863 vld1.8 {q2-q3}, [r0,:128]
864 vaddw.u8 q10, q8, d4
865 vaddw.u8 q11, q8, d5
866 vaddw.u8 q12, q8, d6
867 vaddw.u8 q13, q8, d7
868 vqmovun.s16 d4, q10
869 vqmovun.s16 d5, q11
870 vqmovun.s16 d6, q12
871 vqmovun.s16 d7, q13
872 vst1.8 {q2-q3}, [r0,:128], r1
873 subs r12, r12, #1
874 bne 1b
875
876 bx lr
877 endfunc
878
879 .macro idct32_odd
880 movrel r12, idct_coeffs
881 add r12, r12, #32
882 vld1.16 {q0-q1}, [r12,:128]
883
884 mbutterfly d16, d31, d0[0], d0[1], q2, q3 @ d16 = t16a, d31 = t31a
885 mbutterfly d24, d23, d0[2], d0[3], q2, q3 @ d24 = t17a, d23 = t30a
886 mbutterfly d20, d27, d1[0], d1[1], q2, q3 @ d20 = t18a, d27 = t29a
887 mbutterfly d28, d19, d1[2], d1[3], q2, q3 @ d28 = t19a, d19 = t28a
888 mbutterfly d18, d29, d2[0], d2[1], q2, q3 @ d18 = t20a, d29 = t27a
889 mbutterfly d26, d21, d2[2], d2[3], q2, q3 @ d26 = t21a, d21 = t26a
890 mbutterfly d22, d25, d3[0], d3[1], q2, q3 @ d22 = t22a, d25 = t25a
891 mbutterfly d30, d17, d3[2], d3[3], q2, q3 @ d30 = t23a, d17 = t24a
892
893 sub r12, r12, #32
894 vld1.16 {q0}, [r12,:128]
895
896 butterfly d4, d24, d16, d24 @ d4 = t16, d24 = t17
897 butterfly d5, d20, d28, d20 @ d5 = t19, d20 = t18
898 butterfly d6, d26, d18, d26 @ d6 = t20, d26 = t21
899 butterfly d7, d22, d30, d22 @ d7 = t23, d22 = t22
900 butterfly d28, d25, d17, d25 @ d28 = t24, d25 = t25
901 butterfly d30, d21, d29, d21 @ d30 = t27, d21 = t26
902 butterfly d29, d23, d31, d23 @ d29 = t31, d23 = t30
903 butterfly d31, d27, d19, d27 @ d31 = t28, d27 = t29
904
905 mbutterfly d23, d24, d0[3], d1[0], q8, q9 @ d23 = t17a, d24 = t30a
906 mbutterfly d27, d20, d0[3], d1[0], q8, q9, neg=1 @ d27 = t29a, d20 = t18a
907 mbutterfly d21, d26, d1[1], d1[2], q8, q9 @ d21 = t21a, d26 = t26a
908 mbutterfly d25, d22, d1[1], d1[2], q8, q9, neg=1 @ d25 = t25a, d22 = t22a
909
910 butterfly d16, d5, d4, d5 @ d16 = t16a, d5 = t19a
911 butterfly d17, d20, d23, d20 @ d17 = t17, d20 = t18
912 butterfly d18, d6, d7, d6 @ d18 = t23a, d6 = t20a
913 butterfly d19, d21, d22, d21 @ d19 = t22, d21 = t21
914 butterfly d4, d28, d28, d30 @ d4 = t24a, d28 = t27a
915 butterfly d23, d26, d25, d26 @ d23 = t25, d26 = t26
916 butterfly d7, d29, d29, d31 @ d7 = t31a, d29 = t28a
917 butterfly d22, d27, d24, d27 @ d22 = t30, d27 = t29
918
919 mbutterfly d27, d20, d0[1], d0[2], q12, q15 @ d27 = t18a, d20 = t29a
920 mbutterfly d29, d5, d0[1], d0[2], q12, q15 @ d29 = t19, d5 = t28
921 mbutterfly d28, d6, d0[1], d0[2], q12, q15, neg=1 @ d28 = t27, d6 = t20
922 mbutterfly d26, d21, d0[1], d0[2], q12, q15, neg=1 @ d26 = t26a, d21 = t21a
923
924 butterfly d31, d24, d7, d4 @ d31 = t31, d24 = t24
925 butterfly d30, d25, d22, d23 @ d30 = t30a, d25 = t25a
926 butterfly_r d23, d16, d16, d18 @ d23 = t23, d16 = t16
927 butterfly_r d22, d17, d17, d19 @ d22 = t22a, d17 = t17a
928 butterfly d18, d21, d27, d21 @ d18 = t18, d21 = t21
929 butterfly_r d27, d28, d5, d28 @ d27 = t27a, d28 = t28a
930 butterfly d4, d26, d20, d26 @ d4 = t29, d26 = t26
931 butterfly d19, d20, d29, d6 @ d19 = t19a, d20 = t20
932 vmov d29, d4 @ d29 = t29
933
934 mbutterfly0 d27, d20, d27, d20, d4, d6, q2, q3 @ d27 = t27, d20 = t20
935 mbutterfly0 d26, d21, d26, d21, d4, d6, q2, q3 @ d26 = t26a, d21 = t21a
936 mbutterfly0 d25, d22, d25, d22, d4, d6, q2, q3 @ d25 = t25, d22 = t22
937 mbutterfly0 d24, d23, d24, d23, d4, d6, q2, q3 @ d24 = t24a, d23 = t23a
938 .endm
939
940 @ Do an 32-point IDCT of a 4x32 slice out of a 32x32 matrix.
941 @ We don't have register space to do a single pass IDCT of 4x32 though,
942 @ but the 32-point IDCT can be decomposed into two 16-point IDCTs;
943 @ a normal IDCT16 with every other input component (the even ones, with
944 @ each output written twice), followed by a separate 16-point IDCT
945 @ of the odd inputs, added/subtracted onto the outputs of the first idct16.
946 @ r0 = dst (temp buffer)
947 @ r1 = unused
948 @ r2 = src
949 function idct32_1d_4x32_pass1_neon
950 movrel r12, idct_coeffs
951 vld1.16 {q0-q1}, [r12,:128]
952
953 @ Double stride of the input, since we only read every other line
954 mov r12, #128
955 vmov.s16 d4, #0
956
957 @ d16 = IN(0), d17 = IN(2) ... d31 = IN(30)
958 .irp i, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31
959 vld1.16 {d\i}, [r2,:64]
960 vst1.16 {d4}, [r2,:64], r12
961 .endr
962
963 idct16
964
965 @ Do four 4x4 transposes. Originally, d16-d31 contain the
966 @ 16 rows. Afterwards, d16-d19, d20-d23, d24-d27, d28-d31
967 @ contain the transposed 4x4 blocks.
968 transpose16_q_4x_4x4 q8, q9, q10, q11, q12, q13, q14, q15, d16, d17, d18, d19, d20, d21, d22, d23, d24, d25, d26, d27, d28, d29, d30, d31
969 @ Store the registers a, b, c, d horizontally, followed
970 @ by the same registers d, c, b, a mirrored.
971 .macro store_rev a, b, c, d
972 .irp i, \a, \b, \c, \d
973 vst1.16 {d\i}, [r0,:64]!
974 vrev64.16 d\i, d\i
975 .endr
976 .irp i, \d, \c, \b, \a
977 vst1.16 {d\i}, [r0,:64]!
978 .endr
979 .endm
980 store_rev 16, 20, 24, 28
981 store_rev 17, 21, 25, 29
982 store_rev 18, 22, 26, 30
983 store_rev 19, 23, 27, 31
984 sub r0, r0, #256
985 .purgem store_rev
986
987 @ Move r2 back to the start of the input, and move
988 @ to the first odd row
989 sub r2, r2, r12, lsl #4
990 add r2, r2, #64
991
992 vmov.s16 d4, #0
993 @ d16 = IN(1), d17 = IN(3) ... d31 = IN(31)
994 .irp i, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31
995 vld1.16 {d\i}, [r2,:64]
996 vst1.16 {d4}, [r2,:64], r12
997 .endr
998
999 idct32_odd
1000
1001 transpose16_q_4x_4x4 q15, q14, q13, q12, q11, q10, q9, q8, d31, d30, d29, d28, d27, d26, d25, d24, d23, d22, d21, d20, d19, d18, d17, d16
1002
1003 @ Store the registers a, b, c, d horizontally,
1004 @ adding into the output first, and then mirrored, subtracted
1005 @ from the output.
1006 .macro store_rev a, b, c, d
1007 .irp i, \a, \b, \c, \d
1008 vld1.16 {d4}, [r0,:64]
1009 vadd.s16 d4, d4, d\i
1010 vst1.16 {d4}, [r0,:64]!
1011 vrev64.16 d\i, d\i
1012 .endr
1013 .irp i, \d, \c, \b, \a
1014 vld1.16 {d4}, [r0,:64]
1015 vsub.s16 d4, d4, d\i
1016 vst1.16 {d4}, [r0,:64]!
1017 .endr
1018 .endm
1019
1020 store_rev 31, 27, 23, 19
1021 store_rev 30, 26, 22, 18
1022 store_rev 29, 25, 21, 17
1023 store_rev 28, 24, 20, 16
1024 .purgem store_rev
1025 bx lr
1026 endfunc
1027 .ltorg
1028
1029 @ This is mostly the same as 4x32_pass1, but without the transpose,
1030 @ and use the source as temp buffer between the two idct passes, and
1031 @ add into the destination.
1032 @ r0 = dst
1033 @ r1 = dst stride
1034 @ r2 = src (temp buffer)
1035 function idct32_1d_4x32_pass2_neon
1036 movrel r12, idct_coeffs
1037 vld1.16 {q0-q1}, [r12,:128]
1038
1039 mov r12, #128
1040 @ d16 = IN(0), d17 = IN(2) ... d31 = IN(30)
1041 .irp i, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31
1042 vld1.16 {d\i}, [r2,:64], r12
1043 .endr
1044 sub r2, r2, r12, lsl #4
1045
1046 idct16
1047
1048 .irp i, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31
1049 vst1.16 {d\i}, [r2,:64], r12
1050 .endr
1051
1052 sub r2, r2, r12, lsl #4
1053 add r2, r2, #64
1054
1055 @ d16 = IN(1), d17 = IN(3) ... d31 = IN(31)
1056 .irp i, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31
1057 vld1.16 {d\i}, [r2,:64], r12
1058 .endr
1059 sub r2, r2, r12, lsl #4
1060 sub r2, r2, #64
1061
1062 idct32_odd
1063
1064 mov r12, #128
1065 .macro load_acc_store a, b, c, d, neg=0
1066 vld1.16 {d4}, [r2,:64], r12
1067 vld1.16 {d5}, [r2,:64], r12
1068 .if \neg == 0
1069 vadd.s16 d4, d4, d\a
1070 vld1.16 {d6}, [r2,:64], r12
1071 vadd.s16 d5, d5, d\b
1072 vld1.16 {d7}, [r2,:64], r12
1073 vadd.s16 d6, d6, d\c
1074 vadd.s16 d7, d7, d\d
1075 .else
1076 vsub.s16 d4, d4, d\a
1077 vld1.16 {d6}, [r2,:64], r12
1078 vsub.s16 d5, d5, d\b
1079 vld1.16 {d7}, [r2,:64], r12
1080 vsub.s16 d6, d6, d\c
1081 vsub.s16 d7, d7, d\d
1082 .endif
1083 vld1.32 {d2[]}, [r0,:32], r1
1084 vld1.32 {d2[1]}, [r0,:32], r1
1085 vrshr.s16 q2, q2, #6
1086 vld1.32 {d3[]}, [r0,:32], r1
1087 vrshr.s16 q3, q3, #6
1088 vld1.32 {d3[1]}, [r0,:32], r1
1089 sub r0, r0, r1, lsl #2
1090 vaddw.u8 q2, q2, d2
1091 vaddw.u8 q3, q3, d3
1092 vqmovun.s16 d4, q2
1093 vqmovun.s16 d5, q3
1094 vst1.32 {d4[0]}, [r0,:32], r1
1095 vst1.32 {d4[1]}, [r0,:32], r1
1096 vst1.32 {d5[0]}, [r0,:32], r1
1097 vst1.32 {d5[1]}, [r0,:32], r1
1098 .endm
1099 load_acc_store 31, 30, 29, 28
1100 load_acc_store 27, 26, 25, 24
1101 load_acc_store 23, 22, 21, 20
1102 load_acc_store 19, 18, 17, 16
1103 sub r2, r2, r12
1104 neg r12, r12
1105 load_acc_store 16, 17, 18, 19, 1
1106 load_acc_store 20, 21, 22, 23, 1
1107 load_acc_store 24, 25, 26, 27, 1
1108 load_acc_store 28, 29, 30, 31, 1
1109 .purgem load_acc_store
1110 bx lr
1111 endfunc
1112
1113 function ff_vp9_idct_idct_32x32_add_neon, export=1
1114 cmp r3, #1
1115 beq idct32x32_dc_add_neon
1116 push {r4-r7,lr}
1117 vpush {q4-q7}
1118
1119 @ Align the stack, allocate a temp buffer
1120 T mov r7, sp
1121 T and r7, r7, #15
1122 A and r7, sp, #15
1123 add r7, r7, #2048
1124 sub sp, sp, r7
1125
1126 mov r4, r0
1127 mov r5, r1
1128 mov r6, r2
1129
1130 .irp i, 0, 4, 8, 12, 16, 20, 24, 28
1131 add r0, sp, #(\i*64)
1132 add r2, r6, #(\i*2)
1133 bl idct32_1d_4x32_pass1_neon
1134 .endr
1135 .irp i, 0, 4, 8, 12, 16, 20, 24, 28
1136 add r0, r4, #(\i)
1137 mov r1, r5
1138 add r2, sp, #(\i*2)
1139 bl idct32_1d_4x32_pass2_neon
1140 .endr
1141
1142 add sp, sp, r7
1143 vpop {q4-q7}
1144 pop {r4-r7,pc}
1145 endfunc