Skip to main content

asmkit/x86/features/
BMI2.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/// `BZHI`.
11///
12/// Supported operand variants:
13///
14/// ```text
15/// +---+---------------+
16/// | # | Operands      |
17/// +---+---------------+
18/// | 1 | Gpd, Gpd, Gpd |
19/// | 2 | Gpd, Mem, Gpd |
20/// | 3 | Gpq, Gpq, Gpq |
21/// | 4 | Gpq, Mem, Gpq |
22/// +---+---------------+
23/// ```
24pub trait BzhiEmitter<A, B, C> {
25    fn bzhi(&mut self, op0: A, op1: B, op2: C);
26}
27
28impl<'a> BzhiEmitter<Gpd, Gpd, Gpd> for Assembler<'a> {
29    fn bzhi(&mut self, op0: Gpd, op1: Gpd, op2: Gpd) {
30        self.emit(
31            BZHI32RRR,
32            op0.as_operand(),
33            op1.as_operand(),
34            op2.as_operand(),
35            &NOREG,
36        );
37    }
38}
39
40impl<'a> BzhiEmitter<Gpd, Mem, Gpd> for Assembler<'a> {
41    fn bzhi(&mut self, op0: Gpd, op1: Mem, op2: Gpd) {
42        self.emit(
43            BZHI32RMR,
44            op0.as_operand(),
45            op1.as_operand(),
46            op2.as_operand(),
47            &NOREG,
48        );
49    }
50}
51
52impl<'a> BzhiEmitter<Gpq, Gpq, Gpq> for Assembler<'a> {
53    fn bzhi(&mut self, op0: Gpq, op1: Gpq, op2: Gpq) {
54        self.emit(
55            BZHI64RRR,
56            op0.as_operand(),
57            op1.as_operand(),
58            op2.as_operand(),
59            &NOREG,
60        );
61    }
62}
63
64impl<'a> BzhiEmitter<Gpq, Mem, Gpq> for Assembler<'a> {
65    fn bzhi(&mut self, op0: Gpq, op1: Mem, op2: Gpq) {
66        self.emit(
67            BZHI64RMR,
68            op0.as_operand(),
69            op1.as_operand(),
70            op2.as_operand(),
71            &NOREG,
72        );
73    }
74}
75
76/// `MULX`.
77///
78/// Supported operand variants:
79///
80/// ```text
81/// +---+---------------+
82/// | # | Operands      |
83/// +---+---------------+
84/// | 1 | Gpd, Gpd, Gpd |
85/// | 2 | Gpd, Gpd, Mem |
86/// | 3 | Gpq, Gpq, Gpq |
87/// | 4 | Gpq, Gpq, Mem |
88/// +---+---------------+
89/// ```
90pub trait MulxEmitter<A, B, C> {
91    fn mulx(&mut self, op0: A, op1: B, op2: C);
92}
93
94impl<'a> MulxEmitter<Gpd, Gpd, Gpd> for Assembler<'a> {
95    fn mulx(&mut self, op0: Gpd, op1: Gpd, op2: Gpd) {
96        self.emit(
97            MULX32RRR,
98            op0.as_operand(),
99            op1.as_operand(),
100            op2.as_operand(),
101            &NOREG,
102        );
103    }
104}
105
106impl<'a> MulxEmitter<Gpd, Gpd, Mem> for Assembler<'a> {
107    fn mulx(&mut self, op0: Gpd, op1: Gpd, op2: Mem) {
108        self.emit(
109            MULX32RRM,
110            op0.as_operand(),
111            op1.as_operand(),
112            op2.as_operand(),
113            &NOREG,
114        );
115    }
116}
117
118impl<'a> MulxEmitter<Gpq, Gpq, Gpq> for Assembler<'a> {
119    fn mulx(&mut self, op0: Gpq, op1: Gpq, op2: Gpq) {
120        self.emit(
121            MULX64RRR,
122            op0.as_operand(),
123            op1.as_operand(),
124            op2.as_operand(),
125            &NOREG,
126        );
127    }
128}
129
130impl<'a> MulxEmitter<Gpq, Gpq, Mem> for Assembler<'a> {
131    fn mulx(&mut self, op0: Gpq, op1: Gpq, op2: Mem) {
132        self.emit(
133            MULX64RRM,
134            op0.as_operand(),
135            op1.as_operand(),
136            op2.as_operand(),
137            &NOREG,
138        );
139    }
140}
141
142/// `PDEP`.
143///
144/// Supported operand variants:
145///
146/// ```text
147/// +---+---------------+
148/// | # | Operands      |
149/// +---+---------------+
150/// | 1 | Gpd, Gpd, Gpd |
151/// | 2 | Gpd, Gpd, Mem |
152/// | 3 | Gpq, Gpq, Gpq |
153/// | 4 | Gpq, Gpq, Mem |
154/// +---+---------------+
155/// ```
156pub trait PdepEmitter<A, B, C> {
157    fn pdep(&mut self, op0: A, op1: B, op2: C);
158}
159
160impl<'a> PdepEmitter<Gpd, Gpd, Gpd> for Assembler<'a> {
161    fn pdep(&mut self, op0: Gpd, op1: Gpd, op2: Gpd) {
162        self.emit(
163            PDEP32RRR,
164            op0.as_operand(),
165            op1.as_operand(),
166            op2.as_operand(),
167            &NOREG,
168        );
169    }
170}
171
172impl<'a> PdepEmitter<Gpd, Gpd, Mem> for Assembler<'a> {
173    fn pdep(&mut self, op0: Gpd, op1: Gpd, op2: Mem) {
174        self.emit(
175            PDEP32RRM,
176            op0.as_operand(),
177            op1.as_operand(),
178            op2.as_operand(),
179            &NOREG,
180        );
181    }
182}
183
184impl<'a> PdepEmitter<Gpq, Gpq, Gpq> for Assembler<'a> {
185    fn pdep(&mut self, op0: Gpq, op1: Gpq, op2: Gpq) {
186        self.emit(
187            PDEP64RRR,
188            op0.as_operand(),
189            op1.as_operand(),
190            op2.as_operand(),
191            &NOREG,
192        );
193    }
194}
195
196impl<'a> PdepEmitter<Gpq, Gpq, Mem> for Assembler<'a> {
197    fn pdep(&mut self, op0: Gpq, op1: Gpq, op2: Mem) {
198        self.emit(
199            PDEP64RRM,
200            op0.as_operand(),
201            op1.as_operand(),
202            op2.as_operand(),
203            &NOREG,
204        );
205    }
206}
207
208/// `PEXT`.
209///
210/// Supported operand variants:
211///
212/// ```text
213/// +---+---------------+
214/// | # | Operands      |
215/// +---+---------------+
216/// | 1 | Gpd, Gpd, Gpd |
217/// | 2 | Gpd, Gpd, Mem |
218/// | 3 | Gpq, Gpq, Gpq |
219/// | 4 | Gpq, Gpq, Mem |
220/// +---+---------------+
221/// ```
222pub trait PextEmitter<A, B, C> {
223    fn pext(&mut self, op0: A, op1: B, op2: C);
224}
225
226impl<'a> PextEmitter<Gpd, Gpd, Gpd> for Assembler<'a> {
227    fn pext(&mut self, op0: Gpd, op1: Gpd, op2: Gpd) {
228        self.emit(
229            PEXT32RRR,
230            op0.as_operand(),
231            op1.as_operand(),
232            op2.as_operand(),
233            &NOREG,
234        );
235    }
236}
237
238impl<'a> PextEmitter<Gpd, Gpd, Mem> for Assembler<'a> {
239    fn pext(&mut self, op0: Gpd, op1: Gpd, op2: Mem) {
240        self.emit(
241            PEXT32RRM,
242            op0.as_operand(),
243            op1.as_operand(),
244            op2.as_operand(),
245            &NOREG,
246        );
247    }
248}
249
250impl<'a> PextEmitter<Gpq, Gpq, Gpq> for Assembler<'a> {
251    fn pext(&mut self, op0: Gpq, op1: Gpq, op2: Gpq) {
252        self.emit(
253            PEXT64RRR,
254            op0.as_operand(),
255            op1.as_operand(),
256            op2.as_operand(),
257            &NOREG,
258        );
259    }
260}
261
262impl<'a> PextEmitter<Gpq, Gpq, Mem> for Assembler<'a> {
263    fn pext(&mut self, op0: Gpq, op1: Gpq, op2: Mem) {
264        self.emit(
265            PEXT64RRM,
266            op0.as_operand(),
267            op1.as_operand(),
268            op2.as_operand(),
269            &NOREG,
270        );
271    }
272}
273
274/// `RORX`.
275///
276/// Supported operand variants:
277///
278/// ```text
279/// +---+---------------+
280/// | # | Operands      |
281/// +---+---------------+
282/// | 1 | Gpd, Gpd, Imm |
283/// | 2 | Gpd, Mem, Imm |
284/// | 3 | Gpq, Gpq, Imm |
285/// | 4 | Gpq, Mem, Imm |
286/// +---+---------------+
287/// ```
288pub trait RorxEmitter<A, B, C> {
289    fn rorx(&mut self, op0: A, op1: B, op2: C);
290}
291
292impl<'a> RorxEmitter<Gpd, Gpd, Imm> for Assembler<'a> {
293    fn rorx(&mut self, op0: Gpd, op1: Gpd, op2: Imm) {
294        self.emit(
295            RORX32RRI,
296            op0.as_operand(),
297            op1.as_operand(),
298            op2.as_operand(),
299            &NOREG,
300        );
301    }
302}
303
304impl<'a> RorxEmitter<Gpd, Mem, Imm> for Assembler<'a> {
305    fn rorx(&mut self, op0: Gpd, op1: Mem, op2: Imm) {
306        self.emit(
307            RORX32RMI,
308            op0.as_operand(),
309            op1.as_operand(),
310            op2.as_operand(),
311            &NOREG,
312        );
313    }
314}
315
316impl<'a> RorxEmitter<Gpq, Gpq, Imm> for Assembler<'a> {
317    fn rorx(&mut self, op0: Gpq, op1: Gpq, op2: Imm) {
318        self.emit(
319            RORX64RRI,
320            op0.as_operand(),
321            op1.as_operand(),
322            op2.as_operand(),
323            &NOREG,
324        );
325    }
326}
327
328impl<'a> RorxEmitter<Gpq, Mem, Imm> for Assembler<'a> {
329    fn rorx(&mut self, op0: Gpq, op1: Mem, op2: Imm) {
330        self.emit(
331            RORX64RMI,
332            op0.as_operand(),
333            op1.as_operand(),
334            op2.as_operand(),
335            &NOREG,
336        );
337    }
338}
339
340/// `SARX`.
341///
342/// Supported operand variants:
343///
344/// ```text
345/// +---+---------------+
346/// | # | Operands      |
347/// +---+---------------+
348/// | 1 | Gpd, Gpd, Gpd |
349/// | 2 | Gpd, Mem, Gpd |
350/// | 3 | Gpq, Gpq, Gpq |
351/// | 4 | Gpq, Mem, Gpq |
352/// +---+---------------+
353/// ```
354pub trait SarxEmitter<A, B, C> {
355    fn sarx(&mut self, op0: A, op1: B, op2: C);
356}
357
358impl<'a> SarxEmitter<Gpd, Gpd, Gpd> for Assembler<'a> {
359    fn sarx(&mut self, op0: Gpd, op1: Gpd, op2: Gpd) {
360        self.emit(
361            SARX32RRR,
362            op0.as_operand(),
363            op1.as_operand(),
364            op2.as_operand(),
365            &NOREG,
366        );
367    }
368}
369
370impl<'a> SarxEmitter<Gpd, Mem, Gpd> for Assembler<'a> {
371    fn sarx(&mut self, op0: Gpd, op1: Mem, op2: Gpd) {
372        self.emit(
373            SARX32RMR,
374            op0.as_operand(),
375            op1.as_operand(),
376            op2.as_operand(),
377            &NOREG,
378        );
379    }
380}
381
382impl<'a> SarxEmitter<Gpq, Gpq, Gpq> for Assembler<'a> {
383    fn sarx(&mut self, op0: Gpq, op1: Gpq, op2: Gpq) {
384        self.emit(
385            SARX64RRR,
386            op0.as_operand(),
387            op1.as_operand(),
388            op2.as_operand(),
389            &NOREG,
390        );
391    }
392}
393
394impl<'a> SarxEmitter<Gpq, Mem, Gpq> for Assembler<'a> {
395    fn sarx(&mut self, op0: Gpq, op1: Mem, op2: Gpq) {
396        self.emit(
397            SARX64RMR,
398            op0.as_operand(),
399            op1.as_operand(),
400            op2.as_operand(),
401            &NOREG,
402        );
403    }
404}
405
406/// `SHLX`.
407///
408/// Supported operand variants:
409///
410/// ```text
411/// +---+---------------+
412/// | # | Operands      |
413/// +---+---------------+
414/// | 1 | Gpd, Gpd, Gpd |
415/// | 2 | Gpd, Mem, Gpd |
416/// | 3 | Gpq, Gpq, Gpq |
417/// | 4 | Gpq, Mem, Gpq |
418/// +---+---------------+
419/// ```
420pub trait ShlxEmitter<A, B, C> {
421    fn shlx(&mut self, op0: A, op1: B, op2: C);
422}
423
424impl<'a> ShlxEmitter<Gpd, Gpd, Gpd> for Assembler<'a> {
425    fn shlx(&mut self, op0: Gpd, op1: Gpd, op2: Gpd) {
426        self.emit(
427            SHLX32RRR,
428            op0.as_operand(),
429            op1.as_operand(),
430            op2.as_operand(),
431            &NOREG,
432        );
433    }
434}
435
436impl<'a> ShlxEmitter<Gpd, Mem, Gpd> for Assembler<'a> {
437    fn shlx(&mut self, op0: Gpd, op1: Mem, op2: Gpd) {
438        self.emit(
439            SHLX32RMR,
440            op0.as_operand(),
441            op1.as_operand(),
442            op2.as_operand(),
443            &NOREG,
444        );
445    }
446}
447
448impl<'a> ShlxEmitter<Gpq, Gpq, Gpq> for Assembler<'a> {
449    fn shlx(&mut self, op0: Gpq, op1: Gpq, op2: Gpq) {
450        self.emit(
451            SHLX64RRR,
452            op0.as_operand(),
453            op1.as_operand(),
454            op2.as_operand(),
455            &NOREG,
456        );
457    }
458}
459
460impl<'a> ShlxEmitter<Gpq, Mem, Gpq> for Assembler<'a> {
461    fn shlx(&mut self, op0: Gpq, op1: Mem, op2: Gpq) {
462        self.emit(
463            SHLX64RMR,
464            op0.as_operand(),
465            op1.as_operand(),
466            op2.as_operand(),
467            &NOREG,
468        );
469    }
470}
471
472/// `SHRX`.
473///
474/// Supported operand variants:
475///
476/// ```text
477/// +---+---------------+
478/// | # | Operands      |
479/// +---+---------------+
480/// | 1 | Gpd, Gpd, Gpd |
481/// | 2 | Gpd, Mem, Gpd |
482/// | 3 | Gpq, Gpq, Gpq |
483/// | 4 | Gpq, Mem, Gpq |
484/// +---+---------------+
485/// ```
486pub trait ShrxEmitter<A, B, C> {
487    fn shrx(&mut self, op0: A, op1: B, op2: C);
488}
489
490impl<'a> ShrxEmitter<Gpd, Gpd, Gpd> for Assembler<'a> {
491    fn shrx(&mut self, op0: Gpd, op1: Gpd, op2: Gpd) {
492        self.emit(
493            SHRX32RRR,
494            op0.as_operand(),
495            op1.as_operand(),
496            op2.as_operand(),
497            &NOREG,
498        );
499    }
500}
501
502impl<'a> ShrxEmitter<Gpd, Mem, Gpd> for Assembler<'a> {
503    fn shrx(&mut self, op0: Gpd, op1: Mem, op2: Gpd) {
504        self.emit(
505            SHRX32RMR,
506            op0.as_operand(),
507            op1.as_operand(),
508            op2.as_operand(),
509            &NOREG,
510        );
511    }
512}
513
514impl<'a> ShrxEmitter<Gpq, Gpq, Gpq> for Assembler<'a> {
515    fn shrx(&mut self, op0: Gpq, op1: Gpq, op2: Gpq) {
516        self.emit(
517            SHRX64RRR,
518            op0.as_operand(),
519            op1.as_operand(),
520            op2.as_operand(),
521            &NOREG,
522        );
523    }
524}
525
526impl<'a> ShrxEmitter<Gpq, Mem, Gpq> for Assembler<'a> {
527    fn shrx(&mut self, op0: Gpq, op1: Mem, op2: Gpq) {
528        self.emit(
529            SHRX64RMR,
530            op0.as_operand(),
531            op1.as_operand(),
532            op2.as_operand(),
533            &NOREG,
534        );
535    }
536}
537
538impl<'a> Assembler<'a> {
539    /// `BZHI`.
540    ///
541    /// Supported operand variants:
542    ///
543    /// ```text
544    /// +---+---------------+
545    /// | # | Operands      |
546    /// +---+---------------+
547    /// | 1 | Gpd, Gpd, Gpd |
548    /// | 2 | Gpd, Mem, Gpd |
549    /// | 3 | Gpq, Gpq, Gpq |
550    /// | 4 | Gpq, Mem, Gpq |
551    /// +---+---------------+
552    /// ```
553    #[inline]
554    pub fn bzhi<A, B, C>(&mut self, op0: A, op1: B, op2: C)
555    where
556        Assembler<'a>: BzhiEmitter<A, B, C>,
557    {
558        <Self as BzhiEmitter<A, B, C>>::bzhi(self, op0, op1, op2);
559    }
560    /// `MULX`.
561    ///
562    /// Supported operand variants:
563    ///
564    /// ```text
565    /// +---+---------------+
566    /// | # | Operands      |
567    /// +---+---------------+
568    /// | 1 | Gpd, Gpd, Gpd |
569    /// | 2 | Gpd, Gpd, Mem |
570    /// | 3 | Gpq, Gpq, Gpq |
571    /// | 4 | Gpq, Gpq, Mem |
572    /// +---+---------------+
573    /// ```
574    #[inline]
575    pub fn mulx<A, B, C>(&mut self, op0: A, op1: B, op2: C)
576    where
577        Assembler<'a>: MulxEmitter<A, B, C>,
578    {
579        <Self as MulxEmitter<A, B, C>>::mulx(self, op0, op1, op2);
580    }
581    /// `PDEP`.
582    ///
583    /// Supported operand variants:
584    ///
585    /// ```text
586    /// +---+---------------+
587    /// | # | Operands      |
588    /// +---+---------------+
589    /// | 1 | Gpd, Gpd, Gpd |
590    /// | 2 | Gpd, Gpd, Mem |
591    /// | 3 | Gpq, Gpq, Gpq |
592    /// | 4 | Gpq, Gpq, Mem |
593    /// +---+---------------+
594    /// ```
595    #[inline]
596    pub fn pdep<A, B, C>(&mut self, op0: A, op1: B, op2: C)
597    where
598        Assembler<'a>: PdepEmitter<A, B, C>,
599    {
600        <Self as PdepEmitter<A, B, C>>::pdep(self, op0, op1, op2);
601    }
602    /// `PEXT`.
603    ///
604    /// Supported operand variants:
605    ///
606    /// ```text
607    /// +---+---------------+
608    /// | # | Operands      |
609    /// +---+---------------+
610    /// | 1 | Gpd, Gpd, Gpd |
611    /// | 2 | Gpd, Gpd, Mem |
612    /// | 3 | Gpq, Gpq, Gpq |
613    /// | 4 | Gpq, Gpq, Mem |
614    /// +---+---------------+
615    /// ```
616    #[inline]
617    pub fn pext<A, B, C>(&mut self, op0: A, op1: B, op2: C)
618    where
619        Assembler<'a>: PextEmitter<A, B, C>,
620    {
621        <Self as PextEmitter<A, B, C>>::pext(self, op0, op1, op2);
622    }
623    /// `RORX`.
624    ///
625    /// Supported operand variants:
626    ///
627    /// ```text
628    /// +---+---------------+
629    /// | # | Operands      |
630    /// +---+---------------+
631    /// | 1 | Gpd, Gpd, Imm |
632    /// | 2 | Gpd, Mem, Imm |
633    /// | 3 | Gpq, Gpq, Imm |
634    /// | 4 | Gpq, Mem, Imm |
635    /// +---+---------------+
636    /// ```
637    #[inline]
638    pub fn rorx<A, B, C>(&mut self, op0: A, op1: B, op2: C)
639    where
640        Assembler<'a>: RorxEmitter<A, B, C>,
641    {
642        <Self as RorxEmitter<A, B, C>>::rorx(self, op0, op1, op2);
643    }
644    /// `SARX`.
645    ///
646    /// Supported operand variants:
647    ///
648    /// ```text
649    /// +---+---------------+
650    /// | # | Operands      |
651    /// +---+---------------+
652    /// | 1 | Gpd, Gpd, Gpd |
653    /// | 2 | Gpd, Mem, Gpd |
654    /// | 3 | Gpq, Gpq, Gpq |
655    /// | 4 | Gpq, Mem, Gpq |
656    /// +---+---------------+
657    /// ```
658    #[inline]
659    pub fn sarx<A, B, C>(&mut self, op0: A, op1: B, op2: C)
660    where
661        Assembler<'a>: SarxEmitter<A, B, C>,
662    {
663        <Self as SarxEmitter<A, B, C>>::sarx(self, op0, op1, op2);
664    }
665    /// `SHLX`.
666    ///
667    /// Supported operand variants:
668    ///
669    /// ```text
670    /// +---+---------------+
671    /// | # | Operands      |
672    /// +---+---------------+
673    /// | 1 | Gpd, Gpd, Gpd |
674    /// | 2 | Gpd, Mem, Gpd |
675    /// | 3 | Gpq, Gpq, Gpq |
676    /// | 4 | Gpq, Mem, Gpq |
677    /// +---+---------------+
678    /// ```
679    #[inline]
680    pub fn shlx<A, B, C>(&mut self, op0: A, op1: B, op2: C)
681    where
682        Assembler<'a>: ShlxEmitter<A, B, C>,
683    {
684        <Self as ShlxEmitter<A, B, C>>::shlx(self, op0, op1, op2);
685    }
686    /// `SHRX`.
687    ///
688    /// Supported operand variants:
689    ///
690    /// ```text
691    /// +---+---------------+
692    /// | # | Operands      |
693    /// +---+---------------+
694    /// | 1 | Gpd, Gpd, Gpd |
695    /// | 2 | Gpd, Mem, Gpd |
696    /// | 3 | Gpq, Gpq, Gpq |
697    /// | 4 | Gpq, Mem, Gpq |
698    /// +---+---------------+
699    /// ```
700    #[inline]
701    pub fn shrx<A, B, C>(&mut self, op0: A, op1: B, op2: C)
702    where
703        Assembler<'a>: ShrxEmitter<A, B, C>,
704    {
705        <Self as ShrxEmitter<A, B, C>>::shrx(self, op0, op1, op2);
706    }
707}