1 /* 2 * Copyright (C) 2013 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 #ifndef ANDROID_AUDIO_RESAMPLER_FIR_OPS_H 18 #define ANDROID_AUDIO_RESAMPLER_FIR_OPS_H 19 20 namespace android { 21 22 #if defined(__arm__) && !defined(__thumb__) 23 #define USE_INLINE_ASSEMBLY (true) 24 #else 25 #define USE_INLINE_ASSEMBLY (false) 26 #endif 27 28 #if defined(__aarch64__) || defined(__ARM_NEON__) 29 #ifndef USE_NEON 30 #define USE_NEON (true) 31 #endif 32 #else 33 #define USE_NEON (false) 34 #endif 35 #if USE_NEON 36 #include <arm_neon.h> 37 #endif 38 39 #if defined(__SSSE3__) // Should be supported in x86 ABI for both 32 & 64-bit. 40 #define USE_SSE (true) 41 #include <tmmintrin.h> 42 #else 43 #define USE_SSE (false) 44 #endif 45 46 template<typename T, typename U> 47 struct is_same 48 { 49 static const bool value = false; 50 }; 51 52 template<typename T> 53 struct is_same<T, T> // partial specialization 54 { 55 static const bool value = true; 56 }; 57 58 static inline 59 int32_t mulRL(int left, int32_t in, uint32_t vRL) 60 { 61 #if USE_INLINE_ASSEMBLY 62 int32_t out; 63 if (left) { 64 asm( "smultb %[out], %[in], %[vRL] \n" 65 : [out]"=r"(out) 66 : [in]"%r"(in), [vRL]"r"(vRL) 67 : ); 68 } else { 69 asm( "smultt %[out], %[in], %[vRL] \n" 70 : [out]"=r"(out) 71 : [in]"%r"(in), [vRL]"r"(vRL) 72 : ); 73 } 74 return out; 75 #else 76 int16_t v = left ? static_cast<int16_t>(vRL) : static_cast<int16_t>(vRL>>16); 77 return static_cast<int32_t>((static_cast<int64_t>(in) * v) >> 16); 78 #endif 79 } 80 81 static inline 82 int32_t mulAdd(int16_t in, int16_t v, int32_t a) 83 { 84 #if USE_INLINE_ASSEMBLY 85 int32_t out; 86 asm( "smlabb %[out], %[v], %[in], %[a] \n" 87 : [out]"=r"(out) 88 : [in]"%r"(in), [v]"r"(v), [a]"r"(a) 89 : ); 90 return out; 91 #else 92 return a + v * in; 93 #endif 94 } 95 96 static inline 97 int32_t mulAdd(int16_t in, int32_t v, int32_t a) 98 { 99 #if USE_INLINE_ASSEMBLY 100 int32_t out; 101 asm( "smlawb %[out], %[v], %[in], %[a] \n" 102 : [out]"=r"(out) 103 : [in]"%r"(in), [v]"r"(v), [a]"r"(a) 104 : ); 105 return out; 106 #else 107 return a + static_cast<int32_t>((static_cast<int64_t>(v) * in) >> 16); 108 #endif 109 } 110 111 static inline 112 int32_t mulAdd(int32_t in, int32_t v, int32_t a) 113 { 114 #if USE_INLINE_ASSEMBLY 115 int32_t out; 116 asm( "smmla %[out], %[v], %[in], %[a] \n" 117 : [out]"=r"(out) 118 : [in]"%r"(in), [v]"r"(v), [a]"r"(a) 119 : ); 120 return out; 121 #else 122 return a + static_cast<int32_t>((static_cast<int64_t>(v) * in) >> 32); 123 #endif 124 } 125 126 static inline 127 int32_t mulAddRL(int left, uint32_t inRL, int16_t v, int32_t a) 128 { 129 #if 0 // USE_INLINE_ASSEMBLY Seems to fail with Clang b/34110890 130 int32_t out; 131 if (left) { 132 asm( "smlabb %[out], %[v], %[inRL], %[a] \n" 133 : [out]"=r"(out) 134 : [inRL]"%r"(inRL), [v]"r"(v), [a]"r"(a) 135 : ); 136 } else { 137 asm( "smlabt %[out], %[v], %[inRL], %[a] \n" 138 : [out]"=r"(out) 139 : [inRL]"%r"(inRL), [v]"r"(v), [a]"r"(a) 140 : ); 141 } 142 return out; 143 #else 144 int16_t s = left ? static_cast<int16_t>(inRL) : static_cast<int16_t>(inRL>>16); 145 return a + v * s; 146 #endif 147 } 148 149 static inline 150 int32_t mulAddRL(int left, uint32_t inRL, int32_t v, int32_t a) 151 { 152 #if 0 // USE_INLINE_ASSEMBLY Seems to fail with Clang b/34110890 153 int32_t out; 154 if (left) { 155 asm( "smlawb %[out], %[v], %[inRL], %[a] \n" 156 : [out]"=r"(out) 157 : [inRL]"%r"(inRL), [v]"r"(v), [a]"r"(a) 158 : ); 159 } else { 160 asm( "smlawt %[out], %[v], %[inRL], %[a] \n" 161 : [out]"=r"(out) 162 : [inRL]"%r"(inRL), [v]"r"(v), [a]"r"(a) 163 : ); 164 } 165 return out; 166 #else 167 int16_t s = left ? static_cast<int16_t>(inRL) : static_cast<int16_t>(inRL>>16); 168 return a + static_cast<int32_t>((static_cast<int64_t>(v) * s) >> 16); 169 #endif 170 } 171 172 } // namespace android 173 174 #endif /*ANDROID_AUDIO_RESAMPLER_FIR_OPS_H*/ 175