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

#
core/stdarch/crates/core_arch/src/x86_64/
bt.rs

    1use crate::arch::asm;
    2#[cfg(test)]
    3use stdarch_test::assert_instr;
    4
    5// x32 wants to use a 32-bit address size, but asm! defaults to using the full
    6// register name (e.g. rax). We have to explicitly override the placeholder to
    7// use the 32-bit register name in that case.
    8#[cfg(target_pointer_width = "32")]
    9macro_rules! bt {
    10    ($inst:expr) => {
    11        concat!($inst, " {b}, ({p:e})")
    12    };
    13}
    14#[cfg(target_pointer_width = "64")]
    15macro_rules! bt {
    16    ($inst:expr) => {
    17        concat!($inst, " {b}, ({p})")
    18    };
    19}
    20
    21/// Returns the bit in position `b` of the memory addressed by `p`.
    22///
    23/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_bittest64)
    24#[inline]
    25#[cfg_attr(test, assert_instr(bt))]
    26#[stable(feature = "simd_x86_bittest", since = "1.55.0")]
    27pub unsafe fn _bittest64(p: *const i64, b: i64) -> u8 {
    28    let r: u8;
    29    asm!(
    30        bt!("btq"),
    31        "setc {r}",
    32        p = in(reg) p,
    33        b = in(reg) b,
    34        r = out(reg_byte) r,
    35        options(readonly, nostack, pure, att_syntax)
    36    );
    37    r
    38}
    39
    40/// Returns the bit in position `b` of the memory addressed by `p`, then sets the bit to `1`.
    41///
    42/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_bittestandset64)
    43#[inline]
    44#[cfg_attr(test, assert_instr(bts))]
    45#[stable(feature = "simd_x86_bittest", since = "1.55.0")]
    46pub unsafe fn _bittestandset64(p: *mut i64, b: i64) -> u8 {
    47    let r: u8;
    48    asm!(
    49        bt!("btsq"),
    50        "setc {r}",
    51        p = in(reg) p,
    52        b = in(reg) b,
    53        r = out(reg_byte) r,
    54        options(nostack, att_syntax)
    55    );
    56    r
    57}
    58
    59/// Returns the bit in position `b` of the memory addressed by `p`, then resets that bit to `0`.
    60///
    61/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_bittestandreset64)
    62#[inline]
    63#[cfg_attr(test, assert_instr(btr))]
    64#[stable(feature = "simd_x86_bittest", since = "1.55.0")]
    65pub unsafe fn _bittestandreset64(p: *mut i64, b: i64) -> u8 {
    66    let r: u8;
    67    asm!(
    68        bt!("btrq"),
    69        "setc {r}",
    70        p = in(reg) p,
    71        b = in(reg) b,
    72        r = out(reg_byte) r,
    73        options(nostack, att_syntax)
    74    );
    75    r
    76}
    77
    78/// Returns the bit in position `b` of the memory addressed by `p`, then inverts that bit.
    79///
    80/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_bittestandcomplement64)
    81#[inline]
    82#[cfg_attr(test, assert_instr(btc))]
    83#[stable(feature = "simd_x86_bittest", since = "1.55.0")]
    84pub unsafe fn _bittestandcomplement64(p: *mut i64, b: i64) -> u8 {
    85    let r: u8;
    86    asm!(
    87        bt!("btcq"),
    88        "setc {r}",
    89        p = in(reg) p,
    90        b = in(reg) b,
    91        r = out(reg_byte) r,
    92        options(nostack, att_syntax)
    93    );
    94    r
    95}
    96
    97#[cfg(test)]
    98mod tests {
    99    use crate::core_arch::x86_64::*;
    100
    101    #[test]
    102    #[cfg_attr(miri, ignore)] // Uses inline assembly
    103    fn test_bittest64() {
    104        unsafe {
    105            let a = 0b0101_0000i64;
    106            assert_eq!(_bittest64(&a as _, 4), 1);
    107            assert_eq!(_bittest64(&a as _, 5), 0);
    108        }
    109    }
    110
    111    #[test]
    112    #[cfg_attr(miri, ignore)] // Uses inline assembly
    113    fn test_bittestandset64() {
    114        unsafe {
    115            let mut a = 0b0101_0000i64;
    116            assert_eq!(_bittestandset64(&mut a as _, 4), 1);
    117            assert_eq!(_bittestandset64(&mut a as _, 4), 1);
    118            assert_eq!(_bittestandset64(&mut a as _, 5), 0);
    119            assert_eq!(_bittestandset64(&mut a as _, 5), 1);
    120        }
    121    }
    122
    123    #[test]
    124    #[cfg_attr(miri, ignore)] // Uses inline assembly
    125    fn test_bittestandreset64() {
    126        unsafe {
    127            let mut a = 0b0101_0000i64;
    128            assert_eq!(_bittestandreset64(&mut a as _, 4), 1);
    129            assert_eq!(_bittestandreset64(&mut a as _, 4), 0);
    130            assert_eq!(_bittestandreset64(&mut a as _, 5), 0);
    131            assert_eq!(_bittestandreset64(&mut a as _, 5), 0);
    132        }
    133    }
    134
    135    #[test]
    136    #[cfg_attr(miri, ignore)] // Uses inline assembly
    137    fn test_bittestandcomplement64() {
    138        unsafe {
    139            let mut a = 0b0101_0000i64;
    140            assert_eq!(_bittestandcomplement64(&mut a as _, 4), 1);
    141            assert_eq!(_bittestandcomplement64(&mut a as _, 4), 0);
    142            assert_eq!(_bittestandcomplement64(&mut a as _, 4), 1);
    143            assert_eq!(_bittestandcomplement64(&mut a as _, 5), 0);
    144            assert_eq!(_bittestandcomplement64(&mut a as _, 5), 1);
    145        }
    146    }
    147}