1//! Bit Manipulation Instruction (BMI) Set 1.0.
2//!
3//! The reference is [Intel 64 and IA-32 Architectures Software Developer's
4//! Manual Volume 2: Instruction Set Reference, A-Z][intel64_ref].
5//!
6//! [Wikipedia][wikipedia_bmi] provides a quick overview of the instructions
7//! available.
8//!
9//! [intel64_ref]: http://www.intel.de/content/dam/www/public/us/en/documents/manuals/64-ia-32-architectures-software-developer-instruction-set-reference-manual-325383.pdf
10//! [wikipedia_bmi]: https://en.wikipedia.org/wiki/Bit_Manipulation_Instruction_Sets#ABM_.28Advanced_Bit_Manipulation.29
11
12#[cfg(test)]
13use stdarch_test::assert_instr;
14
15/// Extracts bits in range [`start`, `start` + `length`) from `a` into
16/// the least significant bits of the result.
17///
18/// [Intel's documentation](https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_bextr_u32)
19#[inline]
20#[target_feature(enable = "bmi1")]
21#[cfg_attr(test, assert_instr(bextr))]
22#[stable(feature = "simd_x86", since = "1.27.0")]
23pub unsafe fn _bextr_u32(a: u32, start: u32, len: u32) -> u32 {
24 _bextr2_u32(a, (start & 0xff_u32) | ((len & 0xff_u32) << 8_u32))
25}
26
27/// Extracts bits of `a` specified by `control` into
28/// the least significant bits of the result.
29///
30/// Bits `[7,0]` of `control` specify the index to the first bit in the range
31/// to be extracted, and bits `[15,8]` specify the length of the range.
32///
33/// [Intel's documentation](https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_bextr2_u32)
34#[inline]
35#[target_feature(enable = "bmi1")]
36#[cfg_attr(test, assert_instr(bextr))]
37#[stable(feature = "simd_x86", since = "1.27.0")]
38pub unsafe fn _bextr2_u32(a: u32, control: u32) -> u32 {
39 x86_bmi_bextr_32(x:a, y:control)
40}
41
42/// Bitwise logical `AND` of inverted `a` with `b`.
43///
44/// [Intel's documentation](https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_andn_u32)
45#[inline]
46#[target_feature(enable = "bmi1")]
47#[cfg_attr(test, assert_instr(andn))]
48#[stable(feature = "simd_x86", since = "1.27.0")]
49pub unsafe fn _andn_u32(a: u32, b: u32) -> u32 {
50 !a & b
51}
52
53/// Extracts lowest set isolated bit.
54///
55/// [Intel's documentation](https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_blsi_u32)
56#[inline]
57#[target_feature(enable = "bmi1")]
58#[cfg_attr(test, assert_instr(blsi))]
59#[stable(feature = "simd_x86", since = "1.27.0")]
60pub unsafe fn _blsi_u32(x: u32) -> u32 {
61 x & x.wrapping_neg()
62}
63
64/// Gets mask up to lowest set bit.
65///
66/// [Intel's documentation](https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_blsmsk_u32)
67#[inline]
68#[target_feature(enable = "bmi1")]
69#[cfg_attr(test, assert_instr(blsmsk))]
70#[stable(feature = "simd_x86", since = "1.27.0")]
71pub unsafe fn _blsmsk_u32(x: u32) -> u32 {
72 x ^ (x.wrapping_sub(1_u32))
73}
74
75/// Resets the lowest set bit of `x`.
76///
77/// If `x` is sets CF.
78///
79/// [Intel's documentation](https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_blsr_u32)
80#[inline]
81#[target_feature(enable = "bmi1")]
82#[cfg_attr(test, assert_instr(blsr))]
83#[stable(feature = "simd_x86", since = "1.27.0")]
84pub unsafe fn _blsr_u32(x: u32) -> u32 {
85 x & (x.wrapping_sub(1))
86}
87
88/// Counts the number of trailing least significant zero bits.
89///
90/// When the source operand is `0`, it returns its size in bits.
91///
92/// [Intel's documentation](https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_tzcnt_u32)
93#[inline]
94#[target_feature(enable = "bmi1")]
95#[cfg_attr(test, assert_instr(tzcnt))]
96#[stable(feature = "simd_x86", since = "1.27.0")]
97pub unsafe fn _tzcnt_u32(x: u32) -> u32 {
98 x.trailing_zeros()
99}
100
101/// Counts the number of trailing least significant zero bits.
102///
103/// When the source operand is `0`, it returns its size in bits.
104///
105/// [Intel's documentation](https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm_tzcnt_32)
106#[inline]
107#[target_feature(enable = "bmi1")]
108#[cfg_attr(test, assert_instr(tzcnt))]
109#[stable(feature = "simd_x86", since = "1.27.0")]
110pub unsafe fn _mm_tzcnt_32(x: u32) -> i32 {
111 x.trailing_zeros() as i32
112}
113
114extern "C" {
115 #[link_name = "llvm.x86.bmi.bextr.32"]
116 fn x86_bmi_bextr_32(x: u32, y: u32) -> u32;
117}
118
119#[cfg(test)]
120mod tests {
121 use stdarch_test::simd_test;
122
123 use crate::core_arch::x86::*;
124
125 #[simd_test(enable = "bmi1")]
126 unsafe fn test_bextr_u32() {
127 let r = _bextr_u32(0b0101_0000u32, 4, 4);
128 assert_eq!(r, 0b0000_0101u32);
129 }
130
131 #[simd_test(enable = "bmi1")]
132 unsafe fn test_andn_u32() {
133 assert_eq!(_andn_u32(0, 0), 0);
134 assert_eq!(_andn_u32(0, 1), 1);
135 assert_eq!(_andn_u32(1, 0), 0);
136 assert_eq!(_andn_u32(1, 1), 0);
137
138 let r = _andn_u32(0b0000_0000u32, 0b0000_0000u32);
139 assert_eq!(r, 0b0000_0000u32);
140
141 let r = _andn_u32(0b0000_0000u32, 0b1111_1111u32);
142 assert_eq!(r, 0b1111_1111u32);
143
144 let r = _andn_u32(0b1111_1111u32, 0b0000_0000u32);
145 assert_eq!(r, 0b0000_0000u32);
146
147 let r = _andn_u32(0b1111_1111u32, 0b1111_1111u32);
148 assert_eq!(r, 0b0000_0000u32);
149
150 let r = _andn_u32(0b0100_0000u32, 0b0101_1101u32);
151 assert_eq!(r, 0b0001_1101u32);
152 }
153
154 #[simd_test(enable = "bmi1")]
155 unsafe fn test_blsi_u32() {
156 assert_eq!(_blsi_u32(0b1101_0000u32), 0b0001_0000u32);
157 }
158
159 #[simd_test(enable = "bmi1")]
160 unsafe fn test_blsmsk_u32() {
161 let r = _blsmsk_u32(0b0011_0000u32);
162 assert_eq!(r, 0b0001_1111u32);
163 }
164
165 #[simd_test(enable = "bmi1")]
166 unsafe fn test_blsr_u32() {
167 // TODO: test the behavior when the input is `0`.
168 let r = _blsr_u32(0b0011_0000u32);
169 assert_eq!(r, 0b0010_0000u32);
170 }
171
172 #[simd_test(enable = "bmi1")]
173 unsafe fn test_tzcnt_u32() {
174 assert_eq!(_tzcnt_u32(0b0000_0001u32), 0u32);
175 assert_eq!(_tzcnt_u32(0b0000_0000u32), 32u32);
176 assert_eq!(_tzcnt_u32(0b1001_0000u32), 4u32);
177 }
178}
179