asmkit/x86/features/BMI1.rs
1use crate::x86::assembler::*;
2use crate::x86::operands::*;
3use super::super::opcodes::*;
4use crate::core::emitter::*;
5use crate::core::operand::*;
6
7/// A dummy operand that represents no register. Here just for simplicity.
8const NOREG: Operand = Operand::new();
9
10/// `ANDN` (ANDN).
11/// Performs a bitwise logical AND of inverted second operand (the first source operand) with the third operand (the
12///
13///
14/// For more details, see the [Intel manual](https://www.felixcloutier.com/x86/ANDN.html).
15///
16/// Supported operand variants:
17///
18/// ```text
19/// +---+---------------+
20/// | # | Operands |
21/// +---+---------------+
22/// | 1 | Gpd, Gpd, Gpd |
23/// | 2 | Gpd, Gpd, Mem |
24/// | 3 | Gpq, Gpq, Gpq |
25/// | 4 | Gpq, Gpq, Mem |
26/// +---+---------------+
27/// ```
28pub trait AndnEmitter<A, B, C> {
29 fn andn(&mut self, op0: A, op1: B, op2: C);
30}
31
32impl<'a> AndnEmitter<Gpd, Gpd, Gpd> for Assembler<'a> {
33 fn andn(&mut self, op0: Gpd, op1: Gpd, op2: Gpd) {
34 self.emit(ANDN32RRR, op0.as_operand(), op1.as_operand(), op2.as_operand(), &NOREG);
35 }
36}
37
38impl<'a> AndnEmitter<Gpd, Gpd, Mem> for Assembler<'a> {
39 fn andn(&mut self, op0: Gpd, op1: Gpd, op2: Mem) {
40 self.emit(ANDN32RRM, op0.as_operand(), op1.as_operand(), op2.as_operand(), &NOREG);
41 }
42}
43
44impl<'a> AndnEmitter<Gpq, Gpq, Gpq> for Assembler<'a> {
45 fn andn(&mut self, op0: Gpq, op1: Gpq, op2: Gpq) {
46 self.emit(ANDN64RRR, op0.as_operand(), op1.as_operand(), op2.as_operand(), &NOREG);
47 }
48}
49
50impl<'a> AndnEmitter<Gpq, Gpq, Mem> for Assembler<'a> {
51 fn andn(&mut self, op0: Gpq, op1: Gpq, op2: Mem) {
52 self.emit(ANDN64RRM, op0.as_operand(), op1.as_operand(), op2.as_operand(), &NOREG);
53 }
54}
55
56/// `BEXTR` (BEXTR).
57/// Extracts contiguous bits from the first source operand (the second operand) using an index value and length value specified in the second source operand (the third operand). Bit 7:0 of the second source operand specifies the starting bit position of bit extraction. A START value exceeding the operand size will not extract any bits from the second source operand. Bit 15:8 of the second source operand specifies the maximum number of bits (LENGTH) beginning at the START position to extract. Only bit positions up to (OperandSize -1) of the first source operand are extracted. The extracted bits are written to the destination register, starting from the least significant bit. All higher order bits in the destination operand (starting at bit position LENGTH) are zeroed. The destination register is cleared if no bits are extracted.
58///
59///
60/// For more details, see the [Intel manual](https://www.felixcloutier.com/x86/BEXTR.html).
61///
62/// Supported operand variants:
63///
64/// ```text
65/// +---+---------------+
66/// | # | Operands |
67/// +---+---------------+
68/// | 1 | Gpd, Gpd, Gpd |
69/// | 2 | Gpd, Mem, Gpd |
70/// | 3 | Gpq, Gpq, Gpq |
71/// | 4 | Gpq, Mem, Gpq |
72/// +---+---------------+
73/// ```
74pub trait BextrEmitter<A, B, C> {
75 fn bextr(&mut self, op0: A, op1: B, op2: C);
76}
77
78impl<'a> BextrEmitter<Gpd, Gpd, Gpd> for Assembler<'a> {
79 fn bextr(&mut self, op0: Gpd, op1: Gpd, op2: Gpd) {
80 self.emit(BEXTR32RRR, op0.as_operand(), op1.as_operand(), op2.as_operand(), &NOREG);
81 }
82}
83
84impl<'a> BextrEmitter<Gpd, Mem, Gpd> for Assembler<'a> {
85 fn bextr(&mut self, op0: Gpd, op1: Mem, op2: Gpd) {
86 self.emit(BEXTR32RMR, op0.as_operand(), op1.as_operand(), op2.as_operand(), &NOREG);
87 }
88}
89
90impl<'a> BextrEmitter<Gpq, Gpq, Gpq> for Assembler<'a> {
91 fn bextr(&mut self, op0: Gpq, op1: Gpq, op2: Gpq) {
92 self.emit(BEXTR64RRR, op0.as_operand(), op1.as_operand(), op2.as_operand(), &NOREG);
93 }
94}
95
96impl<'a> BextrEmitter<Gpq, Mem, Gpq> for Assembler<'a> {
97 fn bextr(&mut self, op0: Gpq, op1: Mem, op2: Gpq) {
98 self.emit(BEXTR64RMR, op0.as_operand(), op1.as_operand(), op2.as_operand(), &NOREG);
99 }
100}
101
102/// `BLSI` (BLSI).
103/// Extracts the lowest set bit from the source operand and set the corresponding bit in the destination register. All other bits in the destination operand are zeroed. If no bits are set in the source operand, BLSI sets all the bits in the destination to 0 and sets ZF and CF.
104///
105///
106/// For more details, see the [Intel manual](https://www.felixcloutier.com/x86/BLSI.html).
107///
108/// Supported operand variants:
109///
110/// ```text
111/// +---+----------+
112/// | # | Operands |
113/// +---+----------+
114/// | 1 | Gpd, Gpd |
115/// | 2 | Gpd, Mem |
116/// | 3 | Gpq, Gpq |
117/// | 4 | Gpq, Mem |
118/// +---+----------+
119/// ```
120pub trait BlsiEmitter<A, B> {
121 fn blsi(&mut self, op0: A, op1: B);
122}
123
124impl<'a> BlsiEmitter<Gpd, Gpd> for Assembler<'a> {
125 fn blsi(&mut self, op0: Gpd, op1: Gpd) {
126 self.emit(BLSI32RR, op0.as_operand(), op1.as_operand(), &NOREG, &NOREG);
127 }
128}
129
130impl<'a> BlsiEmitter<Gpd, Mem> for Assembler<'a> {
131 fn blsi(&mut self, op0: Gpd, op1: Mem) {
132 self.emit(BLSI32RM, op0.as_operand(), op1.as_operand(), &NOREG, &NOREG);
133 }
134}
135
136impl<'a> BlsiEmitter<Gpq, Gpq> for Assembler<'a> {
137 fn blsi(&mut self, op0: Gpq, op1: Gpq) {
138 self.emit(BLSI64RR, op0.as_operand(), op1.as_operand(), &NOREG, &NOREG);
139 }
140}
141
142impl<'a> BlsiEmitter<Gpq, Mem> for Assembler<'a> {
143 fn blsi(&mut self, op0: Gpq, op1: Mem) {
144 self.emit(BLSI64RM, op0.as_operand(), op1.as_operand(), &NOREG, &NOREG);
145 }
146}
147
148/// `BLSMSK` (BLSMSK).
149/// Sets all the lower bits of the destination operand to “1” up to and including lowest set bit (=1) in the source operand. If source operand is zero, BLSMSK sets all bits of the destination operand to 1 and also sets CF to 1.
150///
151///
152/// For more details, see the [Intel manual](https://www.felixcloutier.com/x86/BLSMSK.html).
153///
154/// Supported operand variants:
155///
156/// ```text
157/// +---+----------+
158/// | # | Operands |
159/// +---+----------+
160/// | 1 | Gpd, Gpd |
161/// | 2 | Gpd, Mem |
162/// | 3 | Gpq, Gpq |
163/// | 4 | Gpq, Mem |
164/// +---+----------+
165/// ```
166pub trait BlsmskEmitter<A, B> {
167 fn blsmsk(&mut self, op0: A, op1: B);
168}
169
170impl<'a> BlsmskEmitter<Gpd, Gpd> for Assembler<'a> {
171 fn blsmsk(&mut self, op0: Gpd, op1: Gpd) {
172 self.emit(BLSMSK32RR, op0.as_operand(), op1.as_operand(), &NOREG, &NOREG);
173 }
174}
175
176impl<'a> BlsmskEmitter<Gpd, Mem> for Assembler<'a> {
177 fn blsmsk(&mut self, op0: Gpd, op1: Mem) {
178 self.emit(BLSMSK32RM, op0.as_operand(), op1.as_operand(), &NOREG, &NOREG);
179 }
180}
181
182impl<'a> BlsmskEmitter<Gpq, Gpq> for Assembler<'a> {
183 fn blsmsk(&mut self, op0: Gpq, op1: Gpq) {
184 self.emit(BLSMSK64RR, op0.as_operand(), op1.as_operand(), &NOREG, &NOREG);
185 }
186}
187
188impl<'a> BlsmskEmitter<Gpq, Mem> for Assembler<'a> {
189 fn blsmsk(&mut self, op0: Gpq, op1: Mem) {
190 self.emit(BLSMSK64RM, op0.as_operand(), op1.as_operand(), &NOREG, &NOREG);
191 }
192}
193
194/// `BLSR` (BLSR).
195/// Copies all bits from the source operand to the destination operand and resets (=0) the bit position in the destination operand that corresponds to the lowest set bit of the source operand. If the source operand is zero BLSR sets CF.
196///
197///
198/// For more details, see the [Intel manual](https://www.felixcloutier.com/x86/BLSR.html).
199///
200/// Supported operand variants:
201///
202/// ```text
203/// +---+----------+
204/// | # | Operands |
205/// +---+----------+
206/// | 1 | Gpd, Gpd |
207/// | 2 | Gpd, Mem |
208/// | 3 | Gpq, Gpq |
209/// | 4 | Gpq, Mem |
210/// +---+----------+
211/// ```
212pub trait BlsrEmitter<A, B> {
213 fn blsr(&mut self, op0: A, op1: B);
214}
215
216impl<'a> BlsrEmitter<Gpd, Gpd> for Assembler<'a> {
217 fn blsr(&mut self, op0: Gpd, op1: Gpd) {
218 self.emit(BLSR32RR, op0.as_operand(), op1.as_operand(), &NOREG, &NOREG);
219 }
220}
221
222impl<'a> BlsrEmitter<Gpd, Mem> for Assembler<'a> {
223 fn blsr(&mut self, op0: Gpd, op1: Mem) {
224 self.emit(BLSR32RM, op0.as_operand(), op1.as_operand(), &NOREG, &NOREG);
225 }
226}
227
228impl<'a> BlsrEmitter<Gpq, Gpq> for Assembler<'a> {
229 fn blsr(&mut self, op0: Gpq, op1: Gpq) {
230 self.emit(BLSR64RR, op0.as_operand(), op1.as_operand(), &NOREG, &NOREG);
231 }
232}
233
234impl<'a> BlsrEmitter<Gpq, Mem> for Assembler<'a> {
235 fn blsr(&mut self, op0: Gpq, op1: Mem) {
236 self.emit(BLSR64RM, op0.as_operand(), op1.as_operand(), &NOREG, &NOREG);
237 }
238}
239
240/// `TZCNT` (TZCNT).
241/// TZCNT counts the number of trailing least significant zero bits in source operand (second operand) and returns the result in destination operand (first operand). TZCNT is an extension of the BSF instruction. The key difference between TZCNT and BSF instruction is that TZCNT provides operand size as output when source operand is zero while in the case of BSF instruction, if source operand is zero, the content of destination operand are undefined. On processors that do not support TZCNT, the instruction byte encoding is executed as BSF.
242///
243///
244/// For more details, see the [Intel manual](https://www.felixcloutier.com/x86/TZCNT.html).
245///
246/// Supported operand variants:
247///
248/// ```text
249/// +---+----------+
250/// | # | Operands |
251/// +---+----------+
252/// | 1 | Gpd, Gpd |
253/// | 2 | Gpd, Mem |
254/// | 3 | Gpq, Gpq |
255/// | 4 | Gpq, Mem |
256/// | 5 | Gpw, Gpw |
257/// | 6 | Gpw, Mem |
258/// +---+----------+
259/// ```
260pub trait TzcntEmitter<A, B> {
261 fn tzcnt(&mut self, op0: A, op1: B);
262}
263
264impl<'a> TzcntEmitter<Gpw, Gpw> for Assembler<'a> {
265 fn tzcnt(&mut self, op0: Gpw, op1: Gpw) {
266 self.emit(TZCNT16RR, op0.as_operand(), op1.as_operand(), &NOREG, &NOREG);
267 }
268}
269
270impl<'a> TzcntEmitter<Gpw, Mem> for Assembler<'a> {
271 fn tzcnt(&mut self, op0: Gpw, op1: Mem) {
272 self.emit(TZCNT16RM, op0.as_operand(), op1.as_operand(), &NOREG, &NOREG);
273 }
274}
275
276impl<'a> TzcntEmitter<Gpd, Gpd> for Assembler<'a> {
277 fn tzcnt(&mut self, op0: Gpd, op1: Gpd) {
278 self.emit(TZCNT32RR, op0.as_operand(), op1.as_operand(), &NOREG, &NOREG);
279 }
280}
281
282impl<'a> TzcntEmitter<Gpd, Mem> for Assembler<'a> {
283 fn tzcnt(&mut self, op0: Gpd, op1: Mem) {
284 self.emit(TZCNT32RM, op0.as_operand(), op1.as_operand(), &NOREG, &NOREG);
285 }
286}
287
288impl<'a> TzcntEmitter<Gpq, Gpq> for Assembler<'a> {
289 fn tzcnt(&mut self, op0: Gpq, op1: Gpq) {
290 self.emit(TZCNT64RR, op0.as_operand(), op1.as_operand(), &NOREG, &NOREG);
291 }
292}
293
294impl<'a> TzcntEmitter<Gpq, Mem> for Assembler<'a> {
295 fn tzcnt(&mut self, op0: Gpq, op1: Mem) {
296 self.emit(TZCNT64RM, op0.as_operand(), op1.as_operand(), &NOREG, &NOREG);
297 }
298}
299
300
301impl<'a> Assembler<'a> {
302 /// `ANDN` (ANDN).
303 /// Performs a bitwise logical AND of inverted second operand (the first source operand) with the third operand (the
304 ///
305 ///
306 /// For more details, see the [Intel manual](https://www.felixcloutier.com/x86/ANDN.html).
307 ///
308 /// Supported operand variants:
309 ///
310 /// ```text
311 /// +---+---------------+
312 /// | # | Operands |
313 /// +---+---------------+
314 /// | 1 | Gpd, Gpd, Gpd |
315 /// | 2 | Gpd, Gpd, Mem |
316 /// | 3 | Gpq, Gpq, Gpq |
317 /// | 4 | Gpq, Gpq, Mem |
318 /// +---+---------------+
319 /// ```
320 #[inline]
321 pub fn andn<A, B, C>(&mut self, op0: A, op1: B, op2: C)
322 where Assembler<'a>: AndnEmitter<A, B, C> {
323 <Self as AndnEmitter<A, B, C>>::andn(self, op0, op1, op2);
324 }
325 /// `BEXTR` (BEXTR).
326 /// Extracts contiguous bits from the first source operand (the second operand) using an index value and length value specified in the second source operand (the third operand). Bit 7:0 of the second source operand specifies the starting bit position of bit extraction. A START value exceeding the operand size will not extract any bits from the second source operand. Bit 15:8 of the second source operand specifies the maximum number of bits (LENGTH) beginning at the START position to extract. Only bit positions up to (OperandSize -1) of the first source operand are extracted. The extracted bits are written to the destination register, starting from the least significant bit. All higher order bits in the destination operand (starting at bit position LENGTH) are zeroed. The destination register is cleared if no bits are extracted.
327 ///
328 ///
329 /// For more details, see the [Intel manual](https://www.felixcloutier.com/x86/BEXTR.html).
330 ///
331 /// Supported operand variants:
332 ///
333 /// ```text
334 /// +---+---------------+
335 /// | # | Operands |
336 /// +---+---------------+
337 /// | 1 | Gpd, Gpd, Gpd |
338 /// | 2 | Gpd, Mem, Gpd |
339 /// | 3 | Gpq, Gpq, Gpq |
340 /// | 4 | Gpq, Mem, Gpq |
341 /// +---+---------------+
342 /// ```
343 #[inline]
344 pub fn bextr<A, B, C>(&mut self, op0: A, op1: B, op2: C)
345 where Assembler<'a>: BextrEmitter<A, B, C> {
346 <Self as BextrEmitter<A, B, C>>::bextr(self, op0, op1, op2);
347 }
348 /// `BLSI` (BLSI).
349 /// Extracts the lowest set bit from the source operand and set the corresponding bit in the destination register. All other bits in the destination operand are zeroed. If no bits are set in the source operand, BLSI sets all the bits in the destination to 0 and sets ZF and CF.
350 ///
351 ///
352 /// For more details, see the [Intel manual](https://www.felixcloutier.com/x86/BLSI.html).
353 ///
354 /// Supported operand variants:
355 ///
356 /// ```text
357 /// +---+----------+
358 /// | # | Operands |
359 /// +---+----------+
360 /// | 1 | Gpd, Gpd |
361 /// | 2 | Gpd, Mem |
362 /// | 3 | Gpq, Gpq |
363 /// | 4 | Gpq, Mem |
364 /// +---+----------+
365 /// ```
366 #[inline]
367 pub fn blsi<A, B>(&mut self, op0: A, op1: B)
368 where Assembler<'a>: BlsiEmitter<A, B> {
369 <Self as BlsiEmitter<A, B>>::blsi(self, op0, op1);
370 }
371 /// `BLSMSK` (BLSMSK).
372 /// Sets all the lower bits of the destination operand to “1” up to and including lowest set bit (=1) in the source operand. If source operand is zero, BLSMSK sets all bits of the destination operand to 1 and also sets CF to 1.
373 ///
374 ///
375 /// For more details, see the [Intel manual](https://www.felixcloutier.com/x86/BLSMSK.html).
376 ///
377 /// Supported operand variants:
378 ///
379 /// ```text
380 /// +---+----------+
381 /// | # | Operands |
382 /// +---+----------+
383 /// | 1 | Gpd, Gpd |
384 /// | 2 | Gpd, Mem |
385 /// | 3 | Gpq, Gpq |
386 /// | 4 | Gpq, Mem |
387 /// +---+----------+
388 /// ```
389 #[inline]
390 pub fn blsmsk<A, B>(&mut self, op0: A, op1: B)
391 where Assembler<'a>: BlsmskEmitter<A, B> {
392 <Self as BlsmskEmitter<A, B>>::blsmsk(self, op0, op1);
393 }
394 /// `BLSR` (BLSR).
395 /// Copies all bits from the source operand to the destination operand and resets (=0) the bit position in the destination operand that corresponds to the lowest set bit of the source operand. If the source operand is zero BLSR sets CF.
396 ///
397 ///
398 /// For more details, see the [Intel manual](https://www.felixcloutier.com/x86/BLSR.html).
399 ///
400 /// Supported operand variants:
401 ///
402 /// ```text
403 /// +---+----------+
404 /// | # | Operands |
405 /// +---+----------+
406 /// | 1 | Gpd, Gpd |
407 /// | 2 | Gpd, Mem |
408 /// | 3 | Gpq, Gpq |
409 /// | 4 | Gpq, Mem |
410 /// +---+----------+
411 /// ```
412 #[inline]
413 pub fn blsr<A, B>(&mut self, op0: A, op1: B)
414 where Assembler<'a>: BlsrEmitter<A, B> {
415 <Self as BlsrEmitter<A, B>>::blsr(self, op0, op1);
416 }
417 /// `TZCNT` (TZCNT).
418 /// TZCNT counts the number of trailing least significant zero bits in source operand (second operand) and returns the result in destination operand (first operand). TZCNT is an extension of the BSF instruction. The key difference between TZCNT and BSF instruction is that TZCNT provides operand size as output when source operand is zero while in the case of BSF instruction, if source operand is zero, the content of destination operand are undefined. On processors that do not support TZCNT, the instruction byte encoding is executed as BSF.
419 ///
420 ///
421 /// For more details, see the [Intel manual](https://www.felixcloutier.com/x86/TZCNT.html).
422 ///
423 /// Supported operand variants:
424 ///
425 /// ```text
426 /// +---+----------+
427 /// | # | Operands |
428 /// +---+----------+
429 /// | 1 | Gpd, Gpd |
430 /// | 2 | Gpd, Mem |
431 /// | 3 | Gpq, Gpq |
432 /// | 4 | Gpq, Mem |
433 /// | 5 | Gpw, Gpw |
434 /// | 6 | Gpw, Mem |
435 /// +---+----------+
436 /// ```
437 #[inline]
438 pub fn tzcnt<A, B>(&mut self, op0: A, op1: B)
439 where Assembler<'a>: TzcntEmitter<A, B> {
440 <Self as TzcntEmitter<A, B>>::tzcnt(self, op0, op1);
441 }
442}