ARM: work around linker bug with movw/movt relocations in shared libs
[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         movrel          r3,  idct_coeff_neon
243         vld1.64         {d0,d1}, [r3,:128]
244         .endm
245
246         .macro idct_end
247         vpop            {d8-d15}
248         pop             {r4-r7, pc}
249         .endm
250
251 /* void ff_simple_idct_put_neon(uint8_t *dst, int line_size, DCTELEM *data); */
252 function ff_simple_idct_put_neon, export=1
253         idct_start      r2
254
255         bl              idct_row4_neon
256         bl              idct_row4_neon
257         add             r2,  r2,  #-128
258         bl              idct_col4_neon
259         bl              idct_col4_st8_neon
260         sub             r0,  r0,  r1, lsl #3
261         add             r0,  r0,  #4
262         add             r2,  r2,  #-120
263         bl              idct_col4_neon
264         bl              idct_col4_st8_neon
265
266         idct_end
267         .endfunc
268
269         .align 6
270
271 function idct_col4_add8_neon
272         mov             ip,  r0
273
274         vld1.32         {d10[0]}, [r0,:32], r1
275         vshr.s16        q1,  q1,  #COL_SHIFT-16
276         vld1.32         {d10[1]}, [r0,:32], r1
277         vshr.s16        q2,  q2,  #COL_SHIFT-16
278         vld1.32         {d11[0]}, [r0,:32], r1
279         vshr.s16        q3,  q3,  #COL_SHIFT-16
280         vld1.32         {d11[1]}, [r0,:32], r1
281         vshr.s16        q4,  q4,  #COL_SHIFT-16
282         vld1.32         {d12[0]}, [r0,:32], r1
283         vaddw.u8        q1,  q1,  d10
284         vld1.32         {d12[1]}, [r0,:32], r1
285         vaddw.u8        q2,  q2,  d11
286         vld1.32         {d13[0]}, [r0,:32], r1
287         vqmovun.s16     d2,  q1
288         vld1.32         {d13[1]}, [r0,:32], r1
289         vaddw.u8        q3,  q3,  d12
290         vst1.32         {d2[0]},  [ip,:32], r1
291         vqmovun.s16     d3,  q2
292         vst1.32         {d2[1]},  [ip,:32], r1
293         vaddw.u8        q4,  q4,  d13
294         vst1.32         {d3[0]},  [ip,:32], r1
295         vqmovun.s16     d4,  q3
296         vst1.32         {d3[1]},  [ip,:32], r1
297         vqmovun.s16     d5,  q4
298         vst1.32         {d4[0]},  [ip,:32], r1
299         vst1.32         {d4[1]},  [ip,:32], r1
300         vst1.32         {d5[0]},  [ip,:32], r1
301         vst1.32         {d5[1]},  [ip,:32], r1
302
303         bx              lr
304         .endfunc
305
306 /* void ff_simple_idct_add_neon(uint8_t *dst, int line_size, DCTELEM *data); */
307 function ff_simple_idct_add_neon, export=1
308         idct_start      r2
309
310         bl              idct_row4_neon
311         bl              idct_row4_neon
312         add             r2,  r2,  #-128
313         bl              idct_col4_neon
314         bl              idct_col4_add8_neon
315         sub             r0,  r0,  r1, lsl #3
316         add             r0,  r0,  #4
317         add             r2,  r2,  #-120
318         bl              idct_col4_neon
319         bl              idct_col4_add8_neon
320
321         idct_end
322         .endfunc
323
324         .align 6
325
326 function idct_col4_st16_neon
327         mov             ip,  #16
328
329         vshr.s16        q1,  q1,  #COL_SHIFT-16
330         vshr.s16        q2,  q2,  #COL_SHIFT-16
331         vst1.64         {d2}, [r2,:64], ip
332         vshr.s16        q3,  q3,  #COL_SHIFT-16
333         vst1.64         {d3}, [r2,:64], ip
334         vshr.s16        q4,  q4,  #COL_SHIFT-16
335         vst1.64         {d4}, [r2,:64], ip
336         vst1.64         {d5}, [r2,:64], ip
337         vst1.64         {d6}, [r2,:64], ip
338         vst1.64         {d7}, [r2,:64], ip
339         vst1.64         {d8}, [r2,:64], ip
340         vst1.64         {d9}, [r2,:64], ip
341
342         bx              lr
343         .endfunc
344
345 /* void ff_simple_idct_neon(DCTELEM *data); */
346 function ff_simple_idct_neon, export=1
347         idct_start      r0
348
349         mov             r2,  r0
350         bl              idct_row4_neon
351         bl              idct_row4_neon
352         add             r2,  r2,  #-128
353         bl              idct_col4_neon
354         add             r2,  r2,  #-128
355         bl              idct_col4_st16_neon
356         add             r2,  r2,  #-120
357         bl              idct_col4_neon
358         add             r2,  r2,  #-128
359         bl              idct_col4_st16_neon
360
361         idct_end
362         .endfunc