arm: vp9itxfm: Avoid reloading the idct32 coefficients
[libav.git] / libavcodec / arm / vp9itxfm_neon.S
1 /*
2 * Copyright (c) 2016 Google Inc.
3 *
4 * This file is part of Libav.
5 *
6 * Libav is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
10 *
11 * Libav is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with Libav; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19 */
20
21 #include "libavutil/arm/asm.S"
22 #include "neon.S"
23
24 const itxfm4_coeffs, align=4
25 .short 11585, 6270, 15137, 0
26 iadst4_coeffs:
27 .short 5283, 15212, 9929, 13377
28 endconst
29
30 const iadst8_coeffs, align=4
31 .short 16305, 1606, 14449, 7723, 10394, 12665, 4756, 15679
32 idct_coeffs:
33 .short 11585, 6270, 15137, 3196, 16069, 13623, 9102, 1606
34 .short 16305, 12665, 10394, 7723, 14449, 15679, 4756, 0
35 .short 804, 16364, 12140, 11003, 7005, 14811, 15426, 5520
36 .short 3981, 15893, 14053, 8423, 9760, 13160, 16207, 2404
37 endconst
38
39 const iadst16_coeffs, align=4
40 .short 16364, 804, 15893, 3981, 14811, 7005, 13160, 9760
41 .short 11003, 12140, 8423, 14053, 5520, 15426, 2404, 16207
42 endconst
43
44 @ Do four 4x4 transposes, using q registers for the subtransposes that don't
45 @ need to address the individual d registers.
46 @ r0,r1 == rq1, r2,r3 == rq1, etc
47 .macro transpose16_q_4x_4x4 rq0, rq1, rq2, rq3, rq4, rq5, rq6, rq7, r0, r1, r2, r3, r4, r5, r6, r7, r8, r9, r10, r11, r12, r13, r14, r15
48 vtrn.32 \rq0, \rq1
49 vtrn.32 \rq2, \rq3
50 vtrn.32 \rq4, \rq5
51 vtrn.32 \rq6, \rq7
52 vtrn.16 \r0, \r1
53 vtrn.16 \r2, \r3
54 vtrn.16 \r4, \r5
55 vtrn.16 \r6, \r7
56 vtrn.16 \r8, \r9
57 vtrn.16 \r10, \r11
58 vtrn.16 \r12, \r13
59 vtrn.16 \r14, \r15
60 .endm
61
62 @ out1 = ((in1 + in2) * d0[0] + (1 << 13)) >> 14
63 @ out2 = ((in1 - in2) * d0[0] + (1 << 13)) >> 14
64 @ in/out are d registers
65 .macro mbutterfly0 out1, out2, in1, in2, tmpd1, tmpd2, tmpq3, tmpq4, neg=0
66 vadd.s16 \tmpd1, \in1, \in2
67 vsub.s16 \tmpd2, \in1, \in2
68 vmull.s16 \tmpq3, \tmpd1, d0[0]
69 vmull.s16 \tmpq4, \tmpd2, d0[0]
70 .if \neg > 0
71 vneg.s32 \tmpq3, \tmpq3
72 .endif
73 vrshrn.s32 \out1, \tmpq3, #14
74 vrshrn.s32 \out2, \tmpq4, #14
75 .endm
76
77 @ 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
83 .endm
84
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]
95 .ifb \tmpq5
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
102 .else
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
109 .endif
110 .endm
111
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
120 .endm
121
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
134 .endm
135
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
141 .if \neg > 0
142 vneg.s32 \tmp2, \tmp2
143 .endif
144 vrshrn.s32 \inout1, \tmp1, #14
145 vrshrn.s32 \inout2, \tmp2, #14
146 .endm
147
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
154 .endm
155
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
163 .endm
164
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
174 .endm
175
176 @ out1 = in1 + in2
177 @ out2 = in1 - in2
178 .macro butterfly out1, out2, in1, in2
179 vadd.s16 \out1, \in1, \in2
180 vsub.s16 \out2, \in1, \in2
181 .endm
182
183 @ out1 = in1 - in2
184 @ out2 = in1 + in2
185 .macro butterfly_r out1, out2, in1, in2
186 vsub.s16 \out1, \in1, \in2
187 vadd.s16 \out2, \in1, \in2
188 .endm
189
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
198 .endm
199
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
212 .endm
213
214
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
224 .endm
225
226 .macro idct4 c0, c1, c2, c3
227 vmull.s16 q13, \c1, d0[2]
228 vmull.s16 q11, \c1, d0[1]
229 vadd.i16 d16, \c0, \c2
230 vsub.i16 d17, \c0, \c2
231 vmlal.s16 q13, \c3, d0[1]
232 vmull.s16 q9, d16, d0[0]
233 vmull.s16 q10, d17, d0[0]
234 vmlsl.s16 q11, \c3, d0[2]
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
243 .endm
244
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
264 .endm
265
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);
268
269 .macro itxfm_func4x4 txfm1, txfm2
270 function ff_vp9_\txfm1\()_\txfm2\()_4x4_add_neon, export=1
271 .ifc \txfm1,\txfm2
272 .ifc \txfm1,idct
273 movrel r12, itxfm4_coeffs
274 vld1.16 {d0}, [r12,:64]
275 .endif
276 .ifc \txfm1,iadst
277 movrel r12, iadst4_coeffs
278 vld1.16 {d1}, [r12,:64]
279 .endif
280 .else
281 movrel r12, itxfm4_coeffs
282 vld1.16 {q0}, [r12,:128]
283 .endif
284
285 vmov.i16 q15, #0
286 .ifc \txfm1\()_\txfm2,idct_idct
287 cmp r3, #1
288 bne 1f
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]
296 vdup.16 q2, d4[0]
297 vmov q3, q2
298 b 2f
299 .endif
300
301 1:
302 vld1.16 {d4-d7}, [r2,:128]
303 vst1.16 {q15}, [r2,:128]!
304
305 .ifc \txfm1,iwht
306 vshr.s16 q2, q2, #2
307 vshr.s16 q3, q3, #2
308 .endif
309
310 \txfm1\()4 d4, d5, d6, d7
311
312 vst1.16 {q15}, [r2,:128]!
313 @ Transpose 4x4 with 16 bit elements
314 vtrn.16 d4, d5
315 vtrn.16 d6, d7
316 vtrn.32 q2, q3
317
318 \txfm2\()4 d4, d5, d6, d7
319 2:
320 vld1.32 {d0[]}, [r0,:32], r1
321 vld1.32 {d0[1]}, [r0,:32], r1
322 .ifnc \txfm1,iwht
323 vrshr.s16 q2, q2, #4
324 vrshr.s16 q3, q3, #4
325 .endif
326 vaddw.u8 q2, q2, d0
327 vld1.32 {d1[]}, [r0,:32], r1
328 vld1.32 {d1[1]}, [r0,:32], r1
329 vqmovun.s16 d0, q2
330 sub r0, r0, r1, lsl #2
331
332 vaddw.u8 q3, q3, d1
333 vst1.32 {d0[0]}, [r0,:32], r1
334 vqmovun.s16 d1, q3
335
336 vst1.32 {d0[1]}, [r0,:32], r1
337 vst1.32 {d1[0]}, [r0,:32], r1
338 vst1.32 {d1[1]}, [r0,:32], r1
339
340 bx lr
341 endfunc
342 .endm
343
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
349
350
351 .macro idct8
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[1], d0[2], q2, q3, q4, q5 @ q10 = t2a, q14 = t3a
354 dmbutterfly d18, d19, d30, d31, d0[3], d1[0], q2, q3, q4, q5 @ q9 = t4a, q15 = t7a
355 dmbutterfly d26, d27, d22, d23, d1[1], d1[2], q2, q3, q4, q5 @ q13 = t5a, q11 = t6a
356
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
361
362 butterfly q8, q15, q2, q5 @ q8 = out[0], q15 = out[7]
363
364 dmbutterfly0 d4, d5, d10, d11, q11, q13, q9, q13, d18, d19, d26, d27, q2, q5, q11, q12 @ q2 = t6, q5 = t5
365
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]
369 .endm
370
371 .macro iadst8
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
374
375 dbutterfly_n d22, d23, d4, d5, q2, q3, q6, q7, q11, q12, q2, q3 @ q11 = t0, q2 = t4
376
377 dbutterfly_n d24, d25, d6, d7, q4, q5, q8, q15, q12, q3, q6, q7 @ q12 = t1, q3 = t5
378
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
381
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
384
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
388
389 dmbutterfly_l q10, q11, q5, q7, d4, d5, d6, d7, d0[1], d0[2] @ q10,q11 = t5a, q5,q7 = t4a
390 dmbutterfly_l q2, q3, q13, q14, d12, d13, d8, d9, d0[2], d0[1] @ q2,q3 = t6a, q13,q14 = t7a
391
392 dbutterfly_n d28, d29, d8, d9, q10, q11, q13, q14, q4, q6, q10, q11 @ q14 = out[6], q4 = t7
393
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]
396
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]
399
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]
402 .endm
403
404
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
414 vpush {q4-q5}
415 .else
416 movrel r12, iadst8_coeffs
417 vld1.16 {q1}, [r12,:128]!
418 vpush {q4-q7}
419 .endif
420 vld1.16 {q0}, [r12,:128]
421
422 vmov.i16 q2, #0
423 vmov.i16 q3, #0
424
425 .ifc \txfm1\()_\txfm2,idct_idct
426 cmp r3, #1
427 bne 1f
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
434 vdup.16 q8, d16[0]
435 vmov q9, q8
436 vmov q10, q8
437 vmov q11, q8
438 vmov q12, q8
439 vmov q13, q8
440 vmov q14, q8
441 vmov q15, q8
442 vst1.16 {d4[0]}, [r2,:16]
443 b 2f
444 .endif
445 1:
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]!
450 sub r2, 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]!
455
456 \txfm1\()8
457
458 @ Transpose 8x8 with 16 bit elements
459 vswp d17, d24
460 vswp d19, d26
461 vswp d21, d28
462 vswp d23, d30
463 transpose16_4x4 q8, q9, q10, q11, q12, q13, q14, q15
464
465 \txfm2\()8
466 2:
467 mov r3, r0
468 @ Add into the destination
469 vld1.8 {d4}, [r0,:64], r1
470 vrshr.s16 q8, q8, #5
471 vld1.8 {d5}, [r0,:64], r1
472 vrshr.s16 q9, q9, #5
473 vld1.8 {d6}, [r0,:64], r1
474 vrshr.s16 q10, q10, #5
475 vaddw.u8 q8, q8, d4
476 vld1.8 {d7}, [r0,:64], r1
477 vrshr.s16 q11, q11, #5
478 vaddw.u8 q9, q9, d5
479 vld1.8 {d8}, [r0,:64], r1
480 vrshr.s16 q12, q12, #5
481 vaddw.u8 q10, q10, d6
482 vqmovun.s16 d4, q8
483 vld1.8 {d9}, [r0,:64], r1
484 vrshr.s16 q13, q13, #5
485 vaddw.u8 q11, q11, d7
486 vqmovun.s16 d5, q9
487 vld1.8 {d10}, [r0,:64], r1
488 vrshr.s16 q14, q14, #5
489 vaddw.u8 q12, q12, d8
490 vqmovun.s16 d6, q10
491 vld1.8 {d11}, [r0,:64], r1
492 vrshr.s16 q15, q15, #5
493 vaddw.u8 q13, q13, d9
494 vqmovun.s16 d7, q11
495
496
497 vst1.8 {d4}, [r3,:64], r1
498 vaddw.u8 q14, q14, d10
499 vst1.8 {d5}, [r3,:64], r1
500 vqmovun.s16 d8, q12
501 vst1.8 {d6}, [r3,:64], r1
502 vaddw.u8 q15, q15, d11
503 vst1.8 {d7}, [r3,:64], r1
504 vqmovun.s16 d9, q13
505 vst1.8 {d8}, [r3,:64], r1
506 vqmovun.s16 d10, q14
507 vst1.8 {d9}, [r3,:64], r1
508 vqmovun.s16 d11, q15
509
510 vst1.8 {d10}, [r3,:64], r1
511 vst1.8 {d11}, [r3,:64], r1
512
513 .ifc \txfm1\()_\txfm2,idct_idct
514 vpop {q4-q5}
515 .else
516 vpop {q4-q7}
517 .endif
518 bx lr
519 endfunc
520 .endm
521
522 itxfm_func8x8 idct, idct
523 itxfm_func8x8 iadst, idct
524 .ltorg
525 itxfm_func8x8 idct, iadst
526 itxfm_func8x8 iadst, iadst
527
528
529 function idct16x16_dc_add_neon
530 movrel r12, idct_coeffs
531 vld1.16 {d0}, [r12,:64]
532
533 vmov.i16 q2, #0
534
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
540 vdup.16 q8, d16[0]
541 vst1.16 {d4[0]}, [r2,:16]
542
543 vrshr.s16 q8, q8, #6
544
545 mov r3, r0
546 mov r12, #16
547 1:
548 @ Loop to add the constant from q8 into all 16x16 outputs
549 subs r12, r12, #2
550 vld1.8 {q2}, [r0,:128], r1
551 vaddw.u8 q10, q8, d4
552 vld1.8 {q3}, [r0,:128], r1
553 vaddw.u8 q11, q8, d5
554 vaddw.u8 q12, q8, d6
555 vaddw.u8 q13, q8, d7
556 vqmovun.s16 d4, q10
557 vqmovun.s16 d5, q11
558 vqmovun.s16 d6, q12
559 vst1.8 {q2}, [r3,:128], r1
560 vqmovun.s16 d7, q13
561 vst1.8 {q3}, [r3,:128], r1
562 bne 1b
563
564 bx lr
565 endfunc
566 .ltorg
567
568 .macro idct16_end
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
577
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
580
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]
592 bx lr
593 .endm
594
595 function idct16
596 mbutterfly0 d16, d24, d16, d24, d4, d6, q2, q3 @ d16 = t0a, d24 = t1a
597 mbutterfly d20, d28, d0[1], d0[2], q2, q3 @ d20 = t2a, d28 = t3a
598 mbutterfly d18, d30, d0[3], d1[0], q2, q3 @ d18 = t4a, d30 = t7a
599 mbutterfly d26, d22, d1[1], d1[2], q2, q3 @ d26 = t5a, d22 = t6a
600 mbutterfly d17, d31, d1[3], d2[0], q2, q3 @ d17 = t8a, d31 = t15a
601 mbutterfly d25, d23, d2[1], d2[2], q2, q3 @ d25 = t9a, d23 = t14a
602 mbutterfly d21, d27, d2[3], d3[0], q2, q3 @ d21 = t10a, d27 = t13a
603 mbutterfly d29, d19, d3[1], d3[2], q2, q3 @ d29 = t11a, d19 = t12a
604
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
613
614 mbutterfly0 d22, d26, d22, d26, d18, d30, q9, q15 @ d22 = t6a, d26 = t5a
615 mbutterfly d23, d25, d0[1], d0[2], q9, q15 @ d23 = t9a, d25 = t14a
616 mbutterfly d27, d21, d0[1], d0[2], q9, q15, neg=1 @ d27 = t13a, d21 = t10a
617 idct16_end
618 endfunc
619
620 function idct16_half
621 mbutterfly0_h d16, d24, d16, d24, d4, d6, q2, q3 @ d16 = t0a, d24 = t1a
622 mbutterfly_h1 d20, d28, d0[1], d0[2], q2, q3 @ d20 = t2a, d28 = t3a
623 mbutterfly_h1 d18, d30, d0[3], d1[0], q2, q3 @ d18 = t4a, d30 = t7a
624 mbutterfly_h2 d26, d22, d1[1], d1[2], q2, q3 @ d26 = t5a, d22 = t6a
625 mbutterfly_h1 d17, d31, d1[3], d2[0], q2, q3 @ d17 = t8a, d31 = t15a
626 mbutterfly_h2 d25, d23, d2[1], d2[2], q2, q3 @ d25 = t9a, d23 = t14a
627 mbutterfly_h1 d21, d27, d2[3], d3[0], q2, q3 @ d21 = t10a, d27 = t13a
628 mbutterfly_h2 d29, d19, d3[1], d3[2], q2, q3 @ d29 = t11a, d19 = t12a
629
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
638
639 mbutterfly0 d22, d26, d22, d26, d18, d30, q9, q15 @ d22 = t6a, d26 = t5a
640 mbutterfly d23, d25, d0[1], d0[2], q9, q15 @ d23 = t9a, d25 = t14a
641 mbutterfly d27, d21, d0[1], d0[2], q9, q15, neg=1 @ d27 = t13a, d21 = t10a
642 idct16_end
643 endfunc
644
645 function idct16_quarter
646 vmull.s16 q12, d19, d3[2]
647 vmull.s16 q2, d17, d1[3]
648 vmull.s16 q3, d18, d1[0]
649 vmull.s16 q15, d18, d0[3]
650 vneg.s32 q12, q12
651 vmull.s16 q14, d17, d2[0]
652 vmull.s16 q13, d19, d3[1]
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
661
662 mbutterfly_l q10, q11, d17, d24, d0[1], d0[2]
663 mbutterfly_l q9, q15, d29, d16, d0[1], d0[2]
664 vneg.s32 q11, q11
665 vrshrn.s32 d27, q10, #14
666 vrshrn.s32 d21, q11, #14
667 vrshrn.s32 d23, q9, #14
668 vrshrn.s32 d25, q15, #14
669 vmov d4, d28
670 vmov d5, d28
671 mbutterfly0 d22, d26, d7, d6, d18, d30, q9, q15
672 vmov d20, d28
673 idct16_end
674 endfunc
675
676 function iadst16
677 movrel r12, iadst16_coeffs
678 vld1.16 {q0-q1}, [r12,:128]
679
680 mbutterfly_l q3, q2, d31, d16, d0[1], d0[0] @ q3 = t1, q2 = t0
681 mbutterfly_l q5, q4, d23, d24, d2[1], d2[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
685
686 mbutterfly_l q3, q2, d21, d26, d2[3], d2[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, d1[1], d1[0] @ q5 = t5, q4 = t4
689 butterfly_n d18, d21, q6, q2, q3, q2 @ d18 = t2a, d21 = t10a
690
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, d1[3], d1[2] @ q3 = t7, q2 = t6
694 butterfly_n d27, d19, q4, q6, q5, q6 @ d27 = t4a, d19 = t12a
695
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, d0[3], d1[0] @ q7 = t9, q6 = t8
701 butterfly_n d25, d17, q2, q4, q3, q4 @ d25 = t6a, d17 = t14a
702
703 mbutterfly_l q2, q3, d28, d19, d1[0], d0[3] @ 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[1], d1[2] @ 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
708
709 mbutterfly_l q6, q7, d30, d17, d1[2], d1[1] @ 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
713
714 butterfly_r d6, d25, d18, d25 @ d6 = t6, d25 = t2
715 butterfly_r d7, d22, d29, d22 @ d7 = t7, d22 = t3
716
717 mbutterfly_l q5, q4, d19, d28, d0[1], d0[2] @ q5 = t13, q4 = t12
718 mbutterfly_l q6, q7, d30, d17, d0[2], d0[1] @ q6 = t14, q7 = t15
719
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]
723
724 mbutterfly_l q5, q4, d4, d5, d0[1], d0[2] @ q5 = t5a, q4 = t4a
725 mbutterfly_l q6, q7, d7, d6, d0[2], d0[1] @ q6 = t6a, q7 = t7a
726
727 butterfly d2, d6, d27, d25 @ d2 = out[0], d6 = t2a
728 butterfly d3, d7, d23, d21 @ d3 =-out[1], d7 = t10
729
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
733
734 butterfly d5, d8, d20, d22 @ d5 =-out[15],d8 = t3a
735 butterfly d4, d9, d24, d26 @ d4 = out[14],d9 = t11
736
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]
741
742 vneg.s16 d31, d5 @ d31 = out[15]
743 vneg.s16 d17, d3 @ d17 = out[1]
744
745 vmov d16, d2
746 vmov d30, d4
747 bx lr
748 endfunc
749
750 .macro load_add_store coef0, coef1, coef2, coef3
751 vrshr.s16 \coef0, \coef0, #6
752 vrshr.s16 \coef1, \coef1, #6
753
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
766
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
779
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
784 .endm
785
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)
790 @ r1 = slice offset
791 @ r2 = src
792 function \txfm\()16_1d_4x16_pass1_neon
793 push {lr}
794
795 mov r12, #32
796 vmov.s16 q2, #0
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
800 .endr
801
802 bl \txfm\()16
803
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
808
809 @ Store the transposed 4x4 blocks horizontally.
810 cmp r1, #12
811 beq 1f
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]!
814 .endr
815 pop {pc}
816 1:
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
821 @ last 4x4 block).
822 add r0, r0, #8
823 vst1.16 {d20}, [r0,:64]!
824 vst1.16 {d24}, [r0,:64]!
825 vst1.16 {d28}, [r0,:64]!
826 add r0, r0, #8
827 vst1.16 {d21}, [r0,:64]!
828 vst1.16 {d25}, [r0,:64]!
829 vst1.16 {d29}, [r0,:64]!
830 add r0, r0, #8
831 vst1.16 {d22}, [r0,:64]!
832 vst1.16 {d26}, [r0,:64]!
833 vst1.16 {d30}, [r0,:64]!
834 add r0, r0, #8
835 vst1.16 {d23}, [r0,:64]!
836 vst1.16 {d27}, [r0,:64]!
837 vst1.16 {d31}, [r0,:64]!
838 vmov d28, d16
839 vmov d29, d17
840 vmov d30, d18
841 vmov d31, d19
842 pop {pc}
843 endfunc
844
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.
847 @ r0 = dst
848 @ r1 = dst stride
849 @ r2 = src (temp buffer)
850 @ r3 = slice offset
851 function \txfm\()16_1d_4x16_pass2_neon
852 push {lr}
853 mov r12, #32
854 .irp i, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27
855 vld1.16 {d\i}, [r2,:64], r12
856 .endr
857 cmp r3, #0
858 beq 1f
859 .irp i, 28, 29, 30, 31
860 vld1.16 {d\i}, [r2,:64], r12
861 .endr
862 1:
863
864 add r3, r0, r1
865 lsl r1, r1, #1
866 bl \txfm\()16
867
868 load_add_store q8, q9, q10, q11
869 load_add_store q12, q13, q14, q15
870
871 pop {pc}
872 endfunc
873 .endm
874
875 itxfm16_1d_funcs idct
876 itxfm16_1d_funcs iadst
877
878 @ This is the minimum eob value for each subpartition, in increments of 4
879 const min_eob_idct_idct_16, align=4
880 .short 0, 10, 38, 89
881 endconst
882
883 .macro itxfm_func16x16 txfm1, txfm2
884 function ff_vp9_\txfm1\()_\txfm2\()_16x16_add_neon, export=1
885 .ifc \txfm1\()_\txfm2,idct_idct
886 cmp r3, #1
887 beq idct16x16_dc_add_neon
888 .endif
889 push {r4-r8,lr}
890 .ifnc \txfm1\()_\txfm2,idct_idct
891 vpush {q4-q7}
892 .else
893 movrel r8, min_eob_idct_idct_16 + 2
894 .endif
895
896 @ Align the stack, allocate a temp buffer
897 T mov r7, sp
898 T and r7, r7, #15
899 A and r7, sp, #15
900 add r7, r7, #512
901 sub sp, sp, r7
902
903 mov r4, r0
904 mov r5, r1
905 mov r6, r2
906
907 .ifc \txfm1,idct
908 movrel r12, idct_coeffs
909 vld1.16 {q0-q1}, [r12,:128]
910 .endif
911
912 .ifc \txfm1\()_\txfm2,idct_idct
913 cmp r3, #10
914 ble idct16x16_quarter_add_neon
915 cmp r3, #38
916 ble idct16x16_half_add_neon
917 .endif
918
919 .irp i, 0, 4, 8, 12
920 add r0, sp, #(\i*32)
921 .ifc \txfm1\()_\txfm2,idct_idct
922 .if \i > 0
923 ldrh_post r1, r8, #2
924 cmp r3, r1
925 it le
926 movle r1, #(16 - \i)/4
927 ble 1f
928 .endif
929 .endif
930 mov r1, #\i
931 add r2, r6, #(\i*2)
932 bl \txfm1\()16_1d_4x16_pass1_neon
933 .endr
934
935 .ifc \txfm1\()_\txfm2,idct_idct
936 b 3f
937 1:
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
940 vmov.i16 q14, #0
941 vmov.i16 q15, #0
942 2:
943 subs r1, r1, #1
944 .rept 4
945 vst1.16 {q14-q15}, [r0,:128]!
946 .endr
947 bne 2b
948 3:
949 .endif
950
951 .ifc \txfm1\()_\txfm2,iadst_idct
952 movrel r12, idct_coeffs
953 vld1.16 {q0-q1}, [r12,:128]
954 .endif
955 .irp i, 0, 4, 8, 12
956 add r0, r4, #(\i)
957 mov r1, r5
958 add r2, sp, #(\i*2)
959 mov r3, #\i
960 bl \txfm2\()16_1d_4x16_pass2_neon
961 .endr
962
963 add sp, sp, r7
964 .ifnc \txfm1\()_\txfm2,idct_idct
965 vpop {q4-q7}
966 .endif
967 pop {r4-r8,pc}
968 endfunc
969 .endm
970
971 itxfm_func16x16 idct, idct
972 itxfm_func16x16 iadst, idct
973 itxfm_func16x16 idct, iadst
974 itxfm_func16x16 iadst, iadst
975 .ltorg
976
977 function idct16_1d_4x16_pass1_quarter_neon
978 push {lr}
979 mov r12, #32
980 vmov.s16 q2, #0
981 .irp i, 16, 17, 18, 19
982 vld1.16 {d\i}, [r2,:64]
983 vst1.16 {d4}, [r2,:64], r12
984 .endr
985
986 bl idct16_quarter
987
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
992
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.
996 add r0, r0, #8
997 vst1.16 {d20}, [r0,:64]!
998 vst1.16 {d24}, [r0,:64]!
999 vst1.16 {d28}, [r0,:64]!
1000 add r0, r0, #8
1001 vst1.16 {d21}, [r0,:64]!
1002 vst1.16 {d25}, [r0,:64]!
1003 vst1.16 {d29}, [r0,:64]!
1004 add r0, r0, #8
1005 vst1.16 {d22}, [r0,:64]!
1006 vst1.16 {d26}, [r0,:64]!
1007 vst1.16 {d30}, [r0,:64]!
1008 add r0, r0, #8
1009 vst1.16 {d23}, [r0,:64]!
1010 vst1.16 {d27}, [r0,:64]!
1011 vst1.16 {d31}, [r0,:64]!
1012 pop {pc}
1013 endfunc
1014
1015 function idct16_1d_4x16_pass2_quarter_neon
1016 push {lr}
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.
1019 cmp r3, #0
1020 beq 1f
1021 mov r12, #32
1022 .irp i, 16, 17, 18, 19
1023 vld1.16 {d\i}, [r2,:64], r12
1024 .endr
1025 1:
1026
1027 add r3, r0, r1
1028 lsl r1, r1, #1
1029 bl idct16_quarter
1030
1031 load_add_store q8, q9, q10, q11
1032 load_add_store q12, q13, q14, q15
1033
1034 pop {pc}
1035 endfunc
1036
1037 function idct16_1d_4x16_pass1_half_neon
1038 push {lr}
1039 mov r12, #32
1040 vmov.s16 q2, #0
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
1044 .endr
1045
1046 bl idct16_half
1047
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
1052
1053 @ Store the transposed 4x4 blocks horizontally.
1054 cmp r1, #4
1055 beq 1f
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]!
1058 .endr
1059 pop {pc}
1060 1:
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).
1066 add r0, r0, #8
1067 vst1.16 {d20}, [r0,:64]!
1068 vst1.16 {d24}, [r0,:64]!
1069 vst1.16 {d28}, [r0,:64]!
1070 add r0, r0, #8
1071 vst1.16 {d21}, [r0,:64]!
1072 vst1.16 {d25}, [r0,:64]!
1073 vst1.16 {d29}, [r0,:64]!
1074 add r0, r0, #8
1075 vst1.16 {d22}, [r0,:64]!
1076 vst1.16 {d26}, [r0,:64]!
1077 vst1.16 {d30}, [r0,:64]!
1078 add r0, r0, #8
1079 vst1.16 {d23}, [r0,:64]!
1080 vst1.16 {d27}, [r0,:64]!
1081 vst1.16 {d31}, [r0,:64]!
1082 vmov d20, d16
1083 vmov d21, d17
1084 vmov d22, d18
1085 vmov d23, d19
1086 pop {pc}
1087 endfunc
1088
1089 function idct16_1d_4x16_pass2_half_neon
1090 push {lr}
1091 mov r12, #32
1092 cmp r3, #0
1093 .irp i, 16, 17, 18, 19
1094 vld1.16 {d\i}, [r2,:64], r12
1095 .endr
1096 beq 1f
1097 .irp i, 20, 21, 22, 23
1098 vld1.16 {d\i}, [r2,:64], r12
1099 .endr
1100 1:
1101
1102 add r3, r0, r1
1103 lsl r1, r1, #1
1104 bl idct16_half
1105
1106 load_add_store q8, q9, q10, q11
1107 load_add_store q12, q13, q14, q15
1108
1109 pop {pc}
1110 endfunc
1111 .purgem load_add_store
1112
1113 .macro idct16_partial size
1114 function idct16x16_\size\()_add_neon
1115 add r0, sp, #(0*32)
1116 mov r1, #0
1117 add r2, r6, #(0*2)
1118 bl idct16_1d_4x16_pass1_\size\()_neon
1119 .ifc \size,half
1120 add r0, sp, #(4*32)
1121 mov r1, #4
1122 add r2, r6, #(4*2)
1123 bl idct16_1d_4x16_pass1_\size\()_neon
1124 .endif
1125 .irp i, 0, 4, 8, 12
1126 add r0, r4, #(\i)
1127 mov r1, r5
1128 add r2, sp, #(\i*2)
1129 mov r3, #\i
1130 bl idct16_1d_4x16_pass2_\size\()_neon
1131 .endr
1132
1133 add sp, sp, r7
1134 pop {r4-r8,pc}
1135 endfunc
1136 .endm
1137
1138 idct16_partial quarter
1139 idct16_partial half
1140
1141 function idct32x32_dc_add_neon
1142 movrel r12, idct_coeffs
1143 vld1.16 {d0}, [r12,:64]
1144
1145 vmov.i16 q2, #0
1146
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
1152 vdup.16 q8, d16[0]
1153 vst1.16 {d4[0]}, [r2,:16]
1154
1155 vrshr.s16 q8, q8, #6
1156
1157 mov r3, r0
1158 mov r12, #32
1159 1:
1160 @ Loop to add the constant from q8 into all 32x32 outputs
1161 subs r12, r12, #2
1162 vld1.8 {q0-q1}, [r0,:128], r1
1163 vaddw.u8 q9, q8, d0
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
1171 vqmovun.s16 d0, q9
1172 vaddw.u8 q9, q8, d7
1173 vqmovun.s16 d1, q10
1174 vqmovun.s16 d2, q11
1175 vqmovun.s16 d3, q12
1176 vqmovun.s16 d4, q13
1177 vqmovun.s16 d5, q14
1178 vst1.8 {q0-q1}, [r3,:128], r1
1179 vqmovun.s16 d6, q15
1180 vqmovun.s16 d7, q9
1181 vst1.8 {q2-q3}, [r3,:128], r1
1182 bne 1b
1183
1184 bx lr
1185 endfunc
1186
1187 .macro idct32_end
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
1196
1197 mbutterfly d27, d20, d0[1], d0[2], q12, q15 @ d27 = t18a, d20 = t29a
1198 mbutterfly d29, d9, d0[1], d0[2], q12, q15 @ d29 = t19, d9 = t28
1199 mbutterfly d28, d10, d0[1], d0[2], q12, q15, neg=1 @ d28 = t27, d10 = t20
1200 mbutterfly d26, d21, d0[1], d0[2], q12, q15, neg=1 @ d26 = t26a, d21 = t21a
1201
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
1211
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
1216 bx lr
1217 .endm
1218
1219 function idct32_odd
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
1228
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
1237
1238 mbutterfly d23, d24, d0[3], d1[0], q8, q9 @ d23 = t17a, d24 = t30a
1239 mbutterfly d27, d20, d0[3], d1[0], q8, q9, neg=1 @ d27 = t29a, d20 = t18a
1240 mbutterfly d21, d26, d1[1], d1[2], q8, q9 @ d21 = t21a, d26 = t26a
1241 mbutterfly d25, d22, d1[1], d1[2], q8, q9, neg=1 @ d25 = t25a, d22 = t22a
1242 idct32_end
1243 endfunc
1244
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
1254
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
1263
1264 mbutterfly d23, d24, d0[3], d1[0], q8, q9 @ d23 = t17a, d24 = t30a
1265 mbutterfly d27, d20, d0[3], d1[0], q8, q9, neg=1 @ d27 = t29a, d20 = t18a
1266 mbutterfly d21, d26, d1[1], d1[2], q8, q9 @ d21 = t21a, d26 = t26a
1267 mbutterfly d25, d22, d1[1], d1[2], q8, q9, neg=1 @ d25 = t25a, d22 = t22a
1268
1269 idct32_end
1270 endfunc
1271
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]
1281
1282 vneg.s32 q14, q14
1283 vneg.s32 q5, q5
1284
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
1293
1294 mbutterfly_l q8, q9, d29, d8, d0[3], d1[0]
1295 mbutterfly_l q13, q10, d31, d9, d0[3], d1[0]
1296 vrshrn.s32 d23, q8, #14
1297 vrshrn.s32 d24, q9, #14
1298 vneg.s32 q10, q10
1299 vrshrn.s32 d27, q13, #14
1300 vrshrn.s32 d20, q10, #14
1301 mbutterfly_l q8, q9, d30, d10, d1[1], d1[2]
1302 vrshrn.s32 d21, q8, #14
1303 vrshrn.s32 d26, q9, #14
1304 mbutterfly_l q8, q9, d28, d11, d1[1], d1[2]
1305 vrshrn.s32 d25, q8, #14
1306 vneg.s32 q9, q9
1307 vrshrn.s32 d22, q9, #14
1308
1309 idct32_end
1310 endfunc
1311
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)
1320 @ r1 = unused
1321 @ r2 = src
1322 function idct32_1d_4x32_pass1\suffix\()_neon
1323 push {lr}
1324
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
1327 @ to q4-q5
1328 vmov q4, q2
1329 vmov q5, q3
1330
1331 @ Double stride of the input, since we only read every other line
1332 mov r12, #128
1333 vmov.s16 d4, #0
1334
1335 @ d16 = IN(0), d17 = IN(2) ... d31 = IN(30)
1336 .ifb \suffix
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
1340 .endr
1341 .endif
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
1346 .endr
1347 .endif
1348 .ifc \suffix,_half
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
1352 .endr
1353 .endif
1354
1355 bl idct16\suffix
1356
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.
1359 vmov q2, q4
1360 vmov q3, q5
1361
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]!
1371 vrev64.16 d\i, d\i
1372 .endr
1373 .irp i, \d, \c, \b, \a
1374 vst1.16 {d\i}, [r0,:64]!
1375 .endr
1376 .endm
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
1381 sub r0, r0, #256
1382 .purgem store_rev
1383
1384 @ Move r2 back to the start of the input, and move
1385 @ to the first odd row
1386 .ifb \suffix
1387 sub r2, r2, r12, lsl #4
1388 .endif
1389 .ifc \suffix,_quarter
1390 sub r2, r2, r12, lsl #2
1391 .endif
1392 .ifc \suffix,_half
1393 sub r2, r2, r12, lsl #3
1394 .endif
1395 add r2, r2, #64
1396
1397 vmov.s16 d8, #0
1398 @ d16 = IN(1), d17 = IN(3) ... d31 = IN(31)
1399 .ifb \suffix
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
1403 .endr
1404 .endif
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
1409 .endr
1410 .endif
1411 .ifc \suffix,_half
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
1415 .endr
1416 .endif
1417
1418 bl idct32_odd\suffix
1419
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
1421
1422 @ Store the registers a, b, c, d horizontally,
1423 @ adding into the output first, and then mirrored, subtracted
1424 @ from the output.
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]!
1430 vrev64.16 d\i, d\i
1431 .endr
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]!
1436 .endr
1437 .endm
1438
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
1443 .purgem store_rev
1444 pop {pc}
1445 endfunc
1446 .ltorg
1447
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.
1451 @ r0 = dst
1452 @ r1 = dst stride
1453 @ r2 = src (temp buffer)
1454 function idct32_1d_4x32_pass2\suffix\()_neon
1455 push {lr}
1456 vmov q4, q2
1457 vmov q5, q3
1458
1459 mov r12, #128
1460 @ d16 = IN(0), d17 = IN(2) ... d31 = IN(30)
1461 .ifb \suffix
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
1464 .endr
1465 sub r2, r2, r12, lsl #4
1466 .endif
1467 .ifc \suffix,_quarter
1468 .irp i, 16, 17, 18, 19
1469 vld1.16 {d\i}, [r2,:64], r12
1470 .endr
1471 sub r2, r2, r12, lsl #2
1472 .endif
1473 .ifc \suffix,_half
1474 .irp i, 16, 17, 18, 19, 20, 21, 22, 23
1475 vld1.16 {d\i}, [r2,:64], r12
1476 .endr
1477 sub r2, r2, r12, lsl #3
1478 .endif
1479
1480 bl idct16\suffix
1481
1482 vmov q2, q4
1483 vmov q3, q5
1484
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
1487 .endr
1488
1489 sub r2, r2, r12, lsl #4
1490 add r2, r2, #64
1491
1492 @ d16 = IN(1), d17 = IN(3) ... d31 = IN(31)
1493 .ifb \suffix
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
1496 .endr
1497 sub r2, r2, r12, lsl #4
1498 .endif
1499 .ifc \suffix,_quarter
1500 .irp i, 16, 17, 18, 19
1501 vld1.16 {d\i}, [r2,:64], r12
1502 .endr
1503 sub r2, r2, r12, lsl #2
1504 .endif
1505 .ifc \suffix,_half
1506 .irp i, 16, 17, 18, 19, 20, 21, 22, 23
1507 vld1.16 {d\i}, [r2,:64], r12
1508 .endr
1509 sub r2, r2, r12, lsl #3
1510 .endif
1511 sub r2, r2, #64
1512
1513 bl idct32_odd\suffix
1514
1515 mov r12, #128
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
1519 .if \neg == 0
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
1526 .else
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
1533 .endif
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
1543 vqmovun.s16 d8, q4
1544 vqmovun.s16 d9, q5
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
1549 .endm
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
1554 sub r2, r2, r12
1555 neg r12, r12
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
1561 pop {pc}
1562 endfunc
1563 .endm
1564
1565 idct32_funcs
1566 idct32_funcs _quarter
1567 idct32_funcs _half
1568
1569 const min_eob_idct_idct_32, align=4
1570 .short 0, 9, 34, 70, 135, 240, 336, 448
1571 endconst
1572
1573 function ff_vp9_idct_idct_32x32_add_neon, export=1
1574 cmp r3, #1
1575 beq idct32x32_dc_add_neon
1576 push {r4-r8,lr}
1577 vpush {q4-q6}
1578 movrel r8, min_eob_idct_idct_32 + 2
1579
1580 @ Align the stack, allocate a temp buffer
1581 T mov r7, sp
1582 T and r7, r7, #15
1583 A and r7, sp, #15
1584 add r7, r7, #2048
1585 sub sp, sp, r7
1586
1587 mov r4, r0
1588 mov r5, r1
1589 mov r6, r2
1590
1591 movrel r12, idct_coeffs
1592 vld1.16 {q0-q1}, [r12,:128]!
1593 vld1.16 {q2-q3}, [r12,:128]
1594
1595 cmp r3, #34
1596 ble idct32x32_quarter_add_neon
1597 cmp r3, #135
1598 ble idct32x32_half_add_neon
1599
1600 .irp i, 0, 4, 8, 12, 16, 20, 24, 28
1601 add r0, sp, #(\i*64)
1602 .if \i > 0
1603 ldrh_post r1, r8, #2
1604 cmp r3, r1
1605 it le
1606 movle r1, #(32 - \i)/2
1607 ble 1f
1608 .endif
1609 add r2, r6, #(\i*2)
1610 bl idct32_1d_4x32_pass1_neon
1611 .endr
1612 b 3f
1613
1614 1:
1615 @ Write zeros to the temp buffer for pass 2
1616 vmov.i16 q14, #0
1617 vmov.i16 q15, #0
1618 2:
1619 subs r1, r1, #1
1620 .rept 4
1621 vst1.16 {q14-q15}, [r0,:128]!
1622 .endr
1623 bne 2b
1624 3:
1625 .irp i, 0, 4, 8, 12, 16, 20, 24, 28
1626 add r0, r4, #(\i)
1627 mov r1, r5
1628 add r2, sp, #(\i*2)
1629 bl idct32_1d_4x32_pass2_neon
1630 .endr
1631
1632 add sp, sp, r7
1633 vpop {q4-q6}
1634 pop {r4-r8,pc}
1635 endfunc
1636
1637 function idct32x32_quarter_add_neon
1638 .irp i, 0, 4
1639 add r0, sp, #(\i*64)
1640 .if \i == 4
1641 cmp r3, #9
1642 ble 1f
1643 .endif
1644 add r2, r6, #(\i*2)
1645 bl idct32_1d_4x32_pass1_quarter_neon
1646 .endr
1647 b 3f
1648
1649 1:
1650 @ Write zeros to the temp buffer for pass 2
1651 vmov.i16 q14, #0
1652 vmov.i16 q15, #0
1653 .rept 8
1654 vst1.16 {q14-q15}, [r0,:128]!
1655 .endr
1656 3:
1657 .irp i, 0, 4, 8, 12, 16, 20, 24, 28
1658 add r0, r4, #(\i)
1659 mov r1, r5
1660 add r2, sp, #(\i*2)
1661 bl idct32_1d_4x32_pass2_quarter_neon
1662 .endr
1663
1664 add sp, sp, r7
1665 vpop {q4-q6}
1666 pop {r4-r8,pc}
1667 endfunc
1668
1669 function idct32x32_half_add_neon
1670 .irp i, 0, 4, 8, 12
1671 add r0, sp, #(\i*64)
1672 .if \i > 0
1673 ldrh_post r1, r8, #2
1674 cmp r3, r1
1675 it le
1676 movle r1, #(16 - \i)/2
1677 ble 1f
1678 .endif
1679 add r2, r6, #(\i*2)
1680 bl idct32_1d_4x32_pass1_half_neon
1681 .endr
1682 b 3f
1683
1684 1:
1685 @ Write zeros to the temp buffer for pass 2
1686 vmov.i16 q14, #0
1687 vmov.i16 q15, #0
1688 2:
1689 subs r1, r1, #1
1690 .rept 4
1691 vst1.16 {q14-q15}, [r0,:128]!
1692 .endr
1693 bne 2b
1694 3:
1695 .irp i, 0, 4, 8, 12, 16, 20, 24, 28
1696 add r0, r4, #(\i)
1697 mov r1, r5
1698 add r2, sp, #(\i*2)
1699 bl idct32_1d_4x32_pass2_half_neon
1700 .endr
1701
1702 add sp, sp, r7
1703 vpop {q4-q6}
1704 pop {r4-r8,pc}
1705 endfunc