• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1/*
2 * ARM NEON IDCT
3 *
4 * Copyright (c) 2008 Mans Rullgard <mans@mansr.com>
5 *
6 * Based on Simple IDCT
7 * Copyright (c) 2001 Michael Niedermayer <michaelni@gmx.at>
8 *
9 * This file is part of FFmpeg.
10 *
11 * FFmpeg is free software; you can redistribute it and/or
12 * modify it under the terms of the GNU Lesser General Public
13 * License as published by the Free Software Foundation; either
14 * version 2.1 of the License, or (at your option) any later version.
15 *
16 * FFmpeg is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
19 * Lesser General Public License for more details.
20 *
21 * You should have received a copy of the GNU Lesser General Public
22 * License along with FFmpeg; if not, write to the Free Software
23 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
24 */
25
26#include "libavutil/arm/asm.S"
27
28#define W1  22725  //cos(i*M_PI/16)*sqrt(2)*(1<<14) + 0.5
29#define W2  21407  //cos(i*M_PI/16)*sqrt(2)*(1<<14) + 0.5
30#define W3  19266  //cos(i*M_PI/16)*sqrt(2)*(1<<14) + 0.5
31#define W4  16383  //cos(i*M_PI/16)*sqrt(2)*(1<<14) + 0.5
32#define W5  12873  //cos(i*M_PI/16)*sqrt(2)*(1<<14) + 0.5
33#define W6  8867   //cos(i*M_PI/16)*sqrt(2)*(1<<14) + 0.5
34#define W7  4520   //cos(i*M_PI/16)*sqrt(2)*(1<<14) + 0.5
35#define W4c ((1<<(COL_SHIFT-1))/W4)
36#define ROW_SHIFT 11
37#define COL_SHIFT 20
38
39#define w1 d0[0]
40#define w2 d0[1]
41#define w3 d0[2]
42#define w4 d0[3]
43#define w5 d1[0]
44#define w6 d1[1]
45#define w7 d1[2]
46#define w4c d1[3]
47
48        .macro idct_col4_top
49        vmull.s16       q7,  d6,  w2    /* q9   = W2 * col[2] */
50        vmull.s16       q8,  d6,  w6    /* q10  = W6 * col[2] */
51        vmull.s16       q9,  d4,  w1    /* q9   = W1 * col[1] */
52        vadd.i32        q11, q15, q7
53        vmull.s16       q10, d4,  w3    /* q10  = W3 * col[1] */
54        vadd.i32        q12, q15, q8
55        vmull.s16       q5,  d4,  w5    /* q5   = W5 * col[1] */
56        vsub.i32        q13, q15, q8
57        vmull.s16       q6,  d4,  w7    /* q6   = W7 * col[1] */
58        vsub.i32        q14, q15, q7
59
60        vmlal.s16       q9,  d8,  w3    /* q9  += W3 * col[3] */
61        vmlsl.s16       q10, d8,  w7    /* q10 -= W7 * col[3] */
62        vmlsl.s16       q5,  d8,  w1    /* q5  -= W1 * col[3] */
63        vmlsl.s16       q6,  d8,  w5    /* q6  -= W5 * col[3] */
64        .endm
65
66        .text
67        .align 6
68
69function idct_row4_pld_neon
70        pld             [r0]
71        add             r3,  r0,  r1,  lsl #2
72        pld             [r0, r1]
73        pld             [r0, r1, lsl #1]
74A       pld             [r3, -r1]
75        pld             [r3]
76        pld             [r3, r1]
77        add             r3,  r3,  r1,  lsl #1
78        pld             [r3]
79        pld             [r3, r1]
80endfunc
81
82function idct_row4_neon
83        vmov.i32        q15, #(1<<(ROW_SHIFT-1))
84        vld1.64         {d2-d5},  [r2,:128]!
85        vmlal.s16       q15, d2,  w4    /* q15  += W4 * col[0] */
86        vld1.64         {d6,d7},  [r2,:128]!
87        vorr            d10, d3,  d5
88        vld1.64         {d8,d9},  [r2,:128]!
89        add             r2,  r2,  #-64
90
91        vorr            d11, d7,  d9
92        vorr            d10, d10, d11
93        vmov            r3,  r4,  d10
94
95        idct_col4_top
96
97        orrs            r3,  r3,  r4
98        beq             1f
99
100        vmull.s16       q7,  d3,  w4    /* q7   = W4 * col[4] */
101        vmlal.s16       q9,  d5,  w5    /* q9  += W5 * col[5] */
102        vmlsl.s16       q10, d5,  w1    /* q10 -= W1 * col[5] */
103        vmull.s16       q8,  d7,  w2    /* q8   = W2 * col[6] */
104        vmlal.s16       q5,  d5,  w7    /* q5  += W7 * col[5] */
105        vadd.i32        q11, q11, q7
106        vsub.i32        q12, q12, q7
107        vsub.i32        q13, q13, q7
108        vadd.i32        q14, q14, q7
109        vmlal.s16       q6,  d5,  w3    /* q6  += W3 * col[5] */
110        vmull.s16       q7,  d7,  w6    /* q7   = W6 * col[6] */
111        vmlal.s16       q9,  d9,  w7
112        vmlsl.s16       q10, d9,  w5
113        vmlal.s16       q5,  d9,  w3
114        vmlsl.s16       q6,  d9,  w1
115        vadd.i32        q11, q11, q7
116        vsub.i32        q12, q12, q8
117        vadd.i32        q13, q13, q8
118        vsub.i32        q14, q14, q7
119
1201:      vadd.i32        q3,  q11, q9
121        vadd.i32        q4,  q12, q10
122        vshrn.i32       d2,  q3,  #ROW_SHIFT
123        vshrn.i32       d4,  q4,  #ROW_SHIFT
124        vadd.i32        q7,  q13, q5
125        vadd.i32        q8,  q14, q6
126        vtrn.16         d2,  d4
127        vshrn.i32       d6,  q7,  #ROW_SHIFT
128        vshrn.i32       d8,  q8,  #ROW_SHIFT
129        vsub.i32        q14, q14, q6
130        vsub.i32        q11, q11, q9
131        vtrn.16         d6,  d8
132        vsub.i32        q13, q13, q5
133        vshrn.i32       d3,  q14, #ROW_SHIFT
134        vtrn.32         d2,  d6
135        vsub.i32        q12, q12, q10
136        vtrn.32         d4,  d8
137        vshrn.i32       d5,  q13, #ROW_SHIFT
138        vshrn.i32       d7,  q12, #ROW_SHIFT
139        vshrn.i32       d9,  q11, #ROW_SHIFT
140
141        vtrn.16         d3,  d5
142        vtrn.16         d7,  d9
143        vtrn.32         d3,  d7
144        vtrn.32         d5,  d9
145
146        vst1.64         {d2-d5},  [r2,:128]!
147        vst1.64         {d6-d9},  [r2,:128]!
148
149        bx              lr
150endfunc
151
152function idct_col4_neon
153        mov             ip,  #16
154        vld1.64         {d2}, [r2,:64], ip /* d2 = col[0] */
155        vdup.16         d30, w4c
156        vld1.64         {d4}, [r2,:64], ip /* d3 = col[1] */
157        vadd.i16        d30, d30, d2
158        vld1.64         {d6}, [r2,:64], ip /* d4 = col[2] */
159        vmull.s16       q15, d30, w4 /* q15 = W4*(col[0]+(1<<COL_SHIFT-1)/W4)*/
160        vld1.64         {d8}, [r2,:64], ip /* d5 = col[3] */
161
162        ldrd            r4,  r5,  [r2]
163        ldrd            r6,  r7,  [r2, #16]
164        orrs            r4,  r4,  r5
165
166        idct_col4_top
167        it              eq
168        addeq           r2,  r2,  #16
169        beq             1f
170
171        vld1.64         {d3}, [r2,:64], ip /* d6 = col[4] */
172        vmull.s16       q7,  d3,  w4    /* q7   = W4 * col[4] */
173        vadd.i32        q11, q11, q7
174        vsub.i32        q12, q12, q7
175        vsub.i32        q13, q13, q7
176        vadd.i32        q14, q14, q7
177
1781:      orrs            r6,  r6,  r7
179        ldrd            r4,  r5,  [r2, #16]
180        it              eq
181        addeq           r2,  r2,  #16
182        beq             2f
183
184        vld1.64         {d5}, [r2,:64], ip /* d7 = col[5] */
185        vmlal.s16       q9,  d5,  w5    /* q9  += W5 * col[5] */
186        vmlsl.s16       q10, d5,  w1    /* q10 -= W1 * col[5] */
187        vmlal.s16       q5,  d5,  w7    /* q5  += W7 * col[5] */
188        vmlal.s16       q6,  d5,  w3    /* q6  += W3 * col[5] */
189
1902:      orrs            r4,  r4,  r5
191        ldrd            r4,  r5,  [r2, #16]
192        it              eq
193        addeq           r2,  r2,  #16
194        beq             3f
195
196        vld1.64         {d7}, [r2,:64], ip /* d8 = col[6] */
197        vmull.s16       q7,  d7,  w6    /* q7   = W6 * col[6] */
198        vmull.s16       q8,  d7,  w2    /* q8   = W2 * col[6] */
199        vadd.i32        q11, q11, q7
200        vsub.i32        q14, q14, q7
201        vsub.i32        q12, q12, q8
202        vadd.i32        q13, q13, q8
203
2043:      orrs            r4,  r4,  r5
205        it              eq
206        addeq           r2,  r2,  #16
207        beq             4f
208
209        vld1.64         {d9}, [r2,:64], ip /* d9 = col[7] */
210        vmlal.s16       q9,  d9,  w7
211        vmlsl.s16       q10, d9,  w5
212        vmlal.s16       q5,  d9,  w3
213        vmlsl.s16       q6,  d9,  w1
214
2154:      vaddhn.i32      d2,  q11, q9
216        vaddhn.i32      d3,  q12, q10
217        vaddhn.i32      d4,  q13, q5
218        vaddhn.i32      d5,  q14, q6
219        vsubhn.i32      d9,  q11, q9
220        vsubhn.i32      d8,  q12, q10
221        vsubhn.i32      d7,  q13, q5
222        vsubhn.i32      d6,  q14, q6
223
224        bx              lr
225endfunc
226
227        .align 6
228
229function idct_col4_st8_neon
230        vqshrun.s16     d2,  q1,  #COL_SHIFT-16
231        vqshrun.s16     d3,  q2,  #COL_SHIFT-16
232        vqshrun.s16     d4,  q3,  #COL_SHIFT-16
233        vqshrun.s16     d5,  q4,  #COL_SHIFT-16
234        vst1.32         {d2[0]}, [r0,:32], r1
235        vst1.32         {d2[1]}, [r0,:32], r1
236        vst1.32         {d3[0]}, [r0,:32], r1
237        vst1.32         {d3[1]}, [r0,:32], r1
238        vst1.32         {d4[0]}, [r0,:32], r1
239        vst1.32         {d4[1]}, [r0,:32], r1
240        vst1.32         {d5[0]}, [r0,:32], r1
241        vst1.32         {d5[1]}, [r0,:32], r1
242
243        bx              lr
244endfunc
245
246const   idct_coeff_neon, align=4
247        .short W1, W2, W3, W4, W5, W6, W7, W4c
248endconst
249
250        .macro idct_start data
251        push            {r4-r7, lr}
252        pld             [\data]
253        pld             [\data, #64]
254        vpush           {d8-d15}
255        movrel          r3,  idct_coeff_neon
256        vld1.64         {d0,d1}, [r3,:128]
257        .endm
258
259        .macro idct_end
260        vpop            {d8-d15}
261        pop             {r4-r7, pc}
262        .endm
263
264/* void ff_simple_idct_put_neon(uint8_t *dst, ptrdiff_t line_size, int16_t *data); */
265function ff_simple_idct_put_neon, export=1
266        idct_start      r2
267
268        bl              idct_row4_pld_neon
269        bl              idct_row4_neon
270        add             r2,  r2,  #-128
271        bl              idct_col4_neon
272        bl              idct_col4_st8_neon
273        sub             r0,  r0,  r1, lsl #3
274        add             r0,  r0,  #4
275        add             r2,  r2,  #-120
276        bl              idct_col4_neon
277        bl              idct_col4_st8_neon
278
279        idct_end
280endfunc
281
282        .align 6
283
284function idct_col4_add8_neon
285        mov             ip,  r0
286
287        vld1.32         {d10[0]}, [r0,:32], r1
288        vshr.s16        q1,  q1,  #COL_SHIFT-16
289        vld1.32         {d10[1]}, [r0,:32], r1
290        vshr.s16        q2,  q2,  #COL_SHIFT-16
291        vld1.32         {d11[0]}, [r0,:32], r1
292        vshr.s16        q3,  q3,  #COL_SHIFT-16
293        vld1.32         {d11[1]}, [r0,:32], r1
294        vshr.s16        q4,  q4,  #COL_SHIFT-16
295        vld1.32         {d12[0]}, [r0,:32], r1
296        vaddw.u8        q1,  q1,  d10
297        vld1.32         {d12[1]}, [r0,:32], r1
298        vaddw.u8        q2,  q2,  d11
299        vld1.32         {d13[0]}, [r0,:32], r1
300        vqmovun.s16     d2,  q1
301        vld1.32         {d13[1]}, [r0,:32], r1
302        vaddw.u8        q3,  q3,  d12
303        vst1.32         {d2[0]},  [ip,:32], r1
304        vqmovun.s16     d3,  q2
305        vst1.32         {d2[1]},  [ip,:32], r1
306        vaddw.u8        q4,  q4,  d13
307        vst1.32         {d3[0]},  [ip,:32], r1
308        vqmovun.s16     d4,  q3
309        vst1.32         {d3[1]},  [ip,:32], r1
310        vqmovun.s16     d5,  q4
311        vst1.32         {d4[0]},  [ip,:32], r1
312        vst1.32         {d4[1]},  [ip,:32], r1
313        vst1.32         {d5[0]},  [ip,:32], r1
314        vst1.32         {d5[1]},  [ip,:32], r1
315
316        bx              lr
317endfunc
318
319/* void ff_simple_idct_add_neon(uint8_t *dst, ptrdiff_t line_size, int16_t *data); */
320function ff_simple_idct_add_neon, export=1
321        idct_start      r2
322
323        bl              idct_row4_pld_neon
324        bl              idct_row4_neon
325        add             r2,  r2,  #-128
326        bl              idct_col4_neon
327        bl              idct_col4_add8_neon
328        sub             r0,  r0,  r1, lsl #3
329        add             r0,  r0,  #4
330        add             r2,  r2,  #-120
331        bl              idct_col4_neon
332        bl              idct_col4_add8_neon
333
334        idct_end
335endfunc
336
337        .align 6
338
339function idct_col4_st16_neon
340        mov             ip,  #16
341
342        vshr.s16        q1,  q1,  #COL_SHIFT-16
343        vshr.s16        q2,  q2,  #COL_SHIFT-16
344        vst1.64         {d2}, [r2,:64], ip
345        vshr.s16        q3,  q3,  #COL_SHIFT-16
346        vst1.64         {d3}, [r2,:64], ip
347        vshr.s16        q4,  q4,  #COL_SHIFT-16
348        vst1.64         {d4}, [r2,:64], ip
349        vst1.64         {d5}, [r2,:64], ip
350        vst1.64         {d6}, [r2,:64], ip
351        vst1.64         {d7}, [r2,:64], ip
352        vst1.64         {d8}, [r2,:64], ip
353        vst1.64         {d9}, [r2,:64], ip
354
355        bx              lr
356endfunc
357
358/* void ff_simple_idct_neon(int16_t *data); */
359function ff_simple_idct_neon, export=1
360        idct_start      r0
361
362        mov             r2,  r0
363        bl              idct_row4_neon
364        bl              idct_row4_neon
365        add             r2,  r2,  #-128
366        bl              idct_col4_neon
367        add             r2,  r2,  #-128
368        bl              idct_col4_st16_neon
369        add             r2,  r2,  #-120
370        bl              idct_col4_neon
371        add             r2,  r2,  #-128
372        bl              idct_col4_st16_neon
373
374        idct_end
375endfunc
376