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