xref: /aosp_15_r20/external/gemmlowp/fixedpoint/fixedpoint_neon.h (revision 5f39d1b313f0528e11bae88b3029b54b9e1033e7)
1*5f39d1b3SJooyung Han // Copyright 2015 The Gemmlowp Authors. All Rights Reserved.
2*5f39d1b3SJooyung Han //
3*5f39d1b3SJooyung Han // Licensed under the Apache License, Version 2.0 (the "License");
4*5f39d1b3SJooyung Han // you may not use this file except in compliance with the License.
5*5f39d1b3SJooyung Han // You may obtain a copy of the License at
6*5f39d1b3SJooyung Han //
7*5f39d1b3SJooyung Han //     http://www.apache.org/licenses/LICENSE-2.0
8*5f39d1b3SJooyung Han //
9*5f39d1b3SJooyung Han // Unless required by applicable law or agreed to in writing, software
10*5f39d1b3SJooyung Han // distributed under the License is distributed on an "AS IS" BASIS,
11*5f39d1b3SJooyung Han // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12*5f39d1b3SJooyung Han // See the License for the specific language governing permissions and
13*5f39d1b3SJooyung Han // limitations under the License.
14*5f39d1b3SJooyung Han 
15*5f39d1b3SJooyung Han // fixedpoint_neon.h: optimized NEON specializations of the templates
16*5f39d1b3SJooyung Han // in fixedpoint.h.
17*5f39d1b3SJooyung Han 
18*5f39d1b3SJooyung Han #ifndef GEMMLOWP_INTERNAL_FIXEDPOINT_NEON_H_
19*5f39d1b3SJooyung Han #define GEMMLOWP_INTERNAL_FIXEDPOINT_NEON_H_
20*5f39d1b3SJooyung Han 
21*5f39d1b3SJooyung Han #include <arm_neon.h>
22*5f39d1b3SJooyung Han 
23*5f39d1b3SJooyung Han namespace gemmlowp {
24*5f39d1b3SJooyung Han 
25*5f39d1b3SJooyung Han template <>
26*5f39d1b3SJooyung Han struct FixedPointRawTypeTraits<int32x4_t> {
27*5f39d1b3SJooyung Han   typedef std::int32_t ScalarRawType;
28*5f39d1b3SJooyung Han   static constexpr int kLanes = 4;
29*5f39d1b3SJooyung Han };
30*5f39d1b3SJooyung Han 
31*5f39d1b3SJooyung Han template <>
32*5f39d1b3SJooyung Han struct FixedPointRawTypeTraits<int16x8_t> {
33*5f39d1b3SJooyung Han   typedef std::int16_t ScalarRawType;
34*5f39d1b3SJooyung Han   static constexpr int kLanes = 8;
35*5f39d1b3SJooyung Han };
36*5f39d1b3SJooyung Han 
37*5f39d1b3SJooyung Han template <>
38*5f39d1b3SJooyung Han inline int32x4_t BitAnd(int32x4_t a, int32x4_t b) {
39*5f39d1b3SJooyung Han   return vandq_s32(a, b);
40*5f39d1b3SJooyung Han }
41*5f39d1b3SJooyung Han 
42*5f39d1b3SJooyung Han template <>
43*5f39d1b3SJooyung Han inline int16x8_t BitAnd(int16x8_t a, int16x8_t b) {
44*5f39d1b3SJooyung Han   return vandq_s16(a, b);
45*5f39d1b3SJooyung Han }
46*5f39d1b3SJooyung Han 
47*5f39d1b3SJooyung Han template <>
48*5f39d1b3SJooyung Han inline int32x4_t BitOr(int32x4_t a, int32x4_t b) {
49*5f39d1b3SJooyung Han   return vorrq_s32(a, b);
50*5f39d1b3SJooyung Han }
51*5f39d1b3SJooyung Han 
52*5f39d1b3SJooyung Han template <>
53*5f39d1b3SJooyung Han inline int16x8_t BitOr(int16x8_t a, int16x8_t b) {
54*5f39d1b3SJooyung Han   return vorrq_s16(a, b);
55*5f39d1b3SJooyung Han }
56*5f39d1b3SJooyung Han 
57*5f39d1b3SJooyung Han template <>
58*5f39d1b3SJooyung Han inline int32x4_t BitXor(int32x4_t a, int32x4_t b) {
59*5f39d1b3SJooyung Han   return veorq_s32(a, b);
60*5f39d1b3SJooyung Han }
61*5f39d1b3SJooyung Han 
62*5f39d1b3SJooyung Han template <>
63*5f39d1b3SJooyung Han inline int16x8_t BitXor(int16x8_t a, int16x8_t b) {
64*5f39d1b3SJooyung Han   return veorq_s16(a, b);
65*5f39d1b3SJooyung Han }
66*5f39d1b3SJooyung Han 
67*5f39d1b3SJooyung Han template <>
68*5f39d1b3SJooyung Han inline int32x4_t BitNot(int32x4_t a) {
69*5f39d1b3SJooyung Han   return veorq_s32(a, vdupq_n_s32(-1));
70*5f39d1b3SJooyung Han }
71*5f39d1b3SJooyung Han 
72*5f39d1b3SJooyung Han template <>
73*5f39d1b3SJooyung Han inline int16x8_t BitNot(int16x8_t a) {
74*5f39d1b3SJooyung Han   return veorq_s16(a, vdupq_n_s16(-1));
75*5f39d1b3SJooyung Han }
76*5f39d1b3SJooyung Han 
77*5f39d1b3SJooyung Han template <>
78*5f39d1b3SJooyung Han inline int32x4_t Add(int32x4_t a, int32x4_t b) {
79*5f39d1b3SJooyung Han   return vaddq_s32(a, b);
80*5f39d1b3SJooyung Han }
81*5f39d1b3SJooyung Han 
82*5f39d1b3SJooyung Han template <>
83*5f39d1b3SJooyung Han inline int16x8_t Add(int16x8_t a, int16x8_t b) {
84*5f39d1b3SJooyung Han   return vaddq_s16(a, b);
85*5f39d1b3SJooyung Han }
86*5f39d1b3SJooyung Han 
87*5f39d1b3SJooyung Han template <>
88*5f39d1b3SJooyung Han inline int32x4_t Sub(int32x4_t a, int32x4_t b) {
89*5f39d1b3SJooyung Han   return vsubq_s32(a, b);
90*5f39d1b3SJooyung Han }
91*5f39d1b3SJooyung Han 
92*5f39d1b3SJooyung Han template <>
93*5f39d1b3SJooyung Han inline int16x8_t Sub(int16x8_t a, int16x8_t b) {
94*5f39d1b3SJooyung Han   return vsubq_s16(a, b);
95*5f39d1b3SJooyung Han }
96*5f39d1b3SJooyung Han 
97*5f39d1b3SJooyung Han template <>
98*5f39d1b3SJooyung Han inline int32x4_t Neg(int32x4_t a) {
99*5f39d1b3SJooyung Han   return vnegq_s32(a);
100*5f39d1b3SJooyung Han }
101*5f39d1b3SJooyung Han 
102*5f39d1b3SJooyung Han template <>
103*5f39d1b3SJooyung Han inline int16x8_t Neg(int16x8_t a) {
104*5f39d1b3SJooyung Han   return vnegq_s16(a);
105*5f39d1b3SJooyung Han }
106*5f39d1b3SJooyung Han 
107*5f39d1b3SJooyung Han template <>
108*5f39d1b3SJooyung Han inline int32x4_t ShiftLeft(int32x4_t a, int offset) {
109*5f39d1b3SJooyung Han   return vshlq_s32(a, vdupq_n_s32(offset));
110*5f39d1b3SJooyung Han }
111*5f39d1b3SJooyung Han 
112*5f39d1b3SJooyung Han template <>
113*5f39d1b3SJooyung Han inline int16x8_t ShiftLeft(int16x8_t a, int offset) {
114*5f39d1b3SJooyung Han   return vshlq_s16(a, vdupq_n_s16(offset));
115*5f39d1b3SJooyung Han }
116*5f39d1b3SJooyung Han 
117*5f39d1b3SJooyung Han template <>
118*5f39d1b3SJooyung Han inline int32x4_t ShiftLeft(int32x4_t a, int32x4_t offset) {
119*5f39d1b3SJooyung Han   return vshlq_s32(a, offset);
120*5f39d1b3SJooyung Han }
121*5f39d1b3SJooyung Han 
122*5f39d1b3SJooyung Han template <>
123*5f39d1b3SJooyung Han inline int16x8_t ShiftLeft(int16x8_t a, int16x8_t offset) {
124*5f39d1b3SJooyung Han   return vshlq_s16(a, offset);
125*5f39d1b3SJooyung Han }
126*5f39d1b3SJooyung Han 
127*5f39d1b3SJooyung Han template <>
128*5f39d1b3SJooyung Han inline int32x4_t ShiftRight(int32x4_t a, int offset) {
129*5f39d1b3SJooyung Han   return vshlq_s32(a, vdupq_n_s32(-offset));
130*5f39d1b3SJooyung Han }
131*5f39d1b3SJooyung Han 
132*5f39d1b3SJooyung Han template <>
133*5f39d1b3SJooyung Han inline int16x8_t ShiftRight(int16x8_t a, int offset) {
134*5f39d1b3SJooyung Han   return vshlq_s16(a, vdupq_n_s16(-offset));
135*5f39d1b3SJooyung Han }
136*5f39d1b3SJooyung Han 
137*5f39d1b3SJooyung Han template <>
138*5f39d1b3SJooyung Han inline int32x4_t SelectUsingMask(int32x4_t if_mask, int32x4_t then_val,
139*5f39d1b3SJooyung Han                                  int32x4_t else_val) {
140*5f39d1b3SJooyung Han   return vbslq_s32(vreinterpretq_u32_s32(if_mask), then_val, else_val);
141*5f39d1b3SJooyung Han }
142*5f39d1b3SJooyung Han 
143*5f39d1b3SJooyung Han template <>
144*5f39d1b3SJooyung Han inline int16x8_t SelectUsingMask(int16x8_t if_mask, int16x8_t then_val,
145*5f39d1b3SJooyung Han                                  int16x8_t else_val) {
146*5f39d1b3SJooyung Han   return vbslq_s16(vreinterpretq_u16_s16(if_mask), then_val, else_val);
147*5f39d1b3SJooyung Han }
148*5f39d1b3SJooyung Han 
149*5f39d1b3SJooyung Han template <>
150*5f39d1b3SJooyung Han inline int32x4_t MaskIfEqual(int32x4_t a, int32x4_t b) {
151*5f39d1b3SJooyung Han   return vreinterpretq_s32_u32(vceqq_s32(a, b));
152*5f39d1b3SJooyung Han }
153*5f39d1b3SJooyung Han 
154*5f39d1b3SJooyung Han template <>
155*5f39d1b3SJooyung Han inline int16x8_t MaskIfEqual(int16x8_t a, int16x8_t b) {
156*5f39d1b3SJooyung Han   return vreinterpretq_s16_u16(vceqq_s16(a, b));
157*5f39d1b3SJooyung Han }
158*5f39d1b3SJooyung Han 
159*5f39d1b3SJooyung Han template <>
160*5f39d1b3SJooyung Han inline int32x4_t MaskIfNotEqual(int32x4_t a, int32x4_t b) {
161*5f39d1b3SJooyung Han   return BitNot(MaskIfEqual(a, b));
162*5f39d1b3SJooyung Han }
163*5f39d1b3SJooyung Han 
164*5f39d1b3SJooyung Han template <>
165*5f39d1b3SJooyung Han inline int16x8_t MaskIfNotEqual(int16x8_t a, int16x8_t b) {
166*5f39d1b3SJooyung Han   return BitNot(MaskIfEqual(a, b));
167*5f39d1b3SJooyung Han }
168*5f39d1b3SJooyung Han 
169*5f39d1b3SJooyung Han template <>
170*5f39d1b3SJooyung Han inline int32x4_t MaskIfZero(int32x4_t a) {
171*5f39d1b3SJooyung Han   return MaskIfEqual(a, vdupq_n_s32(0));
172*5f39d1b3SJooyung Han }
173*5f39d1b3SJooyung Han 
174*5f39d1b3SJooyung Han template <>
175*5f39d1b3SJooyung Han inline int16x8_t MaskIfZero(int16x8_t a) {
176*5f39d1b3SJooyung Han   return MaskIfEqual(a, vdupq_n_s16(0));
177*5f39d1b3SJooyung Han }
178*5f39d1b3SJooyung Han 
179*5f39d1b3SJooyung Han template <>
180*5f39d1b3SJooyung Han inline int32x4_t MaskIfNonZero(int32x4_t a) {
181*5f39d1b3SJooyung Han   return vreinterpretq_s32_u32(vtstq_s32(a, a));
182*5f39d1b3SJooyung Han }
183*5f39d1b3SJooyung Han 
184*5f39d1b3SJooyung Han template <>
185*5f39d1b3SJooyung Han inline int16x8_t MaskIfNonZero(int16x8_t a) {
186*5f39d1b3SJooyung Han   return vreinterpretq_s16_u16(vtstq_s16(a, a));
187*5f39d1b3SJooyung Han }
188*5f39d1b3SJooyung Han 
189*5f39d1b3SJooyung Han template <>
190*5f39d1b3SJooyung Han inline int32x4_t MaskIfGreaterThan(int32x4_t a, int32x4_t b) {
191*5f39d1b3SJooyung Han   return vreinterpretq_s32_u32(vcgtq_s32(a, b));
192*5f39d1b3SJooyung Han }
193*5f39d1b3SJooyung Han 
194*5f39d1b3SJooyung Han template <>
195*5f39d1b3SJooyung Han inline int16x8_t MaskIfGreaterThan(int16x8_t a, int16x8_t b) {
196*5f39d1b3SJooyung Han   return vreinterpretq_s16_u16(vcgtq_s16(a, b));
197*5f39d1b3SJooyung Han }
198*5f39d1b3SJooyung Han 
199*5f39d1b3SJooyung Han template <>
200*5f39d1b3SJooyung Han inline int32x4_t MaskIfGreaterThanOrEqual(int32x4_t a, int32x4_t b) {
201*5f39d1b3SJooyung Han   return vreinterpretq_s32_u32(vcgeq_s32(a, b));
202*5f39d1b3SJooyung Han }
203*5f39d1b3SJooyung Han 
204*5f39d1b3SJooyung Han template <>
205*5f39d1b3SJooyung Han inline int16x8_t MaskIfGreaterThanOrEqual(int16x8_t a, int16x8_t b) {
206*5f39d1b3SJooyung Han   return vreinterpretq_s16_u16(vcgeq_s16(a, b));
207*5f39d1b3SJooyung Han }
208*5f39d1b3SJooyung Han 
209*5f39d1b3SJooyung Han template <>
210*5f39d1b3SJooyung Han inline int32x4_t MaskIfLessThan(int32x4_t a, int32x4_t b) {
211*5f39d1b3SJooyung Han   return vreinterpretq_s32_u32(vcltq_s32(a, b));
212*5f39d1b3SJooyung Han }
213*5f39d1b3SJooyung Han 
214*5f39d1b3SJooyung Han template <>
215*5f39d1b3SJooyung Han inline int16x8_t MaskIfLessThan(int16x8_t a, int16x8_t b) {
216*5f39d1b3SJooyung Han   return vreinterpretq_s16_u16(vcltq_s16(a, b));
217*5f39d1b3SJooyung Han }
218*5f39d1b3SJooyung Han 
219*5f39d1b3SJooyung Han template <>
220*5f39d1b3SJooyung Han inline int32x4_t MaskIfLessThanOrEqual(int32x4_t a, int32x4_t b) {
221*5f39d1b3SJooyung Han   return vreinterpretq_s32_u32(vcleq_s32(a, b));
222*5f39d1b3SJooyung Han }
223*5f39d1b3SJooyung Han 
224*5f39d1b3SJooyung Han template <>
225*5f39d1b3SJooyung Han inline int16x8_t MaskIfLessThanOrEqual(int16x8_t a, int16x8_t b) {
226*5f39d1b3SJooyung Han   return vreinterpretq_s16_u16(vcleq_s16(a, b));
227*5f39d1b3SJooyung Han }
228*5f39d1b3SJooyung Han 
229*5f39d1b3SJooyung Han template <>
230*5f39d1b3SJooyung Han inline bool All(int32x4_t a) {
231*5f39d1b3SJooyung Han   a = vandq_s32(a, vextq_s32(a, a, 1));
232*5f39d1b3SJooyung Han   a = vandq_s32(a, vextq_s32(a, a, 2));
233*5f39d1b3SJooyung Han   return vgetq_lane_s32(a, 0);
234*5f39d1b3SJooyung Han }
235*5f39d1b3SJooyung Han 
236*5f39d1b3SJooyung Han template <>
237*5f39d1b3SJooyung Han inline bool All(int16x8_t a) {
238*5f39d1b3SJooyung Han   a = vandq_s16(a, vextq_s16(a, a, 1));
239*5f39d1b3SJooyung Han   a = vandq_s16(a, vextq_s16(a, a, 2));
240*5f39d1b3SJooyung Han   a = vandq_s16(a, vextq_s16(a, a, 4));
241*5f39d1b3SJooyung Han   return vgetq_lane_s16(a, 0);
242*5f39d1b3SJooyung Han }
243*5f39d1b3SJooyung Han 
244*5f39d1b3SJooyung Han template <>
245*5f39d1b3SJooyung Han inline bool Any(int32x4_t a) {
246*5f39d1b3SJooyung Han   a = vorrq_s32(a, vextq_s32(a, a, 1));
247*5f39d1b3SJooyung Han   a = vorrq_s32(a, vextq_s32(a, a, 2));
248*5f39d1b3SJooyung Han   return vgetq_lane_s32(a, 0);
249*5f39d1b3SJooyung Han }
250*5f39d1b3SJooyung Han 
251*5f39d1b3SJooyung Han template <>
252*5f39d1b3SJooyung Han inline bool Any(int16x8_t a) {
253*5f39d1b3SJooyung Han   a = vorrq_s16(a, vextq_s16(a, a, 1));
254*5f39d1b3SJooyung Han   a = vorrq_s16(a, vextq_s16(a, a, 2));
255*5f39d1b3SJooyung Han   a = vorrq_s16(a, vextq_s16(a, a, 4));
256*5f39d1b3SJooyung Han   return vgetq_lane_s16(a, 0);
257*5f39d1b3SJooyung Han }
258*5f39d1b3SJooyung Han 
259*5f39d1b3SJooyung Han template <>
260*5f39d1b3SJooyung Han inline int32x4_t RoundingHalfSum(int32x4_t a, int32x4_t b) {
261*5f39d1b3SJooyung Han   return vrhaddq_s32(a, b);
262*5f39d1b3SJooyung Han }
263*5f39d1b3SJooyung Han 
264*5f39d1b3SJooyung Han template <>
265*5f39d1b3SJooyung Han inline int16x8_t RoundingHalfSum(int16x8_t a, int16x8_t b) {
266*5f39d1b3SJooyung Han   return vrhaddq_s16(a, b);
267*5f39d1b3SJooyung Han }
268*5f39d1b3SJooyung Han 
269*5f39d1b3SJooyung Han template <>
270*5f39d1b3SJooyung Han inline int32x4_t SaturatingRoundingDoublingHighMul(int32x4_t a, int32x4_t b) {
271*5f39d1b3SJooyung Han   return vqrdmulhq_s32(a, b);
272*5f39d1b3SJooyung Han }
273*5f39d1b3SJooyung Han 
274*5f39d1b3SJooyung Han template <>
275*5f39d1b3SJooyung Han inline int16x8_t SaturatingRoundingDoublingHighMul(int16x8_t a, int16x8_t b) {
276*5f39d1b3SJooyung Han   return vqrdmulhq_s16(a, b);
277*5f39d1b3SJooyung Han }
278*5f39d1b3SJooyung Han 
279*5f39d1b3SJooyung Han template <>
280*5f39d1b3SJooyung Han inline int32x4_t RoundingDivideByPOT(int32x4_t x, int exponent) {
281*5f39d1b3SJooyung Han   const int32x4_t shift_vec = vdupq_n_s32(-exponent);
282*5f39d1b3SJooyung Han   const int32x4_t fixup = vshrq_n_s32(vandq_s32(x, shift_vec), 31);
283*5f39d1b3SJooyung Han   const int32x4_t fixed_up_x = vqaddq_s32(x, fixup);
284*5f39d1b3SJooyung Han   return vrshlq_s32(fixed_up_x, shift_vec);
285*5f39d1b3SJooyung Han }
286*5f39d1b3SJooyung Han 
287*5f39d1b3SJooyung Han template <>
288*5f39d1b3SJooyung Han inline int16x8_t RoundingDivideByPOT(int16x8_t x, int exponent) {
289*5f39d1b3SJooyung Han   const int16x8_t shift_vec = vdupq_n_s16(-exponent);
290*5f39d1b3SJooyung Han   const int16x8_t fixup = vshrq_n_s16(vandq_s16(x, shift_vec), 15);
291*5f39d1b3SJooyung Han   const int16x8_t fixed_up_x = vqaddq_s16(x, fixup);
292*5f39d1b3SJooyung Han   return vrshlq_s16(fixed_up_x, shift_vec);
293*5f39d1b3SJooyung Han }
294*5f39d1b3SJooyung Han 
295*5f39d1b3SJooyung Han template <>
296*5f39d1b3SJooyung Han inline int32x4_t RoundingDivideByPOT(int32x4_t x, int32x4_t exponent) {
297*5f39d1b3SJooyung Han   const int32x4_t shift_vec = vnegq_s32(exponent);
298*5f39d1b3SJooyung Han   const int32x4_t fixup = vshrq_n_s32(vandq_s32(x, shift_vec), 31);
299*5f39d1b3SJooyung Han   const int32x4_t fixed_up_x = vqaddq_s32(x, fixup);
300*5f39d1b3SJooyung Han   return vrshlq_s32(fixed_up_x, shift_vec);
301*5f39d1b3SJooyung Han }
302*5f39d1b3SJooyung Han 
303*5f39d1b3SJooyung Han template <>
304*5f39d1b3SJooyung Han inline int16x8_t RoundingDivideByPOT(int16x8_t x, int16x8_t exponent) {
305*5f39d1b3SJooyung Han   const int16x8_t shift_vec = vnegq_s16(exponent);
306*5f39d1b3SJooyung Han   const int16x8_t fixup = vshrq_n_s16(vandq_s16(x, shift_vec), 15);
307*5f39d1b3SJooyung Han   const int16x8_t fixed_up_x = vqaddq_s16(x, fixup);
308*5f39d1b3SJooyung Han   return vrshlq_s16(fixed_up_x, shift_vec);
309*5f39d1b3SJooyung Han }
310*5f39d1b3SJooyung Han 
311*5f39d1b3SJooyung Han template <int Exponent>
312*5f39d1b3SJooyung Han struct ImplSaturatingRoundingMultiplyByPOT<Exponent, int32x4_t, 1> {
313*5f39d1b3SJooyung Han   static int32x4_t eval(int32x4_t x) { return vqshlq_n_s32(x, Exponent); }
314*5f39d1b3SJooyung Han };
315*5f39d1b3SJooyung Han 
316*5f39d1b3SJooyung Han template <int Exponent>
317*5f39d1b3SJooyung Han struct ImplSaturatingRoundingMultiplyByPOT<Exponent, int32x4_t, -1> {
318*5f39d1b3SJooyung Han   static int32x4_t eval(int32x4_t x) {
319*5f39d1b3SJooyung Han     const int32x4_t fixup = vshrq_n_s32(x, 31);
320*5f39d1b3SJooyung Han     const int32x4_t fixed_up_x = vqaddq_s32(x, fixup);
321*5f39d1b3SJooyung Han     return vrshrq_n_s32(fixed_up_x, -Exponent);
322*5f39d1b3SJooyung Han   }
323*5f39d1b3SJooyung Han };
324*5f39d1b3SJooyung Han 
325*5f39d1b3SJooyung Han template <int Exponent>
326*5f39d1b3SJooyung Han struct ImplSaturatingRoundingMultiplyByPOT<Exponent, int16x8_t, 1> {
327*5f39d1b3SJooyung Han   static int16x8_t eval(int16x8_t x) { return vqshlq_n_s16(x, Exponent); }
328*5f39d1b3SJooyung Han };
329*5f39d1b3SJooyung Han 
330*5f39d1b3SJooyung Han template <int Exponent>
331*5f39d1b3SJooyung Han struct ImplSaturatingRoundingMultiplyByPOT<Exponent, int16x8_t, -1> {
332*5f39d1b3SJooyung Han   static int16x8_t eval(int16x8_t x) {
333*5f39d1b3SJooyung Han     const int16x8_t fixup = vshrq_n_s16(x, 15);
334*5f39d1b3SJooyung Han     const int16x8_t fixed_up_x = vqaddq_s16(x, fixup);
335*5f39d1b3SJooyung Han     return vrshrq_n_s16(fixed_up_x, -Exponent);
336*5f39d1b3SJooyung Han   }
337*5f39d1b3SJooyung Han };
338*5f39d1b3SJooyung Han 
339*5f39d1b3SJooyung Han template <>
340*5f39d1b3SJooyung Han inline int32x4_t Dup<int32x4_t>(std::int32_t x) {
341*5f39d1b3SJooyung Han   return vdupq_n_s32(x);
342*5f39d1b3SJooyung Han }
343*5f39d1b3SJooyung Han 
344*5f39d1b3SJooyung Han template <>
345*5f39d1b3SJooyung Han inline int16x8_t Dup<int16x8_t>(std::int16_t x) {
346*5f39d1b3SJooyung Han   return vdupq_n_s16(x);
347*5f39d1b3SJooyung Han }
348*5f39d1b3SJooyung Han 
349*5f39d1b3SJooyung Han // So far this is only needed for int16.
350*5f39d1b3SJooyung Han template <>
351*5f39d1b3SJooyung Han inline int16x8_t SaturatingAdd(int16x8_t a, int16x8_t b) {
352*5f39d1b3SJooyung Han   return vqaddq_s16(a, b);
353*5f39d1b3SJooyung Han }
354*5f39d1b3SJooyung Han 
355*5f39d1b3SJooyung Han }  // end namespace gemmlowp
356*5f39d1b3SJooyung Han 
357*5f39d1b3SJooyung Han #endif  // GEMMLOWP_INTERNAL_FIXEDPOINT_NEON_H_
358