8dc4bbfa5529e232ec49d8bec0d04f718e6f6cd1
[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, d5, d4, d5 @ d16 = t16a, d5 = t19a
1189 butterfly d17, d20, d23, d20 @ d17 = t17, d20 = t18
1190 butterfly d18, d6, d7, d6 @ d18 = t23a, d6 = t20a
1191 butterfly d19, d21, d22, d21 @ d19 = t22, d21 = t21
1192 butterfly d4, d28, d28, d30 @ d4 = t24a, d28 = t27a
1193 butterfly d23, d26, d25, d26 @ d23 = t25, d26 = t26
1194 butterfly d7, d29, d29, d31 @ d7 = 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, d5, d0[1], d0[2], q12, q15 @ d29 = t19, d5 = t28
1199 mbutterfly d28, d6, d0[1], d0[2], q12, q15, neg=1 @ d28 = t27, d6 = t20
1200 mbutterfly d26, d21, d0[1], d0[2], q12, q15, neg=1 @ d26 = t26a, d21 = t21a
1201
1202 butterfly d31, d24, d7, d4 @ 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, d5, d28 @ d27 = t27a, d28 = t28a
1208 butterfly d4, d26, d20, d26 @ d4 = t29, d26 = t26
1209 butterfly d19, d20, d29, d6 @ d19 = t19a, d20 = t20
1210 vmov d29, d4 @ d29 = t29
1211
1212 mbutterfly0 d27, d20, d27, d20, d4, d6, q2, q3 @ d27 = t27, d20 = t20
1213 mbutterfly0 d26, d21, d26, d21, d4, d6, q2, q3 @ d26 = t26a, d21 = t21a
1214 mbutterfly0 d25, d22, d25, d22, d4, d6, q2, q3 @ d25 = t25, d22 = t22
1215 mbutterfly0 d24, d23, d24, d23, d4, d6, q2, q3 @ d24 = t24a, d23 = t23a
1216 bx lr
1217 .endm
1218
1219 function idct32_odd
1220 movrel r12, idct_coeffs
1221 add r12, r12, #32
1222 vld1.16 {q0-q1}, [r12,:128]
1223
1224 mbutterfly d16, d31, d0[0], d0[1], q2, q3 @ d16 = t16a, d31 = t31a
1225 mbutterfly d24, d23, d0[2], d0[3], q2, q3 @ d24 = t17a, d23 = t30a
1226 mbutterfly d20, d27, d1[0], d1[1], q2, q3 @ d20 = t18a, d27 = t29a
1227 mbutterfly d28, d19, d1[2], d1[3], q2, q3 @ d28 = t19a, d19 = t28a
1228 mbutterfly d18, d29, d2[0], d2[1], q2, q3 @ d18 = t20a, d29 = t27a
1229 mbutterfly d26, d21, d2[2], d2[3], q2, q3 @ d26 = t21a, d21 = t26a
1230 mbutterfly d22, d25, d3[0], d3[1], q2, q3 @ d22 = t22a, d25 = t25a
1231 mbutterfly d30, d17, d3[2], d3[3], q2, q3 @ d30 = t23a, d17 = t24a
1232
1233 sub r12, r12, #32
1234 vld1.16 {q0}, [r12,:128]
1235
1236 butterfly d4, d24, d16, d24 @ d4 = t16, d24 = t17
1237 butterfly d5, d20, d28, d20 @ d5 = t19, d20 = t18
1238 butterfly d6, d26, d18, d26 @ d6 = t20, d26 = t21
1239 butterfly d7, d22, d30, d22 @ d7 = t23, d22 = t22
1240 butterfly d28, d25, d17, d25 @ d28 = t24, d25 = t25
1241 butterfly d30, d21, d29, d21 @ d30 = t27, d21 = t26
1242 butterfly d29, d23, d31, d23 @ d29 = t31, d23 = t30
1243 butterfly d31, d27, d19, d27 @ d31 = t28, d27 = t29
1244
1245 mbutterfly d23, d24, d0[3], d1[0], q8, q9 @ d23 = t17a, d24 = t30a
1246 mbutterfly d27, d20, d0[3], d1[0], q8, q9, neg=1 @ d27 = t29a, d20 = t18a
1247 mbutterfly d21, d26, d1[1], d1[2], q8, q9 @ d21 = t21a, d26 = t26a
1248 mbutterfly d25, d22, d1[1], d1[2], q8, q9, neg=1 @ d25 = t25a, d22 = t22a
1249 idct32_end
1250 endfunc
1251
1252 function idct32_odd_half
1253 movrel r12, idct_coeffs
1254 add r12, r12, #32
1255 vld1.16 {q0-q1}, [r12,:128]
1256
1257 mbutterfly_h1 d16, d31, d0[0], d0[1], q2, q3 @ d16 = t16a, d31 = t31a
1258 mbutterfly_h2 d24, d23, d0[2], d0[3], q2, q3 @ d24 = t17a, d23 = t30a
1259 mbutterfly_h1 d20, d27, d1[0], d1[1], q2, q3 @ d20 = t18a, d27 = t29a
1260 mbutterfly_h2 d28, d19, d1[2], d1[3], q2, q3 @ d28 = t19a, d19 = t28a
1261 mbutterfly_h1 d18, d29, d2[0], d2[1], q2, q3 @ d18 = t20a, d29 = t27a
1262 mbutterfly_h2 d26, d21, d2[2], d2[3], q2, q3 @ d26 = t21a, d21 = t26a
1263 mbutterfly_h1 d22, d25, d3[0], d3[1], q2, q3 @ d22 = t22a, d25 = t25a
1264 mbutterfly_h2 d30, d17, d3[2], d3[3], q2, q3 @ d30 = t23a, d17 = t24a
1265
1266 sub r12, r12, #32
1267 vld1.16 {q0}, [r12,:128]
1268
1269 butterfly d4, d24, d16, d24 @ d4 = t16, d24 = t17
1270 butterfly d5, d20, d28, d20 @ d5 = t19, d20 = t18
1271 butterfly d6, d26, d18, d26 @ d6 = t20, d26 = t21
1272 butterfly d7, d22, d30, d22 @ d7 = t23, d22 = t22
1273 butterfly d28, d25, d17, d25 @ d28 = t24, d25 = t25
1274 butterfly d30, d21, d29, d21 @ d30 = t27, d21 = t26
1275 butterfly d29, d23, d31, d23 @ d29 = t31, d23 = t30
1276 butterfly d31, d27, d19, d27 @ d31 = t28, d27 = t29
1277
1278 mbutterfly d23, d24, d0[3], d1[0], q8, q9 @ d23 = t17a, d24 = t30a
1279 mbutterfly d27, d20, d0[3], d1[0], q8, q9, neg=1 @ d27 = t29a, d20 = t18a
1280 mbutterfly d21, d26, d1[1], d1[2], q8, q9 @ d21 = t21a, d26 = t26a
1281 mbutterfly d25, d22, d1[1], d1[2], q8, q9, neg=1 @ d25 = t25a, d22 = t22a
1282
1283 idct32_end
1284 endfunc
1285
1286 function idct32_odd_quarter
1287 movrel r12, idct_coeffs
1288 add r12, r12, #32
1289 vld1.16 {q0-q1}, [r12,:128]
1290
1291 vmull.s16 q2, d16, d0[0]
1292 vmull.s16 q14, d19, d1[3]
1293 vmull.s16 q15, d16, d0[1]
1294 vmull.s16 q11, d17, d3[2]
1295 vmull.s16 q3, d17, d3[3]
1296 vmull.s16 q13, d19, d1[2]
1297 vmull.s16 q10, d18, d2[0]
1298 vmull.s16 q12, d18, d2[1]
1299
1300 sub r12, r12, #32
1301 vld1.16 {q0}, [r12,:128]
1302
1303 vneg.s32 q14, q14
1304 vneg.s32 q3, q3
1305
1306 vrshrn.s32 d4, q2, #14
1307 vrshrn.s32 d5, q14, #14
1308 vrshrn.s32 d29, q15, #14
1309 vrshrn.s32 d28, q11, #14
1310 vrshrn.s32 d7, q3, #14
1311 vrshrn.s32 d31, q13, #14
1312 vrshrn.s32 d6, q10, #14
1313 vrshrn.s32 d30, q12, #14
1314
1315 mbutterfly_l q8, q9, d29, d4, d0[3], d1[0]
1316 mbutterfly_l q13, q10, d31, d5, d0[3], d1[0]
1317 vrshrn.s32 d23, q8, #14
1318 vrshrn.s32 d24, q9, #14
1319 vneg.s32 q10, q10
1320 vrshrn.s32 d27, q13, #14
1321 vrshrn.s32 d20, q10, #14
1322 mbutterfly_l q8, q9, d30, d6, d1[1], d1[2]
1323 vrshrn.s32 d21, q8, #14
1324 vrshrn.s32 d26, q9, #14
1325 mbutterfly_l q8, q9, d28, d7, d1[1], d1[2]
1326 vrshrn.s32 d25, q8, #14
1327 vneg.s32 q9, q9
1328 vrshrn.s32 d22, q9, #14
1329
1330 idct32_end
1331 endfunc
1332
1333 .macro idct32_funcs suffix
1334 @ Do an 32-point IDCT of a 4x32 slice out of a 32x32 matrix.
1335 @ We don't have register space to do a single pass IDCT of 4x32 though,
1336 @ but the 32-point IDCT can be decomposed into two 16-point IDCTs;
1337 @ a normal IDCT16 with every other input component (the even ones, with
1338 @ each output written twice), followed by a separate 16-point IDCT
1339 @ of the odd inputs, added/subtracted onto the outputs of the first idct16.
1340 @ r0 = dst (temp buffer)
1341 @ r1 = unused
1342 @ r2 = src
1343 function idct32_1d_4x32_pass1\suffix\()_neon
1344 push {lr}
1345
1346 movrel r12, idct_coeffs
1347 vld1.16 {q0-q1}, [r12,:128]
1348
1349 @ Double stride of the input, since we only read every other line
1350 mov r12, #128
1351 vmov.s16 d4, #0
1352
1353 @ d16 = IN(0), d17 = IN(2) ... d31 = IN(30)
1354 .ifb \suffix
1355 .irp i, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31
1356 vld1.16 {d\i}, [r2,:64]
1357 vst1.16 {d4}, [r2,:64], r12
1358 .endr
1359 .endif
1360 .ifc \suffix,_quarter
1361 .irp i, 16, 17, 18, 19
1362 vld1.16 {d\i}, [r2,:64]
1363 vst1.16 {d4}, [r2,:64], r12
1364 .endr
1365 .endif
1366 .ifc \suffix,_half
1367 .irp i, 16, 17, 18, 19, 20, 21, 22, 23
1368 vld1.16 {d\i}, [r2,:64]
1369 vst1.16 {d4}, [r2,:64], r12
1370 .endr
1371 .endif
1372
1373 bl idct16\suffix
1374
1375 @ Do four 4x4 transposes. Originally, d16-d31 contain the
1376 @ 16 rows. Afterwards, d16-d19, d20-d23, d24-d27, d28-d31
1377 @ contain the transposed 4x4 blocks.
1378 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
1379 @ Store the registers a, b, c, d horizontally, followed
1380 @ by the same registers d, c, b, a mirrored.
1381 .macro store_rev a, b, c, d
1382 .irp i, \a, \b, \c, \d
1383 vst1.16 {d\i}, [r0,:64]!
1384 vrev64.16 d\i, d\i
1385 .endr
1386 .irp i, \d, \c, \b, \a
1387 vst1.16 {d\i}, [r0,:64]!
1388 .endr
1389 .endm
1390 store_rev 16, 20, 24, 28
1391 store_rev 17, 21, 25, 29
1392 store_rev 18, 22, 26, 30
1393 store_rev 19, 23, 27, 31
1394 sub r0, r0, #256
1395 .purgem store_rev
1396
1397 @ Move r2 back to the start of the input, and move
1398 @ to the first odd row
1399 .ifb \suffix
1400 sub r2, r2, r12, lsl #4
1401 .endif
1402 .ifc \suffix,_quarter
1403 sub r2, r2, r12, lsl #2
1404 .endif
1405 .ifc \suffix,_half
1406 sub r2, r2, r12, lsl #3
1407 .endif
1408 add r2, r2, #64
1409
1410 vmov.s16 d4, #0
1411 @ d16 = IN(1), d17 = IN(3) ... d31 = IN(31)
1412 .ifb \suffix
1413 .irp i, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31
1414 vld1.16 {d\i}, [r2,:64]
1415 vst1.16 {d4}, [r2,:64], r12
1416 .endr
1417 .endif
1418 .ifc \suffix,_quarter
1419 .irp i, 16, 17, 18, 19
1420 vld1.16 {d\i}, [r2,:64]
1421 vst1.16 {d4}, [r2,:64], r12
1422 .endr
1423 .endif
1424 .ifc \suffix,_half
1425 .irp i, 16, 17, 18, 19, 20, 21, 22, 23
1426 vld1.16 {d\i}, [r2,:64]
1427 vst1.16 {d4}, [r2,:64], r12
1428 .endr
1429 .endif
1430
1431 bl idct32_odd\suffix
1432
1433 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
1434
1435 @ Store the registers a, b, c, d horizontally,
1436 @ adding into the output first, and then mirrored, subtracted
1437 @ from the output.
1438 .macro store_rev a, b, c, d
1439 .irp i, \a, \b, \c, \d
1440 vld1.16 {d4}, [r0,:64]
1441 vadd.s16 d4, d4, d\i
1442 vst1.16 {d4}, [r0,:64]!
1443 vrev64.16 d\i, d\i
1444 .endr
1445 .irp i, \d, \c, \b, \a
1446 vld1.16 {d4}, [r0,:64]
1447 vsub.s16 d4, d4, d\i
1448 vst1.16 {d4}, [r0,:64]!
1449 .endr
1450 .endm
1451
1452 store_rev 31, 27, 23, 19
1453 store_rev 30, 26, 22, 18
1454 store_rev 29, 25, 21, 17
1455 store_rev 28, 24, 20, 16
1456 .purgem store_rev
1457 pop {pc}
1458 endfunc
1459 .ltorg
1460
1461 @ This is mostly the same as 4x32_pass1, but without the transpose,
1462 @ and use the source as temp buffer between the two idct passes, and
1463 @ add into the destination.
1464 @ r0 = dst
1465 @ r1 = dst stride
1466 @ r2 = src (temp buffer)
1467 function idct32_1d_4x32_pass2\suffix\()_neon
1468 push {lr}
1469 movrel r12, idct_coeffs
1470 vld1.16 {q0-q1}, [r12,:128]
1471
1472 mov r12, #128
1473 @ d16 = IN(0), d17 = IN(2) ... d31 = IN(30)
1474 .ifb \suffix
1475 .irp i, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31
1476 vld1.16 {d\i}, [r2,:64], r12
1477 .endr
1478 sub r2, r2, r12, lsl #4
1479 .endif
1480 .ifc \suffix,_quarter
1481 .irp i, 16, 17, 18, 19
1482 vld1.16 {d\i}, [r2,:64], r12
1483 .endr
1484 sub r2, r2, r12, lsl #2
1485 .endif
1486 .ifc \suffix,_half
1487 .irp i, 16, 17, 18, 19, 20, 21, 22, 23
1488 vld1.16 {d\i}, [r2,:64], r12
1489 .endr
1490 sub r2, r2, r12, lsl #3
1491 .endif
1492
1493 bl idct16\suffix
1494
1495 .irp i, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31
1496 vst1.16 {d\i}, [r2,:64], r12
1497 .endr
1498
1499 sub r2, r2, r12, lsl #4
1500 add r2, r2, #64
1501
1502 @ d16 = IN(1), d17 = IN(3) ... d31 = IN(31)
1503 .ifb \suffix
1504 .irp i, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31
1505 vld1.16 {d\i}, [r2,:64], r12
1506 .endr
1507 sub r2, r2, r12, lsl #4
1508 .endif
1509 .ifc \suffix,_quarter
1510 .irp i, 16, 17, 18, 19
1511 vld1.16 {d\i}, [r2,:64], r12
1512 .endr
1513 sub r2, r2, r12, lsl #2
1514 .endif
1515 .ifc \suffix,_half
1516 .irp i, 16, 17, 18, 19, 20, 21, 22, 23
1517 vld1.16 {d\i}, [r2,:64], r12
1518 .endr
1519 sub r2, r2, r12, lsl #3
1520 .endif
1521 sub r2, r2, #64
1522
1523 bl idct32_odd\suffix
1524
1525 mov r12, #128
1526 .macro load_acc_store a, b, c, d, neg=0
1527 vld1.16 {d4}, [r2,:64], r12
1528 vld1.16 {d5}, [r2,:64], r12
1529 .if \neg == 0
1530 vadd.s16 d4, d4, d\a
1531 vld1.16 {d6}, [r2,:64], r12
1532 vadd.s16 d5, d5, d\b
1533 vld1.16 {d7}, [r2,:64], r12
1534 vadd.s16 d6, d6, d\c
1535 vadd.s16 d7, d7, d\d
1536 .else
1537 vsub.s16 d4, d4, d\a
1538 vld1.16 {d6}, [r2,:64], r12
1539 vsub.s16 d5, d5, d\b
1540 vld1.16 {d7}, [r2,:64], r12
1541 vsub.s16 d6, d6, d\c
1542 vsub.s16 d7, d7, d\d
1543 .endif
1544 vld1.32 {d2[]}, [r0,:32], r1
1545 vld1.32 {d2[1]}, [r0,:32], r1
1546 vrshr.s16 q2, q2, #6
1547 vld1.32 {d3[]}, [r0,:32], r1
1548 vrshr.s16 q3, q3, #6
1549 vld1.32 {d3[1]}, [r0,:32], r1
1550 sub r0, r0, r1, lsl #2
1551 vaddw.u8 q2, q2, d2
1552 vaddw.u8 q3, q3, d3
1553 vqmovun.s16 d4, q2
1554 vqmovun.s16 d5, q3
1555 vst1.32 {d4[0]}, [r0,:32], r1
1556 vst1.32 {d4[1]}, [r0,:32], r1
1557 vst1.32 {d5[0]}, [r0,:32], r1
1558 vst1.32 {d5[1]}, [r0,:32], r1
1559 .endm
1560 load_acc_store 31, 30, 29, 28
1561 load_acc_store 27, 26, 25, 24
1562 load_acc_store 23, 22, 21, 20
1563 load_acc_store 19, 18, 17, 16
1564 sub r2, r2, r12
1565 neg r12, r12
1566 load_acc_store 16, 17, 18, 19, 1
1567 load_acc_store 20, 21, 22, 23, 1
1568 load_acc_store 24, 25, 26, 27, 1
1569 load_acc_store 28, 29, 30, 31, 1
1570 .purgem load_acc_store
1571 pop {pc}
1572 endfunc
1573 .endm
1574
1575 idct32_funcs
1576 idct32_funcs _quarter
1577 idct32_funcs _half
1578
1579 const min_eob_idct_idct_32, align=4
1580 .short 0, 9, 34, 70, 135, 240, 336, 448
1581 endconst
1582
1583 function ff_vp9_idct_idct_32x32_add_neon, export=1
1584 cmp r3, #1
1585 beq idct32x32_dc_add_neon
1586 push {r4-r8,lr}
1587 vpush {q4-q7}
1588 movrel r8, min_eob_idct_idct_32 + 2
1589
1590 @ Align the stack, allocate a temp buffer
1591 T mov r7, sp
1592 T and r7, r7, #15
1593 A and r7, sp, #15
1594 add r7, r7, #2048
1595 sub sp, sp, r7
1596
1597 mov r4, r0
1598 mov r5, r1
1599 mov r6, r2
1600
1601 cmp r3, #34
1602 ble idct32x32_quarter_add_neon
1603 cmp r3, #135
1604 ble idct32x32_half_add_neon
1605
1606 .irp i, 0, 4, 8, 12, 16, 20, 24, 28
1607 add r0, sp, #(\i*64)
1608 .if \i > 0
1609 ldrh_post r1, r8, #2
1610 cmp r3, r1
1611 it le
1612 movle r1, #(32 - \i)/2
1613 ble 1f
1614 .endif
1615 add r2, r6, #(\i*2)
1616 bl idct32_1d_4x32_pass1_neon
1617 .endr
1618 b 3f
1619
1620 1:
1621 @ Write zeros to the temp buffer for pass 2
1622 vmov.i16 q14, #0
1623 vmov.i16 q15, #0
1624 2:
1625 subs r1, r1, #1
1626 .rept 4
1627 vst1.16 {q14-q15}, [r0,:128]!
1628 .endr
1629 bne 2b
1630 3:
1631 .irp i, 0, 4, 8, 12, 16, 20, 24, 28
1632 add r0, r4, #(\i)
1633 mov r1, r5
1634 add r2, sp, #(\i*2)
1635 bl idct32_1d_4x32_pass2_neon
1636 .endr
1637
1638 add sp, sp, r7
1639 vpop {q4-q7}
1640 pop {r4-r8,pc}
1641 endfunc
1642
1643 function idct32x32_quarter_add_neon
1644 .irp i, 0, 4
1645 add r0, sp, #(\i*64)
1646 .if \i == 4
1647 cmp r3, #9
1648 ble 1f
1649 .endif
1650 add r2, r6, #(\i*2)
1651 bl idct32_1d_4x32_pass1_quarter_neon
1652 .endr
1653 b 3f
1654
1655 1:
1656 @ Write zeros to the temp buffer for pass 2
1657 vmov.i16 q14, #0
1658 vmov.i16 q15, #0
1659 .rept 8
1660 vst1.16 {q14-q15}, [r0,:128]!
1661 .endr
1662 3:
1663 .irp i, 0, 4, 8, 12, 16, 20, 24, 28
1664 add r0, r4, #(\i)
1665 mov r1, r5
1666 add r2, sp, #(\i*2)
1667 bl idct32_1d_4x32_pass2_quarter_neon
1668 .endr
1669
1670 add sp, sp, r7
1671 vpop {q4-q7}
1672 pop {r4-r8,pc}
1673 endfunc
1674
1675 function idct32x32_half_add_neon
1676 .irp i, 0, 4, 8, 12
1677 add r0, sp, #(\i*64)
1678 .if \i > 0
1679 ldrh_post r1, r8, #2
1680 cmp r3, r1
1681 it le
1682 movle r1, #(16 - \i)/2
1683 ble 1f
1684 .endif
1685 add r2, r6, #(\i*2)
1686 bl idct32_1d_4x32_pass1_half_neon
1687 .endr
1688 b 3f
1689
1690 1:
1691 @ Write zeros to the temp buffer for pass 2
1692 vmov.i16 q14, #0
1693 vmov.i16 q15, #0
1694 2:
1695 subs r1, r1, #1
1696 .rept 4
1697 vst1.16 {q14-q15}, [r0,:128]!
1698 .endr
1699 bne 2b
1700 3:
1701 .irp i, 0, 4, 8, 12, 16, 20, 24, 28
1702 add r0, r4, #(\i)
1703 mov r1, r5
1704 add r2, sp, #(\i*2)
1705 bl idct32_1d_4x32_pass2_half_neon
1706 .endr
1707
1708 add sp, sp, r7
1709 vpop {q4-q7}
1710 pop {r4-r8,pc}
1711 endfunc