]> git.sesse.net Git - ffmpeg/blob - libavcodec/arm/simple_idct_armv6.S
Merge remote-tracking branch 'qatar/master'
[ffmpeg] / libavcodec / arm / simple_idct_armv6.S
1 /*
2  * Simple IDCT
3  *
4  * Copyright (c) 2001 Michael Niedermayer <michaelni@gmx.at>
5  * Copyright (c) 2007 Mans Rullgard <mans@mansr.com>
6  *
7  * This file is part of FFmpeg.
8  *
9  * FFmpeg is free software; you can redistribute it and/or
10  * modify it under the terms of the GNU Lesser General Public
11  * License as published by the Free Software Foundation; either
12  * version 2.1 of the License, or (at your option) any later version.
13  *
14  * FFmpeg is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
17  * Lesser General Public License for more details.
18  *
19  * You should have received a copy of the GNU Lesser General Public
20  * License along with FFmpeg; if not, write to the Free Software
21  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
22  */
23
24 #include "asm.S"
25
26 #define W1  22725   /* cos(i*M_PI/16)*sqrt(2)*(1<<14) + 0.5 */
27 #define W2  21407   /* cos(i*M_PI/16)*sqrt(2)*(1<<14) + 0.5 */
28 #define W3  19266   /* cos(i*M_PI/16)*sqrt(2)*(1<<14) + 0.5 */
29 #define W4  16383   /* cos(i*M_PI/16)*sqrt(2)*(1<<14) + 0.5 */
30 #define W5  12873   /* cos(i*M_PI/16)*sqrt(2)*(1<<14) + 0.5 */
31 #define W6  8867    /* cos(i*M_PI/16)*sqrt(2)*(1<<14) + 0.5 */
32 #define W7  4520    /* cos(i*M_PI/16)*sqrt(2)*(1<<14) + 0.5 */
33 #define ROW_SHIFT 11
34 #define COL_SHIFT 20
35
36 #define W13 (W1 | (W3 << 16))
37 #define W26 (W2 | (W6 << 16))
38 #define W42 (W4 | (W2 << 16))
39 #define W42n (-W4&0xffff | (-W2 << 16))
40 #define W46 (W4 | (W6 << 16))
41 #define W57 (W5 | (W7 << 16))
42
43         .text
44         .align
45 w13:    .long W13
46 w26:    .long W26
47 w42:    .long W42
48 w42n:   .long W42n
49 w46:    .long W46
50 w57:    .long W57
51
52 /*
53   Compute partial IDCT of single row.
54   shift = left-shift amount
55   r0 = source address
56   r2 = row[2,0] <= 2 cycles
57   r3 = row[3,1]
58   ip = w42      <= 2 cycles
59
60   Output in registers r4--r11
61 */
62         .macro idct_row shift
63         ldr    lr, w46               /* lr  = W4 | (W6 << 16) */
64         mov    r1, #(1<<(\shift-1))
65         smlad  r4, r2, ip, r1
66         smlsd  r7, r2, ip, r1
67         ldr    ip, w13               /* ip  = W1 | (W3 << 16) */
68         ldr    r10,w57               /* r10 = W5 | (W7 << 16) */
69         smlad  r5, r2, lr, r1
70         smlsd  r6, r2, lr, r1
71
72         smuad  r8, r3, ip            /* r8  =  B0 = W1*row[1] + W3*row[3] */
73         smusdx r11,r3, r10           /* r11 =  B3 = W7*row[1] - W5*row[3] */
74         ldr    lr, [r0, #12]         /* lr  =  row[7,5] */
75         pkhtb  r2, ip, r10,asr #16   /* r3  =  W7 | (W3 << 16) */
76         pkhbt  r1, ip, r10,lsl #16   /* r1  =  W1 | (W5 << 16) */
77         smusdx r9, r2, r3            /* r9  = -B1 = W7*row[3] - W3*row[1] */
78         smlad  r8, lr, r10,r8        /* B0  +=      W5*row[5] + W7*row[7] */
79         smusdx r10,r3, r1            /* r10 =  B2 = W5*row[1] - W1*row[3] */
80
81         ldr    r3, w42n              /* r3 =  -W4 | (-W2 << 16) */
82         smlad  r10,lr, r2, r10       /* B2 +=  W7*row[5] + W3*row[7] */
83         ldr    r2, [r0, #4]          /* r2 =   row[6,4] */
84         smlsdx r11,lr, ip, r11       /* B3 +=  W3*row[5] - W1*row[7] */
85         ldr    ip, w46               /* ip =   W4 | (W6 << 16) */
86         smlad  r9, lr, r1, r9        /* B1 -=  W1*row[5] + W5*row[7] */
87
88         smlad  r5, r2, r3, r5        /* A1 += -W4*row[4] - W2*row[6] */
89         smlsd  r6, r2, r3, r6        /* A2 += -W4*row[4] + W2*row[6] */
90         smlad  r4, r2, ip, r4        /* A0 +=  W4*row[4] + W6*row[6] */
91         smlsd  r7, r2, ip, r7        /* A3 +=  W4*row[4] - W6*row[6] */
92         .endm
93
94 /*
95   Compute partial IDCT of half row.
96   shift = left-shift amount
97   r2 = row[2,0]
98   r3 = row[3,1]
99   ip = w42
100
101   Output in registers r4--r11
102 */
103         .macro idct_row4 shift
104         ldr    lr, w46               /* lr =  W4 | (W6 << 16) */
105         ldr    r10,w57               /* r10 = W5 | (W7 << 16) */
106         mov    r1, #(1<<(\shift-1))
107         smlad  r4, r2, ip, r1
108         smlsd  r7, r2, ip, r1
109         ldr    ip, w13               /* ip =  W1 | (W3 << 16) */
110         smlad  r5, r2, lr, r1
111         smlsd  r6, r2, lr, r1
112         smusdx r11,r3, r10           /* r11 =  B3 = W7*row[1] - W5*row[3] */
113         smuad  r8, r3, ip            /* r8  =  B0 = W1*row[1] + W3*row[3] */
114         pkhtb  r2, ip, r10,asr #16   /* r3  =  W7 | (W3 << 16) */
115         pkhbt  r1, ip, r10,lsl #16   /* r1  =  W1 | (W5 << 16) */
116         smusdx r9, r2, r3            /* r9  = -B1 = W7*row[3] - W3*row[1] */
117         smusdx r10,r3, r1            /* r10 =  B2 = W5*row[1] - W1*row[3] */
118         .endm
119
120 /*
121   Compute final part of IDCT single row without shift.
122   Input in registers r4--r11
123   Output in registers ip, r4--r6, lr, r8--r10
124 */
125         .macro idct_finish
126         add    ip, r4, r8            /* r1 = A0 + B0 */
127         sub    lr, r4, r8            /* r2 = A0 - B0 */
128         sub    r4, r5, r9            /* r2 = A1 + B1 */
129         add    r8, r5, r9            /* r2 = A1 - B1 */
130         add    r5, r6, r10           /* r1 = A2 + B2 */
131         sub    r9, r6, r10           /* r1 = A2 - B2 */
132         add    r6, r7, r11           /* r2 = A3 + B3 */
133         sub    r10,r7, r11           /* r2 = A3 - B3 */
134         .endm
135
136 /*
137   Compute final part of IDCT single row.
138   shift = right-shift amount
139   Input/output in registers r4--r11
140 */
141         .macro idct_finish_shift shift
142         add    r3, r4, r8            /* r3 = A0 + B0 */
143         sub    r2, r4, r8            /* r2 = A0 - B0 */
144         mov    r4, r3, asr #\shift
145         mov    r8, r2, asr #\shift
146
147         sub    r3, r5, r9            /* r3 = A1 + B1 */
148         add    r2, r5, r9            /* r2 = A1 - B1 */
149         mov    r5, r3, asr #\shift
150         mov    r9, r2, asr #\shift
151
152         add    r3, r6, r10           /* r3 = A2 + B2 */
153         sub    r2, r6, r10           /* r2 = A2 - B2 */
154         mov    r6, r3, asr #\shift
155         mov    r10,r2, asr #\shift
156
157         add    r3, r7, r11           /* r3 = A3 + B3 */
158         sub    r2, r7, r11           /* r2 = A3 - B3 */
159         mov    r7, r3, asr #\shift
160         mov    r11,r2, asr #\shift
161         .endm
162
163 /*
164   Compute final part of IDCT single row, saturating results at 8 bits.
165   shift = right-shift amount
166   Input/output in registers r4--r11
167 */
168         .macro idct_finish_shift_sat shift
169         add    r3, r4, r8            /* r3 = A0 + B0 */
170         sub    ip, r4, r8            /* ip = A0 - B0 */
171         usat   r4, #8, r3, asr #\shift
172         usat   r8, #8, ip, asr #\shift
173
174         sub    r3, r5, r9            /* r3 = A1 + B1 */
175         add    ip, r5, r9            /* ip = A1 - B1 */
176         usat   r5, #8, r3, asr #\shift
177         usat   r9, #8, ip, asr #\shift
178
179         add    r3, r6, r10           /* r3 = A2 + B2 */
180         sub    ip, r6, r10           /* ip = A2 - B2 */
181         usat   r6, #8, r3, asr #\shift
182         usat   r10,#8, ip, asr #\shift
183
184         add    r3, r7, r11           /* r3 = A3 + B3 */
185         sub    ip, r7, r11           /* ip = A3 - B3 */
186         usat   r7, #8, r3, asr #\shift
187         usat   r11,#8, ip, asr #\shift
188         .endm
189
190 /*
191   Compute IDCT of single row, storing as column.
192   r0 = source
193   r1 = dest
194 */
195 function idct_row_armv6
196         push   {lr}
197
198         ldr    lr, [r0, #12]         /* lr = row[7,5] */
199         ldr    ip, [r0, #4]          /* ip = row[6,4] */
200         ldr    r3, [r0, #8]          /* r3 = row[3,1] */
201         ldr    r2, [r0]              /* r2 = row[2,0] */
202         orrs   lr, lr, ip
203         itt    eq
204         cmpeq  lr, r3
205         cmpeq  lr, r2, lsr #16
206         beq    1f
207         push   {r1}
208         ldr    ip, w42               /* ip = W4 | (W2 << 16) */
209         cmp    lr, #0
210         beq    2f
211
212         idct_row   ROW_SHIFT
213         b      3f
214
215 2:      idct_row4  ROW_SHIFT
216
217 3:      pop    {r1}
218         idct_finish_shift ROW_SHIFT
219
220         strh   r4, [r1]
221         strh   r5, [r1, #(16*2)]
222         strh   r6, [r1, #(16*4)]
223         strh   r7, [r1, #(16*6)]
224         strh   r11,[r1, #(16*1)]
225         strh   r10,[r1, #(16*3)]
226         strh   r9, [r1, #(16*5)]
227         strh   r8, [r1, #(16*7)]
228
229         pop    {pc}
230
231 1:      mov    r2, r2, lsl #3
232         strh   r2, [r1]
233         strh   r2, [r1, #(16*2)]
234         strh   r2, [r1, #(16*4)]
235         strh   r2, [r1, #(16*6)]
236         strh   r2, [r1, #(16*1)]
237         strh   r2, [r1, #(16*3)]
238         strh   r2, [r1, #(16*5)]
239         strh   r2, [r1, #(16*7)]
240         pop    {pc}
241 endfunc
242
243 /*
244   Compute IDCT of single column, read as row.
245   r0 = source
246   r1 = dest
247 */
248 function idct_col_armv6
249         push   {r1, lr}
250
251         ldr    r2, [r0]              /* r2 = row[2,0] */
252         ldr    ip, w42               /* ip = W4 | (W2 << 16) */
253         ldr    r3, [r0, #8]          /* r3 = row[3,1] */
254         idct_row COL_SHIFT
255         pop    {r1}
256         idct_finish_shift COL_SHIFT
257
258         strh   r4, [r1]
259         strh   r5, [r1, #(16*1)]
260         strh   r6, [r1, #(16*2)]
261         strh   r7, [r1, #(16*3)]
262         strh   r11,[r1, #(16*4)]
263         strh   r10,[r1, #(16*5)]
264         strh   r9, [r1, #(16*6)]
265         strh   r8, [r1, #(16*7)]
266
267         pop    {pc}
268 endfunc
269
270 /*
271   Compute IDCT of single column, read as row, store saturated 8-bit.
272   r0 = source
273   r1 = dest
274   r2 = line size
275 */
276 function idct_col_put_armv6
277         push   {r1, r2, lr}
278
279         ldr    r2, [r0]              /* r2 = row[2,0] */
280         ldr    ip, w42               /* ip = W4 | (W2 << 16) */
281         ldr    r3, [r0, #8]          /* r3 = row[3,1] */
282         idct_row COL_SHIFT
283         pop    {r1, r2}
284         idct_finish_shift_sat COL_SHIFT
285
286         strb_post r4, r1, r2
287         strb_post r5, r1, r2
288         strb_post r6, r1, r2
289         strb_post r7, r1, r2
290         strb_post r11,r1, r2
291         strb_post r10,r1, r2
292         strb_post r9, r1, r2
293         strb_post r8, r1, r2
294
295         sub    r1, r1, r2, lsl #3
296
297         pop    {pc}
298 endfunc
299
300 /*
301   Compute IDCT of single column, read as row, add/store saturated 8-bit.
302   r0 = source
303   r1 = dest
304   r2 = line size
305 */
306 function idct_col_add_armv6
307         push   {r1, r2, lr}
308
309         ldr    r2, [r0]              /* r2 = row[2,0] */
310         ldr    ip, w42               /* ip = W4 | (W2 << 16) */
311         ldr    r3, [r0, #8]          /* r3 = row[3,1] */
312         idct_row COL_SHIFT
313         pop    {r1, r2}
314         idct_finish
315
316         ldrb   r3, [r1]
317         ldrb   r7, [r1, r2]
318         ldrb   r11,[r1, r2, lsl #2]
319         add    ip, r3, ip, asr #COL_SHIFT
320         usat   ip, #8, ip
321         add    r4, r7, r4, asr #COL_SHIFT
322         strb_post ip, r1, r2
323         ldrb   ip, [r1, r2]
324         usat   r4, #8, r4
325         ldrb   r11,[r1, r2, lsl #2]
326         add    r5, ip, r5, asr #COL_SHIFT
327         usat   r5, #8, r5
328         strb_post r4, r1, r2
329         ldrb   r3, [r1, r2]
330         ldrb   ip, [r1, r2, lsl #2]
331         strb_post r5, r1, r2
332         ldrb   r7, [r1, r2]
333         ldrb   r4, [r1, r2, lsl #2]
334         add    r6, r3, r6, asr #COL_SHIFT
335         usat   r6, #8, r6
336         add    r10,r7, r10,asr #COL_SHIFT
337         usat   r10,#8, r10
338         add    r9, r11,r9, asr #COL_SHIFT
339         usat   r9, #8, r9
340         add    r8, ip, r8, asr #COL_SHIFT
341         usat   r8, #8, r8
342         add    lr, r4, lr, asr #COL_SHIFT
343         usat   lr, #8, lr
344         strb_post r6, r1, r2
345         strb_post r10,r1, r2
346         strb_post r9, r1, r2
347         strb_post r8, r1, r2
348         strb_post lr, r1, r2
349
350         sub    r1, r1, r2, lsl #3
351
352         pop    {pc}
353 endfunc
354
355 /*
356   Compute 8 IDCT row transforms.
357   func = IDCT row->col function
358   width = width of columns in bytes
359 */
360         .macro idct_rows func width
361         bl     \func
362         add    r0, r0, #(16*2)
363         add    r1, r1, #\width
364         bl     \func
365         add    r0, r0, #(16*2)
366         add    r1, r1, #\width
367         bl     \func
368         add    r0, r0, #(16*2)
369         add    r1, r1, #\width
370         bl     \func
371         sub    r0, r0, #(16*5)
372         add    r1, r1, #\width
373         bl     \func
374         add    r0, r0, #(16*2)
375         add    r1, r1, #\width
376         bl     \func
377         add    r0, r0, #(16*2)
378         add    r1, r1, #\width
379         bl     \func
380         add    r0, r0, #(16*2)
381         add    r1, r1, #\width
382         bl     \func
383
384         sub    r0, r0, #(16*7)
385         .endm
386
387 /* void ff_simple_idct_armv6(DCTELEM *data); */
388 function ff_simple_idct_armv6, export=1
389         push   {r4-r11, lr}
390         sub    sp, sp, #128
391
392         mov    r1, sp
393         idct_rows idct_row_armv6, 2
394         mov    r1, r0
395         mov    r0, sp
396         idct_rows idct_col_armv6, 2
397
398         add    sp, sp, #128
399         pop    {r4-r11, pc}
400 endfunc
401
402 /* ff_simple_idct_add_armv6(uint8_t *dest, int line_size, DCTELEM *data); */
403 function ff_simple_idct_add_armv6, export=1
404         push   {r0, r1, r4-r11, lr}
405         sub    sp, sp, #128
406
407         mov    r0, r2
408         mov    r1, sp
409         idct_rows idct_row_armv6, 2
410         mov    r0, sp
411         ldr    r1, [sp, #128]
412         ldr    r2, [sp, #(128+4)]
413         idct_rows idct_col_add_armv6, 1
414
415         add    sp, sp, #(128+8)
416         pop    {r4-r11, pc}
417 endfunc
418
419 /* ff_simple_idct_put_armv6(uint8_t *dest, int line_size, DCTELEM *data); */
420 function ff_simple_idct_put_armv6, export=1
421         push   {r0, r1, r4-r11, lr}
422         sub    sp, sp, #128
423
424         mov    r0, r2
425         mov    r1, sp
426         idct_rows idct_row_armv6, 2
427         mov    r0, sp
428         ldr    r1, [sp, #128]
429         ldr    r2, [sp, #(128+4)]
430         idct_rows idct_col_put_armv6, 1
431
432         add    sp, sp, #(128+8)
433         pop    {r4-r11, pc}
434 endfunc