      1
      2
      3
      4
      5
      6
      7
      8
      9
     10
     11
     12
     13
     14
     15
     16
     17
     18
     19
     20
     21
     22
     23
     24
     25
     26
     27
     28
     29
     30
     31
     32
     33
     34
     35
     36
     37
     38
     39
     40
     41
     42
     43
     44
     45
     46
     47
     48
     49
     50
     51
     52
     53
     54
     55
     56
     57
     58
     59
     60
     61
     62
     63
     64
     65
     66
     67
     68
     69
     70
     71
     72
     73
     74
     75
     76
     77
     78
     79
     80
     81
     82
     83
     84
     85
     86
     87
     88
     89
     90
     91
     92
     93
     94
     95
     96
     97
     98
     99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156
    157
    158
    159
    160
    161
    162
    163
    164
    165
    166
    167
    168
    169
    170
    171
    172
    173
    174
    175
    176
    177
    178
    179
    180
    181
    182
    183
    184
    185
    186
    187
    188
    189
    190
    191
    192
    193
    194
    195
    196
    197
    198
    199
    200
    201
    202
    203
    204
    205
    206
    207
    208
    209

    //! `x86_64`'s Streaming SIMD Extensions 2 (SSE2)

    use crate::{
        core_arch::{simd_llvm::*, x86::*},
        intrinsics,
    };

    #[cfg(test)]
    use stdarch_test::assert_instr;

    #[allow(improper_ctypes)]
    extern "C" {
        #[link_name = "llvm.x86.sse2.cvtsd2si64"]
        fn cvtsd2si64(a: __m128d) -> i64;
        #[link_name = "llvm.x86.sse2.cvttsd2si64"]
        fn cvttsd2si64(a: __m128d) -> i64;
    }

    /// Converts the lower double-precision (64-bit) floating-point element in a to
    /// a 64-bit integer.
    ///
    /// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_cvtsd_si64)
    #[inline]
    #[target_feature(enable = "sse2")]
    #[cfg_attr(test, assert_instr(cvtsd2si))]
    #[stable(feature = "simd_x86", since = "1.27.0")]
    pub unsafe fn _mm_cvtsd_si64(a: __m128d) -> i64 {
        cvtsd2si64(a)
    }

    /// Alias for `_mm_cvtsd_si64`
    ///
    /// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_cvtsd_si64x)
    #[inline]
    #[target_feature(enable = "sse2")]
    #[cfg_attr(test, assert_instr(cvtsd2si))]
    #[stable(feature = "simd_x86", since = "1.27.0")]
    pub unsafe fn _mm_cvtsd_si64x(a: __m128d) -> i64 {
        _mm_cvtsd_si64(a)
    }

    /// Converts the lower double-precision (64-bit) floating-point element in `a`
    /// to a 64-bit integer with truncation.
    ///
    /// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_cvttsd_si64)
    #[inline]
    #[target_feature(enable = "sse2")]
    #[cfg_attr(test, assert_instr(cvttsd2si))]
    #[stable(feature = "simd_x86", since = "1.27.0")]
    pub unsafe fn _mm_cvttsd_si64(a: __m128d) -> i64 {
        cvttsd2si64(a)
    }

    /// Alias for `_mm_cvttsd_si64`
    ///
    /// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_cvttsd_si64x)
    #[inline]
    #[target_feature(enable = "sse2")]
    #[cfg_attr(test, assert_instr(cvttsd2si))]
    #[stable(feature = "simd_x86", since = "1.27.0")]
    pub unsafe fn _mm_cvttsd_si64x(a: __m128d) -> i64 {
        _mm_cvttsd_si64(a)
    }

    /// Stores a 64-bit integer value in the specified memory location.
    /// To minimize caching, the data is flagged as non-temporal (unlikely to be
    /// used again soon).
    ///
    /// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_stream_si64)
    #[inline]
    #[target_feature(enable = "sse2")]
    #[cfg_attr(test, assert_instr(movnti))]
    #[stable(feature = "simd_x86", since = "1.27.0")]
    pub unsafe fn _mm_stream_si64(mem_addr: *mut i64, a: i64) {
        intrinsics::nontemporal_store(mem_addr, a);
    }

    /// Returns a vector whose lowest element is `a` and all higher elements are
    /// `0`.
    ///
    /// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_cvtsi64_si128)
    #[inline]
    #[target_feature(enable = "sse2")]
    #[cfg_attr(all(test, not(windows)), assert_instr(movq))]
    #[stable(feature = "simd_x86", since = "1.27.0")]
    pub unsafe fn _mm_cvtsi64_si128(a: i64) -> __m128i {
        _mm_set_epi64x(0, a)
    }

    /// Returns a vector whose lowest element is `a` and all higher elements are
    /// `0`.
    ///
    /// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_cvtsi64x_si128)
    #[inline]
    #[target_feature(enable = "sse2")]
    #[cfg_attr(all(test, not(windows)), assert_instr(movq))]
    #[stable(feature = "simd_x86", since = "1.27.0")]
    pub unsafe fn _mm_cvtsi64x_si128(a: i64) -> __m128i {
        _mm_cvtsi64_si128(a)
    }

    /// Returns the lowest element of `a`.
    ///
    /// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_cvtsi128_si64)
    #[inline]
    #[target_feature(enable = "sse2")]
    #[cfg_attr(all(test, not(windows)), assert_instr(movq))]
    #[stable(feature = "simd_x86", since = "1.27.0")]
    pub unsafe fn _mm_cvtsi128_si64(a: __m128i) -> i64 {
        simd_extract(a.as_i64x2(), 0)
    }

    /// Returns the lowest element of `a`.
    ///
    /// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_cvtsi128_si64x)
    #[inline]
    #[target_feature(enable = "sse2")]
    #[cfg_attr(all(test, not(windows)), assert_instr(movq))]
    #[stable(feature = "simd_x86", since = "1.27.0")]
    pub unsafe fn _mm_cvtsi128_si64x(a: __m128i) -> i64 {
        _mm_cvtsi128_si64(a)
    }

    /// Returns `a` with its lower element replaced by `b` after converting it to
    /// an `f64`.
    ///
    /// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_cvtsi64_sd)
    #[inline]
    #[target_feature(enable = "sse2")]
    #[cfg_attr(test, assert_instr(cvtsi2sd))]
    #[stable(feature = "simd_x86", since = "1.27.0")]
    pub unsafe fn _mm_cvtsi64_sd(a: __m128d, b: i64) -> __m128d {
        simd_insert(a, 0, b as f64)
    }

    /// Returns `a` with its lower element replaced by `b` after converting it to
    /// an `f64`.
    ///
    /// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_cvtsi64x_sd)
    #[inline]
    #[target_feature(enable = "sse2")]
    #[cfg_attr(test, assert_instr(cvtsi2sd))]
    #[stable(feature = "simd_x86", since = "1.27.0")]
    pub unsafe fn _mm_cvtsi64x_sd(a: __m128d, b: i64) -> __m128d {
        _mm_cvtsi64_sd(a, b)
    }

    #[cfg(test)]
    mod tests {
        use crate::core_arch::arch::x86_64::*;
        use std::{boxed, f64, i64};
        use stdarch_test::simd_test;

        #[simd_test(enable = "sse2")]
        unsafe fn test_mm_cvtsd_si64() {
            let r = _mm_cvtsd_si64(_mm_setr_pd(-2.0, 5.0));
            assert_eq!(r, -2_i64);

            let r = _mm_cvtsd_si64(_mm_setr_pd(f64::MAX, f64::MIN));
            assert_eq!(r, i64::MIN);
        }

        #[simd_test(enable = "sse2")]
        unsafe fn test_mm_cvtsd_si64x() {
            let r = _mm_cvtsd_si64x(_mm_setr_pd(f64::NAN, f64::NAN));
            assert_eq!(r, i64::MIN);
        }

        #[simd_test(enable = "sse2")]
        unsafe fn test_mm_cvttsd_si64() {
            let a = _mm_setr_pd(-1.1, 2.2);
            let r = _mm_cvttsd_si64(a);
            assert_eq!(r, -1_i64);
        }

        #[simd_test(enable = "sse2")]
        unsafe fn test_mm_cvttsd_si64x() {
            let a = _mm_setr_pd(f64::NEG_INFINITY, f64::NAN);
            let r = _mm_cvttsd_si64x(a);
            assert_eq!(r, i64::MIN);
        }

        #[simd_test(enable = "sse2")]
        unsafe fn test_mm_stream_si64() {
            let a: i64 = 7;
            let mut mem = boxed::Box::<i64>::new(-1);
            _mm_stream_si64(&mut *mem as *mut i64, a);
            assert_eq!(a, *mem);
        }

        #[simd_test(enable = "sse2")]
        unsafe fn test_mm_cvtsi64_si128() {
            let r = _mm_cvtsi64_si128(5);
            assert_eq_m128i(r, _mm_setr_epi64x(5, 0));
        }

        #[simd_test(enable = "sse2")]
        unsafe fn test_mm_cvtsi128_si64() {
            let r = _mm_cvtsi128_si64(_mm_setr_epi64x(5, 0));
            assert_eq!(r, 5);
        }

        #[simd_test(enable = "sse2")]
        unsafe fn test_mm_cvtsi64_sd() {
            let a = _mm_set1_pd(3.5);
            let r = _mm_cvtsi64_sd(a, 5);
            assert_eq_m128d(r, _mm_setr_pd(5.0, 3.5));
        }
    }