ARM: rename coefficient table in NEON IDCT
[ffmpeg.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