4 * Copyright (c) 2008 Mans Rullgard <mans@mansr.com>
7 * Copyright (c) 2001 Michael Niedermayer <michaelni@gmx.at>
9 * This file is part of FFmpeg.
11 * FFmpeg is free software; you can redistribute it and/or
12 * modify it under the terms of the GNU Lesser General Public
13 * License as published by the Free Software Foundation; either
14 * version 2.1 of the License, or (at your option) any later version.
16 * FFmpeg is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
19 * Lesser General Public License for more details.
21 * You should have received a copy of the GNU Lesser General Public
22 * License along with FFmpeg; if not, write to the Free Software
23 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
26 #include "libavutil/arm/asm.S"
28 #define W1 22725 //cos(i*M_PI/16)*sqrt(2)*(1<<14) + 0.5
29 #define W2 21407 //cos(i*M_PI/16)*sqrt(2)*(1<<14) + 0.5
30 #define W3 19266 //cos(i*M_PI/16)*sqrt(2)*(1<<14) + 0.5
31 #define W4 16383 //cos(i*M_PI/16)*sqrt(2)*(1<<14) + 0.5
32 #define W5 12873 //cos(i*M_PI/16)*sqrt(2)*(1<<14) + 0.5
33 #define W6 8867 //cos(i*M_PI/16)*sqrt(2)*(1<<14) + 0.5
34 #define W7 4520 //cos(i*M_PI/16)*sqrt(2)*(1<<14) + 0.5
35 #define W4c ((1<<(COL_SHIFT-1))/W4)
49 vmull.s16 q7, d6, w2 /* q9 = W2 * col[2] */
50 vmull.s16 q8, d6, w6 /* q10 = W6 * col[2] */
51 vmull.s16 q9, d4, w1 /* q9 = W1 * col[1] */
53 vmull.s16 q10, d4, w3 /* q10 = W3 * col[1] */
55 vmull.s16 q5, d4, w5 /* q5 = W5 * col[1] */
57 vmull.s16 q6, d4, w7 /* q6 = W7 * col[1] */
60 vmlal.s16 q9, d8, w3 /* q9 += W3 * col[3] */
61 vmlsl.s16 q10, d8, w7 /* q10 -= W7 * col[3] */
62 vmlsl.s16 q5, d8, w1 /* q5 -= W1 * col[3] */
63 vmlsl.s16 q6, d8, w5 /* q6 -= W5 * col[3] */
69 function idct_row4_pld_neon
71 add r3, r0, r1, lsl #2
77 add r3, r3, r1, lsl #1
82 function idct_row4_neon
83 vmov.i32 q15, #(1<<(ROW_SHIFT-1))
84 vld1.64 {d2-d5}, [r2,:128]!
85 vmlal.s16 q15, d2, w4 /* q15 += W4 * col[0] */
86 vld1.64 {d6,d7}, [r2,:128]!
88 vld1.64 {d8,d9}, [r2,:128]!
100 vmull.s16 q7, d3, w4 /* q7 = W4 * col[4] */
101 vmlal.s16 q9, d5, w5 /* q9 += W5 * col[5] */
102 vmlsl.s16 q10, d5, w1 /* q10 -= W1 * col[5] */
103 vmull.s16 q8, d7, w2 /* q8 = W2 * col[6] */
104 vmlal.s16 q5, d5, w7 /* q5 += W7 * col[5] */
105 vadd.i32 q11, q11, q7
106 vsub.i32 q12, q12, q7
107 vsub.i32 q13, q13, q7
108 vadd.i32 q14, q14, q7
109 vmlal.s16 q6, d5, w3 /* q6 += W3 * col[5] */
110 vmull.s16 q7, d7, w6 /* q7 = W6 * col[6] */
112 vmlsl.s16 q10, d9, w5
115 vadd.i32 q11, q11, q7
116 vsub.i32 q12, q12, q8
117 vadd.i32 q13, q13, q8
118 vsub.i32 q14, q14, q7
120 1: vadd.i32 q3, q11, q9
121 vadd.i32 q4, q12, q10
122 vshrn.i32 d2, q3, #ROW_SHIFT
123 vshrn.i32 d4, q4, #ROW_SHIFT
127 vshrn.i32 d6, q7, #ROW_SHIFT
128 vshrn.i32 d8, q8, #ROW_SHIFT
129 vsub.i32 q14, q14, q6
130 vsub.i32 q11, q11, q9
132 vsub.i32 q13, q13, q5
133 vshrn.i32 d3, q14, #ROW_SHIFT
135 vsub.i32 q12, q12, q10
137 vshrn.i32 d5, q13, #ROW_SHIFT
138 vshrn.i32 d7, q12, #ROW_SHIFT
139 vshrn.i32 d9, q11, #ROW_SHIFT
146 vst1.64 {d2-d5}, [r2,:128]!
147 vst1.64 {d6-d9}, [r2,:128]!
152 function idct_col4_neon
154 vld1.64 {d2}, [r2,:64], ip /* d2 = col[0] */
156 vld1.64 {d4}, [r2,:64], ip /* d3 = col[1] */
157 vadd.i16 d30, d30, d2
158 vld1.64 {d6}, [r2,:64], ip /* d4 = col[2] */
159 vmull.s16 q15, d30, w4 /* q15 = W4*(col[0]+(1<<COL_SHIFT-1)/W4)*/
160 vld1.64 {d8}, [r2,:64], ip /* d5 = col[3] */
171 vld1.64 {d3}, [r2,:64], ip /* d6 = col[4] */
172 vmull.s16 q7, d3, w4 /* q7 = W4 * col[4] */
173 vadd.i32 q11, q11, q7
174 vsub.i32 q12, q12, q7
175 vsub.i32 q13, q13, q7
176 vadd.i32 q14, q14, q7
184 vld1.64 {d5}, [r2,:64], ip /* d7 = col[5] */
185 vmlal.s16 q9, d5, w5 /* q9 += W5 * col[5] */
186 vmlsl.s16 q10, d5, w1 /* q10 -= W1 * col[5] */
187 vmlal.s16 q5, d5, w7 /* q5 += W7 * col[5] */
188 vmlal.s16 q6, d5, w3 /* q6 += W3 * col[5] */
196 vld1.64 {d7}, [r2,:64], ip /* d8 = col[6] */
197 vmull.s16 q7, d7, w6 /* q7 = W6 * col[6] */
198 vmull.s16 q8, d7, w2 /* q8 = W2 * col[6] */
199 vadd.i32 q11, q11, q7
200 vsub.i32 q14, q14, q7
201 vsub.i32 q12, q12, q8
202 vadd.i32 q13, q13, q8
209 vld1.64 {d9}, [r2,:64], ip /* d9 = col[7] */
211 vmlsl.s16 q10, d9, w5
215 4: vaddhn.i32 d2, q11, q9
216 vaddhn.i32 d3, q12, q10
217 vaddhn.i32 d4, q13, q5
218 vaddhn.i32 d5, q14, q6
219 vsubhn.i32 d9, q11, q9
220 vsubhn.i32 d8, q12, q10
221 vsubhn.i32 d7, q13, q5
222 vsubhn.i32 d6, q14, q6
229 function idct_col4_st8_neon
230 vqshrun.s16 d2, q1, #COL_SHIFT-16
231 vqshrun.s16 d3, q2, #COL_SHIFT-16
232 vqshrun.s16 d4, q3, #COL_SHIFT-16
233 vqshrun.s16 d5, q4, #COL_SHIFT-16
234 vst1.32 {d2[0]}, [r0,:32], r1
235 vst1.32 {d2[1]}, [r0,:32], r1
236 vst1.32 {d3[0]}, [r0,:32], r1
237 vst1.32 {d3[1]}, [r0,:32], r1
238 vst1.32 {d4[0]}, [r0,:32], r1
239 vst1.32 {d4[1]}, [r0,:32], r1
240 vst1.32 {d5[0]}, [r0,:32], r1
241 vst1.32 {d5[1]}, [r0,:32], r1
246 const idct_coeff_neon, align=4
247 .short W1, W2, W3, W4, W5, W6, W7, W4c
250 .macro idct_start data
255 movrel r3, idct_coeff_neon
256 vld1.64 {d0,d1}, [r3,:128]
264 /* void ff_simple_idct_put_neon(uint8_t *dst, int line_size, DCTELEM *data); */
265 function ff_simple_idct_put_neon, export=1
268 bl idct_row4_pld_neon
272 bl idct_col4_st8_neon
273 sub r0, r0, r1, lsl #3
277 bl idct_col4_st8_neon
284 function idct_col4_add8_neon
287 vld1.32 {d10[0]}, [r0,:32], r1
288 vshr.s16 q1, q1, #COL_SHIFT-16
289 vld1.32 {d10[1]}, [r0,:32], r1
290 vshr.s16 q2, q2, #COL_SHIFT-16
291 vld1.32 {d11[0]}, [r0,:32], r1
292 vshr.s16 q3, q3, #COL_SHIFT-16
293 vld1.32 {d11[1]}, [r0,:32], r1
294 vshr.s16 q4, q4, #COL_SHIFT-16
295 vld1.32 {d12[0]}, [r0,:32], r1
297 vld1.32 {d12[1]}, [r0,:32], r1
299 vld1.32 {d13[0]}, [r0,:32], r1
301 vld1.32 {d13[1]}, [r0,:32], r1
303 vst1.32 {d2[0]}, [ip,:32], r1
305 vst1.32 {d2[1]}, [ip,:32], r1
307 vst1.32 {d3[0]}, [ip,:32], r1
309 vst1.32 {d3[1]}, [ip,:32], r1
311 vst1.32 {d4[0]}, [ip,:32], r1
312 vst1.32 {d4[1]}, [ip,:32], r1
313 vst1.32 {d5[0]}, [ip,:32], r1
314 vst1.32 {d5[1]}, [ip,:32], r1
319 /* void ff_simple_idct_add_neon(uint8_t *dst, int line_size, DCTELEM *data); */
320 function ff_simple_idct_add_neon, export=1
323 bl idct_row4_pld_neon
327 bl idct_col4_add8_neon
328 sub r0, r0, r1, lsl #3
332 bl idct_col4_add8_neon
339 function idct_col4_st16_neon
342 vshr.s16 q1, q1, #COL_SHIFT-16
343 vshr.s16 q2, q2, #COL_SHIFT-16
344 vst1.64 {d2}, [r2,:64], ip
345 vshr.s16 q3, q3, #COL_SHIFT-16
346 vst1.64 {d3}, [r2,:64], ip
347 vshr.s16 q4, q4, #COL_SHIFT-16
348 vst1.64 {d4}, [r2,:64], ip
349 vst1.64 {d5}, [r2,:64], ip
350 vst1.64 {d6}, [r2,:64], ip
351 vst1.64 {d7}, [r2,:64], ip
352 vst1.64 {d8}, [r2,:64], ip
353 vst1.64 {d9}, [r2,:64], ip
358 /* void ff_simple_idct_neon(DCTELEM *data); */
359 function ff_simple_idct_neon, export=1
368 bl idct_col4_st16_neon
372 bl idct_col4_st16_neon