2 * Copyright (c) 2016 Google Inc.
4 * This file is part of Libav.
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.
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.
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
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
795 @ Align the stack, allocate a temp buffer
807 movrel r12, idct_coeffs
808 vld1.16 {q0-q1}, [r12,:128]
815 bl \txfm1\()16_1d_4x16_pass1_neon
818 movrel r12, idct_coeffs
819 vld1.16 {q0-q1}, [r12,:128]
826 bl \txfm2\()16_1d_4x16_pass2_neon
830 .ifnc \txfm1\()_\txfm2,idct_idct
837 itxfm_func16x16 idct, idct
838 itxfm_func16x16 iadst, idct
839 itxfm_func16x16 idct, iadst
840 itxfm_func16x16 iadst, iadst
844 function idct32x32_dc_add_neon
845 movrel r12, idct_coeffs
846 vld1.16 {d0}, [r12,:64]
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
856 vst1.16 {d4[0]}, [r2,:16]
862 @ Loop to add the constant from q8 into all 32x32 outputs
863 vld1.8 {q2-q3}, [r0,:128]
872 vst1.8 {q2-q3}, [r0,:128], r1
880 movrel r12, idct_coeffs
882 vld1.16 {q0-q1}, [r12,:128]
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
894 vld1.16 {q0}, [r12,:128]
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
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
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
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
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
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
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)
949 function idct32_1d_4x32_pass1_neon
950 movrel r12, idct_coeffs
951 vld1.16 {q0-q1}, [r12,:128]
953 @ Double stride of the input, since we only read every other line
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
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]!
976 .irp i, \d, \c, \b, \a
977 vst1.16 {d\i}, [r0,:64]!
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
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
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
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
1003 @ Store the registers a, b, c, d horizontally,
1004 @ adding into the output first, and then mirrored, subtracted
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]!
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]!
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
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.
1034 @ r2 = src (temp buffer)
1035 function idct32_1d_4x32_pass2_neon
1036 movrel r12, idct_coeffs
1037 vld1.16 {q0-q1}, [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
1044 sub r2, r2, r12, lsl #4
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
1052 sub r2, r2, r12, lsl #4
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
1059 sub r2, r2, r12, lsl #4
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
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
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
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
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
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
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
1113 function ff_vp9_idct_idct_32x32_add_neon, export=1
1115 beq idct32x32_dc_add_neon
1119 @ Align the stack, allocate a temp buffer
1130 .irp i, 0, 4, 8, 12, 16, 20, 24, 28
1131 add r0, sp, #(\i*64)
1133 bl idct32_1d_4x32_pass1_neon
1135 .irp i, 0, 4, 8, 12, 16, 20, 24, 28
1139 bl idct32_1d_4x32_pass2_neon