Skip to main content

asmkit/x86/features/
BMI2.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/// `BZHI` (BZHI). 
11/// BZHI copies the bits of the first source operand (the second operand) into the destination operand (the first operand) and clears the higher bits in the destination according to the INDEX value specified by the second source operand (the third operand). The INDEX is specified by bits 7:0 of the second source operand. The INDEX value is saturated at the value of OperandSize -1. CF is set, if the number contained in the 8 low bits of the third operand is greater than OperandSize -1.
12///
13///
14/// For more details, see the [Intel manual](https://www.felixcloutier.com/x86/BZHI.html).
15///
16/// Supported operand variants:
17///
18/// ```text
19/// +---+---------------+
20/// | # | Operands      |
21/// +---+---------------+
22/// | 1 | Gpd, Gpd, Gpd |
23/// | 2 | Gpd, Mem, Gpd |
24/// | 3 | Gpq, Gpq, Gpq |
25/// | 4 | Gpq, Mem, Gpq |
26/// +---+---------------+
27/// ```
28pub trait BzhiEmitter<A, B, C> {
29    fn bzhi(&mut self, op0: A, op1: B, op2: C);
30}
31
32impl<'a> BzhiEmitter<Gpd, Gpd, Gpd> for Assembler<'a> {
33    fn bzhi(&mut self, op0: Gpd, op1: Gpd, op2: Gpd) {
34        self.emit(BZHI32RRR, op0.as_operand(), op1.as_operand(), op2.as_operand(), &NOREG);
35    }
36}
37
38impl<'a> BzhiEmitter<Gpd, Mem, Gpd> for Assembler<'a> {
39    fn bzhi(&mut self, op0: Gpd, op1: Mem, op2: Gpd) {
40        self.emit(BZHI32RMR, op0.as_operand(), op1.as_operand(), op2.as_operand(), &NOREG);
41    }
42}
43
44impl<'a> BzhiEmitter<Gpq, Gpq, Gpq> for Assembler<'a> {
45    fn bzhi(&mut self, op0: Gpq, op1: Gpq, op2: Gpq) {
46        self.emit(BZHI64RRR, op0.as_operand(), op1.as_operand(), op2.as_operand(), &NOREG);
47    }
48}
49
50impl<'a> BzhiEmitter<Gpq, Mem, Gpq> for Assembler<'a> {
51    fn bzhi(&mut self, op0: Gpq, op1: Mem, op2: Gpq) {
52        self.emit(BZHI64RMR, op0.as_operand(), op1.as_operand(), op2.as_operand(), &NOREG);
53    }
54}
55
56/// `MULX` (MULX). 
57/// Performs an unsigned multiplication of the implicit source operand (EDX/RDX) and the specified source operand (the third operand) and stores the low half of the result in the second destination (second operand), the high half of the result in the first destination operand (first operand), without reading or writing the arithmetic flags. This enables efficient programming where the software can interleave add with carry operations and multiplications.
58///
59///
60/// For more details, see the [Intel manual](https://www.felixcloutier.com/x86/MULX.html).
61///
62/// Supported operand variants:
63///
64/// ```text
65/// +---+---------------+
66/// | # | Operands      |
67/// +---+---------------+
68/// | 1 | Gpd, Gpd, Gpd |
69/// | 2 | Gpd, Gpd, Mem |
70/// | 3 | Gpq, Gpq, Gpq |
71/// | 4 | Gpq, Gpq, Mem |
72/// +---+---------------+
73/// ```
74pub trait MulxEmitter<A, B, C> {
75    fn mulx(&mut self, op0: A, op1: B, op2: C);
76}
77
78impl<'a> MulxEmitter<Gpd, Gpd, Gpd> for Assembler<'a> {
79    fn mulx(&mut self, op0: Gpd, op1: Gpd, op2: Gpd) {
80        self.emit(MULX32RRR, op0.as_operand(), op1.as_operand(), op2.as_operand(), &NOREG);
81    }
82}
83
84impl<'a> MulxEmitter<Gpd, Gpd, Mem> for Assembler<'a> {
85    fn mulx(&mut self, op0: Gpd, op1: Gpd, op2: Mem) {
86        self.emit(MULX32RRM, op0.as_operand(), op1.as_operand(), op2.as_operand(), &NOREG);
87    }
88}
89
90impl<'a> MulxEmitter<Gpq, Gpq, Gpq> for Assembler<'a> {
91    fn mulx(&mut self, op0: Gpq, op1: Gpq, op2: Gpq) {
92        self.emit(MULX64RRR, op0.as_operand(), op1.as_operand(), op2.as_operand(), &NOREG);
93    }
94}
95
96impl<'a> MulxEmitter<Gpq, Gpq, Mem> for Assembler<'a> {
97    fn mulx(&mut self, op0: Gpq, op1: Gpq, op2: Mem) {
98        self.emit(MULX64RRM, op0.as_operand(), op1.as_operand(), op2.as_operand(), &NOREG);
99    }
100}
101
102/// `PDEP` (PDEP). 
103/// PDEP uses a mask in the second source operand (the third operand) to transfer/scatter contiguous low order bits in the first source operand (the second operand) into the destination (the first operand). PDEP takes the low bits from the first source operand and deposit them in the destination operand at the corresponding bit locations that are set in the second source operand (mask). All other bits (bits not set in mask) in destination are set to zero.
104///
105///
106/// For more details, see the [Intel manual](https://www.felixcloutier.com/x86/PDEP.html).
107///
108/// Supported operand variants:
109///
110/// ```text
111/// +---+---------------+
112/// | # | Operands      |
113/// +---+---------------+
114/// | 1 | Gpd, Gpd, Gpd |
115/// | 2 | Gpd, Gpd, Mem |
116/// | 3 | Gpq, Gpq, Gpq |
117/// | 4 | Gpq, Gpq, Mem |
118/// +---+---------------+
119/// ```
120pub trait PdepEmitter<A, B, C> {
121    fn pdep(&mut self, op0: A, op1: B, op2: C);
122}
123
124impl<'a> PdepEmitter<Gpd, Gpd, Gpd> for Assembler<'a> {
125    fn pdep(&mut self, op0: Gpd, op1: Gpd, op2: Gpd) {
126        self.emit(PDEP32RRR, op0.as_operand(), op1.as_operand(), op2.as_operand(), &NOREG);
127    }
128}
129
130impl<'a> PdepEmitter<Gpd, Gpd, Mem> for Assembler<'a> {
131    fn pdep(&mut self, op0: Gpd, op1: Gpd, op2: Mem) {
132        self.emit(PDEP32RRM, op0.as_operand(), op1.as_operand(), op2.as_operand(), &NOREG);
133    }
134}
135
136impl<'a> PdepEmitter<Gpq, Gpq, Gpq> for Assembler<'a> {
137    fn pdep(&mut self, op0: Gpq, op1: Gpq, op2: Gpq) {
138        self.emit(PDEP64RRR, op0.as_operand(), op1.as_operand(), op2.as_operand(), &NOREG);
139    }
140}
141
142impl<'a> PdepEmitter<Gpq, Gpq, Mem> for Assembler<'a> {
143    fn pdep(&mut self, op0: Gpq, op1: Gpq, op2: Mem) {
144        self.emit(PDEP64RRM, op0.as_operand(), op1.as_operand(), op2.as_operand(), &NOREG);
145    }
146}
147
148/// `PEXT` (PEXT). 
149/// PEXT uses a mask in the second source operand (the third operand) to transfer either contiguous or non-contiguous bits in the first source operand (the second operand) to contiguous low order bit positions in the destination (the first operand). For each bit set in the MASK, PEXT extracts the corresponding bits from the first source operand and writes them into contiguous lower bits of destination operand. The remaining upper bits of destination are zeroed.
150///
151///
152/// For more details, see the [Intel manual](https://www.felixcloutier.com/x86/PEXT.html).
153///
154/// Supported operand variants:
155///
156/// ```text
157/// +---+---------------+
158/// | # | Operands      |
159/// +---+---------------+
160/// | 1 | Gpd, Gpd, Gpd |
161/// | 2 | Gpd, Gpd, Mem |
162/// | 3 | Gpq, Gpq, Gpq |
163/// | 4 | Gpq, Gpq, Mem |
164/// +---+---------------+
165/// ```
166pub trait PextEmitter<A, B, C> {
167    fn pext(&mut self, op0: A, op1: B, op2: C);
168}
169
170impl<'a> PextEmitter<Gpd, Gpd, Gpd> for Assembler<'a> {
171    fn pext(&mut self, op0: Gpd, op1: Gpd, op2: Gpd) {
172        self.emit(PEXT32RRR, op0.as_operand(), op1.as_operand(), op2.as_operand(), &NOREG);
173    }
174}
175
176impl<'a> PextEmitter<Gpd, Gpd, Mem> for Assembler<'a> {
177    fn pext(&mut self, op0: Gpd, op1: Gpd, op2: Mem) {
178        self.emit(PEXT32RRM, op0.as_operand(), op1.as_operand(), op2.as_operand(), &NOREG);
179    }
180}
181
182impl<'a> PextEmitter<Gpq, Gpq, Gpq> for Assembler<'a> {
183    fn pext(&mut self, op0: Gpq, op1: Gpq, op2: Gpq) {
184        self.emit(PEXT64RRR, op0.as_operand(), op1.as_operand(), op2.as_operand(), &NOREG);
185    }
186}
187
188impl<'a> PextEmitter<Gpq, Gpq, Mem> for Assembler<'a> {
189    fn pext(&mut self, op0: Gpq, op1: Gpq, op2: Mem) {
190        self.emit(PEXT64RRM, op0.as_operand(), op1.as_operand(), op2.as_operand(), &NOREG);
191    }
192}
193
194/// `RORX` (RORX). 
195/// Rotates the bits of second operand right by the count value specified in imm8 without affecting arithmetic flags. The RORX instruction does not read or write the arithmetic flags.
196///
197///
198/// For more details, see the [Intel manual](https://www.felixcloutier.com/x86/RORX.html).
199///
200/// Supported operand variants:
201///
202/// ```text
203/// +---+---------------+
204/// | # | Operands      |
205/// +---+---------------+
206/// | 1 | Gpd, Gpd, Imm |
207/// | 2 | Gpd, Mem, Imm |
208/// | 3 | Gpq, Gpq, Imm |
209/// | 4 | Gpq, Mem, Imm |
210/// +---+---------------+
211/// ```
212pub trait RorxEmitter<A, B, C> {
213    fn rorx(&mut self, op0: A, op1: B, op2: C);
214}
215
216impl<'a> RorxEmitter<Gpd, Gpd, Imm> for Assembler<'a> {
217    fn rorx(&mut self, op0: Gpd, op1: Gpd, op2: Imm) {
218        self.emit(RORX32RRI, op0.as_operand(), op1.as_operand(), op2.as_operand(), &NOREG);
219    }
220}
221
222impl<'a> RorxEmitter<Gpd, Mem, Imm> for Assembler<'a> {
223    fn rorx(&mut self, op0: Gpd, op1: Mem, op2: Imm) {
224        self.emit(RORX32RMI, op0.as_operand(), op1.as_operand(), op2.as_operand(), &NOREG);
225    }
226}
227
228impl<'a> RorxEmitter<Gpq, Gpq, Imm> for Assembler<'a> {
229    fn rorx(&mut self, op0: Gpq, op1: Gpq, op2: Imm) {
230        self.emit(RORX64RRI, op0.as_operand(), op1.as_operand(), op2.as_operand(), &NOREG);
231    }
232}
233
234impl<'a> RorxEmitter<Gpq, Mem, Imm> for Assembler<'a> {
235    fn rorx(&mut self, op0: Gpq, op1: Mem, op2: Imm) {
236        self.emit(RORX64RMI, op0.as_operand(), op1.as_operand(), op2.as_operand(), &NOREG);
237    }
238}
239
240/// `SARX` (SARX). 
241/// Shifts the bits of the first source operand (the second operand) to the left or right by a COUNT value specified in the second source operand (the third operand). The result is written to the destination operand (the first operand).
242///
243///
244/// For more details, see the [Intel manual](https://www.felixcloutier.com/x86/SARX%3ASHLX%3ASHRX.html).
245///
246/// Supported operand variants:
247///
248/// ```text
249/// +---+---------------+
250/// | # | Operands      |
251/// +---+---------------+
252/// | 1 | Gpd, Gpd, Gpd |
253/// | 2 | Gpd, Mem, Gpd |
254/// | 3 | Gpq, Gpq, Gpq |
255/// | 4 | Gpq, Mem, Gpq |
256/// +---+---------------+
257/// ```
258pub trait SarxEmitter<A, B, C> {
259    fn sarx(&mut self, op0: A, op1: B, op2: C);
260}
261
262impl<'a> SarxEmitter<Gpd, Gpd, Gpd> for Assembler<'a> {
263    fn sarx(&mut self, op0: Gpd, op1: Gpd, op2: Gpd) {
264        self.emit(SARX32RRR, op0.as_operand(), op1.as_operand(), op2.as_operand(), &NOREG);
265    }
266}
267
268impl<'a> SarxEmitter<Gpd, Mem, Gpd> for Assembler<'a> {
269    fn sarx(&mut self, op0: Gpd, op1: Mem, op2: Gpd) {
270        self.emit(SARX32RMR, op0.as_operand(), op1.as_operand(), op2.as_operand(), &NOREG);
271    }
272}
273
274impl<'a> SarxEmitter<Gpq, Gpq, Gpq> for Assembler<'a> {
275    fn sarx(&mut self, op0: Gpq, op1: Gpq, op2: Gpq) {
276        self.emit(SARX64RRR, op0.as_operand(), op1.as_operand(), op2.as_operand(), &NOREG);
277    }
278}
279
280impl<'a> SarxEmitter<Gpq, Mem, Gpq> for Assembler<'a> {
281    fn sarx(&mut self, op0: Gpq, op1: Mem, op2: Gpq) {
282        self.emit(SARX64RMR, op0.as_operand(), op1.as_operand(), op2.as_operand(), &NOREG);
283    }
284}
285
286/// `SHLX` (SHLX). 
287/// Shifts the bits of the first source operand (the second operand) to the left or right by a COUNT value specified in the second source operand (the third operand). The result is written to the destination operand (the first operand).
288///
289///
290/// For more details, see the [Intel manual](https://www.felixcloutier.com/x86/SARX%3ASHLX%3ASHRX.html).
291///
292/// Supported operand variants:
293///
294/// ```text
295/// +---+---------------+
296/// | # | Operands      |
297/// +---+---------------+
298/// | 1 | Gpd, Gpd, Gpd |
299/// | 2 | Gpd, Mem, Gpd |
300/// | 3 | Gpq, Gpq, Gpq |
301/// | 4 | Gpq, Mem, Gpq |
302/// +---+---------------+
303/// ```
304pub trait ShlxEmitter<A, B, C> {
305    fn shlx(&mut self, op0: A, op1: B, op2: C);
306}
307
308impl<'a> ShlxEmitter<Gpd, Gpd, Gpd> for Assembler<'a> {
309    fn shlx(&mut self, op0: Gpd, op1: Gpd, op2: Gpd) {
310        self.emit(SHLX32RRR, op0.as_operand(), op1.as_operand(), op2.as_operand(), &NOREG);
311    }
312}
313
314impl<'a> ShlxEmitter<Gpd, Mem, Gpd> for Assembler<'a> {
315    fn shlx(&mut self, op0: Gpd, op1: Mem, op2: Gpd) {
316        self.emit(SHLX32RMR, op0.as_operand(), op1.as_operand(), op2.as_operand(), &NOREG);
317    }
318}
319
320impl<'a> ShlxEmitter<Gpq, Gpq, Gpq> for Assembler<'a> {
321    fn shlx(&mut self, op0: Gpq, op1: Gpq, op2: Gpq) {
322        self.emit(SHLX64RRR, op0.as_operand(), op1.as_operand(), op2.as_operand(), &NOREG);
323    }
324}
325
326impl<'a> ShlxEmitter<Gpq, Mem, Gpq> for Assembler<'a> {
327    fn shlx(&mut self, op0: Gpq, op1: Mem, op2: Gpq) {
328        self.emit(SHLX64RMR, op0.as_operand(), op1.as_operand(), op2.as_operand(), &NOREG);
329    }
330}
331
332/// `SHRX` (SHRX). 
333/// Shifts the bits of the first source operand (the second operand) to the left or right by a COUNT value specified in the second source operand (the third operand). The result is written to the destination operand (the first operand).
334///
335///
336/// For more details, see the [Intel manual](https://www.felixcloutier.com/x86/SARX%3ASHLX%3ASHRX.html).
337///
338/// Supported operand variants:
339///
340/// ```text
341/// +---+---------------+
342/// | # | Operands      |
343/// +---+---------------+
344/// | 1 | Gpd, Gpd, Gpd |
345/// | 2 | Gpd, Mem, Gpd |
346/// | 3 | Gpq, Gpq, Gpq |
347/// | 4 | Gpq, Mem, Gpq |
348/// +---+---------------+
349/// ```
350pub trait ShrxEmitter<A, B, C> {
351    fn shrx(&mut self, op0: A, op1: B, op2: C);
352}
353
354impl<'a> ShrxEmitter<Gpd, Gpd, Gpd> for Assembler<'a> {
355    fn shrx(&mut self, op0: Gpd, op1: Gpd, op2: Gpd) {
356        self.emit(SHRX32RRR, op0.as_operand(), op1.as_operand(), op2.as_operand(), &NOREG);
357    }
358}
359
360impl<'a> ShrxEmitter<Gpd, Mem, Gpd> for Assembler<'a> {
361    fn shrx(&mut self, op0: Gpd, op1: Mem, op2: Gpd) {
362        self.emit(SHRX32RMR, op0.as_operand(), op1.as_operand(), op2.as_operand(), &NOREG);
363    }
364}
365
366impl<'a> ShrxEmitter<Gpq, Gpq, Gpq> for Assembler<'a> {
367    fn shrx(&mut self, op0: Gpq, op1: Gpq, op2: Gpq) {
368        self.emit(SHRX64RRR, op0.as_operand(), op1.as_operand(), op2.as_operand(), &NOREG);
369    }
370}
371
372impl<'a> ShrxEmitter<Gpq, Mem, Gpq> for Assembler<'a> {
373    fn shrx(&mut self, op0: Gpq, op1: Mem, op2: Gpq) {
374        self.emit(SHRX64RMR, op0.as_operand(), op1.as_operand(), op2.as_operand(), &NOREG);
375    }
376}
377
378
379impl<'a> Assembler<'a> {
380    /// `BZHI` (BZHI). 
381    /// BZHI copies the bits of the first source operand (the second operand) into the destination operand (the first operand) and clears the higher bits in the destination according to the INDEX value specified by the second source operand (the third operand). The INDEX is specified by bits 7:0 of the second source operand. The INDEX value is saturated at the value of OperandSize -1. CF is set, if the number contained in the 8 low bits of the third operand is greater than OperandSize -1.
382    ///
383    ///
384    /// For more details, see the [Intel manual](https://www.felixcloutier.com/x86/BZHI.html).
385    ///
386    /// Supported operand variants:
387    ///
388    /// ```text
389    /// +---+---------------+
390    /// | # | Operands      |
391    /// +---+---------------+
392    /// | 1 | Gpd, Gpd, Gpd |
393    /// | 2 | Gpd, Mem, Gpd |
394    /// | 3 | Gpq, Gpq, Gpq |
395    /// | 4 | Gpq, Mem, Gpq |
396    /// +---+---------------+
397    /// ```
398    #[inline]
399    pub fn bzhi<A, B, C>(&mut self, op0: A, op1: B, op2: C)
400    where Assembler<'a>: BzhiEmitter<A, B, C> {
401        <Self as BzhiEmitter<A, B, C>>::bzhi(self, op0, op1, op2);
402    }
403    /// `MULX` (MULX). 
404    /// Performs an unsigned multiplication of the implicit source operand (EDX/RDX) and the specified source operand (the third operand) and stores the low half of the result in the second destination (second operand), the high half of the result in the first destination operand (first operand), without reading or writing the arithmetic flags. This enables efficient programming where the software can interleave add with carry operations and multiplications.
405    ///
406    ///
407    /// For more details, see the [Intel manual](https://www.felixcloutier.com/x86/MULX.html).
408    ///
409    /// Supported operand variants:
410    ///
411    /// ```text
412    /// +---+---------------+
413    /// | # | Operands      |
414    /// +---+---------------+
415    /// | 1 | Gpd, Gpd, Gpd |
416    /// | 2 | Gpd, Gpd, Mem |
417    /// | 3 | Gpq, Gpq, Gpq |
418    /// | 4 | Gpq, Gpq, Mem |
419    /// +---+---------------+
420    /// ```
421    #[inline]
422    pub fn mulx<A, B, C>(&mut self, op0: A, op1: B, op2: C)
423    where Assembler<'a>: MulxEmitter<A, B, C> {
424        <Self as MulxEmitter<A, B, C>>::mulx(self, op0, op1, op2);
425    }
426    /// `PDEP` (PDEP). 
427    /// PDEP uses a mask in the second source operand (the third operand) to transfer/scatter contiguous low order bits in the first source operand (the second operand) into the destination (the first operand). PDEP takes the low bits from the first source operand and deposit them in the destination operand at the corresponding bit locations that are set in the second source operand (mask). All other bits (bits not set in mask) in destination are set to zero.
428    ///
429    ///
430    /// For more details, see the [Intel manual](https://www.felixcloutier.com/x86/PDEP.html).
431    ///
432    /// Supported operand variants:
433    ///
434    /// ```text
435    /// +---+---------------+
436    /// | # | Operands      |
437    /// +---+---------------+
438    /// | 1 | Gpd, Gpd, Gpd |
439    /// | 2 | Gpd, Gpd, Mem |
440    /// | 3 | Gpq, Gpq, Gpq |
441    /// | 4 | Gpq, Gpq, Mem |
442    /// +---+---------------+
443    /// ```
444    #[inline]
445    pub fn pdep<A, B, C>(&mut self, op0: A, op1: B, op2: C)
446    where Assembler<'a>: PdepEmitter<A, B, C> {
447        <Self as PdepEmitter<A, B, C>>::pdep(self, op0, op1, op2);
448    }
449    /// `PEXT` (PEXT). 
450    /// PEXT uses a mask in the second source operand (the third operand) to transfer either contiguous or non-contiguous bits in the first source operand (the second operand) to contiguous low order bit positions in the destination (the first operand). For each bit set in the MASK, PEXT extracts the corresponding bits from the first source operand and writes them into contiguous lower bits of destination operand. The remaining upper bits of destination are zeroed.
451    ///
452    ///
453    /// For more details, see the [Intel manual](https://www.felixcloutier.com/x86/PEXT.html).
454    ///
455    /// Supported operand variants:
456    ///
457    /// ```text
458    /// +---+---------------+
459    /// | # | Operands      |
460    /// +---+---------------+
461    /// | 1 | Gpd, Gpd, Gpd |
462    /// | 2 | Gpd, Gpd, Mem |
463    /// | 3 | Gpq, Gpq, Gpq |
464    /// | 4 | Gpq, Gpq, Mem |
465    /// +---+---------------+
466    /// ```
467    #[inline]
468    pub fn pext<A, B, C>(&mut self, op0: A, op1: B, op2: C)
469    where Assembler<'a>: PextEmitter<A, B, C> {
470        <Self as PextEmitter<A, B, C>>::pext(self, op0, op1, op2);
471    }
472    /// `RORX` (RORX). 
473    /// Rotates the bits of second operand right by the count value specified in imm8 without affecting arithmetic flags. The RORX instruction does not read or write the arithmetic flags.
474    ///
475    ///
476    /// For more details, see the [Intel manual](https://www.felixcloutier.com/x86/RORX.html).
477    ///
478    /// Supported operand variants:
479    ///
480    /// ```text
481    /// +---+---------------+
482    /// | # | Operands      |
483    /// +---+---------------+
484    /// | 1 | Gpd, Gpd, Imm |
485    /// | 2 | Gpd, Mem, Imm |
486    /// | 3 | Gpq, Gpq, Imm |
487    /// | 4 | Gpq, Mem, Imm |
488    /// +---+---------------+
489    /// ```
490    #[inline]
491    pub fn rorx<A, B, C>(&mut self, op0: A, op1: B, op2: C)
492    where Assembler<'a>: RorxEmitter<A, B, C> {
493        <Self as RorxEmitter<A, B, C>>::rorx(self, op0, op1, op2);
494    }
495    /// `SARX` (SARX). 
496    /// Shifts the bits of the first source operand (the second operand) to the left or right by a COUNT value specified in the second source operand (the third operand). The result is written to the destination operand (the first operand).
497    ///
498    ///
499    /// For more details, see the [Intel manual](https://www.felixcloutier.com/x86/SARX%3ASHLX%3ASHRX.html).
500    ///
501    /// Supported operand variants:
502    ///
503    /// ```text
504    /// +---+---------------+
505    /// | # | Operands      |
506    /// +---+---------------+
507    /// | 1 | Gpd, Gpd, Gpd |
508    /// | 2 | Gpd, Mem, Gpd |
509    /// | 3 | Gpq, Gpq, Gpq |
510    /// | 4 | Gpq, Mem, Gpq |
511    /// +---+---------------+
512    /// ```
513    #[inline]
514    pub fn sarx<A, B, C>(&mut self, op0: A, op1: B, op2: C)
515    where Assembler<'a>: SarxEmitter<A, B, C> {
516        <Self as SarxEmitter<A, B, C>>::sarx(self, op0, op1, op2);
517    }
518    /// `SHLX` (SHLX). 
519    /// Shifts the bits of the first source operand (the second operand) to the left or right by a COUNT value specified in the second source operand (the third operand). The result is written to the destination operand (the first operand).
520    ///
521    ///
522    /// For more details, see the [Intel manual](https://www.felixcloutier.com/x86/SARX%3ASHLX%3ASHRX.html).
523    ///
524    /// Supported operand variants:
525    ///
526    /// ```text
527    /// +---+---------------+
528    /// | # | Operands      |
529    /// +---+---------------+
530    /// | 1 | Gpd, Gpd, Gpd |
531    /// | 2 | Gpd, Mem, Gpd |
532    /// | 3 | Gpq, Gpq, Gpq |
533    /// | 4 | Gpq, Mem, Gpq |
534    /// +---+---------------+
535    /// ```
536    #[inline]
537    pub fn shlx<A, B, C>(&mut self, op0: A, op1: B, op2: C)
538    where Assembler<'a>: ShlxEmitter<A, B, C> {
539        <Self as ShlxEmitter<A, B, C>>::shlx(self, op0, op1, op2);
540    }
541    /// `SHRX` (SHRX). 
542    /// Shifts the bits of the first source operand (the second operand) to the left or right by a COUNT value specified in the second source operand (the third operand). The result is written to the destination operand (the first operand).
543    ///
544    ///
545    /// For more details, see the [Intel manual](https://www.felixcloutier.com/x86/SARX%3ASHLX%3ASHRX.html).
546    ///
547    /// Supported operand variants:
548    ///
549    /// ```text
550    /// +---+---------------+
551    /// | # | Operands      |
552    /// +---+---------------+
553    /// | 1 | Gpd, Gpd, Gpd |
554    /// | 2 | Gpd, Mem, Gpd |
555    /// | 3 | Gpq, Gpq, Gpq |
556    /// | 4 | Gpq, Mem, Gpq |
557    /// +---+---------------+
558    /// ```
559    #[inline]
560    pub fn shrx<A, B, C>(&mut self, op0: A, op1: B, op2: C)
561    where Assembler<'a>: ShrxEmitter<A, B, C> {
562        <Self as ShrxEmitter<A, B, C>>::shrx(self, op0, op1, op2);
563    }
564}