simd32.rs - source
Description: Source of the Rust file `library/core/src/../../stdarch/crates/core_arch/src/arm/simd32.rs`.

#
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
    96unsafe extern "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::{i8x4, i16x2, 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}