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 20namespace 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 46template<typename T, typename U> 47struct is_same 48{ 49 static const bool value = false; 50}; 51 52template<typename T> 53struct is_same<T, T> // partial specialization 54{ 55 static const bool value = true; 56}; 57 58static inline 59int32_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 81static inline 82int32_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 96static inline 97int32_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 111static inline 112int32_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 126static inline 127int32_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 149static inline 150int32_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