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