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