]> git.proxmox.com Git - rustc.git/blob - library/stdarch/crates/core_arch/src/x86/bt.rs
New upstream version 1.55.0+dfsg1
[rustc.git] / library / stdarch / crates / core_arch / src / x86 / bt.rs
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:e}, ({p:e})")
11 };
12 }
13 #[cfg(target_pointer_width = "64")]
14 macro_rules! bt {
15 ($inst:expr) => {
16 concat!($inst, " {b:e}, ({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")]
24 pub unsafe fn _bittest(p: *const i32, b: i32) -> u8 {
25 let r: u8;
26 asm!(
27 bt!("btl"),
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")]
41 pub unsafe fn _bittestandset(p: *mut i32, b: i32) -> u8 {
42 let r: u8;
43 asm!(
44 bt!("btsl"),
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")]
58 pub unsafe fn _bittestandreset(p: *mut i32, b: i32) -> u8 {
59 let r: u8;
60 asm!(
61 bt!("btrl"),
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")]
75 pub unsafe fn _bittestandcomplement(p: *mut i32, b: i32) -> u8 {
76 let r: u8;
77 asm!(
78 bt!("btcl"),
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::*;
91
92 #[test]
93 fn test_bittest() {
94 unsafe {
95 let a = 0b0101_0000i32;
96 assert_eq!(_bittest(&a as _, 4), 1);
97 assert_eq!(_bittest(&a as _, 5), 0);
98 }
99 }
100
101 #[test]
102 fn test_bittestandset() {
103 unsafe {
104 let mut a = 0b0101_0000i32;
105 assert_eq!(_bittestandset(&mut a as _, 4), 1);
106 assert_eq!(_bittestandset(&mut a as _, 4), 1);
107 assert_eq!(_bittestandset(&mut a as _, 5), 0);
108 assert_eq!(_bittestandset(&mut a as _, 5), 1);
109 }
110 }
111
112 #[test]
113 fn test_bittestandreset() {
114 unsafe {
115 let mut a = 0b0101_0000i32;
116 assert_eq!(_bittestandreset(&mut a as _, 4), 1);
117 assert_eq!(_bittestandreset(&mut a as _, 4), 0);
118 assert_eq!(_bittestandreset(&mut a as _, 5), 0);
119 assert_eq!(_bittestandreset(&mut a as _, 5), 0);
120 }
121 }
122
123 #[test]
124 fn test_bittestandcomplement() {
125 unsafe {
126 let mut a = 0b0101_0000i32;
127 assert_eq!(_bittestandcomplement(&mut a as _, 4), 1);
128 assert_eq!(_bittestandcomplement(&mut a as _, 4), 0);
129 assert_eq!(_bittestandcomplement(&mut a as _, 4), 1);
130 assert_eq!(_bittestandcomplement(&mut a as _, 5), 0);
131 assert_eq!(_bittestandcomplement(&mut a as _, 5), 1);
132 }
133 }
134 }