]> git.sesse.net Git - ffmpeg/blob - libavcodec/arm/hevcdsp_idct_neon.S
doc: set documentencoding on toplevel texi files.
[ffmpeg] / libavcodec / arm / hevcdsp_idct_neon.S
1 /*
2  * Copyright (c) 2014 Seppo Tomperi <seppo.tomperi@vtt.fi>
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 "libavutil/arm/asm.S"
22 #include "neon.S"
23
24 .code 32
25
26 function ff_hevc_idct_4x4_dc_neon_8, export=1
27         ldrsh       r1, [r0]
28         ldr         r2, =0x20
29         add         r1, #1
30         asr         r1, #1
31         add         r1, r2
32         asr         r1, #6
33         vdup.16     q0, r1
34         vdup.16     q1, r1
35         vst1.16     {q0, q1}, [r0]
36         bx lr
37 endfunc
38
39 function ff_hevc_idct_8x8_dc_neon_8, export=1
40         ldrsh       r1, [r0]
41         ldr         r2, =0x20
42         add         r1, #1
43         asr         r1, #1
44         add         r1, r2
45         asr         r1, #6
46         vdup.16     q8, r1
47         vdup.16     q9, r1
48         vmov.16     q10, q8
49         vmov.16     q11, q8
50         vmov.16     q12, q8
51         vmov.16     q13, q8
52         vmov.16     q14, q8
53         vmov.16     q15, q8
54         vstm        r0, {q8-q15}
55         bx lr
56 endfunc
57
58 function ff_hevc_idct_16x16_dc_neon_8, export=1
59         ldrsh       r1, [r0]
60         ldr         r2, =0x20
61         add         r1, #1
62         asr         r1, #1
63         add         r1, r2
64         asr         r1, #6
65         vdup.16     q8, r1
66         vdup.16     q9, r1
67         vmov.16     q10, q8
68         vmov.16     q11, q8
69         vmov.16     q12, q8
70         vmov.16     q13, q8
71         vmov.16     q14, q8
72         vmov.16     q15, q8
73         vstm        r0!, {q8-q15}
74         vstm        r0!, {q8-q15}
75         vstm        r0!, {q8-q15}
76         vstm        r0, {q8-q15}
77         bx lr
78 endfunc
79
80 function ff_hevc_idct_32x32_dc_neon_8, export=1
81         ldrsh       r1, [r0]
82         ldr         r2, =0x20
83         add         r1, #1
84         asr         r1, #1
85         add         r1, r2
86         asr         r1, #6
87         mov         r3, #16
88         vdup.16     q8, r1
89         vdup.16     q9, r1
90         vmov.16     q10, q8
91         vmov.16     q11, q8
92         vmov.16     q12, q8
93         vmov.16     q13, q8
94         vmov.16     q14, q8
95         vmov.16     q15, q8
96 1:      subs        r3, #1
97         vstm        r0!, {q8-q15}
98         bne         1b
99         bx lr
100 endfunc
101
102 function ff_hevc_transform_add_4x4_neon_8, export=1
103         vldm        r1, {q0-q1}
104         vld1.32     d4[0], [r0], r2
105         vld1.32     d4[1], [r0], r2
106         vld1.32     d5[0], [r0], r2
107         vld1.32     d5[1], [r0], r2
108         sub         r0, r0, r2, lsl #2
109         vmovl.u8    q8, d4
110         vmovl.u8    q9, d5
111         vqadd.s16   q0, q0, q8
112         vqadd.s16   q1, q1, q9
113         vqmovun.s16 d0, q0
114         vqmovun.s16 d1, q1
115         vst1.32     d0[0], [r0], r2
116         vst1.32     d0[1], [r0], r2
117         vst1.32     d1[0], [r0], r2
118         vst1.32     d1[1], [r0], r2
119         bx          lr
120 endfunc
121
122 function ff_hevc_transform_add_8x8_neon_8, export=1
123         mov         r3,   #8
124 1:      subs        r3,   #1
125         vld1.16     {q0}, [r1]!
126         vld1.8      d16,  [r0]
127         vmovl.u8    q8,   d16
128         vqadd.s16   q0,   q8
129         vqmovun.s16 d0,   q0
130         vst1.32     d0,   [r0], r2
131         bne         1b
132         bx          lr
133 endfunc
134
135 function ff_hevc_transform_add_16x16_neon_8, export=1
136         mov         r3,   #16
137 1:      subs        r3,   #1
138         vld1.16     {q0, q1}, [r1]!
139         vld1.8      {q8},  [r0]
140         vmovl.u8    q9,  d16
141         vmovl.u8    q10, d17
142         vqadd.s16   q0,  q9
143         vqadd.s16   q1,  q10
144         vqmovun.s16 d0,  q0
145         vqmovun.s16 d1,  q1
146         vst1.8      {q0},   [r0], r2
147         bne         1b
148         bx          lr
149 endfunc
150
151 function ff_hevc_transform_add_32x32_neon_8, export=1
152         mov         r3,   #32
153 1:      subs        r3,   #1
154         vldm        r1!, {q0-q3}
155         vld1.8      {q8, q9},  [r0]
156         vmovl.u8    q10, d16
157         vmovl.u8    q11, d17
158         vmovl.u8    q12, d18
159         vmovl.u8    q13, d19
160         vqadd.s16   q0,  q10
161         vqadd.s16   q1,  q11
162         vqadd.s16   q2,  q12
163         vqadd.s16   q3,  q13
164         vqmovun.s16 d0,  q0
165         vqmovun.s16 d1,  q1
166         vqmovun.s16 d2,  q2
167         vqmovun.s16 d3,  q3
168         vst1.8     {q0, q1},   [r0], r2
169         bne         1b
170         bx          lr
171 endfunc
172
173 .macro  transpose_16b_8x8   r0, r1, r2, r3, r4, r5, r6, r7
174         vtrn.64         \r0, \r4
175         vtrn.64         \r1, \r5
176         vtrn.64         \r2, \r6
177         vtrn.64         \r3, \r7
178         vtrn.32         \r0, \r2
179         vtrn.32         \r1, \r3
180         vtrn.32         \r4, \r6
181         vtrn.32         \r5, \r7
182         vtrn.16         \r0, \r1
183         vtrn.16         \r2, \r3
184         vtrn.16         \r4, \r5
185         vtrn.16         \r6, \r7
186 .endm
187
188 // in 4 q regs
189 // output 8 d regs
190 .macro transpose_16b_4x4    r0, r1, r2, r3
191         vtrn.32         \r0, \r2
192         vtrn.32         \r1, \r3
193         vtrn.16         \r0, \r1
194         vtrn.16         \r2, \r3
195 .endm
196
197 /* uses registers q2 - q9 for temp values */
198 /* TODO: reorder */
199 .macro tr4_luma_shift r0, r1, r2, r3, shift
200         vaddl.s16   q5, \r0, \r2    // c0 = src0 + src2
201         vaddl.s16   q2, \r2, \r3    // c1 = src2 + src3
202         vsubl.s16   q4, \r0, \r3    // c2 = src0 - src3
203         vmull.s16   q6, \r1, d0[0]  // c3 = 74 * src1
204
205         vaddl.s16   q7, \r0, \r3    // src0 + src3
206         vsubw.s16   q7, q7, \r2     // src0 - src2 + src3
207         vmul.s32    q7, q7, d0[0]   // dst2 = 74 * (src0 - src2 + src3)
208
209         vmul.s32    q8, q5, d0[1]   // 29 * c0
210         vmul.s32    q9, q2, d1[0]   // 55 * c1
211         vadd.s32    q8, q9          // 29 * c0 + 55 * c1
212         vadd.s32    q8, q6          // dst0 = 29 * c0 + 55 * c1 + c3
213
214         vmul.s32    q2, q2, d0[1]   // 29 * c1
215         vmul.s32    q9, q4, d1[0]   // 55 * c2
216         vsub.s32    q9, q2          // 55 * c2 - 29 * c1
217         vadd.s32    q9, q6          // dst1 = 55 * c2 - 29 * c1 + c3
218
219         vmul.s32    q5, q5, d1[0]   // 55 * c0
220         vmul.s32    q4, q4, d0[1]   // 29 * c2
221         vadd.s32    q5, q4          // 55 * c0 + 29 * c2
222         vsub.s32    q5, q6          // dst3 = 55 * c0 + 29 * c2 - c3
223
224         vqrshrn.s32   \r0, q8, \shift
225         vqrshrn.s32   \r1, q9, \shift
226         vqrshrn.s32   \r2, q7, \shift
227         vqrshrn.s32   \r3, q5, \shift
228 .endm
229
230 /* uses registers q2 - q6 for temp values */
231 .macro tr4 r0, r1, r2, r3
232         vmull.s16  q4, \r1, d0[0]   // 83 * src1
233         vmull.s16  q6, \r1, d0[1]   // 36 * src1
234         vshll.s16  q2, \r0, #6   // 64 * src0
235         vshll.s16  q3, \r2, #6   // 64 * src2
236         vadd.s32   q5, q2, q3    // 64 * (src0 + src2)     e0
237         vsub.s32   q2, q2, q3    // 64 * (src0 - src2)     e1
238         vmlal.s16  q4, \r3, d0[1]   // 83 * src1 + 36 * src3  o0
239         vmlsl.s16  q6, \r3, d0[0]   // 36 * src1 - 83 * src3  o1
240
241         vsub.s32   q3, q5, q4    // e0 - o0
242         vadd.s32   q4, q5, q4    // e0 + o0
243         vadd.s32   q5, q2, q6    // e1 + o1
244         vsub.s32   q6, q2, q6    // e1 - o1
245 .endm
246
247 .macro tr4_shift r0, r1, r2, r3, shift
248         vmull.s16  q4, \r1, d0[0]   // 83 * src1
249         vmull.s16  q6, \r1, d0[1]   // 36 * src1
250         vshll.s16  q2, \r0, #6   // 64 * src0
251         vshll.s16  q3, \r2, #6   // 64 * src2
252         vadd.s32   q5, q2, q3    // 64 * (src0 + src2)     e0
253         vsub.s32   q2, q2, q3    // 64 * (src0 - src2)     e1
254         vmlal.s16  q4, \r3, d0[1]   // 83 * src1 + 36 * src3  o0
255         vmlsl.s16  q6, \r3, d0[0]   // 36 * src1 - 83 * src3  o1
256
257         vsub.s32   q3, q5, q4    // e0 - o0
258         vadd.s32   q4, q5, q4    // e0 + o0
259         vadd.s32   q5, q2, q6    // e1 + o1
260         vsub.s32   q6, q2, q6    // e1 - o1
261
262         vqrshrn.s32   \r0, q4, \shift
263         vqrshrn.s32   \r1, q5, \shift
264         vqrshrn.s32   \r2, q6, \shift
265         vqrshrn.s32   \r3, q3, \shift
266 .endm
267
268 function ff_hevc_transform_4x4_neon_8, export=1
269         vpush       {d8-d15}
270         vld1.16     {q14, q15}, [r0]  // coeffs
271         ldr         r3, =0x00240053 // 36 and 83
272         vmov.32     d0[0], r3
273
274         tr4_shift d28, d29, d30, d31, #7
275
276         vtrn.16     d28, d29
277         vtrn.16     d30, d31
278         vtrn.32     q14, q15
279
280         tr4_shift d28, d29, d30, d31, #12
281
282         vtrn.16     d28, d29
283         vtrn.16     d30, d31
284         vtrn.32     q14, q15
285
286         vst1.16     {q14, q15}, [r0]
287         vpop        {d8-d15}
288         bx lr
289 endfunc
290
291 function ff_hevc_transform_luma_4x4_neon_8, export=1
292         vpush       {d8-d15}
293         vld1.16     {q14, q15}, [r0]  // coeffs
294         ldr         r3, =0x4a  // 74
295         vmov.32     d0[0], r3
296         ldr         r3, =0x1d  // 29
297         vmov.32     d0[1], r3
298         ldr         r3, =0x37  // 55
299         vmov.32     d1[0], r3
300
301         tr4_luma_shift d28, d29, d30, d31, #7
302
303         vtrn.16     d28, d29
304         vtrn.16     d30, d31
305         vtrn.32     q14, q15
306
307         tr4_luma_shift d28, d29, d30, d31, #12
308
309         vtrn.16     d28, d29
310         vtrn.16     d30, d31
311         vtrn.32     q14, q15
312         vst1.16     {q14, q15}, [r0]
313         vpop        {d8-d15}
314         bx lr
315 endfunc
316
317 .macro tr8_begin in0, in1, in2, in3
318         vmull.s16  q7, \in0, d1[1]   // 89 * src1
319         vmull.s16  q8, \in0, d1[0]   // 75 * src1
320         vmull.s16  q9, \in0, d1[3]   // 50 * src1
321         vmull.s16  q10, \in0, d1[2]  // 18 * src1
322
323         vmlal.s16  q7, \in1, d1[0]   // 75 * src3
324         vmlsl.s16  q8, \in1, d1[2]   //-18 * src3
325         vmlsl.s16  q9, \in1, d1[1]   //-89 * src3
326         vmlsl.s16  q10, \in1, d1[3]  //-50 * src3
327
328         vmlal.s16  q7, \in2, d1[3]   // 50 * src5
329         vmlsl.s16  q8, \in2, d1[1]   //-89 * src5
330         vmlal.s16  q9, \in2, d1[2]   // 18 * src5
331         vmlal.s16  q10, \in2, d1[0]  // 75 * src5
332
333         vmlal.s16  q7, \in3, d1[2]   // 18 * src7
334         vmlsl.s16  q8, \in3, d1[3]   //-50 * src7
335         vmlal.s16  q9, \in3, d1[0]   // 75 * src7
336         vmlsl.s16  q10, \in3, d1[1]  //-89 * src7
337 .endm
338
339 .macro tr8_end shift
340         vadd.s32   q1, q4, q7   //  e_8[0] + o_8[0], dst[0]
341         vsub.s32   q4, q4, q7   //  e_8[0] - o_8[0], dst[7]
342
343         vadd.s32   q2, q5, q8   // e_8[1] + o_8[1], dst[1]
344         vsub.s32   q5, q5, q8   // e_8[1] - o_8[1], dst[6]
345
346         vadd.s32   q11, q6, q9  // e_8[2] + o_8[2], dst[2]
347         vsub.s32    q6, q6, q9  // e_8[2] - o_8[2], dst[5]
348
349         vadd.s32   q12, q3, q10 // e_8[3] + o_8[3], dst[3]
350         vsub.s32   q3, q3, q10  // e_8[3] - o_8[3], dst[4]
351         vqrshrn.s32   d2, q1, \shift
352         vqrshrn.s32   d3, q2, \shift
353         vqrshrn.s32   d4, q11, \shift
354         vqrshrn.s32   d5, q12, \shift
355         vqrshrn.s32   d6, q3, \shift
356         vqrshrn.s32   d7, q6, \shift
357         vqrshrn.s32   d9, q4, \shift
358         vqrshrn.s32   d8, q5, \shift
359 .endm
360
361 function ff_hevc_transform_8x8_neon_8, export=1
362         push   {r4-r8}
363         vpush {d8-d15}
364         mov    r5, #16
365
366         adr       r3, tr4f
367         vld1.16   {d0, d1}, [r3]
368
369         // left half
370         vld1.16 {d24}, [r0], r5
371         vld1.16 {d25}, [r0], r5
372         vld1.16 {d26}, [r0], r5
373         vld1.16 {d27}, [r0], r5
374         vld1.16 {d28}, [r0], r5
375         vld1.16 {d29}, [r0], r5
376         vld1.16 {d30}, [r0], r5
377         vld1.16 {d31}, [r0], r5
378         sub      r0, #128
379         tr8_begin d25, d27, d29, d31
380         tr4       d24, d26, d28, d30
381         tr8_end   #7
382         vst1.16 {d2}, [r0], r5
383         vst1.16 {d3}, [r0], r5
384         vst1.16 {d4}, [r0], r5
385         vst1.16 {d5}, [r0], r5
386         vst1.16 {d6}, [r0], r5
387         vst1.16 {d7}, [r0], r5
388         vst1.16 {d8}, [r0], r5
389         vst1.16 {d9}, [r0], r5
390         sub      r0, #128
391         //skip right half if col_limit in r1 is less than 4
392         cmp      r1, #4
393         blt      1f
394         //right half
395         add      r0, #8
396         vld1.16 {d24}, [r0], r5
397         vld1.16 {d25}, [r0], r5
398         vld1.16 {d26}, [r0], r5
399         vld1.16 {d27}, [r0], r5
400         vld1.16 {d28}, [r0], r5
401         vld1.16 {d29}, [r0], r5
402         vld1.16 {d30}, [r0], r5
403         vld1.16 {d31}, [r0], r5
404         sub      r0, #128
405         tr8_begin d25, d27, d29, d31
406         tr4       d24, d26, d28, d30
407         tr8_end   #7
408         vst1.16 {d2}, [r0], r5
409         vst1.16 {d3}, [r0], r5
410         vst1.16 {d4}, [r0], r5
411         vst1.16 {d5}, [r0], r5
412         vst1.16 {d6}, [r0], r5
413         vst1.16 {d7}, [r0], r5
414         vst1.16 {d8}, [r0], r5
415         vst1.16 {d9}, [r0], r5
416         sub      r0, #136
417 1:
418         // top half
419         vldm r0, {q12-q15} // coeffs
420         transpose_16b_4x4 d24, d26, d28, d30
421         transpose_16b_4x4 d25, d27, d29, d31
422         tr8_begin d26, d30, d27, d31
423         tr4 d24, d28, d25, d29
424         tr8_end #12
425         transpose_16b_4x4 d2, d3, d4, d5
426         transpose_16b_4x4 d6, d7, d8, d9
427         vswp     d7, d5
428         vswp     d7, d8
429         vswp     d3, d6
430         vswp     d6, d4
431         vstm r0!, {q1-q4}
432
433         // bottom half
434         vldm r0, {q12-q15} // coeffs
435         transpose_16b_4x4 d24, d26, d28, d30
436         transpose_16b_4x4 d25, d27, d29, d31
437         tr8_begin d26, d30, d27, d31
438         tr4 d24, d28, d25, d29
439         tr8_end #12
440         transpose_16b_4x4 d2, d3, d4, d5
441         transpose_16b_4x4 d6, d7, d8, d9
442         vswp     d7, d5
443         vswp     d7, d8
444         vswp     d3, d6
445         vswp     d6, d4
446         //vstm     r0, {q1-q4}
447         vst1.16 {q1-q2}, [r0]
448         add     r0, #32
449         vst1.16 {q3-q4}, [r0]
450         sub     r0, #32
451         vpop {d8-d15}
452         pop {r4-r8}
453         bx lr
454 endfunc
455
456 .align 4
457 tr4f:
458 .word 0x00240053  // 36 and d1[0] = 83
459 .word 0x00000000
460 tr8f:
461 .word 0x0059004b  // 89, d0[0] = 75
462 .word 0x00320012  // 50, d0[2] = 18
463 tr16:
464 .word 0x005a0057  // 90, d2[0] = 87
465 .word 0x00500046  // 80, d2[2] = 70
466 .word 0x0039002b  // 57, d2[0] = 43
467 .word 0x00190009  // 25, d2[2] = 9