ffmpeg / libavcodec / arm / simple_idct_neon.S @ 96088566
History | View | Annotate | Download (12.4 KB)
1 |
/* |
---|---|
2 |
* ARM NEON IDCT |
3 |
* |
4 |
* Copyright (c) 2008 Mans Rullgard <mans@mansr.com> |
5 |
* |
6 |
* Based on Simple IDCT |
7 |
* Copyright (c) 2001 Michael Niedermayer <michaelni@gmx.at> |
8 |
* |
9 |
* This file is part of FFmpeg. |
10 |
* |
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. |
15 |
* |
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. |
20 |
* |
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 |
24 |
*/ |
25 |
|
26 |
#include "asm.S" |
27 |
|
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) |
36 |
#define ROW_SHIFT 11 |
37 |
#define COL_SHIFT 20 |
38 |
|
39 |
#define w1 d0[0] |
40 |
#define w2 d0[1] |
41 |
#define w3 d0[2] |
42 |
#define w4 d0[3] |
43 |
#define w5 d1[0] |
44 |
#define w6 d1[1] |
45 |
#define w7 d1[2] |
46 |
#define w4c d1[3] |
47 |
|
48 |
.macro idct_col4_top |
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] */ |
52 |
vadd.i32 q11, q15, q7 |
53 |
vmull.s16 q10, d4, w3 /* q10 = W3 * col[1] */ |
54 |
vadd.i32 q12, q15, q8 |
55 |
vmull.s16 q5, d4, w5 /* q5 = W5 * col[1] */ |
56 |
vsub.i32 q13, q15, q8 |
57 |
vmull.s16 q6, d4, w7 /* q6 = W7 * col[1] */ |
58 |
vsub.i32 q14, q15, q7 |
59 |
|
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] */ |
64 |
.endm |
65 |
|
66 |
.text |
67 |
.align 6 |
68 |
|
69 |
function idct_row4_pld_neon |
70 |
pld [r0] |
71 |
add r3, r0, r1, lsl #2 |
72 |
pld [r0, r1] |
73 |
pld [r0, r1, lsl #1] |
74 |
pld [r3, -r1] |
75 |
pld [r3] |
76 |
pld [r3, r1] |
77 |
add r3, r3, r1, lsl #1 |
78 |
pld [r3] |
79 |
pld [r3, r1] |
80 |
endfunc |
81 |
|
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]! |
87 |
vorr d10, d3, d5 |
88 |
vld1.64 {d8,d9}, [r2,:128]! |
89 |
add r2, r2, #-64 |
90 |
|
91 |
vorr d11, d7, d9 |
92 |
vorr d10, d10, d11 |
93 |
vmov r3, r4, d10 |
94 |
|
95 |
idct_col4_top |
96 |
|
97 |
orrs r3, r3, r4 |
98 |
beq 1f |
99 |
|
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] */ |
111 |
vmlal.s16 q9, d9, w7 |
112 |
vmlsl.s16 q10, d9, w5 |
113 |
vmlal.s16 q5, d9, w3 |
114 |
vmlsl.s16 q6, d9, w1 |
115 |
vadd.i32 q11, q11, q7 |
116 |
vsub.i32 q12, q12, q8 |
117 |
vadd.i32 q13, q13, q8 |
118 |
vsub.i32 q14, q14, q7 |
119 |
|
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 |
124 |
vadd.i32 q7, q13, q5 |
125 |
vadd.i32 q8, q14, q6 |
126 |
vtrn.16 d2, d4 |
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 |
131 |
vtrn.16 d6, d8 |
132 |
vsub.i32 q13, q13, q5 |
133 |
vshrn.i32 d3, q14, #ROW_SHIFT |
134 |
vtrn.32 d2, d6 |
135 |
vsub.i32 q12, q12, q10 |
136 |
vtrn.32 d4, d8 |
137 |
vshrn.i32 d5, q13, #ROW_SHIFT |
138 |
vshrn.i32 d7, q12, #ROW_SHIFT |
139 |
vshrn.i32 d9, q11, #ROW_SHIFT |
140 |
|
141 |
vtrn.16 d3, d5 |
142 |
vtrn.16 d7, d9 |
143 |
vtrn.32 d3, d7 |
144 |
vtrn.32 d5, d9 |
145 |
|
146 |
vst1.64 {d2-d5}, [r2,:128]! |
147 |
vst1.64 {d6-d9}, [r2,:128]! |
148 |
|
149 |
bx lr |
150 |
endfunc |
151 |
|
152 |
function idct_col4_neon |
153 |
mov ip, #16 |
154 |
vld1.64 {d2}, [r2,:64], ip /* d2 = col[0] */ |
155 |
vdup.16 d30, w4c |
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] */ |
161 |
|
162 |
ldrd r4, [r2] |
163 |
ldrd r6, [r2, #16] |
164 |
orrs r4, r4, r5 |
165 |
|
166 |
idct_col4_top |
167 |
addeq r2, r2, #16 |
168 |
beq 1f |
169 |
|
170 |
vld1.64 {d3}, [r2,:64], ip /* d6 = col[4] */ |
171 |
vmull.s16 q7, d3, w4 /* q7 = W4 * col[4] */ |
172 |
vadd.i32 q11, q11, q7 |
173 |
vsub.i32 q12, q12, q7 |
174 |
vsub.i32 q13, q13, q7 |
175 |
vadd.i32 q14, q14, q7 |
176 |
|
177 |
1: orrs r6, r6, r7 |
178 |
ldrd r4, [r2, #16] |
179 |
addeq r2, r2, #16 |
180 |
beq 2f |
181 |
|
182 |
vld1.64 {d5}, [r2,:64], ip /* d7 = col[5] */ |
183 |
vmlal.s16 q9, d5, w5 /* q9 += W5 * col[5] */ |
184 |
vmlsl.s16 q10, d5, w1 /* q10 -= W1 * col[5] */ |
185 |
vmlal.s16 q5, d5, w7 /* q5 += W7 * col[5] */ |
186 |
vmlal.s16 q6, d5, w3 /* q6 += W3 * col[5] */ |
187 |
|
188 |
2: orrs r4, r4, r5 |
189 |
ldrd r4, [r2, #16] |
190 |
addeq r2, r2, #16 |
191 |
beq 3f |
192 |
|
193 |
vld1.64 {d7}, [r2,:64], ip /* d8 = col[6] */ |
194 |
vmull.s16 q7, d7, w6 /* q7 = W6 * col[6] */ |
195 |
vmull.s16 q8, d7, w2 /* q8 = W2 * col[6] */ |
196 |
vadd.i32 q11, q11, q7 |
197 |
vsub.i32 q14, q14, q7 |
198 |
vsub.i32 q12, q12, q8 |
199 |
vadd.i32 q13, q13, q8 |
200 |
|
201 |
3: orrs r4, r4, r5 |
202 |
addeq r2, r2, #16 |
203 |
beq 4f |
204 |
|
205 |
vld1.64 {d9}, [r2,:64], ip /* d9 = col[7] */ |
206 |
vmlal.s16 q9, d9, w7 |
207 |
vmlsl.s16 q10, d9, w5 |
208 |
vmlal.s16 q5, d9, w3 |
209 |
vmlsl.s16 q6, d9, w1 |
210 |
|
211 |
4: vaddhn.i32 d2, q11, q9 |
212 |
vaddhn.i32 d3, q12, q10 |
213 |
vaddhn.i32 d4, q13, q5 |
214 |
vaddhn.i32 d5, q14, q6 |
215 |
vsubhn.i32 d9, q11, q9 |
216 |
vsubhn.i32 d8, q12, q10 |
217 |
vsubhn.i32 d7, q13, q5 |
218 |
vsubhn.i32 d6, q14, q6 |
219 |
|
220 |
bx lr |
221 |
endfunc |
222 |
|
223 |
.align 6 |
224 |
|
225 |
function idct_col4_st8_neon |
226 |
vqshrun.s16 d2, q1, #COL_SHIFT-16 |
227 |
vqshrun.s16 d3, q2, #COL_SHIFT-16 |
228 |
vqshrun.s16 d4, q3, #COL_SHIFT-16 |
229 |
vqshrun.s16 d5, q4, #COL_SHIFT-16 |
230 |
vst1.32 {d2[0]}, [r0,:32], r1 |
231 |
vst1.32 {d2[1]}, [r0,:32], r1 |
232 |
vst1.32 {d3[0]}, [r0,:32], r1 |
233 |
vst1.32 {d3[1]}, [r0,:32], r1 |
234 |
vst1.32 {d4[0]}, [r0,:32], r1 |
235 |
vst1.32 {d4[1]}, [r0,:32], r1 |
236 |
vst1.32 {d5[0]}, [r0,:32], r1 |
237 |
vst1.32 {d5[1]}, [r0,:32], r1 |
238 |
|
239 |
bx lr |
240 |
endfunc |
241 |
|
242 |
.section .rodata |
243 |
.align 4 |
244 |
idct_coeff_neon: |
245 |
.short W1, W2, W3, W4, W5, W6, W7, W4c |
246 |
|
247 |
.macro idct_start data |
248 |
push {r4-r7, lr} |
249 |
pld [\data] |
250 |
pld [\data, #64] |
251 |
vpush {d8-d15} |
252 |
movrel r3, idct_coeff_neon |
253 |
vld1.64 {d0,d1}, [r3,:128] |
254 |
.endm |
255 |
|
256 |
.macro idct_end |
257 |
vpop {d8-d15} |
258 |
pop {r4-r7, pc} |
259 |
.endm |
260 |
|
261 |
/* void ff_simple_idct_put_neon(uint8_t *dst, int line_size, DCTELEM *data); */ |
262 |
function ff_simple_idct_put_neon, export=1 |
263 |
idct_start r2 |
264 |
|
265 |
bl idct_row4_pld_neon |
266 |
bl idct_row4_neon |
267 |
add r2, r2, #-128 |
268 |
bl idct_col4_neon |
269 |
bl idct_col4_st8_neon |
270 |
sub r0, r0, r1, lsl #3 |
271 |
add r0, r0, #4 |
272 |
add r2, r2, #-120 |
273 |
bl idct_col4_neon |
274 |
bl idct_col4_st8_neon |
275 |
|
276 |
idct_end |
277 |
endfunc |
278 |
|
279 |
.align 6 |
280 |
|
281 |
function idct_col4_add8_neon |
282 |
mov ip, r0 |
283 |
|
284 |
vld1.32 {d10[0]}, [r0,:32], r1 |
285 |
vshr.s16 q1, q1, #COL_SHIFT-16 |
286 |
vld1.32 {d10[1]}, [r0,:32], r1 |
287 |
vshr.s16 q2, q2, #COL_SHIFT-16 |
288 |
vld1.32 {d11[0]}, [r0,:32], r1 |
289 |
vshr.s16 q3, q3, #COL_SHIFT-16 |
290 |
vld1.32 {d11[1]}, [r0,:32], r1 |
291 |
vshr.s16 q4, q4, #COL_SHIFT-16 |
292 |
vld1.32 {d12[0]}, [r0,:32], r1 |
293 |
vaddw.u8 q1, q1, d10 |
294 |
vld1.32 {d12[1]}, [r0,:32], r1 |
295 |
vaddw.u8 q2, q2, d11 |
296 |
vld1.32 {d13[0]}, [r0,:32], r1 |
297 |
vqmovun.s16 d2, q1 |
298 |
vld1.32 {d13[1]}, [r0,:32], r1 |
299 |
vaddw.u8 q3, q3, d12 |
300 |
vst1.32 {d2[0]}, [ip,:32], r1 |
301 |
vqmovun.s16 d3, q2 |
302 |
vst1.32 {d2[1]}, [ip,:32], r1 |
303 |
vaddw.u8 q4, q4, d13 |
304 |
vst1.32 {d3[0]}, [ip,:32], r1 |
305 |
vqmovun.s16 d4, q3 |
306 |
vst1.32 {d3[1]}, [ip,:32], r1 |
307 |
vqmovun.s16 d5, q4 |
308 |
vst1.32 {d4[0]}, [ip,:32], r1 |
309 |
vst1.32 {d4[1]}, [ip,:32], r1 |
310 |
vst1.32 {d5[0]}, [ip,:32], r1 |
311 |
vst1.32 {d5[1]}, [ip,:32], r1 |
312 |
|
313 |
bx lr |
314 |
endfunc |
315 |
|
316 |
/* void ff_simple_idct_add_neon(uint8_t *dst, int line_size, DCTELEM *data); */ |
317 |
function ff_simple_idct_add_neon, export=1 |
318 |
idct_start r2 |
319 |
|
320 |
bl idct_row4_pld_neon |
321 |
bl idct_row4_neon |
322 |
add r2, r2, #-128 |
323 |
bl idct_col4_neon |
324 |
bl idct_col4_add8_neon |
325 |
sub r0, r0, r1, lsl #3 |
326 |
add r0, r0, #4 |
327 |
add r2, r2, #-120 |
328 |
bl idct_col4_neon |
329 |
bl idct_col4_add8_neon |
330 |
|
331 |
idct_end |
332 |
endfunc |
333 |
|
334 |
.align 6 |
335 |
|
336 |
function idct_col4_st16_neon |
337 |
mov ip, #16 |
338 |
|
339 |
vshr.s16 q1, q1, #COL_SHIFT-16 |
340 |
vshr.s16 q2, q2, #COL_SHIFT-16 |
341 |
vst1.64 {d2}, [r2,:64], ip |
342 |
vshr.s16 q3, q3, #COL_SHIFT-16 |
343 |
vst1.64 {d3}, [r2,:64], ip |
344 |
vshr.s16 q4, q4, #COL_SHIFT-16 |
345 |
vst1.64 {d4}, [r2,:64], ip |
346 |
vst1.64 {d5}, [r2,:64], ip |
347 |
vst1.64 {d6}, [r2,:64], ip |
348 |
vst1.64 {d7}, [r2,:64], ip |
349 |
vst1.64 {d8}, [r2,:64], ip |
350 |
vst1.64 {d9}, [r2,:64], ip |
351 |
|
352 |
bx lr |
353 |
endfunc |
354 |
|
355 |
/* void ff_simple_idct_neon(DCTELEM *data); */ |
356 |
function ff_simple_idct_neon, export=1 |
357 |
idct_start r0 |
358 |
|
359 |
mov r2, r0 |
360 |
bl idct_row4_neon |
361 |
bl idct_row4_neon |
362 |
add r2, r2, #-128 |
363 |
bl idct_col4_neon |
364 |
add r2, r2, #-128 |
365 |
bl idct_col4_st16_neon |
366 |
add r2, r2, #-120 |
367 |
bl idct_col4_neon |
368 |
add r2, r2, #-128 |
369 |
bl idct_col4_st16_neon |
370 |
|
371 |
idct_end |
372 |
endfunc |