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

#
core/stdarch/crates/core_arch/src/x86/
bmi1.rs

    1//! Bit Manipulation Instruction (BMI) Set 1.0.
    2//!
    3//! The reference is [Intel 64 and IA-32 Architectures Software Developer's
    4//! Manual Volume 2: Instruction Set Reference, A-Z][intel64_ref].
    5//!
    6//! [Wikipedia][wikipedia_bmi] provides a quick overview of the instructions
    7//! available.
    8//!
    9//! [intel64_ref]: https://www.intel.com/content/dam/www/public/us/en/documents/manuals/64-ia-32-architectures-software-developer-instruction-set-reference-manual-325383.pdf
    10//! [wikipedia_bmi]: https://en.wikipedia.org/wiki/Bit_Manipulation_Instruction_Sets#ABM_.28Advanced_Bit_Manipulation.29
    11
    12#[cfg(test)]
    13use stdarch_test::assert_instr;
    14
    15/// Extracts bits in range [`start`, `start` + `length`) from `a` into
    16/// the least significant bits of the result.
    17///
    18/// [Intel's documentation](https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_bextr_u32)
    19#[inline]
    20#[target_feature(enable = "bmi1")]
    21#[cfg_attr(test, assert_instr(bextr))]
    22#[stable(feature = "simd_x86", since = "1.27.0")]
    23pub fn _bextr_u32(a: u32, start: u32, len: u32) -> u32 {
    24    _bextr2_u32(a, (start & 0xff_u32) | ((len & 0xff_u32) << 8_u32))
    25}
    26
    27/// Extracts bits of `a` specified by `control` into
    28/// the least significant bits of the result.
    29///
    30/// Bits `[7,0]` of `control` specify the index to the first bit in the range
    31/// to be extracted, and bits `[15,8]` specify the length of the range.
    32///
    33/// [Intel's documentation](https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_bextr2_u32)
    34#[inline]
    35#[target_feature(enable = "bmi1")]
    36#[cfg_attr(test, assert_instr(bextr))]
    37#[stable(feature = "simd_x86", since = "1.27.0")]
    38pub fn _bextr2_u32(a: u32, control: u32) -> u32 {
    39    unsafe { x86_bmi_bextr_32(a, control) }
    40}
    41
    42/// Bitwise logical `AND` of inverted `a` with `b`.
    43///
    44/// [Intel's documentation](https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_andn_u32)
    45#[inline]
    46#[target_feature(enable = "bmi1")]
    47#[cfg_attr(test, assert_instr(andn))]
    48#[stable(feature = "simd_x86", since = "1.27.0")]
    49#[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")]
    50pub const fn _andn_u32(a: u32, b: u32) -> u32 {
    51    !a & b
    52}
    53
    54/// Extracts lowest set isolated bit.
    55///
    56/// [Intel's documentation](https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_blsi_u32)
    57#[inline]
    58#[target_feature(enable = "bmi1")]
    59#[cfg_attr(test, assert_instr(blsi))]
    60#[stable(feature = "simd_x86", since = "1.27.0")]
    61#[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")]
    62pub const fn _blsi_u32(x: u32) -> u32 {
    63    x & x.wrapping_neg()
    64}
    65
    66/// Gets mask up to lowest set bit.
    67///
    68/// [Intel's documentation](https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_blsmsk_u32)
    69#[inline]
    70#[target_feature(enable = "bmi1")]
    71#[cfg_attr(test, assert_instr(blsmsk))]
    72#[stable(feature = "simd_x86", since = "1.27.0")]
    73#[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")]
    74pub const fn _blsmsk_u32(x: u32) -> u32 {
    75    x ^ (x.wrapping_sub(1_u32))
    76}
    77
    78/// Resets the lowest set bit of `x`.
    79///
    80/// If `x` is sets CF.
    81///
    82/// [Intel's documentation](https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_blsr_u32)
    83#[inline]
    84#[target_feature(enable = "bmi1")]
    85#[cfg_attr(test, assert_instr(blsr))]
    86#[stable(feature = "simd_x86", since = "1.27.0")]
    87#[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")]
    88pub const fn _blsr_u32(x: u32) -> u32 {
    89    x & (x.wrapping_sub(1))
    90}
    91
    92/// Counts the number of trailing least significant zero bits.
    93///
    94/// When the source operand is `0`, it returns its size in bits.
    95///
    96/// [Intel's documentation](https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_tzcnt_u16)
    97#[inline]
    98#[target_feature(enable = "bmi1")]
    99#[cfg_attr(test, assert_instr(tzcnt))]
    100#[stable(feature = "simd_x86_updates", since = "1.82.0")]
    101#[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")]
    102pub const fn _tzcnt_u16(x: u16) -> u16 {
    103    x.trailing_zeros() as u16
    104}
    105
    106/// Counts the number of trailing least significant zero bits.
    107///
    108/// When the source operand is `0`, it returns its size in bits.
    109///
    110/// [Intel's documentation](https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_tzcnt_u32)
    111#[inline]
    112#[target_feature(enable = "bmi1")]
    113#[cfg_attr(test, assert_instr(tzcnt))]
    114#[stable(feature = "simd_x86", since = "1.27.0")]
    115#[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")]
    116pub const fn _tzcnt_u32(x: u32) -> u32 {
    117    x.trailing_zeros()
    118}
    119
    120/// Counts the number of trailing least significant zero bits.
    121///
    122/// When the source operand is `0`, it returns its size in bits.
    123///
    124/// [Intel's documentation](https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm_tzcnt_32)
    125#[inline]
    126#[target_feature(enable = "bmi1")]
    127#[cfg_attr(test, assert_instr(tzcnt))]
    128#[stable(feature = "simd_x86", since = "1.27.0")]
    129#[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")]
    130pub const fn _mm_tzcnt_32(x: u32) -> i32 {
    131    x.trailing_zeros() as i32
    132}
    133
    134unsafe extern "C" {
    135    #[link_name = "llvm.x86.bmi.bextr.32"]
    136    fn x86_bmi_bextr_32(x: u32, y: u32) -> u32;
    137}
    138
    139#[cfg(test)]
    140mod tests {
    141    use crate::core_arch::assert_eq_const as assert_eq;
    142    use stdarch_test::simd_test;
    143
    144    use crate::core_arch::x86::*;
    145
    146    #[simd_test(enable = "bmi1")]
    147    fn test_bextr_u32() {
    148        let r = _bextr_u32(0b0101_0000u32, 4, 4);
    149        assert_eq!(r, 0b0000_0101u32);
    150    }
    151
    152    #[simd_test(enable = "bmi1")]
    153    const fn test_andn_u32() {
    154        assert_eq!(_andn_u32(0, 0), 0);
    155        assert_eq!(_andn_u32(0, 1), 1);
    156        assert_eq!(_andn_u32(1, 0), 0);
    157        assert_eq!(_andn_u32(1, 1), 0);
    158
    159        let r = _andn_u32(0b0000_0000u32, 0b0000_0000u32);
    160        assert_eq!(r, 0b0000_0000u32);
    161
    162        let r = _andn_u32(0b0000_0000u32, 0b1111_1111u32);
    163        assert_eq!(r, 0b1111_1111u32);
    164
    165        let r = _andn_u32(0b1111_1111u32, 0b0000_0000u32);
    166        assert_eq!(r, 0b0000_0000u32);
    167
    168        let r = _andn_u32(0b1111_1111u32, 0b1111_1111u32);
    169        assert_eq!(r, 0b0000_0000u32);
    170
    171        let r = _andn_u32(0b0100_0000u32, 0b0101_1101u32);
    172        assert_eq!(r, 0b0001_1101u32);
    173    }
    174
    175    #[simd_test(enable = "bmi1")]
    176    const fn test_blsi_u32() {
    177        assert_eq!(_blsi_u32(0b1101_0000u32), 0b0001_0000u32);
    178    }
    179
    180    #[simd_test(enable = "bmi1")]
    181    const fn test_blsmsk_u32() {
    182        let r = _blsmsk_u32(0b0011_0000u32);
    183        assert_eq!(r, 0b0001_1111u32);
    184    }
    185
    186    #[simd_test(enable = "bmi1")]
    187    const fn test_blsr_u32() {
    188        // TODO: test the behavior when the input is `0`.
    189        let r = _blsr_u32(0b0011_0000u32);
    190        assert_eq!(r, 0b0010_0000u32);
    191    }
    192
    193    #[simd_test(enable = "bmi1")]
    194    const fn test_tzcnt_u16() {
    195        assert_eq!(_tzcnt_u16(0b0000_0001u16), 0u16);
    196        assert_eq!(_tzcnt_u16(0b0000_0000u16), 16u16);
    197        assert_eq!(_tzcnt_u16(0b1001_0000u16), 4u16);
    198    }
    199
    200    #[simd_test(enable = "bmi1")]
    201    const fn test_tzcnt_u32() {
    202        assert_eq!(_tzcnt_u32(0b0000_0001u32), 0u32);
    203        assert_eq!(_tzcnt_u32(0b0000_0000u32), 32u32);
    204        assert_eq!(_tzcnt_u32(0b1001_0000u32), 4u32);
    205    }
    206}