Enabled ARMv7 code in Android NDK build.

Review URL: https://webrtc-codereview.appspot.com/725005

git-svn-id: http://webrtc.googlecode.com/svn/trunk@2622 4adac7df-926f-26a2-2b94-8c16560cd09d
This commit is contained in:
kma@webrtc.org 2012-08-16 19:19:51 +00:00
parent a15ea4965e
commit ee508e5fb6
5 changed files with 126 additions and 92 deletions

View File

@ -176,8 +176,7 @@
'defines': [ 'defines': [
'WEBRTC_LINUX', 'WEBRTC_LINUX',
'WEBRTC_ANDROID', 'WEBRTC_ANDROID',
# TODO(leozwang): move WEBRTC_ARCH_ARM to typedefs.h. 'WEBRTC_ARCH_ARM_V7A', # Set default platform to ARMv7.
'WEBRTC_ARCH_ARM',
'WEBRTC_DETECT_ARM_NEON', 'WEBRTC_DETECT_ARM_NEON',
# TODO(leozwang): Investigate CLOCK_REALTIME and CLOCK_MONOTONIC # TODO(leozwang): Investigate CLOCK_REALTIME and CLOCK_MONOTONIC
# support on Android. Keep WEBRTC_CLOCK_TYPE_REALTIME for now, # support on Android. Keep WEBRTC_CLOCK_TYPE_REALTIME for now,

View File

@ -35,49 +35,11 @@ static __inline WebRtc_Word16 WebRtcSpl_AddSatW16(WebRtc_Word16 a,
return WebRtcSpl_SatW32ToW16((WebRtc_Word32) a + (WebRtc_Word32) b); return WebRtcSpl_SatW32ToW16((WebRtc_Word32) a + (WebRtc_Word32) b);
} }
static __inline WebRtc_Word32 WebRtcSpl_AddSatW32(WebRtc_Word32 l_var1,
WebRtc_Word32 l_var2) {
WebRtc_Word32 l_sum;
// perform long addition
l_sum = l_var1 + l_var2;
// check for under or overflow
if (WEBRTC_SPL_IS_NEG(l_var1)) {
if (WEBRTC_SPL_IS_NEG(l_var2) && !WEBRTC_SPL_IS_NEG(l_sum)) {
l_sum = (WebRtc_Word32)0x80000000;
}
} else {
if (!WEBRTC_SPL_IS_NEG(l_var2) && WEBRTC_SPL_IS_NEG(l_sum)) {
l_sum = (WebRtc_Word32)0x7FFFFFFF;
}
}
return l_sum;
}
static __inline WebRtc_Word16 WebRtcSpl_SubSatW16(WebRtc_Word16 var1, static __inline WebRtc_Word16 WebRtcSpl_SubSatW16(WebRtc_Word16 var1,
WebRtc_Word16 var2) { WebRtc_Word16 var2) {
return WebRtcSpl_SatW32ToW16((WebRtc_Word32) var1 - (WebRtc_Word32) var2); return WebRtcSpl_SatW32ToW16((WebRtc_Word32) var1 - (WebRtc_Word32) var2);
} }
static __inline WebRtc_Word32 WebRtcSpl_SubSatW32(WebRtc_Word32 l_var1,
WebRtc_Word32 l_var2) {
WebRtc_Word32 l_diff;
// perform subtraction
l_diff = l_var1 - l_var2;
// check for underflow
if ((l_var1 < 0) && (l_var2 > 0) && (l_diff > 0))
l_diff = (WebRtc_Word32)0x80000000;
// check for overflow
if ((l_var1 > 0) && (l_var2 < 0) && (l_diff < 0))
l_diff = (WebRtc_Word32)0x7FFFFFFF;
return l_diff;
}
static __inline WebRtc_Word16 WebRtcSpl_GetSizeInBits(WebRtc_UWord32 n) { static __inline WebRtc_Word16 WebRtcSpl_GetSizeInBits(WebRtc_UWord32 n) {
int bits; int bits;
@ -156,4 +118,46 @@ static __inline int32_t WebRtc_MulAccumW16(int16_t a,
#endif // WEBRTC_ARCH_ARM_V7A #endif // WEBRTC_ARCH_ARM_V7A
// The following functions have no optimized versions.
// TODO(kma): Consider saturating add/sub instructions in X86 platform.
static __inline WebRtc_Word32 WebRtcSpl_AddSatW32(WebRtc_Word32 l_var1,
WebRtc_Word32 l_var2) {
WebRtc_Word32 l_sum;
// Perform long addition
l_sum = l_var1 + l_var2;
if (l_var1 < 0) { // Check for underflow.
if ((l_var2 < 0) && (l_sum >= 0)) {
l_sum = (WebRtc_Word32)0x80000000;
}
} else { // Check for overflow.
if ((l_var2 > 0) && (l_sum < 0)) {
l_sum = (WebRtc_Word32)0x7FFFFFFF;
}
}
return l_sum;
}
static __inline WebRtc_Word32 WebRtcSpl_SubSatW32(WebRtc_Word32 l_var1,
WebRtc_Word32 l_var2) {
WebRtc_Word32 l_diff;
// Perform subtraction.
l_diff = l_var1 - l_var2;
if (l_var1 < 0) { // Check for underflow.
if ((l_var2 > 0) && (l_diff > 0)) {
l_diff = (WebRtc_Word32)0x80000000;
}
} else { // Check for overflow.
if ((l_var2 < 0) && (l_diff < 0)) {
l_diff = (WebRtc_Word32)0x7FFFFFFF;
}
}
return l_diff;
}
#endif // WEBRTC_SPL_SPL_INL_H_ #endif // WEBRTC_SPL_SPL_INL_H_

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2011 The WebRTC project authors. All Rights Reserved. * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
* *
* Use of this source code is governed by a BSD-style license * 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 * that can be found in the LICENSE file in the root of the source
@ -9,42 +9,50 @@
*/ */
// This header file includes the inline functions for ARM processors in /* This header file includes the inline functions for ARM processors in
// the fix point signal processing library. * the fix point signal processing library.
*/
#ifndef WEBRTC_SPL_SPL_INL_ARMV7_H_ #ifndef WEBRTC_SPL_SPL_INL_ARMV7_H_
#define WEBRTC_SPL_SPL_INL_ARMV7_H_ #define WEBRTC_SPL_SPL_INL_ARMV7_H_
// TODO(kma): Replace some assembly code with GCC intrinsics /* TODO(kma): Replace some assembly code with GCC intrinsics
// (e.g. __builtin_clz). * (e.g. __builtin_clz).
*/
static __inline WebRtc_Word32 WEBRTC_SPL_MUL_16_32_RSFT16(WebRtc_Word16 a, static __inline WebRtc_Word32 WEBRTC_SPL_MUL_16_32_RSFT16(WebRtc_Word16 a,
WebRtc_Word32 b) { WebRtc_Word32 b) {
WebRtc_Word32 tmp; WebRtc_Word32 tmp = 0;
__asm__("smulwb %0, %1, %2":"=r"(tmp):"r"(b), "r"(a)); __asm __volatile ("smulwb %0, %1, %2":"=r"(tmp):"r"(b), "r"(a));
return tmp; return tmp;
} }
static __inline WebRtc_Word32 WEBRTC_SPL_MUL_32_32_RSFT32(WebRtc_Word16 a, static __inline WebRtc_Word32 WEBRTC_SPL_MUL_32_32_RSFT32(WebRtc_Word16 a,
WebRtc_Word16 b, WebRtc_Word16 b,
WebRtc_Word32 c) { WebRtc_Word32 c) {
WebRtc_Word32 tmp; WebRtc_Word32 tmp = 0;
__asm__("pkhbt %0, %1, %2, lsl #16" : "=r"(tmp) : "r"(b), "r"(a)); __asm __volatile (
__asm__("smmul %0, %1, %2":"=r"(tmp):"r"(tmp), "r"(c)); "pkhbt %[tmp], %[b], %[a], lsl #16\n\t"
"smmulr %[tmp], %[tmp], %[c]\n\t"
:[tmp]"+r"(tmp)
:[a]"r"(a),
[b]"r"(b),
[c]"r"(c)
);
return tmp; return tmp;
} }
static __inline WebRtc_Word32 WEBRTC_SPL_MUL_32_32_RSFT32BI(WebRtc_Word32 a, static __inline WebRtc_Word32 WEBRTC_SPL_MUL_32_32_RSFT32BI(WebRtc_Word32 a,
WebRtc_Word32 b) { WebRtc_Word32 b) {
WebRtc_Word32 tmp; WebRtc_Word32 tmp = 0;
__asm__("smmul %0, %1, %2":"=r"(tmp):"r"(a), "r"(b)); __asm volatile ("smmulr %0, %1, %2":"=r"(tmp):"r"(a), "r"(b));
return tmp; return tmp;
} }
static __inline WebRtc_Word32 WEBRTC_SPL_MUL_16_16(WebRtc_Word16 a, static __inline WebRtc_Word32 WEBRTC_SPL_MUL_16_16(WebRtc_Word16 a,
WebRtc_Word16 b) { WebRtc_Word16 b) {
WebRtc_Word32 tmp; WebRtc_Word32 tmp = 0;
__asm__("smulbb %0, %1, %2":"=r"(tmp):"r"(a), "r"(b)); __asm __volatile ("smulbb %0, %1, %2":"=r"(tmp):"r"(a), "r"(b));
return tmp; return tmp;
} }
@ -52,88 +60,93 @@ static __inline int32_t WebRtc_MulAccumW16(int16_t a,
int16_t b, int16_t b,
int32_t c) { int32_t c) {
int32_t tmp = 0; int32_t tmp = 0;
__asm__("smlabb %0, %1, %2, %3":"=r"(tmp):"r"(a), "r"(b), "r"(c)); __asm __volatile ("smlabb %0, %1, %2, %3":"=r"(tmp):"r"(a), "r"(b), "r"(c));
return tmp; return tmp;
} }
static __inline WebRtc_Word16 WebRtcSpl_AddSatW16(WebRtc_Word16 a, static __inline WebRtc_Word16 WebRtcSpl_AddSatW16(WebRtc_Word16 a,
WebRtc_Word16 b) { WebRtc_Word16 b) {
WebRtc_Word32 s_sum; WebRtc_Word32 s_sum = 0;
__asm__("qadd16 %0, %1, %2":"=r"(s_sum):"r"(a), "r"(b)); __asm __volatile ("qadd16 %0, %1, %2":"=r"(s_sum):"r"(a), "r"(b));
return (WebRtc_Word16) s_sum; return (WebRtc_Word16) s_sum;
} }
/* TODO(kma): find the cause of unittest errors by the next two functions:
* http://code.google.com/p/webrtc/issues/detail?id=740.
*/
#if 0
static __inline WebRtc_Word32 WebRtcSpl_AddSatW32(WebRtc_Word32 l_var1, static __inline WebRtc_Word32 WebRtcSpl_AddSatW32(WebRtc_Word32 l_var1,
WebRtc_Word32 l_var2) { WebRtc_Word32 l_var2) {
WebRtc_Word32 l_sum; WebRtc_Word32 l_sum = 0;
__asm__("qadd %0, %1, %2":"=r"(l_sum):"r"(l_var1), "r"(l_var2)); __asm __volatile ("qadd %0, %1, %2":"=r"(l_sum):"r"(l_var1), "r"(l_var2));
return l_sum; return l_sum;
} }
static __inline WebRtc_Word32 WebRtcSpl_SubSatW32(WebRtc_Word32 l_var1,
WebRtc_Word32 l_var2) {
WebRtc_Word32 l_sub = 0;
__asm __volatile ("qsub %0, %1, %2":"=r"(l_sub):"r"(l_var1), "r"(l_var2));
return l_sub;
}
#endif
static __inline WebRtc_Word16 WebRtcSpl_SubSatW16(WebRtc_Word16 var1, static __inline WebRtc_Word16 WebRtcSpl_SubSatW16(WebRtc_Word16 var1,
WebRtc_Word16 var2) { WebRtc_Word16 var2) {
WebRtc_Word32 s_sub; WebRtc_Word32 s_sub = 0;
__asm__("qsub16 %0, %1, %2":"=r"(s_sub):"r"(var1), "r"(var2)); __asm __volatile ("qsub16 %0, %1, %2":"=r"(s_sub):"r"(var1), "r"(var2));
return (WebRtc_Word16)s_sub; return (WebRtc_Word16)s_sub;
} }
static __inline WebRtc_Word32 WebRtcSpl_SubSatW32(WebRtc_Word32 l_var1,
WebRtc_Word32 l_var2) {
WebRtc_Word32 l_sub;
__asm__("qsub %0, %1, %2":"=r"(l_sub):"r"(l_var1), "r"(l_var2));
return l_sub;
}
static __inline WebRtc_Word16 WebRtcSpl_GetSizeInBits(WebRtc_UWord32 n) { static __inline WebRtc_Word16 WebRtcSpl_GetSizeInBits(WebRtc_UWord32 n) {
WebRtc_Word32 tmp; WebRtc_Word32 tmp = 0;
__asm__("clz %0, %1":"=r"(tmp):"r"(n)); __asm __volatile ("clz %0, %1":"=r"(tmp):"r"(n));
return (WebRtc_Word16)(32 - tmp); return (WebRtc_Word16)(32 - tmp);
} }
static __inline int WebRtcSpl_NormW32(WebRtc_Word32 a) { static __inline int WebRtcSpl_NormW32(WebRtc_Word32 a) {
WebRtc_Word32 tmp; WebRtc_Word32 tmp = 0;
if (a <= 0) a ^= 0xFFFFFFFF; if (a <= 0) a ^= 0xFFFFFFFF;
__asm__("clz %0, %1":"=r"(tmp):"r"(a)); __asm __volatile ("clz %0, %1":"=r"(tmp):"r"(a));
return tmp - 1; return tmp - 1;
} }
static __inline int WebRtcSpl_NormU32(WebRtc_UWord32 a) { static __inline int WebRtcSpl_NormU32(WebRtc_UWord32 a) {
int tmp; int tmp = 0;
if (a == 0) return 0; if (a == 0) return 0;
__asm__("clz %0, %1":"=r"(tmp):"r"(a)); __asm __volatile ("clz %0, %1":"=r"(tmp):"r"(a));
return tmp; return tmp;
} }
static __inline int WebRtcSpl_NormW16(WebRtc_Word16 a) { static __inline int WebRtcSpl_NormW16(WebRtc_Word16 a) {
WebRtc_Word32 tmp; WebRtc_Word32 tmp = 0;
if (a <= 0) a ^= 0xFFFFFFFF; if (a <= 0) a ^= 0xFFFFFFFF;
__asm__("clz %0, %1":"=r"(tmp):"r"(a)); __asm __volatile ("clz %0, %1":"=r"(tmp):"r"(a));
return tmp - 17; return tmp - 17;
} }
static __inline WebRtc_Word16 WebRtcSpl_SatW32ToW16(WebRtc_Word32 value32) { static __inline WebRtc_Word16 WebRtcSpl_SatW32ToW16(WebRtc_Word32 value32) {
WebRtc_Word16 out16; WebRtc_Word16 out16 = 0;
__asm__("ssat %r0, #16, %r1" : "=r"(out16) : "r"(value32)); __asm __volatile ("ssat %r0, #16, %r1" : "=r"(out16) : "r"(value32));
return out16; return out16;
} }

View File

@ -109,22 +109,38 @@ TEST_F(SplTest, MacroTest) {
} }
TEST_F(SplTest, InlineTest) { TEST_F(SplTest, InlineTest) {
WebRtc_Word16 a = 121; WebRtc_Word16 a16 = 121;
WebRtc_Word16 b = -17; WebRtc_Word16 b16 = -17;
WebRtc_Word32 A = 111121; WebRtc_Word32 a32 = 111121;
WebRtc_Word32 B = -1711; WebRtc_Word32 b32 = -1711;
char bVersion[8]; char bVersion[8];
EXPECT_EQ(104, WebRtcSpl_AddSatW16(a, b)); EXPECT_EQ(17, WebRtcSpl_GetSizeInBits(a32));
EXPECT_EQ(138, WebRtcSpl_SubSatW16(a, b)); EXPECT_EQ(14, WebRtcSpl_NormW32(a32));
EXPECT_EQ(4, WebRtcSpl_NormW16(b32));
EXPECT_EQ(15, WebRtcSpl_NormU32(a32));
EXPECT_EQ(109410, WebRtcSpl_AddSatW32(A, B)); EXPECT_EQ(104, WebRtcSpl_AddSatW16(a16, b16));
EXPECT_EQ(112832, WebRtcSpl_SubSatW32(A, B)); EXPECT_EQ(138, WebRtcSpl_SubSatW16(a16, b16));
EXPECT_EQ(17, WebRtcSpl_GetSizeInBits(A)); EXPECT_EQ(109410, WebRtcSpl_AddSatW32(a32, b32));
EXPECT_EQ(14, WebRtcSpl_NormW32(A)); EXPECT_EQ(112832, WebRtcSpl_SubSatW32(a32, b32));
EXPECT_EQ(4, WebRtcSpl_NormW16(B)); a32 = 0x80000000;
EXPECT_EQ(15, WebRtcSpl_NormU32(A)); b32 = 0x80000000;
// Cast to signed int to avoid compiler complaint on gtest.h.
EXPECT_EQ(static_cast<int>(0x80000000), WebRtcSpl_AddSatW32(a32, b32));
a32 = 0x7fffffff;
b32 = 0x7fffffff;
EXPECT_EQ(0x7fffffff, WebRtcSpl_AddSatW32(a32, b32));
a32 = 0;
b32 = 0x80000000;
EXPECT_EQ(0x7fffffff, WebRtcSpl_SubSatW32(a32, b32));
a32 = 0x7fffffff;
b32 = 0x80000000;
EXPECT_EQ(0x7fffffff, WebRtcSpl_SubSatW32(a32, b32));
a32 = 0x80000000;
b32 = 0x7fffffff;
EXPECT_EQ(static_cast<int>(0x80000000), WebRtcSpl_SubSatW32(a32, b32));
EXPECT_EQ(0, WebRtcSpl_get_version(bVersion, 8)); EXPECT_EQ(0, WebRtcSpl_get_version(bVersion, 8));
} }

View File

@ -1409,7 +1409,9 @@ static int TimeToFrequencyDomain(const WebRtc_Word16* time_signal,
WebRtc_Word16 *fft = (WebRtc_Word16 *) (((uintptr_t) fft_buf + 31) & ~31); WebRtc_Word16 *fft = (WebRtc_Word16 *) (((uintptr_t) fft_buf + 31) & ~31);
WebRtc_Word16 tmp16no1; WebRtc_Word16 tmp16no1;
#ifndef WEBRTC_ARCH_ARM_V7A
WebRtc_Word16 tmp16no2; WebRtc_Word16 tmp16no2;
#endif
#ifdef AECM_WITH_ABS_APPROX #ifdef AECM_WITH_ABS_APPROX
WebRtc_Word16 max_value = 0; WebRtc_Word16 max_value = 0;
WebRtc_Word16 min_value = 0; WebRtc_Word16 min_value = 0;