1use super::regs::{self};
4use crate::ir::condcodes::{FloatCC, IntCC};
5use crate::ir::types::*;
6use crate::ir::MemFlags;
7use crate::isa::x64::inst::regs::pretty_print_reg;
8use crate::isa::x64::inst::Inst;
9use crate::machinst::*;
10use smallvec::{smallvec, SmallVec};
11use std::fmt;
12use std::string::String;
13
14pub use crate::isa::x64::lower::isle::generated_code::DivSignedness;
15
16pub trait ToWritableReg {
18 fn to_writable_reg(&self) -> Writable<Reg>;
20}
21
22pub trait FromWritableReg: Sized {
24 fn from_writable_reg(w: Writable<Reg>) -> Option<Self>;
26}
27
28macro_rules! newtype_of_reg {
31 (
32 $newtype_reg:ident,
33 $newtype_writable_reg:ident,
34 $newtype_option_writable_reg:ident,
35 reg_mem: ($($newtype_reg_mem:ident $(aligned:$aligned:ident)?),*),
36 reg_mem_imm: ($($newtype_reg_mem_imm:ident $(aligned:$aligned_imm:ident)?),*),
37 $newtype_imm8_reg:ident,
38 |$check_reg:ident| $check:expr
39 ) => {
40 #[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
42 pub struct $newtype_reg(Reg);
43
44 impl PartialEq<Reg> for $newtype_reg {
45 fn eq(&self, other: &Reg) -> bool {
46 self.0 == *other
47 }
48 }
49
50 impl From<$newtype_reg> for Reg {
51 fn from(r: $newtype_reg) -> Self {
52 r.0
53 }
54 }
55
56 impl $newtype_reg {
57 pub fn new($check_reg: Reg) -> Option<Self> {
60 if $check {
61 Some(Self($check_reg))
62 } else {
63 None
64 }
65 }
66
67 pub fn unwrap_new($check_reg: Reg) -> Self {
70 if $check {
71 Self($check_reg)
72 } else {
73 panic!(
74 "cannot construct {} from register {:?} with register class {:?}",
75 stringify!($newtype_reg),
76 $check_reg,
77 $check_reg.class(),
78 )
79 }
80 }
81
82 pub fn to_reg(self) -> Reg {
84 self.0
85 }
86 }
87
88 impl std::ops::Deref for $newtype_reg {
95 type Target = Reg;
96
97 fn deref(&self) -> &Reg {
98 &self.0
99 }
100 }
101
102 impl AsMut<Reg> for $newtype_reg {
106 fn as_mut(&mut self) -> &mut Reg {
107 &mut self.0
108 }
109 }
110
111 pub type $newtype_writable_reg = Writable<$newtype_reg>;
113
114 #[allow(dead_code)] pub type $newtype_option_writable_reg = Option<Writable<$newtype_reg>>;
117
118 impl ToWritableReg for $newtype_writable_reg {
119 fn to_writable_reg(&self) -> Writable<Reg> {
120 Writable::from_reg(self.to_reg().to_reg())
121 }
122 }
123
124 impl FromWritableReg for $newtype_writable_reg {
125 fn from_writable_reg(w: Writable<Reg>) -> Option<Self> {
126 Some(Writable::from_reg($newtype_reg::new(w.to_reg())?))
127 }
128 }
129
130 $(
131 #[derive(Clone, Debug)]
133 pub struct $newtype_reg_mem(RegMem);
134
135 impl From<$newtype_reg_mem> for RegMem {
136 fn from(rm: $newtype_reg_mem) -> Self {
137 rm.0
138 }
139 }
140 impl<'a> From<&'a $newtype_reg_mem> for &'a RegMem {
141 fn from(rm: &'a $newtype_reg_mem) -> &'a RegMem {
142 &rm.0
143 }
144 }
145
146 impl From<$newtype_reg> for $newtype_reg_mem {
147 fn from(r: $newtype_reg) -> Self {
148 $newtype_reg_mem(RegMem::reg(r.into()))
149 }
150 }
151
152 impl $newtype_reg_mem {
153 pub fn new(rm: RegMem) -> Option<Self> {
157 match rm {
158 RegMem::Mem { addr } => {
159 let mut _allow = true;
160 $(
161 if $aligned {
162 _allow = addr.aligned();
163 }
164 )?
165 if _allow {
166 Some(Self(RegMem::Mem { addr }))
167 } else {
168 None
169 }
170 }
171 RegMem::Reg { reg } => Some($newtype_reg::new(reg)?.into()),
172 }
173 }
174
175 pub fn unwrap_new(rm: RegMem) -> Self {
178 match rm {
179 RegMem::Mem { addr } => {
180 $(
181 if $aligned && !addr.aligned() {
182 panic!(
183 "cannot create {} from an unaligned memory address: {addr:?}",
184 stringify!($newtype_reg_mem),
185 );
186 }
187 )?
188 Self(RegMem::Mem { addr })
189 }
190 RegMem::Reg { reg } => $newtype_reg::unwrap_new(reg).into(),
191 }
192 }
193
194 pub fn to_reg_mem(self) -> RegMem {
196 self.0
197 }
198
199 #[allow(dead_code)] pub(crate) fn get_operands(&mut self, collector: &mut impl OperandVisitor) {
201 self.0.get_operands(collector);
202 }
203 }
204 impl PrettyPrint for $newtype_reg_mem {
205 fn pretty_print(&self, size: u8) -> String {
206 self.0.pretty_print(size)
207 }
208 }
209 )*
210
211 $(
212 #[derive(Clone, Debug)]
214 pub struct $newtype_reg_mem_imm(RegMemImm);
215
216 impl From<$newtype_reg_mem_imm> for RegMemImm {
217 fn from(rmi: $newtype_reg_mem_imm) -> RegMemImm {
218 rmi.0
219 }
220 }
221 impl<'a> From<&'a $newtype_reg_mem_imm> for &'a RegMemImm {
222 fn from(rmi: &'a $newtype_reg_mem_imm) -> &'a RegMemImm {
223 &rmi.0
224 }
225 }
226
227 impl From<$newtype_reg> for $newtype_reg_mem_imm {
228 fn from(r: $newtype_reg) -> Self {
229 $newtype_reg_mem_imm(RegMemImm::reg(r.into()))
230 }
231 }
232
233 impl $newtype_reg_mem_imm {
234 pub fn new(rmi: RegMemImm) -> Option<Self> {
238 match rmi {
239 RegMemImm::Imm { .. } => Some(Self(rmi)),
240 RegMemImm::Mem { addr } => {
241 let mut _allow = true;
242 $(
243 if $aligned_imm {
244 _allow = addr.aligned();
245 }
246 )?
247 if _allow {
248 Some(Self(RegMemImm::Mem { addr }))
249 } else {
250 None
251 }
252 }
253 RegMemImm::Reg { reg } => Some($newtype_reg::new(reg)?.into()),
254 }
255 }
256
257 pub fn unwrap_new(rmi: RegMemImm) -> Self {
260 match rmi {
261 RegMemImm::Imm { .. } => Self(rmi),
262 RegMemImm::Mem { addr } => {
263 $(
264 if $aligned_imm && !addr.aligned() {
265 panic!(
266 "cannot construct {} from unaligned memory address: {:?}",
267 stringify!($newtype_reg_mem_imm),
268 addr,
269 );
270 }
271 )?
272 Self(RegMemImm::Mem { addr })
273
274 }
275 RegMemImm::Reg { reg } => $newtype_reg::unwrap_new(reg).into(),
276 }
277 }
278
279 #[allow(dead_code)] pub fn to_reg_mem_imm(self) -> RegMemImm {
282 self.0
283 }
284
285 #[allow(dead_code)] pub(crate) fn get_operands(&mut self, collector: &mut impl OperandVisitor) {
287 self.0.get_operands(collector);
288 }
289 }
290
291 impl PrettyPrint for $newtype_reg_mem_imm {
292 fn pretty_print(&self, size: u8) -> String {
293 self.0.pretty_print(size)
294 }
295 }
296 )*
297
298 #[derive(Clone, Debug)]
300 #[allow(dead_code)] pub struct $newtype_imm8_reg(Imm8Reg);
302
303 impl From<$newtype_reg> for $newtype_imm8_reg {
304 fn from(r: $newtype_reg) -> Self {
305 Self(Imm8Reg::Reg { reg: r.to_reg() })
306 }
307 }
308
309 impl $newtype_imm8_reg {
310 #[allow(dead_code)] pub fn new(imm8_reg: Imm8Reg) -> Option<Self> {
314 match imm8_reg {
315 Imm8Reg::Imm8 { .. } => Some(Self(imm8_reg)),
316 Imm8Reg::Reg { reg } => Some($newtype_reg::new(reg)?.into()),
317 }
318 }
319
320 pub fn unwrap_new(imm8_reg: Imm8Reg) -> Self {
323 match imm8_reg {
324 Imm8Reg::Imm8 { .. } => Self(imm8_reg),
325 Imm8Reg::Reg { reg } => $newtype_reg::unwrap_new(reg).into(),
326 }
327 }
328
329 #[allow(dead_code)] pub fn as_imm8_reg(&self) -> &Imm8Reg {
332 &self.0
333 }
334
335 #[allow(dead_code)] pub fn as_imm8_reg_mut(&mut self) -> &mut Imm8Reg {
338 &mut self.0
339 }
340 }
341 };
342}
343
344newtype_of_reg!(
346 Gpr,
347 WritableGpr,
348 OptionWritableGpr,
349 reg_mem: (GprMem),
350 reg_mem_imm: (GprMemImm),
351 Imm8Gpr,
352 |reg| reg.class() == RegClass::Int
353);
354
355newtype_of_reg!(
357 Xmm,
358 WritableXmm,
359 OptionWritableXmm,
360 reg_mem: (XmmMem, XmmMemAligned aligned:true),
361 reg_mem_imm: (XmmMemImm, XmmMemAlignedImm aligned:true),
362 Imm8Xmm,
363 |reg| reg.class() == RegClass::Float
364);
365
366pub use crate::isa::x64::lower::isle::generated_code::Amode;
371
372impl Amode {
373 pub fn imm_reg(simm32: i32, base: Reg) -> Self {
375 debug_assert!(base.class() == RegClass::Int);
376 Self::ImmReg {
377 simm32,
378 base,
379 flags: MemFlags::trusted(),
380 }
381 }
382
383 pub fn imm_reg_reg_shift(simm32: i32, base: Gpr, index: Gpr, shift: u8) -> Self {
385 debug_assert!(base.class() == RegClass::Int);
386 debug_assert!(index.class() == RegClass::Int);
387 debug_assert!(shift <= 3);
388 Self::ImmRegRegShift {
389 simm32,
390 base,
391 index,
392 shift,
393 flags: MemFlags::trusted(),
394 }
395 }
396
397 pub(crate) fn rip_relative(target: MachLabel) -> Self {
398 Self::RipRelative { target }
399 }
400
401 pub fn with_flags(&self, flags: MemFlags) -> Self {
403 match self {
404 &Self::ImmReg { simm32, base, .. } => Self::ImmReg {
405 simm32,
406 base,
407 flags,
408 },
409 &Self::ImmRegRegShift {
410 simm32,
411 base,
412 index,
413 shift,
414 ..
415 } => Self::ImmRegRegShift {
416 simm32,
417 base,
418 index,
419 shift,
420 flags,
421 },
422 _ => panic!("Amode {self:?} cannot take memflags"),
423 }
424 }
425
426 pub(crate) fn get_operands(&mut self, collector: &mut impl OperandVisitor) {
428 match self {
429 Amode::ImmReg { base, .. } => {
430 if *base != regs::rbp() && *base != regs::rsp() {
431 collector.reg_use(base);
432 }
433 }
434 Amode::ImmRegRegShift { base, index, .. } => {
435 debug_assert_ne!(base.to_reg(), regs::rbp());
436 debug_assert_ne!(base.to_reg(), regs::rsp());
437 collector.reg_use(base);
438 debug_assert_ne!(index.to_reg(), regs::rbp());
439 debug_assert_ne!(index.to_reg(), regs::rsp());
440 collector.reg_use(index);
441 }
442 Amode::RipRelative { .. } => {
443 }
445 }
446 }
447
448 pub(crate) fn get_operands_late(&mut self, collector: &mut impl OperandVisitor) {
450 match self {
451 Amode::ImmReg { base, .. } => {
452 collector.reg_late_use(base);
453 }
454 Amode::ImmRegRegShift { base, index, .. } => {
455 collector.reg_late_use(base);
456 collector.reg_late_use(index);
457 }
458 Amode::RipRelative { .. } => {
459 }
461 }
462 }
463
464 pub(crate) fn get_flags(&self) -> MemFlags {
465 match self {
466 Amode::ImmReg { flags, .. } | Amode::ImmRegRegShift { flags, .. } => *flags,
467 Amode::RipRelative { .. } => MemFlags::trusted(),
468 }
469 }
470
471 pub(crate) fn offset(&self, offset: i32) -> Self {
473 let mut ret = self.clone();
474 match &mut ret {
475 &mut Amode::ImmReg { ref mut simm32, .. } => *simm32 += offset,
476 &mut Amode::ImmRegRegShift { ref mut simm32, .. } => *simm32 += offset,
477 _ => panic!("Cannot offset amode: {self:?}"),
478 }
479 ret
480 }
481
482 pub(crate) fn aligned(&self) -> bool {
483 self.get_flags().aligned()
484 }
485}
486
487impl PrettyPrint for Amode {
488 fn pretty_print(&self, _size: u8) -> String {
489 match self {
490 Amode::ImmReg { simm32, base, .. } => {
491 format!("{}({})", *simm32, pretty_print_reg(*base, 8))
494 }
495 Amode::ImmRegRegShift {
496 simm32,
497 base,
498 index,
499 shift,
500 ..
501 } => format!(
502 "{}({},{},{})",
503 *simm32,
504 pretty_print_reg(base.to_reg(), 8),
505 pretty_print_reg(index.to_reg(), 8),
506 1 << shift
507 ),
508 Amode::RipRelative { target } => format!("label{}(%rip)", target.as_u32()),
509 }
510 }
511}
512
513#[derive(Clone, Debug)]
517pub enum SyntheticAmode {
518 Real(Amode),
520
521 IncomingArg {
523 offset: u32,
525 },
526
527 SlotOffset {
530 simm32: i32,
532 },
533
534 ConstantOffset(VCodeConstant),
536}
537
538impl SyntheticAmode {
539 pub fn real(amode: Amode) -> Self {
541 Self::Real(amode)
542 }
543
544 pub(crate) fn slot_offset(simm32: i32) -> Self {
545 SyntheticAmode::SlotOffset { simm32 }
546 }
547
548 pub(crate) fn get_operands(&mut self, collector: &mut impl OperandVisitor) {
550 match self {
551 SyntheticAmode::Real(addr) => addr.get_operands(collector),
552 SyntheticAmode::IncomingArg { .. } => {
553 }
555 SyntheticAmode::SlotOffset { .. } => {
556 }
558 SyntheticAmode::ConstantOffset(_) => {}
559 }
560 }
561
562 pub(crate) fn get_operands_late(&mut self, collector: &mut impl OperandVisitor) {
564 match self {
565 SyntheticAmode::Real(addr) => addr.get_operands_late(collector),
566 SyntheticAmode::IncomingArg { .. } => {
567 }
569 SyntheticAmode::SlotOffset { .. } => {
570 }
572 SyntheticAmode::ConstantOffset(_) => {}
573 }
574 }
575
576 pub(crate) fn finalize(&self, frame: &FrameLayout, buffer: &mut MachBuffer<Inst>) -> Amode {
577 match self {
578 SyntheticAmode::Real(addr) => addr.clone(),
579 SyntheticAmode::IncomingArg { offset } => {
580 let args_max_fp_offset = frame.tail_args_size + frame.setup_area_size;
583 Amode::imm_reg(
584 i32::try_from(args_max_fp_offset - offset).unwrap(),
585 regs::rbp(),
586 )
587 }
588 SyntheticAmode::SlotOffset { simm32 } => {
589 let off = *simm32 as i64 + i64::from(frame.outgoing_args_size);
590 Amode::imm_reg(off.try_into().expect("invalid sp offset"), regs::rsp())
591 }
592 SyntheticAmode::ConstantOffset(c) => {
593 Amode::rip_relative(buffer.get_label_for_constant(*c))
594 }
595 }
596 }
597
598 pub(crate) fn aligned(&self) -> bool {
599 match self {
600 SyntheticAmode::Real(addr) => addr.aligned(),
601 &SyntheticAmode::IncomingArg { .. }
602 | SyntheticAmode::SlotOffset { .. }
603 | SyntheticAmode::ConstantOffset { .. } => true,
604 }
605 }
606}
607
608impl Into<SyntheticAmode> for Amode {
609 fn into(self) -> SyntheticAmode {
610 SyntheticAmode::Real(self)
611 }
612}
613
614impl Into<SyntheticAmode> for VCodeConstant {
615 fn into(self) -> SyntheticAmode {
616 SyntheticAmode::ConstantOffset(self)
617 }
618}
619
620impl PrettyPrint for SyntheticAmode {
621 fn pretty_print(&self, _size: u8) -> String {
622 match self {
623 SyntheticAmode::Real(addr) => addr.pretty_print(8),
625 &SyntheticAmode::IncomingArg { offset } => {
626 format!("rbp(stack args max - {offset})")
627 }
628 SyntheticAmode::SlotOffset { simm32 } => {
629 format!("rsp({} + virtual offset)", *simm32)
630 }
631 SyntheticAmode::ConstantOffset(c) => format!("const({})", c.as_u32()),
632 }
633 }
634}
635
636#[derive(Clone, Debug)]
641pub enum RegMemImm {
642 Reg {
644 reg: Reg,
646 },
647 Mem {
649 addr: SyntheticAmode,
651 },
652 Imm {
654 simm32: u32,
656 },
657}
658
659impl RegMemImm {
660 pub fn reg(reg: Reg) -> Self {
662 debug_assert!(reg.class() == RegClass::Int || reg.class() == RegClass::Float);
663 Self::Reg { reg }
664 }
665
666 pub fn mem(addr: impl Into<SyntheticAmode>) -> Self {
668 Self::Mem { addr: addr.into() }
669 }
670
671 pub fn imm(simm32: u32) -> Self {
673 Self::Imm { simm32 }
674 }
675
676 pub(crate) fn assert_regclass_is(&self, expected_reg_class: RegClass) {
678 if let Self::Reg { reg } = self {
679 debug_assert_eq!(reg.class(), expected_reg_class);
680 }
681 }
682
683 pub(crate) fn get_operands(&mut self, collector: &mut impl OperandVisitor) {
685 match self {
686 Self::Reg { reg } => collector.reg_use(reg),
687 Self::Mem { addr } => addr.get_operands(collector),
688 Self::Imm { .. } => {}
689 }
690 }
691}
692
693impl From<RegMem> for RegMemImm {
694 fn from(rm: RegMem) -> RegMemImm {
695 match rm {
696 RegMem::Reg { reg } => RegMemImm::Reg { reg },
697 RegMem::Mem { addr } => RegMemImm::Mem { addr },
698 }
699 }
700}
701
702impl From<Reg> for RegMemImm {
703 fn from(reg: Reg) -> Self {
704 RegMemImm::Reg { reg }
705 }
706}
707
708impl PrettyPrint for RegMemImm {
709 fn pretty_print(&self, size: u8) -> String {
710 match self {
711 Self::Reg { reg } => pretty_print_reg(*reg, size),
712 Self::Mem { addr } => addr.pretty_print(size),
713 Self::Imm { simm32 } => format!("${}", *simm32 as i32),
714 }
715 }
716}
717
718#[derive(Clone, Debug)]
720pub enum Imm8Reg {
721 Imm8 {
723 imm: u8,
725 },
726 Reg {
728 reg: Reg,
730 },
731}
732
733impl From<u8> for Imm8Reg {
734 fn from(imm: u8) -> Self {
735 Self::Imm8 { imm }
736 }
737}
738
739impl From<Reg> for Imm8Reg {
740 fn from(reg: Reg) -> Self {
741 Self::Reg { reg }
742 }
743}
744
745#[derive(Clone, Debug)]
748pub enum RegMem {
749 Reg {
751 reg: Reg,
753 },
754 Mem {
756 addr: SyntheticAmode,
758 },
759}
760
761impl RegMem {
762 pub fn reg(reg: Reg) -> Self {
764 debug_assert!(reg.class() == RegClass::Int || reg.class() == RegClass::Float);
765 Self::Reg { reg }
766 }
767
768 pub fn mem(addr: impl Into<SyntheticAmode>) -> Self {
770 Self::Mem { addr: addr.into() }
771 }
772 pub(crate) fn assert_regclass_is(&self, expected_reg_class: RegClass) {
774 if let Self::Reg { reg } = self {
775 debug_assert_eq!(reg.class(), expected_reg_class);
776 }
777 }
778 pub(crate) fn get_operands(&mut self, collector: &mut impl OperandVisitor) {
780 match self {
781 RegMem::Reg { reg } => collector.reg_use(reg),
782 RegMem::Mem { addr, .. } => addr.get_operands(collector),
783 }
784 }
785}
786
787impl From<Reg> for RegMem {
788 fn from(reg: Reg) -> RegMem {
789 RegMem::Reg { reg }
790 }
791}
792
793impl From<Writable<Reg>> for RegMem {
794 fn from(r: Writable<Reg>) -> Self {
795 RegMem::reg(r.to_reg())
796 }
797}
798
799impl PrettyPrint for RegMem {
800 fn pretty_print(&self, size: u8) -> String {
801 match self {
802 RegMem::Reg { reg } => pretty_print_reg(*reg, size),
803 RegMem::Mem { addr, .. } => addr.pretty_print(size),
804 }
805 }
806}
807
808pub use crate::isa::x64::lower::isle::generated_code::AluRmROpcode;
809
810impl AluRmROpcode {
811 pub(crate) fn available_from(&self) -> SmallVec<[InstructionSet; 2]> {
812 match self {
813 AluRmROpcode::Andn => smallvec![InstructionSet::BMI1],
814 AluRmROpcode::Sarx | AluRmROpcode::Shrx | AluRmROpcode::Shlx | AluRmROpcode::Bzhi => {
815 smallvec![InstructionSet::BMI2]
816 }
817 }
818 }
819}
820
821impl fmt::Display for AluRmROpcode {
822 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
823 f.write_str(&format!("{self:?}").to_lowercase())
824 }
825}
826
827#[derive(Clone, PartialEq)]
828pub enum UnaryRmROpcode {
830 Bsr,
832 Bsf,
834 Lzcnt,
836 Tzcnt,
838 Popcnt,
840}
841
842impl UnaryRmROpcode {
843 pub(crate) fn available_from(&self) -> SmallVec<[InstructionSet; 2]> {
844 match self {
845 UnaryRmROpcode::Bsr | UnaryRmROpcode::Bsf => smallvec![],
846 UnaryRmROpcode::Lzcnt => smallvec![InstructionSet::Lzcnt],
847 UnaryRmROpcode::Tzcnt => smallvec![InstructionSet::BMI1],
848 UnaryRmROpcode::Popcnt => smallvec![InstructionSet::Popcnt],
849 }
850 }
851}
852
853impl fmt::Debug for UnaryRmROpcode {
854 fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
855 match self {
856 UnaryRmROpcode::Bsr => write!(fmt, "bsr"),
857 UnaryRmROpcode::Bsf => write!(fmt, "bsf"),
858 UnaryRmROpcode::Lzcnt => write!(fmt, "lzcnt"),
859 UnaryRmROpcode::Tzcnt => write!(fmt, "tzcnt"),
860 UnaryRmROpcode::Popcnt => write!(fmt, "popcnt"),
861 }
862 }
863}
864
865impl fmt::Display for UnaryRmROpcode {
866 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
867 fmt::Debug::fmt(self, f)
868 }
869}
870
871pub use crate::isa::x64::lower::isle::generated_code::UnaryRmRVexOpcode;
872
873impl UnaryRmRVexOpcode {
874 pub(crate) fn available_from(&self) -> SmallVec<[InstructionSet; 2]> {
875 match self {
876 UnaryRmRVexOpcode::Blsi | UnaryRmRVexOpcode::Blsmsk | UnaryRmRVexOpcode::Blsr => {
877 smallvec![InstructionSet::BMI1]
878 }
879 }
880 }
881}
882
883impl fmt::Display for UnaryRmRVexOpcode {
884 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
885 f.write_str(&format!("{self:?}").to_lowercase())
886 }
887}
888
889pub use crate::isa::x64::lower::isle::generated_code::UnaryRmRImmVexOpcode;
890
891impl UnaryRmRImmVexOpcode {
892 pub(crate) fn available_from(&self) -> SmallVec<[InstructionSet; 2]> {
893 match self {
894 UnaryRmRImmVexOpcode::Rorx => {
895 smallvec![InstructionSet::BMI2]
896 }
897 }
898 }
899}
900
901impl fmt::Display for UnaryRmRImmVexOpcode {
902 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
903 f.write_str(&format!("{self:?}").to_lowercase())
904 }
905}
906
907#[derive(Clone, Copy, PartialEq)]
908pub enum CmpOpcode {
910 Cmp,
912 Test,
914}
915
916#[derive(Debug)]
917pub(crate) enum InstructionSet {
918 SSE,
919 SSE2,
920 CMPXCHG16b,
921 SSSE3,
922 SSE41,
923 SSE42,
924 Popcnt,
925 Lzcnt,
926 BMI1,
927 #[allow(dead_code)] BMI2,
929 FMA,
930 AVX,
931 AVX2,
932 AVX512BITALG,
933 AVX512DQ,
934 AVX512F,
935 AVX512VBMI,
936 AVX512VL,
937}
938
939#[derive(Clone, Copy, PartialEq)]
941#[allow(dead_code)] #[allow(missing_docs)]
943pub enum SseOpcode {
944 Blendvpd,
945 Blendvps,
946 Comiss,
947 Comisd,
948 Cmpps,
949 Cmppd,
950 Cmpss,
951 Cmpsd,
952 Cvtdq2ps,
953 Cvtdq2pd,
954 Cvtpd2ps,
955 Cvtps2pd,
956 Cvtsd2ss,
957 Cvtsd2si,
958 Cvtsi2ss,
959 Cvtsi2sd,
960 Cvtss2si,
961 Cvtss2sd,
962 Cvttpd2dq,
963 Cvttps2dq,
964 Cvttss2si,
965 Cvttsd2si,
966 Divps,
967 Divpd,
968 Divss,
969 Divsd,
970 Insertps,
971 Maxps,
972 Maxpd,
973 Maxss,
974 Maxsd,
975 Minps,
976 Minpd,
977 Minss,
978 Minsd,
979 Movaps,
980 Movapd,
981 Movd,
982 Movdqa,
983 Movdqu,
984 Movlhps,
985 Movmskps,
986 Movmskpd,
987 Movq,
988 Movss,
989 Movsd,
990 Movups,
991 Movupd,
992 Mulps,
993 Mulpd,
994 Mulss,
995 Mulsd,
996 Pabsb,
997 Pabsw,
998 Pabsd,
999 Packssdw,
1000 Packsswb,
1001 Packusdw,
1002 Packuswb,
1003 Palignr,
1004 Pavgb,
1005 Pavgw,
1006 Pblendvb,
1007 Pcmpeqb,
1008 Pcmpeqw,
1009 Pcmpeqd,
1010 Pcmpeqq,
1011 Pcmpgtb,
1012 Pcmpgtw,
1013 Pcmpgtd,
1014 Pcmpgtq,
1015 Pextrb,
1016 Pextrw,
1017 Pextrd,
1018 Pextrq,
1019 Pinsrb,
1020 Pinsrw,
1021 Pinsrd,
1022 Pmaddubsw,
1023 Pmaddwd,
1024 Pmaxsb,
1025 Pmaxsw,
1026 Pmaxsd,
1027 Pmaxub,
1028 Pmaxuw,
1029 Pmaxud,
1030 Pminsb,
1031 Pminsw,
1032 Pminsd,
1033 Pminub,
1034 Pminuw,
1035 Pminud,
1036 Pmovmskb,
1037 Pmovsxbd,
1038 Pmovsxbw,
1039 Pmovsxbq,
1040 Pmovsxwd,
1041 Pmovsxwq,
1042 Pmovsxdq,
1043 Pmovzxbd,
1044 Pmovzxbw,
1045 Pmovzxbq,
1046 Pmovzxwd,
1047 Pmovzxwq,
1048 Pmovzxdq,
1049 Pmuldq,
1050 Pmulhw,
1051 Pmulhuw,
1052 Pmulhrsw,
1053 Pmulld,
1054 Pmullw,
1055 Pmuludq,
1056 Pshufb,
1057 Pshufd,
1058 Psllw,
1059 Pslld,
1060 Psllq,
1061 Psraw,
1062 Psrad,
1063 Psrlw,
1064 Psrld,
1065 Psrlq,
1066 Ptest,
1067 Punpckhbw,
1068 Punpckhwd,
1069 Punpcklbw,
1070 Punpcklwd,
1071 Rcpss,
1072 Roundps,
1073 Roundpd,
1074 Roundss,
1075 Roundsd,
1076 Rsqrtss,
1077 Shufps,
1078 Sqrtps,
1079 Sqrtpd,
1080 Sqrtss,
1081 Sqrtsd,
1082 Ucomiss,
1083 Ucomisd,
1084 Unpcklps,
1085 Unpcklpd,
1086 Unpckhps,
1087 Punpckhdq,
1088 Punpckldq,
1089 Punpckhqdq,
1090 Punpcklqdq,
1091 Pshuflw,
1092 Pshufhw,
1093 Pblendw,
1094 Movddup,
1095}
1096
1097impl SseOpcode {
1098 pub(crate) fn available_from(&self) -> InstructionSet {
1100 use InstructionSet::*;
1101 match self {
1102 SseOpcode::Comiss
1103 | SseOpcode::Cmpps
1104 | SseOpcode::Cmpss
1105 | SseOpcode::Cvtsi2ss
1106 | SseOpcode::Cvtss2si
1107 | SseOpcode::Cvttss2si
1108 | SseOpcode::Divps
1109 | SseOpcode::Divss
1110 | SseOpcode::Maxps
1111 | SseOpcode::Maxss
1112 | SseOpcode::Minps
1113 | SseOpcode::Minss
1114 | SseOpcode::Movaps
1115 | SseOpcode::Movlhps
1116 | SseOpcode::Movmskps
1117 | SseOpcode::Movss
1118 | SseOpcode::Movups
1119 | SseOpcode::Mulps
1120 | SseOpcode::Mulss
1121 | SseOpcode::Rcpss
1122 | SseOpcode::Rsqrtss
1123 | SseOpcode::Shufps
1124 | SseOpcode::Sqrtps
1125 | SseOpcode::Sqrtss
1126 | SseOpcode::Ucomiss
1127 | SseOpcode::Unpcklps
1128 | SseOpcode::Unpckhps => SSE,
1129
1130 SseOpcode::Cmppd
1131 | SseOpcode::Cmpsd
1132 | SseOpcode::Comisd
1133 | SseOpcode::Cvtdq2ps
1134 | SseOpcode::Cvtdq2pd
1135 | SseOpcode::Cvtpd2ps
1136 | SseOpcode::Cvtps2pd
1137 | SseOpcode::Cvtsd2ss
1138 | SseOpcode::Cvtsd2si
1139 | SseOpcode::Cvtsi2sd
1140 | SseOpcode::Cvtss2sd
1141 | SseOpcode::Cvttpd2dq
1142 | SseOpcode::Cvttps2dq
1143 | SseOpcode::Cvttsd2si
1144 | SseOpcode::Divpd
1145 | SseOpcode::Divsd
1146 | SseOpcode::Maxpd
1147 | SseOpcode::Maxsd
1148 | SseOpcode::Minpd
1149 | SseOpcode::Minsd
1150 | SseOpcode::Movapd
1151 | SseOpcode::Movd
1152 | SseOpcode::Movmskpd
1153 | SseOpcode::Movq
1154 | SseOpcode::Movsd
1155 | SseOpcode::Movupd
1156 | SseOpcode::Movdqa
1157 | SseOpcode::Movdqu
1158 | SseOpcode::Mulpd
1159 | SseOpcode::Mulsd
1160 | SseOpcode::Packssdw
1161 | SseOpcode::Packsswb
1162 | SseOpcode::Packuswb
1163 | SseOpcode::Pavgb
1164 | SseOpcode::Pavgw
1165 | SseOpcode::Pcmpeqb
1166 | SseOpcode::Pcmpeqw
1167 | SseOpcode::Pcmpeqd
1168 | SseOpcode::Pcmpgtb
1169 | SseOpcode::Pcmpgtw
1170 | SseOpcode::Pcmpgtd
1171 | SseOpcode::Pextrw
1172 | SseOpcode::Pinsrw
1173 | SseOpcode::Pmaddwd
1174 | SseOpcode::Pmaxsw
1175 | SseOpcode::Pmaxub
1176 | SseOpcode::Pminsw
1177 | SseOpcode::Pminub
1178 | SseOpcode::Pmovmskb
1179 | SseOpcode::Pmulhw
1180 | SseOpcode::Pmulhuw
1181 | SseOpcode::Pmullw
1182 | SseOpcode::Pmuludq
1183 | SseOpcode::Pshufd
1184 | SseOpcode::Psllw
1185 | SseOpcode::Pslld
1186 | SseOpcode::Psllq
1187 | SseOpcode::Psraw
1188 | SseOpcode::Psrad
1189 | SseOpcode::Psrlw
1190 | SseOpcode::Psrld
1191 | SseOpcode::Psrlq
1192 | SseOpcode::Punpckhbw
1193 | SseOpcode::Punpckhwd
1194 | SseOpcode::Punpcklbw
1195 | SseOpcode::Punpcklwd
1196 | SseOpcode::Sqrtpd
1197 | SseOpcode::Sqrtsd
1198 | SseOpcode::Ucomisd
1199 | SseOpcode::Punpckldq
1200 | SseOpcode::Punpckhdq
1201 | SseOpcode::Punpcklqdq
1202 | SseOpcode::Punpckhqdq
1203 | SseOpcode::Pshuflw
1204 | SseOpcode::Pshufhw
1205 | SseOpcode::Unpcklpd => SSE2,
1206
1207 SseOpcode::Pabsb
1208 | SseOpcode::Pabsw
1209 | SseOpcode::Pabsd
1210 | SseOpcode::Palignr
1211 | SseOpcode::Pmulhrsw
1212 | SseOpcode::Pshufb
1213 | SseOpcode::Pmaddubsw
1214 | SseOpcode::Movddup => SSSE3,
1215
1216 SseOpcode::Blendvpd
1217 | SseOpcode::Blendvps
1218 | SseOpcode::Insertps
1219 | SseOpcode::Packusdw
1220 | SseOpcode::Pblendvb
1221 | SseOpcode::Pcmpeqq
1222 | SseOpcode::Pextrb
1223 | SseOpcode::Pextrd
1224 | SseOpcode::Pextrq
1225 | SseOpcode::Pinsrb
1226 | SseOpcode::Pinsrd
1227 | SseOpcode::Pmaxsb
1228 | SseOpcode::Pmaxsd
1229 | SseOpcode::Pmaxuw
1230 | SseOpcode::Pmaxud
1231 | SseOpcode::Pminsb
1232 | SseOpcode::Pminsd
1233 | SseOpcode::Pminuw
1234 | SseOpcode::Pminud
1235 | SseOpcode::Pmovsxbd
1236 | SseOpcode::Pmovsxbw
1237 | SseOpcode::Pmovsxbq
1238 | SseOpcode::Pmovsxwd
1239 | SseOpcode::Pmovsxwq
1240 | SseOpcode::Pmovsxdq
1241 | SseOpcode::Pmovzxbd
1242 | SseOpcode::Pmovzxbw
1243 | SseOpcode::Pmovzxbq
1244 | SseOpcode::Pmovzxwd
1245 | SseOpcode::Pmovzxwq
1246 | SseOpcode::Pmovzxdq
1247 | SseOpcode::Pmuldq
1248 | SseOpcode::Pmulld
1249 | SseOpcode::Ptest
1250 | SseOpcode::Roundps
1251 | SseOpcode::Roundpd
1252 | SseOpcode::Roundss
1253 | SseOpcode::Roundsd
1254 | SseOpcode::Pblendw => SSE41,
1255
1256 SseOpcode::Pcmpgtq => SSE42,
1257 }
1258 }
1259
1260 pub(crate) fn src_size(&self) -> u8 {
1262 match self {
1263 SseOpcode::Movd => 4,
1264 _ => 8,
1265 }
1266 }
1267
1268 pub(crate) fn has_scalar_src2(self) -> bool {
1270 match self {
1271 SseOpcode::Pinsrb | SseOpcode::Pinsrw | SseOpcode::Pinsrd => true,
1272 SseOpcode::Pmovsxbw
1273 | SseOpcode::Pmovsxbd
1274 | SseOpcode::Pmovsxbq
1275 | SseOpcode::Pmovsxwd
1276 | SseOpcode::Pmovsxwq
1277 | SseOpcode::Pmovsxdq => true,
1278 SseOpcode::Pmovzxbw
1279 | SseOpcode::Pmovzxbd
1280 | SseOpcode::Pmovzxbq
1281 | SseOpcode::Pmovzxwd
1282 | SseOpcode::Pmovzxwq
1283 | SseOpcode::Pmovzxdq => true,
1284 _ => false,
1285 }
1286 }
1287}
1288
1289impl fmt::Debug for SseOpcode {
1290 fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
1291 let name = match self {
1292 SseOpcode::Blendvpd => "blendvpd",
1293 SseOpcode::Blendvps => "blendvps",
1294 SseOpcode::Cmpps => "cmpps",
1295 SseOpcode::Cmppd => "cmppd",
1296 SseOpcode::Cmpss => "cmpss",
1297 SseOpcode::Cmpsd => "cmpsd",
1298 SseOpcode::Comiss => "comiss",
1299 SseOpcode::Comisd => "comisd",
1300 SseOpcode::Cvtdq2ps => "cvtdq2ps",
1301 SseOpcode::Cvtdq2pd => "cvtdq2pd",
1302 SseOpcode::Cvtpd2ps => "cvtpd2ps",
1303 SseOpcode::Cvtps2pd => "cvtps2pd",
1304 SseOpcode::Cvtsd2ss => "cvtsd2ss",
1305 SseOpcode::Cvtsd2si => "cvtsd2si",
1306 SseOpcode::Cvtsi2ss => "cvtsi2ss",
1307 SseOpcode::Cvtsi2sd => "cvtsi2sd",
1308 SseOpcode::Cvtss2si => "cvtss2si",
1309 SseOpcode::Cvtss2sd => "cvtss2sd",
1310 SseOpcode::Cvttpd2dq => "cvttpd2dq",
1311 SseOpcode::Cvttps2dq => "cvttps2dq",
1312 SseOpcode::Cvttss2si => "cvttss2si",
1313 SseOpcode::Cvttsd2si => "cvttsd2si",
1314 SseOpcode::Divps => "divps",
1315 SseOpcode::Divpd => "divpd",
1316 SseOpcode::Divss => "divss",
1317 SseOpcode::Divsd => "divsd",
1318 SseOpcode::Insertps => "insertps",
1319 SseOpcode::Maxps => "maxps",
1320 SseOpcode::Maxpd => "maxpd",
1321 SseOpcode::Maxss => "maxss",
1322 SseOpcode::Maxsd => "maxsd",
1323 SseOpcode::Minps => "minps",
1324 SseOpcode::Minpd => "minpd",
1325 SseOpcode::Minss => "minss",
1326 SseOpcode::Minsd => "minsd",
1327 SseOpcode::Movaps => "movaps",
1328 SseOpcode::Movapd => "movapd",
1329 SseOpcode::Movd => "movd",
1330 SseOpcode::Movdqa => "movdqa",
1331 SseOpcode::Movdqu => "movdqu",
1332 SseOpcode::Movlhps => "movlhps",
1333 SseOpcode::Movmskps => "movmskps",
1334 SseOpcode::Movmskpd => "movmskpd",
1335 SseOpcode::Movq => "movq",
1336 SseOpcode::Movss => "movss",
1337 SseOpcode::Movsd => "movsd",
1338 SseOpcode::Movups => "movups",
1339 SseOpcode::Movupd => "movupd",
1340 SseOpcode::Mulps => "mulps",
1341 SseOpcode::Mulpd => "mulpd",
1342 SseOpcode::Mulss => "mulss",
1343 SseOpcode::Mulsd => "mulsd",
1344 SseOpcode::Pabsb => "pabsb",
1345 SseOpcode::Pabsw => "pabsw",
1346 SseOpcode::Pabsd => "pabsd",
1347 SseOpcode::Packssdw => "packssdw",
1348 SseOpcode::Packsswb => "packsswb",
1349 SseOpcode::Packusdw => "packusdw",
1350 SseOpcode::Packuswb => "packuswb",
1351 SseOpcode::Palignr => "palignr",
1352 SseOpcode::Pavgb => "pavgb",
1353 SseOpcode::Pavgw => "pavgw",
1354 SseOpcode::Pblendvb => "pblendvb",
1355 SseOpcode::Pcmpeqb => "pcmpeqb",
1356 SseOpcode::Pcmpeqw => "pcmpeqw",
1357 SseOpcode::Pcmpeqd => "pcmpeqd",
1358 SseOpcode::Pcmpeqq => "pcmpeqq",
1359 SseOpcode::Pcmpgtb => "pcmpgtb",
1360 SseOpcode::Pcmpgtw => "pcmpgtw",
1361 SseOpcode::Pcmpgtd => "pcmpgtd",
1362 SseOpcode::Pcmpgtq => "pcmpgtq",
1363 SseOpcode::Pextrb => "pextrb",
1364 SseOpcode::Pextrw => "pextrw",
1365 SseOpcode::Pextrd => "pextrd",
1366 SseOpcode::Pextrq => "pextrq",
1367 SseOpcode::Pinsrb => "pinsrb",
1368 SseOpcode::Pinsrw => "pinsrw",
1369 SseOpcode::Pinsrd => "pinsrd",
1370 SseOpcode::Pmaddubsw => "pmaddubsw",
1371 SseOpcode::Pmaddwd => "pmaddwd",
1372 SseOpcode::Pmaxsb => "pmaxsb",
1373 SseOpcode::Pmaxsw => "pmaxsw",
1374 SseOpcode::Pmaxsd => "pmaxsd",
1375 SseOpcode::Pmaxub => "pmaxub",
1376 SseOpcode::Pmaxuw => "pmaxuw",
1377 SseOpcode::Pmaxud => "pmaxud",
1378 SseOpcode::Pminsb => "pminsb",
1379 SseOpcode::Pminsw => "pminsw",
1380 SseOpcode::Pminsd => "pminsd",
1381 SseOpcode::Pminub => "pminub",
1382 SseOpcode::Pminuw => "pminuw",
1383 SseOpcode::Pminud => "pminud",
1384 SseOpcode::Pmovmskb => "pmovmskb",
1385 SseOpcode::Pmovsxbd => "pmovsxbd",
1386 SseOpcode::Pmovsxbw => "pmovsxbw",
1387 SseOpcode::Pmovsxbq => "pmovsxbq",
1388 SseOpcode::Pmovsxwd => "pmovsxwd",
1389 SseOpcode::Pmovsxwq => "pmovsxwq",
1390 SseOpcode::Pmovsxdq => "pmovsxdq",
1391 SseOpcode::Pmovzxbd => "pmovzxbd",
1392 SseOpcode::Pmovzxbw => "pmovzxbw",
1393 SseOpcode::Pmovzxbq => "pmovzxbq",
1394 SseOpcode::Pmovzxwd => "pmovzxwd",
1395 SseOpcode::Pmovzxwq => "pmovzxwq",
1396 SseOpcode::Pmovzxdq => "pmovzxdq",
1397 SseOpcode::Pmuldq => "pmuldq",
1398 SseOpcode::Pmulhw => "pmulhw",
1399 SseOpcode::Pmulhuw => "pmulhuw",
1400 SseOpcode::Pmulhrsw => "pmulhrsw",
1401 SseOpcode::Pmulld => "pmulld",
1402 SseOpcode::Pmullw => "pmullw",
1403 SseOpcode::Pmuludq => "pmuludq",
1404 SseOpcode::Pshufb => "pshufb",
1405 SseOpcode::Pshufd => "pshufd",
1406 SseOpcode::Psllw => "psllw",
1407 SseOpcode::Pslld => "pslld",
1408 SseOpcode::Psllq => "psllq",
1409 SseOpcode::Psraw => "psraw",
1410 SseOpcode::Psrad => "psrad",
1411 SseOpcode::Psrlw => "psrlw",
1412 SseOpcode::Psrld => "psrld",
1413 SseOpcode::Psrlq => "psrlq",
1414 SseOpcode::Ptest => "ptest",
1415 SseOpcode::Punpckhbw => "punpckhbw",
1416 SseOpcode::Punpckhwd => "punpckhwd",
1417 SseOpcode::Punpcklbw => "punpcklbw",
1418 SseOpcode::Punpcklwd => "punpcklwd",
1419 SseOpcode::Rcpss => "rcpss",
1420 SseOpcode::Roundps => "roundps",
1421 SseOpcode::Roundpd => "roundpd",
1422 SseOpcode::Roundss => "roundss",
1423 SseOpcode::Roundsd => "roundsd",
1424 SseOpcode::Rsqrtss => "rsqrtss",
1425 SseOpcode::Shufps => "shufps",
1426 SseOpcode::Sqrtps => "sqrtps",
1427 SseOpcode::Sqrtpd => "sqrtpd",
1428 SseOpcode::Sqrtss => "sqrtss",
1429 SseOpcode::Sqrtsd => "sqrtsd",
1430 SseOpcode::Ucomiss => "ucomiss",
1431 SseOpcode::Ucomisd => "ucomisd",
1432 SseOpcode::Unpcklps => "unpcklps",
1433 SseOpcode::Unpckhps => "unpckhps",
1434 SseOpcode::Punpckldq => "punpckldq",
1435 SseOpcode::Punpckhdq => "punpckhdq",
1436 SseOpcode::Punpcklqdq => "punpcklqdq",
1437 SseOpcode::Punpckhqdq => "punpckhqdq",
1438 SseOpcode::Pshuflw => "pshuflw",
1439 SseOpcode::Pshufhw => "pshufhw",
1440 SseOpcode::Pblendw => "pblendw",
1441 SseOpcode::Movddup => "movddup",
1442 SseOpcode::Unpcklpd => "unpcklpd",
1443 };
1444 write!(fmt, "{name}")
1445 }
1446}
1447
1448impl fmt::Display for SseOpcode {
1449 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1450 fmt::Debug::fmt(self, f)
1451 }
1452}
1453
1454pub use crate::isa::x64::lower::isle::generated_code::AvxOpcode;
1455
1456impl AvxOpcode {
1457 pub(crate) fn available_from(&self) -> SmallVec<[InstructionSet; 2]> {
1459 match self {
1460 AvxOpcode::Vfmadd213ss
1461 | AvxOpcode::Vfmadd213sd
1462 | AvxOpcode::Vfmadd213ps
1463 | AvxOpcode::Vfmadd213pd
1464 | AvxOpcode::Vfmadd132ss
1465 | AvxOpcode::Vfmadd132sd
1466 | AvxOpcode::Vfmadd132ps
1467 | AvxOpcode::Vfmadd132pd
1468 | AvxOpcode::Vfnmadd213ss
1469 | AvxOpcode::Vfnmadd213sd
1470 | AvxOpcode::Vfnmadd213ps
1471 | AvxOpcode::Vfnmadd213pd
1472 | AvxOpcode::Vfnmadd132ss
1473 | AvxOpcode::Vfnmadd132sd
1474 | AvxOpcode::Vfnmadd132ps
1475 | AvxOpcode::Vfnmadd132pd
1476 | AvxOpcode::Vfmsub213ss
1477 | AvxOpcode::Vfmsub213sd
1478 | AvxOpcode::Vfmsub213ps
1479 | AvxOpcode::Vfmsub213pd
1480 | AvxOpcode::Vfmsub132ss
1481 | AvxOpcode::Vfmsub132sd
1482 | AvxOpcode::Vfmsub132ps
1483 | AvxOpcode::Vfmsub132pd
1484 | AvxOpcode::Vfnmsub213ss
1485 | AvxOpcode::Vfnmsub213sd
1486 | AvxOpcode::Vfnmsub213ps
1487 | AvxOpcode::Vfnmsub213pd
1488 | AvxOpcode::Vfnmsub132ss
1489 | AvxOpcode::Vfnmsub132sd
1490 | AvxOpcode::Vfnmsub132ps
1491 | AvxOpcode::Vfnmsub132pd => smallvec![InstructionSet::FMA],
1492 AvxOpcode::Vminps
1493 | AvxOpcode::Vminpd
1494 | AvxOpcode::Vmaxps
1495 | AvxOpcode::Vmaxpd
1496 | AvxOpcode::Vandnps
1497 | AvxOpcode::Vandnpd
1498 | AvxOpcode::Vpandn
1499 | AvxOpcode::Vcmpps
1500 | AvxOpcode::Vcmppd
1501 | AvxOpcode::Vpsrlw
1502 | AvxOpcode::Vpsrld
1503 | AvxOpcode::Vpsrlq
1504 | AvxOpcode::Vpaddb
1505 | AvxOpcode::Vpaddw
1506 | AvxOpcode::Vpaddd
1507 | AvxOpcode::Vpaddq
1508 | AvxOpcode::Vpaddsb
1509 | AvxOpcode::Vpaddsw
1510 | AvxOpcode::Vpaddusb
1511 | AvxOpcode::Vpaddusw
1512 | AvxOpcode::Vpsubb
1513 | AvxOpcode::Vpsubw
1514 | AvxOpcode::Vpsubd
1515 | AvxOpcode::Vpsubq
1516 | AvxOpcode::Vpsubsb
1517 | AvxOpcode::Vpsubsw
1518 | AvxOpcode::Vpsubusb
1519 | AvxOpcode::Vpsubusw
1520 | AvxOpcode::Vpavgb
1521 | AvxOpcode::Vpavgw
1522 | AvxOpcode::Vpand
1523 | AvxOpcode::Vandps
1524 | AvxOpcode::Vandpd
1525 | AvxOpcode::Vpor
1526 | AvxOpcode::Vorps
1527 | AvxOpcode::Vorpd
1528 | AvxOpcode::Vpxor
1529 | AvxOpcode::Vxorps
1530 | AvxOpcode::Vxorpd
1531 | AvxOpcode::Vpmullw
1532 | AvxOpcode::Vpmulld
1533 | AvxOpcode::Vpmulhw
1534 | AvxOpcode::Vpmulhd
1535 | AvxOpcode::Vpmulhrsw
1536 | AvxOpcode::Vpmulhuw
1537 | AvxOpcode::Vpmuldq
1538 | AvxOpcode::Vpmuludq
1539 | AvxOpcode::Vpunpckhwd
1540 | AvxOpcode::Vpunpcklwd
1541 | AvxOpcode::Vunpcklps
1542 | AvxOpcode::Vunpckhps
1543 | AvxOpcode::Vaddps
1544 | AvxOpcode::Vaddpd
1545 | AvxOpcode::Vsubps
1546 | AvxOpcode::Vsubpd
1547 | AvxOpcode::Vmulps
1548 | AvxOpcode::Vmulpd
1549 | AvxOpcode::Vdivps
1550 | AvxOpcode::Vdivpd
1551 | AvxOpcode::Vpcmpeqb
1552 | AvxOpcode::Vpcmpeqw
1553 | AvxOpcode::Vpcmpeqd
1554 | AvxOpcode::Vpcmpeqq
1555 | AvxOpcode::Vpcmpgtb
1556 | AvxOpcode::Vpcmpgtw
1557 | AvxOpcode::Vpcmpgtd
1558 | AvxOpcode::Vpcmpgtq
1559 | AvxOpcode::Vblendvps
1560 | AvxOpcode::Vblendvpd
1561 | AvxOpcode::Vpblendvb
1562 | AvxOpcode::Vmovlhps
1563 | AvxOpcode::Vpminsb
1564 | AvxOpcode::Vpminsw
1565 | AvxOpcode::Vpminsd
1566 | AvxOpcode::Vpminub
1567 | AvxOpcode::Vpminuw
1568 | AvxOpcode::Vpminud
1569 | AvxOpcode::Vpmaxsb
1570 | AvxOpcode::Vpmaxsw
1571 | AvxOpcode::Vpmaxsd
1572 | AvxOpcode::Vpmaxub
1573 | AvxOpcode::Vpmaxuw
1574 | AvxOpcode::Vpmaxud
1575 | AvxOpcode::Vpunpcklbw
1576 | AvxOpcode::Vpunpckhbw
1577 | AvxOpcode::Vpacksswb
1578 | AvxOpcode::Vpackssdw
1579 | AvxOpcode::Vpackuswb
1580 | AvxOpcode::Vpackusdw
1581 | AvxOpcode::Vpalignr
1582 | AvxOpcode::Vpinsrb
1583 | AvxOpcode::Vpinsrw
1584 | AvxOpcode::Vpinsrd
1585 | AvxOpcode::Vpinsrq
1586 | AvxOpcode::Vpmaddwd
1587 | AvxOpcode::Vpmaddubsw
1588 | AvxOpcode::Vinsertps
1589 | AvxOpcode::Vpshufb
1590 | AvxOpcode::Vshufps
1591 | AvxOpcode::Vpsllw
1592 | AvxOpcode::Vpslld
1593 | AvxOpcode::Vpsllq
1594 | AvxOpcode::Vpsraw
1595 | AvxOpcode::Vpsrad
1596 | AvxOpcode::Vpmovsxbw
1597 | AvxOpcode::Vpmovzxbw
1598 | AvxOpcode::Vpmovsxwd
1599 | AvxOpcode::Vpmovzxwd
1600 | AvxOpcode::Vpmovsxdq
1601 | AvxOpcode::Vpmovzxdq
1602 | AvxOpcode::Vaddss
1603 | AvxOpcode::Vaddsd
1604 | AvxOpcode::Vmulss
1605 | AvxOpcode::Vmulsd
1606 | AvxOpcode::Vsubss
1607 | AvxOpcode::Vsubsd
1608 | AvxOpcode::Vdivss
1609 | AvxOpcode::Vdivsd
1610 | AvxOpcode::Vpabsb
1611 | AvxOpcode::Vpabsw
1612 | AvxOpcode::Vpabsd
1613 | AvxOpcode::Vminss
1614 | AvxOpcode::Vminsd
1615 | AvxOpcode::Vmaxss
1616 | AvxOpcode::Vmaxsd
1617 | AvxOpcode::Vsqrtps
1618 | AvxOpcode::Vsqrtpd
1619 | AvxOpcode::Vroundpd
1620 | AvxOpcode::Vroundps
1621 | AvxOpcode::Vcvtdq2pd
1622 | AvxOpcode::Vcvtdq2ps
1623 | AvxOpcode::Vcvtpd2ps
1624 | AvxOpcode::Vcvtps2pd
1625 | AvxOpcode::Vcvttpd2dq
1626 | AvxOpcode::Vcvttps2dq
1627 | AvxOpcode::Vphaddw
1628 | AvxOpcode::Vphaddd
1629 | AvxOpcode::Vpunpckldq
1630 | AvxOpcode::Vpunpckhdq
1631 | AvxOpcode::Vpunpcklqdq
1632 | AvxOpcode::Vpunpckhqdq
1633 | AvxOpcode::Vpshuflw
1634 | AvxOpcode::Vpshufhw
1635 | AvxOpcode::Vpshufd
1636 | AvxOpcode::Vmovss
1637 | AvxOpcode::Vmovsd
1638 | AvxOpcode::Vmovups
1639 | AvxOpcode::Vmovupd
1640 | AvxOpcode::Vmovdqu
1641 | AvxOpcode::Vpextrb
1642 | AvxOpcode::Vpextrw
1643 | AvxOpcode::Vpextrd
1644 | AvxOpcode::Vpextrq
1645 | AvxOpcode::Vpblendw
1646 | AvxOpcode::Vmovddup
1647 | AvxOpcode::Vbroadcastss
1648 | AvxOpcode::Vmovd
1649 | AvxOpcode::Vmovq
1650 | AvxOpcode::Vmovmskps
1651 | AvxOpcode::Vmovmskpd
1652 | AvxOpcode::Vpmovmskb
1653 | AvxOpcode::Vcvtsi2ss
1654 | AvxOpcode::Vcvtsi2sd
1655 | AvxOpcode::Vcvtss2sd
1656 | AvxOpcode::Vcvtsd2ss
1657 | AvxOpcode::Vsqrtss
1658 | AvxOpcode::Vsqrtsd
1659 | AvxOpcode::Vroundss
1660 | AvxOpcode::Vroundsd
1661 | AvxOpcode::Vunpcklpd
1662 | AvxOpcode::Vptest
1663 | AvxOpcode::Vucomiss
1664 | AvxOpcode::Vucomisd => {
1665 smallvec![InstructionSet::AVX]
1666 }
1667
1668 AvxOpcode::Vpbroadcastb | AvxOpcode::Vpbroadcastw | AvxOpcode::Vpbroadcastd => {
1669 smallvec![InstructionSet::AVX2]
1670 }
1671 }
1672 }
1673
1674 pub(crate) fn is_commutative(&self) -> bool {
1679 match *self {
1680 AvxOpcode::Vpaddb
1681 | AvxOpcode::Vpaddw
1682 | AvxOpcode::Vpaddd
1683 | AvxOpcode::Vpaddq
1684 | AvxOpcode::Vpaddsb
1685 | AvxOpcode::Vpaddsw
1686 | AvxOpcode::Vpaddusb
1687 | AvxOpcode::Vpaddusw
1688 | AvxOpcode::Vpand
1689 | AvxOpcode::Vandps
1690 | AvxOpcode::Vandpd
1691 | AvxOpcode::Vpor
1692 | AvxOpcode::Vorps
1693 | AvxOpcode::Vorpd
1694 | AvxOpcode::Vpxor
1695 | AvxOpcode::Vxorps
1696 | AvxOpcode::Vxorpd
1697 | AvxOpcode::Vpmuldq
1698 | AvxOpcode::Vpmuludq
1699 | AvxOpcode::Vaddps
1700 | AvxOpcode::Vaddpd
1701 | AvxOpcode::Vmulps
1702 | AvxOpcode::Vmulpd
1703 | AvxOpcode::Vpcmpeqb
1704 | AvxOpcode::Vpcmpeqw
1705 | AvxOpcode::Vpcmpeqd
1706 | AvxOpcode::Vpcmpeqq
1707 | AvxOpcode::Vaddss
1708 | AvxOpcode::Vaddsd
1709 | AvxOpcode::Vmulss
1710 | AvxOpcode::Vmulsd => true,
1711 _ => false,
1712 }
1713 }
1714}
1715
1716impl fmt::Display for AvxOpcode {
1717 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1718 format!("{self:?}").to_lowercase().fmt(f)
1719 }
1720}
1721
1722#[derive(Copy, Clone, PartialEq)]
1723#[allow(missing_docs)]
1724pub enum Avx512TupleType {
1725 Full,
1726 FullMem,
1727 Mem128,
1728}
1729
1730pub use crate::isa::x64::lower::isle::generated_code::Avx512Opcode;
1731
1732impl Avx512Opcode {
1733 pub(crate) fn available_from(&self) -> SmallVec<[InstructionSet; 2]> {
1735 match self {
1736 Avx512Opcode::Vcvtudq2ps
1737 | Avx512Opcode::Vpabsq
1738 | Avx512Opcode::Vpsraq
1739 | Avx512Opcode::VpsraqImm => {
1740 smallvec![InstructionSet::AVX512F, InstructionSet::AVX512VL]
1741 }
1742 Avx512Opcode::Vpermi2b => {
1743 smallvec![InstructionSet::AVX512VL, InstructionSet::AVX512VBMI]
1744 }
1745 Avx512Opcode::Vpmullq => smallvec![InstructionSet::AVX512VL, InstructionSet::AVX512DQ],
1746 Avx512Opcode::Vpopcntb => {
1747 smallvec![InstructionSet::AVX512VL, InstructionSet::AVX512BITALG]
1748 }
1749 }
1750 }
1751
1752 pub fn tuple_type(&self) -> Avx512TupleType {
1759 use Avx512Opcode::*;
1760 use Avx512TupleType::*;
1761
1762 match self {
1763 Vcvtudq2ps | Vpabsq | Vpmullq | VpsraqImm => Full,
1764 Vpermi2b | Vpopcntb => FullMem,
1765 Vpsraq => Mem128,
1766 }
1767 }
1768}
1769
1770impl fmt::Display for Avx512Opcode {
1771 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1772 let s = format!("{self:?}");
1773 f.write_str(&s.to_lowercase())
1774 }
1775}
1776
1777#[allow(dead_code)]
1781#[derive(Clone, PartialEq)]
1782pub enum ExtKind {
1783 None,
1785 SignExtend,
1787 ZeroExtend,
1789}
1790
1791#[derive(Clone, PartialEq)]
1794pub enum ExtMode {
1795 BL,
1797 BQ,
1799 WL,
1801 WQ,
1803 LQ,
1805}
1806
1807impl ExtMode {
1808 pub(crate) fn new(from_bits: u16, to_bits: u16) -> Option<ExtMode> {
1810 match (from_bits, to_bits) {
1811 (1, 8) | (1, 16) | (1, 32) | (8, 16) | (8, 32) => Some(ExtMode::BL),
1812 (1, 64) | (8, 64) => Some(ExtMode::BQ),
1813 (16, 32) => Some(ExtMode::WL),
1814 (16, 64) => Some(ExtMode::WQ),
1815 (32, 64) => Some(ExtMode::LQ),
1816 _ => None,
1817 }
1818 }
1819
1820 pub(crate) fn src_size(&self) -> u8 {
1822 match self {
1823 ExtMode::BL | ExtMode::BQ => 1,
1824 ExtMode::WL | ExtMode::WQ => 2,
1825 ExtMode::LQ => 4,
1826 }
1827 }
1828
1829 pub(crate) fn dst_size(&self) -> u8 {
1831 match self {
1832 ExtMode::BL | ExtMode::WL => 4,
1833 ExtMode::BQ | ExtMode::WQ | ExtMode::LQ => 8,
1834 }
1835 }
1836
1837 pub(crate) fn src_type(&self) -> Type {
1839 match self {
1840 ExtMode::BL | ExtMode::BQ => I8,
1841 ExtMode::WL | ExtMode::WQ => I16,
1842 ExtMode::LQ => I32,
1843 }
1844 }
1845}
1846
1847impl fmt::Debug for ExtMode {
1848 fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
1849 let name = match self {
1850 ExtMode::BL => "bl",
1851 ExtMode::BQ => "bq",
1852 ExtMode::WL => "wl",
1853 ExtMode::WQ => "wq",
1854 ExtMode::LQ => "lq",
1855 };
1856 write!(fmt, "{name}")
1857 }
1858}
1859
1860impl fmt::Display for ExtMode {
1861 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1862 fmt::Debug::fmt(self, f)
1863 }
1864}
1865
1866#[derive(Clone, Copy)]
1868pub enum ShiftKind {
1869 ShiftLeft,
1871 ShiftRightLogical,
1873 ShiftRightArithmetic,
1875 RotateLeft,
1877 RotateRight,
1879}
1880
1881impl fmt::Debug for ShiftKind {
1882 fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
1883 let name = match self {
1884 ShiftKind::ShiftLeft => "shl",
1885 ShiftKind::ShiftRightLogical => "shr",
1886 ShiftKind::ShiftRightArithmetic => "sar",
1887 ShiftKind::RotateLeft => "rol",
1888 ShiftKind::RotateRight => "ror",
1889 };
1890 write!(fmt, "{name}")
1891 }
1892}
1893
1894impl fmt::Display for ShiftKind {
1895 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1896 fmt::Debug::fmt(self, f)
1897 }
1898}
1899
1900#[derive(Copy, Clone, PartialEq, Eq)]
1903#[repr(u8)]
1904pub enum CC {
1905 O = 0,
1907 NO = 1,
1909
1910 B = 2,
1912 NB = 3,
1914
1915 Z = 4,
1917 NZ = 5,
1919
1920 BE = 6,
1922 NBE = 7,
1924
1925 S = 8,
1927 NS = 9,
1929
1930 L = 12,
1932 NL = 13,
1934
1935 LE = 14,
1937 NLE = 15,
1939
1940 P = 10,
1942
1943 NP = 11,
1945}
1946
1947impl CC {
1948 pub(crate) fn from_intcc(intcc: IntCC) -> Self {
1949 match intcc {
1950 IntCC::Equal => CC::Z,
1951 IntCC::NotEqual => CC::NZ,
1952 IntCC::SignedGreaterThanOrEqual => CC::NL,
1953 IntCC::SignedGreaterThan => CC::NLE,
1954 IntCC::SignedLessThanOrEqual => CC::LE,
1955 IntCC::SignedLessThan => CC::L,
1956 IntCC::UnsignedGreaterThanOrEqual => CC::NB,
1957 IntCC::UnsignedGreaterThan => CC::NBE,
1958 IntCC::UnsignedLessThanOrEqual => CC::BE,
1959 IntCC::UnsignedLessThan => CC::B,
1960 }
1961 }
1962
1963 pub(crate) fn invert(&self) -> Self {
1964 match self {
1965 CC::O => CC::NO,
1966 CC::NO => CC::O,
1967
1968 CC::B => CC::NB,
1969 CC::NB => CC::B,
1970
1971 CC::Z => CC::NZ,
1972 CC::NZ => CC::Z,
1973
1974 CC::BE => CC::NBE,
1975 CC::NBE => CC::BE,
1976
1977 CC::S => CC::NS,
1978 CC::NS => CC::S,
1979
1980 CC::L => CC::NL,
1981 CC::NL => CC::L,
1982
1983 CC::LE => CC::NLE,
1984 CC::NLE => CC::LE,
1985
1986 CC::P => CC::NP,
1987 CC::NP => CC::P,
1988 }
1989 }
1990
1991 pub(crate) fn get_enc(self) -> u8 {
1992 self as u8
1993 }
1994}
1995
1996impl fmt::Debug for CC {
1997 fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
1998 let name = match self {
1999 CC::O => "o",
2000 CC::NO => "no",
2001 CC::B => "b",
2002 CC::NB => "nb",
2003 CC::Z => "z",
2004 CC::NZ => "nz",
2005 CC::BE => "be",
2006 CC::NBE => "nbe",
2007 CC::S => "s",
2008 CC::NS => "ns",
2009 CC::L => "l",
2010 CC::NL => "nl",
2011 CC::LE => "le",
2012 CC::NLE => "nle",
2013 CC::P => "p",
2014 CC::NP => "np",
2015 };
2016 write!(fmt, "{name}")
2017 }
2018}
2019
2020impl fmt::Display for CC {
2021 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
2022 fmt::Debug::fmt(self, f)
2023 }
2024}
2025
2026#[derive(Clone, Copy)]
2030pub enum FcmpImm {
2031 Equal = 0x00,
2033 LessThan = 0x01,
2035 LessThanOrEqual = 0x02,
2037 Unordered = 0x03,
2039 NotEqual = 0x04,
2041 UnorderedOrGreaterThanOrEqual = 0x05,
2043 UnorderedOrGreaterThan = 0x06,
2045 Ordered = 0x07,
2047}
2048
2049impl FcmpImm {
2050 pub(crate) fn encode(self) -> u8 {
2051 self as u8
2052 }
2053}
2054
2055impl From<FloatCC> for FcmpImm {
2056 fn from(cond: FloatCC) -> Self {
2057 match cond {
2058 FloatCC::Equal => FcmpImm::Equal,
2059 FloatCC::LessThan => FcmpImm::LessThan,
2060 FloatCC::LessThanOrEqual => FcmpImm::LessThanOrEqual,
2061 FloatCC::Unordered => FcmpImm::Unordered,
2062 FloatCC::NotEqual => FcmpImm::NotEqual,
2063 FloatCC::UnorderedOrGreaterThanOrEqual => FcmpImm::UnorderedOrGreaterThanOrEqual,
2064 FloatCC::UnorderedOrGreaterThan => FcmpImm::UnorderedOrGreaterThan,
2065 FloatCC::Ordered => FcmpImm::Ordered,
2066 _ => panic!("unable to create comparison predicate for {cond}"),
2067 }
2068 }
2069}
2070
2071#[derive(Clone, Copy)]
2078pub enum RoundImm {
2079 RoundNearest = 0x00,
2081 RoundDown = 0x01,
2083 RoundUp = 0x02,
2085 RoundZero = 0x03,
2087}
2088
2089impl RoundImm {
2090 pub(crate) fn encode(self) -> u8 {
2091 self as u8
2092 }
2093}
2094
2095#[derive(Clone, Copy, PartialEq)]
2097pub enum OperandSize {
2098 Size8,
2100 Size16,
2102 Size32,
2104 Size64,
2106}
2107
2108impl OperandSize {
2109 pub(crate) fn from_bytes(num_bytes: u32) -> Self {
2110 match num_bytes {
2111 1 => OperandSize::Size8,
2112 2 => OperandSize::Size16,
2113 4 => OperandSize::Size32,
2114 8 => OperandSize::Size64,
2115 _ => unreachable!("Invalid OperandSize: {}", num_bytes),
2116 }
2117 }
2118
2119 pub(crate) fn from_ty(ty: Type) -> Self {
2122 Self::from_bytes(ty.lane_type().bytes())
2123 }
2124
2125 pub(crate) fn is_one_of(&self, sizes: &[Self]) -> bool {
2127 sizes.iter().any(|val| *self == *val)
2128 }
2129
2130 pub(crate) fn to_bytes(&self) -> u8 {
2131 match self {
2132 Self::Size8 => 1,
2133 Self::Size16 => 2,
2134 Self::Size32 => 4,
2135 Self::Size64 => 8,
2136 }
2137 }
2138
2139 pub(crate) fn to_bits(&self) -> u8 {
2140 self.to_bytes() * 8
2141 }
2142
2143 pub(crate) fn to_type(&self) -> Type {
2144 match self {
2145 Self::Size8 => I8,
2146 Self::Size16 => I16,
2147 Self::Size32 => I32,
2148 Self::Size64 => I64,
2149 }
2150 }
2151}
2152
2153#[derive(Clone)]
2155#[allow(dead_code)]
2156pub enum FenceKind {
2157 MFence,
2159 LFence,
2161 SFence,
2163}