ARM: rename coefficient table in NEON IDCT
[libav.git] / libavcodec / arm / simple_idct_neon.S
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 .fpu neon
49
50 .macro idct_col4_top
51 vmull.s16 q7, d6, w2 /* q9 = W2 * col[2] */
52 vmull.s16 q8, d6, w6 /* q10 = W6 * col[2] */
53 vmull.s16 q9, d4, w1 /* q9 = W1 * col[1] */
54 vadd.i32 q11, q15, q7
55 vmull.s16 q10, d4, w3 /* q10 = W3 * col[1] */
56 vadd.i32 q12, q15, q8
57 vmull.s16 q5, d4, w5 /* q5 = W5 * col[1] */
58 vsub.i32 q13, q15, q8
59 vmull.s16 q6, d4, w7 /* q6 = W7 * col[1] */
60 vsub.i32 q14, q15, q7
61
62 vmlal.s16 q9, d8, w3 /* q9 += W3 * col[3] */
63 vmlsl.s16 q10, d8, w7 /* q10 -= W7 * col[3] */
64 vmlsl.s16 q5, d8, w1 /* q5 -= W1 * col[3] */
65 vmlsl.s16 q6, d8, w5 /* q6 -= W5 * col[3] */
66 .endm
67
68 .text
69 .align 6
70
71 function idct_row4_neon
72 vmov.i32 q15, #(1<<(ROW_SHIFT-1))
73 vld1.64 {d2-d5}, [r2,:128]!
74 vmlal.s16 q15, d2, w4 /* q15 += W4 * col[0] */
75 vld1.64 {d6,d7}, [r2,:128]!
76 vorr d10, d3, d5
77 vld1.64 {d8,d9}, [r2,:128]!
78 add r2, r2, #-64
79
80 vorr d11, d7, d9
81 vorr d10, d10, d11
82 vmov r3, r4, d10
83
84 idct_col4_top
85
86 orrs r3, r3, r4
87 beq 1f
88
89 vmull.s16 q7, d3, w4 /* q7 = W4 * col[4] */
90 vmlal.s16 q9, d5, w5 /* q9 += W5 * col[5] */
91 vmlsl.s16 q10, d5, w1 /* q10 -= W1 * col[5] */
92 vmull.s16 q8, d7, w2 /* q8 = W2 * col[6] */
93 vmlal.s16 q5, d5, w7 /* q5 += W7 * col[5] */
94 vadd.i32 q11, q11, q7
95 vsub.i32 q12, q12, q7
96 vsub.i32 q13, q13, q7
97 vadd.i32 q14, q14, q7
98 vmlal.s16 q6, d5, w3 /* q6 += W3 * col[5] */
99 vmull.s16 q7, d7, w6 /* q7 = W6 * col[6] */
100 vmlal.s16 q9, d9, w7
101 vmlsl.s16 q10, d9, w5
102 vmlal.s16 q5, d9, w3
103 vmlsl.s16 q6, d9, w1
104 vadd.i32 q11, q11, q7
105 vsub.i32 q12, q12, q8
106 vadd.i32 q13, q13, q8
107 vsub.i32 q14, q14, q7
108
109 1: vadd.i32 q3, q11, q9
110 vadd.i32 q4, q12, q10
111 vshrn.i32 d2, q3, #ROW_SHIFT
112 vshrn.i32 d4, q4, #ROW_SHIFT
113 vadd.i32 q7, q13, q5
114 vadd.i32 q8, q14, q6
115 vtrn.16 d2, d4
116 vshrn.i32 d6, q7, #ROW_SHIFT
117 vshrn.i32 d8, q8, #ROW_SHIFT
118 vsub.i32 q14, q14, q6
119 vsub.i32 q11, q11, q9
120 vtrn.16 d6, d8
121 vsub.i32 q13, q13, q5
122 vshrn.i32 d3, q14, #ROW_SHIFT
123 vtrn.32 d2, d6
124 vsub.i32 q12, q12, q10
125 vtrn.32 d4, d8
126 vshrn.i32 d5, q13, #ROW_SHIFT
127 vshrn.i32 d7, q12, #ROW_SHIFT
128 vshrn.i32 d9, q11, #ROW_SHIFT
129
130 vtrn.16 d3, d5
131 vtrn.16 d7, d9
132 vtrn.32 d3, d7
133 vtrn.32 d5, d9
134
135 vst1.64 {d2-d5}, [r2,:128]!
136 vst1.64 {d6-d9}, [r2,:128]!
137
138 bx lr
139 .endfunc
140
141 function idct_col4_neon
142 mov ip, #16
143 vld1.64 {d2}, [r2,:64], ip /* d2 = col[0] */
144 vdup.16 d30, w4c
145 vld1.64 {d4}, [r2,:64], ip /* d3 = col[1] */
146 vadd.i16 d30, d30, d2
147 vld1.64 {d6}, [r2,:64], ip /* d4 = col[2] */
148 vmull.s16 q15, d30, w4 /* q15 = W4*(col[0]+(1<<COL_SHIFT-1)/W4)*/
149 vld1.64 {d8}, [r2,:64], ip /* d5 = col[3] */
150
151 ldrd r4, [r2]
152 ldrd r6, [r2, #16]
153 orrs r4, r4, r5
154
155 idct_col4_top
156 addeq r2, r2, #16
157 beq 1f
158
159 vld1.64 {d3}, [r2,:64], ip /* d6 = col[4] */
160 vmull.s16 q7, d3, w4 /* q7 = W4 * col[4] */
161 vadd.i32 q11, q11, q7
162 vsub.i32 q12, q12, q7
163 vsub.i32 q13, q13, q7
164 vadd.i32 q14, q14, q7
165
166 1: orrs r6, r6, r7
167 ldrd r4, [r2, #16]
168 addeq r2, r2, #16
169 beq 2f
170
171 vld1.64 {d5}, [r2,:64], ip /* d7 = col[5] */
172 vmlal.s16 q9, d5, w5 /* q9 += W5 * col[5] */
173 vmlsl.s16 q10, d5, w1 /* q10 -= W1 * col[5] */
174 vmlal.s16 q5, d5, w7 /* q5 += W7 * col[5] */
175 vmlal.s16 q6, d5, w3 /* q6 += W3 * col[5] */
176
177 2: orrs r4, r4, r5
178 ldrd r4, [r2, #16]
179 addeq r2, r2, #16
180 beq 3f
181
182 vld1.64 {d7}, [r2,:64], ip /* d8 = col[6] */
183 vmull.s16 q7, d7, w6 /* q7 = W6 * col[6] */
184 vmull.s16 q8, d7, w2 /* q8 = W2 * col[6] */
185 vadd.i32 q11, q11, q7
186 vsub.i32 q14, q14, q7
187 vsub.i32 q12, q12, q8
188 vadd.i32 q13, q13, q8
189
190 3: orrs r4, r4, r5
191 addeq r2, r2, #16
192 beq 4f
193
194 vld1.64 {d9}, [r2,:64], ip /* d9 = col[7] */
195 vmlal.s16 q9, d9, w7
196 vmlsl.s16 q10, d9, w5
197 vmlal.s16 q5, d9, w3
198 vmlsl.s16 q6, d9, w1
199
200 4: vaddhn.i32 d2, q11, q9
201 vaddhn.i32 d3, q12, q10
202 vaddhn.i32 d4, q13, q5
203 vaddhn.i32 d5, q14, q6
204 vsubhn.i32 d9, q11, q9
205 vsubhn.i32 d8, q12, q10
206 vsubhn.i32 d7, q13, q5
207 vsubhn.i32 d6, q14, q6
208
209 bx lr
210 .endfunc
211
212 .align 6
213
214 function idct_col4_st8_neon
215 vqshrun.s16 d2, q1, #COL_SHIFT-16
216 vqshrun.s16 d3, q2, #COL_SHIFT-16
217 vqshrun.s16 d4, q3, #COL_SHIFT-16
218 vqshrun.s16 d5, q4, #COL_SHIFT-16
219 vst1.32 {d2[0]}, [r0,:32], r1
220 vst1.32 {d2[1]}, [r0,:32], r1
221 vst1.32 {d3[0]}, [r0,:32], r1
222 vst1.32 {d3[1]}, [r0,:32], r1
223 vst1.32 {d4[0]}, [r0,:32], r1
224 vst1.32 {d4[1]}, [r0,:32], r1
225 vst1.32 {d5[0]}, [r0,:32], r1
226 vst1.32 {d5[1]}, [r0,:32], r1
227
228 bx lr
229 .endfunc
230
231 .section .rodata
232 .align 4
233 idct_coeff_neon:
234 .short W1, W2, W3, W4, W5, W6, W7, W4c
235 .previous
236
237 .macro idct_start data
238 push {r4-r7, lr}
239 pld [\data]
240 pld [\data, #64]
241 vpush {d8-d15}
242 movw r3, #:lower16:idct_coeff_neon
243 movt r3, #:upper16:idct_coeff_neon
244 vld1.64 {d0,d1}, [r3,:128]
245 .endm
246
247 .macro idct_end
248 vpop {d8-d15}
249 pop {r4-r7, pc}
250 .endm
251
252 /* void ff_simple_idct_put_neon(uint8_t *dst, int line_size, DCTELEM *data); */
253 function ff_simple_idct_put_neon, export=1
254 idct_start r2
255
256 bl idct_row4_neon
257 bl idct_row4_neon
258 add r2, r2, #-128
259 bl idct_col4_neon
260 bl idct_col4_st8_neon
261 sub r0, r0, r1, lsl #3
262 add r0, r0, #4
263 add r2, r2, #-120
264 bl idct_col4_neon
265 bl idct_col4_st8_neon
266
267 idct_end
268 .endfunc
269
270 .align 6
271
272 function idct_col4_add8_neon
273 mov ip, r0
274
275 vld1.32 {d10[0]}, [r0,:32], r1
276 vshr.s16 q1, q1, #COL_SHIFT-16
277 vld1.32 {d10[1]}, [r0,:32], r1
278 vshr.s16 q2, q2, #COL_SHIFT-16
279 vld1.32 {d11[0]}, [r0,:32], r1
280 vshr.s16 q3, q3, #COL_SHIFT-16
281 vld1.32 {d11[1]}, [r0,:32], r1
282 vshr.s16 q4, q4, #COL_SHIFT-16
283 vld1.32 {d12[0]}, [r0,:32], r1
284 vaddw.u8 q1, q1, d10
285 vld1.32 {d12[1]}, [r0,:32], r1
286 vaddw.u8 q2, q2, d11
287 vld1.32 {d13[0]}, [r0,:32], r1
288 vqmovun.s16 d2, q1
289 vld1.32 {d13[1]}, [r0,:32], r1
290 vaddw.u8 q3, q3, d12
291 vst1.32 {d2[0]}, [ip,:32], r1
292 vqmovun.s16 d3, q2
293 vst1.32 {d2[1]}, [ip,:32], r1
294 vaddw.u8 q4, q4, d13
295 vst1.32 {d3[0]}, [ip,:32], r1
296 vqmovun.s16 d4, q3
297 vst1.32 {d3[1]}, [ip,:32], r1
298 vqmovun.s16 d5, q4
299 vst1.32 {d4[0]}, [ip,:32], r1
300 vst1.32 {d4[1]}, [ip,:32], r1
301 vst1.32 {d5[0]}, [ip,:32], r1
302 vst1.32 {d5[1]}, [ip,:32], r1
303
304 bx lr
305 .endfunc
306
307 /* void ff_simple_idct_add_neon(uint8_t *dst, int line_size, DCTELEM *data); */
308 function ff_simple_idct_add_neon, export=1
309 idct_start r2
310
311 bl idct_row4_neon
312 bl idct_row4_neon
313 add r2, r2, #-128
314 bl idct_col4_neon
315 bl idct_col4_add8_neon
316 sub r0, r0, r1, lsl #3
317 add r0, r0, #4
318 add r2, r2, #-120
319 bl idct_col4_neon
320 bl idct_col4_add8_neon
321
322 idct_end
323 .endfunc
324
325 .align 6
326
327 function idct_col4_st16_neon
328 mov ip, #16
329
330 vshr.s16 q1, q1, #COL_SHIFT-16
331 vshr.s16 q2, q2, #COL_SHIFT-16
332 vst1.64 {d2}, [r2,:64], ip
333 vshr.s16 q3, q3, #COL_SHIFT-16
334 vst1.64 {d3}, [r2,:64], ip
335 vshr.s16 q4, q4, #COL_SHIFT-16
336 vst1.64 {d4}, [r2,:64], ip
337 vst1.64 {d5}, [r2,:64], ip
338 vst1.64 {d6}, [r2,:64], ip
339 vst1.64 {d7}, [r2,:64], ip
340 vst1.64 {d8}, [r2,:64], ip
341 vst1.64 {d9}, [r2,:64], ip
342
343 bx lr
344 .endfunc
345
346 /* void ff_simple_idct_neon(DCTELEM *data); */
347 function ff_simple_idct_neon, export=1
348 idct_start r0
349
350 mov r2, r0
351 bl idct_row4_neon
352 bl idct_row4_neon
353 add r2, r2, #-128
354 bl idct_col4_neon
355 add r2, r2, #-128
356 bl idct_col4_st16_neon
357 add r2, r2, #-120
358 bl idct_col4_neon
359 add r2, r2, #-128
360 bl idct_col4_st16_neon
361
362 idct_end
363 .endfunc