1/*
2 *  Copyright (c) 2013 The WebRTC project authors. All Rights Reserved.
3 *
4 *  Use of this source code is governed by a BSD-style license
5 *  that can be found in the LICENSE file in the root of the source
6 *  tree. An additional intellectual property rights grant can be found
7 *  in the file PATENTS.  All contributing project authors may
8 *  be found in the AUTHORS file in the root of the source tree.
9 */
10
11
12// This header file includes the inline functions in
13// the fix point signal processing library.
14
15#ifndef WEBRTC_SPL_SPL_INL_MIPS_H_
16#define WEBRTC_SPL_SPL_INL_MIPS_H_
17
18static __inline int32_t WEBRTC_SPL_MUL_16_16(int32_t a,
19                                             int32_t b) {
20  int32_t value32 = 0;
21  int32_t a1 = 0, b1 = 0;
22
23  __asm __volatile(
24#if defined(MIPS32_R2_LE)
25    "seh    %[a1],          %[a]                \n\t"
26    "seh    %[b1],          %[b]                \n\t"
27#else
28    "sll    %[a1],          %[a],         16    \n\t"
29    "sll    %[b1],          %[b],         16    \n\t"
30    "sra    %[a1],          %[a1],        16    \n\t"
31    "sra    %[b1],          %[b1],        16    \n\t"
32#endif
33    "mul    %[value32],     %[a1],  %[b1]       \n\t"
34    : [value32] "=r" (value32), [a1] "=&r" (a1), [b1] "=&r" (b1)
35    : [a] "r" (a), [b] "r" (b)
36    : "hi", "lo"
37  );
38  return value32;
39}
40
41static __inline int32_t WEBRTC_SPL_MUL_16_32_RSFT16(int16_t a,
42                                                    int32_t b) {
43  int32_t value32 = 0, b1 = 0, b2 = 0;
44  int32_t a1 = 0;
45
46  __asm __volatile(
47#if defined(MIPS32_R2_LE)
48    "seh    %[a1],          %[a]                        \n\t"
49#else
50    "sll    %[a1],          %[a],           16          \n\t"
51    "sra    %[a1],          %[a1],          16          \n\t"
52#endif
53    "andi   %[b2],          %[b],           0xFFFF      \n\t"
54    "sra    %[b1],          %[b],           16          \n\t"
55    "sra    %[b2],          %[b2],          1           \n\t"
56    "mul    %[value32],     %[a1],          %[b1]       \n\t"
57    "mul    %[b2],          %[a1],          %[b2]       \n\t"
58    "addiu  %[b2],          %[b2],          0x4000      \n\t"
59    "sra    %[b2],          %[b2],          15          \n\t"
60    "addu   %[value32],     %[value32],     %[b2]       \n\t"
61    : [value32] "=&r" (value32), [b1] "=&r" (b1), [b2] "=&r" (b2),
62      [a1] "=&r" (a1)
63    : [a] "r" (a), [b] "r" (b)
64    : "hi", "lo"
65  );
66  return value32;
67}
68
69#if defined(MIPS_DSP_R1_LE)
70static __inline int16_t WebRtcSpl_SatW32ToW16(int32_t value32) {
71  __asm __volatile(
72    "shll_s.w   %[value32], %[value32], 16      \n\t"
73    "sra        %[value32], %[value32], 16      \n\t"
74    : [value32] "+r" (value32)
75    :
76  );
77  int16_t out16 = (int16_t)value32;
78  return out16;
79}
80
81static __inline int16_t WebRtcSpl_AddSatW16(int16_t a, int16_t b) {
82  int32_t value32 = 0;
83
84  __asm __volatile(
85    "addq_s.ph      %[value32],     %[a],   %[b]    \n\t"
86    : [value32] "=r" (value32)
87    : [a] "r" (a), [b] "r" (b)
88  );
89  return (int16_t)value32;
90}
91
92static __inline int32_t WebRtcSpl_AddSatW32(int32_t l_var1, int32_t l_var2) {
93  int32_t l_sum;
94
95  __asm __volatile(
96    "addq_s.w   %[l_sum],       %[l_var1],      %[l_var2]    \n\t"
97    : [l_sum] "=r" (l_sum)
98    : [l_var1] "r" (l_var1), [l_var2] "r" (l_var2)
99  );
100
101  return l_sum;
102}
103
104static __inline int16_t WebRtcSpl_SubSatW16(int16_t var1, int16_t var2) {
105  int32_t value32;
106
107  __asm __volatile(
108    "subq_s.ph  %[value32], %[var1],    %[var2]     \n\t"
109    : [value32] "=r" (value32)
110    : [var1] "r" (var1), [var2] "r" (var2)
111  );
112
113  return (int16_t)value32;
114}
115
116static __inline int32_t WebRtcSpl_SubSatW32(int32_t l_var1, int32_t l_var2) {
117  int32_t l_diff;
118
119  __asm __volatile(
120    "subq_s.w   %[l_diff],      %[l_var1],      %[l_var2]    \n\t"
121    : [l_diff] "=r" (l_diff)
122    : [l_var1] "r" (l_var1), [l_var2] "r" (l_var2)
123  );
124
125  return l_diff;
126}
127#endif
128
129static __inline int16_t WebRtcSpl_GetSizeInBits(uint32_t n) {
130  int bits = 0;
131  int i32 = 32;
132
133  __asm __volatile(
134    "clz    %[bits],    %[n]                    \n\t"
135    "subu   %[bits],    %[i32],     %[bits]     \n\t"
136    : [bits] "=&r" (bits)
137    : [n] "r" (n), [i32] "r" (i32)
138  );
139
140  return (int16_t)bits;
141}
142
143static __inline int16_t WebRtcSpl_NormW32(int32_t a) {
144  int zeros = 0;
145
146  __asm __volatile(
147    ".set       push                                \n\t"
148    ".set       noreorder                           \n\t"
149    "bnez       %[a],       1f                      \n\t"
150    " sra       %[zeros],   %[a],       31          \n\t"
151    "b          2f                                  \n\t"
152    " move      %[zeros],   $zero                   \n\t"
153   "1:                                              \n\t"
154    "xor        %[zeros],   %[a],       %[zeros]    \n\t"
155    "clz        %[zeros],   %[zeros]                \n\t"
156    "addiu      %[zeros],   %[zeros],   -1          \n\t"
157   "2:                                              \n\t"
158    ".set       pop                                 \n\t"
159    : [zeros]"=&r"(zeros)
160    : [a] "r" (a)
161  );
162
163  return (int16_t)zeros;
164}
165
166static __inline int16_t WebRtcSpl_NormU32(uint32_t a) {
167  int zeros = 0;
168
169  __asm __volatile(
170    "clz    %[zeros],   %[a]    \n\t"
171    : [zeros] "=r" (zeros)
172    : [a] "r" (a)
173  );
174
175  return (int16_t)(zeros & 0x1f);
176}
177
178static __inline int16_t WebRtcSpl_NormW16(int16_t a) {
179  int zeros = 0;
180  int a0 = a << 16;
181
182  __asm __volatile(
183    ".set       push                                \n\t"
184    ".set       noreorder                           \n\t"
185    "bnez       %[a0],      1f                      \n\t"
186    " sra       %[zeros],   %[a0],      31          \n\t"
187    "b          2f                                  \n\t"
188    " move      %[zeros],   $zero                   \n\t"
189   "1:                                              \n\t"
190    "xor        %[zeros],   %[a0],      %[zeros]    \n\t"
191    "clz        %[zeros],   %[zeros]                \n\t"
192    "addiu      %[zeros],   %[zeros],   -1          \n\t"
193   "2:                                              \n\t"
194    ".set       pop                                 \n\t"
195    : [zeros]"=&r"(zeros)
196    : [a0] "r" (a0)
197  );
198
199  return (int16_t)zeros;
200}
201
202static __inline int32_t WebRtc_MulAccumW16(int16_t a,
203                                           int16_t b,
204                                           int32_t c) {
205  int32_t res = 0, c1 = 0;
206  __asm __volatile(
207#if defined(MIPS32_R2_LE)
208    "seh    %[a],       %[a]            \n\t"
209    "seh    %[b],       %[b]            \n\t"
210#else
211    "sll    %[a],       %[a],   16      \n\t"
212    "sll    %[b],       %[b],   16      \n\t"
213    "sra    %[a],       %[a],   16      \n\t"
214    "sra    %[b],       %[b],   16      \n\t"
215#endif
216    "mul    %[res],     %[a],   %[b]    \n\t"
217    "addu   %[c1],      %[c],   %[res]  \n\t"
218    : [c1] "=r" (c1), [res] "=&r" (res)
219    : [a] "r" (a), [b] "r" (b), [c] "r" (c)
220    : "hi", "lo"
221  );
222  return (c1);
223}
224
225#endif  // WEBRTC_SPL_SPL_INL_MIPS_H_
226