Skip to main content

asmkit/x86/features/
LZCNT.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/// `LZCNT` (LZCNT). 
11/// Counts the number of leading most significant zero bits in a source operand (second operand) returning the result into a destination (first operand).
12///
13///
14/// For more details, see the [Intel manual](https://www.felixcloutier.com/x86/LZCNT.html).
15///
16/// Supported operand variants:
17///
18/// ```text
19/// +---+----------+
20/// | # | Operands |
21/// +---+----------+
22/// | 1 | Gpd, Gpd |
23/// | 2 | Gpd, Mem |
24/// | 3 | Gpq, Gpq |
25/// | 4 | Gpq, Mem |
26/// | 5 | Gpw, Gpw |
27/// | 6 | Gpw, Mem |
28/// +---+----------+
29/// ```
30pub trait LzcntEmitter<A, B> {
31    fn lzcnt(&mut self, op0: A, op1: B);
32}
33
34impl<'a> LzcntEmitter<Gpw, Gpw> for Assembler<'a> {
35    fn lzcnt(&mut self, op0: Gpw, op1: Gpw) {
36        self.emit(LZCNT16RR, op0.as_operand(), op1.as_operand(), &NOREG, &NOREG);
37    }
38}
39
40impl<'a> LzcntEmitter<Gpw, Mem> for Assembler<'a> {
41    fn lzcnt(&mut self, op0: Gpw, op1: Mem) {
42        self.emit(LZCNT16RM, op0.as_operand(), op1.as_operand(), &NOREG, &NOREG);
43    }
44}
45
46impl<'a> LzcntEmitter<Gpd, Gpd> for Assembler<'a> {
47    fn lzcnt(&mut self, op0: Gpd, op1: Gpd) {
48        self.emit(LZCNT32RR, op0.as_operand(), op1.as_operand(), &NOREG, &NOREG);
49    }
50}
51
52impl<'a> LzcntEmitter<Gpd, Mem> for Assembler<'a> {
53    fn lzcnt(&mut self, op0: Gpd, op1: Mem) {
54        self.emit(LZCNT32RM, op0.as_operand(), op1.as_operand(), &NOREG, &NOREG);
55    }
56}
57
58impl<'a> LzcntEmitter<Gpq, Gpq> for Assembler<'a> {
59    fn lzcnt(&mut self, op0: Gpq, op1: Gpq) {
60        self.emit(LZCNT64RR, op0.as_operand(), op1.as_operand(), &NOREG, &NOREG);
61    }
62}
63
64impl<'a> LzcntEmitter<Gpq, Mem> for Assembler<'a> {
65    fn lzcnt(&mut self, op0: Gpq, op1: Mem) {
66        self.emit(LZCNT64RM, op0.as_operand(), op1.as_operand(), &NOREG, &NOREG);
67    }
68}
69
70
71impl<'a> Assembler<'a> {
72    /// `LZCNT` (LZCNT). 
73    /// Counts the number of leading most significant zero bits in a source operand (second operand) returning the result into a destination (first operand).
74    ///
75    ///
76    /// For more details, see the [Intel manual](https://www.felixcloutier.com/x86/LZCNT.html).
77    ///
78    /// Supported operand variants:
79    ///
80    /// ```text
81    /// +---+----------+
82    /// | # | Operands |
83    /// +---+----------+
84    /// | 1 | Gpd, Gpd |
85    /// | 2 | Gpd, Mem |
86    /// | 3 | Gpq, Gpq |
87    /// | 4 | Gpq, Mem |
88    /// | 5 | Gpw, Gpw |
89    /// | 6 | Gpw, Mem |
90    /// +---+----------+
91    /// ```
92    #[inline]
93    pub fn lzcnt<A, B>(&mut self, op0: A, op1: B)
94    where Assembler<'a>: LzcntEmitter<A, B> {
95        <Self as LzcntEmitter<A, B>>::lzcnt(self, op0, op1);
96    }
97}