b2e16f4629a50d31c691fc58e2b280aff4e5be06
[libav.git] / libavcodec / arm / vp3dsp_neon.S
1 /*
2 * Copyright (c) 2009 David Conrad
3 *
4 * This file is part of FFmpeg.
5 *
6 * FFmpeg 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 * FFmpeg 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 FFmpeg; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19 */
20
21 #include "asm.S"
22
23 .section .rodata
24 .align 4
25
26 vp3_idct_constants:
27 .short 64277, 60547, 54491, 46341, 36410, 25080, 12785
28
29 #define xC1S7 d0[0]
30 #define xC2S6 d0[1]
31 #define xC3S5 d0[2]
32 #define xC4S4 d0[3]
33 #define xC5S3 d1[0]
34 #define xC6S2 d1[1]
35 #define xC7S1 d1[2]
36
37 .text
38
39 .macro vp3_loop_filter
40 vsubl.u8 q3, d18, d17
41 vsubl.u8 q2, d16, d19
42 vadd.i16 q1, q3, q3
43 vadd.i16 q2, q2, q3
44 vadd.i16 q0, q1, q2
45 vrshr.s16 q0, q0, #3
46 vmovl.u8 q9, d18
47 vdup.u16 q15, r2
48
49 vabs.s16 q1, q0
50 vshr.s16 q0, q0, #15
51 vqsub.u16 q2, q15, q1
52 vqsub.u16 q3, q2, q1
53 vsub.i16 q1, q2, q3
54 veor q1, q1, q0
55 vsub.i16 q0, q1, q0
56
57 vaddw.u8 q2, q0, d17
58 vsub.i16 q3, q9, q0
59 vqmovun.s16 d0, q2
60 vqmovun.s16 d1, q3
61 .endm
62
63 function ff_vp3_v_loop_filter_neon, export=1
64 sub ip, r0, r1
65 sub r0, r0, r1, lsl #1
66 vld1.64 {d16}, [r0,:64], r1
67 vld1.64 {d17}, [r0,:64], r1
68 vld1.64 {d18}, [r0,:64], r1
69 vld1.64 {d19}, [r0,:64], r1
70 ldrb r2, [r2, #129*4]
71
72 vp3_loop_filter
73
74 vst1.64 {d0}, [ip,:64], r1
75 vst1.64 {d1}, [ip,:64], r1
76 bx lr
77 .endfunc
78
79 function ff_vp3_h_loop_filter_neon, export=1
80 sub ip, r0, #1
81 sub r0, r0, #2
82 vld1.32 {d16[]}, [r0], r1
83 vld1.32 {d17[]}, [r0], r1
84 vld1.32 {d18[]}, [r0], r1
85 vld1.32 {d19[]}, [r0], r1
86 vld1.32 {d16[1]}, [r0], r1
87 vld1.32 {d17[1]}, [r0], r1
88 vld1.32 {d18[1]}, [r0], r1
89 vld1.32 {d19[1]}, [r0], r1
90 ldrb r2, [r2, #129*4]
91
92 vtrn.8 d16, d17
93 vtrn.8 d18, d19
94 vtrn.16 d16, d18
95 vtrn.16 d17, d19
96
97 vp3_loop_filter
98
99 vtrn.8 d0, d1
100
101 vst1.16 {d0[0]}, [ip], r1
102 vst1.16 {d1[0]}, [ip], r1
103 vst1.16 {d0[1]}, [ip], r1
104 vst1.16 {d1[1]}, [ip], r1
105 vst1.16 {d0[2]}, [ip], r1
106 vst1.16 {d1[2]}, [ip], r1
107 vst1.16 {d0[3]}, [ip], r1
108 vst1.16 {d1[3]}, [ip], r1
109 bx lr
110 .endfunc
111
112
113 function vp3_idct_start_neon
114 vpush {d8-d15}
115 movrel r3, vp3_idct_constants
116 vld1.64 {d0-d1}, [r3,:128]
117 vld1.64 {d16-d19}, [r2,:128]!
118 vld1.64 {d20-d23}, [r2,:128]!
119 vld1.64 {d24-d27}, [r2,:128]!
120 vadd.s16 q1, q8, q12
121 vsub.s16 q8, q8, q12
122 vld1.64 {d28-d31}, [r2,:128]!
123 .endfunc
124
125 function vp3_idct_core_neon
126 vmull.s16 q2, d18, xC1S7 // (ip[1] * C1) << 16
127 vmull.s16 q3, d19, xC1S7
128 vmull.s16 q4, d2, xC4S4 // ((ip[0] + ip[4]) * C4) << 16
129 vmull.s16 q5, d3, xC4S4
130 vmull.s16 q6, d16, xC4S4 // ((ip[0] - ip[4]) * C4) << 16
131 vmull.s16 q7, d17, xC4S4
132 vshrn.s32 d4, q2, #16
133 vshrn.s32 d5, q3, #16
134 vshrn.s32 d6, q4, #16
135 vshrn.s32 d7, q5, #16
136 vshrn.s32 d8, q6, #16
137 vshrn.s32 d9, q7, #16
138 vadd.s16 q12, q1, q3 // E = (ip[0] + ip[4]) * C4
139 vadd.s16 q8, q8, q4 // F = (ip[0] - ip[4]) * C4
140 vadd.s16 q1, q2, q9 // ip[1] * C1
141
142 vmull.s16 q2, d30, xC1S7 // (ip[7] * C1) << 16
143 vmull.s16 q3, d31, xC1S7
144 vmull.s16 q4, d30, xC7S1 // (ip[7] * C7) << 16
145 vmull.s16 q5, d31, xC7S1
146 vmull.s16 q6, d18, xC7S1 // (ip[1] * C7) << 16
147 vmull.s16 q7, d19, xC7S1
148 vshrn.s32 d4, q2, #16
149 vshrn.s32 d5, q3, #16
150 vshrn.s32 d6, q4, #16 // ip[7] * C7
151 vshrn.s32 d7, q5, #16
152 vshrn.s32 d8, q6, #16 // ip[1] * C7
153 vshrn.s32 d9, q7, #16
154 vadd.s16 q2, q2, q15 // ip[7] * C1
155 vadd.s16 q9, q1, q3 // A = ip[1] * C1 + ip[7] * C7
156 vsub.s16 q15, q4, q2 // B = ip[1] * C7 - ip[7] * C1
157
158 vmull.s16 q2, d22, xC5S3 // (ip[3] * C5) << 16
159 vmull.s16 q3, d23, xC5S3
160 vmull.s16 q4, d22, xC3S5 // (ip[3] * C3) << 16
161 vmull.s16 q5, d23, xC3S5
162 vmull.s16 q6, d26, xC5S3 // (ip[5] * C5) << 16
163 vmull.s16 q7, d27, xC5S3
164 vshrn.s32 d4, q2, #16
165 vshrn.s32 d5, q3, #16
166 vshrn.s32 d6, q4, #16
167 vshrn.s32 d7, q5, #16
168 vshrn.s32 d8, q6, #16
169 vshrn.s32 d9, q7, #16
170 vadd.s16 q3, q3, q11 // ip[3] * C3
171 vadd.s16 q4, q4, q13 // ip[5] * C5
172 vadd.s16 q1, q2, q11 // ip[3] * C5
173 vadd.s16 q11, q3, q4 // C = ip[3] * C3 + ip[5] * C5
174
175 vmull.s16 q2, d26, xC3S5 // (ip[5] * C3) << 16
176 vmull.s16 q3, d27, xC3S5
177 vmull.s16 q4, d20, xC2S6 // (ip[2] * C2) << 16
178 vmull.s16 q5, d21, xC2S6
179 vmull.s16 q6, d28, xC6S2 // (ip[6] * C6) << 16
180 vmull.s16 q7, d29, xC6S2
181 vshrn.s32 d4, q2, #16
182 vshrn.s32 d5, q3, #16
183 vshrn.s32 d6, q4, #16
184 vshrn.s32 d7, q5, #16
185 vshrn.s32 d8, q6, #16 // ip[6] * C6
186 vshrn.s32 d9, q7, #16
187 vadd.s16 q2, q2, q13 // ip[5] * C3
188 vadd.s16 q3, q3, q10 // ip[2] * C2
189 vsub.s16 q13, q2, q1 // D = ip[5] * C3 - ip[3] * C5
190 vsub.s16 q1, q9, q11 // (A - C)
191 vadd.s16 q11, q9, q11 // Cd = A + C
192 vsub.s16 q9, q15, q13 // (B - D)
193 vadd.s16 q13, q15, q13 // Dd = B + D
194 vadd.s16 q15, q3, q4 // G = ip[2] * C2 + ip[6] * C6
195
196 vmull.s16 q2, d2, xC4S4 // ((A - C) * C4) << 16
197 vmull.s16 q3, d3, xC4S4
198 vmull.s16 q4, d28, xC2S6 // (ip[6] * C2) << 16
199 vmull.s16 q5, d29, xC2S6
200 vmull.s16 q6, d20, xC6S2 // (ip[2] * C6) << 16
201 vmull.s16 q7, d21, xC6S2
202 vshrn.s32 d4, q2, #16
203 vshrn.s32 d5, q3, #16
204 vshrn.s32 d6, q4, #16
205 vshrn.s32 d7, q5, #16
206 vshrn.s32 d8, q6, #16 // ip[2] * C6
207 vmull.s16 q5, d18, xC4S4 // ((B - D) * C4) << 16
208 vmull.s16 q6, d19, xC4S4
209 vshrn.s32 d9, q7, #16
210 vadd.s16 q3, q3, q14 // ip[6] * C2
211 vadd.s16 q10, q1, q2 // Ad = (A - C) * C4
212 vsub.s16 q14, q4, q3 // H = ip[2] * C6 - ip[6] * C2
213 bx lr
214 .endfunc
215
216 .macro VP3_IDCT_END type
217 function vp3_idct_end_\type\()_neon
218 .ifc \type, col
219 vdup.16 q0, r3
220 vadd.s16 q12, q12, q0
221 vadd.s16 q8, q8, q0
222 .endif
223
224 vshrn.s32 d2, q5, #16
225 vshrn.s32 d3, q6, #16
226 vadd.s16 q2, q12, q15 // Gd = E + G
227 vadd.s16 q9, q1, q9 // (B - D) * C4
228 vsub.s16 q12, q12, q15 // Ed = E - G
229 vsub.s16 q3, q8, q10 // Fd = F - Ad
230 vadd.s16 q10, q8, q10 // Add = F + Ad
231 vadd.s16 q4, q9, q14 // Hd = Bd + H
232 vsub.s16 q14, q9, q14 // Bdd = Bd - H
233 vadd.s16 q8, q2, q11 // [0] = Gd + Cd
234 vsub.s16 q15, q2, q11 // [7] = Gd - Cd
235 vadd.s16 q9, q10, q4 // [1] = Add + Hd
236 vsub.s16 q10, q10, q4 // [2] = Add - Hd
237 vadd.s16 q11, q12, q13 // [3] = Ed + Dd
238 vsub.s16 q12, q12, q13 // [4] = Ed - Dd
239 .ifc \type, row
240 vtrn.16 q8, q9
241 .endif
242 vadd.s16 q13, q3, q14 // [5] = Fd + Bdd
243 vsub.s16 q14, q3, q14 // [6] = Fd - Bdd
244
245 .ifc \type, row
246 // 8x8 transpose
247 vtrn.16 q10, q11
248 vtrn.16 q12, q13
249 vtrn.16 q14, q15
250 vtrn.32 q8, q10
251 vtrn.32 q9, q11
252 vtrn.32 q12, q14
253 vtrn.32 q13, q15
254 vswp d17, d24
255 vswp d19, d26
256 vadd.s16 q1, q8, q12
257 vswp d21, d28
258 vsub.s16 q8, q8, q12
259 vswp d23, d30
260 .endif
261 bx lr
262 .endfunc
263 .endm
264
265 VP3_IDCT_END row
266 VP3_IDCT_END col
267
268 function ff_vp3_idct_neon, export=1
269 mov ip, lr
270 mov r2, r0
271 bl vp3_idct_start_neon
272 bl vp3_idct_end_row_neon
273 mov r3, #8
274 bl vp3_idct_core_neon
275 bl vp3_idct_end_col_neon
276 mov lr, ip
277 vpop {d8-d15}
278
279 vshr.s16 q8, q8, #4
280 vshr.s16 q9, q9, #4
281 vshr.s16 q10, q10, #4
282 vshr.s16 q11, q11, #4
283 vshr.s16 q12, q12, #4
284 vst1.64 {d16-d19}, [r0,:128]!
285 vshr.s16 q13, q13, #4
286 vshr.s16 q14, q14, #4
287 vst1.64 {d20-d23}, [r0,:128]!
288 vshr.s16 q15, q15, #4
289 vst1.64 {d24-d27}, [r0,:128]!
290 vst1.64 {d28-d31}, [r0,:128]!
291 bx lr
292 .endfunc
293
294 function ff_vp3_idct_put_neon, export=1
295 mov ip, lr
296 bl vp3_idct_start_neon
297 bl vp3_idct_end_row_neon
298 mov r3, #8
299 add r3, r3, #2048 // convert signed pixel to unsigned
300 bl vp3_idct_core_neon
301 bl vp3_idct_end_col_neon
302 mov lr, ip
303 vpop {d8-d15}
304
305 vqshrun.s16 d0, q8, #4
306 vqshrun.s16 d1, q9, #4
307 vqshrun.s16 d2, q10, #4
308 vqshrun.s16 d3, q11, #4
309 vst1.64 {d0}, [r0,:64], r1
310 vqshrun.s16 d4, q12, #4
311 vst1.64 {d1}, [r0,:64], r1
312 vqshrun.s16 d5, q13, #4
313 vst1.64 {d2}, [r0,:64], r1
314 vqshrun.s16 d6, q14, #4
315 vst1.64 {d3}, [r0,:64], r1
316 vqshrun.s16 d7, q15, #4
317 vst1.64 {d4}, [r0,:64], r1
318 vst1.64 {d5}, [r0,:64], r1
319 vst1.64 {d6}, [r0,:64], r1
320 vst1.64 {d7}, [r0,:64], r1
321 bx lr
322 .endfunc
323
324 function ff_vp3_idct_add_neon, export=1
325 mov ip, lr
326 bl vp3_idct_start_neon
327 bl vp3_idct_end_row_neon
328 mov r3, #8
329 bl vp3_idct_core_neon
330 bl vp3_idct_end_col_neon
331 mov lr, ip
332 vpop {d8-d15}
333 mov r2, r0
334
335 vld1.64 {d0}, [r0,:64], r1
336 vshr.s16 q8, q8, #4
337 vld1.64 {d1}, [r0,:64], r1
338 vshr.s16 q9, q9, #4
339 vld1.64 {d2}, [r0,:64], r1
340 vaddw.u8 q8, q8, d0
341 vld1.64 {d3}, [r0,:64], r1
342 vaddw.u8 q9, q9, d1
343 vld1.64 {d4}, [r0,:64], r1
344 vshr.s16 q10, q10, #4
345 vld1.64 {d5}, [r0,:64], r1
346 vshr.s16 q11, q11, #4
347 vld1.64 {d6}, [r0,:64], r1
348 vqmovun.s16 d0, q8
349 vld1.64 {d7}, [r0,:64], r1
350 vqmovun.s16 d1, q9
351 vaddw.u8 q10, q10, d2
352 vaddw.u8 q11, q11, d3
353 vshr.s16 q12, q12, #4
354 vshr.s16 q13, q13, #4
355 vqmovun.s16 d2, q10
356 vqmovun.s16 d3, q11
357 vaddw.u8 q12, q12, d4
358 vaddw.u8 q13, q13, d5
359 vshr.s16 q14, q14, #4
360 vshr.s16 q15, q15, #4
361 vst1.64 {d0}, [r2,:64], r1
362 vqmovun.s16 d4, q12
363 vst1.64 {d1}, [r2,:64], r1
364 vqmovun.s16 d5, q13
365 vst1.64 {d2}, [r2,:64], r1
366 vaddw.u8 q14, q14, d6
367 vst1.64 {d3}, [r2,:64], r1
368 vaddw.u8 q15, q15, d7
369 vst1.64 {d4}, [r2,:64], r1
370 vqmovun.s16 d6, q14
371 vst1.64 {d5}, [r2,:64], r1
372 vqmovun.s16 d7, q15
373 vst1.64 {d6}, [r2,:64], r1
374 vst1.64 {d7}, [r2,:64], r1
375 bx lr
376 .endfunc