Skip to main content

asmkit/x86/features/
LZCNT.rs

1use super::super::opcodes::*;
2use crate::core::emitter::*;
3use crate::core::operand::*;
4use crate::x86::assembler::*;
5use crate::x86::operands::*;
6
7/// A dummy operand that represents no register. Here just for simplicity.
8const NOREG: Operand = Operand::new();
9
10/// `LZCNT`.
11///
12/// Supported operand variants:
13///
14/// ```text
15/// +---+----------+
16/// | # | Operands |
17/// +---+----------+
18/// | 1 | Gpd, Gpd |
19/// | 2 | Gpd, Mem |
20/// | 3 | Gpq, Gpq |
21/// | 4 | Gpq, Mem |
22/// | 5 | Gpw, Gpw |
23/// | 6 | Gpw, Mem |
24/// +---+----------+
25/// ```
26pub trait LzcntEmitter<A, B> {
27    fn lzcnt(&mut self, op0: A, op1: B);
28}
29
30impl<'a> LzcntEmitter<Gpw, Gpw> for Assembler<'a> {
31    fn lzcnt(&mut self, op0: Gpw, op1: Gpw) {
32        self.emit(
33            LZCNT16RR,
34            op0.as_operand(),
35            op1.as_operand(),
36            &NOREG,
37            &NOREG,
38        );
39    }
40}
41
42impl<'a> LzcntEmitter<Gpw, Mem> for Assembler<'a> {
43    fn lzcnt(&mut self, op0: Gpw, op1: Mem) {
44        self.emit(
45            LZCNT16RM,
46            op0.as_operand(),
47            op1.as_operand(),
48            &NOREG,
49            &NOREG,
50        );
51    }
52}
53
54impl<'a> LzcntEmitter<Gpd, Gpd> for Assembler<'a> {
55    fn lzcnt(&mut self, op0: Gpd, op1: Gpd) {
56        self.emit(
57            LZCNT32RR,
58            op0.as_operand(),
59            op1.as_operand(),
60            &NOREG,
61            &NOREG,
62        );
63    }
64}
65
66impl<'a> LzcntEmitter<Gpd, Mem> for Assembler<'a> {
67    fn lzcnt(&mut self, op0: Gpd, op1: Mem) {
68        self.emit(
69            LZCNT32RM,
70            op0.as_operand(),
71            op1.as_operand(),
72            &NOREG,
73            &NOREG,
74        );
75    }
76}
77
78impl<'a> LzcntEmitter<Gpq, Gpq> for Assembler<'a> {
79    fn lzcnt(&mut self, op0: Gpq, op1: Gpq) {
80        self.emit(
81            LZCNT64RR,
82            op0.as_operand(),
83            op1.as_operand(),
84            &NOREG,
85            &NOREG,
86        );
87    }
88}
89
90impl<'a> LzcntEmitter<Gpq, Mem> for Assembler<'a> {
91    fn lzcnt(&mut self, op0: Gpq, op1: Mem) {
92        self.emit(
93            LZCNT64RM,
94            op0.as_operand(),
95            op1.as_operand(),
96            &NOREG,
97            &NOREG,
98        );
99    }
100}
101
102impl<'a> Assembler<'a> {
103    /// `LZCNT`.
104    ///
105    /// Supported operand variants:
106    ///
107    /// ```text
108    /// +---+----------+
109    /// | # | Operands |
110    /// +---+----------+
111    /// | 1 | Gpd, Gpd |
112    /// | 2 | Gpd, Mem |
113    /// | 3 | Gpq, Gpq |
114    /// | 4 | Gpq, Mem |
115    /// | 5 | Gpw, Gpw |
116    /// | 6 | Gpw, Mem |
117    /// +---+----------+
118    /// ```
119    #[inline]
120    pub fn lzcnt<A, B>(&mut self, op0: A, op1: B)
121    where
122        Assembler<'a>: LzcntEmitter<A, B>,
123    {
124        <Self as LzcntEmitter<A, B>>::lzcnt(self, op0, op1);
125    }
126}