core/stdarch/crates/core_arch/src/arm/
simd32.rs

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)]
66use stdarch_test::assert_instr;
67
68use crate::mem::transmute;
69
70/// ARM-specific vector of four packed `i8` packed into a 32-bit integer.
71#[allow(non_camel_case_types)]
72#[unstable(feature = "stdarch_arm_dsp", issue = "117237")]
73pub type int8x4_t = i32;
74
75/// ARM-specific vector of four packed `u8` packed into a 32-bit integer.
76#[allow(non_camel_case_types)]
77#[unstable(feature = "stdarch_arm_dsp", issue = "117237")]
78pub type uint8x4_t = u32;
79
80/// ARM-specific vector of two packed `i16` packed into a 32-bit integer.
81#[allow(non_camel_case_types)]
82#[unstable(feature = "stdarch_arm_dsp", issue = "117237")]
83pub type int16x2_t = i32;
84
85/// ARM-specific vector of two packed `u16` packed into a 32-bit integer.
86#[allow(non_camel_case_types)]
87#[unstable(feature = "stdarch_arm_dsp", issue = "117237")]
88pub type uint16x2_t = u32;
89
90macro_rules! dsp_call {
91    ($name:expr, $a:expr, $b:expr) => {
92        transmute($name(transmute($a), transmute($b)))
93    };
94}
95
96extern "unadjusted" {
97    #[link_name = "llvm.arm.qadd8"]
98    fn arm_qadd8(a: i32, b: i32) -> i32;
99
100    #[link_name = "llvm.arm.qsub8"]
101    fn arm_qsub8(a: i32, b: i32) -> i32;
102
103    #[link_name = "llvm.arm.qsub16"]
104    fn arm_qsub16(a: i32, b: i32) -> i32;
105
106    #[link_name = "llvm.arm.qadd16"]
107    fn arm_qadd16(a: i32, b: i32) -> i32;
108
109    #[link_name = "llvm.arm.qasx"]
110    fn arm_qasx(a: i32, b: i32) -> i32;
111
112    #[link_name = "llvm.arm.qsax"]
113    fn arm_qsax(a: i32, b: i32) -> i32;
114
115    #[link_name = "llvm.arm.sadd16"]
116    fn arm_sadd16(a: i32, b: i32) -> i32;
117
118    #[link_name = "llvm.arm.sadd8"]
119    fn arm_sadd8(a: i32, b: i32) -> i32;
120
121    #[link_name = "llvm.arm.smlad"]
122    fn arm_smlad(a: i32, b: i32, c: i32) -> i32;
123
124    #[link_name = "llvm.arm.smlsd"]
125    fn arm_smlsd(a: i32, b: i32, c: i32) -> i32;
126
127    #[link_name = "llvm.arm.sasx"]
128    fn arm_sasx(a: i32, b: i32) -> i32;
129
130    #[link_name = "llvm.arm.sel"]
131    fn arm_sel(a: i32, b: i32) -> i32;
132
133    #[link_name = "llvm.arm.shadd8"]
134    fn arm_shadd8(a: i32, b: i32) -> i32;
135
136    #[link_name = "llvm.arm.shadd16"]
137    fn arm_shadd16(a: i32, b: i32) -> i32;
138
139    #[link_name = "llvm.arm.shsub8"]
140    fn arm_shsub8(a: i32, b: i32) -> i32;
141
142    #[link_name = "llvm.arm.ssub8"]
143    fn arm_ssub8(a: i32, b: i32) -> i32;
144
145    #[link_name = "llvm.arm.usub8"]
146    fn arm_usub8(a: i32, b: i32) -> i32;
147
148    #[link_name = "llvm.arm.shsub16"]
149    fn arm_shsub16(a: i32, b: i32) -> i32;
150
151    #[link_name = "llvm.arm.smuad"]
152    fn arm_smuad(a: i32, b: i32) -> i32;
153
154    #[link_name = "llvm.arm.smuadx"]
155    fn arm_smuadx(a: i32, b: i32) -> i32;
156
157    #[link_name = "llvm.arm.smusd"]
158    fn arm_smusd(a: i32, b: i32) -> i32;
159
160    #[link_name = "llvm.arm.smusdx"]
161    fn arm_smusdx(a: i32, b: i32) -> i32;
162
163    #[link_name = "llvm.arm.usad8"]
164    fn arm_usad8(a: i32, b: i32) -> u32;
165}
166
167/// Saturating four 8-bit integer additions
168///
169/// Returns the 8-bit signed equivalent of
170///
171/// res\[0\] = a\[0\] + b\[0\]
172/// res\[1\] = a\[1\] + b\[1\]
173/// res\[2\] = a\[2\] + b\[2\]
174/// res\[3\] = a\[3\] + b\[3\]
175#[inline]
176#[cfg_attr(test, assert_instr(qadd8))]
177#[unstable(feature = "stdarch_arm_dsp", issue = "117237")]
178pub unsafe fn __qadd8(a: int8x4_t, b: int8x4_t) -> int8x4_t {
179    dsp_call!(arm_qadd8, a, b)
180}
181
182/// Saturating two 8-bit integer subtraction
183///
184/// Returns the 8-bit signed equivalent of
185///
186/// res\[0\] = a\[0\] - b\[0\]
187/// res\[1\] = a\[1\] - b\[1\]
188/// res\[2\] = a\[2\] - b\[2\]
189/// res\[3\] = a\[3\] - b\[3\]
190#[inline]
191#[cfg_attr(test, assert_instr(qsub8))]
192#[unstable(feature = "stdarch_arm_dsp", issue = "117237")]
193pub unsafe fn __qsub8(a: int8x4_t, b: int8x4_t) -> int8x4_t {
194    dsp_call!(arm_qsub8, a, b)
195}
196
197/// Saturating two 16-bit integer subtraction
198///
199/// Returns the 16-bit signed equivalent of
200///
201/// res\[0\] = a\[0\] - b\[0\]
202/// res\[1\] = a\[1\] - b\[1\]
203#[inline]
204#[cfg_attr(test, assert_instr(qsub16))]
205#[unstable(feature = "stdarch_arm_dsp", issue = "117237")]
206pub unsafe fn __qsub16(a: int16x2_t, b: int16x2_t) -> int16x2_t {
207    dsp_call!(arm_qsub16, a, b)
208}
209
210/// Saturating two 16-bit integer additions
211///
212/// Returns the 16-bit signed equivalent of
213///
214/// res\[0\] = a\[0\] + b\[0\]
215/// res\[1\] = a\[1\] + b\[1\]
216#[inline]
217#[cfg_attr(test, assert_instr(qadd16))]
218#[unstable(feature = "stdarch_arm_dsp", issue = "117237")]
219pub unsafe fn __qadd16(a: int16x2_t, b: int16x2_t) -> int16x2_t {
220    dsp_call!(arm_qadd16, a, b)
221}
222
223/// Returns the 16-bit signed saturated equivalent of
224///
225/// res\[0\] = a\[0\] - b\[1\]
226/// res\[1\] = a\[1\] + b\[0\]
227#[inline]
228#[cfg_attr(test, assert_instr(qasx))]
229#[unstable(feature = "stdarch_arm_dsp", issue = "117237")]
230pub unsafe fn __qasx(a: int16x2_t, b: int16x2_t) -> int16x2_t {
231    dsp_call!(arm_qasx, a, b)
232}
233
234/// Returns the 16-bit signed saturated equivalent of
235///
236/// res\[0\] = a\[0\] + b\[1\]
237/// res\[1\] = a\[1\] - b\[0\]
238#[inline]
239#[cfg_attr(test, assert_instr(qsax))]
240#[unstable(feature = "stdarch_arm_dsp", issue = "117237")]
241pub unsafe fn __qsax(a: int16x2_t, b: int16x2_t) -> int16x2_t {
242    dsp_call!(arm_qsax, a, b)
243}
244
245/// Returns the 16-bit signed saturated equivalent of
246///
247/// res\[0\] = a\[0\] + b\[1\]
248/// res\[1\] = a\[1\] + b\[0\]
249///
250/// and the GE bits of the APSR are set.
251#[inline]
252#[cfg_attr(test, assert_instr(sadd16))]
253#[unstable(feature = "stdarch_arm_dsp", issue = "117237")]
254pub unsafe fn __sadd16(a: int16x2_t, b: int16x2_t) -> int16x2_t {
255    dsp_call!(arm_sadd16, a, b)
256}
257
258/// Returns the 8-bit signed saturated equivalent of
259///
260/// res\[0\] = a\[0\] + b\[1\]
261/// res\[1\] = a\[1\] + b\[0\]
262/// res\[2\] = a\[2\] + b\[2\]
263/// res\[3\] = a\[3\] + b\[3\]
264///
265/// and the GE bits of the APSR are set.
266#[inline]
267#[cfg_attr(test, assert_instr(sadd8))]
268#[unstable(feature = "stdarch_arm_dsp", issue = "117237")]
269pub unsafe fn __sadd8(a: int8x4_t, b: int8x4_t) -> int8x4_t {
270    dsp_call!(arm_sadd8, a, b)
271}
272
273/// Dual 16-bit Signed Multiply with Addition of products
274/// and 32-bit accumulation.
275///
276/// Returns the 16-bit signed equivalent of
277/// res = a\[0\] * b\[0\] + a\[1\] * b\[1\] + c
278#[inline]
279#[cfg_attr(test, assert_instr(smlad))]
280#[unstable(feature = "stdarch_arm_dsp", issue = "117237")]
281pub unsafe fn __smlad(a: int16x2_t, b: int16x2_t, c: i32) -> i32 {
282    arm_smlad(transmute(a), transmute(b), c)
283}
284
285/// Dual 16-bit Signed Multiply with Subtraction  of products
286/// and 32-bit accumulation and overflow detection.
287///
288/// Returns the 16-bit signed equivalent of
289/// res = a\[0\] * b\[0\] - a\[1\] * b\[1\] + c
290#[inline]
291#[cfg_attr(test, assert_instr(smlsd))]
292#[unstable(feature = "stdarch_arm_dsp", issue = "117237")]
293pub unsafe fn __smlsd(a: int16x2_t, b: int16x2_t, c: i32) -> i32 {
294    arm_smlsd(transmute(a), transmute(b), c)
295}
296
297/// Returns the 16-bit signed equivalent of
298///
299/// res\[0\] = a\[0\] - b\[1\]
300/// res\[1\] = a\[1\] + b\[0\]
301///
302/// and the GE bits of the APSR are set.
303#[inline]
304#[cfg_attr(test, assert_instr(sasx))]
305#[unstable(feature = "stdarch_arm_dsp", issue = "117237")]
306pub unsafe fn __sasx(a: int16x2_t, b: int16x2_t) -> int16x2_t {
307    dsp_call!(arm_sasx, a, b)
308}
309
310/// Select bytes from each operand according to APSR GE flags
311///
312/// Returns the equivalent of
313///
314/// res\[0\] = GE\[0\] ? a\[0\] : b\[0\]
315/// res\[1\] = GE\[1\] ? a\[1\] : b\[1\]
316/// res\[2\] = GE\[2\] ? a\[2\] : b\[2\]
317/// res\[3\] = GE\[3\] ? a\[3\] : b\[3\]
318///
319/// where GE are bits of APSR
320#[inline]
321#[cfg_attr(test, assert_instr(sel))]
322#[unstable(feature = "stdarch_arm_dsp", issue = "117237")]
323pub unsafe fn __sel(a: int8x4_t, b: int8x4_t) -> int8x4_t {
324    dsp_call!(arm_sel, a, b)
325}
326
327/// Signed halving parallel byte-wise addition.
328///
329/// Returns the 8-bit signed equivalent of
330///
331/// res\[0\] = (a\[0\] + b\[0\]) / 2
332/// res\[1\] = (a\[1\] + b\[1\]) / 2
333/// res\[2\] = (a\[2\] + b\[2\]) / 2
334/// res\[3\] = (a\[3\] + b\[3\]) / 2
335#[inline]
336#[cfg_attr(test, assert_instr(shadd8))]
337#[unstable(feature = "stdarch_arm_dsp", issue = "117237")]
338pub unsafe fn __shadd8(a: int8x4_t, b: int8x4_t) -> int8x4_t {
339    dsp_call!(arm_shadd8, a, b)
340}
341
342/// Signed halving parallel halfword-wise addition.
343///
344/// Returns the 16-bit signed equivalent of
345///
346/// res\[0\] = (a\[0\] + b\[0\]) / 2
347/// res\[1\] = (a\[1\] + b\[1\]) / 2
348#[inline]
349#[cfg_attr(test, assert_instr(shadd16))]
350#[unstable(feature = "stdarch_arm_dsp", issue = "117237")]
351pub unsafe fn __shadd16(a: int16x2_t, b: int16x2_t) -> int16x2_t {
352    dsp_call!(arm_shadd16, a, b)
353}
354
355/// Signed halving parallel byte-wise subtraction.
356///
357/// Returns the 8-bit signed equivalent of
358///
359/// res\[0\] = (a\[0\] - b\[0\]) / 2
360/// res\[1\] = (a\[1\] - b\[1\]) / 2
361/// res\[2\] = (a\[2\] - b\[2\]) / 2
362/// res\[3\] = (a\[3\] - b\[3\]) / 2
363#[inline]
364#[cfg_attr(test, assert_instr(shsub8))]
365#[unstable(feature = "stdarch_arm_dsp", issue = "117237")]
366pub unsafe fn __shsub8(a: int8x4_t, b: int8x4_t) -> int8x4_t {
367    dsp_call!(arm_shsub8, a, b)
368}
369
370/// Inserts a `USUB8` instruction.
371///
372/// Returns the 8-bit unsigned equivalent of
373///
374/// res\[0\] = a\[0\] - a\[0\]
375/// res\[1\] = a\[1\] - a\[1\]
376/// res\[2\] = a\[2\] - a\[2\]
377/// res\[3\] = a\[3\] - a\[3\]
378///
379/// where \[0\] is the lower 8 bits and \[3\] is the upper 8 bits.
380/// The GE bits of the APSR are set.
381#[inline]
382#[cfg_attr(test, assert_instr(usub8))]
383#[unstable(feature = "stdarch_arm_dsp", issue = "117237")]
384pub unsafe fn __usub8(a: uint8x4_t, b: uint8x4_t) -> uint8x4_t {
385    dsp_call!(arm_usub8, a, b)
386}
387
388/// Inserts a `SSUB8` instruction.
389///
390/// Returns the 8-bit signed equivalent of
391///
392/// res\[0\] = a\[0\] - a\[0\]
393/// res\[1\] = a\[1\] - a\[1\]
394/// res\[2\] = a\[2\] - a\[2\]
395/// res\[3\] = a\[3\] - a\[3\]
396///
397/// where \[0\] is the lower 8 bits and \[3\] is the upper 8 bits.
398/// The GE bits of the APSR are set.
399#[inline]
400#[cfg_attr(test, assert_instr(ssub8))]
401#[unstable(feature = "stdarch_arm_dsp", issue = "117237")]
402pub unsafe fn __ssub8(a: int8x4_t, b: int8x4_t) -> int8x4_t {
403    dsp_call!(arm_ssub8, a, b)
404}
405
406/// Signed halving parallel halfword-wise subtraction.
407///
408/// Returns the 16-bit signed equivalent of
409///
410/// res\[0\] = (a\[0\] - b\[0\]) / 2
411/// res\[1\] = (a\[1\] - b\[1\]) / 2
412#[inline]
413#[cfg_attr(test, assert_instr(shsub16))]
414#[unstable(feature = "stdarch_arm_dsp", issue = "117237")]
415pub unsafe fn __shsub16(a: int16x2_t, b: int16x2_t) -> int16x2_t {
416    dsp_call!(arm_shsub16, a, b)
417}
418
419/// Signed Dual Multiply Add.
420///
421/// Returns the equivalent of
422///
423/// res = a\[0\] * b\[0\] + a\[1\] * b\[1\]
424///
425/// and sets the Q flag if overflow occurs on the addition.
426#[inline]
427#[cfg_attr(test, assert_instr(smuad))]
428#[unstable(feature = "stdarch_arm_dsp", issue = "117237")]
429pub unsafe fn __smuad(a: int16x2_t, b: int16x2_t) -> i32 {
430    arm_smuad(transmute(a), transmute(b))
431}
432
433/// Signed Dual Multiply Add Reversed.
434///
435/// Returns the equivalent of
436///
437/// res = a\[0\] * b\[1\] + a\[1\] * b\[0\]
438///
439/// and sets the Q flag if overflow occurs on the addition.
440#[inline]
441#[cfg_attr(test, assert_instr(smuadx))]
442#[unstable(feature = "stdarch_arm_dsp", issue = "117237")]
443pub unsafe fn __smuadx(a: int16x2_t, b: int16x2_t) -> i32 {
444    arm_smuadx(transmute(a), transmute(b))
445}
446
447/// Signed Dual Multiply Subtract.
448///
449/// Returns the equivalent of
450///
451/// res = a\[0\] * b\[0\] - a\[1\] * b\[1\]
452///
453/// and sets the Q flag if overflow occurs on the addition.
454#[inline]
455#[cfg_attr(test, assert_instr(smusd))]
456#[unstable(feature = "stdarch_arm_dsp", issue = "117237")]
457pub unsafe fn __smusd(a: int16x2_t, b: int16x2_t) -> i32 {
458    arm_smusd(transmute(a), transmute(b))
459}
460
461/// Signed Dual Multiply Subtract Reversed.
462///
463/// Returns the equivalent of
464///
465/// res = a\[0\] * b\[1\] - a\[1\] * b\[0\]
466///
467/// and sets the Q flag if overflow occurs on the addition.
468#[inline]
469#[cfg_attr(test, assert_instr(smusdx))]
470#[unstable(feature = "stdarch_arm_dsp", issue = "117237")]
471pub unsafe fn __smusdx(a: int16x2_t, b: int16x2_t) -> i32 {
472    arm_smusdx(transmute(a), transmute(b))
473}
474
475/// Sum of 8-bit absolute differences.
476///
477/// Returns the 8-bit unsigned equivalent of
478///
479/// res = abs(a\[0\] - b\[0\]) + abs(a\[1\] - b\[1\]) +\
480///          (a\[2\] - b\[2\]) + (a\[3\] - b\[3\])
481#[inline]
482#[cfg_attr(test, assert_instr(usad8))]
483#[unstable(feature = "stdarch_arm_dsp", issue = "117237")]
484pub unsafe fn __usad8(a: int8x4_t, b: int8x4_t) -> u32 {
485    arm_usad8(transmute(a), transmute(b))
486}
487
488/// Sum of 8-bit absolute differences and constant.
489///
490/// Returns the 8-bit unsigned equivalent of
491///
492/// res = abs(a\[0\] - b\[0\]) + abs(a\[1\] - b\[1\]) +\
493///          (a\[2\] - b\[2\]) + (a\[3\] - b\[3\]) + c
494#[inline]
495#[cfg_attr(test, assert_instr(usad8))]
496#[unstable(feature = "stdarch_arm_dsp", issue = "117237")]
497pub unsafe fn __usada8(a: int8x4_t, b: int8x4_t, c: u32) -> u32 {
498    __usad8(a, b) + c
499}
500
501#[cfg(test)]
502mod tests {
503    use crate::core_arch::simd::{i16x2, i8x4, u8x4};
504    use std::mem::transmute;
505    use stdarch_test::simd_test;
506
507    #[test]
508    fn qadd8() {
509        unsafe {
510            let a = i8x4::new(1, 2, 3, i8::MAX);
511            let b = i8x4::new(2, -1, 0, 1);
512            let c = i8x4::new(3, 1, 3, i8::MAX);
513            let r: i8x4 = dsp_call!(super::__qadd8, a, b);
514            assert_eq!(r, c);
515        }
516    }
517
518    #[test]
519    fn qsub8() {
520        unsafe {
521            let a = i8x4::new(1, 2, 3, i8::MIN);
522            let b = i8x4::new(2, -1, 0, 1);
523            let c = i8x4::new(-1, 3, 3, i8::MIN);
524            let r: i8x4 = dsp_call!(super::__qsub8, a, b);
525            assert_eq!(r, c);
526        }
527    }
528
529    #[test]
530    fn qadd16() {
531        unsafe {
532            let a = i16x2::new(1, 2);
533            let b = i16x2::new(2, -1);
534            let c = i16x2::new(3, 1);
535            let r: i16x2 = dsp_call!(super::__qadd16, a, b);
536            assert_eq!(r, c);
537        }
538    }
539
540    #[test]
541    fn qsub16() {
542        unsafe {
543            let a = i16x2::new(10, 20);
544            let b = i16x2::new(20, -10);
545            let c = i16x2::new(-10, 30);
546            let r: i16x2 = dsp_call!(super::__qsub16, a, b);
547            assert_eq!(r, c);
548        }
549    }
550
551    #[test]
552    fn qasx() {
553        unsafe {
554            let a = i16x2::new(1, i16::MAX);
555            let b = i16x2::new(2, 2);
556            let c = i16x2::new(-1, i16::MAX);
557            let r: i16x2 = dsp_call!(super::__qasx, a, b);
558            assert_eq!(r, c);
559        }
560    }
561
562    #[test]
563    fn qsax() {
564        unsafe {
565            let a = i16x2::new(1, i16::MAX);
566            let b = i16x2::new(2, 2);
567            let c = i16x2::new(3, i16::MAX - 2);
568            let r: i16x2 = dsp_call!(super::__qsax, a, b);
569            assert_eq!(r, c);
570        }
571    }
572
573    #[test]
574    fn sadd16() {
575        unsafe {
576            let a = i16x2::new(1, i16::MAX);
577            let b = i16x2::new(2, 2);
578            let c = i16x2::new(3, -i16::MAX);
579            let r: i16x2 = dsp_call!(super::__sadd16, a, b);
580            assert_eq!(r, c);
581        }
582    }
583
584    #[test]
585    fn sadd8() {
586        unsafe {
587            let a = i8x4::new(1, 2, 3, i8::MAX);
588            let b = i8x4::new(4, 3, 2, 2);
589            let c = i8x4::new(5, 5, 5, -i8::MAX);
590            let r: i8x4 = dsp_call!(super::__sadd8, a, b);
591            assert_eq!(r, c);
592        }
593    }
594
595    #[test]
596    fn sasx() {
597        unsafe {
598            let a = i16x2::new(1, 2);
599            let b = i16x2::new(2, 1);
600            let c = i16x2::new(0, 4);
601            let r: i16x2 = dsp_call!(super::__sasx, a, b);
602            assert_eq!(r, c);
603        }
604    }
605
606    #[test]
607    fn smlad() {
608        unsafe {
609            let a = i16x2::new(1, 2);
610            let b = i16x2::new(3, 4);
611            let r = super::__smlad(transmute(a), transmute(b), 10);
612            assert_eq!(r, (1 * 3) + (2 * 4) + 10);
613        }
614    }
615
616    #[test]
617    fn smlsd() {
618        unsafe {
619            let a = i16x2::new(1, 2);
620            let b = i16x2::new(3, 4);
621            let r = super::__smlsd(transmute(a), transmute(b), 10);
622            assert_eq!(r, ((1 * 3) - (2 * 4)) + 10);
623        }
624    }
625
626    #[test]
627    fn sel() {
628        unsafe {
629            let a = i8x4::new(1, 2, 3, i8::MAX);
630            let b = i8x4::new(4, 3, 2, 2);
631            // call sadd8() to set GE bits
632            super::__sadd8(transmute(a), transmute(b));
633            let c = i8x4::new(1, 2, 3, i8::MAX);
634            let r: i8x4 = dsp_call!(super::__sel, a, b);
635            assert_eq!(r, c);
636        }
637    }
638
639    #[test]
640    fn shadd8() {
641        unsafe {
642            let a = i8x4::new(1, 2, 3, 4);
643            let b = i8x4::new(5, 4, 3, 2);
644            let c = i8x4::new(3, 3, 3, 3);
645            let r: i8x4 = dsp_call!(super::__shadd8, a, b);
646            assert_eq!(r, c);
647        }
648    }
649
650    #[test]
651    fn shadd16() {
652        unsafe {
653            let a = i16x2::new(1, 2);
654            let b = i16x2::new(5, 4);
655            let c = i16x2::new(3, 3);
656            let r: i16x2 = dsp_call!(super::__shadd16, a, b);
657            assert_eq!(r, c);
658        }
659    }
660
661    #[test]
662    fn shsub8() {
663        unsafe {
664            let a = i8x4::new(1, 2, 3, 4);
665            let b = i8x4::new(5, 4, 3, 2);
666            let c = i8x4::new(-2, -1, 0, 1);
667            let r: i8x4 = dsp_call!(super::__shsub8, a, b);
668            assert_eq!(r, c);
669        }
670    }
671
672    #[test]
673    fn ssub8() {
674        unsafe {
675            let a = i8x4::new(1, 2, 3, 4);
676            let b = i8x4::new(5, 4, 3, 2);
677            let c = i8x4::new(-4, -2, 0, 2);
678            let r: i8x4 = dsp_call!(super::__ssub8, a, b);
679            assert_eq!(r, c);
680        }
681    }
682
683    #[test]
684    fn usub8() {
685        unsafe {
686            let a = u8x4::new(1, 2, 3, 4);
687            let b = u8x4::new(5, 4, 3, 2);
688            let c = u8x4::new(252, 254, 0, 2);
689            let r: u8x4 = dsp_call!(super::__usub8, a, b);
690            assert_eq!(r, c);
691        }
692    }
693
694    #[test]
695    fn shsub16() {
696        unsafe {
697            let a = i16x2::new(1, 2);
698            let b = i16x2::new(5, 4);
699            let c = i16x2::new(-2, -1);
700            let r: i16x2 = dsp_call!(super::__shsub16, a, b);
701            assert_eq!(r, c);
702        }
703    }
704
705    #[test]
706    fn smuad() {
707        unsafe {
708            let a = i16x2::new(1, 2);
709            let b = i16x2::new(5, 4);
710            let r = super::__smuad(transmute(a), transmute(b));
711            assert_eq!(r, 13);
712        }
713    }
714
715    #[test]
716    fn smuadx() {
717        unsafe {
718            let a = i16x2::new(1, 2);
719            let b = i16x2::new(5, 4);
720            let r = super::__smuadx(transmute(a), transmute(b));
721            assert_eq!(r, 14);
722        }
723    }
724
725    #[test]
726    fn smusd() {
727        unsafe {
728            let a = i16x2::new(1, 2);
729            let b = i16x2::new(5, 4);
730            let r = super::__smusd(transmute(a), transmute(b));
731            assert_eq!(r, -3);
732        }
733    }
734
735    #[test]
736    fn smusdx() {
737        unsafe {
738            let a = i16x2::new(1, 2);
739            let b = i16x2::new(5, 4);
740            let r = super::__smusdx(transmute(a), transmute(b));
741            assert_eq!(r, -6);
742        }
743    }
744
745    #[test]
746    fn usad8() {
747        unsafe {
748            let a = i8x4::new(1, 2, 3, 4);
749            let b = i8x4::new(4, 3, 2, 1);
750            let r = super::__usad8(transmute(a), transmute(b));
751            assert_eq!(r, 8);
752        }
753    }
754
755    #[test]
756    fn usad8a() {
757        unsafe {
758            let a = i8x4::new(1, 2, 3, 4);
759            let b = i8x4::new(4, 3, 2, 1);
760            let c = 10;
761            let r = super::__usada8(transmute(a), transmute(b), c);
762            assert_eq!(r, 8 + c);
763        }
764    }
765}