blob: 562425bf0538954cfe31751421dd826366ce9bca [file] [log] [blame]
@ Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
@ Use of this source code is governed by a BSD-style license
@ that can be found in the LICENSE file in the root of the source
@ tree. An additional intellectual property rights grant can be found
@ in the file PATENTS. All contributing project authors may
@ be found in the AUTHORS file in the root of the source tree.
@ vector_scaling_operations_neon.s
@ This file contains the function WebRtcSpl_ScaleAndAddVectorsWithRoundNeon(),
@ optimized for ARM Neon platform. Output is bit-exact with the reference
@ C code in vector_scaling_operations.c.
.arch armv7-a
.fpu neon
.align 2
.global WebRtcSpl_ScaleAndAddVectorsWithRoundNeon
push {r4-r9}
ldr r4, [sp, #32] @ length
ldr r5, [sp, #28] @ out_vector
ldrsh r6, [sp, #24] @ right_shifts
cmp r4, #0
ble END @ Return if length <= 0.
cmp r4, #8
vdup.16 d26, r1 @ in_vector1_scale
vdup.16 d27, r3 @ in_vector2_scale
@ Neon instructions can only right shift by an immediate value. To shift right
@ by a register value, we have to do a left shift left by the negative value.
rsb r7, r6, #0
vdup.16 q12, r7 @ -right_shifts
bic r7, r4, #7 @ Counter for LOOP_UNROLLED_BY_8: length / 8 * 8.
vld1.16 {d28, d29}, [r0]! @ in_vector1[]
vld1.16 {d30, d31}, [r2]! @ in_vector2[]
vmull.s16 q0, d28, d26
vmull.s16 q1, d29, d26
vmull.s16 q2, d30, d27
vmull.s16 q3, d31, d27
vadd.s32 q0, q2
vadd.s32 q1, q3
vrshl.s32 q0, q12 @ Round shift right by right_shifts.
vrshl.s32 q1, q12
vmovn.i32 d0, q0 @ Cast to 16 bit values.
vmovn.i32 d1, q1
subs r7, #8
vst1.16 {d0, d1}, [r5]!
ands r4, #0xFF @ Counter for LOOP_NO_UNROLLING: length % 8.
beq END
mov r9, #1
lsl r9, r6
lsr r9, #1
ldrh r7, [r0], #2
ldrh r8, [r2], #2
smulbb r7, r7, r1
smulbb r8, r8, r3
subs r4, #1
add r7, r9
add r7, r8
asr r7, r6
strh r7, [r5], #2
pop {r4-r9}
bx lr