mirror of
https://github.com/FFmpeg/FFmpeg.git
synced 2024-12-23 12:43:46 +02:00
aa28df74ab
When compiling FFmpeg with GCC-9, some very random segfaults were
observed in code which had previously called down into the SBC encoder
NEON assembly routines. This was caused by these functions clobbering
some of the vfp callee saved registers (d8 - d15 aka q4 - q7). GCC was
using these registers to save local variables, but after these
functions returned, they would contain garbage.
Fix by reallocating the registers in the two affected functions in
the following way:
ff_sbc_analyze_4_neon: q2-q5 => q8-q11, then q1-q4 => q8-q11
ff_sbc_analyze_8_neon: q2-q9 => q8-q15
The reason for using these replacements is to keep closely related
sets of registers consecutively numbered which hopefully makes the
code more easy to follow. Since this commit only reallocates
registers, it should have no performance impact.
Signed-off-by: James Cowgill <jcowgill@debian.org>
Signed-off-by: Martin Storsjö <martin@martin.st>
(cherry picked from commit 50a4dff69f
)
Signed-off-by: Martin Storsjö <martin@martin.st>
715 lines
25 KiB
ArmAsm
715 lines
25 KiB
ArmAsm
/*
|
|
* Bluetooth low-complexity, subband codec (SBC)
|
|
*
|
|
* Copyright (C) 2017 Aurelien Jacobs <aurel@gnuage.org>
|
|
* Copyright (C) 2008-2010 Nokia Corporation
|
|
* Copyright (C) 2004-2010 Marcel Holtmann <marcel@holtmann.org>
|
|
* Copyright (C) 2004-2005 Henryk Ploetz <henryk@ploetzli.ch>
|
|
* Copyright (C) 2005-2006 Brad Midgley <bmidgley@xmission.com>
|
|
*
|
|
* This file is part of FFmpeg.
|
|
*
|
|
* FFmpeg 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.
|
|
*
|
|
* FFmpeg 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 FFmpeg; if not, write to the Free Software
|
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
|
*/
|
|
|
|
/**
|
|
* @file
|
|
* SBC ARM NEON optimizations
|
|
*/
|
|
|
|
#include "libavutil/arm/asm.S"
|
|
#include "neon.S"
|
|
|
|
#define SBC_PROTO_FIXED_SCALE 16
|
|
|
|
function ff_sbc_analyze_4_neon, export=1
|
|
/* TODO: merge even and odd cases (or even merge all four calls to this
|
|
* function) in order to have only aligned reads from 'in' array
|
|
* and reduce number of load instructions */
|
|
vld1.16 {d16, d17}, [r0, :64]!
|
|
vld1.16 {d20, d21}, [r2, :128]!
|
|
|
|
vmull.s16 q0, d16, d20
|
|
vld1.16 {d18, d19}, [r0, :64]!
|
|
vmull.s16 q1, d17, d21
|
|
vld1.16 {d22, d23}, [r2, :128]!
|
|
|
|
vmlal.s16 q0, d18, d22
|
|
vld1.16 {d16, d17}, [r0, :64]!
|
|
vmlal.s16 q1, d19, d23
|
|
vld1.16 {d20, d21}, [r2, :128]!
|
|
|
|
vmlal.s16 q0, d16, d20
|
|
vld1.16 {d18, d19}, [r0, :64]!
|
|
vmlal.s16 q1, d17, d21
|
|
vld1.16 {d22, d23}, [r2, :128]!
|
|
|
|
vmlal.s16 q0, d18, d22
|
|
vld1.16 {d16, d17}, [r0, :64]!
|
|
vmlal.s16 q1, d19, d23
|
|
vld1.16 {d20, d21}, [r2, :128]!
|
|
|
|
vmlal.s16 q0, d16, d20
|
|
vmlal.s16 q1, d17, d21
|
|
|
|
vpadd.s32 d0, d0, d1
|
|
vpadd.s32 d1, d2, d3
|
|
|
|
vrshrn.s32 d0, q0, SBC_PROTO_FIXED_SCALE
|
|
|
|
vld1.16 {d16, d17, d18, d19}, [r2, :128]!
|
|
|
|
vdup.i32 d1, d0[1] /* TODO: can be eliminated */
|
|
vdup.i32 d0, d0[0] /* TODO: can be eliminated */
|
|
|
|
vmull.s16 q10, d16, d0
|
|
vmull.s16 q11, d17, d0
|
|
vmlal.s16 q10, d18, d1
|
|
vmlal.s16 q11, d19, d1
|
|
|
|
vpadd.s32 d0, d20, d21 /* TODO: can be eliminated */
|
|
vpadd.s32 d1, d22, d23 /* TODO: can be eliminated */
|
|
|
|
vst1.32 {d0, d1}, [r1, :128]
|
|
|
|
bx lr
|
|
endfunc
|
|
|
|
function ff_sbc_analyze_8_neon, export=1
|
|
/* TODO: merge even and odd cases (or even merge all four calls to this
|
|
* function) in order to have only aligned reads from 'in' array
|
|
* and reduce number of load instructions */
|
|
vld1.16 {d16, d17}, [r0, :64]!
|
|
vld1.16 {d20, d21}, [r2, :128]!
|
|
|
|
vmull.s16 q12, d16, d20
|
|
vld1.16 {d18, d19}, [r0, :64]!
|
|
vmull.s16 q13, d17, d21
|
|
vld1.16 {d22, d23}, [r2, :128]!
|
|
vmull.s16 q14, d18, d22
|
|
vld1.16 {d16, d17}, [r0, :64]!
|
|
vmull.s16 q15, d19, d23
|
|
vld1.16 {d20, d21}, [r2, :128]!
|
|
|
|
vmlal.s16 q12, d16, d20
|
|
vld1.16 {d18, d19}, [r0, :64]!
|
|
vmlal.s16 q13, d17, d21
|
|
vld1.16 {d22, d23}, [r2, :128]!
|
|
vmlal.s16 q14, d18, d22
|
|
vld1.16 {d16, d17}, [r0, :64]!
|
|
vmlal.s16 q15, d19, d23
|
|
vld1.16 {d20, d21}, [r2, :128]!
|
|
|
|
vmlal.s16 q12, d16, d20
|
|
vld1.16 {d18, d19}, [r0, :64]!
|
|
vmlal.s16 q13, d17, d21
|
|
vld1.16 {d22, d23}, [r2, :128]!
|
|
vmlal.s16 q14, d18, d22
|
|
vld1.16 {d16, d17}, [r0, :64]!
|
|
vmlal.s16 q15, d19, d23
|
|
vld1.16 {d20, d21}, [r2, :128]!
|
|
|
|
vmlal.s16 q12, d16, d20
|
|
vld1.16 {d18, d19}, [r0, :64]!
|
|
vmlal.s16 q13, d17, d21
|
|
vld1.16 {d22, d23}, [r2, :128]!
|
|
vmlal.s16 q14, d18, d22
|
|
vld1.16 {d16, d17}, [r0, :64]!
|
|
vmlal.s16 q15, d19, d23
|
|
vld1.16 {d20, d21}, [r2, :128]!
|
|
|
|
vmlal.s16 q12, d16, d20
|
|
vld1.16 {d18, d19}, [r0, :64]!
|
|
vmlal.s16 q13, d17, d21
|
|
vld1.16 {d22, d23}, [r2, :128]!
|
|
|
|
vmlal.s16 q14, d18, d22
|
|
vmlal.s16 q15, d19, d23
|
|
|
|
vpadd.s32 d0, d24, d25
|
|
vpadd.s32 d1, d26, d27
|
|
vpadd.s32 d2, d28, d29
|
|
vpadd.s32 d3, d30, d31
|
|
|
|
vrshr.s32 q0, q0, SBC_PROTO_FIXED_SCALE
|
|
vrshr.s32 q1, q1, SBC_PROTO_FIXED_SCALE
|
|
vmovn.s32 d0, q0
|
|
vmovn.s32 d1, q1
|
|
|
|
vdup.i32 d3, d1[1] /* TODO: can be eliminated */
|
|
vdup.i32 d2, d1[0] /* TODO: can be eliminated */
|
|
vdup.i32 d1, d0[1] /* TODO: can be eliminated */
|
|
vdup.i32 d0, d0[0] /* TODO: can be eliminated */
|
|
|
|
vld1.16 {d16, d17}, [r2, :128]!
|
|
vmull.s16 q12, d16, d0
|
|
vld1.16 {d18, d19}, [r2, :128]!
|
|
vmull.s16 q13, d17, d0
|
|
vmull.s16 q14, d18, d0
|
|
vmull.s16 q15, d19, d0
|
|
|
|
vld1.16 {d16, d17}, [r2, :128]!
|
|
vmlal.s16 q12, d16, d1
|
|
vld1.16 {d18, d19}, [r2, :128]!
|
|
vmlal.s16 q13, d17, d1
|
|
vmlal.s16 q14, d18, d1
|
|
vmlal.s16 q15, d19, d1
|
|
|
|
vld1.16 {d16, d17}, [r2, :128]!
|
|
vmlal.s16 q12, d16, d2
|
|
vld1.16 {d18, d19}, [r2, :128]!
|
|
vmlal.s16 q13, d17, d2
|
|
vmlal.s16 q14, d18, d2
|
|
vmlal.s16 q15, d19, d2
|
|
|
|
vld1.16 {d16, d17}, [r2, :128]!
|
|
vmlal.s16 q12, d16, d3
|
|
vld1.16 {d18, d19}, [r2, :128]!
|
|
vmlal.s16 q13, d17, d3
|
|
vmlal.s16 q14, d18, d3
|
|
vmlal.s16 q15, d19, d3
|
|
|
|
vpadd.s32 d0, d24, d25 /* TODO: can be eliminated */
|
|
vpadd.s32 d1, d26, d27 /* TODO: can be eliminated */
|
|
vpadd.s32 d2, d28, d29 /* TODO: can be eliminated */
|
|
vpadd.s32 d3, d30, d31 /* TODO: can be eliminated */
|
|
|
|
vst1.32 {d0, d1, d2, d3}, [r1, :128]
|
|
|
|
bx lr
|
|
endfunc
|
|
|
|
function ff_sbc_calc_scalefactors_neon, export=1
|
|
@ parameters
|
|
@ r0 = sb_sample_f
|
|
@ r1 = scale_factor
|
|
@ r2 = blocks
|
|
@ r3 = channels
|
|
@ r4 = subbands
|
|
@ local variables
|
|
@ r5 = in_loop_1
|
|
@ r6 = in
|
|
@ r7 = out_loop_1
|
|
@ r8 = out
|
|
@ r9 = ch
|
|
@ r10 = sb
|
|
@ r11 = inc
|
|
@ r12 = blk
|
|
|
|
push {r1-r2, r4-r12}
|
|
ldr r4, [sp, #44]
|
|
mov r11, #64
|
|
|
|
mov r9, #0
|
|
1:
|
|
add r5, r0, r9, lsl#5
|
|
add r7, r1, r9, lsl#5
|
|
|
|
mov r10, #0
|
|
2:
|
|
add r6, r5, r10, lsl#2
|
|
add r8, r7, r10, lsl#2
|
|
mov r12, r2
|
|
|
|
vmov.s32 q0, #0
|
|
vmov.s32 q1, #0x8000 @ 1 << SCALE_OUT_BITS
|
|
vmov.s32 q14, #1
|
|
vmov.s32 q15, #16 @ 31 - SCALE_OUT_BITS
|
|
vadd.s32 q1, q1, q14
|
|
3:
|
|
vld1.32 {d16, d17}, [r6, :128], r11
|
|
vabs.s32 q8, q8
|
|
vld1.32 {d18, d19}, [r6, :128], r11
|
|
vabs.s32 q9, q9
|
|
vld1.32 {d20, d21}, [r6, :128], r11
|
|
vabs.s32 q10, q10
|
|
vld1.32 {d22, d23}, [r6, :128], r11
|
|
vabs.s32 q11, q11
|
|
vmax.s32 q0, q0, q8
|
|
vmax.s32 q1, q1, q9
|
|
vmax.s32 q0, q0, q10
|
|
vmax.s32 q1, q1, q11
|
|
subs r12, r12, #4
|
|
bgt 3b
|
|
vmax.s32 q0, q0, q1
|
|
vsub.s32 q0, q0, q14
|
|
vclz.s32 q0, q0
|
|
vsub.s32 q0, q15, q0
|
|
vst1.32 {d0, d1}, [r8, :128]
|
|
|
|
add r10, r10, #4
|
|
cmp r10, r4
|
|
blt 2b
|
|
|
|
add r9, r9, #1
|
|
cmp r9, r3
|
|
blt 1b
|
|
|
|
pop {r1-r2, r4-r12}
|
|
bx lr
|
|
endfunc
|
|
|
|
/*
|
|
* constants: q13 = (31 - SCALE_OUT_BITS)
|
|
* q14 = 1
|
|
* input: q0 - ((1 << SCALE_OUT_BITS) + 1)
|
|
* r5 - samples for channel 0
|
|
* r6 - samples for shannel 1
|
|
* output: q0, q1 - scale factors without joint stereo
|
|
* q2, q3 - scale factors with joint stereo
|
|
* q15 - joint stereo selection mask
|
|
*/
|
|
.macro calc_scalefactors
|
|
vmov.s32 q1, q0
|
|
vmov.s32 q2, q0
|
|
vmov.s32 q3, q0
|
|
mov r3, r2
|
|
1:
|
|
vld1.32 {d18, d19}, [r6, :128], r11
|
|
vbic.s32 q11, q9, q14
|
|
vld1.32 {d16, d17}, [r5, :128], r11
|
|
vhadd.s32 q10, q8, q11
|
|
vhsub.s32 q11, q8, q11
|
|
vabs.s32 q8, q8
|
|
vabs.s32 q9, q9
|
|
vabs.s32 q10, q10
|
|
vabs.s32 q11, q11
|
|
vmax.s32 q0, q0, q8
|
|
vmax.s32 q1, q1, q9
|
|
vmax.s32 q2, q2, q10
|
|
vmax.s32 q3, q3, q11
|
|
subs r3, r3, #1
|
|
bgt 1b
|
|
vsub.s32 q0, q0, q14
|
|
vsub.s32 q1, q1, q14
|
|
vsub.s32 q2, q2, q14
|
|
vsub.s32 q3, q3, q14
|
|
vclz.s32 q0, q0
|
|
vclz.s32 q1, q1
|
|
vclz.s32 q2, q2
|
|
vclz.s32 q3, q3
|
|
vsub.s32 q0, q13, q0
|
|
vsub.s32 q1, q13, q1
|
|
vsub.s32 q2, q13, q2
|
|
vsub.s32 q3, q13, q3
|
|
.endm
|
|
|
|
/*
|
|
* constants: q14 = 1
|
|
* input: q15 - joint stereo selection mask
|
|
* r5 - value set by calc_scalefactors macro
|
|
* r6 - value set by calc_scalefactors macro
|
|
*/
|
|
.macro update_joint_stereo_samples
|
|
sub r8, r6, r11
|
|
sub r7, r5, r11
|
|
sub r6, r6, r11, asl #1
|
|
sub r5, r5, r11, asl #1
|
|
vld1.32 {d18, d19}, [r6, :128]
|
|
vbic.s32 q11, q9, q14
|
|
vld1.32 {d16, d17}, [r5, :128]
|
|
vld1.32 {d2, d3}, [r8, :128]
|
|
vbic.s32 q3, q1, q14
|
|
vld1.32 {d0, d1}, [r7, :128]
|
|
vhsub.s32 q10, q8, q11
|
|
vhadd.s32 q11, q8, q11
|
|
vhsub.s32 q2, q0, q3
|
|
vhadd.s32 q3, q0, q3
|
|
vbif.s32 q10, q9, q15
|
|
vbif.s32 d22, d16, d30
|
|
sub r11, r10, r11, asl #1
|
|
sub r3, r2, #2
|
|
2:
|
|
vbif.s32 d23, d17, d31
|
|
vst1.32 {d20, d21}, [r6, :128], r11
|
|
vbif.s32 d4, d2, d30
|
|
vld1.32 {d18, d19}, [r6, :128]
|
|
vbif.s32 d5, d3, d31
|
|
vst1.32 {d22, d23}, [r5, :128], r11
|
|
vbif.s32 d6, d0, d30
|
|
vld1.32 {d16, d17}, [r5, :128]
|
|
vbif.s32 d7, d1, d31
|
|
vst1.32 {d4, d5}, [r8, :128], r11
|
|
vbic.s32 q11, q9, q14
|
|
vld1.32 {d2, d3}, [r8, :128]
|
|
vst1.32 {d6, d7}, [r7, :128], r11
|
|
vbic.s32 q3, q1, q14
|
|
vld1.32 {d0, d1}, [r7, :128]
|
|
vhsub.s32 q10, q8, q11
|
|
vhadd.s32 q11, q8, q11
|
|
vhsub.s32 q2, q0, q3
|
|
vhadd.s32 q3, q0, q3
|
|
vbif.s32 q10, q9, q15
|
|
vbif.s32 d22, d16, d30
|
|
subs r3, r3, #2
|
|
bgt 2b
|
|
sub r11, r10, r11, asr #1
|
|
vbif.s32 d23, d17, d31
|
|
vst1.32 {d20, d21}, [r6, :128]
|
|
vbif.s32 q2, q1, q15
|
|
vst1.32 {d22, d23}, [r5, :128]
|
|
vbif.s32 q3, q0, q15
|
|
vst1.32 {d4, d5}, [r8, :128]
|
|
vst1.32 {d6, d7}, [r7, :128]
|
|
.endm
|
|
|
|
function ff_sbc_calc_scalefactors_j_neon, export=1
|
|
@ parameters
|
|
@ r0 = in = sb_sample_f
|
|
@ r1 = out = scale_factor
|
|
@ r2 = blocks
|
|
@ r3 = subbands
|
|
@ local variables
|
|
@ r4 = consts = ff_sbcdsp_joint_bits_mask
|
|
@ r5 = in0
|
|
@ r6 = in1
|
|
@ r7 = out0
|
|
@ r8 = out1
|
|
@ r10 = zero
|
|
@ r11 = inc
|
|
@ return r0 = joint
|
|
|
|
push {r3-r11}
|
|
movrelx r4, X(ff_sbcdsp_joint_bits_mask)
|
|
mov r10, #0
|
|
mov r11, #64
|
|
|
|
vmov.s32 q14, #1
|
|
vmov.s32 q13, #16 @ 31 - SCALE_OUT_BITS
|
|
|
|
cmp r3, #4
|
|
bne 8f
|
|
|
|
4: @ 4 subbands
|
|
add r5, r0, #0
|
|
add r6, r0, #32
|
|
add r7, r1, #0
|
|
add r8, r1, #32
|
|
vmov.s32 q0, #0x8000 @ 1 << SCALE_OUT_BITS
|
|
vadd.s32 q0, q0, q14
|
|
|
|
calc_scalefactors
|
|
|
|
@ check whether to use joint stereo for subbands 0, 1, 2
|
|
vadd.s32 q15, q0, q1
|
|
vadd.s32 q9, q2, q3
|
|
vmov.s32 d31[1], r10 @ last subband -> no joint
|
|
vld1.32 {d16, d17}, [r4, :128]!
|
|
vcgt.s32 q15, q15, q9
|
|
|
|
@ calculate and save to memory 'joint' variable
|
|
@ update and save scale factors to memory
|
|
vand.s32 q8, q8, q15
|
|
vbit.s32 q0, q2, q15
|
|
vpadd.s32 d16, d16, d17
|
|
vbit.s32 q1, q3, q15
|
|
vpadd.s32 d16, d16, d16
|
|
vst1.32 {d0, d1}, [r7, :128]
|
|
vst1.32 {d2, d3}, [r8, :128]
|
|
vmov.32 r0, d16[0]
|
|
|
|
update_joint_stereo_samples
|
|
b 9f
|
|
|
|
8: @ 8 subbands
|
|
add r5, r0, #16
|
|
add r6, r0, #48
|
|
add r7, r1, #16
|
|
add r8, r1, #48
|
|
vmov.s32 q0, #0x8000 @ 1 << SCALE_OUT_BITS
|
|
vadd.s32 q0, q0, q14
|
|
|
|
calc_scalefactors
|
|
|
|
@ check whether to use joint stereo for subbands 4, 5, 6
|
|
vadd.s32 q15, q0, q1
|
|
vadd.s32 q9, q2, q3
|
|
vmov.s32 d31[1], r10 @ last subband -> no joint
|
|
vld1.32 {d16, d17}, [r4, :128]!
|
|
vcgt.s32 q15, q15, q9
|
|
|
|
@ calculate part of 'joint' variable and save it to d24
|
|
@ update and save scale factors to memory
|
|
vand.s32 q8, q8, q15
|
|
vbit.s32 q0, q2, q15
|
|
vpadd.s32 d16, d16, d17
|
|
vbit.s32 q1, q3, q15
|
|
vst1.32 {d0, d1}, [r7, :128]
|
|
vst1.32 {d2, d3}, [r8, :128]
|
|
vpadd.s32 d24, d16, d16
|
|
|
|
update_joint_stereo_samples
|
|
|
|
add r5, r0, #0
|
|
add r6, r0, #32
|
|
add r7, r1, #0
|
|
add r8, r1, #32
|
|
vmov.s32 q0, #0x8000 @ 1 << SCALE_OUT_BITS
|
|
vadd.s32 q0, q0, q14
|
|
|
|
calc_scalefactors
|
|
|
|
@ check whether to use joint stereo for subbands 0, 1, 2, 3
|
|
vadd.s32 q15, q0, q1
|
|
vadd.s32 q9, q2, q3
|
|
vld1.32 {d16, d17}, [r4, :128]!
|
|
vcgt.s32 q15, q15, q9
|
|
|
|
@ combine last part of 'joint' with d24 and save to memory
|
|
@ update and save scale factors to memory
|
|
vand.s32 q8, q8, q15
|
|
vbit.s32 q0, q2, q15
|
|
vpadd.s32 d16, d16, d17
|
|
vbit.s32 q1, q3, q15
|
|
vpadd.s32 d16, d16, d16
|
|
vst1.32 {d0, d1}, [r7, :128]
|
|
vadd.s32 d16, d16, d24
|
|
vst1.32 {d2, d3}, [r8, :128]
|
|
vmov.32 r0, d16[0]
|
|
|
|
update_joint_stereo_samples
|
|
9:
|
|
pop {r3-r11}
|
|
bx lr
|
|
endfunc
|
|
|
|
function ff_sbc_enc_process_input_4s_neon, export=1
|
|
@ parameters
|
|
@ r0 = positioin
|
|
@ r1 = pcm
|
|
@ r2 = X
|
|
@ r3 = nsamples
|
|
@ r4 = nchannels
|
|
@ local variables
|
|
@ r5 = ff_sbc_input_perm_4
|
|
@ r6 = src / x
|
|
@ r7 = dst / y
|
|
|
|
push {r1, r3-r7}
|
|
ldr r4, [sp, #24]
|
|
movrelx r5, X(ff_sbc_input_perm_4)
|
|
|
|
@ handle X buffer wraparound
|
|
cmp r0, r3
|
|
bge 1f @ if (position < nsamples)
|
|
add r7, r2, #576 @ &X[0][SBC_X_BUFFER_SIZE - 40]
|
|
add r6, r2, r0, lsl#1 @ &X[0][position]
|
|
vld1.16 {d0, d1, d2, d3}, [r6, :128]!
|
|
vst1.16 {d0, d1, d2, d3}, [r7, :128]!
|
|
vld1.16 {d0, d1, d2, d3}, [r6, :128]!
|
|
vst1.16 {d0, d1, d2, d3}, [r7, :128]!
|
|
vld1.16 {d0}, [r6, :64]!
|
|
vst1.16 {d0}, [r7, :64]!
|
|
cmp r4, #1
|
|
ble 2f @ if (nchannels > 1)
|
|
add r7, r2, #1232 @ &X[1][SBC_X_BUFFER_SIZE - 40]
|
|
add r6, r2, #656
|
|
add r6, r6, r0, lsl#1 @ &X[1][position]
|
|
vld1.16 {d0, d1, d2, d3}, [r6, :128]!
|
|
vst1.16 {d0, d1, d2, d3}, [r7, :128]!
|
|
vld1.16 {d0, d1, d2, d3}, [r6, :128]!
|
|
vst1.16 {d0, d1, d2, d3}, [r7, :128]!
|
|
vld1.16 {d0}, [r6, :64]!
|
|
vst1.16 {d0}, [r7, :64]!
|
|
2:
|
|
mov r0, #288 @ SBC_X_BUFFER_SIZE - 40
|
|
1:
|
|
|
|
add r6, r2, r0, lsl#1 @ &X[0][position]
|
|
add r7, r6, #656 @ &X[1][position]
|
|
|
|
cmp r4, #1
|
|
ble 8f @ if (nchannels > 1)
|
|
tst r1, #1
|
|
beq 7f @ if (pcm & 1)
|
|
@ poor 'pcm' alignment
|
|
vld1.8 {d0, d1}, [r5, :128]
|
|
1:
|
|
sub r6, r6, #16
|
|
sub r7, r7, #16
|
|
sub r0, r0, #8
|
|
vld1.8 {d4, d5}, [r1]!
|
|
vuzp.16 d4, d5
|
|
vld1.8 {d20, d21}, [r1]!
|
|
vuzp.16 d20, d21
|
|
vswp d5, d20
|
|
vtbl.8 d16, {d4, d5}, d0
|
|
vtbl.8 d17, {d4, d5}, d1
|
|
vtbl.8 d18, {d20, d21}, d0
|
|
vtbl.8 d19, {d20, d21}, d1
|
|
vst1.16 {d16, d17}, [r6, :128]
|
|
vst1.16 {d18, d19}, [r7, :128]
|
|
subs r3, r3, #8
|
|
bgt 1b
|
|
b 9f
|
|
7:
|
|
@ proper 'pcm' alignment
|
|
vld1.8 {d0, d1}, [r5, :128]
|
|
1:
|
|
sub r6, r6, #16
|
|
sub r7, r7, #16
|
|
sub r0, r0, #8
|
|
vld2.16 {d4, d5}, [r1]!
|
|
vld2.16 {d20, d21}, [r1]!
|
|
vswp d5, d20
|
|
vtbl.8 d16, {d4, d5}, d0
|
|
vtbl.8 d17, {d4, d5}, d1
|
|
vtbl.8 d18, {d20, d21}, d0
|
|
vtbl.8 d19, {d20, d21}, d1
|
|
vst1.16 {d16, d17}, [r6, :128]
|
|
vst1.16 {d18, d19}, [r7, :128]
|
|
subs r3, r3, #8
|
|
bgt 1b
|
|
b 9f
|
|
8:
|
|
@ mono
|
|
vld1.8 {d0, d1}, [r5, :128]
|
|
1:
|
|
sub r6, r6, #16
|
|
sub r0, r0, #8
|
|
vld1.8 {d4, d5}, [r1]!
|
|
vtbl.8 d16, {d4, d5}, d0
|
|
vtbl.8 d17, {d4, d5}, d1
|
|
vst1.16 {d16, d17}, [r6, :128]
|
|
subs r3, r3, #8
|
|
bgt 1b
|
|
9:
|
|
pop {r1, r3-r7}
|
|
bx lr
|
|
endfunc
|
|
|
|
function ff_sbc_enc_process_input_8s_neon, export=1
|
|
@ parameters
|
|
@ r0 = positioin
|
|
@ r1 = pcm
|
|
@ r2 = X
|
|
@ r3 = nsamples
|
|
@ r4 = nchannels
|
|
@ local variables
|
|
@ r5 = ff_sbc_input_perm_8
|
|
@ r6 = src
|
|
@ r7 = dst
|
|
|
|
push {r1, r3-r7}
|
|
ldr r4, [sp, #24]
|
|
movrelx r5, X(ff_sbc_input_perm_8)
|
|
|
|
@ handle X buffer wraparound
|
|
cmp r0, r3
|
|
bge 1f @ if (position < nsamples)
|
|
add r7, r2, #512 @ &X[0][SBC_X_BUFFER_SIZE - 72]
|
|
add r6, r2, r0, lsl#1 @ &X[0][position]
|
|
vld1.16 {d0, d1, d2, d3}, [r6, :128]!
|
|
vst1.16 {d0, d1, d2, d3}, [r7, :128]!
|
|
vld1.16 {d0, d1, d2, d3}, [r6, :128]!
|
|
vst1.16 {d0, d1, d2, d3}, [r7, :128]!
|
|
vld1.16 {d0, d1, d2, d3}, [r6, :128]!
|
|
vst1.16 {d0, d1, d2, d3}, [r7, :128]!
|
|
vld1.16 {d0, d1, d2, d3}, [r6, :128]!
|
|
vst1.16 {d0, d1, d2, d3}, [r7, :128]!
|
|
vld1.16 {d0, d1}, [r6, :128]!
|
|
vst1.16 {d0, d1}, [r7, :128]!
|
|
cmp r4, #1
|
|
ble 2f @ if (nchannels > 1)
|
|
add r7, r2, #1168 @ &X[1][SBC_X_BUFFER_SIZE - 72]
|
|
add r6, r2, #656
|
|
add r6, r6, r0, lsl#1 @ &X[1][position]
|
|
vld1.16 {d0, d1, d2, d3}, [r6, :128]!
|
|
vst1.16 {d0, d1, d2, d3}, [r7, :128]!
|
|
vld1.16 {d0, d1, d2, d3}, [r6, :128]!
|
|
vst1.16 {d0, d1, d2, d3}, [r7, :128]!
|
|
vld1.16 {d0, d1, d2, d3}, [r6, :128]!
|
|
vst1.16 {d0, d1, d2, d3}, [r7, :128]!
|
|
vld1.16 {d0, d1, d2, d3}, [r6, :128]!
|
|
vst1.16 {d0, d1, d2, d3}, [r7, :128]!
|
|
vld1.16 {d0, d1}, [r6, :128]!
|
|
vst1.16 {d0, d1}, [r7, :128]!
|
|
2:
|
|
mov r0, #256 @ SBC_X_BUFFER_SIZE - 72
|
|
1:
|
|
|
|
add r6, r2, r0, lsl#1 @ &X[0][position]
|
|
add r7, r6, #656 @ &X[1][position]
|
|
|
|
cmp r4, #1
|
|
ble 8f @ if (nchannels > 1)
|
|
tst r1, #1
|
|
beq 7f @ if (pcm & 1)
|
|
@ poor 'pcm' alignment
|
|
vld1.8 {d0, d1, d2, d3}, [r5, :128]
|
|
1:
|
|
sub r6, r6, #32
|
|
sub r7, r7, #32
|
|
sub r0, r0, #16
|
|
vld1.8 {d4, d5, d6, d7}, [r1]!
|
|
vuzp.16 q2, q3
|
|
vld1.8 {d20, d21, d22, d23}, [r1]!
|
|
vuzp.16 q10, q11
|
|
vswp q3, q10
|
|
vtbl.8 d16, {d4, d5, d6, d7}, d0
|
|
vtbl.8 d17, {d4, d5, d6, d7}, d1
|
|
vtbl.8 d18, {d4, d5, d6, d7}, d2
|
|
vtbl.8 d19, {d4, d5, d6, d7}, d3
|
|
vst1.16 {d16, d17, d18, d19}, [r6, :128]
|
|
vtbl.8 d16, {d20, d21, d22, d23}, d0
|
|
vtbl.8 d17, {d20, d21, d22, d23}, d1
|
|
vtbl.8 d18, {d20, d21, d22, d23}, d2
|
|
vtbl.8 d19, {d20, d21, d22, d23}, d3
|
|
vst1.16 {d16, d17, d18, d19}, [r7, :128]
|
|
subs r3, r3, #16
|
|
bgt 1b
|
|
b 9f
|
|
7:
|
|
@ proper 'pcm' alignment
|
|
vld1.8 {d0, d1, d2, d3}, [r5, :128]
|
|
1:
|
|
sub r6, r6, #32
|
|
sub r7, r7, #32
|
|
sub r0, r0, #16
|
|
vld2.16 {d4, d5, d6, d7}, [r1]!
|
|
vld2.16 {d20, d21, d22, d23}, [r1]!
|
|
vswp q3, q10
|
|
vtbl.8 d16, {d4, d5, d6, d7}, d0
|
|
vtbl.8 d17, {d4, d5, d6, d7}, d1
|
|
vtbl.8 d18, {d4, d5, d6, d7}, d2
|
|
vtbl.8 d19, {d4, d5, d6, d7}, d3
|
|
vst1.16 {d16, d17, d18, d19}, [r6, :128]
|
|
vtbl.8 d16, {d20, d21, d22, d23}, d0
|
|
vtbl.8 d17, {d20, d21, d22, d23}, d1
|
|
vtbl.8 d18, {d20, d21, d22, d23}, d2
|
|
vtbl.8 d19, {d20, d21, d22, d23}, d3
|
|
vst1.16 {d16, d17, d18, d19}, [r7, :128]
|
|
subs r3, r3, #16
|
|
bgt 1b
|
|
b 9f
|
|
8:
|
|
@ mono
|
|
vld1.8 {d0, d1, d2, d3}, [r5, :128]
|
|
1:
|
|
sub r6, r6, #32
|
|
sub r0, r0, #16
|
|
vld1.8 {d4, d5, d6, d7}, [r1]!
|
|
vtbl.8 d16, {d4, d5, d6, d7}, d0
|
|
vtbl.8 d17, {d4, d5, d6, d7}, d1
|
|
vtbl.8 d18, {d4, d5, d6, d7}, d2
|
|
vtbl.8 d19, {d4, d5, d6, d7}, d3
|
|
vst1.16 {d16, d17, d18, d19}, [r6, :128]
|
|
subs r3, r3, #16
|
|
bgt 1b
|
|
9:
|
|
pop {r1, r3-r7}
|
|
bx lr
|
|
endfunc
|