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