d841802158f3f91cdf2e8bff675306511ca19105
[ffmpeg.git] / libavcodec / arm / fmtconvert_vfp.S
1 /*
2  * Copyright (c) 2008 Siarhei Siamashka <ssvb@users.sourceforge.net>
3  * Copyright (c) 2013 RISC OS Open Ltd <bavison@riscosopen.org>
4  *
5  * This file is part of Libav.
6  *
7  * Libav is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Lesser General Public
9  * License as published by the Free Software Foundation; either
10  * version 2.1 of the License, or (at your option) any later version.
11  *
12  * Libav is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  * Lesser General Public License for more details.
16  *
17  * You should have received a copy of the GNU Lesser General Public
18  * License along with Libav; if not, write to the Free Software
19  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20  */
21
22 #include "config.h"
23 #include "libavutil/arm/asm.S"
24
25 /**
26  * ARM VFP optimized float to int16 conversion.
27  * Assume that len is a positive number and is multiple of 8, destination
28  * buffer is at least 4 bytes aligned (8 bytes alignment is better for
29  * performance), little-endian byte sex.
30  */
31 @ void ff_float_to_int16_vfp(int16_t *dst, const float *src, int len)
32 function ff_float_to_int16_vfp, export=1
33         push            {r4-r8,lr}
34         vpush           {d8-d11}
35         vldmia          r1!, {s16-s23}
36         vcvt.s32.f32    s0,  s16
37         vcvt.s32.f32    s1,  s17
38         vcvt.s32.f32    s2,  s18
39         vcvt.s32.f32    s3,  s19
40         vcvt.s32.f32    s4,  s20
41         vcvt.s32.f32    s5,  s21
42         vcvt.s32.f32    s6,  s22
43         vcvt.s32.f32    s7,  s23
44 1:
45         subs            r2,  r2,  #8
46         vmov            r3,  r4,  s0, s1
47         vmov            r5,  r6,  s2, s3
48         vmov            r7,  r8,  s4, s5
49         vmov            ip,  lr,  s6, s7
50         it              gt
51         vldmiagt        r1!, {s16-s23}
52         ssat            r4,  #16, r4
53         ssat            r3,  #16, r3
54         ssat            r6,  #16, r6
55         ssat            r5,  #16, r5
56         pkhbt           r3,  r3,  r4, lsl #16
57         pkhbt           r4,  r5,  r6, lsl #16
58         itttt           gt
59         vcvtgt.s32.f32  s0,  s16
60         vcvtgt.s32.f32  s1,  s17
61         vcvtgt.s32.f32  s2,  s18
62         vcvtgt.s32.f32  s3,  s19
63         itttt           gt
64         vcvtgt.s32.f32  s4,  s20
65         vcvtgt.s32.f32  s5,  s21
66         vcvtgt.s32.f32  s6,  s22
67         vcvtgt.s32.f32  s7,  s23
68         ssat            r8,  #16, r8
69         ssat            r7,  #16, r7
70         ssat            lr,  #16, lr
71         ssat            ip,  #16, ip
72         pkhbt           r5,  r7,  r8, lsl #16
73         pkhbt           r6,  ip,  lr, lsl #16
74         stmia           r0!, {r3-r6}
75         bgt             1b
76
77         vpop            {d8-d11}
78         pop             {r4-r8,pc}
79 endfunc
80
81 /**
82  * ARM VFP optimised int32 to float conversion.
83  * Assume len is a multiple of 8, destination buffer is at least 4 bytes aligned
84  * (16 bytes alignment is best for BCM2835), little-endian.
85  */
86 @ void ff_int32_to_float_fmul_array8_vfp(FmtConvertContext *c, float *dst, const int32_t *src, const float *mul, int len)
87 function ff_int32_to_float_fmul_array8_vfp, export=1
88         push    {lr}
89         ldr     a1, [sp, #4]
90         subs    lr, a1, #3*8
91         bcc     50f                        @ too short to pipeline
92         @ Now need to find (len / 8) % 3. The approximation
93         @ x / 24 = (x * 0xAB) >> 12
94         @ is good for x < 4096, which is true for both AC3 and DCA.
95         mov     a1, #0xAB
96         ldr     ip, =0x03070000            @ RunFast mode, short vectors of length 8, stride 1
97         mul     a1, lr, a1
98         vpush   {s16-s31}
99         mov     a1, a1, lsr #12
100         add     a1, a1, a1, lsl #1
101         rsb     a1, a1, lr, lsr #3
102         cmp     a1, #1
103         fmrx    a1, FPSCR
104         fmxr    FPSCR, ip
105         beq     11f
106         blo     10f
107         @ Array is (2 + multiple of 3) x 8 floats long
108         @ drop through...
109         vldmia          a3!, {s16-s23}
110         vldmia          a4!, {s2,s3}
111         vldmia          a3!, {s24-s31}
112         vcvt.f32.s32    s16, s16
113         vcvt.f32.s32    s17, s17
114         vcvt.f32.s32    s18, s18
115         vcvt.f32.s32    s19, s19
116         vcvt.f32.s32    s20, s20
117         vcvt.f32.s32    s21, s21
118         vcvt.f32.s32    s22, s22
119         vcvt.f32.s32    s23, s23
120         vmul.f32        s16, s16, s2
121         @ drop through...
122 3:
123         vldmia          a3!, {s8-s15}
124         vldmia          a4!, {s1}
125         vcvt.f32.s32    s24, s24
126         vcvt.f32.s32    s25, s25
127         vcvt.f32.s32    s26, s26
128         vcvt.f32.s32    s27, s27
129         vcvt.f32.s32    s28, s28
130         vcvt.f32.s32    s29, s29
131         vcvt.f32.s32    s30, s30
132         vcvt.f32.s32    s31, s31
133         vmul.f32        s24, s24, s3
134         vstmia          a2!, {s16-s19}
135         vstmia          a2!, {s20-s23}
136 2:
137         vldmia          a3!, {s16-s23}
138         vldmia          a4!, {s2}
139         vcvt.f32.s32    s8, s8
140         vcvt.f32.s32    s9, s9
141         vcvt.f32.s32    s10, s10
142         vcvt.f32.s32    s11, s11
143         vcvt.f32.s32    s12, s12
144         vcvt.f32.s32    s13, s13
145         vcvt.f32.s32    s14, s14
146         vcvt.f32.s32    s15, s15
147         vmul.f32        s8, s8, s1
148         vstmia          a2!, {s24-s27}
149         vstmia          a2!, {s28-s31}
150 1:
151         vldmia          a3!, {s24-s31}
152         vldmia          a4!, {s3}
153         vcvt.f32.s32    s16, s16
154         vcvt.f32.s32    s17, s17
155         vcvt.f32.s32    s18, s18
156         vcvt.f32.s32    s19, s19
157         vcvt.f32.s32    s20, s20
158         vcvt.f32.s32    s21, s21
159         vcvt.f32.s32    s22, s22
160         vcvt.f32.s32    s23, s23
161         vmul.f32        s16, s16, s2
162         vstmia          a2!, {s8-s11}
163         vstmia          a2!, {s12-s15}
164
165         subs            lr, lr, #8*3
166         bpl             3b
167
168         vcvt.f32.s32    s24, s24
169         vcvt.f32.s32    s25, s25
170         vcvt.f32.s32    s26, s26
171         vcvt.f32.s32    s27, s27
172         vcvt.f32.s32    s28, s28
173         vcvt.f32.s32    s29, s29
174         vcvt.f32.s32    s30, s30
175         vcvt.f32.s32    s31, s31
176         vmul.f32        s24, s24, s3
177         vstmia          a2!, {s16-s19}
178         vstmia          a2!, {s20-s23}
179         vstmia          a2!, {s24-s27}
180         vstmia          a2!, {s28-s31}
181
182         fmxr    FPSCR, a1
183         vpop    {s16-s31}
184         pop     {pc}
185
186 10:     @ Array is (multiple of 3) x 8 floats long
187         vldmia          a3!, {s8-s15}
188         vldmia          a4!, {s1,s2}
189         vldmia          a3!, {s16-s23}
190         vcvt.f32.s32    s8, s8
191         vcvt.f32.s32    s9, s9
192         vcvt.f32.s32    s10, s10
193         vcvt.f32.s32    s11, s11
194         vcvt.f32.s32    s12, s12
195         vcvt.f32.s32    s13, s13
196         vcvt.f32.s32    s14, s14
197         vcvt.f32.s32    s15, s15
198         vmul.f32        s8, s8, s1
199         b               1b
200
201 11:     @ Array is (1 + multiple of 3) x 8 floats long
202         vldmia          a3!, {s24-s31}
203         vldmia          a4!, {s3}
204         vldmia          a3!, {s8-s15}
205         vldmia          a4!, {s1}
206         vcvt.f32.s32    s24, s24
207         vcvt.f32.s32    s25, s25
208         vcvt.f32.s32    s26, s26
209         vcvt.f32.s32    s27, s27
210         vcvt.f32.s32    s28, s28
211         vcvt.f32.s32    s29, s29
212         vcvt.f32.s32    s30, s30
213         vcvt.f32.s32    s31, s31
214         vmul.f32        s24, s24, s3
215         b               2b
216
217 50:
218         ldr     lr, =0x03070000         @ RunFast mode, short vectors of length 8, stride 1
219         fmrx    ip, FPSCR
220         fmxr    FPSCR, lr
221 51:
222         vldmia          a3!, {s8-s15}
223         vldmia          a4!, {s0}
224         vcvt.f32.s32    s8, s8
225         vcvt.f32.s32    s9, s9
226         vcvt.f32.s32    s10, s10
227         vcvt.f32.s32    s11, s11
228         vcvt.f32.s32    s12, s12
229         vcvt.f32.s32    s13, s13
230         vcvt.f32.s32    s14, s14
231         vcvt.f32.s32    s15, s15
232         vmul.f32        s8, s8, s0
233         subs            a1, a1, #8
234         vstmia          a2!, {s8-s11}
235         vstmia          a2!, {s12-s15}
236         bne             51b
237
238         fmxr    FPSCR, ip
239         pop     {pc}
240 endfunc
241
242 /**
243  * ARM VFP optimised int32 to float conversion.
244  * Assume len is a multiple of 8, destination buffer is at least 4 bytes aligned
245  * (16 bytes alignment is best for BCM2835), little-endian.
246  * TODO: could be further optimised by unrolling and interleaving, as above
247  */
248 @ void ff_int32_to_float_fmul_scalar_vfp(float *dst, const int32_t *src, float mul, int len)
249 function ff_int32_to_float_fmul_scalar_vfp, export=1
250 VFP     tmp     .req    a4
251 VFP     len     .req    a3
252 NOVFP   tmp     .req    a3
253 NOVFP   len     .req    a4
254 NOVFP   vmov    s0, a3
255         ldr     tmp, =0x03070000           @ RunFast mode, short vectors of length 8, stride 1
256         fmrx    ip, FPSCR
257         fmxr    FPSCR, tmp
258 1:
259         vldmia          a2!, {s8-s15}
260         vcvt.f32.s32    s8, s8
261         vcvt.f32.s32    s9, s9
262         vcvt.f32.s32    s10, s10
263         vcvt.f32.s32    s11, s11
264         vcvt.f32.s32    s12, s12
265         vcvt.f32.s32    s13, s13
266         vcvt.f32.s32    s14, s14
267         vcvt.f32.s32    s15, s15
268         vmul.f32        s8, s8, s0
269         subs            len, len, #8
270         vstmia          a1!, {s8-s11}
271         vstmia          a1!, {s12-s15}
272         bne             1b
273
274         fmxr    FPSCR, ip
275         bx      lr
276 endfunc
277         .unreq  tmp
278         .unreq  len