2 * Copyright (c) 2016 Google Inc.
4 * This file is part of FFmpeg.
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.
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.
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
21 #include "libavutil/arm/asm.S"
24 const itxfm4_coeffs, align=4
25 .short 11585, 0, 6270, 15137
27 .short 5283, 15212, 9929, 13377
30 const iadst8_coeffs, align=4
31 .short 16305, 1606, 14449, 7723, 10394, 12665, 4756, 15679
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
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
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
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]
71 vneg.s32 \tmpq3, \tmpq3
73 vrshrn.s32 \out1, \tmpq3, #14
74 vrshrn.s32 \out2, \tmpq4, #14
77 @ Same as mbutterfly0 above, but treating the input in in2 as zero,
78 @ writing the same output into both out1 and out2.
79 .macro mbutterfly0_h out1, out2, in1, in2, tmpd1, tmpd2, tmpq3, tmpq4
80 vmull.s16 \tmpq3, \in1, d0[0]
81 vrshrn.s32 \out1, \tmpq3, #14
82 vrshrn.s32 \out2, \tmpq3, #14
85 @ out1,out2 = ((in1 + in2) * d0[0] + (1 << 13)) >> 14
86 @ out3,out4 = ((in1 - in2) * d0[0] + (1 << 13)) >> 14
87 @ Same as mbutterfly0, but with input being 2 q registers, output
88 @ being 4 d registers.
89 @ This can do with either 4 or 6 temporary q registers.
90 .macro dmbutterfly0 out1, out2, out3, out4, in1, in2, tmpq1, tmpq2, tmpd11, tmpd12, tmpd21, tmpd22, tmpq3, tmpq4, tmpq5, tmpq6
91 vadd.s16 \tmpq1, \in1, \in2
92 vsub.s16 \tmpq2, \in1, \in2
93 vmull.s16 \tmpq3, \tmpd11, d0[0]
94 vmull.s16 \tmpq4, \tmpd12, d0[0]
96 vrshrn.s32 \out1, \tmpq3, #14
97 vrshrn.s32 \out2, \tmpq4, #14
98 vmull.s16 \tmpq3, \tmpd21, d0[0]
99 vmull.s16 \tmpq4, \tmpd22, d0[0]
100 vrshrn.s32 \out3, \tmpq3, #14
101 vrshrn.s32 \out4, \tmpq4, #14
103 vmull.s16 \tmpq5, \tmpd21, d0[0]
104 vmull.s16 \tmpq6, \tmpd22, d0[0]
105 vrshrn.s32 \out1, \tmpq3, #14
106 vrshrn.s32 \out2, \tmpq4, #14
107 vrshrn.s32 \out3, \tmpq5, #14
108 vrshrn.s32 \out4, \tmpq6, #14
112 @ out1 = in1 * coef1 - in2 * coef2
113 @ out2 = in1 * coef2 + in2 * coef1
114 @ out are 2 q registers, in are 2 d registers
115 .macro mbutterfly_l out1, out2, in1, in2, coef1, coef2
116 vmull.s16 \out1, \in1, \coef1
117 vmlsl.s16 \out1, \in2, \coef2
118 vmull.s16 \out2, \in1, \coef2
119 vmlal.s16 \out2, \in2, \coef1
122 @ out1,out2 = in1,in2 * coef1 - in3,in4 * coef2
123 @ out3,out4 = in1,in2 * coef2 + in3,in4 * coef1
124 @ out are 4 q registers, in are 4 d registers
125 .macro dmbutterfly_l out1, out2, out3, out4, in1, in2, in3, in4, coef1, coef2
126 vmull.s16 \out1, \in1, \coef1
127 vmull.s16 \out2, \in2, \coef1
128 vmull.s16 \out3, \in1, \coef2
129 vmull.s16 \out4, \in2, \coef2
130 vmlsl.s16 \out1, \in3, \coef2
131 vmlsl.s16 \out2, \in4, \coef2
132 vmlal.s16 \out3, \in3, \coef1
133 vmlal.s16 \out4, \in4, \coef1
136 @ inout1 = (inout1 * coef1 - inout2 * coef2 + (1 << 13)) >> 14
137 @ inout2 = (inout1 * coef2 + inout2 * coef1 + (1 << 13)) >> 14
138 @ inout are 2 d registers, tmp are 2 q registers
139 .macro mbutterfly inout1, inout2, coef1, coef2, tmp1, tmp2, neg=0
140 mbutterfly_l \tmp1, \tmp2, \inout1, \inout2, \coef1, \coef2
142 vneg.s32 \tmp2, \tmp2
144 vrshrn.s32 \inout1, \tmp1, #14
145 vrshrn.s32 \inout2, \tmp2, #14
148 @ Same as mbutterfly above, but treating the input in inout2 as zero
149 .macro mbutterfly_h1 inout1, inout2, coef1, coef2, tmp1, tmp2
150 vmull.s16 \tmp1, \inout1, \coef1
151 vmull.s16 \tmp2, \inout1, \coef2
152 vrshrn.s32 \inout1, \tmp1, #14
153 vrshrn.s32 \inout2, \tmp2, #14
156 @ Same as mbutterfly above, but treating the input in inout1 as zero
157 .macro mbutterfly_h2 inout1, inout2, coef1, coef2, tmp1, tmp2
158 vmull.s16 \tmp1, \inout2, \coef2
159 vmull.s16 \tmp2, \inout2, \coef1
160 vneg.s32 \tmp1, \tmp1
161 vrshrn.s32 \inout2, \tmp2, #14
162 vrshrn.s32 \inout1, \tmp1, #14
165 @ inout1,inout2 = (inout1,inout2 * coef1 - inout3,inout4 * coef2 + (1 << 13)) >> 14
166 @ inout3,inout4 = (inout1,inout2 * coef2 + inout3,inout4 * coef1 + (1 << 13)) >> 14
167 @ inout are 4 d registers, tmp are 4 q registers
168 .macro dmbutterfly inout1, inout2, inout3, inout4, coef1, coef2, tmp1, tmp2, tmp3, tmp4
169 dmbutterfly_l \tmp1, \tmp2, \tmp3, \tmp4, \inout1, \inout2, \inout3, \inout4, \coef1, \coef2
170 vrshrn.s32 \inout1, \tmp1, #14
171 vrshrn.s32 \inout2, \tmp2, #14
172 vrshrn.s32 \inout3, \tmp3, #14
173 vrshrn.s32 \inout4, \tmp4, #14
178 .macro butterfly out1, out2, in1, in2
179 vadd.s16 \out1, \in1, \in2
180 vsub.s16 \out2, \in1, \in2
185 .macro butterfly_r out1, out2, in1, in2
186 vsub.s16 \out1, \in1, \in2
187 vadd.s16 \out2, \in1, \in2
190 @ out1 = (in1 + in2 + (1 << 13)) >> 14
191 @ out2 = (in1 - in2 + (1 << 13)) >> 14
192 @ out are 2 d registers, in are 2 q registers, tmp are 2 q registers
193 .macro butterfly_n out1, out2, in1, in2, tmp1, tmp2
194 vadd.s32 \tmp1, \in1, \in2
195 vsub.s32 \tmp2, \in1, \in2
196 vrshrn.s32 \out1, \tmp1, #14
197 vrshrn.s32 \out2, \tmp2, #14
200 @ out1,out2 = (in1,in2 + in3,in4 + (1 << 13)) >> 14
201 @ out3,out4 = (in1,in2 - in3,in4 + (1 << 13)) >> 14
202 @ out are 4 d registers, in are 4 q registers, tmp are 4 q registers
203 .macro dbutterfly_n out1, out2, out3, out4, in1, in2, in3, in4, tmp1, tmp2, tmp3, tmp4
204 vadd.s32 \tmp1, \in1, \in3
205 vadd.s32 \tmp2, \in2, \in4
206 vsub.s32 \tmp3, \in1, \in3
207 vsub.s32 \tmp4, \in2, \in4
208 vrshrn.s32 \out1, \tmp1, #14
209 vrshrn.s32 \out2, \tmp2, #14
210 vrshrn.s32 \out3, \tmp3, #14
211 vrshrn.s32 \out4, \tmp4, #14
215 .macro iwht4 c0, c1, c2, c3
216 vadd.i16 \c0, \c0, \c1
217 vsub.i16 d17, \c2, \c3
218 vsub.i16 d16, \c0, d17
219 vshr.s16 d16, d16, #1
220 vsub.i16 \c2, d16, \c1
221 vsub.i16 \c1, d16, \c3
222 vadd.i16 \c3, d17, \c2
223 vsub.i16 \c0, \c0, \c1
226 .macro idct4 c0, c1, c2, c3
227 vmull.s16 q13, \c1, d0[3]
228 vmull.s16 q11, \c1, d0[2]
229 vadd.i16 d16, \c0, \c2
230 vsub.i16 d17, \c0, \c2
231 vmlal.s16 q13, \c3, d0[2]
232 vmull.s16 q9, d16, d0[0]
233 vmull.s16 q10, d17, d0[0]
234 vmlsl.s16 q11, \c3, d0[3]
235 vrshrn.s32 d26, q13, #14
236 vrshrn.s32 d18, q9, #14
237 vrshrn.s32 d20, q10, #14
238 vrshrn.s32 d22, q11, #14
239 vadd.i16 \c0, d18, d26
240 vsub.i16 \c3, d18, d26
241 vadd.i16 \c1, d20, d22
242 vsub.i16 \c2, d20, d22
245 .macro iadst4 c0, c1, c2, c3
246 vmull.s16 q10, \c0, d1[0]
247 vmlal.s16 q10, \c2, d1[1]
248 vmlal.s16 q10, \c3, d1[2]
249 vmull.s16 q11, \c0, d1[2]
250 vmlsl.s16 q11, \c2, d1[0]
251 vsub.s16 \c0, \c0, \c2
252 vmlsl.s16 q11, \c3, d1[1]
253 vadd.s16 \c0, \c0, \c3
254 vmull.s16 q13, \c1, d1[3]
255 vmull.s16 q12, \c0, d1[3]
256 vadd.s32 q14, q10, q13
257 vadd.s32 q1, q11, q13
258 vrshrn.s32 \c0, q14, #14
259 vadd.s32 q10, q10, q11
260 vrshrn.s32 \c1, q1, #14
261 vsub.s32 q10, q10, q13
262 vrshrn.s32 \c2, q12, #14
263 vrshrn.s32 \c3, q10, #14
266 @ The public functions in this file have got the following signature:
267 @ void itxfm_add(uint8_t *dst, ptrdiff_t stride, int16_t *block, int eob);
269 .macro itxfm_func4x4 txfm1, txfm2
270 function ff_vp9_\txfm1\()_\txfm2\()_4x4_add_neon, export=1
273 movrel r12, itxfm4_coeffs
274 vld1.16 {d0}, [r12,:64]
277 movrel r12, iadst4_coeffs
278 vld1.16 {d1}, [r12,:64]
281 movrel r12, itxfm4_coeffs
282 vld1.16 {q0}, [r12,:128]
286 .ifc \txfm1\()_\txfm2,idct_idct
289 @ DC-only for idct/idct
290 vld1.16 {d4[]}, [r2,:16]
291 vmull.s16 q2, d4, d0[0]
292 vrshrn.s32 d4, q2, #14
293 vmull.s16 q2, d4, d0[0]
294 vrshrn.s32 d4, q2, #14
295 vst1.16 {d30[0]}, [r2,:16]
302 vld1.16 {d4-d7}, [r2,:128]
303 vst1.16 {q15}, [r2,:128]!
310 \txfm1\()4 d4, d5, d6, d7
312 vst1.16 {q15}, [r2,:128]!
313 @ Transpose 4x4 with 16 bit elements
318 \txfm2\()4 d4, d5, d6, d7
320 vld1.32 {d0[]}, [r0,:32], r1
321 vld1.32 {d0[1]}, [r0,:32], r1
327 vld1.32 {d1[]}, [r0,:32], r1
328 vld1.32 {d1[1]}, [r0,:32], r1
330 sub r0, r0, r1, lsl #2
333 vst1.32 {d0[0]}, [r0,:32], r1
336 vst1.32 {d0[1]}, [r0,:32], r1
337 vst1.32 {d1[0]}, [r0,:32], r1
338 vst1.32 {d1[1]}, [r0,:32], r1
344 itxfm_func4x4 idct, idct
345 itxfm_func4x4 iadst, idct
346 itxfm_func4x4 idct, iadst
347 itxfm_func4x4 iadst, iadst
348 itxfm_func4x4 iwht, iwht
352 dmbutterfly0 d16, d17, d24, d25, q8, q12, q2, q4, d4, d5, d8, d9, q3, q2, q5, q4 @ q8 = t0a, q12 = t1a
353 dmbutterfly d20, d21, d28, d29, d0[2], d0[3], q2, q3, q4, q5 @ q10 = t2a, q14 = t3a
354 dmbutterfly d18, d19, d30, d31, d1[0], d1[1], q2, q3, q4, q5 @ q9 = t4a, q15 = t7a
355 dmbutterfly d26, d27, d22, d23, d1[2], d1[3], q2, q3, q4, q5 @ q13 = t5a, q11 = t6a
357 butterfly q2, q14, q8, q14 @ q2 = t0, q14 = t3
358 butterfly q3, q10, q12, q10 @ q3 = t1, q10 = t2
359 butterfly q4, q13, q9, q13 @ q4 = t4, q13 = t5a
360 butterfly q5, q11, q15, q11 @ q5 = t7, q11 = t6a
362 butterfly q8, q15, q2, q5 @ q8 = out[0], q15 = out[7]
364 dmbutterfly0 d4, d5, d10, d11, q11, q13, q9, q13, d18, d19, d26, d27, q2, q5, q11, q12 @ q2 = t6, q5 = t5
366 butterfly q11, q12, q14, q4 @ q11 = out[3], q12 = out[4]
367 butterfly q9, q14, q3, q2 @ q9 = out[1], q14 = out[6]
368 butterfly_r q13, q10, q10, q5 @ q13 = out[5], q10 = out[2]
372 dmbutterfly_l q4, q5, q2, q3, d30, d31, d16, d17, d2[1], d2[0] @ q4,q5 = t1a, q2,q3 = t0a
373 dmbutterfly_l q8, q15, q6, q7, d22, d23, d24, d25, d3[1], d3[0] @ q8,q15 = t5a, q6,q7 = t4a
375 dbutterfly_n d22, d23, d4, d5, q2, q3, q6, q7, q11, q12, q2, q3 @ q11 = t0, q2 = t4
377 dbutterfly_n d24, d25, d6, d7, q4, q5, q8, q15, q12, q3, q6, q7 @ q12 = t1, q3 = t5
379 dmbutterfly_l q6, q7, q4, q5, d26, d27, d20, d21, d2[3], d2[2] @ q6,q7 = t3a, q4,q5 = t2a
380 dmbutterfly_l q10, q13, q8, q15, d18, d19, d28, d29, d3[3], d3[2] @ q10,q13 = t7a, q8,q15 = t6a
382 dbutterfly_n d18, d19, d8, d9, q4, q5, q8, q15, q9, q14, q4, q5 @ q9 = t2, q4 = t6
383 dbutterfly_n d16, d17, d12, d13, q6, q7, q10, q13, q8, q15, q6, q7 @ q8 = t3, q6 = t7
385 butterfly q15, q12, q12, q8 @ q15 = -out[7], q12 = t3
386 vneg.s16 q15, q15 @ q15 = out[7]
387 butterfly q8, q9, q11, q9 @ q8 = out[0], q9 = t2
389 dmbutterfly_l q10, q11, q5, q7, d4, d5, d6, d7, d0[2], d0[3] @ q10,q11 = t5a, q5,q7 = t4a
390 dmbutterfly_l q2, q3, q13, q14, d12, d13, d8, d9, d0[3], d0[2] @ q2,q3 = t6a, q13,q14 = t7a
392 dbutterfly_n d28, d29, d8, d9, q10, q11, q13, q14, q4, q6, q10, q11 @ q14 = out[6], q4 = t7
394 dmbutterfly0 d22, d23, d24, d25, q9, q12, q6, q13, d12, d13, d26, d27, q9, q10 @ q11 = -out[3], q12 = out[4]
395 vneg.s16 q11, q11 @ q11 = out[3]
397 dbutterfly_n d18, d19, d4, d5, q5, q7, q2, q3, q9, q10, q2, q3 @ q9 = -out[1], q2 = t6
398 vneg.s16 q9, q9 @ q9 = out[1]
400 dmbutterfly0 d20, d21, d26, d27, q2, q4, q3, q5, d6, d7, d10, d11, q6, q7 @ q10 = out[2], q13 = -out[5]
401 vneg.s16 q13, q13 @ q13 = out[5]
405 .macro itxfm_func8x8 txfm1, txfm2
406 function ff_vp9_\txfm1\()_\txfm2\()_8x8_add_neon, export=1
407 @ Push q4-q7 if iadst is used, idct requires
408 @ a few scratch registers less, so only push q4-q5
409 @ if only idct is involved.
410 @ The iadst also uses a few coefficients from
411 @ idct, so those always need to be loaded.
412 .ifc \txfm1\()_\txfm2,idct_idct
413 movrel r12, idct_coeffs
416 movrel r12, iadst8_coeffs
417 vld1.16 {q1}, [r12,:128]!
420 vld1.16 {q0}, [r12,:128]
425 .ifc \txfm1\()_\txfm2,idct_idct
428 @ DC-only for idct/idct
429 vld1.16 {d16[]}, [r2,:16]
430 vmull.s16 q8, d16, d0[0]
431 vrshrn.s32 d16, q8, #14
432 vmull.s16 q8, d16, d0[0]
433 vrshrn.s32 d16, q8, #14
442 vst1.16 {d4[0]}, [r2,:16]
446 vld1.16 {q8-q9}, [r2,:128]!
447 vld1.16 {q10-q11}, [r2,:128]!
448 vld1.16 {q12-q13}, [r2,:128]!
449 vld1.16 {q14-q15}, [r2,:128]!
451 vst1.16 {q2-q3}, [r2,:128]!
452 vst1.16 {q2-q3}, [r2,:128]!
453 vst1.16 {q2-q3}, [r2,:128]!
454 vst1.16 {q2-q3}, [r2,:128]!
458 @ Transpose 8x8 with 16 bit elements
463 transpose16_4x4 q8, q9, q10, q11, q12, q13, q14, q15
468 @ Add into the destination
469 vld1.8 {d4}, [r0,:64], r1
471 vld1.8 {d5}, [r0,:64], r1
473 vld1.8 {d6}, [r0,:64], r1
474 vrshr.s16 q10, q10, #5
476 vld1.8 {d7}, [r0,:64], r1
477 vrshr.s16 q11, q11, #5
479 vld1.8 {d8}, [r0,:64], r1
480 vrshr.s16 q12, q12, #5
481 vaddw.u8 q10, q10, d6
483 vld1.8 {d9}, [r0,:64], r1
484 vrshr.s16 q13, q13, #5
485 vaddw.u8 q11, q11, d7
487 vld1.8 {d10}, [r0,:64], r1
488 vrshr.s16 q14, q14, #5
489 vaddw.u8 q12, q12, d8
491 vld1.8 {d11}, [r0,:64], r1
492 vrshr.s16 q15, q15, #5
493 vaddw.u8 q13, q13, d9
497 vst1.8 {d4}, [r3,:64], r1
498 vaddw.u8 q14, q14, d10
499 vst1.8 {d5}, [r3,:64], r1
501 vst1.8 {d6}, [r3,:64], r1
502 vaddw.u8 q15, q15, d11
503 vst1.8 {d7}, [r3,:64], r1
505 vst1.8 {d8}, [r3,:64], r1
507 vst1.8 {d9}, [r3,:64], r1
510 vst1.8 {d10}, [r3,:64], r1
511 vst1.8 {d11}, [r3,:64], r1
513 .ifc \txfm1\()_\txfm2,idct_idct
522 itxfm_func8x8 idct, idct
523 itxfm_func8x8 iadst, idct
525 itxfm_func8x8 idct, iadst
526 itxfm_func8x8 iadst, iadst
529 function idct16x16_dc_add_neon
530 movrel r12, idct_coeffs
531 vld1.16 {d0}, [r12,:64]
535 vld1.16 {d16[]}, [r2,:16]
536 vmull.s16 q8, d16, d0[0]
537 vrshrn.s32 d16, q8, #14
538 vmull.s16 q8, d16, d0[0]
539 vrshrn.s32 d16, q8, #14
541 vst1.16 {d4[0]}, [r2,:16]
548 @ Loop to add the constant from q8 into all 16x16 outputs
550 vld1.8 {q2}, [r0,:128], r1
552 vld1.8 {q3}, [r0,:128], r1
559 vst1.8 {q2}, [r3,:128], r1
561 vst1.8 {q3}, [r3,:128], r1
569 butterfly d18, d7, d4, d7 @ d18 = t0a, d7 = t7a
570 butterfly d19, d22, d5, d22 @ d19 = t1a, d22 = t6
571 butterfly d4, d26, d20, d26 @ d4 = t2a, d26 = t5
572 butterfly d5, d6, d28, d6 @ d5 = t3a, d6 = t4
573 butterfly d20, d28, d16, d24 @ d20 = t8a, d28 = t11a
574 butterfly d24, d21, d23, d21 @ d24 = t9, d21 = t10
575 butterfly d23, d27, d25, d27 @ d23 = t14, d27 = t13
576 butterfly d25, d29, d29, d17 @ d25 = t15a, d29 = t12a
578 mbutterfly0 d27, d21, d27, d21, d16, d30, q8, q15 @ d27 = t13a, d21 = t10a
579 mbutterfly0 d29, d28, d29, d28, d16, d30, q8, q15 @ d29 = t12, d28 = t11
581 vswp d27, d29 @ d27 = t12, d29 = t13a
582 vswp d28, d27 @ d28 = t12, d27 = t11
583 butterfly d16, d31, d18, d25 @ d16 = out[0], d31 = out[15]
584 butterfly d17, d30, d19, d23 @ d17 = out[1], d30 = out[14]
585 butterfly_r d25, d22, d22, d24 @ d25 = out[9], d22 = out[6]
586 butterfly d23, d24, d7, d20 @ d23 = out[7], d24 = out[8]
587 butterfly d18, d29, d4, d29 @ d18 = out[2], d29 = out[13]
588 butterfly d19, d28, d5, d28 @ d19 = out[3], d28 = out[12]
589 vmov d4, d21 @ d4 = t10a
590 butterfly d20, d27, d6, d27 @ d20 = out[4], d27 = out[11]
591 butterfly d21, d26, d26, d4 @ d21 = out[5], d26 = out[10]
596 mbutterfly0 d16, d24, d16, d24, d4, d6, q2, q3 @ d16 = t0a, d24 = t1a
597 mbutterfly d20, d28, d0[2], d0[3], q2, q3 @ d20 = t2a, d28 = t3a
598 mbutterfly d18, d30, d1[0], d1[1], q2, q3 @ d18 = t4a, d30 = t7a
599 mbutterfly d26, d22, d1[2], d1[3], q2, q3 @ d26 = t5a, d22 = t6a
600 mbutterfly d17, d31, d2[0], d2[1], q2, q3 @ d17 = t8a, d31 = t15a
601 mbutterfly d25, d23, d2[2], d2[3], q2, q3 @ d25 = t9a, d23 = t14a
602 mbutterfly d21, d27, d3[0], d3[1], q2, q3 @ d21 = t10a, d27 = t13a
603 mbutterfly d29, d19, d3[2], d3[3], q2, q3 @ d29 = t11a, d19 = t12a
605 butterfly d4, d28, d16, d28 @ d4 = t0, d28 = t3
606 butterfly d5, d20, d24, d20 @ d5 = t1, d20 = t2
607 butterfly d6, d26, d18, d26 @ d6 = t4, d26 = t5
608 butterfly d7, d22, d30, d22 @ d7 = t7, d22 = t6
609 butterfly d16, d25, d17, d25 @ d16 = t8, d25 = t9
610 butterfly d24, d21, d29, d21 @ d24 = t11, d21 = t10
611 butterfly d17, d27, d19, d27 @ d17 = t12, d27 = t13
612 butterfly d29, d23, d31, d23 @ d29 = t15, d23 = t14
614 mbutterfly0 d22, d26, d22, d26, d18, d30, q9, q15 @ d22 = t6a, d26 = t5a
615 mbutterfly d23, d25, d0[2], d0[3], q9, q15 @ d23 = t9a, d25 = t14a
616 mbutterfly d27, d21, d0[2], d0[3], q9, q15, neg=1 @ d27 = t13a, d21 = t10a
621 mbutterfly0_h d16, d24, d16, d24, d4, d6, q2, q3 @ d16 = t0a, d24 = t1a
622 mbutterfly_h1 d20, d28, d0[2], d0[3], q2, q3 @ d20 = t2a, d28 = t3a
623 mbutterfly_h1 d18, d30, d1[0], d1[1], q2, q3 @ d18 = t4a, d30 = t7a
624 mbutterfly_h2 d26, d22, d1[2], d1[3], q2, q3 @ d26 = t5a, d22 = t6a
625 mbutterfly_h1 d17, d31, d2[0], d2[1], q2, q3 @ d17 = t8a, d31 = t15a
626 mbutterfly_h2 d25, d23, d2[2], d2[3], q2, q3 @ d25 = t9a, d23 = t14a
627 mbutterfly_h1 d21, d27, d3[0], d3[1], q2, q3 @ d21 = t10a, d27 = t13a
628 mbutterfly_h2 d29, d19, d3[2], d3[3], q2, q3 @ d29 = t11a, d19 = t12a
630 butterfly d4, d28, d16, d28 @ d4 = t0, d28 = t3
631 butterfly d5, d20, d24, d20 @ d5 = t1, d20 = t2
632 butterfly d6, d26, d18, d26 @ d6 = t4, d26 = t5
633 butterfly d7, d22, d30, d22 @ d7 = t7, d22 = t6
634 butterfly d16, d25, d17, d25 @ d16 = t8, d25 = t9
635 butterfly d24, d21, d29, d21 @ d24 = t11, d21 = t10
636 butterfly d17, d27, d19, d27 @ d17 = t12, d27 = t13
637 butterfly d29, d23, d31, d23 @ d29 = t15, d23 = t14
639 mbutterfly0 d22, d26, d22, d26, d18, d30, q9, q15 @ d22 = t6a, d26 = t5a
640 mbutterfly d23, d25, d0[2], d0[3], q9, q15 @ d23 = t9a, d25 = t14a
641 mbutterfly d27, d21, d0[2], d0[3], q9, q15, neg=1 @ d27 = t13a, d21 = t10a
645 function idct16_quarter
646 vmull.s16 q12, d19, d3[3]
647 vmull.s16 q2, d17, d2[0]
648 vmull.s16 q3, d18, d1[1]
649 vmull.s16 q15, d18, d1[0]
651 vmull.s16 q14, d17, d2[1]
652 vmull.s16 q13, d19, d3[2]
653 vmull.s16 q11, d16, d0[0]
654 vrshrn.s32 d24, q12, #14
655 vrshrn.s32 d16, q2, #14
656 vrshrn.s32 d7, q3, #14
657 vrshrn.s32 d6, q15, #14
658 vrshrn.s32 d29, q14, #14
659 vrshrn.s32 d17, q13, #14
660 vrshrn.s32 d28, q11, #14
662 mbutterfly_l q10, q11, d17, d24, d0[2], d0[3]
663 mbutterfly_l q9, q15, d29, d16, d0[2], d0[3]
665 vrshrn.s32 d27, q10, #14
666 vrshrn.s32 d21, q11, #14
667 vrshrn.s32 d23, q9, #14
668 vrshrn.s32 d25, q15, #14
671 mbutterfly0 d22, d26, d7, d6, d18, d30, q9, q15
677 movrel r12, iadst16_coeffs
678 vld1.16 {q0-q1}, [r12,:128]
680 mbutterfly_l q3, q2, d31, d16, d0[1], d0[0] @ q3 = t1, q2 = t0
681 mbutterfly_l q5, q4, d23, d24, d1[1], d1[0] @ q5 = t9, q4 = t8
682 butterfly_n d31, d24, q3, q5, q6, q5 @ d31 = t1a, d24 = t9a
683 mbutterfly_l q7, q6, d29, d18, d0[3], d0[2] @ q7 = t3, q6 = t2
684 butterfly_n d16, d23, q2, q4, q3, q4 @ d16 = t0a, d23 = t8a
686 mbutterfly_l q3, q2, d21, d26, d1[3], d1[2] @ q3 = t11, q2 = t10
687 butterfly_n d29, d26, q7, q3, q4, q3 @ d29 = t3a, d26 = t11a
688 mbutterfly_l q5, q4, d27, d20, d2[1], d2[0] @ q5 = t5, q4 = t4
689 butterfly_n d18, d21, q6, q2, q3, q2 @ d18 = t2a, d21 = t10a
691 mbutterfly_l q7, q6, d19, d28, d3[1], d3[0] @ q7 = t13, q6 = t12
692 butterfly_n d20, d28, q5, q7, q2, q7 @ d20 = t5a, d28 = t13a
693 mbutterfly_l q3, q2, d25, d22, d2[3], d2[2] @ q3 = t7, q2 = t6
694 butterfly_n d27, d19, q4, q6, q5, q6 @ d27 = t4a, d19 = t12a
696 mbutterfly_l q5, q4, d17, d30, d3[3], d3[2] @ q5 = t15, q4 = t14
697 movrel r12, idct_coeffs
698 vld1.16 {q0}, [r12,:128]
699 butterfly_n d22, d30, q3, q5, q6, q5 @ d22 = t7a, d30 = t15a
700 mbutterfly_l q7, q6, d23, d24, d1[0], d1[1] @ q7 = t9, q6 = t8
701 butterfly_n d25, d17, q2, q4, q3, q4 @ d25 = t6a, d17 = t14a
703 mbutterfly_l q2, q3, d28, d19, d1[1], d1[0] @ q2 = t12, q3 = t13
704 butterfly_n d23, d19, q6, q2, q4, q2 @ d23 = t8a, d19 = t12a
705 mbutterfly_l q5, q4, d21, d26, d1[2], d1[3] @ q5 = t11, q4 = t10
706 butterfly_r d4, d27, d16, d27 @ d4 = t4, d27 = t0
707 butterfly_n d24, d28, q7, q3, q6, q3 @ d24 = t9a, d28 = t13a
709 mbutterfly_l q6, q7, d30, d17, d1[3], d1[2] @ q6 = t14, q7 = t15
710 butterfly_r d5, d20, d31, d20 @ d5 = t5, d20 = t1
711 butterfly_n d21, d17, q4, q6, q3, q6 @ d21 = t10a, d17 = t14a
712 butterfly_n d26, d30, q5, q7, q4, q7 @ d26 = t11a, d30 = t15a
714 butterfly_r d6, d25, d18, d25 @ d6 = t6, d25 = t2
715 butterfly_r d7, d22, d29, d22 @ d7 = t7, d22 = t3
717 mbutterfly_l q5, q4, d19, d28, d0[2], d0[3] @ q5 = t13, q4 = t12
718 mbutterfly_l q6, q7, d30, d17, d0[3], d0[2] @ q6 = t14, q7 = t15
720 butterfly_n d18, d30, q4, q6, q8, q6 @ d18 = out[2], d30 = t14a
721 butterfly_n d29, d17, q5, q7, q6, q7 @ d29 = -out[13], d17 = t15a
722 vneg.s16 d29, d29 @ d29 = out[13]
724 mbutterfly_l q5, q4, d4, d5, d0[2], d0[3] @ q5 = t5a, q4 = t4a
725 mbutterfly_l q6, q7, d7, d6, d0[3], d0[2] @ q6 = t6a, q7 = t7a
727 butterfly d2, d6, d27, d25 @ d2 = out[0], d6 = t2a
728 butterfly d3, d7, d23, d21 @ d3 =-out[1], d7 = t10
730 butterfly_n d19, d31, q4, q6, q2, q4 @ d19 = -out[3], d31 = t6
731 vneg.s16 d19, d19 @ d19 = out[3]
732 butterfly_n d28, d16, q5, q7, q2, q5 @ d28 = out[12], d16 = t7
734 butterfly d5, d8, d20, d22 @ d5 =-out[15],d8 = t3a
735 butterfly d4, d9, d24, d26 @ d4 = out[14],d9 = t11
737 mbutterfly0 d23, d24, d6, d8, d10, d11, q6, q7, 1 @ d23 = out[7], d24 = out[8]
738 mbutterfly0 d20, d27, d16, d31, d10, d11, q6, q7 @ d20 = out[4], d27 = out[11]
739 mbutterfly0 d22, d25, d9, d7, d10, d11, q6, q7 @ d22 = out[6], d25 = out[9]
740 mbutterfly0 d21, d26, d30, d17, d10, d11, q6, q7, 1 @ d21 = out[5], d26 = out[10]
742 vneg.s16 d31, d5 @ d31 = out[15]
743 vneg.s16 d17, d3 @ d17 = out[1]
750 .macro load_add_store coef0, coef1, coef2, coef3
751 vrshr.s16 \coef0, \coef0, #6
752 vrshr.s16 \coef1, \coef1, #6
754 vld1.32 {d4[]}, [r0,:32], r1
755 vld1.32 {d4[1]}, [r3,:32], r1
756 vrshr.s16 \coef2, \coef2, #6
757 vrshr.s16 \coef3, \coef3, #6
758 vld1.32 {d5[]}, [r0,:32], r1
759 vld1.32 {d5[1]}, [r3,:32], r1
760 vaddw.u8 \coef0, \coef0, d4
761 vld1.32 {d6[]}, [r0,:32], r1
762 vld1.32 {d6[1]}, [r3,:32], r1
763 vaddw.u8 \coef1, \coef1, d5
764 vld1.32 {d7[]}, [r0,:32], r1
765 vld1.32 {d7[1]}, [r3,:32], r1
767 vqmovun.s16 d4, \coef0
768 vqmovun.s16 d5, \coef1
769 sub r0, r0, r1, lsl #2
770 sub r3, r3, r1, lsl #2
771 vaddw.u8 \coef2, \coef2, d6
772 vaddw.u8 \coef3, \coef3, d7
773 vst1.32 {d4[0]}, [r0,:32], r1
774 vst1.32 {d4[1]}, [r3,:32], r1
775 vqmovun.s16 d6, \coef2
776 vst1.32 {d5[0]}, [r0,:32], r1
777 vst1.32 {d5[1]}, [r3,:32], r1
778 vqmovun.s16 d7, \coef3
780 vst1.32 {d6[0]}, [r0,:32], r1
781 vst1.32 {d6[1]}, [r3,:32], r1
782 vst1.32 {d7[0]}, [r0,:32], r1
783 vst1.32 {d7[1]}, [r3,:32], r1
786 .macro itxfm16_1d_funcs txfm
787 @ Read a vertical 4x16 slice out of a 16x16 matrix, do a transform on it,
788 @ transpose into a horizontal 16x4 slice and store.
789 @ r0 = dst (temp buffer)
792 function \txfm\()16_1d_4x16_pass1_neon
797 .irp i, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31
798 vld1.16 {d\i}, [r2,:64]
799 vst1.16 {d4}, [r2,:64], r12
804 @ Do four 4x4 transposes. Originally, d16-d31 contain the
805 @ 16 rows. Afterwards, d16-d19, d20-d23, d24-d27, d28-d31
806 @ contain the transposed 4x4 blocks.
807 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
809 @ Store the transposed 4x4 blocks horizontally.
812 .irp i, 16, 20, 24, 28, 17, 21, 25, 29, 18, 22, 26, 30, 19, 23, 27, 31
813 vst1.16 {d\i}, [r0,:64]!
817 @ Special case: For the last input column (r1 == 12),
818 @ which would be stored as the last row in the temp buffer,
819 @ don't store the first 4x4 block, but keep it in registers
820 @ for the first slice of the second pass (where it is the
823 vst1.16 {d20}, [r0,:64]!
824 vst1.16 {d24}, [r0,:64]!
825 vst1.16 {d28}, [r0,:64]!
827 vst1.16 {d21}, [r0,:64]!
828 vst1.16 {d25}, [r0,:64]!
829 vst1.16 {d29}, [r0,:64]!
831 vst1.16 {d22}, [r0,:64]!
832 vst1.16 {d26}, [r0,:64]!
833 vst1.16 {d30}, [r0,:64]!
835 vst1.16 {d23}, [r0,:64]!
836 vst1.16 {d27}, [r0,:64]!
837 vst1.16 {d31}, [r0,:64]!
845 @ Read a vertical 4x16 slice out of a 16x16 matrix, do a transform on it,
846 @ load the destination pixels (from a similar 4x16 slice), add and store back.
849 @ r2 = src (temp buffer)
851 function \txfm\()16_1d_4x16_pass2_neon
854 .irp i, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27
855 vld1.16 {d\i}, [r2,:64], r12
859 .irp i, 28, 29, 30, 31
860 vld1.16 {d\i}, [r2,:64], r12
868 load_add_store q8, q9, q10, q11
869 load_add_store q12, q13, q14, q15
875 itxfm16_1d_funcs idct
876 itxfm16_1d_funcs iadst
878 @ This is the minimum eob value for each subpartition, in increments of 4
879 const min_eob_idct_idct_16, align=4
883 .macro itxfm_func16x16 txfm1, txfm2
884 function ff_vp9_\txfm1\()_\txfm2\()_16x16_add_neon, export=1
885 .ifc \txfm1\()_\txfm2,idct_idct
887 beq idct16x16_dc_add_neon
890 .ifnc \txfm1\()_\txfm2,idct_idct
894 @ Align the stack, allocate a temp buffer
906 movrel r12, idct_coeffs
907 vld1.16 {q0-q1}, [r12,:128]
910 .ifc \txfm1\()_\txfm2,idct_idct
912 ble idct16x16_quarter_add_neon
914 ble idct16x16_half_add_neon
916 movrel r8, min_eob_idct_idct_16 + 2
921 .ifc \txfm1\()_\txfm2,idct_idct
926 movle r1, #(16 - \i)/4
932 bl \txfm1\()16_1d_4x16_pass1_neon
935 .ifc \txfm1\()_\txfm2,idct_idct
938 @ For all-zero slices in pass 1, set d28-d31 to zero, for the in-register
939 @ passthrough of coefficients to pass 2 and clear the end of the temp buffer
945 vst1.16 {q14-q15}, [r0,:128]!
951 .ifc \txfm1\()_\txfm2,iadst_idct
952 movrel r12, idct_coeffs
953 vld1.16 {q0-q1}, [r12,:128]
960 bl \txfm2\()16_1d_4x16_pass2_neon
964 .ifnc \txfm1\()_\txfm2,idct_idct
971 itxfm_func16x16 idct, idct
972 itxfm_func16x16 iadst, idct
973 itxfm_func16x16 idct, iadst
974 itxfm_func16x16 iadst, iadst
977 function idct16_1d_4x16_pass1_quarter_neon
981 .irp i, 16, 17, 18, 19
982 vld1.16 {d\i}, [r2,:64]
983 vst1.16 {d4}, [r2,:64], r12
988 @ Do four 4x4 transposes. Originally, d16-d31 contain the
989 @ 16 rows. Afterwards, d16-d19, d20-d23, d24-d27, d28-d31
990 @ contain the transposed 4x4 blocks.
991 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
993 @ Store the transposed 4x4 blocks horizontally.
994 @ The first 4x4 block is kept in registers for the second pass,
995 @ store the rest in the temp buffer.
997 vst1.16 {d20}, [r0,:64]!
998 vst1.16 {d24}, [r0,:64]!
999 vst1.16 {d28}, [r0,:64]!
1001 vst1.16 {d21}, [r0,:64]!
1002 vst1.16 {d25}, [r0,:64]!
1003 vst1.16 {d29}, [r0,:64]!
1005 vst1.16 {d22}, [r0,:64]!
1006 vst1.16 {d26}, [r0,:64]!
1007 vst1.16 {d30}, [r0,:64]!
1009 vst1.16 {d23}, [r0,:64]!
1010 vst1.16 {d27}, [r0,:64]!
1011 vst1.16 {d31}, [r0,:64]!
1015 function idct16_1d_4x16_pass2_quarter_neon
1017 @ Only load the top 4 lines, and only do it for the later slices.
1018 @ For the first slice, d16-d19 is kept in registers from the first pass.
1022 .irp i, 16, 17, 18, 19
1023 vld1.16 {d\i}, [r2,:64], r12
1031 load_add_store q8, q9, q10, q11
1032 load_add_store q12, q13, q14, q15
1037 function idct16_1d_4x16_pass1_half_neon
1041 .irp i, 16, 17, 18, 19, 20, 21, 22, 23
1042 vld1.16 {d\i}, [r2,:64]
1043 vst1.16 {d4}, [r2,:64], r12
1048 @ Do four 4x4 transposes. Originally, d16-d31 contain the
1049 @ 16 rows. Afterwards, d16-d19, d20-d23, d24-d27, d28-d31
1050 @ contain the transposed 4x4 blocks.
1051 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
1053 @ Store the transposed 4x4 blocks horizontally.
1056 .irp i, 16, 20, 24, 28, 17, 21, 25, 29, 18, 22, 26, 30, 19, 23, 27, 31
1057 vst1.16 {d\i}, [r0,:64]!
1061 @ Special case: For the second input column (r1 == 4),
1062 @ which would be stored as the second row in the temp buffer,
1063 @ don't store the first 4x4 block, but keep it in registers
1064 @ for the first slice of the second pass (where it is the
1065 @ second 4x4 block).
1067 vst1.16 {d20}, [r0,:64]!
1068 vst1.16 {d24}, [r0,:64]!
1069 vst1.16 {d28}, [r0,:64]!
1071 vst1.16 {d21}, [r0,:64]!
1072 vst1.16 {d25}, [r0,:64]!
1073 vst1.16 {d29}, [r0,:64]!
1075 vst1.16 {d22}, [r0,:64]!
1076 vst1.16 {d26}, [r0,:64]!
1077 vst1.16 {d30}, [r0,:64]!
1079 vst1.16 {d23}, [r0,:64]!
1080 vst1.16 {d27}, [r0,:64]!
1081 vst1.16 {d31}, [r0,:64]!
1089 function idct16_1d_4x16_pass2_half_neon
1093 .irp i, 16, 17, 18, 19
1094 vld1.16 {d\i}, [r2,:64], r12
1097 .irp i, 20, 21, 22, 23
1098 vld1.16 {d\i}, [r2,:64], r12
1106 load_add_store q8, q9, q10, q11
1107 load_add_store q12, q13, q14, q15
1111 .purgem load_add_store
1113 .macro idct16_partial size
1114 function idct16x16_\size\()_add_neon
1118 bl idct16_1d_4x16_pass1_\size\()_neon
1123 bl idct16_1d_4x16_pass1_\size\()_neon
1130 bl idct16_1d_4x16_pass2_\size\()_neon
1138 idct16_partial quarter
1141 function idct32x32_dc_add_neon
1142 movrel r12, idct_coeffs
1143 vld1.16 {d0}, [r12,:64]
1147 vld1.16 {d16[]}, [r2,:16]
1148 vmull.s16 q8, d16, d0[0]
1149 vrshrn.s32 d16, q8, #14
1150 vmull.s16 q8, d16, d0[0]
1151 vrshrn.s32 d16, q8, #14
1153 vst1.16 {d4[0]}, [r2,:16]
1155 vrshr.s16 q8, q8, #6
1160 @ Loop to add the constant from q8 into all 32x32 outputs
1162 vld1.8 {q0-q1}, [r0,:128], r1
1164 vaddw.u8 q10, q8, d1
1165 vld1.8 {q2-q3}, [r0,:128], r1
1166 vaddw.u8 q11, q8, d2
1167 vaddw.u8 q12, q8, d3
1168 vaddw.u8 q13, q8, d4
1169 vaddw.u8 q14, q8, d5
1170 vaddw.u8 q15, q8, d6
1178 vst1.8 {q0-q1}, [r3,:128], r1
1181 vst1.8 {q2-q3}, [r3,:128], r1
1188 butterfly d16, d9, d8, d9 @ d16 = t16a, d9 = t19a
1189 butterfly d17, d20, d23, d20 @ d17 = t17, d20 = t18
1190 butterfly d18, d10, d11, d10 @ d18 = t23a, d10 = t20a
1191 butterfly d19, d21, d22, d21 @ d19 = t22, d21 = t21
1192 butterfly d8, d28, d28, d30 @ d8 = t24a, d28 = t27a
1193 butterfly d23, d26, d25, d26 @ d23 = t25, d26 = t26
1194 butterfly d11, d29, d29, d31 @ d11 = t31a, d29 = t28a
1195 butterfly d22, d27, d24, d27 @ d22 = t30, d27 = t29
1197 mbutterfly d27, d20, d0[2], d0[3], q12, q15 @ d27 = t18a, d20 = t29a
1198 mbutterfly d29, d9, d0[2], d0[3], q12, q15 @ d29 = t19, d5 = t28
1199 mbutterfly d28, d10, d0[2], d0[3], q12, q15, neg=1 @ d28 = t27, d6 = t20
1200 mbutterfly d26, d21, d0[2], d0[3], q12, q15, neg=1 @ d26 = t26a, d21 = t21a
1202 butterfly d31, d24, d11, d8 @ d31 = t31, d24 = t24
1203 butterfly d30, d25, d22, d23 @ d30 = t30a, d25 = t25a
1204 butterfly_r d23, d16, d16, d18 @ d23 = t23, d16 = t16
1205 butterfly_r d22, d17, d17, d19 @ d22 = t22a, d17 = t17a
1206 butterfly d18, d21, d27, d21 @ d18 = t18, d21 = t21
1207 butterfly_r d27, d28, d9, d28 @ d27 = t27a, d28 = t28a
1208 butterfly d8, d26, d20, d26 @ d8 = t29, d26 = t26
1209 butterfly d19, d20, d29, d10 @ d19 = t19a, d20 = t20
1210 vmov d29, d8 @ d29 = t29
1212 mbutterfly0 d27, d20, d27, d20, d8, d10, q4, q5 @ d27 = t27, d20 = t20
1213 mbutterfly0 d26, d21, d26, d21, d8, d10, q4, q5 @ d26 = t26a, d21 = t21a
1214 mbutterfly0 d25, d22, d25, d22, d8, d10, q4, q5 @ d25 = t25, d22 = t22
1215 mbutterfly0 d24, d23, d24, d23, d8, d10, q4, q5 @ d24 = t24a, d23 = t23a
1220 mbutterfly d16, d31, d4[0], d4[1], q4, q5 @ d16 = t16a, d31 = t31a
1221 mbutterfly d24, d23, d4[2], d4[3], q4, q5 @ d24 = t17a, d23 = t30a
1222 mbutterfly d20, d27, d5[0], d5[1], q4, q5 @ d20 = t18a, d27 = t29a
1223 mbutterfly d28, d19, d5[2], d5[3], q4, q5 @ d28 = t19a, d19 = t28a
1224 mbutterfly d18, d29, d6[0], d6[1], q4, q5 @ d18 = t20a, d29 = t27a
1225 mbutterfly d26, d21, d6[2], d6[3], q4, q5 @ d26 = t21a, d21 = t26a
1226 mbutterfly d22, d25, d7[0], d7[1], q4, q5 @ d22 = t22a, d25 = t25a
1227 mbutterfly d30, d17, d7[2], d7[3], q4, q5 @ d30 = t23a, d17 = t24a
1229 butterfly d8, d24, d16, d24 @ d8 = t16, d24 = t17
1230 butterfly d9, d20, d28, d20 @ d9 = t19, d20 = t18
1231 butterfly d10, d26, d18, d26 @ d10 = t20, d26 = t21
1232 butterfly d11, d22, d30, d22 @ d11 = t23, d22 = t22
1233 butterfly d28, d25, d17, d25 @ d28 = t24, d25 = t25
1234 butterfly d30, d21, d29, d21 @ d30 = t27, d21 = t26
1235 butterfly d29, d23, d31, d23 @ d29 = t31, d23 = t30
1236 butterfly d31, d27, d19, d27 @ d31 = t28, d27 = t29
1238 mbutterfly d23, d24, d1[0], d1[1], q8, q9 @ d23 = t17a, d24 = t30a
1239 mbutterfly d27, d20, d1[0], d1[1], q8, q9, neg=1 @ d27 = t29a, d20 = t18a
1240 mbutterfly d21, d26, d1[2], d1[3], q8, q9 @ d21 = t21a, d26 = t26a
1241 mbutterfly d25, d22, d1[2], d1[3], q8, q9, neg=1 @ d25 = t25a, d22 = t22a
1245 function idct32_odd_half
1246 mbutterfly_h1 d16, d31, d4[0], d4[1], q4, q5 @ d16 = t16a, d31 = t31a
1247 mbutterfly_h2 d24, d23, d4[2], d4[3], q4, q5 @ d24 = t17a, d23 = t30a
1248 mbutterfly_h1 d20, d27, d5[0], d5[1], q4, q5 @ d20 = t18a, d27 = t29a
1249 mbutterfly_h2 d28, d19, d5[2], d5[3], q4, q5 @ d28 = t19a, d19 = t28a
1250 mbutterfly_h1 d18, d29, d6[0], d6[1], q4, q5 @ d18 = t20a, d29 = t27a
1251 mbutterfly_h2 d26, d21, d6[2], d6[3], q4, q5 @ d26 = t21a, d21 = t26a
1252 mbutterfly_h1 d22, d25, d7[0], d7[1], q4, q5 @ d22 = t22a, d25 = t25a
1253 mbutterfly_h2 d30, d17, d7[2], d7[3], q4, q5 @ d30 = t23a, d17 = t24a
1255 butterfly d8, d24, d16, d24 @ d8 = t16, d24 = t17
1256 butterfly d9, d20, d28, d20 @ d9 = t19, d20 = t18
1257 butterfly d10, d26, d18, d26 @ d10 = t20, d26 = t21
1258 butterfly d11, d22, d30, d22 @ d11 = t23, d22 = t22
1259 butterfly d28, d25, d17, d25 @ d28 = t24, d25 = t25
1260 butterfly d30, d21, d29, d21 @ d30 = t27, d21 = t26
1261 butterfly d29, d23, d31, d23 @ d29 = t31, d23 = t30
1262 butterfly d31, d27, d19, d27 @ d31 = t28, d27 = t29
1264 mbutterfly d23, d24, d1[0], d1[1], q8, q9 @ d23 = t17a, d24 = t30a
1265 mbutterfly d27, d20, d1[0], d1[1], q8, q9, neg=1 @ d27 = t29a, d20 = t18a
1266 mbutterfly d21, d26, d1[2], d1[3], q8, q9 @ d21 = t21a, d26 = t26a
1267 mbutterfly d25, d22, d1[2], d1[3], q8, q9, neg=1 @ d25 = t25a, d22 = t22a
1272 function idct32_odd_quarter
1273 vmull.s16 q4, d16, d4[0]
1274 vmull.s16 q14, d19, d5[3]
1275 vmull.s16 q15, d16, d4[1]
1276 vmull.s16 q11, d17, d7[2]
1277 vmull.s16 q5, d17, d7[3]
1278 vmull.s16 q13, d19, d5[2]
1279 vmull.s16 q10, d18, d6[0]
1280 vmull.s16 q12, d18, d6[1]
1285 vrshrn.s32 d8, q4, #14
1286 vrshrn.s32 d9, q14, #14
1287 vrshrn.s32 d29, q15, #14
1288 vrshrn.s32 d28, q11, #14
1289 vrshrn.s32 d11, q5, #14
1290 vrshrn.s32 d31, q13, #14
1291 vrshrn.s32 d10, q10, #14
1292 vrshrn.s32 d30, q12, #14
1294 mbutterfly_l q8, q9, d29, d8, d1[0], d1[1]
1295 mbutterfly_l q13, q10, d31, d9, d1[0], d1[1]
1296 vrshrn.s32 d23, q8, #14
1297 vrshrn.s32 d24, q9, #14
1299 vrshrn.s32 d27, q13, #14
1300 vrshrn.s32 d20, q10, #14
1301 mbutterfly_l q8, q9, d30, d10, d1[2], d1[3]
1302 vrshrn.s32 d21, q8, #14
1303 vrshrn.s32 d26, q9, #14
1304 mbutterfly_l q8, q9, d28, d11, d1[2], d1[3]
1305 vrshrn.s32 d25, q8, #14
1307 vrshrn.s32 d22, q9, #14
1312 .macro idct32_funcs suffix
1313 @ Do an 32-point IDCT of a 4x32 slice out of a 32x32 matrix.
1314 @ We don't have register space to do a single pass IDCT of 4x32 though,
1315 @ but the 32-point IDCT can be decomposed into two 16-point IDCTs;
1316 @ a normal IDCT16 with every other input component (the even ones, with
1317 @ each output written twice), followed by a separate 16-point IDCT
1318 @ of the odd inputs, added/subtracted onto the outputs of the first idct16.
1319 @ r0 = dst (temp buffer)
1322 function idct32_1d_4x32_pass1\suffix\()_neon
1325 @ idct16 clobbers q2-q3 (since it doesn't clobber q4-q7 at all
1326 @ when doing the normal 16x16 idct), so move the idct32_odd coeffs
1331 @ Double stride of the input, since we only read every other line
1335 @ d16 = IN(0), d17 = IN(2) ... d31 = IN(30)
1337 .irp i, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31
1338 vld1.16 {d\i}, [r2,:64]
1339 vst1.16 {d4}, [r2,:64], r12
1342 .ifc \suffix,_quarter
1343 .irp i, 16, 17, 18, 19
1344 vld1.16 {d\i}, [r2,:64]
1345 vst1.16 {d4}, [r2,:64], r12
1349 .irp i, 16, 17, 18, 19, 20, 21, 22, 23
1350 vld1.16 {d\i}, [r2,:64]
1351 vst1.16 {d4}, [r2,:64], r12
1357 @ Move the idct32_odd coeffs back into q2-q3 for idct32_odd;
1358 @ the constants for a vmul with a lane must be in q0-q3.
1362 @ Do four 4x4 transposes. Originally, d16-d31 contain the
1363 @ 16 rows. Afterwards, d16-d19, d20-d23, d24-d27, d28-d31
1364 @ contain the transposed 4x4 blocks.
1365 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
1366 @ Store the registers a, b, c, d horizontally, followed
1367 @ by the same registers d, c, b, a mirrored.
1368 .macro store_rev a, b, c, d
1369 .irp i, \a, \b, \c, \d
1370 vst1.16 {d\i}, [r0,:64]!
1373 .irp i, \d, \c, \b, \a
1374 vst1.16 {d\i}, [r0,:64]!
1377 store_rev 16, 20, 24, 28
1378 store_rev 17, 21, 25, 29
1379 store_rev 18, 22, 26, 30
1380 store_rev 19, 23, 27, 31
1384 @ Move r2 back to the start of the input, and move
1385 @ to the first odd row
1387 sub r2, r2, r12, lsl #4
1389 .ifc \suffix,_quarter
1390 sub r2, r2, r12, lsl #2
1393 sub r2, r2, r12, lsl #3
1398 @ d16 = IN(1), d17 = IN(3) ... d31 = IN(31)
1400 .irp i, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31
1401 vld1.16 {d\i}, [r2,:64]
1402 vst1.16 {d8}, [r2,:64], r12
1405 .ifc \suffix,_quarter
1406 .irp i, 16, 17, 18, 19
1407 vld1.16 {d\i}, [r2,:64]
1408 vst1.16 {d8}, [r2,:64], r12
1412 .irp i, 16, 17, 18, 19, 20, 21, 22, 23
1413 vld1.16 {d\i}, [r2,:64]
1414 vst1.16 {d8}, [r2,:64], r12
1418 bl idct32_odd\suffix
1420 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
1422 @ Store the registers a, b, c, d horizontally,
1423 @ adding into the output first, and then mirrored, subtracted
1425 .macro store_rev a, b, c, d
1426 .irp i, \a, \b, \c, \d
1427 vld1.16 {d8}, [r0,:64]
1428 vadd.s16 d8, d8, d\i
1429 vst1.16 {d8}, [r0,:64]!
1432 .irp i, \d, \c, \b, \a
1433 vld1.16 {d8}, [r0,:64]
1434 vsub.s16 d8, d8, d\i
1435 vst1.16 {d8}, [r0,:64]!
1439 store_rev 31, 27, 23, 19
1440 store_rev 30, 26, 22, 18
1441 store_rev 29, 25, 21, 17
1442 store_rev 28, 24, 20, 16
1448 @ This is mostly the same as 4x32_pass1, but without the transpose,
1449 @ and use the source as temp buffer between the two idct passes, and
1450 @ add into the destination.
1453 @ r2 = src (temp buffer)
1454 function idct32_1d_4x32_pass2\suffix\()_neon
1460 @ d16 = IN(0), d17 = IN(2) ... d31 = IN(30)
1462 .irp i, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31
1463 vld1.16 {d\i}, [r2,:64], r12
1465 sub r2, r2, r12, lsl #4
1467 .ifc \suffix,_quarter
1468 .irp i, 16, 17, 18, 19
1469 vld1.16 {d\i}, [r2,:64], r12
1471 sub r2, r2, r12, lsl #2
1474 .irp i, 16, 17, 18, 19, 20, 21, 22, 23
1475 vld1.16 {d\i}, [r2,:64], r12
1477 sub r2, r2, r12, lsl #3
1485 .irp i, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31
1486 vst1.16 {d\i}, [r2,:64], r12
1489 sub r2, r2, r12, lsl #4
1492 @ d16 = IN(1), d17 = IN(3) ... d31 = IN(31)
1494 .irp i, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31
1495 vld1.16 {d\i}, [r2,:64], r12
1497 sub r2, r2, r12, lsl #4
1499 .ifc \suffix,_quarter
1500 .irp i, 16, 17, 18, 19
1501 vld1.16 {d\i}, [r2,:64], r12
1503 sub r2, r2, r12, lsl #2
1506 .irp i, 16, 17, 18, 19, 20, 21, 22, 23
1507 vld1.16 {d\i}, [r2,:64], r12
1509 sub r2, r2, r12, lsl #3
1513 bl idct32_odd\suffix
1516 .macro load_acc_store a, b, c, d, neg=0
1517 vld1.16 {d8}, [r2,:64], r12
1518 vld1.16 {d9}, [r2,:64], r12
1520 vadd.s16 d8, d8, d\a
1521 vld1.16 {d10}, [r2,:64], r12
1522 vadd.s16 d9, d9, d\b
1523 vld1.16 {d11}, [r2,:64], r12
1524 vadd.s16 d10, d10, d\c
1525 vadd.s16 d11, d11, d\d
1527 vsub.s16 d8, d8, d\a
1528 vld1.16 {d10}, [r2,:64], r12
1529 vsub.s16 d9, d9, d\b
1530 vld1.16 {d11}, [r2,:64], r12
1531 vsub.s16 d10, d10, d\c
1532 vsub.s16 d11, d11, d\d
1534 vld1.32 {d12[]}, [r0,:32], r1
1535 vld1.32 {d12[1]}, [r0,:32], r1
1536 vrshr.s16 q4, q4, #6
1537 vld1.32 {d13[]}, [r0,:32], r1
1538 vrshr.s16 q5, q5, #6
1539 vld1.32 {d13[1]}, [r0,:32], r1
1540 sub r0, r0, r1, lsl #2
1541 vaddw.u8 q4, q4, d12
1542 vaddw.u8 q5, q5, d13
1545 vst1.32 {d8[0]}, [r0,:32], r1
1546 vst1.32 {d8[1]}, [r0,:32], r1
1547 vst1.32 {d9[0]}, [r0,:32], r1
1548 vst1.32 {d9[1]}, [r0,:32], r1
1550 load_acc_store 31, 30, 29, 28
1551 load_acc_store 27, 26, 25, 24
1552 load_acc_store 23, 22, 21, 20
1553 load_acc_store 19, 18, 17, 16
1556 load_acc_store 16, 17, 18, 19, 1
1557 load_acc_store 20, 21, 22, 23, 1
1558 load_acc_store 24, 25, 26, 27, 1
1559 load_acc_store 28, 29, 30, 31, 1
1560 .purgem load_acc_store
1566 idct32_funcs _quarter
1569 const min_eob_idct_idct_32, align=4
1570 .short 0, 9, 34, 70, 135, 240, 336, 448
1573 function ff_vp9_idct_idct_32x32_add_neon, export=1
1575 beq idct32x32_dc_add_neon
1579 @ Align the stack, allocate a temp buffer
1590 movrel r12, idct_coeffs
1591 vld1.16 {q0-q1}, [r12,:128]!
1592 vld1.16 {q2-q3}, [r12,:128]
1595 ble idct32x32_quarter_add_neon
1597 ble idct32x32_half_add_neon
1599 movrel r8, min_eob_idct_idct_32 + 2
1601 .irp i, 0, 4, 8, 12, 16, 20, 24, 28
1602 add r0, sp, #(\i*64)
1604 ldrh_post r1, r8, #2
1607 movle r1, #(32 - \i)/2
1611 bl idct32_1d_4x32_pass1_neon
1616 @ Write zeros to the temp buffer for pass 2
1622 vst1.16 {q14-q15}, [r0,:128]!
1626 .irp i, 0, 4, 8, 12, 16, 20, 24, 28
1630 bl idct32_1d_4x32_pass2_neon
1638 .macro idct32_partial size
1639 function idct32x32_\size\()_add_neon
1641 add r0, sp, #(\i*64)
1649 bl idct32_1d_4x32_pass1_\size\()_neon
1654 add r0, sp, #(\i*64)
1660 bl idct32_1d_4x32_pass1_\size\()_neon
1666 @ Write zeros to the temp buffer for pass 2
1670 vst1.16 {q14-q15}, [r0,:128]!
1674 .irp i, 0, 4, 8, 12, 16, 20, 24, 28
1678 bl idct32_1d_4x32_pass2_\size\()_neon
1687 idct32_partial quarter