1 //! # References
2 //!
3 //! - Section 8.5 "32-bit SIMD intrinsics" of ACLE
4 //!
5 //! Intrinsics that could live here
6 //!
7 //! - \[x\] __sel
8 //! - \[ \] __ssat16
9 //! - \[ \] __usat16
10 //! - \[ \] __sxtab16
11 //! - \[ \] __sxtb16
12 //! - \[ \] __uxtab16
13 //! - \[ \] __uxtb16
14 //! - \[x\] __qadd8
15 //! - \[x\] __qsub8
16 //! - \[x\] __sadd8
17 //! - \[x\] __shadd8
18 //! - \[x\] __shsub8
19 //! - \[x\] __ssub8
20 //! - \[ \] __uadd8
21 //! - \[ \] __uhadd8
22 //! - \[ \] __uhsub8
23 //! - \[ \] __uqadd8
24 //! - \[ \] __uqsub8
25 //! - \[x\] __usub8
26 //! - \[x\] __usad8
27 //! - \[x\] __usada8
28 //! - \[x\] __qadd16
29 //! - \[x\] __qasx
30 //! - \[x\] __qsax
31 //! - \[x\] __qsub16
32 //! - \[x\] __sadd16
33 //! - \[x\] __sasx
34 //! - \[x\] __shadd16
35 //! - \[ \] __shasx
36 //! - \[ \] __shsax
37 //! - \[x\] __shsub16
38 //! - \[ \] __ssax
39 //! - \[ \] __ssub16
40 //! - \[ \] __uadd16
41 //! - \[ \] __uasx
42 //! - \[ \] __uhadd16
43 //! - \[ \] __uhasx
44 //! - \[ \] __uhsax
45 //! - \[ \] __uhsub16
46 //! - \[ \] __uqadd16
47 //! - \[ \] __uqasx
48 //! - \[x\] __uqsax
49 //! - \[ \] __uqsub16
50 //! - \[ \] __usax
51 //! - \[ \] __usub16
52 //! - \[x\] __smlad
53 //! - \[ \] __smladx
54 //! - \[ \] __smlald
55 //! - \[ \] __smlaldx
56 //! - \[x\] __smlsd
57 //! - \[ \] __smlsdx
58 //! - \[ \] __smlsld
59 //! - \[ \] __smlsldx
60 //! - \[x\] __smuad
61 //! - \[x\] __smuadx
62 //! - \[x\] __smusd
63 //! - \[x\] __smusdx
64 
65 #[cfg(test)]
66 use stdarch_test::assert_instr;
67 
68 use crate::{core_arch::arm::dsp::int16x2_t, mem::transmute};
69 
70 types! {
71     /// ARM-specific 32-bit wide vector of four packed `i8`.
72     pub struct int8x4_t(i8, i8, i8, i8);
73     /// ARM-specific 32-bit wide vector of four packed `u8`.
74     pub struct uint8x4_t(u8, u8, u8, u8);
75 }
76 
77 macro_rules! dsp_call {
78     ($name:expr, $a:expr, $b:expr) => {
79         transmute($name(transmute($a), transmute($b)))
80     };
81 }
82 
83 extern "unadjusted" {
84     #[link_name = "llvm.arm.qadd8"]
arm_qadd8(a: i32, b: i32) -> i3285     fn arm_qadd8(a: i32, b: i32) -> i32;
86 
87     #[link_name = "llvm.arm.qsub8"]
arm_qsub8(a: i32, b: i32) -> i3288     fn arm_qsub8(a: i32, b: i32) -> i32;
89 
90     #[link_name = "llvm.arm.qsub16"]
arm_qsub16(a: i32, b: i32) -> i3291     fn arm_qsub16(a: i32, b: i32) -> i32;
92 
93     #[link_name = "llvm.arm.qadd16"]
arm_qadd16(a: i32, b: i32) -> i3294     fn arm_qadd16(a: i32, b: i32) -> i32;
95 
96     #[link_name = "llvm.arm.qasx"]
arm_qasx(a: i32, b: i32) -> i3297     fn arm_qasx(a: i32, b: i32) -> i32;
98 
99     #[link_name = "llvm.arm.qsax"]
arm_qsax(a: i32, b: i32) -> i32100     fn arm_qsax(a: i32, b: i32) -> i32;
101 
102     #[link_name = "llvm.arm.sadd16"]
arm_sadd16(a: i32, b: i32) -> i32103     fn arm_sadd16(a: i32, b: i32) -> i32;
104 
105     #[link_name = "llvm.arm.sadd8"]
arm_sadd8(a: i32, b: i32) -> i32106     fn arm_sadd8(a: i32, b: i32) -> i32;
107 
108     #[link_name = "llvm.arm.smlad"]
arm_smlad(a: i32, b: i32, c: i32) -> i32109     fn arm_smlad(a: i32, b: i32, c: i32) -> i32;
110 
111     #[link_name = "llvm.arm.smlsd"]
arm_smlsd(a: i32, b: i32, c: i32) -> i32112     fn arm_smlsd(a: i32, b: i32, c: i32) -> i32;
113 
114     #[link_name = "llvm.arm.sasx"]
arm_sasx(a: i32, b: i32) -> i32115     fn arm_sasx(a: i32, b: i32) -> i32;
116 
117     #[link_name = "llvm.arm.sel"]
arm_sel(a: i32, b: i32) -> i32118     fn arm_sel(a: i32, b: i32) -> i32;
119 
120     #[link_name = "llvm.arm.shadd8"]
arm_shadd8(a: i32, b: i32) -> i32121     fn arm_shadd8(a: i32, b: i32) -> i32;
122 
123     #[link_name = "llvm.arm.shadd16"]
arm_shadd16(a: i32, b: i32) -> i32124     fn arm_shadd16(a: i32, b: i32) -> i32;
125 
126     #[link_name = "llvm.arm.shsub8"]
arm_shsub8(a: i32, b: i32) -> i32127     fn arm_shsub8(a: i32, b: i32) -> i32;
128 
129     #[link_name = "llvm.arm.ssub8"]
arm_ssub8(a: i32, b: i32) -> i32130     fn arm_ssub8(a: i32, b: i32) -> i32;
131 
132     #[link_name = "llvm.arm.usub8"]
arm_usub8(a: i32, b: i32) -> i32133     fn arm_usub8(a: i32, b: i32) -> i32;
134 
135     #[link_name = "llvm.arm.shsub16"]
arm_shsub16(a: i32, b: i32) -> i32136     fn arm_shsub16(a: i32, b: i32) -> i32;
137 
138     #[link_name = "llvm.arm.smuad"]
arm_smuad(a: i32, b: i32) -> i32139     fn arm_smuad(a: i32, b: i32) -> i32;
140 
141     #[link_name = "llvm.arm.smuadx"]
arm_smuadx(a: i32, b: i32) -> i32142     fn arm_smuadx(a: i32, b: i32) -> i32;
143 
144     #[link_name = "llvm.arm.smusd"]
arm_smusd(a: i32, b: i32) -> i32145     fn arm_smusd(a: i32, b: i32) -> i32;
146 
147     #[link_name = "llvm.arm.smusdx"]
arm_smusdx(a: i32, b: i32) -> i32148     fn arm_smusdx(a: i32, b: i32) -> i32;
149 
150     #[link_name = "llvm.arm.usad8"]
arm_usad8(a: i32, b: i32) -> u32151     fn arm_usad8(a: i32, b: i32) -> u32;
152 }
153 
154 /// Saturating four 8-bit integer additions
155 ///
156 /// Returns the 8-bit signed equivalent of
157 ///
158 /// res\[0\] = a\[0\] + b\[0\]
159 /// res\[1\] = a\[1\] + b\[1\]
160 /// res\[2\] = a\[2\] + b\[2\]
161 /// res\[3\] = a\[3\] + b\[3\]
162 #[inline]
163 #[cfg_attr(test, assert_instr(qadd8))]
__qadd8(a: int8x4_t, b: int8x4_t) -> int8x4_t164 pub unsafe fn __qadd8(a: int8x4_t, b: int8x4_t) -> int8x4_t {
165     dsp_call!(arm_qadd8, a, b)
166 }
167 
168 /// Saturating two 8-bit integer subtraction
169 ///
170 /// Returns the 8-bit signed equivalent of
171 ///
172 /// res\[0\] = a\[0\] - b\[0\]
173 /// res\[1\] = a\[1\] - b\[1\]
174 /// res\[2\] = a\[2\] - b\[2\]
175 /// res\[3\] = a\[3\] - b\[3\]
176 #[inline]
177 #[cfg_attr(test, assert_instr(qsub8))]
__qsub8(a: int8x4_t, b: int8x4_t) -> int8x4_t178 pub unsafe fn __qsub8(a: int8x4_t, b: int8x4_t) -> int8x4_t {
179     dsp_call!(arm_qsub8, a, b)
180 }
181 
182 /// Saturating two 16-bit integer subtraction
183 ///
184 /// Returns the 16-bit signed equivalent of
185 ///
186 /// res\[0\] = a\[0\] - b\[0\]
187 /// res\[1\] = a\[1\] - b\[1\]
188 #[inline]
189 #[cfg_attr(test, assert_instr(qsub16))]
__qsub16(a: int16x2_t, b: int16x2_t) -> int16x2_t190 pub unsafe fn __qsub16(a: int16x2_t, b: int16x2_t) -> int16x2_t {
191     dsp_call!(arm_qsub16, a, b)
192 }
193 
194 /// Saturating two 16-bit integer additions
195 ///
196 /// Returns the 16-bit signed equivalent of
197 ///
198 /// res\[0\] = a\[0\] + b\[0\]
199 /// res\[1\] = a\[1\] + b\[1\]
200 #[inline]
201 #[cfg_attr(test, assert_instr(qadd16))]
__qadd16(a: int16x2_t, b: int16x2_t) -> int16x2_t202 pub unsafe fn __qadd16(a: int16x2_t, b: int16x2_t) -> int16x2_t {
203     dsp_call!(arm_qadd16, a, b)
204 }
205 
206 /// Returns the 16-bit signed saturated equivalent of
207 ///
208 /// res\[0\] = a\[0\] - b\[1\]
209 /// res\[1\] = a\[1\] + b\[0\]
210 #[inline]
211 #[cfg_attr(test, assert_instr(qasx))]
__qasx(a: int16x2_t, b: int16x2_t) -> int16x2_t212 pub unsafe fn __qasx(a: int16x2_t, b: int16x2_t) -> int16x2_t {
213     dsp_call!(arm_qasx, a, b)
214 }
215 
216 /// Returns the 16-bit signed saturated equivalent of
217 ///
218 /// res\[0\] = a\[0\] + b\[1\]
219 /// res\[1\] = a\[1\] - b\[0\]
220 #[inline]
221 #[cfg_attr(test, assert_instr(qsax))]
__qsax(a: int16x2_t, b: int16x2_t) -> int16x2_t222 pub unsafe fn __qsax(a: int16x2_t, b: int16x2_t) -> int16x2_t {
223     dsp_call!(arm_qsax, a, b)
224 }
225 
226 /// Returns the 16-bit signed saturated equivalent of
227 ///
228 /// res\[0\] = a\[0\] + b\[1\]
229 /// res\[1\] = a\[1\] + b\[0\]
230 ///
231 /// and the GE bits of the APSR are set.
232 #[inline]
233 #[cfg_attr(test, assert_instr(sadd16))]
__sadd16(a: int16x2_t, b: int16x2_t) -> int16x2_t234 pub unsafe fn __sadd16(a: int16x2_t, b: int16x2_t) -> int16x2_t {
235     dsp_call!(arm_sadd16, a, b)
236 }
237 
238 /// Returns the 8-bit signed saturated equivalent of
239 ///
240 /// res\[0\] = a\[0\] + b\[1\]
241 /// res\[1\] = a\[1\] + b\[0\]
242 /// res\[2\] = a\[2\] + b\[2\]
243 /// res\[3\] = a\[3\] + b\[3\]
244 ///
245 /// and the GE bits of the APSR are set.
246 #[inline]
247 #[cfg_attr(test, assert_instr(sadd8))]
__sadd8(a: int8x4_t, b: int8x4_t) -> int8x4_t248 pub unsafe fn __sadd8(a: int8x4_t, b: int8x4_t) -> int8x4_t {
249     dsp_call!(arm_sadd8, a, b)
250 }
251 
252 /// Dual 16-bit Signed Multiply with Addition of products
253 /// and 32-bit accumulation.
254 ///
255 /// Returns the 16-bit signed equivalent of
256 /// res = a\[0\] * b\[0\] + a\[1\] * b\[1\] + c
257 #[inline]
258 #[cfg_attr(test, assert_instr(smlad))]
__smlad(a: int16x2_t, b: int16x2_t, c: i32) -> i32259 pub unsafe fn __smlad(a: int16x2_t, b: int16x2_t, c: i32) -> i32 {
260     arm_smlad(transmute(a), transmute(b), c)
261 }
262 
263 /// Dual 16-bit Signed Multiply with Subtraction  of products
264 /// and 32-bit accumulation and overflow detection.
265 ///
266 /// Returns the 16-bit signed equivalent of
267 /// res = a\[0\] * b\[0\] - a\[1\] * b\[1\] + c
268 #[inline]
269 #[cfg_attr(test, assert_instr(smlsd))]
__smlsd(a: int16x2_t, b: int16x2_t, c: i32) -> i32270 pub unsafe fn __smlsd(a: int16x2_t, b: int16x2_t, c: i32) -> i32 {
271     arm_smlsd(transmute(a), transmute(b), c)
272 }
273 
274 /// Returns the 16-bit signed equivalent of
275 ///
276 /// res\[0\] = a\[0\] - b\[1\]
277 /// res\[1\] = a\[1\] + b\[0\]
278 ///
279 /// and the GE bits of the APSR are set.
280 #[inline]
281 #[cfg_attr(test, assert_instr(sasx))]
__sasx(a: int16x2_t, b: int16x2_t) -> int16x2_t282 pub unsafe fn __sasx(a: int16x2_t, b: int16x2_t) -> int16x2_t {
283     dsp_call!(arm_sasx, a, b)
284 }
285 
286 /// Select bytes from each operand according to APSR GE flags
287 ///
288 /// Returns the equivalent of
289 ///
290 /// res\[0\] = GE\[0\] ? a\[0\] : b\[0\]
291 /// res\[1\] = GE\[1\] ? a\[1\] : b\[1\]
292 /// res\[2\] = GE\[2\] ? a\[2\] : b\[2\]
293 /// res\[3\] = GE\[3\] ? a\[3\] : b\[3\]
294 ///
295 /// where GE are bits of APSR
296 #[inline]
297 #[cfg_attr(test, assert_instr(sel))]
__sel(a: int8x4_t, b: int8x4_t) -> int8x4_t298 pub unsafe fn __sel(a: int8x4_t, b: int8x4_t) -> int8x4_t {
299     dsp_call!(arm_sel, a, b)
300 }
301 
302 /// Signed halving parallel byte-wise addition.
303 ///
304 /// Returns the 8-bit signed equivalent of
305 ///
306 /// res\[0\] = (a\[0\] + b\[0\]) / 2
307 /// res\[1\] = (a\[1\] + b\[1\]) / 2
308 /// res\[2\] = (a\[2\] + b\[2\]) / 2
309 /// res\[3\] = (a\[3\] + b\[3\]) / 2
310 #[inline]
311 #[cfg_attr(test, assert_instr(shadd8))]
__shadd8(a: int8x4_t, b: int8x4_t) -> int8x4_t312 pub unsafe fn __shadd8(a: int8x4_t, b: int8x4_t) -> int8x4_t {
313     dsp_call!(arm_shadd8, a, b)
314 }
315 
316 /// Signed halving parallel halfword-wise addition.
317 ///
318 /// Returns the 16-bit signed equivalent of
319 ///
320 /// res\[0\] = (a\[0\] + b\[0\]) / 2
321 /// res\[1\] = (a\[1\] + b\[1\]) / 2
322 #[inline]
323 #[cfg_attr(test, assert_instr(shadd16))]
__shadd16(a: int16x2_t, b: int16x2_t) -> int16x2_t324 pub unsafe fn __shadd16(a: int16x2_t, b: int16x2_t) -> int16x2_t {
325     dsp_call!(arm_shadd16, a, b)
326 }
327 
328 /// Signed halving parallel byte-wise subtraction.
329 ///
330 /// Returns the 8-bit signed equivalent of
331 ///
332 /// res\[0\] = (a\[0\] - b\[0\]) / 2
333 /// res\[1\] = (a\[1\] - b\[1\]) / 2
334 /// res\[2\] = (a\[2\] - b\[2\]) / 2
335 /// res\[3\] = (a\[3\] - b\[3\]) / 2
336 #[inline]
337 #[cfg_attr(test, assert_instr(shsub8))]
__shsub8(a: int8x4_t, b: int8x4_t) -> int8x4_t338 pub unsafe fn __shsub8(a: int8x4_t, b: int8x4_t) -> int8x4_t {
339     dsp_call!(arm_shsub8, a, b)
340 }
341 
342 /// Inserts a `USUB8` instruction.
343 ///
344 /// Returns the 8-bit unsigned equivalent of
345 ///
346 /// res\[0\] = a\[0\] - a\[0\]
347 /// res\[1\] = a\[1\] - a\[1\]
348 /// res\[2\] = a\[2\] - a\[2\]
349 /// res\[3\] = a\[3\] - a\[3\]
350 ///
351 /// where \[0\] is the lower 8 bits and \[3\] is the upper 8 bits.
352 /// The GE bits of the APSR are set.
353 #[inline]
354 #[cfg_attr(test, assert_instr(usub8))]
__usub8(a: uint8x4_t, b: uint8x4_t) -> uint8x4_t355 pub unsafe fn __usub8(a: uint8x4_t, b: uint8x4_t) -> uint8x4_t {
356     dsp_call!(arm_usub8, a, b)
357 }
358 
359 /// Inserts a `SSUB8` instruction.
360 ///
361 /// Returns the 8-bit signed equivalent of
362 ///
363 /// res\[0\] = a\[0\] - a\[0\]
364 /// res\[1\] = a\[1\] - a\[1\]
365 /// res\[2\] = a\[2\] - a\[2\]
366 /// res\[3\] = a\[3\] - a\[3\]
367 ///
368 /// where \[0\] is the lower 8 bits and \[3\] is the upper 8 bits.
369 /// The GE bits of the APSR are set.
370 #[inline]
371 #[cfg_attr(test, assert_instr(ssub8))]
__ssub8(a: int8x4_t, b: int8x4_t) -> int8x4_t372 pub unsafe fn __ssub8(a: int8x4_t, b: int8x4_t) -> int8x4_t {
373     dsp_call!(arm_ssub8, a, b)
374 }
375 
376 /// Signed halving parallel halfword-wise subtraction.
377 ///
378 /// Returns the 16-bit signed equivalent of
379 ///
380 /// res\[0\] = (a\[0\] - b\[0\]) / 2
381 /// res\[1\] = (a\[1\] - b\[1\]) / 2
382 #[inline]
383 #[cfg_attr(test, assert_instr(shsub16))]
__shsub16(a: int16x2_t, b: int16x2_t) -> int16x2_t384 pub unsafe fn __shsub16(a: int16x2_t, b: int16x2_t) -> int16x2_t {
385     dsp_call!(arm_shsub16, a, b)
386 }
387 
388 /// Signed Dual Multiply Add.
389 ///
390 /// Returns the equivalent of
391 ///
392 /// res = a\[0\] * b\[0\] + a\[1\] * b\[1\]
393 ///
394 /// and sets the Q flag if overflow occurs on the addition.
395 #[inline]
396 #[cfg_attr(test, assert_instr(smuad))]
__smuad(a: int16x2_t, b: int16x2_t) -> i32397 pub unsafe fn __smuad(a: int16x2_t, b: int16x2_t) -> i32 {
398     arm_smuad(transmute(a), transmute(b))
399 }
400 
401 /// Signed Dual Multiply Add Reversed.
402 ///
403 /// Returns the equivalent of
404 ///
405 /// res = a\[0\] * b\[1\] + a\[1\] * b\[0\]
406 ///
407 /// and sets the Q flag if overflow occurs on the addition.
408 #[inline]
409 #[cfg_attr(test, assert_instr(smuadx))]
__smuadx(a: int16x2_t, b: int16x2_t) -> i32410 pub unsafe fn __smuadx(a: int16x2_t, b: int16x2_t) -> i32 {
411     arm_smuadx(transmute(a), transmute(b))
412 }
413 
414 /// Signed Dual Multiply Subtract.
415 ///
416 /// Returns the equivalent of
417 ///
418 /// res = a\[0\] * b\[0\] - a\[1\] * b\[1\]
419 ///
420 /// and sets the Q flag if overflow occurs on the addition.
421 #[inline]
422 #[cfg_attr(test, assert_instr(smusd))]
__smusd(a: int16x2_t, b: int16x2_t) -> i32423 pub unsafe fn __smusd(a: int16x2_t, b: int16x2_t) -> i32 {
424     arm_smusd(transmute(a), transmute(b))
425 }
426 
427 /// Signed Dual Multiply Subtract Reversed.
428 ///
429 /// Returns the equivalent of
430 ///
431 /// res = a\[0\] * b\[1\] - a\[1\] * b\[0\]
432 ///
433 /// and sets the Q flag if overflow occurs on the addition.
434 #[inline]
435 #[cfg_attr(test, assert_instr(smusdx))]
__smusdx(a: int16x2_t, b: int16x2_t) -> i32436 pub unsafe fn __smusdx(a: int16x2_t, b: int16x2_t) -> i32 {
437     arm_smusdx(transmute(a), transmute(b))
438 }
439 
440 /// Sum of 8-bit absolute differences.
441 ///
442 /// Returns the 8-bit unsigned equivalent of
443 ///
444 /// res = abs(a\[0\] - b\[0\]) + abs(a\[1\] - b\[1\]) +\
445 ///          (a\[2\] - b\[2\]) + (a\[3\] - b\[3\])
446 #[inline]
447 #[cfg_attr(test, assert_instr(usad8))]
__usad8(a: int8x4_t, b: int8x4_t) -> u32448 pub unsafe fn __usad8(a: int8x4_t, b: int8x4_t) -> u32 {
449     arm_usad8(transmute(a), transmute(b))
450 }
451 
452 /// Sum of 8-bit absolute differences and constant.
453 ///
454 /// Returns the 8-bit unsigned equivalent of
455 ///
456 /// res = abs(a\[0\] - b\[0\]) + abs(a\[1\] - b\[1\]) +\
457 ///          (a\[2\] - b\[2\]) + (a\[3\] - b\[3\]) + c
458 #[inline]
459 #[cfg_attr(test, assert_instr(usad8))]
__usada8(a: int8x4_t, b: int8x4_t, c: u32) -> u32460 pub unsafe fn __usada8(a: int8x4_t, b: int8x4_t, c: u32) -> u32 {
461     __usad8(a, b) + c
462 }
463 
464 #[cfg(test)]
465 mod tests {
466     use crate::core_arch::simd::{i16x2, i8x4, u8x4};
467     use std::mem::transmute;
468     use stdarch_test::simd_test;
469 
470     #[test]
qadd8()471     fn qadd8() {
472         unsafe {
473             let a = i8x4::new(1, 2, 3, i8::MAX);
474             let b = i8x4::new(2, -1, 0, 1);
475             let c = i8x4::new(3, 1, 3, i8::MAX);
476             let r: i8x4 = dsp_call!(super::__qadd8, a, b);
477             assert_eq!(r, c);
478         }
479     }
480 
481     #[test]
qsub8()482     fn qsub8() {
483         unsafe {
484             let a = i8x4::new(1, 2, 3, i8::MIN);
485             let b = i8x4::new(2, -1, 0, 1);
486             let c = i8x4::new(-1, 3, 3, i8::MIN);
487             let r: i8x4 = dsp_call!(super::__qsub8, a, b);
488             assert_eq!(r, c);
489         }
490     }
491 
492     #[test]
qadd16()493     fn qadd16() {
494         unsafe {
495             let a = i16x2::new(1, 2);
496             let b = i16x2::new(2, -1);
497             let c = i16x2::new(3, 1);
498             let r: i16x2 = dsp_call!(super::__qadd16, a, b);
499             assert_eq!(r, c);
500         }
501     }
502 
503     #[test]
qsub16()504     fn qsub16() {
505         unsafe {
506             let a = i16x2::new(10, 20);
507             let b = i16x2::new(20, -10);
508             let c = i16x2::new(-10, 30);
509             let r: i16x2 = dsp_call!(super::__qsub16, a, b);
510             assert_eq!(r, c);
511         }
512     }
513 
514     #[test]
qasx()515     fn qasx() {
516         unsafe {
517             let a = i16x2::new(1, i16::MAX);
518             let b = i16x2::new(2, 2);
519             let c = i16x2::new(-1, i16::MAX);
520             let r: i16x2 = dsp_call!(super::__qasx, a, b);
521             assert_eq!(r, c);
522         }
523     }
524 
525     #[test]
qsax()526     fn qsax() {
527         unsafe {
528             let a = i16x2::new(1, i16::MAX);
529             let b = i16x2::new(2, 2);
530             let c = i16x2::new(3, i16::MAX - 2);
531             let r: i16x2 = dsp_call!(super::__qsax, a, b);
532             assert_eq!(r, c);
533         }
534     }
535 
536     #[test]
sadd16()537     fn sadd16() {
538         unsafe {
539             let a = i16x2::new(1, i16::MAX);
540             let b = i16x2::new(2, 2);
541             let c = i16x2::new(3, -i16::MAX);
542             let r: i16x2 = dsp_call!(super::__sadd16, a, b);
543             assert_eq!(r, c);
544         }
545     }
546 
547     #[test]
sadd8()548     fn sadd8() {
549         unsafe {
550             let a = i8x4::new(1, 2, 3, i8::MAX);
551             let b = i8x4::new(4, 3, 2, 2);
552             let c = i8x4::new(5, 5, 5, -i8::MAX);
553             let r: i8x4 = dsp_call!(super::__sadd8, a, b);
554             assert_eq!(r, c);
555         }
556     }
557 
558     #[test]
sasx()559     fn sasx() {
560         unsafe {
561             let a = i16x2::new(1, 2);
562             let b = i16x2::new(2, 1);
563             let c = i16x2::new(0, 4);
564             let r: i16x2 = dsp_call!(super::__sasx, a, b);
565             assert_eq!(r, c);
566         }
567     }
568 
569     #[test]
smlad()570     fn smlad() {
571         unsafe {
572             let a = i16x2::new(1, 2);
573             let b = i16x2::new(3, 4);
574             let r = super::__smlad(transmute(a), transmute(b), 10);
575             assert_eq!(r, (1 * 3) + (2 * 4) + 10);
576         }
577     }
578 
579     #[test]
smlsd()580     fn smlsd() {
581         unsafe {
582             let a = i16x2::new(1, 2);
583             let b = i16x2::new(3, 4);
584             let r = super::__smlsd(transmute(a), transmute(b), 10);
585             assert_eq!(r, ((1 * 3) - (2 * 4)) + 10);
586         }
587     }
588 
589     #[test]
sel()590     fn sel() {
591         unsafe {
592             let a = i8x4::new(1, 2, 3, i8::MAX);
593             let b = i8x4::new(4, 3, 2, 2);
594             // call sadd8() to set GE bits
595             super::__sadd8(transmute(a), transmute(b));
596             let c = i8x4::new(1, 2, 3, i8::MAX);
597             let r: i8x4 = dsp_call!(super::__sel, a, b);
598             assert_eq!(r, c);
599         }
600     }
601 
602     #[test]
shadd8()603     fn shadd8() {
604         unsafe {
605             let a = i8x4::new(1, 2, 3, 4);
606             let b = i8x4::new(5, 4, 3, 2);
607             let c = i8x4::new(3, 3, 3, 3);
608             let r: i8x4 = dsp_call!(super::__shadd8, a, b);
609             assert_eq!(r, c);
610         }
611     }
612 
613     #[test]
shadd16()614     fn shadd16() {
615         unsafe {
616             let a = i16x2::new(1, 2);
617             let b = i16x2::new(5, 4);
618             let c = i16x2::new(3, 3);
619             let r: i16x2 = dsp_call!(super::__shadd16, a, b);
620             assert_eq!(r, c);
621         }
622     }
623 
624     #[test]
shsub8()625     fn shsub8() {
626         unsafe {
627             let a = i8x4::new(1, 2, 3, 4);
628             let b = i8x4::new(5, 4, 3, 2);
629             let c = i8x4::new(-2, -1, 0, 1);
630             let r: i8x4 = dsp_call!(super::__shsub8, a, b);
631             assert_eq!(r, c);
632         }
633     }
634 
635     #[test]
ssub8()636     fn ssub8() {
637         unsafe {
638             let a = i8x4::new(1, 2, 3, 4);
639             let b = i8x4::new(5, 4, 3, 2);
640             let c = i8x4::new(-4, -2, 0, 2);
641             let r: i8x4 = dsp_call!(super::__ssub8, a, b);
642             assert_eq!(r, c);
643         }
644     }
645 
646     #[test]
usub8()647     fn usub8() {
648         unsafe {
649             let a = u8x4::new(1, 2, 3, 4);
650             let b = u8x4::new(5, 4, 3, 2);
651             let c = u8x4::new(252, 254, 0, 2);
652             let r: u8x4 = dsp_call!(super::__usub8, a, b);
653             assert_eq!(r, c);
654         }
655     }
656 
657     #[test]
shsub16()658     fn shsub16() {
659         unsafe {
660             let a = i16x2::new(1, 2);
661             let b = i16x2::new(5, 4);
662             let c = i16x2::new(-2, -1);
663             let r: i16x2 = dsp_call!(super::__shsub16, a, b);
664             assert_eq!(r, c);
665         }
666     }
667 
668     #[test]
smuad()669     fn smuad() {
670         unsafe {
671             let a = i16x2::new(1, 2);
672             let b = i16x2::new(5, 4);
673             let r = super::__smuad(transmute(a), transmute(b));
674             assert_eq!(r, 13);
675         }
676     }
677 
678     #[test]
smuadx()679     fn smuadx() {
680         unsafe {
681             let a = i16x2::new(1, 2);
682             let b = i16x2::new(5, 4);
683             let r = super::__smuadx(transmute(a), transmute(b));
684             assert_eq!(r, 14);
685         }
686     }
687 
688     #[test]
smusd()689     fn smusd() {
690         unsafe {
691             let a = i16x2::new(1, 2);
692             let b = i16x2::new(5, 4);
693             let r = super::__smusd(transmute(a), transmute(b));
694             assert_eq!(r, -3);
695         }
696     }
697 
698     #[test]
smusdx()699     fn smusdx() {
700         unsafe {
701             let a = i16x2::new(1, 2);
702             let b = i16x2::new(5, 4);
703             let r = super::__smusdx(transmute(a), transmute(b));
704             assert_eq!(r, -6);
705         }
706     }
707 
708     #[test]
usad8()709     fn usad8() {
710         unsafe {
711             let a = i8x4::new(1, 2, 3, 4);
712             let b = i8x4::new(4, 3, 2, 1);
713             let r = super::__usad8(transmute(a), transmute(b));
714             assert_eq!(r, 8);
715         }
716     }
717 
718     #[test]
usad8a()719     fn usad8a() {
720         unsafe {
721             let a = i8x4::new(1, 2, 3, 4);
722             let b = i8x4::new(4, 3, 2, 1);
723             let c = 10;
724             let r = super::__usada8(transmute(a), transmute(b), c);
725             assert_eq!(r, 8 + c);
726         }
727     }
728 }
729