Commit | Line | Data |
---|---|---|
a67ae670 MS |
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 | @ out1,out2 = ((in1 + in2) * d0[0] + (1 << 13)) >> 14 | |
78 | @ out3,out4 = ((in1 - in2) * d0[0] + (1 << 13)) >> 14 | |
79 | @ Same as mbutterfly0, but with input being 2 q registers, output | |
80 | @ being 4 d registers. | |
81 | @ This can do with either 4 or 6 temporary q registers. | |
82 | .macro dmbutterfly0 out1, out2, out3, out4, in1, in2, tmpq1, tmpq2, tmpd11, tmpd12, tmpd21, tmpd22, tmpq3, tmpq4, tmpq5, tmpq6 | |
83 | vadd.s16 \tmpq1, \in1, \in2 | |
84 | vsub.s16 \tmpq2, \in1, \in2 | |
85 | vmull.s16 \tmpq3, \tmpd11, d0[0] | |
86 | vmull.s16 \tmpq4, \tmpd12, d0[0] | |
87 | .ifb \tmpq5 | |
88 | vrshrn.s32 \out1, \tmpq3, #14 | |
89 | vrshrn.s32 \out2, \tmpq4, #14 | |
90 | vmull.s16 \tmpq3, \tmpd21, d0[0] | |
91 | vmull.s16 \tmpq4, \tmpd22, d0[0] | |
92 | vrshrn.s32 \out3, \tmpq3, #14 | |
93 | vrshrn.s32 \out4, \tmpq4, #14 | |
94 | .else | |
95 | vmull.s16 \tmpq5, \tmpd21, d0[0] | |
96 | vmull.s16 \tmpq6, \tmpd22, d0[0] | |
97 | vrshrn.s32 \out1, \tmpq3, #14 | |
98 | vrshrn.s32 \out2, \tmpq4, #14 | |
99 | vrshrn.s32 \out3, \tmpq5, #14 | |
100 | vrshrn.s32 \out4, \tmpq6, #14 | |
101 | .endif | |
102 | .endm | |
103 | ||
104 | @ out1 = in1 * coef1 - in2 * coef2 | |
105 | @ out2 = in1 * coef2 + in2 * coef1 | |
106 | @ out are 2 q registers, in are 2 d registers | |
107 | .macro mbutterfly_l out1, out2, in1, in2, coef1, coef2 | |
108 | vmull.s16 \out1, \in1, \coef1 | |
109 | vmlsl.s16 \out1, \in2, \coef2 | |
110 | vmull.s16 \out2, \in1, \coef2 | |
111 | vmlal.s16 \out2, \in2, \coef1 | |
112 | .endm | |
113 | ||
114 | @ out1,out2 = in1,in2 * coef1 - in3,in4 * coef2 | |
115 | @ out3,out4 = in1,in2 * coef2 + in3,in4 * coef1 | |
116 | @ out are 4 q registers, in are 4 d registers | |
117 | .macro dmbutterfly_l out1, out2, out3, out4, in1, in2, in3, in4, coef1, coef2 | |
118 | vmull.s16 \out1, \in1, \coef1 | |
119 | vmull.s16 \out2, \in2, \coef1 | |
120 | vmull.s16 \out3, \in1, \coef2 | |
121 | vmull.s16 \out4, \in2, \coef2 | |
122 | vmlsl.s16 \out1, \in3, \coef2 | |
123 | vmlsl.s16 \out2, \in4, \coef2 | |
124 | vmlal.s16 \out3, \in3, \coef1 | |
125 | vmlal.s16 \out4, \in4, \coef1 | |
126 | .endm | |
127 | ||
79566ec8 MS |
128 | @ inout1 = (inout1 * coef1 - inout2 * coef2 + (1 << 13)) >> 14 |
129 | @ inout2 = (inout1 * coef2 + inout2 * coef1 + (1 << 13)) >> 14 | |
130 | @ inout are 2 d registers, tmp are 2 q registers | |
131 | .macro mbutterfly inout1, inout2, coef1, coef2, tmp1, tmp2, neg=0 | |
132 | mbutterfly_l \tmp1, \tmp2, \inout1, \inout2, \coef1, \coef2 | |
a67ae670 MS |
133 | .if \neg > 0 |
134 | vneg.s32 \tmp2, \tmp2 | |
135 | .endif | |
79566ec8 MS |
136 | vrshrn.s32 \inout1, \tmp1, #14 |
137 | vrshrn.s32 \inout2, \tmp2, #14 | |
a67ae670 MS |
138 | .endm |
139 | ||
140 | @ inout1,inout2 = (inout1,inout2 * coef1 - inout3,inout4 * coef2 + (1 << 13)) >> 14 | |
141 | @ inout3,inout4 = (inout1,inout2 * coef2 + inout3,inout4 * coef1 + (1 << 13)) >> 14 | |
142 | @ inout are 4 d registers, tmp are 4 q registers | |
143 | .macro dmbutterfly inout1, inout2, inout3, inout4, coef1, coef2, tmp1, tmp2, tmp3, tmp4 | |
144 | dmbutterfly_l \tmp1, \tmp2, \tmp3, \tmp4, \inout1, \inout2, \inout3, \inout4, \coef1, \coef2 | |
145 | vrshrn.s32 \inout1, \tmp1, #14 | |
146 | vrshrn.s32 \inout2, \tmp2, #14 | |
147 | vrshrn.s32 \inout3, \tmp3, #14 | |
148 | vrshrn.s32 \inout4, \tmp4, #14 | |
149 | .endm | |
150 | ||
151 | @ out1 = in1 + in2 | |
152 | @ out2 = in1 - in2 | |
153 | .macro butterfly out1, out2, in1, in2 | |
154 | vadd.s16 \out1, \in1, \in2 | |
155 | vsub.s16 \out2, \in1, \in2 | |
156 | .endm | |
157 | ||
158 | @ out1 = in1 - in2 | |
159 | @ out2 = in1 + in2 | |
160 | .macro butterfly_r out1, out2, in1, in2 | |
161 | vsub.s16 \out1, \in1, \in2 | |
162 | vadd.s16 \out2, \in1, \in2 | |
163 | .endm | |
164 | ||
165 | @ out1 = (in1 + in2 + (1 << 13)) >> 14 | |
166 | @ out2 = (in1 - in2 + (1 << 13)) >> 14 | |
167 | @ out are 2 d registers, in are 2 q registers, tmp are 2 q registers | |
168 | .macro butterfly_n out1, out2, in1, in2, tmp1, tmp2 | |
169 | vadd.s32 \tmp1, \in1, \in2 | |
170 | vsub.s32 \tmp2, \in1, \in2 | |
171 | vrshrn.s32 \out1, \tmp1, #14 | |
172 | vrshrn.s32 \out2, \tmp2, #14 | |
173 | .endm | |
174 | ||
175 | @ out1,out2 = (in1,in2 + in3,in4 + (1 << 13)) >> 14 | |
176 | @ out3,out4 = (in1,in2 - in3,in4 + (1 << 13)) >> 14 | |
177 | @ out are 4 d registers, in are 4 q registers, tmp are 4 q registers | |
178 | .macro dbutterfly_n out1, out2, out3, out4, in1, in2, in3, in4, tmp1, tmp2, tmp3, tmp4 | |
179 | vadd.s32 \tmp1, \in1, \in3 | |
180 | vadd.s32 \tmp2, \in2, \in4 | |
181 | vsub.s32 \tmp3, \in1, \in3 | |
182 | vsub.s32 \tmp4, \in2, \in4 | |
183 | vrshrn.s32 \out1, \tmp1, #14 | |
184 | vrshrn.s32 \out2, \tmp2, #14 | |
185 | vrshrn.s32 \out3, \tmp3, #14 | |
186 | vrshrn.s32 \out4, \tmp4, #14 | |
187 | .endm | |
188 | ||
189 | ||
190 | .macro iwht4 c0, c1, c2, c3 | |
191 | vadd.i16 \c0, \c0, \c1 | |
192 | vsub.i16 d17, \c2, \c3 | |
193 | vsub.i16 d16, \c0, d17 | |
194 | vshr.s16 d16, d16, #1 | |
195 | vsub.i16 \c2, d16, \c1 | |
196 | vsub.i16 \c1, d16, \c3 | |
197 | vadd.i16 \c3, d17, \c2 | |
198 | vsub.i16 \c0, \c0, \c1 | |
199 | .endm | |
200 | ||
201 | .macro idct4 c0, c1, c2, c3 | |
202 | vmull.s16 q13, \c1, d0[2] | |
203 | vmull.s16 q11, \c1, d0[1] | |
204 | vadd.i16 d16, \c0, \c2 | |
205 | vsub.i16 d17, \c0, \c2 | |
206 | vmlal.s16 q13, \c3, d0[1] | |
207 | vmull.s16 q9, d16, d0[0] | |
208 | vmull.s16 q10, d17, d0[0] | |
209 | vmlsl.s16 q11, \c3, d0[2] | |
210 | vrshrn.s32 d26, q13, #14 | |
211 | vrshrn.s32 d18, q9, #14 | |
212 | vrshrn.s32 d20, q10, #14 | |
213 | vrshrn.s32 d22, q11, #14 | |
214 | vadd.i16 \c0, d18, d26 | |
215 | vsub.i16 \c3, d18, d26 | |
216 | vadd.i16 \c1, d20, d22 | |
217 | vsub.i16 \c2, d20, d22 | |
218 | .endm | |
219 | ||
220 | .macro iadst4 c0, c1, c2, c3 | |
221 | vmull.s16 q10, \c0, d1[0] | |
222 | vmlal.s16 q10, \c2, d1[1] | |
223 | vmlal.s16 q10, \c3, d1[2] | |
224 | vmull.s16 q11, \c0, d1[2] | |
225 | vmlsl.s16 q11, \c2, d1[0] | |
226 | vsub.s16 \c0, \c0, \c2 | |
227 | vmlsl.s16 q11, \c3, d1[1] | |
228 | vadd.s16 \c0, \c0, \c3 | |
229 | vmull.s16 q13, \c1, d1[3] | |
230 | vmull.s16 q12, \c0, d1[3] | |
231 | vadd.s32 q14, q10, q13 | |
232 | vadd.s32 q1, q11, q13 | |
233 | vrshrn.s32 \c0, q14, #14 | |
234 | vadd.s32 q10, q10, q11 | |
235 | vrshrn.s32 \c1, q1, #14 | |
236 | vsub.s32 q10, q10, q13 | |
237 | vrshrn.s32 \c2, q12, #14 | |
238 | vrshrn.s32 \c3, q10, #14 | |
239 | .endm | |
240 | ||
241 | @ The public functions in this file have got the following signature: | |
242 | @ void itxfm_add(uint8_t *dst, ptrdiff_t stride, int16_t *block, int eob); | |
243 | ||
244 | .macro itxfm_func4x4 txfm1, txfm2 | |
245 | function ff_vp9_\txfm1\()_\txfm2\()_4x4_add_neon, export=1 | |
246 | .ifc \txfm1,\txfm2 | |
247 | .ifc \txfm1,idct | |
248 | movrel r12, itxfm4_coeffs | |
249 | vld1.16 {d0}, [r12,:64] | |
250 | .endif | |
251 | .ifc \txfm1,iadst | |
252 | movrel r12, iadst4_coeffs | |
253 | vld1.16 {d1}, [r12,:64] | |
254 | .endif | |
255 | .else | |
256 | movrel r12, itxfm4_coeffs | |
257 | vld1.16 {q0}, [r12,:128] | |
258 | .endif | |
259 | ||
260 | vmov.i16 q15, #0 | |
52d196fb | 261 | .ifc \txfm1\()_\txfm2,idct_idct |
a67ae670 MS |
262 | cmp r3, #1 |
263 | bne 1f | |
264 | @ DC-only for idct/idct | |
265 | vld1.16 {d4[]}, [r2,:16] | |
266 | vmull.s16 q2, d4, d0[0] | |
267 | vrshrn.s32 d4, q2, #14 | |
268 | vmull.s16 q2, d4, d0[0] | |
269 | vrshrn.s32 d4, q2, #14 | |
270 | vst1.16 {d30[0]}, [r2,:16] | |
271 | vdup.16 q2, d4[0] | |
272 | vmov q3, q2 | |
273 | b 2f | |
274 | .endif | |
a67ae670 MS |
275 | |
276 | 1: | |
277 | vld1.16 {d4-d7}, [r2,:128] | |
278 | vst1.16 {q15}, [r2,:128]! | |
279 | ||
280 | .ifc \txfm1,iwht | |
281 | vshr.s16 q2, q2, #2 | |
282 | vshr.s16 q3, q3, #2 | |
283 | .endif | |
284 | ||
285 | \txfm1\()4 d4, d5, d6, d7 | |
286 | ||
287 | vst1.16 {q15}, [r2,:128]! | |
288 | @ Transpose 4x4 with 16 bit elements | |
289 | vtrn.16 d4, d5 | |
290 | vtrn.16 d6, d7 | |
291 | vtrn.32 q2, q3 | |
292 | ||
293 | \txfm2\()4 d4, d5, d6, d7 | |
294 | 2: | |
295 | vld1.32 {d0[]}, [r0,:32], r1 | |
296 | vld1.32 {d0[1]}, [r0,:32], r1 | |
297 | .ifnc \txfm1,iwht | |
298 | vrshr.s16 q2, q2, #4 | |
299 | vrshr.s16 q3, q3, #4 | |
300 | .endif | |
301 | vaddw.u8 q2, q2, d0 | |
302 | vld1.32 {d1[]}, [r0,:32], r1 | |
303 | vld1.32 {d1[1]}, [r0,:32], r1 | |
304 | vqmovun.s16 d0, q2 | |
305 | sub r0, r0, r1, lsl #2 | |
306 | ||
307 | vaddw.u8 q3, q3, d1 | |
308 | vst1.32 {d0[0]}, [r0,:32], r1 | |
309 | vqmovun.s16 d1, q3 | |
310 | ||
311 | vst1.32 {d0[1]}, [r0,:32], r1 | |
312 | vst1.32 {d1[0]}, [r0,:32], r1 | |
313 | vst1.32 {d1[1]}, [r0,:32], r1 | |
314 | ||
315 | bx lr | |
316 | endfunc | |
317 | .endm | |
318 | ||
319 | itxfm_func4x4 idct, idct | |
320 | itxfm_func4x4 iadst, idct | |
321 | itxfm_func4x4 idct, iadst | |
322 | itxfm_func4x4 iadst, iadst | |
323 | itxfm_func4x4 iwht, iwht | |
324 | ||
325 | ||
326 | .macro idct8 | |
327 | dmbutterfly0 d16, d17, d24, d25, q8, q12, q2, q4, d4, d5, d8, d9, q3, q2, q5, q4 @ q8 = t0a, q12 = t1a | |
328 | dmbutterfly d20, d21, d28, d29, d0[1], d0[2], q2, q3, q4, q5 @ q10 = t2a, q14 = t3a | |
329 | dmbutterfly d18, d19, d30, d31, d0[3], d1[0], q2, q3, q4, q5 @ q9 = t4a, q15 = t7a | |
330 | dmbutterfly d26, d27, d22, d23, d1[1], d1[2], q2, q3, q4, q5 @ q13 = t5a, q11 = t6a | |
331 | ||
332 | butterfly q2, q14, q8, q14 @ q2 = t0, q14 = t3 | |
333 | butterfly q3, q10, q12, q10 @ q3 = t1, q10 = t2 | |
334 | butterfly q4, q13, q9, q13 @ q4 = t4, q13 = t5a | |
335 | butterfly q5, q11, q15, q11 @ q5 = t7, q11 = t6a | |
336 | ||
337 | butterfly q8, q15, q2, q5 @ q8 = out[0], q15 = out[7] | |
338 | ||
339 | dmbutterfly0 d4, d5, d10, d11, q11, q13, q9, q13, d18, d19, d26, d27, q2, q5, q11, q12 @ q2 = t6, q5 = t5 | |
340 | ||
341 | butterfly q11, q12, q14, q4 @ q11 = out[3], q12 = out[4] | |
342 | butterfly q9, q14, q3, q2 @ q9 = out[1], q14 = out[6] | |
343 | butterfly_r q13, q10, q10, q5 @ q13 = out[5], q10 = out[2] | |
344 | .endm | |
345 | ||
346 | .macro iadst8 | |
347 | dmbutterfly_l q4, q5, q2, q3, d30, d31, d16, d17, d2[1], d2[0] @ q4,q5 = t1a, q2,q3 = t0a | |
348 | dmbutterfly_l q8, q15, q6, q7, d22, d23, d24, d25, d3[1], d3[0] @ q8,q15 = t5a, q6,q7 = t4a | |
349 | ||
350 | dbutterfly_n d22, d23, d4, d5, q2, q3, q6, q7, q11, q12, q2, q3 @ q11 = t0, q2 = t4 | |
351 | ||
352 | dbutterfly_n d24, d25, d6, d7, q4, q5, q8, q15, q12, q3, q6, q7 @ q12 = t1, q3 = t5 | |
353 | ||
354 | dmbutterfly_l q6, q7, q4, q5, d26, d27, d20, d21, d2[3], d2[2] @ q6,q7 = t3a, q4,q5 = t2a | |
355 | dmbutterfly_l q10, q13, q8, q15, d18, d19, d28, d29, d3[3], d3[2] @ q10,q13 = t7a, q8,q15 = t6a | |
356 | ||
357 | dbutterfly_n d18, d19, d8, d9, q4, q5, q8, q15, q9, q14, q4, q5 @ q9 = t2, q4 = t6 | |
358 | dbutterfly_n d16, d17, d12, d13, q6, q7, q10, q13, q8, q15, q6, q7 @ q8 = t3, q6 = t7 | |
359 | ||
360 | butterfly q15, q12, q12, q8 @ q15 = -out[7], q12 = t3 | |
361 | vneg.s16 q15, q15 @ q15 = out[7] | |
362 | butterfly q8, q9, q11, q9 @ q8 = out[0], q9 = t2 | |
363 | ||
364 | dmbutterfly_l q10, q11, q5, q7, d4, d5, d6, d7, d0[1], d0[2] @ q10,q11 = t5a, q5,q7 = t4a | |
365 | dmbutterfly_l q2, q3, q13, q14, d12, d13, d8, d9, d0[2], d0[1] @ q2,q3 = t6a, q13,q14 = t7a | |
366 | ||
367 | dbutterfly_n d28, d29, d8, d9, q10, q11, q13, q14, q4, q6, q10, q11 @ q14 = out[6], q4 = t7 | |
368 | ||
369 | dmbutterfly0 d22, d23, d24, d25, q9, q12, q6, q13, d12, d13, d26, d27, q9, q10 @ q11 = -out[3], q12 = out[4] | |
370 | vneg.s16 q11, q11 @ q11 = out[3] | |
371 | ||
372 | dbutterfly_n d18, d19, d4, d5, q5, q7, q2, q3, q9, q10, q2, q3 @ q9 = -out[1], q2 = t6 | |
373 | vneg.s16 q9, q9 @ q9 = out[1] | |
374 | ||
375 | dmbutterfly0 d20, d21, d26, d27, q2, q4, q3, q5, d6, d7, d10, d11, q6, q7 @ q10 = out[2], q13 = -out[5] | |
376 | vneg.s16 q13, q13 @ q13 = out[5] | |
377 | .endm | |
378 | ||
379 | ||
380 | .macro itxfm_func8x8 txfm1, txfm2 | |
381 | function ff_vp9_\txfm1\()_\txfm2\()_8x8_add_neon, export=1 | |
382 | @ Push q4-q7 if iadst is used, idct requires | |
383 | @ a few scratch registers less, so only push q4-q5 | |
384 | @ if only idct is involved. | |
385 | @ The iadst also uses a few coefficients from | |
386 | @ idct, so those always need to be loaded. | |
52d196fb MS |
387 | .ifc \txfm1\()_\txfm2,idct_idct |
388 | movrel r12, idct_coeffs | |
389 | vpush {q4-q5} | |
a67ae670 MS |
390 | vld1.16 {q0}, [r12,:128] |
391 | .else | |
a67ae670 MS |
392 | movrel r12, iadst8_coeffs |
393 | vld1.16 {q1}, [r12,:128]! | |
394 | vpush {q4-q7} | |
395 | vld1.16 {q0}, [r12,:128] | |
a67ae670 MS |
396 | .endif |
397 | ||
398 | vmov.i16 q2, #0 | |
399 | vmov.i16 q3, #0 | |
400 | ||
52d196fb | 401 | .ifc \txfm1\()_\txfm2,idct_idct |
a67ae670 MS |
402 | cmp r3, #1 |
403 | bne 1f | |
404 | @ DC-only for idct/idct | |
405 | vld1.16 {d16[]}, [r2,:16] | |
406 | vmull.s16 q8, d16, d0[0] | |
407 | vrshrn.s32 d16, q8, #14 | |
408 | vmull.s16 q8, d16, d0[0] | |
409 | vrshrn.s32 d16, q8, #14 | |
410 | vdup.16 q8, d16[0] | |
411 | vmov q9, q8 | |
412 | vmov q10, q8 | |
413 | vmov q11, q8 | |
414 | vmov q12, q8 | |
415 | vmov q13, q8 | |
416 | vmov q14, q8 | |
417 | vmov q15, q8 | |
418 | vst1.16 {d4[0]}, [r2,:16] | |
419 | b 2f | |
420 | .endif | |
a67ae670 MS |
421 | 1: |
422 | vld1.16 {q8-q9}, [r2,:128]! | |
423 | vld1.16 {q10-q11}, [r2,:128]! | |
424 | vld1.16 {q12-q13}, [r2,:128]! | |
425 | vld1.16 {q14-q15}, [r2,:128]! | |
426 | sub r2, r2, #128 | |
427 | vst1.16 {q2-q3}, [r2,:128]! | |
428 | vst1.16 {q2-q3}, [r2,:128]! | |
429 | vst1.16 {q2-q3}, [r2,:128]! | |
430 | vst1.16 {q2-q3}, [r2,:128]! | |
431 | ||
432 | \txfm1\()8 | |
433 | ||
434 | @ Transpose 8x8 with 16 bit elements | |
435 | vswp d17, d24 | |
436 | vswp d19, d26 | |
437 | vswp d21, d28 | |
438 | vswp d23, d30 | |
439 | transpose16_4x4 q8, q9, q10, q11, q12, q13, q14, q15 | |
440 | ||
441 | \txfm2\()8 | |
442 | 2: | |
443 | mov r3, r0 | |
444 | @ Add into the destination | |
445 | vld1.8 {d4}, [r0,:64], r1 | |
446 | vrshr.s16 q8, q8, #5 | |
447 | vld1.8 {d5}, [r0,:64], r1 | |
448 | vrshr.s16 q9, q9, #5 | |
449 | vld1.8 {d6}, [r0,:64], r1 | |
450 | vrshr.s16 q10, q10, #5 | |
451 | vaddw.u8 q8, q8, d4 | |
452 | vld1.8 {d7}, [r0,:64], r1 | |
453 | vrshr.s16 q11, q11, #5 | |
454 | vaddw.u8 q9, q9, d5 | |
455 | vld1.8 {d8}, [r0,:64], r1 | |
456 | vrshr.s16 q12, q12, #5 | |
457 | vaddw.u8 q10, q10, d6 | |
458 | vqmovun.s16 d4, q8 | |
459 | vld1.8 {d9}, [r0,:64], r1 | |
460 | vrshr.s16 q13, q13, #5 | |
461 | vaddw.u8 q11, q11, d7 | |
462 | vqmovun.s16 d5, q9 | |
463 | vld1.8 {d10}, [r0,:64], r1 | |
464 | vrshr.s16 q14, q14, #5 | |
465 | vaddw.u8 q12, q12, d8 | |
466 | vqmovun.s16 d6, q10 | |
467 | vld1.8 {d11}, [r0,:64], r1 | |
468 | vrshr.s16 q15, q15, #5 | |
469 | vaddw.u8 q13, q13, d9 | |
470 | vqmovun.s16 d7, q11 | |
471 | ||
472 | ||
473 | vst1.8 {d4}, [r3,:64], r1 | |
474 | vaddw.u8 q14, q14, d10 | |
475 | vst1.8 {d5}, [r3,:64], r1 | |
476 | vqmovun.s16 d8, q12 | |
477 | vst1.8 {d6}, [r3,:64], r1 | |
478 | vaddw.u8 q15, q15, d11 | |
479 | vst1.8 {d7}, [r3,:64], r1 | |
480 | vqmovun.s16 d9, q13 | |
481 | vst1.8 {d8}, [r3,:64], r1 | |
482 | vqmovun.s16 d10, q14 | |
483 | vst1.8 {d9}, [r3,:64], r1 | |
484 | vqmovun.s16 d11, q15 | |
485 | ||
486 | vst1.8 {d10}, [r3,:64], r1 | |
487 | vst1.8 {d11}, [r3,:64], r1 | |
488 | ||
52d196fb MS |
489 | .ifc \txfm1\()_\txfm2,idct_idct |
490 | vpop {q4-q5} | |
a67ae670 | 491 | .else |
a67ae670 | 492 | vpop {q4-q7} |
a67ae670 MS |
493 | .endif |
494 | bx lr | |
495 | endfunc | |
496 | .endm | |
497 | ||
498 | itxfm_func8x8 idct, idct | |
499 | itxfm_func8x8 iadst, idct | |
500 | .ltorg | |
501 | itxfm_func8x8 idct, iadst | |
502 | itxfm_func8x8 iadst, iadst | |
503 | ||
504 | ||
505 | function idct16x16_dc_add_neon | |
506 | movrel r12, idct_coeffs | |
507 | vld1.16 {d0}, [r12,:64] | |
508 | ||
509 | vmov.i16 q2, #0 | |
510 | ||
511 | vld1.16 {d16[]}, [r2,:16] | |
512 | vmull.s16 q8, d16, d0[0] | |
513 | vrshrn.s32 d16, q8, #14 | |
514 | vmull.s16 q8, d16, d0[0] | |
515 | vrshrn.s32 d16, q8, #14 | |
516 | vdup.16 q8, d16[0] | |
517 | vst1.16 {d4[0]}, [r2,:16] | |
518 | ||
519 | vrshr.s16 q8, q8, #6 | |
520 | ||
521 | mov r12, #16 | |
522 | 1: | |
523 | @ Loop to add the constant from q8 into all 16x16 outputs | |
524 | vld1.8 {q3}, [r0,:128] | |
525 | vaddw.u8 q10, q8, d6 | |
526 | vaddw.u8 q11, q8, d7 | |
527 | vqmovun.s16 d6, q10 | |
528 | vqmovun.s16 d7, q11 | |
529 | vst1.8 {q3}, [r0,:128], r1 | |
530 | subs r12, r12, #1 | |
531 | bne 1b | |
532 | ||
533 | bx lr | |
534 | endfunc | |
535 | .ltorg | |
536 | ||
537 | .macro idct16 | |
538 | mbutterfly0 d16, d24, d16, d24, d4, d6, q2, q3 @ d16 = t0a, d24 = t1a | |
539 | mbutterfly d20, d28, d0[1], d0[2], q2, q3 @ d20 = t2a, d28 = t3a | |
540 | mbutterfly d18, d30, d0[3], d1[0], q2, q3 @ d18 = t4a, d30 = t7a | |
541 | mbutterfly d26, d22, d1[1], d1[2], q2, q3 @ d26 = t5a, d22 = t6a | |
542 | mbutterfly d17, d31, d1[3], d2[0], q2, q3 @ d17 = t8a, d31 = t15a | |
543 | mbutterfly d25, d23, d2[1], d2[2], q2, q3 @ d25 = t9a, d23 = t14a | |
544 | mbutterfly d21, d27, d2[3], d3[0], q2, q3 @ d21 = t10a, d27 = t13a | |
545 | mbutterfly d29, d19, d3[1], d3[2], q2, q3 @ d29 = t11a, d19 = t12a | |
546 | ||
547 | butterfly d4, d28, d16, d28 @ d4 = t0, d28 = t3 | |
548 | butterfly d5, d20, d24, d20 @ d5 = t1, d20 = t2 | |
549 | butterfly d6, d26, d18, d26 @ d6 = t4, d26 = t5 | |
550 | butterfly d7, d22, d30, d22 @ d7 = t7, d22 = t6 | |
551 | butterfly d16, d25, d17, d25 @ d16 = t8, d25 = t9 | |
552 | butterfly d24, d21, d29, d21 @ d24 = t11, d21 = t10 | |
553 | butterfly d17, d27, d19, d27 @ d17 = t12, d27 = t13 | |
554 | butterfly d29, d23, d31, d23 @ d29 = t15, d23 = t14 | |
555 | ||
556 | mbutterfly0 d22, d26, d22, d26, d18, d30, q9, q15 @ d22 = t6a, d26 = t5a | |
557 | mbutterfly d23, d25, d0[1], d0[2], q9, q15 @ d23 = t9a, d25 = t14a | |
558 | mbutterfly d27, d21, d0[1], d0[2], q9, q15, neg=1 @ d27 = t13a, d21 = t10a | |
559 | ||
560 | butterfly d18, d7, d4, d7 @ d18 = t0a, d7 = t7a | |
561 | butterfly d19, d22, d5, d22 @ d19 = t1a, d22 = t6 | |
562 | butterfly d4, d26, d20, d26 @ d4 = t2a, d26 = t5 | |
563 | butterfly d5, d6, d28, d6 @ d5 = t3a, d6 = t4 | |
564 | butterfly d20, d28, d16, d24 @ d20 = t8a, d28 = t11a | |
565 | butterfly d24, d21, d23, d21 @ d24 = t9, d21 = t10 | |
566 | butterfly d23, d27, d25, d27 @ d23 = t14, d27 = t13 | |
567 | butterfly d25, d29, d29, d17 @ d25 = t15a, d29 = t12a | |
568 | ||
569 | mbutterfly0 d27, d21, d27, d21, d16, d30, q8, q15 @ d27 = t13a, d21 = t10a | |
570 | mbutterfly0 d29, d28, d29, d28, d16, d30, q8, q15 @ d29 = t12, d28 = t11 | |
571 | ||
572 | vswp d27, d29 @ d27 = t12, d29 = t13a | |
573 | vswp d28, d27 @ d28 = t12, d27 = t11 | |
574 | butterfly d16, d31, d18, d25 @ d16 = out[0], d31 = out[15] | |
575 | butterfly d17, d30, d19, d23 @ d17 = out[1], d30 = out[14] | |
576 | butterfly_r d25, d22, d22, d24 @ d25 = out[9], d22 = out[6] | |
577 | butterfly d23, d24, d7, d20 @ d23 = out[7], d24 = out[8] | |
578 | butterfly d18, d29, d4, d29 @ d18 = out[2], d29 = out[13] | |
579 | butterfly d19, d28, d5, d28 @ d19 = out[3], d28 = out[12] | |
580 | vmov d4, d21 @ d4 = t10a | |
581 | butterfly d20, d27, d6, d27 @ d20 = out[4], d27 = out[11] | |
582 | butterfly d21, d26, d26, d4 @ d21 = out[5], d26 = out[10] | |
583 | .endm | |
584 | ||
585 | .macro iadst16 | |
586 | movrel r12, iadst16_coeffs | |
587 | vld1.16 {q0-q1}, [r12,:128] | |
588 | ||
589 | mbutterfly_l q3, q2, d31, d16, d0[1], d0[0] @ q3 = t1, q2 = t0 | |
590 | mbutterfly_l q5, q4, d23, d24, d2[1], d2[0] @ q5 = t9, q4 = t8 | |
591 | butterfly_n d31, d24, q3, q5, q6, q5 @ d31 = t1a, d24 = t9a | |
592 | mbutterfly_l q7, q6, d29, d18, d0[3], d0[2] @ q7 = t3, q6 = t2 | |
593 | butterfly_n d16, d23, q2, q4, q3, q4 @ d16 = t0a, d23 = t8a | |
594 | ||
595 | mbutterfly_l q3, q2, d21, d26, d2[3], d2[2] @ q3 = t11, q2 = t10 | |
596 | butterfly_n d29, d26, q7, q3, q4, q3 @ d29 = t3a, d26 = t11a | |
597 | mbutterfly_l q5, q4, d27, d20, d1[1], d1[0] @ q5 = t5, q4 = t4 | |
598 | butterfly_n d18, d21, q6, q2, q3, q2 @ d18 = t2a, d21 = t10a | |
599 | ||
600 | mbutterfly_l q7, q6, d19, d28, d3[1], d3[0] @ q7 = t13, q6 = t12 | |
601 | butterfly_n d20, d28, q5, q7, q2, q7 @ d20 = t5a, d28 = t13a | |
602 | mbutterfly_l q3, q2, d25, d22, d1[3], d1[2] @ q3 = t7, q2 = t6 | |
603 | butterfly_n d27, d19, q4, q6, q5, q6 @ d27 = t4a, d19 = t12a | |
604 | ||
605 | mbutterfly_l q5, q4, d17, d30, d3[3], d3[2] @ q5 = t15, q4 = t14 | |
606 | movrel r12, idct_coeffs | |
607 | vld1.16 {q0}, [r12,:128] | |
608 | butterfly_n d22, d30, q3, q5, q6, q5 @ d22 = t7a, d30 = t15a | |
609 | mbutterfly_l q7, q6, d23, d24, d0[3], d1[0] @ q7 = t9, q6 = t8 | |
610 | butterfly_n d25, d17, q2, q4, q3, q4 @ d25 = t6a, d17 = t14a | |
611 | ||
612 | mbutterfly_l q2, q3, d28, d19, d1[0], d0[3] @ q2 = t12, q3 = t13 | |
613 | butterfly_n d23, d19, q6, q2, q4, q2 @ d23 = t8a, d19 = t12a | |
614 | mbutterfly_l q5, q4, d21, d26, d1[1], d1[2] @ q5 = t11, q4 = t10 | |
615 | butterfly_r d4, d27, d16, d27 @ d4 = t4, d27 = t0 | |
616 | butterfly_n d24, d28, q7, q3, q6, q3 @ d24 = t9a, d28 = t13a | |
617 | ||
618 | mbutterfly_l q6, q7, d30, d17, d1[2], d1[1] @ q6 = t14, q7 = t15 | |
619 | butterfly_r d5, d20, d31, d20 @ d5 = t5, d20 = t1 | |
620 | butterfly_n d21, d17, q4, q6, q3, q6 @ d21 = t10a, d17 = t14a | |
621 | butterfly_n d26, d30, q5, q7, q4, q7 @ d26 = t11a, d30 = t15a | |
622 | ||
623 | butterfly_r d6, d25, d18, d25 @ d6 = t6, d25 = t2 | |
624 | butterfly_r d7, d22, d29, d22 @ d7 = t7, d22 = t3 | |
625 | ||
626 | mbutterfly_l q5, q4, d19, d28, d0[1], d0[2] @ q5 = t13, q4 = t12 | |
627 | mbutterfly_l q6, q7, d30, d17, d0[2], d0[1] @ q6 = t14, q7 = t15 | |
628 | ||
629 | butterfly_n d18, d30, q4, q6, q8, q6 @ d18 = out[2], d30 = t14a | |
630 | butterfly_n d29, d17, q5, q7, q6, q7 @ d29 = -out[13], d17 = t15a | |
631 | vneg.s16 d29, d29 @ d29 = out[13] | |
632 | ||
633 | mbutterfly_l q5, q4, d4, d5, d0[1], d0[2] @ q5 = t5a, q4 = t4a | |
634 | mbutterfly_l q6, q7, d7, d6, d0[2], d0[1] @ q6 = t6a, q7 = t7a | |
635 | ||
636 | butterfly d2, d6, d27, d25 @ d2 = out[0], d6 = t2a | |
637 | butterfly d3, d7, d23, d21 @ d3 =-out[1], d7 = t10 | |
638 | ||
639 | butterfly_n d19, d31, q4, q6, q2, q4 @ d19 = -out[3], d31 = t6 | |
640 | vneg.s16 d19, d19 @ d19 = out[3] | |
641 | butterfly_n d28, d16, q5, q7, q2, q5 @ d28 = out[12], d16 = t7 | |
642 | ||
643 | butterfly d5, d8, d20, d22 @ d5 =-out[15],d8 = t3a | |
644 | butterfly d4, d9, d24, d26 @ d4 = out[14],d9 = t11 | |
645 | ||
646 | mbutterfly0 d23, d24, d6, d8, d10, d11, q6, q7, 1 @ d23 = out[7], d24 = out[8] | |
647 | mbutterfly0 d20, d27, d16, d31, d10, d11, q6, q7 @ d20 = out[4], d27 = out[11] | |
648 | mbutterfly0 d22, d25, d9, d7, d10, d11, q6, q7 @ d22 = out[6], d25 = out[9] | |
649 | mbutterfly0 d21, d26, d30, d17, d10, d11, q6, q7, 1 @ d21 = out[5], d26 = out[10] | |
650 | ||
651 | vneg.s16 d31, d5 @ d31 = out[15] | |
652 | vneg.s16 d17, d3 @ d17 = out[1] | |
653 | ||
654 | vmov d16, d2 | |
655 | vmov d30, d4 | |
656 | .endm | |
657 | ||
658 | .macro itxfm16_1d_funcs txfm | |
659 | @ Read a vertical 4x16 slice out of a 16x16 matrix, do a transform on it, | |
660 | @ transpose into a horizontal 16x4 slice and store. | |
661 | @ r0 = dst (temp buffer) | |
662 | @ r1 = unused | |
663 | @ r2 = src | |
664 | @ r3 = slice offset | |
665 | function \txfm\()16_1d_4x16_pass1_neon | |
666 | mov r12, #32 | |
667 | vmov.s16 q2, #0 | |
668 | .irp i, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31 | |
669 | vld1.16 {d\i}, [r2,:64] | |
670 | vst1.16 {d4}, [r2,:64], r12 | |
671 | .endr | |
672 | ||
673 | \txfm\()16 | |
674 | ||
675 | @ Do four 4x4 transposes. Originally, d16-d31 contain the | |
676 | @ 16 rows. Afterwards, d16-d19, d20-d23, d24-d27, d28-d31 | |
677 | @ contain the transposed 4x4 blocks. | |
678 | transpose16_q_4x_4x4 q8, q9, q10, q11, q12, q13, q14, q15, d16, d17, d18, d19, d20, d21, d22, d23, d24, d25, d26, d27, d28, d29, d30, d31 | |
679 | ||
680 | @ Store the transposed 4x4 blocks horizontally. | |
681 | cmp r3, #12 | |
682 | beq 1f | |
683 | .irp i, 16, 20, 24, 28, 17, 21, 25, 29, 18, 22, 26, 30, 19, 23, 27, 31 | |
684 | vst1.16 {d\i}, [r0,:64]! | |
685 | .endr | |
686 | bx lr | |
687 | 1: | |
688 | @ Special case: For the last input column (r3 == 12), | |
689 | @ which would be stored as the last row in the temp buffer, | |
690 | @ don't store the first 4x4 block, but keep it in registers | |
691 | @ for the first slice of the second pass (where it is the | |
692 | @ last 4x4 block). | |
693 | add r0, r0, #8 | |
694 | .irp i, 20, 24, 28 | |
695 | vst1.16 {d\i}, [r0,:64]! | |
696 | .endr | |
697 | add r0, r0, #8 | |
698 | .irp i, 21, 25, 29 | |
699 | vst1.16 {d\i}, [r0,:64]! | |
700 | .endr | |
701 | add r0, r0, #8 | |
702 | .irp i, 22, 26, 30 | |
703 | vst1.16 {d\i}, [r0,:64]! | |
704 | .endr | |
705 | add r0, r0, #8 | |
706 | .irp i, 23, 27, 31 | |
707 | vst1.16 {d\i}, [r0,:64]! | |
708 | .endr | |
709 | vmov d28, d16 | |
710 | vmov d29, d17 | |
711 | vmov d30, d18 | |
712 | vmov d31, d19 | |
713 | bx lr | |
714 | endfunc | |
715 | ||
716 | @ Read a vertical 4x16 slice out of a 16x16 matrix, do a transform on it, | |
717 | @ load the destination pixels (from a similar 4x16 slice), add and store back. | |
718 | @ r0 = dst | |
719 | @ r1 = dst stride | |
720 | @ r2 = src (temp buffer) | |
721 | @ r3 = slice offset | |
722 | function \txfm\()16_1d_4x16_pass2_neon | |
723 | mov r12, #32 | |
724 | .irp i, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27 | |
725 | vld1.16 {d\i}, [r2,:64], r12 | |
726 | .endr | |
727 | cmp r3, #0 | |
728 | beq 1f | |
729 | .irp i, 28, 29, 30, 31 | |
730 | vld1.16 {d\i}, [r2,:64], r12 | |
731 | .endr | |
732 | 1: | |
733 | ||
734 | add r3, r0, r1 | |
735 | lsl r1, r1, #1 | |
736 | \txfm\()16 | |
737 | ||
738 | .macro load_add_store coef0, coef1, coef2, coef3 | |
739 | vrshr.s16 \coef0, \coef0, #6 | |
740 | vrshr.s16 \coef1, \coef1, #6 | |
741 | ||
742 | vld1.32 {d4[]}, [r0,:32], r1 | |
743 | vld1.32 {d4[1]}, [r3,:32], r1 | |
744 | vrshr.s16 \coef2, \coef2, #6 | |
745 | vrshr.s16 \coef3, \coef3, #6 | |
746 | vld1.32 {d5[]}, [r0,:32], r1 | |
747 | vld1.32 {d5[1]}, [r3,:32], r1 | |
748 | vaddw.u8 \coef0, \coef0, d4 | |
749 | vld1.32 {d6[]}, [r0,:32], r1 | |
750 | vld1.32 {d6[1]}, [r3,:32], r1 | |
751 | vaddw.u8 \coef1, \coef1, d5 | |
752 | vld1.32 {d7[]}, [r0,:32], r1 | |
753 | vld1.32 {d7[1]}, [r3,:32], r1 | |
754 | ||
755 | vqmovun.s16 d4, \coef0 | |
756 | vqmovun.s16 d5, \coef1 | |
757 | sub r0, r0, r1, lsl #2 | |
758 | sub r3, r3, r1, lsl #2 | |
759 | vaddw.u8 \coef2, \coef2, d6 | |
760 | vaddw.u8 \coef3, \coef3, d7 | |
761 | vst1.32 {d4[0]}, [r0,:32], r1 | |
762 | vst1.32 {d4[1]}, [r3,:32], r1 | |
763 | vqmovun.s16 d6, \coef2 | |
764 | vst1.32 {d5[0]}, [r0,:32], r1 | |
765 | vst1.32 {d5[1]}, [r3,:32], r1 | |
766 | vqmovun.s16 d7, \coef3 | |
767 | ||
768 | vst1.32 {d6[0]}, [r0,:32], r1 | |
769 | vst1.32 {d6[1]}, [r3,:32], r1 | |
770 | vst1.32 {d7[0]}, [r0,:32], r1 | |
771 | vst1.32 {d7[1]}, [r3,:32], r1 | |
772 | .endm | |
773 | load_add_store q8, q9, q10, q11 | |
774 | load_add_store q12, q13, q14, q15 | |
775 | .purgem load_add_store | |
776 | ||
777 | bx lr | |
778 | endfunc | |
779 | .endm | |
780 | ||
781 | itxfm16_1d_funcs idct | |
782 | itxfm16_1d_funcs iadst | |
783 | ||
784 | .macro itxfm_func16x16 txfm1, txfm2 | |
785 | function ff_vp9_\txfm1\()_\txfm2\()_16x16_add_neon, export=1 | |
52d196fb | 786 | .ifc \txfm1\()_\txfm2,idct_idct |
a67ae670 MS |
787 | cmp r3, #1 |
788 | beq idct16x16_dc_add_neon | |
789 | .endif | |
a67ae670 | 790 | push {r4-r7,lr} |
52d196fb | 791 | .ifnc \txfm1\()_\txfm2,idct_idct |
a67ae670 MS |
792 | vpush {q4-q7} |
793 | .endif | |
a67ae670 MS |
794 | |
795 | @ Align the stack, allocate a temp buffer | |
e5b0fc17 JG |
796 | T mov r7, sp |
797 | T and r7, r7, #15 | |
798 | A and r7, sp, #15 | |
799 | add r7, r7, #512 | |
800 | sub sp, sp, r7 | |
a67ae670 MS |
801 | |
802 | mov r4, r0 | |
803 | mov r5, r1 | |
804 | mov r6, r2 | |
805 | ||
806 | .ifc \txfm1,idct | |
807 | movrel r12, idct_coeffs | |
808 | vld1.16 {q0-q1}, [r12,:128] | |
809 | .endif | |
810 | ||
811 | .irp i, 0, 4, 8, 12 | |
812 | add r0, sp, #(\i*32) | |
813 | add r2, r6, #(\i*2) | |
814 | mov r3, #\i | |
815 | bl \txfm1\()16_1d_4x16_pass1_neon | |
816 | .endr | |
3c87039a | 817 | .ifc \txfm1\()_\txfm2,iadst_idct |
a67ae670 MS |
818 | movrel r12, idct_coeffs |
819 | vld1.16 {q0-q1}, [r12,:128] | |
820 | .endif | |
821 | .irp i, 0, 4, 8, 12 | |
822 | add r0, r4, #(\i) | |
823 | mov r1, r5 | |
824 | add r2, sp, #(\i*2) | |
825 | mov r3, #\i | |
826 | bl \txfm2\()16_1d_4x16_pass2_neon | |
827 | .endr | |
828 | ||
e5b0fc17 | 829 | add sp, sp, r7 |
52d196fb | 830 | .ifnc \txfm1\()_\txfm2,idct_idct |
a67ae670 MS |
831 | vpop {q4-q7} |
832 | .endif | |
a67ae670 MS |
833 | pop {r4-r7,pc} |
834 | endfunc | |
835 | .endm | |
836 | ||
837 | itxfm_func16x16 idct, idct | |
838 | itxfm_func16x16 iadst, idct | |
839 | itxfm_func16x16 idct, iadst | |
840 | itxfm_func16x16 iadst, iadst | |
841 | .ltorg | |
842 | ||
843 | ||
844 | function idct32x32_dc_add_neon | |
845 | movrel r12, idct_coeffs | |
846 | vld1.16 {d0}, [r12,:64] | |
847 | ||
848 | vmov.i16 q2, #0 | |
849 | ||
850 | vld1.16 {d16[]}, [r2,:16] | |
851 | vmull.s16 q8, d16, d0[0] | |
852 | vrshrn.s32 d16, q8, #14 | |
853 | vmull.s16 q8, d16, d0[0] | |
854 | vrshrn.s32 d16, q8, #14 | |
855 | vdup.16 q8, d16[0] | |
856 | vst1.16 {d4[0]}, [r2,:16] | |
857 | ||
858 | vrshr.s16 q8, q8, #6 | |
859 | ||
860 | mov r12, #32 | |
861 | 1: | |
862 | @ Loop to add the constant from q8 into all 32x32 outputs | |
863 | vld1.8 {q2-q3}, [r0,:128] | |
864 | vaddw.u8 q10, q8, d4 | |
865 | vaddw.u8 q11, q8, d5 | |
866 | vaddw.u8 q12, q8, d6 | |
867 | vaddw.u8 q13, q8, d7 | |
868 | vqmovun.s16 d4, q10 | |
869 | vqmovun.s16 d5, q11 | |
870 | vqmovun.s16 d6, q12 | |
871 | vqmovun.s16 d7, q13 | |
872 | vst1.8 {q2-q3}, [r0,:128], r1 | |
873 | subs r12, r12, #1 | |
874 | bne 1b | |
875 | ||
876 | bx lr | |
877 | endfunc | |
878 | ||
879 | .macro idct32_odd | |
880 | movrel r12, idct_coeffs | |
881 | add r12, r12, #32 | |
882 | vld1.16 {q0-q1}, [r12,:128] | |
883 | ||
884 | mbutterfly d16, d31, d0[0], d0[1], q2, q3 @ d16 = t16a, d31 = t31a | |
885 | mbutterfly d24, d23, d0[2], d0[3], q2, q3 @ d24 = t17a, d23 = t30a | |
886 | mbutterfly d20, d27, d1[0], d1[1], q2, q3 @ d20 = t18a, d27 = t29a | |
887 | mbutterfly d28, d19, d1[2], d1[3], q2, q3 @ d28 = t19a, d19 = t28a | |
888 | mbutterfly d18, d29, d2[0], d2[1], q2, q3 @ d18 = t20a, d29 = t27a | |
889 | mbutterfly d26, d21, d2[2], d2[3], q2, q3 @ d26 = t21a, d21 = t26a | |
890 | mbutterfly d22, d25, d3[0], d3[1], q2, q3 @ d22 = t22a, d25 = t25a | |
891 | mbutterfly d30, d17, d3[2], d3[3], q2, q3 @ d30 = t23a, d17 = t24a | |
892 | ||
893 | sub r12, r12, #32 | |
894 | vld1.16 {q0}, [r12,:128] | |
895 | ||
896 | butterfly d4, d24, d16, d24 @ d4 = t16, d24 = t17 | |
897 | butterfly d5, d20, d28, d20 @ d5 = t19, d20 = t18 | |
898 | butterfly d6, d26, d18, d26 @ d6 = t20, d26 = t21 | |
899 | butterfly d7, d22, d30, d22 @ d7 = t23, d22 = t22 | |
900 | butterfly d28, d25, d17, d25 @ d28 = t24, d25 = t25 | |
901 | butterfly d30, d21, d29, d21 @ d30 = t27, d21 = t26 | |
902 | butterfly d29, d23, d31, d23 @ d29 = t31, d23 = t30 | |
903 | butterfly d31, d27, d19, d27 @ d31 = t28, d27 = t29 | |
904 | ||
905 | mbutterfly d23, d24, d0[3], d1[0], q8, q9 @ d23 = t17a, d24 = t30a | |
906 | mbutterfly d27, d20, d0[3], d1[0], q8, q9, neg=1 @ d27 = t29a, d20 = t18a | |
907 | mbutterfly d21, d26, d1[1], d1[2], q8, q9 @ d21 = t21a, d26 = t26a | |
908 | mbutterfly d25, d22, d1[1], d1[2], q8, q9, neg=1 @ d25 = t25a, d22 = t22a | |
909 | ||
910 | butterfly d16, d5, d4, d5 @ d16 = t16a, d5 = t19a | |
911 | butterfly d17, d20, d23, d20 @ d17 = t17, d20 = t18 | |
912 | butterfly d18, d6, d7, d6 @ d18 = t23a, d6 = t20a | |
913 | butterfly d19, d21, d22, d21 @ d19 = t22, d21 = t21 | |
914 | butterfly d4, d28, d28, d30 @ d4 = t24a, d28 = t27a | |
915 | butterfly d23, d26, d25, d26 @ d23 = t25, d26 = t26 | |
916 | butterfly d7, d29, d29, d31 @ d7 = t31a, d29 = t28a | |
917 | butterfly d22, d27, d24, d27 @ d22 = t30, d27 = t29 | |
918 | ||
919 | mbutterfly d27, d20, d0[1], d0[2], q12, q15 @ d27 = t18a, d20 = t29a | |
920 | mbutterfly d29, d5, d0[1], d0[2], q12, q15 @ d29 = t19, d5 = t28 | |
921 | mbutterfly d28, d6, d0[1], d0[2], q12, q15, neg=1 @ d28 = t27, d6 = t20 | |
922 | mbutterfly d26, d21, d0[1], d0[2], q12, q15, neg=1 @ d26 = t26a, d21 = t21a | |
923 | ||
924 | butterfly d31, d24, d7, d4 @ d31 = t31, d24 = t24 | |
925 | butterfly d30, d25, d22, d23 @ d30 = t30a, d25 = t25a | |
926 | butterfly_r d23, d16, d16, d18 @ d23 = t23, d16 = t16 | |
927 | butterfly_r d22, d17, d17, d19 @ d22 = t22a, d17 = t17a | |
928 | butterfly d18, d21, d27, d21 @ d18 = t18, d21 = t21 | |
929 | butterfly_r d27, d28, d5, d28 @ d27 = t27a, d28 = t28a | |
930 | butterfly d4, d26, d20, d26 @ d4 = t29, d26 = t26 | |
931 | butterfly d19, d20, d29, d6 @ d19 = t19a, d20 = t20 | |
932 | vmov d29, d4 @ d29 = t29 | |
933 | ||
934 | mbutterfly0 d27, d20, d27, d20, d4, d6, q2, q3 @ d27 = t27, d20 = t20 | |
935 | mbutterfly0 d26, d21, d26, d21, d4, d6, q2, q3 @ d26 = t26a, d21 = t21a | |
936 | mbutterfly0 d25, d22, d25, d22, d4, d6, q2, q3 @ d25 = t25, d22 = t22 | |
937 | mbutterfly0 d24, d23, d24, d23, d4, d6, q2, q3 @ d24 = t24a, d23 = t23a | |
938 | .endm | |
939 | ||
940 | @ Do an 32-point IDCT of a 4x32 slice out of a 32x32 matrix. | |
941 | @ We don't have register space to do a single pass IDCT of 4x32 though, | |
942 | @ but the 32-point IDCT can be decomposed into two 16-point IDCTs; | |
943 | @ a normal IDCT16 with every other input component (the even ones, with | |
944 | @ each output written twice), followed by a separate 16-point IDCT | |
945 | @ of the odd inputs, added/subtracted onto the outputs of the first idct16. | |
946 | @ r0 = dst (temp buffer) | |
947 | @ r1 = unused | |
948 | @ r2 = src | |
949 | function idct32_1d_4x32_pass1_neon | |
950 | movrel r12, idct_coeffs | |
951 | vld1.16 {q0-q1}, [r12,:128] | |
952 | ||
953 | @ Double stride of the input, since we only read every other line | |
954 | mov r12, #128 | |
955 | vmov.s16 d4, #0 | |
956 | ||
957 | @ d16 = IN(0), d17 = IN(2) ... d31 = IN(30) | |
958 | .irp i, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31 | |
959 | vld1.16 {d\i}, [r2,:64] | |
960 | vst1.16 {d4}, [r2,:64], r12 | |
961 | .endr | |
962 | ||
963 | idct16 | |
964 | ||
965 | @ Do four 4x4 transposes. Originally, d16-d31 contain the | |
966 | @ 16 rows. Afterwards, d16-d19, d20-d23, d24-d27, d28-d31 | |
967 | @ contain the transposed 4x4 blocks. | |
968 | transpose16_q_4x_4x4 q8, q9, q10, q11, q12, q13, q14, q15, d16, d17, d18, d19, d20, d21, d22, d23, d24, d25, d26, d27, d28, d29, d30, d31 | |
969 | @ Store the registers a, b, c, d horizontally, followed | |
970 | @ by the same registers d, c, b, a mirrored. | |
971 | .macro store_rev a, b, c, d | |
972 | .irp i, \a, \b, \c, \d | |
973 | vst1.16 {d\i}, [r0,:64]! | |
974 | vrev64.16 d\i, d\i | |
975 | .endr | |
976 | .irp i, \d, \c, \b, \a | |
977 | vst1.16 {d\i}, [r0,:64]! | |
978 | .endr | |
979 | .endm | |
980 | store_rev 16, 20, 24, 28 | |
981 | store_rev 17, 21, 25, 29 | |
982 | store_rev 18, 22, 26, 30 | |
983 | store_rev 19, 23, 27, 31 | |
984 | sub r0, r0, #256 | |
985 | .purgem store_rev | |
986 | ||
987 | @ Move r2 back to the start of the input, and move | |
988 | @ to the first odd row | |
989 | sub r2, r2, r12, lsl #4 | |
990 | add r2, r2, #64 | |
991 | ||
992 | vmov.s16 d4, #0 | |
993 | @ d16 = IN(1), d17 = IN(3) ... d31 = IN(31) | |
994 | .irp i, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31 | |
995 | vld1.16 {d\i}, [r2,:64] | |
996 | vst1.16 {d4}, [r2,:64], r12 | |
997 | .endr | |
998 | ||
999 | idct32_odd | |
1000 | ||
1001 | transpose16_q_4x_4x4 q15, q14, q13, q12, q11, q10, q9, q8, d31, d30, d29, d28, d27, d26, d25, d24, d23, d22, d21, d20, d19, d18, d17, d16 | |
1002 | ||
1003 | @ Store the registers a, b, c, d horizontally, | |
1004 | @ adding into the output first, and then mirrored, subtracted | |
1005 | @ from the output. | |
1006 | .macro store_rev a, b, c, d | |
1007 | .irp i, \a, \b, \c, \d | |
1008 | vld1.16 {d4}, [r0,:64] | |
1009 | vadd.s16 d4, d4, d\i | |
1010 | vst1.16 {d4}, [r0,:64]! | |
1011 | vrev64.16 d\i, d\i | |
1012 | .endr | |
1013 | .irp i, \d, \c, \b, \a | |
1014 | vld1.16 {d4}, [r0,:64] | |
1015 | vsub.s16 d4, d4, d\i | |
1016 | vst1.16 {d4}, [r0,:64]! | |
1017 | .endr | |
1018 | .endm | |
1019 | ||
721bc375 MS |
1020 | store_rev 31, 27, 23, 19 |
1021 | store_rev 30, 26, 22, 18 | |
1022 | store_rev 29, 25, 21, 17 | |
1023 | store_rev 28, 24, 20, 16 | |
a67ae670 MS |
1024 | .purgem store_rev |
1025 | bx lr | |
1026 | endfunc | |
1027 | .ltorg | |
1028 | ||
1029 | @ This is mostly the same as 4x32_pass1, but without the transpose, | |
1030 | @ and use the source as temp buffer between the two idct passes, and | |
1031 | @ add into the destination. | |
1032 | @ r0 = dst | |
1033 | @ r1 = dst stride | |
1034 | @ r2 = src (temp buffer) | |
1035 | function idct32_1d_4x32_pass2_neon | |
1036 | movrel r12, idct_coeffs | |
1037 | vld1.16 {q0-q1}, [r12,:128] | |
1038 | ||
1039 | mov r12, #128 | |
1040 | @ d16 = IN(0), d17 = IN(2) ... d31 = IN(30) | |
1041 | .irp i, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31 | |
1042 | vld1.16 {d\i}, [r2,:64], r12 | |
1043 | .endr | |
1044 | sub r2, r2, r12, lsl #4 | |
1045 | ||
1046 | idct16 | |
1047 | ||
1048 | .irp i, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31 | |
1049 | vst1.16 {d\i}, [r2,:64], r12 | |
1050 | .endr | |
1051 | ||
1052 | sub r2, r2, r12, lsl #4 | |
1053 | add r2, r2, #64 | |
1054 | ||
1055 | @ d16 = IN(1), d17 = IN(3) ... d31 = IN(31) | |
1056 | .irp i, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31 | |
1057 | vld1.16 {d\i}, [r2,:64], r12 | |
1058 | .endr | |
1059 | sub r2, r2, r12, lsl #4 | |
1060 | sub r2, r2, #64 | |
1061 | ||
1062 | idct32_odd | |
1063 | ||
1064 | mov r12, #128 | |
1065 | .macro load_acc_store a, b, c, d, neg=0 | |
1066 | vld1.16 {d4}, [r2,:64], r12 | |
1067 | vld1.16 {d5}, [r2,:64], r12 | |
1068 | .if \neg == 0 | |
1069 | vadd.s16 d4, d4, d\a | |
1070 | vld1.16 {d6}, [r2,:64], r12 | |
1071 | vadd.s16 d5, d5, d\b | |
1072 | vld1.16 {d7}, [r2,:64], r12 | |
1073 | vadd.s16 d6, d6, d\c | |
1074 | vadd.s16 d7, d7, d\d | |
1075 | .else | |
1076 | vsub.s16 d4, d4, d\a | |
1077 | vld1.16 {d6}, [r2,:64], r12 | |
1078 | vsub.s16 d5, d5, d\b | |
1079 | vld1.16 {d7}, [r2,:64], r12 | |
1080 | vsub.s16 d6, d6, d\c | |
1081 | vsub.s16 d7, d7, d\d | |
1082 | .endif | |
1083 | vld1.32 {d2[]}, [r0,:32], r1 | |
1084 | vld1.32 {d2[1]}, [r0,:32], r1 | |
1085 | vrshr.s16 q2, q2, #6 | |
1086 | vld1.32 {d3[]}, [r0,:32], r1 | |
1087 | vrshr.s16 q3, q3, #6 | |
1088 | vld1.32 {d3[1]}, [r0,:32], r1 | |
1089 | sub r0, r0, r1, lsl #2 | |
1090 | vaddw.u8 q2, q2, d2 | |
1091 | vaddw.u8 q3, q3, d3 | |
1092 | vqmovun.s16 d4, q2 | |
1093 | vqmovun.s16 d5, q3 | |
1094 | vst1.32 {d4[0]}, [r0,:32], r1 | |
1095 | vst1.32 {d4[1]}, [r0,:32], r1 | |
1096 | vst1.32 {d5[0]}, [r0,:32], r1 | |
1097 | vst1.32 {d5[1]}, [r0,:32], r1 | |
1098 | .endm | |
1099 | load_acc_store 31, 30, 29, 28 | |
1100 | load_acc_store 27, 26, 25, 24 | |
1101 | load_acc_store 23, 22, 21, 20 | |
1102 | load_acc_store 19, 18, 17, 16 | |
1103 | sub r2, r2, r12 | |
1104 | neg r12, r12 | |
1105 | load_acc_store 16, 17, 18, 19, 1 | |
1106 | load_acc_store 20, 21, 22, 23, 1 | |
1107 | load_acc_store 24, 25, 26, 27, 1 | |
1108 | load_acc_store 28, 29, 30, 31, 1 | |
1109 | .purgem load_acc_store | |
1110 | bx lr | |
1111 | endfunc | |
1112 | ||
1113 | function ff_vp9_idct_idct_32x32_add_neon, export=1 | |
1114 | cmp r3, #1 | |
1115 | beq idct32x32_dc_add_neon | |
1116 | push {r4-r7,lr} | |
1117 | vpush {q4-q7} | |
a67ae670 MS |
1118 | |
1119 | @ Align the stack, allocate a temp buffer | |
e5b0fc17 JG |
1120 | T mov r7, sp |
1121 | T and r7, r7, #15 | |
1122 | A and r7, sp, #15 | |
1123 | add r7, r7, #2048 | |
1124 | sub sp, sp, r7 | |
a67ae670 MS |
1125 | |
1126 | mov r4, r0 | |
1127 | mov r5, r1 | |
1128 | mov r6, r2 | |
1129 | ||
1130 | .irp i, 0, 4, 8, 12, 16, 20, 24, 28 | |
1131 | add r0, sp, #(\i*64) | |
1132 | add r2, r6, #(\i*2) | |
1133 | bl idct32_1d_4x32_pass1_neon | |
1134 | .endr | |
1135 | .irp i, 0, 4, 8, 12, 16, 20, 24, 28 | |
1136 | add r0, r4, #(\i) | |
1137 | mov r1, r5 | |
1138 | add r2, sp, #(\i*2) | |
1139 | bl idct32_1d_4x32_pass2_neon | |
1140 | .endr | |
1141 | ||
e5b0fc17 | 1142 | add sp, sp, r7 |
a67ae670 MS |
1143 | vpop {q4-q7} |
1144 | pop {r4-r7,pc} | |
1145 | endfunc |