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 "asm.S"
22
23const   vp3_idct_constants, align=4
24.short 64277, 60547, 54491, 46341, 36410, 25080, 12785
25endconst
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
59function 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
73endfunc
74
75function 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
106endfunc
107
108
109function 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]!
119endfunc
120
121function 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
210endfunc
211
212.macro VP3_IDCT_END type
213function 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
258endfunc
259.endm
260
261VP3_IDCT_END row
262VP3_IDCT_END col
263
264function 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
288endfunc
289
290function 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
318endfunc
319
320function 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
372endfunc
373
374function 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
414endfunc
415