1 | use crate::arch::asm; |
2 | #[cfg (test)] |
3 | use 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" )] |
9 | macro_rules! bt { |
10 | ($inst:expr) => { |
11 | concat!($inst, " {b:e}, ({p:e})" ) |
12 | }; |
13 | } |
14 | #[cfg (target_pointer_width = "64" )] |
15 | macro_rules! bt { |
16 | ($inst:expr) => { |
17 | concat!($inst, " {b:e}, ({p})" ) |
18 | }; |
19 | } |
20 | |
21 | /// Returns the bit in position `b` of the memory addressed by `p`. |
22 | #[inline ] |
23 | #[cfg_attr (test, assert_instr(bt))] |
24 | #[stable (feature = "simd_x86_bittest" , since = "1.55.0" )] |
25 | pub unsafe fn _bittest(p: *const i32, b: i32) -> u8 { |
26 | let r: u8; |
27 | asm!( |
28 | bt!("btl" ), |
29 | "setc {r}" , |
30 | p = in(reg) p, |
31 | b = in(reg) b, |
32 | r = out(reg_byte) r, |
33 | options(readonly, nostack, pure, att_syntax) |
34 | ); |
35 | r |
36 | } |
37 | |
38 | /// Returns the bit in position `b` of the memory addressed by `p`, then sets the bit to `1`. |
39 | #[inline ] |
40 | #[cfg_attr (test, assert_instr(bts))] |
41 | #[stable (feature = "simd_x86_bittest" , since = "1.55.0" )] |
42 | pub unsafe fn _bittestandset(p: *mut i32, b: i32) -> u8 { |
43 | let r: u8; |
44 | asm!( |
45 | bt!("btsl" ), |
46 | "setc {r}" , |
47 | p = in(reg) p, |
48 | b = in(reg) b, |
49 | r = out(reg_byte) r, |
50 | options(nostack, att_syntax) |
51 | ); |
52 | r |
53 | } |
54 | |
55 | /// Returns the bit in position `b` of the memory addressed by `p`, then resets that bit to `0`. |
56 | #[inline ] |
57 | #[cfg_attr (test, assert_instr(btr))] |
58 | #[stable (feature = "simd_x86_bittest" , since = "1.55.0" )] |
59 | pub unsafe fn _bittestandreset(p: *mut i32, b: i32) -> u8 { |
60 | let r: u8; |
61 | asm!( |
62 | bt!("btrl" ), |
63 | "setc {r}" , |
64 | p = in(reg) p, |
65 | b = in(reg) b, |
66 | r = out(reg_byte) r, |
67 | options(nostack, att_syntax) |
68 | ); |
69 | r |
70 | } |
71 | |
72 | /// Returns the bit in position `b` of the memory addressed by `p`, then inverts that bit. |
73 | #[inline ] |
74 | #[cfg_attr (test, assert_instr(btc))] |
75 | #[stable (feature = "simd_x86_bittest" , since = "1.55.0" )] |
76 | pub unsafe fn _bittestandcomplement(p: *mut i32, b: i32) -> u8 { |
77 | let r: u8; |
78 | asm!( |
79 | bt!("btcl" ), |
80 | "setc {r}" , |
81 | p = in(reg) p, |
82 | b = in(reg) b, |
83 | r = out(reg_byte) r, |
84 | options(nostack, att_syntax) |
85 | ); |
86 | r |
87 | } |
88 | |
89 | #[cfg (test)] |
90 | mod tests { |
91 | use crate::core_arch::x86::*; |
92 | |
93 | #[test ] |
94 | #[cfg_attr (miri, ignore)] // Uses inline assembly |
95 | fn test_bittest() { |
96 | unsafe { |
97 | let a = 0b0101_0000i32; |
98 | assert_eq!(_bittest(&a as _, 4), 1); |
99 | assert_eq!(_bittest(&a as _, 5), 0); |
100 | } |
101 | } |
102 | |
103 | #[test ] |
104 | #[cfg_attr (miri, ignore)] // Uses inline assembly |
105 | fn test_bittestandset() { |
106 | unsafe { |
107 | let mut a = 0b0101_0000i32; |
108 | assert_eq!(_bittestandset(&mut a as _, 4), 1); |
109 | assert_eq!(_bittestandset(&mut a as _, 4), 1); |
110 | assert_eq!(_bittestandset(&mut a as _, 5), 0); |
111 | assert_eq!(_bittestandset(&mut a as _, 5), 1); |
112 | } |
113 | } |
114 | |
115 | #[test ] |
116 | #[cfg_attr (miri, ignore)] // Uses inline assembly |
117 | fn test_bittestandreset() { |
118 | unsafe { |
119 | let mut a = 0b0101_0000i32; |
120 | assert_eq!(_bittestandreset(&mut a as _, 4), 1); |
121 | assert_eq!(_bittestandreset(&mut a as _, 4), 0); |
122 | assert_eq!(_bittestandreset(&mut a as _, 5), 0); |
123 | assert_eq!(_bittestandreset(&mut a as _, 5), 0); |
124 | } |
125 | } |
126 | |
127 | #[test ] |
128 | #[cfg_attr (miri, ignore)] // Uses inline assembly |
129 | fn test_bittestandcomplement() { |
130 | unsafe { |
131 | let mut a = 0b0101_0000i32; |
132 | assert_eq!(_bittestandcomplement(&mut a as _, 4), 1); |
133 | assert_eq!(_bittestandcomplement(&mut a as _, 4), 0); |
134 | assert_eq!(_bittestandcomplement(&mut a as _, 4), 1); |
135 | assert_eq!(_bittestandcomplement(&mut a as _, 5), 0); |
136 | assert_eq!(_bittestandcomplement(&mut a as _, 5), 1); |
137 | } |
138 | } |
139 | } |
140 | |