summaryrefslogtreecommitdiff
path: root/libavcodec/arm/fmtconvert_vfp.S
blob: d841802158f3f91cdf2e8bff675306511ca19105 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
/*
 * Copyright (c) 2008 Siarhei Siamashka <ssvb@users.sourceforge.net>
 * Copyright (c) 2013 RISC OS Open Ltd <bavison@riscosopen.org>
 *
 * This file is part of Libav.
 *
 * Libav is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * Libav is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with Libav; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
 */

#include "config.h"
#include "libavutil/arm/asm.S"

/**
 * ARM VFP optimized float to int16 conversion.
 * Assume that len is a positive number and is multiple of 8, destination
 * buffer is at least 4 bytes aligned (8 bytes alignment is better for
 * performance), little-endian byte sex.
 */
@ void ff_float_to_int16_vfp(int16_t *dst, const float *src, int len)
function ff_float_to_int16_vfp, export=1
        push            {r4-r8,lr}
        vpush           {d8-d11}
        vldmia          r1!, {s16-s23}
        vcvt.s32.f32    s0,  s16
        vcvt.s32.f32    s1,  s17
        vcvt.s32.f32    s2,  s18
        vcvt.s32.f32    s3,  s19
        vcvt.s32.f32    s4,  s20
        vcvt.s32.f32    s5,  s21
        vcvt.s32.f32    s6,  s22
        vcvt.s32.f32    s7,  s23
1:
        subs            r2,  r2,  #8
        vmov            r3,  r4,  s0, s1
        vmov            r5,  r6,  s2, s3
        vmov            r7,  r8,  s4, s5
        vmov            ip,  lr,  s6, s7
        it              gt
        vldmiagt        r1!, {s16-s23}
        ssat            r4,  #16, r4
        ssat            r3,  #16, r3
        ssat            r6,  #16, r6
        ssat            r5,  #16, r5
        pkhbt           r3,  r3,  r4, lsl #16
        pkhbt           r4,  r5,  r6, lsl #16
        itttt           gt
        vcvtgt.s32.f32  s0,  s16
        vcvtgt.s32.f32  s1,  s17
        vcvtgt.s32.f32  s2,  s18
        vcvtgt.s32.f32  s3,  s19
        itttt           gt
        vcvtgt.s32.f32  s4,  s20
        vcvtgt.s32.f32  s5,  s21
        vcvtgt.s32.f32  s6,  s22
        vcvtgt.s32.f32  s7,  s23
        ssat            r8,  #16, r8
        ssat            r7,  #16, r7
        ssat            lr,  #16, lr
        ssat            ip,  #16, ip
        pkhbt           r5,  r7,  r8, lsl #16
        pkhbt           r6,  ip,  lr, lsl #16
        stmia           r0!, {r3-r6}
        bgt             1b

        vpop            {d8-d11}
        pop             {r4-r8,pc}
endfunc

/**
 * ARM VFP optimised int32 to float conversion.
 * Assume len is a multiple of 8, destination buffer is at least 4 bytes aligned
 * (16 bytes alignment is best for BCM2835), little-endian.
 */
@ void ff_int32_to_float_fmul_array8_vfp(FmtConvertContext *c, float *dst, const int32_t *src, const float *mul, int len)
function ff_int32_to_float_fmul_array8_vfp, export=1
        push    {lr}
        ldr     a1, [sp, #4]
        subs    lr, a1, #3*8
        bcc     50f                        @ too short to pipeline
        @ Now need to find (len / 8) % 3. The approximation
        @ x / 24 = (x * 0xAB) >> 12
        @ is good for x < 4096, which is true for both AC3 and DCA.
        mov     a1, #0xAB
        ldr     ip, =0x03070000            @ RunFast mode, short vectors of length 8, stride 1
        mul     a1, lr, a1
        vpush   {s16-s31}
        mov     a1, a1, lsr #12
        add     a1, a1, a1, lsl #1
        rsb     a1, a1, lr, lsr #3
        cmp     a1, #1
        fmrx    a1, FPSCR
        fmxr    FPSCR, ip
        beq     11f
        blo     10f
        @ Array is (2 + multiple of 3) x 8 floats long
        @ drop through...
        vldmia          a3!, {s16-s23}
        vldmia          a4!, {s2,s3}
        vldmia          a3!, {s24-s31}
        vcvt.f32.s32    s16, s16
        vcvt.f32.s32    s17, s17
        vcvt.f32.s32    s18, s18
        vcvt.f32.s32    s19, s19
        vcvt.f32.s32    s20, s20
        vcvt.f32.s32    s21, s21
        vcvt.f32.s32    s22, s22
        vcvt.f32.s32    s23, s23
        vmul.f32        s16, s16, s2
        @ drop through...
3:
        vldmia          a3!, {s8-s15}
        vldmia          a4!, {s1}
        vcvt.f32.s32    s24, s24
        vcvt.f32.s32    s25, s25
        vcvt.f32.s32    s26, s26
        vcvt.f32.s32    s27, s27
        vcvt.f32.s32    s28, s28
        vcvt.f32.s32    s29, s29
        vcvt.f32.s32    s30, s30
        vcvt.f32.s32    s31, s31
        vmul.f32        s24, s24, s3
        vstmia          a2!, {s16-s19}
        vstmia          a2!, {s20-s23}
2:
        vldmia          a3!, {s16-s23}
        vldmia          a4!, {s2}
        vcvt.f32.s32    s8, s8
        vcvt.f32.s32    s9, s9
        vcvt.f32.s32    s10, s10
        vcvt.f32.s32    s11, s11
        vcvt.f32.s32    s12, s12
        vcvt.f32.s32    s13, s13
        vcvt.f32.s32    s14, s14
        vcvt.f32.s32    s15, s15
        vmul.f32        s8, s8, s1
        vstmia          a2!, {s24-s27}
        vstmia          a2!, {s28-s31}
1:
        vldmia          a3!, {s24-s31}
        vldmia          a4!, {s3}
        vcvt.f32.s32    s16, s16
        vcvt.f32.s32    s17, s17
        vcvt.f32.s32    s18, s18
        vcvt.f32.s32    s19, s19
        vcvt.f32.s32    s20, s20
        vcvt.f32.s32    s21, s21
        vcvt.f32.s32    s22, s22
        vcvt.f32.s32    s23, s23
        vmul.f32        s16, s16, s2
        vstmia          a2!, {s8-s11}
        vstmia          a2!, {s12-s15}

        subs            lr, lr, #8*3
        bpl             3b

        vcvt.f32.s32    s24, s24
        vcvt.f32.s32    s25, s25
        vcvt.f32.s32    s26, s26
        vcvt.f32.s32    s27, s27
        vcvt.f32.s32    s28, s28
        vcvt.f32.s32    s29, s29
        vcvt.f32.s32    s30, s30
        vcvt.f32.s32    s31, s31
        vmul.f32        s24, s24, s3
        vstmia          a2!, {s16-s19}
        vstmia          a2!, {s20-s23}
        vstmia          a2!, {s24-s27}
        vstmia          a2!, {s28-s31}

        fmxr    FPSCR, a1
        vpop    {s16-s31}
        pop     {pc}

10:     @ Array is (multiple of 3) x 8 floats long
        vldmia          a3!, {s8-s15}
        vldmia          a4!, {s1,s2}
        vldmia          a3!, {s16-s23}
        vcvt.f32.s32    s8, s8
        vcvt.f32.s32    s9, s9
        vcvt.f32.s32    s10, s10
        vcvt.f32.s32    s11, s11
        vcvt.f32.s32    s12, s12
        vcvt.f32.s32    s13, s13
        vcvt.f32.s32    s14, s14
        vcvt.f32.s32    s15, s15
        vmul.f32        s8, s8, s1
        b               1b

11:     @ Array is (1 + multiple of 3) x 8 floats long
        vldmia          a3!, {s24-s31}
        vldmia          a4!, {s3}
        vldmia          a3!, {s8-s15}
        vldmia          a4!, {s1}
        vcvt.f32.s32    s24, s24
        vcvt.f32.s32    s25, s25
        vcvt.f32.s32    s26, s26
        vcvt.f32.s32    s27, s27
        vcvt.f32.s32    s28, s28
        vcvt.f32.s32    s29, s29
        vcvt.f32.s32    s30, s30
        vcvt.f32.s32    s31, s31
        vmul.f32        s24, s24, s3
        b               2b

50:
        ldr     lr, =0x03070000         @ RunFast mode, short vectors of length 8, stride 1
        fmrx    ip, FPSCR
        fmxr    FPSCR, lr
51:
        vldmia          a3!, {s8-s15}
        vldmia          a4!, {s0}
        vcvt.f32.s32    s8, s8
        vcvt.f32.s32    s9, s9
        vcvt.f32.s32    s10, s10
        vcvt.f32.s32    s11, s11
        vcvt.f32.s32    s12, s12
        vcvt.f32.s32    s13, s13
        vcvt.f32.s32    s14, s14
        vcvt.f32.s32    s15, s15
        vmul.f32        s8, s8, s0
        subs            a1, a1, #8
        vstmia          a2!, {s8-s11}
        vstmia          a2!, {s12-s15}
        bne             51b

        fmxr    FPSCR, ip
        pop     {pc}
endfunc

/**
 * ARM VFP optimised int32 to float conversion.
 * Assume len is a multiple of 8, destination buffer is at least 4 bytes aligned
 * (16 bytes alignment is best for BCM2835), little-endian.
 * TODO: could be further optimised by unrolling and interleaving, as above
 */
@ void ff_int32_to_float_fmul_scalar_vfp(float *dst, const int32_t *src, float mul, int len)
function ff_int32_to_float_fmul_scalar_vfp, export=1
VFP     tmp     .req    a4
VFP     len     .req    a3
NOVFP   tmp     .req    a3
NOVFP   len     .req    a4
NOVFP   vmov    s0, a3
        ldr     tmp, =0x03070000           @ RunFast mode, short vectors of length 8, stride 1
        fmrx    ip, FPSCR
        fmxr    FPSCR, tmp
1:
        vldmia          a2!, {s8-s15}
        vcvt.f32.s32    s8, s8
        vcvt.f32.s32    s9, s9
        vcvt.f32.s32    s10, s10
        vcvt.f32.s32    s11, s11
        vcvt.f32.s32    s12, s12
        vcvt.f32.s32    s13, s13
        vcvt.f32.s32    s14, s14
        vcvt.f32.s32    s15, s15
        vmul.f32        s8, s8, s0
        subs            len, len, #8
        vstmia          a1!, {s8-s11}
        vstmia          a1!, {s12-s15}
        bne             1b

        fmxr    FPSCR, ip
        bx      lr
endfunc
        .unreq  tmp
        .unreq  len