8d22d00038a69fafacd8ff622c1d16cd9ac4cd4d
[ffmpeg.git] / libavcodec / arm / vp3dsp_neon.S
1 /*
2  * Copyright (c) 2009 David Conrad
3  *
4  * This file is part of Libav.
5  *
6  * Libav 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  * Libav 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 Libav; 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 endfunc
120
121 function vp3_idct_core_neon
122     vmull.s16       q2,  d18, xC1S7     // (ip[1] * C1) << 16
123     vmull.s16       q3,  d19, xC1S7
124     vmull.s16       q4,  d2,  xC4S4     // ((ip[0] + ip[4]) * C4) << 16
125     vmull.s16       q5,  d3,  xC4S4
126     vmull.s16       q6,  d16, xC4S4     // ((ip[0] - ip[4]) * C4) << 16
127     vmull.s16       q7,  d17, xC4S4
128     vshrn.s32       d4,  q2,  #16
129     vshrn.s32       d5,  q3,  #16
130     vshrn.s32       d6,  q4,  #16
131     vshrn.s32       d7,  q5,  #16
132     vshrn.s32       d8,  q6,  #16
133     vshrn.s32       d9,  q7,  #16
134     vadd.s16        q12, q1,  q3        // E = (ip[0] + ip[4]) * C4
135     vadd.s16        q8,  q8,  q4        // F = (ip[0] - ip[4]) * C4
136     vadd.s16        q1,  q2,  q9        // ip[1] * C1
137
138     vmull.s16       q2,  d30, xC1S7     // (ip[7] * C1) << 16
139     vmull.s16       q3,  d31, xC1S7
140     vmull.s16       q4,  d30, xC7S1     // (ip[7] * C7) << 16
141     vmull.s16       q5,  d31, xC7S1
142     vmull.s16       q6,  d18, xC7S1     // (ip[1] * C7) << 16
143     vmull.s16       q7,  d19, xC7S1
144     vshrn.s32       d4,  q2,  #16
145     vshrn.s32       d5,  q3,  #16
146     vshrn.s32       d6,  q4,  #16       // ip[7] * C7
147     vshrn.s32       d7,  q5,  #16
148     vshrn.s32       d8,  q6,  #16       // ip[1] * C7
149     vshrn.s32       d9,  q7,  #16
150     vadd.s16        q2,  q2,  q15       // ip[7] * C1
151     vadd.s16        q9,  q1,  q3        // A = ip[1] * C1 + ip[7] * C7
152     vsub.s16        q15, q4,  q2        // B = ip[1] * C7 - ip[7] * C1
153
154     vmull.s16       q2,  d22, xC5S3     // (ip[3] * C5) << 16
155     vmull.s16       q3,  d23, xC5S3
156     vmull.s16       q4,  d22, xC3S5     // (ip[3] * C3) << 16
157     vmull.s16       q5,  d23, xC3S5
158     vmull.s16       q6,  d26, xC5S3     // (ip[5] * C5) << 16
159     vmull.s16       q7,  d27, xC5S3
160     vshrn.s32       d4,  q2,  #16
161     vshrn.s32       d5,  q3,  #16
162     vshrn.s32       d6,  q4,  #16
163     vshrn.s32       d7,  q5,  #16
164     vshrn.s32       d8,  q6,  #16
165     vshrn.s32       d9,  q7,  #16
166     vadd.s16        q3,  q3,  q11       // ip[3] * C3
167     vadd.s16        q4,  q4,  q13       // ip[5] * C5
168     vadd.s16        q1,  q2,  q11       // ip[3] * C5
169     vadd.s16        q11, q3,  q4        // C = ip[3] * C3 + ip[5] * C5
170
171     vmull.s16       q2,  d26, xC3S5     // (ip[5] * C3) << 16
172     vmull.s16       q3,  d27, xC3S5
173     vmull.s16       q4,  d20, xC2S6     // (ip[2] * C2) << 16
174     vmull.s16       q5,  d21, xC2S6
175     vmull.s16       q6,  d28, xC6S2     // (ip[6] * C6) << 16
176     vmull.s16       q7,  d29, xC6S2
177     vshrn.s32       d4,  q2,  #16
178     vshrn.s32       d5,  q3,  #16
179     vshrn.s32       d6,  q4,  #16
180     vshrn.s32       d7,  q5,  #16
181     vshrn.s32       d8,  q6,  #16       // ip[6] * C6
182     vshrn.s32       d9,  q7,  #16
183     vadd.s16        q2,  q2,  q13       // ip[5] * C3
184     vadd.s16        q3,  q3,  q10       // ip[2] * C2
185     vsub.s16        q13, q2,  q1        // D = ip[5] * C3 - ip[3] * C5
186     vsub.s16        q1,  q9,  q11       // (A - C)
187     vadd.s16        q11, q9,  q11       // Cd = A + C
188     vsub.s16        q9,  q15, q13       // (B - D)
189     vadd.s16        q13, q15, q13       // Dd = B + D
190     vadd.s16        q15, q3,  q4        // G = ip[2] * C2 + ip[6] * C6
191
192     vmull.s16       q2,  d2,  xC4S4     // ((A - C) * C4) << 16
193     vmull.s16       q3,  d3,  xC4S4
194     vmull.s16       q4,  d28, xC2S6     // (ip[6] * C2) << 16
195     vmull.s16       q5,  d29, xC2S6
196     vmull.s16       q6,  d20, xC6S2     // (ip[2] * C6) << 16
197     vmull.s16       q7,  d21, xC6S2
198     vshrn.s32       d4,  q2,  #16
199     vshrn.s32       d5,  q3,  #16
200     vshrn.s32       d6,  q4,  #16
201     vshrn.s32       d7,  q5,  #16
202     vshrn.s32       d8,  q6,  #16       // ip[2] * C6
203     vmull.s16       q5,  d18, xC4S4     // ((B - D) * C4) << 16
204     vmull.s16       q6,  d19, xC4S4
205     vshrn.s32       d9,  q7,  #16
206     vadd.s16        q3,  q3,  q14       // ip[6] * C2
207     vadd.s16        q10, q1,  q2        // Ad = (A - C) * C4
208     vsub.s16        q14, q4,  q3        // H = ip[2] * C6 - ip[6] * C2
209     bx              lr
210 endfunc
211
212 .macro VP3_IDCT_END type
213 function vp3_idct_end_\type\()_neon
214 .ifc \type, col
215     vdup.16         q0,  r3
216     vadd.s16        q12, q12, q0
217     vadd.s16        q8,  q8,  q0
218 .endif
219
220     vshrn.s32       d2,  q5,  #16
221     vshrn.s32       d3,  q6,  #16
222     vadd.s16        q2,  q12, q15       // Gd  = E + G
223     vadd.s16        q9,  q1,  q9        // (B - D) * C4
224     vsub.s16        q12, q12, q15       // Ed  = E - G
225     vsub.s16        q3,  q8,  q10       // Fd  = F - Ad
226     vadd.s16        q10, q8,  q10       // Add = F + Ad
227     vadd.s16        q4,  q9,  q14       // Hd  = Bd + H
228     vsub.s16        q14, q9,  q14       // Bdd = Bd - H
229     vadd.s16        q8,  q2,  q11       // [0] = Gd + Cd
230     vsub.s16        q15, q2,  q11       // [7] = Gd - Cd
231     vadd.s16        q9,  q10, q4        // [1] = Add + Hd
232     vsub.s16        q10, q10, q4        // [2] = Add - Hd
233     vadd.s16        q11, q12, q13       // [3] = Ed + Dd
234     vsub.s16        q12, q12, q13       // [4] = Ed - Dd
235 .ifc \type, row
236     vtrn.16         q8,  q9
237 .endif
238     vadd.s16        q13, q3,  q14       // [5] = Fd + Bdd
239     vsub.s16        q14, q3,  q14       // [6] = Fd - Bdd
240
241 .ifc \type, row
242     // 8x8 transpose
243     vtrn.16         q10, q11
244     vtrn.16         q12, q13
245     vtrn.16         q14, q15
246     vtrn.32         q8,  q10
247     vtrn.32         q9,  q11
248     vtrn.32         q12, q14
249     vtrn.32         q13, q15
250     vswp            d17, d24
251     vswp            d19, d26
252     vadd.s16        q1,  q8,  q12
253     vswp            d21, d28
254     vsub.s16        q8,  q8,  q12
255     vswp            d23, d30
256 .endif
257     bx              lr
258 endfunc
259 .endm
260
261 VP3_IDCT_END row
262 VP3_IDCT_END col
263
264 function ff_vp3_idct_neon, export=1
265     mov             ip,  lr
266     mov             r2,  r0
267     bl              vp3_idct_start_neon
268     bl              vp3_idct_end_row_neon
269     mov             r3,  #8
270     bl              vp3_idct_core_neon
271     bl              vp3_idct_end_col_neon
272     mov             lr,  ip
273     vpop            {d8-d15}
274
275     vshr.s16        q8,  q8,  #4
276     vshr.s16        q9,  q9,  #4
277     vshr.s16        q10, q10, #4
278     vshr.s16        q11, q11, #4
279     vshr.s16        q12, q12, #4
280     vst1.64         {d16-d19}, [r0,:128]!
281     vshr.s16        q13, q13, #4
282     vshr.s16        q14, q14, #4
283     vst1.64         {d20-d23}, [r0,:128]!
284     vshr.s16        q15, q15, #4
285     vst1.64         {d24-d27}, [r0,:128]!
286     vst1.64         {d28-d31}, [r0,:128]!
287     bx              lr
288 endfunc
289
290 function ff_vp3_idct_put_neon, export=1
291     mov             ip,  lr
292     bl              vp3_idct_start_neon
293     bl              vp3_idct_end_row_neon
294     mov             r3,  #8
295     add             r3,  r3,  #2048         // convert signed pixel to unsigned
296     bl              vp3_idct_core_neon
297     bl              vp3_idct_end_col_neon
298     mov             lr,  ip
299     vpop            {d8-d15}
300
301     vqshrun.s16     d0,  q8,  #4
302     vqshrun.s16     d1,  q9,  #4
303     vqshrun.s16     d2,  q10, #4
304     vqshrun.s16     d3,  q11, #4
305     vst1.64         {d0}, [r0,:64], r1
306     vqshrun.s16     d4,  q12, #4
307     vst1.64         {d1}, [r0,:64], r1
308     vqshrun.s16     d5,  q13, #4
309     vst1.64         {d2}, [r0,:64], r1
310     vqshrun.s16     d6,  q14, #4
311     vst1.64         {d3}, [r0,:64], r1
312     vqshrun.s16     d7,  q15, #4
313     vst1.64         {d4}, [r0,:64], r1
314     vst1.64         {d5}, [r0,:64], r1
315     vst1.64         {d6}, [r0,:64], r1
316     vst1.64         {d7}, [r0,:64], r1
317     bx              lr
318 endfunc
319
320 function ff_vp3_idct_add_neon, export=1
321     mov             ip,  lr
322     bl              vp3_idct_start_neon
323     bl              vp3_idct_end_row_neon
324     mov             r3,  #8
325     bl              vp3_idct_core_neon
326     bl              vp3_idct_end_col_neon
327     mov             lr,  ip
328     vpop            {d8-d15}
329     mov             r2,  r0
330
331     vld1.64         {d0}, [r0,:64], r1
332     vshr.s16        q8,  q8,  #4
333     vld1.64         {d1}, [r0,:64], r1
334     vshr.s16        q9,  q9,  #4
335     vld1.64         {d2}, [r0,:64], r1
336     vaddw.u8        q8,  q8,  d0
337     vld1.64         {d3}, [r0,:64], r1
338     vaddw.u8        q9,  q9,  d1
339     vld1.64         {d4}, [r0,:64], r1
340     vshr.s16        q10, q10, #4
341     vld1.64         {d5}, [r0,:64], r1
342     vshr.s16        q11, q11, #4
343     vld1.64         {d6}, [r0,:64], r1
344     vqmovun.s16     d0,  q8
345     vld1.64         {d7}, [r0,:64], r1
346     vqmovun.s16     d1,  q9
347     vaddw.u8        q10, q10, d2
348     vaddw.u8        q11, q11, d3
349     vshr.s16        q12, q12, #4
350     vshr.s16        q13, q13, #4
351     vqmovun.s16     d2,  q10
352     vqmovun.s16     d3,  q11
353     vaddw.u8        q12, q12, d4
354     vaddw.u8        q13, q13, d5
355     vshr.s16        q14, q14, #4
356     vshr.s16        q15, q15, #4
357     vst1.64         {d0}, [r2,:64], r1
358     vqmovun.s16     d4,  q12
359     vst1.64         {d1}, [r2,:64], r1
360     vqmovun.s16     d5,  q13
361     vst1.64         {d2}, [r2,:64], r1
362     vaddw.u8        q14, q14, d6
363     vst1.64         {d3}, [r2,:64], r1
364     vaddw.u8        q15, q15, d7
365     vst1.64         {d4}, [r2,:64], r1
366     vqmovun.s16     d6,  q14
367     vst1.64         {d5}, [r2,:64], r1
368     vqmovun.s16     d7,  q15
369     vst1.64         {d6}, [r2,:64], r1
370     vst1.64         {d7}, [r2,:64], r1
371     bx              lr
372 endfunc
373
374 function ff_vp3_idct_dc_add_neon, export=1
375     ldrsh           r2,  [r2]
376     mov             r3,  r0
377     add             r2,  r2,  #15
378     vdup.16         q15, r2
379     vshr.s16        q15, q15, #5
380
381     vld1.8          {d0}, [r0,:64], r1
382     vld1.8          {d1}, [r0,:64], r1
383     vld1.8          {d2}, [r0,:64], r1
384     vaddw.u8        q8,  q15, d0
385     vld1.8          {d3}, [r0,:64], r1
386     vaddw.u8        q9,  q15, d1
387     vld1.8          {d4}, [r0,:64], r1
388     vaddw.u8        q10, q15, d2
389     vld1.8          {d5}, [r0,:64], r1
390     vaddw.u8        q11, q15, d3
391     vld1.8          {d6}, [r0,:64], r1
392     vaddw.u8        q12, q15, d4
393     vld1.8          {d7}, [r0,:64], r1
394     vaddw.u8        q13, q15, d5
395     vqmovun.s16     d0,  q8
396     vaddw.u8        q14, q15, d6
397     vqmovun.s16     d1,  q9
398     vaddw.u8        q15, q15, d7
399     vqmovun.s16     d2,  q10
400     vst1.8          {d0}, [r3,:64], r1
401     vqmovun.s16     d3,  q11
402     vst1.8          {d1}, [r3,:64], r1
403     vqmovun.s16     d4,  q12
404     vst1.8          {d2}, [r3,:64], r1
405     vqmovun.s16     d5,  q13
406     vst1.8          {d3}, [r3,:64], r1
407     vqmovun.s16     d6,  q14
408     vst1.8          {d4}, [r3,:64], r1
409     vqmovun.s16     d7,  q15
410     vst1.8          {d5}, [r3,:64], r1
411     vst1.8          {d6}, [r3,:64], r1
412     vst1.8          {d7}, [r3,:64], r1
413     bx              lr
414 endfunc