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