blob: 5dc1790730d201ce4cc06487ca72b08add6e47d7 [file] [log] [blame]
Andy Hung86eae0e2013-12-09 12:12:46 -08001/*
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
Andy Hung6b667dd2015-02-06 15:05:37 -080028#if defined(__aarch64__) || defined(__ARM_NEON__)
Glenn Kasten4699a6a2016-02-16 10:49:09 -080029#ifndef USE_NEON
Andy Hung86eae0e2013-12-09 12:12:46 -080030#define USE_NEON (true)
Glenn Kasten4699a6a2016-02-16 10:49:09 -080031#endif
Andy Hung86eae0e2013-12-09 12:12:46 -080032#else
33#define USE_NEON (false)
34#endif
Glenn Kasten4699a6a2016-02-16 10:49:09 -080035#if USE_NEON
36#include <arm_neon.h>
37#endif
Andy Hung86eae0e2013-12-09 12:12:46 -080038
39template<typename T, typename U>
40struct is_same
41{
42 static const bool value = false;
43};
44
45template<typename T>
46struct is_same<T, T> // partial specialization
47{
48 static const bool value = true;
49};
50
51static inline
52int32_t mulRL(int left, int32_t in, uint32_t vRL)
53{
54#if USE_INLINE_ASSEMBLY
55 int32_t out;
56 if (left) {
57 asm( "smultb %[out], %[in], %[vRL] \n"
58 : [out]"=r"(out)
59 : [in]"%r"(in), [vRL]"r"(vRL)
60 : );
61 } else {
62 asm( "smultt %[out], %[in], %[vRL] \n"
63 : [out]"=r"(out)
64 : [in]"%r"(in), [vRL]"r"(vRL)
65 : );
66 }
67 return out;
68#else
69 int16_t v = left ? static_cast<int16_t>(vRL) : static_cast<int16_t>(vRL>>16);
70 return static_cast<int32_t>((static_cast<int64_t>(in) * v) >> 16);
71#endif
72}
73
74static inline
75int32_t mulAdd(int16_t in, int16_t v, int32_t a)
76{
77#if USE_INLINE_ASSEMBLY
78 int32_t out;
79 asm( "smlabb %[out], %[v], %[in], %[a] \n"
80 : [out]"=r"(out)
81 : [in]"%r"(in), [v]"r"(v), [a]"r"(a)
82 : );
83 return out;
84#else
85 return a + v * in;
86#endif
87}
88
89static inline
90int32_t mulAdd(int16_t in, int32_t v, int32_t a)
91{
92#if USE_INLINE_ASSEMBLY
93 int32_t out;
94 asm( "smlawb %[out], %[v], %[in], %[a] \n"
95 : [out]"=r"(out)
96 : [in]"%r"(in), [v]"r"(v), [a]"r"(a)
97 : );
98 return out;
99#else
100 return a + static_cast<int32_t>((static_cast<int64_t>(v) * in) >> 16);
101#endif
102}
103
104static inline
105int32_t mulAdd(int32_t in, int32_t v, int32_t a)
106{
107#if USE_INLINE_ASSEMBLY
108 int32_t out;
109 asm( "smmla %[out], %[v], %[in], %[a] \n"
110 : [out]"=r"(out)
111 : [in]"%r"(in), [v]"r"(v), [a]"r"(a)
112 : );
113 return out;
114#else
115 return a + static_cast<int32_t>((static_cast<int64_t>(v) * in) >> 32);
116#endif
117}
118
119static inline
120int32_t mulAddRL(int left, uint32_t inRL, int16_t v, int32_t a)
121{
Andy Hung91452022017-01-05 17:11:19 -0800122#if 0 // USE_INLINE_ASSEMBLY Seems to fail with Clang b/34110890
Andy Hung86eae0e2013-12-09 12:12:46 -0800123 int32_t out;
124 if (left) {
125 asm( "smlabb %[out], %[v], %[inRL], %[a] \n"
126 : [out]"=r"(out)
127 : [inRL]"%r"(inRL), [v]"r"(v), [a]"r"(a)
128 : );
129 } else {
130 asm( "smlabt %[out], %[v], %[inRL], %[a] \n"
131 : [out]"=r"(out)
132 : [inRL]"%r"(inRL), [v]"r"(v), [a]"r"(a)
133 : );
134 }
135 return out;
136#else
137 int16_t s = left ? static_cast<int16_t>(inRL) : static_cast<int16_t>(inRL>>16);
138 return a + v * s;
139#endif
140}
141
142static inline
143int32_t mulAddRL(int left, uint32_t inRL, int32_t v, int32_t a)
144{
Andy Hung91452022017-01-05 17:11:19 -0800145#if 0 // USE_INLINE_ASSEMBLY Seems to fail with Clang b/34110890
Andy Hung86eae0e2013-12-09 12:12:46 -0800146 int32_t out;
147 if (left) {
148 asm( "smlawb %[out], %[v], %[inRL], %[a] \n"
149 : [out]"=r"(out)
150 : [inRL]"%r"(inRL), [v]"r"(v), [a]"r"(a)
151 : );
152 } else {
153 asm( "smlawt %[out], %[v], %[inRL], %[a] \n"
154 : [out]"=r"(out)
155 : [inRL]"%r"(inRL), [v]"r"(v), [a]"r"(a)
156 : );
157 }
158 return out;
159#else
160 int16_t s = left ? static_cast<int16_t>(inRL) : static_cast<int16_t>(inRL>>16);
161 return a + static_cast<int32_t>((static_cast<int64_t>(v) * s) >> 16);
162#endif
163}
164
Glenn Kasten63238ef2015-03-02 15:50:29 -0800165} // namespace android
Andy Hung86eae0e2013-12-09 12:12:46 -0800166
167#endif /*ANDROID_AUDIO_RESAMPLER_FIR_OPS_H*/