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, 6270, 15137, 0
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, 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
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
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 @ 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]
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
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
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
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
128 @ in1 = (in1 * coef1 - in2 * coef2 + (1 << 13)) >> 14
129 @ in2 = (in1 * coef2 + in2 * coef1 + (1 << 13)) >> 14
130 @ in are 2 d registers, tmp are 2 q registers
131 .macro mbutterfly in1, in2, coef1, coef2, tmp1, tmp2, neg=0
132 mbutterfly_l \tmp1, \tmp2, \in1, \in2, \coef1, \coef2
134 vneg.s32 \tmp2, \tmp2
136 vrshrn.s32 \in1, \tmp1, #14
137 vrshrn.s32 \in2, \tmp2, #14
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
153 .macro butterfly out1, out2, in1, in2
154 vadd.s16 \out1, \in1, \in2
155 vsub.s16 \out2, \in1, \in2
160 .macro butterfly_r out1, out2, in1, in2
161 vsub.s16 \out1, \in1, \in2
162 vadd.s16 \out2, \in1, \in2
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
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
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
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
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
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);
244 .macro itxfm_func4x4 txfm1, txfm2
245 function ff_vp9_\txfm1\()_\txfm2\()_4x4_add_neon, export=1
248 movrel r12, itxfm4_coeffs
249 vld1.16 {d0}, [r12,:64]
252 movrel r12, iadst4_coeffs
253 vld1.16 {d1}, [r12,:64]
256 movrel r12, itxfm4_coeffs
257 vld1.16 {q0}, [r12,:128]
261 .ifc \txfm1\()_\txfm2,idct_idct
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]
277 vld1.16 {d4-d7}, [r2,:128]
278 vst1.16 {q15}, [r2,:128]!
285 \txfm1\()4 d4, d5, d6, d7
287 vst1.16 {q15}, [r2,:128]!
288 @ Transpose 4x4 with 16 bit elements
293 \txfm2\()4 d4, d5, d6, d7
295 vld1.32 {d0[]}, [r0,:32], r1
296 vld1.32 {d0[1]}, [r0,:32], r1
302 vld1.32 {d1[]}, [r0,:32], r1
303 vld1.32 {d1[1]}, [r0,:32], r1
305 sub r0, r0, r1, lsl #2
308 vst1.32 {d0[0]}, [r0,:32], r1
311 vst1.32 {d0[1]}, [r0,:32], r1
312 vst1.32 {d1[0]}, [r0,:32], r1
313 vst1.32 {d1[1]}, [r0,:32], r1
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
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
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
337 butterfly q8, q15, q2, q5 @ q8 = out[0], q15 = out[7]
339 dmbutterfly0 d4, d5, d10, d11, q11, q13, q9, q13, d18, d19, d26, d27, q2, q5, q11, q12 @ q2 = t6, q5 = t5
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]
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
350 dbutterfly_n d22, d23, d4, d5, q2, q3, q6, q7, q11, q12, q2, q3 @ q11 = t0, q2 = t4
352 dbutterfly_n d24, d25, d6, d7, q4, q5, q8, q15, q12, q3, q6, q7 @ q12 = t1, q3 = t5
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
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
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
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
367 dbutterfly_n d28, d29, d8, d9, q10, q11, q13, q14, q4, q6, q10, q11 @ q14 = out[6], q4 = t7
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]
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]
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]
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
390 vld1.16 {q0}, [r12,:128]
392 movrel r12, iadst8_coeffs
393 vld1.16 {q1}, [r12,:128]!
395 vld1.16 {q0}, [r12,:128]
401 .ifc \txfm1\()_\txfm2,idct_idct
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
418 vst1.16 {d4[0]}, [r2,:16]
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]!
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]!
434 @ Transpose 8x8 with 16 bit elements
439 transpose16_4x4 q8, q9, q10, q11, q12, q13, q14, q15
444 @ Add into the destination
445 vld1.8 {d4}, [r0,:64], r1
447 vld1.8 {d5}, [r0,:64], r1
449 vld1.8 {d6}, [r0,:64], r1
450 vrshr.s16 q10, q10, #5
452 vld1.8 {d7}, [r0,:64], r1
453 vrshr.s16 q11, q11, #5
455 vld1.8 {d8}, [r0,:64], r1
456 vrshr.s16 q12, q12, #5
457 vaddw.u8 q10, q10, d6
459 vld1.8 {d9}, [r0,:64], r1
460 vrshr.s16 q13, q13, #5
461 vaddw.u8 q11, q11, d7
463 vld1.8 {d10}, [r0,:64], r1
464 vrshr.s16 q14, q14, #5
465 vaddw.u8 q12, q12, d8
467 vld1.8 {d11}, [r0,:64], r1
468 vrshr.s16 q15, q15, #5
469 vaddw.u8 q13, q13, d9
473 vst1.8 {d4}, [r3,:64], r1
474 vaddw.u8 q14, q14, d10
475 vst1.8 {d5}, [r3,:64], r1
477 vst1.8 {d6}, [r3,:64], r1
478 vaddw.u8 q15, q15, d11
479 vst1.8 {d7}, [r3,:64], r1
481 vst1.8 {d8}, [r3,:64], r1
483 vst1.8 {d9}, [r3,:64], r1
486 vst1.8 {d10}, [r3,:64], r1
487 vst1.8 {d11}, [r3,:64], r1
489 .ifc \txfm1\()_\txfm2,idct_idct
498 itxfm_func8x8 idct, idct
499 itxfm_func8x8 iadst, idct
501 itxfm_func8x8 idct, iadst
502 itxfm_func8x8 iadst, iadst
505 function idct16x16_dc_add_neon
506 movrel r12, idct_coeffs
507 vld1.16 {d0}, [r12,:64]
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
517 vst1.16 {d4[0]}, [r2,:16]
523 @ Loop to add the constant from q8 into all 16x16 outputs
524 vld1.8 {q3}, [r0,:128]
529 vst1.8 {q3}, [r0,:128], r1
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
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
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
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
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
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]
586 movrel r12, iadst16_coeffs
587 vld1.16 {q0-q1}, [r12,:128]
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
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
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
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
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
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
623 butterfly_r d6, d25, d18, d25 @ d6 = t6, d25 = t2
624 butterfly_r d7, d22, d29, d22 @ d7 = t7, d22 = t3
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
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]
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
636 butterfly d2, d6, d27, d25 @ d2 = out[0], d6 = t2a
637 butterfly d3, d7, d23, d21 @ d3 =-out[1], d7 = t10
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
643 butterfly d5, d8, d20, d22 @ d5 =-out[15],d8 = t3a
644 butterfly d4, d9, d24, d26 @ d4 = out[14],d9 = t11
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]
651 vneg.s16 d31, d5 @ d31 = out[15]
652 vneg.s16 d17, d3 @ d17 = out[1]
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)
665 function \txfm\()16_1d_4x16_pass1_neon
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
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
680 @ Store the transposed 4x4 blocks horizontally.
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]!
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
695 vst1.16 {d\i}, [r0,:64]!
699 vst1.16 {d\i}, [r0,:64]!
703 vst1.16 {d\i}, [r0,:64]!
707 vst1.16 {d\i}, [r0,:64]!
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.
720 @ r2 = src (temp buffer)
722 function \txfm\()16_1d_4x16_pass2_neon
724 .irp i, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27
725 vld1.16 {d\i}, [r2,:64], r12
729 .irp i, 28, 29, 30, 31
730 vld1.16 {d\i}, [r2,:64], r12
738 .macro load_add_store coef0, coef1, coef2, coef3
739 vrshr.s16 \coef0, \coef0, #6
740 vrshr.s16 \coef1, \coef1, #6
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
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
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
773 load_add_store q8, q9, q10, q11
774 load_add_store q12, q13, q14, q15
775 .purgem load_add_store
781 itxfm16_1d_funcs idct
782 itxfm16_1d_funcs iadst
784 .macro itxfm_func16x16 txfm1, txfm2
785 function ff_vp9_\txfm1\()_\txfm2\()_16x16_add_neon, export=1
786 .ifc \txfm1\()_\txfm2,idct_idct
788 beq idct16x16_dc_add_neon
791 .ifnc \txfm1\()_\txfm2,idct_idct
796 @ Align the stack, allocate a temp buffer
809 movrel r12, idct_coeffs
810 vld1.16 {q0-q1}, [r12,:128]
817 bl \txfm1\()16_1d_4x16_pass1_neon
820 movrel r12, idct_coeffs
821 vld1.16 {q0-q1}, [r12,:128]
828 bl \txfm2\()16_1d_4x16_pass2_neon
832 .ifnc \txfm1\()_\txfm2,idct_idct
839 itxfm_func16x16 idct, idct
840 itxfm_func16x16 iadst, idct
841 itxfm_func16x16 idct, iadst
842 itxfm_func16x16 iadst, iadst
846 function idct32x32_dc_add_neon
847 movrel r12, idct_coeffs
848 vld1.16 {d0}, [r12,:64]
852 vld1.16 {d16[]}, [r2,:16]
853 vmull.s16 q8, d16, d0[0]
854 vrshrn.s32 d16, q8, #14
855 vmull.s16 q8, d16, d0[0]
856 vrshrn.s32 d16, q8, #14
858 vst1.16 {d4[0]}, [r2,:16]
864 @ Loop to add the constant from q8 into all 32x32 outputs
865 vld1.8 {q2-q3}, [r0,:128]
874 vst1.8 {q2-q3}, [r0,:128], r1
882 movrel r12, idct_coeffs
884 vld1.16 {q0-q1}, [r12,:128]
886 mbutterfly d16, d31, d0[0], d0[1], q2, q3 @ d16 = t16a, d31 = t31a
887 mbutterfly d24, d23, d0[2], d0[3], q2, q3 @ d24 = t17a, d23 = t30a
888 mbutterfly d20, d27, d1[0], d1[1], q2, q3 @ d20 = t18a, d27 = t29a
889 mbutterfly d28, d19, d1[2], d1[3], q2, q3 @ d28 = t19a, d19 = t28a
890 mbutterfly d18, d29, d2[0], d2[1], q2, q3 @ d18 = t20a, d29 = t27a
891 mbutterfly d26, d21, d2[2], d2[3], q2, q3 @ d26 = t21a, d21 = t26a
892 mbutterfly d22, d25, d3[0], d3[1], q2, q3 @ d22 = t22a, d25 = t25a
893 mbutterfly d30, d17, d3[2], d3[3], q2, q3 @ d30 = t23a, d17 = t24a
896 vld1.16 {q0}, [r12,:128]
898 butterfly d4, d24, d16, d24 @ d4 = t16, d24 = t17
899 butterfly d5, d20, d28, d20 @ d5 = t19, d20 = t18
900 butterfly d6, d26, d18, d26 @ d6 = t20, d26 = t21
901 butterfly d7, d22, d30, d22 @ d7 = t23, d22 = t22
902 butterfly d28, d25, d17, d25 @ d28 = t24, d25 = t25
903 butterfly d30, d21, d29, d21 @ d30 = t27, d21 = t26
904 butterfly d29, d23, d31, d23 @ d29 = t31, d23 = t30
905 butterfly d31, d27, d19, d27 @ d31 = t28, d27 = t29
907 mbutterfly d23, d24, d0[3], d1[0], q8, q9 @ d23 = t17a, d24 = t30a
908 mbutterfly d27, d20, d0[3], d1[0], q8, q9, neg=1 @ d27 = t29a, d20 = t18a
909 mbutterfly d21, d26, d1[1], d1[2], q8, q9 @ d21 = t21a, d26 = t26a
910 mbutterfly d25, d22, d1[1], d1[2], q8, q9, neg=1 @ d25 = t25a, d22 = t22a
912 butterfly d16, d5, d4, d5 @ d16 = t16a, d5 = t19a
913 butterfly d17, d20, d23, d20 @ d17 = t17, d20 = t18
914 butterfly d18, d6, d7, d6 @ d18 = t23a, d6 = t20a
915 butterfly d19, d21, d22, d21 @ d19 = t22, d21 = t21
916 butterfly d4, d28, d28, d30 @ d4 = t24a, d28 = t27a
917 butterfly d23, d26, d25, d26 @ d23 = t25, d26 = t26
918 butterfly d7, d29, d29, d31 @ d7 = t31a, d29 = t28a
919 butterfly d22, d27, d24, d27 @ d22 = t30, d27 = t29
921 mbutterfly d27, d20, d0[1], d0[2], q12, q15 @ d27 = t18a, d20 = t29a
922 mbutterfly d29, d5, d0[1], d0[2], q12, q15 @ d29 = t19, d5 = t28
923 mbutterfly d28, d6, d0[1], d0[2], q12, q15, neg=1 @ d28 = t27, d6 = t20
924 mbutterfly d26, d21, d0[1], d0[2], q12, q15, neg=1 @ d26 = t26a, d21 = t21a
926 butterfly d31, d24, d7, d4 @ d31 = t31, d24 = t24
927 butterfly d30, d25, d22, d23 @ d30 = t30a, d25 = t25a
928 butterfly_r d23, d16, d16, d18 @ d23 = t23, d16 = t16
929 butterfly_r d22, d17, d17, d19 @ d22 = t22a, d17 = t17a
930 butterfly d18, d21, d27, d21 @ d18 = t18, d21 = t21
931 butterfly_r d27, d28, d5, d28 @ d27 = t27a, d28 = t28a
932 butterfly d4, d26, d20, d26 @ d4 = t29, d26 = t26
933 butterfly d19, d20, d29, d6 @ d19 = t19a, d20 = t20
934 vmov d29, d4 @ d29 = t29
936 mbutterfly0 d27, d20, d27, d20, d4, d6, q2, q3 @ d27 = t27, d20 = t20
937 mbutterfly0 d26, d21, d26, d21, d4, d6, q2, q3 @ d26 = t26a, d21 = t21a
938 mbutterfly0 d25, d22, d25, d22, d4, d6, q2, q3 @ d25 = t25, d22 = t22
939 mbutterfly0 d24, d23, d24, d23, d4, d6, q2, q3 @ d24 = t24a, d23 = t23a
942 @ Do an 32-point IDCT of a 4x32 slice out of a 32x32 matrix.
943 @ We don't have register space to do a single pass IDCT of 4x32 though,
944 @ but the 32-point IDCT can be decomposed into two 16-point IDCTs;
945 @ a normal IDCT16 with every other input component (the even ones, with
946 @ each output written twice), followed by a separate 16-point IDCT
947 @ of the odd inputs, added/subtracted onto the outputs of the first idct16.
948 @ r0 = dst (temp buffer)
951 function idct32_1d_4x32_pass1_neon
952 movrel r12, idct_coeffs
953 vld1.16 {q0-q1}, [r12,:128]
955 @ Double stride of the input, since we only read every other line
959 @ d16 = IN(0), d17 = IN(2) ... d31 = IN(30)
960 .irp i, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31
961 vld1.16 {d\i}, [r2,:64]
962 vst1.16 {d4}, [r2,:64], r12
967 @ Do four 4x4 transposes. Originally, d16-d31 contain the
968 @ 16 rows. Afterwards, d16-d19, d20-d23, d24-d27, d28-d31
969 @ contain the transposed 4x4 blocks.
970 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
971 @ Store the registers a, b, c, d horizontally, followed
972 @ by the same registers d, c, b, a mirrored.
973 .macro store_rev a, b, c, d
974 .irp i, \a, \b, \c, \d
975 vst1.16 {d\i}, [r0,:64]!
978 .irp i, \d, \c, \b, \a
979 vst1.16 {d\i}, [r0,:64]!
982 store_rev 16, 20, 24, 28
983 store_rev 17, 21, 25, 29
984 store_rev 18, 22, 26, 30
985 store_rev 19, 23, 27, 31
989 @ Move r2 back to the start of the input, and move
990 @ to the first odd row
991 sub r2, r2, r12, lsl #4
995 @ d16 = IN(1), d17 = IN(3) ... d31 = IN(31)
996 .irp i, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31
997 vld1.16 {d\i}, [r2,:64]
998 vst1.16 {d4}, [r2,:64], r12
1003 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
1005 @ Store the registers a, b, c, d horizontally,
1006 @ adding into the output first, and then mirrored, subtracted
1008 .macro store_rev a, b, c, d
1009 .irp i, \a, \b, \c, \d
1010 vld1.16 {d4}, [r0,:64]
1011 vadd.s16 d4, d4, d\i
1012 vst1.16 {d4}, [r0,:64]!
1015 .irp i, \d, \c, \b, \a
1016 vld1.16 {d4}, [r0,:64]
1017 vsub.s16 d4, d4, d\i
1018 vst1.16 {d4}, [r0,:64]!
1022 store_rev 31, 27, 23, 19
1023 store_rev 30, 26, 22, 18
1024 store_rev 29, 25, 21, 17
1025 store_rev 28, 24, 20, 16
1031 @ This is mostly the same as 4x32_pass1, but without the transpose,
1032 @ and use the source as temp buffer between the two idct passes, and
1033 @ add into the destination.
1036 @ r2 = src (temp buffer)
1037 function idct32_1d_4x32_pass2_neon
1038 movrel r12, idct_coeffs
1039 vld1.16 {q0-q1}, [r12,:128]
1042 @ d16 = IN(0), d17 = IN(2) ... d31 = IN(30)
1043 .irp i, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31
1044 vld1.16 {d\i}, [r2,:64], r12
1046 sub r2, r2, r12, lsl #4
1050 .irp i, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31
1051 vst1.16 {d\i}, [r2,:64], r12
1054 sub r2, r2, r12, lsl #4
1057 @ d16 = IN(1), d17 = IN(3) ... d31 = IN(31)
1058 .irp i, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31
1059 vld1.16 {d\i}, [r2,:64], r12
1061 sub r2, r2, r12, lsl #4
1067 .macro load_acc_store a, b, c, d, neg=0
1068 vld1.16 {d4}, [r2,:64], r12
1069 vld1.16 {d5}, [r2,:64], r12
1071 vadd.s16 d4, d4, d\a
1072 vld1.16 {d6}, [r2,:64], r12
1073 vadd.s16 d5, d5, d\b
1074 vld1.16 {d7}, [r2,:64], r12
1075 vadd.s16 d6, d6, d\c
1076 vadd.s16 d7, d7, d\d
1078 vsub.s16 d4, d4, d\a
1079 vld1.16 {d6}, [r2,:64], r12
1080 vsub.s16 d5, d5, d\b
1081 vld1.16 {d7}, [r2,:64], r12
1082 vsub.s16 d6, d6, d\c
1083 vsub.s16 d7, d7, d\d
1085 vld1.32 {d2[]}, [r0,:32], r1
1086 vld1.32 {d2[1]}, [r0,:32], r1
1087 vrshr.s16 q2, q2, #6
1088 vld1.32 {d3[]}, [r0,:32], r1
1089 vrshr.s16 q3, q3, #6
1090 vld1.32 {d3[1]}, [r0,:32], r1
1091 sub r0, r0, r1, lsl #2
1096 vst1.32 {d4[0]}, [r0,:32], r1
1097 vst1.32 {d4[1]}, [r0,:32], r1
1098 vst1.32 {d5[0]}, [r0,:32], r1
1099 vst1.32 {d5[1]}, [r0,:32], r1
1101 load_acc_store 31, 30, 29, 28
1102 load_acc_store 27, 26, 25, 24
1103 load_acc_store 23, 22, 21, 20
1104 load_acc_store 19, 18, 17, 16
1107 load_acc_store 16, 17, 18, 19, 1
1108 load_acc_store 20, 21, 22, 23, 1
1109 load_acc_store 24, 25, 26, 27, 1
1110 load_acc_store 28, 29, 30, 31, 1
1111 .purgem load_acc_store
1115 function ff_vp9_idct_idct_32x32_add_neon, export=1
1117 beq idct32x32_dc_add_neon
1122 @ Align the stack, allocate a temp buffer
1125 T sub r12, r12, #2048
1134 .irp i, 0, 4, 8, 12, 16, 20, 24, 28
1135 add r0, sp, #(\i*64)
1137 bl idct32_1d_4x32_pass1_neon
1139 .irp i, 0, 4, 8, 12, 16, 20, 24, 28
1143 bl idct32_1d_4x32_pass2_neon