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