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_neon, export=1
264     mov             ip,  lr
265     mov             r2,  r0
266     bl              vp3_idct_start_neon
267     bl              vp3_idct_end_row_neon
268     mov             r3,  #8
269     bl              vp3_idct_core_neon
270     bl              vp3_idct_end_col_neon
271     mov             lr,  ip
272     vpop            {d8-d15}
273
274     vshr.s16        q8,  q8,  #4
275     vshr.s16        q9,  q9,  #4
276     vshr.s16        q10, q10, #4
277     vshr.s16        q11, q11, #4
278     vshr.s16        q12, q12, #4
279     vst1.64         {d16-d19}, [r0,:128]!
280     vshr.s16        q13, q13, #4
281     vshr.s16        q14, q14, #4
282     vst1.64         {d20-d23}, [r0,:128]!
283     vshr.s16        q15, q15, #4
284     vst1.64         {d24-d27}, [r0,:128]!
285     vst1.64         {d28-d31}, [r0,:128]!
286     bx              lr
287 endfunc
288
289 function ff_vp3_idct_put_neon, export=1
290     mov             ip,  lr
291     bl              vp3_idct_start_neon
292     bl              vp3_idct_end_row_neon
293     mov             r3,  #8
294     add             r3,  r3,  #2048         // convert signed pixel to unsigned
295     bl              vp3_idct_core_neon
296     bl              vp3_idct_end_col_neon
297     mov             lr,  ip
298     vpop            {d8-d15}
299
300     vqshrun.s16     d0,  q8,  #4
301     vqshrun.s16     d1,  q9,  #4
302     vqshrun.s16     d2,  q10, #4
303     vqshrun.s16     d3,  q11, #4
304     vst1.64         {d0}, [r0,:64], r1
305     vqshrun.s16     d4,  q12, #4
306     vst1.64         {d1}, [r0,:64], r1
307     vqshrun.s16     d5,  q13, #4
308     vst1.64         {d2}, [r0,:64], r1
309     vqshrun.s16     d6,  q14, #4
310     vst1.64         {d3}, [r0,:64], r1
311     vqshrun.s16     d7,  q15, #4
312     vst1.64         {d4}, [r0,:64], r1
313     vst1.64         {d5}, [r0,:64], r1
314     vst1.64         {d6}, [r0,:64], r1
315     vst1.64         {d7}, [r0,:64], r1
316     bx              lr
317 endfunc
318
319 function ff_vp3_idct_add_neon, export=1
320     mov             ip,  lr
321     bl              vp3_idct_start_neon
322     bl              vp3_idct_end_row_neon
323     mov             r3,  #8
324     bl              vp3_idct_core_neon
325     bl              vp3_idct_end_col_neon
326     mov             lr,  ip
327     vpop            {d8-d15}
328     mov             r2,  r0
329
330     vld1.64         {d0}, [r0,:64], r1
331     vshr.s16        q8,  q8,  #4
332     vld1.64         {d1}, [r0,:64], r1
333     vshr.s16        q9,  q9,  #4
334     vld1.64         {d2}, [r0,:64], r1
335     vaddw.u8        q8,  q8,  d0
336     vld1.64         {d3}, [r0,:64], r1
337     vaddw.u8        q9,  q9,  d1
338     vld1.64         {d4}, [r0,:64], r1
339     vshr.s16        q10, q10, #4
340     vld1.64         {d5}, [r0,:64], r1
341     vshr.s16        q11, q11, #4
342     vld1.64         {d6}, [r0,:64], r1
343     vqmovun.s16     d0,  q8
344     vld1.64         {d7}, [r0,:64], r1
345     vqmovun.s16     d1,  q9
346     vaddw.u8        q10, q10, d2
347     vaddw.u8        q11, q11, d3
348     vshr.s16        q12, q12, #4
349     vshr.s16        q13, q13, #4
350     vqmovun.s16     d2,  q10
351     vqmovun.s16     d3,  q11
352     vaddw.u8        q12, q12, d4
353     vaddw.u8        q13, q13, d5
354     vshr.s16        q14, q14, #4
355     vshr.s16        q15, q15, #4
356     vst1.64         {d0}, [r2,:64], r1
357     vqmovun.s16     d4,  q12
358     vst1.64         {d1}, [r2,:64], r1
359     vqmovun.s16     d5,  q13
360     vst1.64         {d2}, [r2,:64], r1
361     vaddw.u8        q14, q14, d6
362     vst1.64         {d3}, [r2,:64], r1
363     vaddw.u8        q15, q15, d7
364     vst1.64         {d4}, [r2,:64], r1
365     vqmovun.s16     d6,  q14
366     vst1.64         {d5}, [r2,:64], r1
367     vqmovun.s16     d7,  q15
368     vst1.64         {d6}, [r2,:64], r1
369     vst1.64         {d7}, [r2,:64], r1
370     bx              lr
371 endfunc
372
373 function ff_vp3_idct_dc_add_neon, export=1
374     ldrsh           r2,  [r2]
375     mov             r3,  r0
376     add             r2,  r2,  #15
377     vdup.16         q15, r2
378     vshr.s16        q15, q15, #5
379
380     vld1.8          {d0}, [r0,:64], r1
381     vld1.8          {d1}, [r0,:64], r1
382     vld1.8          {d2}, [r0,:64], r1
383     vaddw.u8        q8,  q15, d0
384     vld1.8          {d3}, [r0,:64], r1
385     vaddw.u8        q9,  q15, d1
386     vld1.8          {d4}, [r0,:64], r1
387     vaddw.u8        q10, q15, d2
388     vld1.8          {d5}, [r0,:64], r1
389     vaddw.u8        q11, q15, d3
390     vld1.8          {d6}, [r0,:64], r1
391     vaddw.u8        q12, q15, d4
392     vld1.8          {d7}, [r0,:64], r1
393     vaddw.u8        q13, q15, d5
394     vqmovun.s16     d0,  q8
395     vaddw.u8        q14, q15, d6
396     vqmovun.s16     d1,  q9
397     vaddw.u8        q15, q15, d7
398     vqmovun.s16     d2,  q10
399     vst1.8          {d0}, [r3,:64], r1
400     vqmovun.s16     d3,  q11
401     vst1.8          {d1}, [r3,:64], r1
402     vqmovun.s16     d4,  q12
403     vst1.8          {d2}, [r3,:64], r1
404     vqmovun.s16     d5,  q13
405     vst1.8          {d3}, [r3,:64], r1
406     vqmovun.s16     d6,  q14
407     vst1.8          {d4}, [r3,:64], r1
408     vqmovun.s16     d7,  q15
409     vst1.8          {d5}, [r3,:64], r1
410     vst1.8          {d6}, [r3,:64], r1
411     vst1.8          {d7}, [r3,:64], r1
412     bx              lr
413 endfunc