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
808#[derive(Copy, Clone, PartialEq)]
810pub enum AluRmiROpcode {
811 Add,
813 Adc,
815 Sub,
817 Sbb,
819 And,
821 Or,
823 Xor,
825}
826
827impl fmt::Debug for AluRmiROpcode {
828 fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
829 let name = match self {
830 AluRmiROpcode::Add => "add",
831 AluRmiROpcode::Adc => "adc",
832 AluRmiROpcode::Sub => "sub",
833 AluRmiROpcode::Sbb => "sbb",
834 AluRmiROpcode::And => "and",
835 AluRmiROpcode::Or => "or",
836 AluRmiROpcode::Xor => "xor",
837 };
838 write!(fmt, "{name}")
839 }
840}
841
842impl fmt::Display for AluRmiROpcode {
843 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
844 fmt::Debug::fmt(self, f)
845 }
846}
847
848pub use crate::isa::x64::lower::isle::generated_code::AluRmROpcode;
849
850impl AluRmROpcode {
851 pub(crate) fn available_from(&self) -> SmallVec<[InstructionSet; 2]> {
852 match self {
853 AluRmROpcode::Andn => smallvec![InstructionSet::BMI1],
854 AluRmROpcode::Sarx | AluRmROpcode::Shrx | AluRmROpcode::Shlx | AluRmROpcode::Bzhi => {
855 smallvec![InstructionSet::BMI2]
856 }
857 }
858 }
859}
860
861impl fmt::Display for AluRmROpcode {
862 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
863 f.write_str(&format!("{self:?}").to_lowercase())
864 }
865}
866
867#[derive(Clone, PartialEq)]
868pub enum UnaryRmROpcode {
870 Bsr,
872 Bsf,
874 Lzcnt,
876 Tzcnt,
878 Popcnt,
880}
881
882impl UnaryRmROpcode {
883 pub(crate) fn available_from(&self) -> SmallVec<[InstructionSet; 2]> {
884 match self {
885 UnaryRmROpcode::Bsr | UnaryRmROpcode::Bsf => smallvec![],
886 UnaryRmROpcode::Lzcnt => smallvec![InstructionSet::Lzcnt],
887 UnaryRmROpcode::Tzcnt => smallvec![InstructionSet::BMI1],
888 UnaryRmROpcode::Popcnt => smallvec![InstructionSet::Popcnt],
889 }
890 }
891}
892
893impl fmt::Debug for UnaryRmROpcode {
894 fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
895 match self {
896 UnaryRmROpcode::Bsr => write!(fmt, "bsr"),
897 UnaryRmROpcode::Bsf => write!(fmt, "bsf"),
898 UnaryRmROpcode::Lzcnt => write!(fmt, "lzcnt"),
899 UnaryRmROpcode::Tzcnt => write!(fmt, "tzcnt"),
900 UnaryRmROpcode::Popcnt => write!(fmt, "popcnt"),
901 }
902 }
903}
904
905impl fmt::Display for UnaryRmROpcode {
906 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
907 fmt::Debug::fmt(self, f)
908 }
909}
910
911pub use crate::isa::x64::lower::isle::generated_code::UnaryRmRVexOpcode;
912
913impl UnaryRmRVexOpcode {
914 pub(crate) fn available_from(&self) -> SmallVec<[InstructionSet; 2]> {
915 match self {
916 UnaryRmRVexOpcode::Blsi | UnaryRmRVexOpcode::Blsmsk | UnaryRmRVexOpcode::Blsr => {
917 smallvec![InstructionSet::BMI1]
918 }
919 }
920 }
921}
922
923impl fmt::Display for UnaryRmRVexOpcode {
924 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
925 f.write_str(&format!("{self:?}").to_lowercase())
926 }
927}
928
929pub use crate::isa::x64::lower::isle::generated_code::UnaryRmRImmVexOpcode;
930
931impl UnaryRmRImmVexOpcode {
932 pub(crate) fn available_from(&self) -> SmallVec<[InstructionSet; 2]> {
933 match self {
934 UnaryRmRImmVexOpcode::Rorx => {
935 smallvec![InstructionSet::BMI2]
936 }
937 }
938 }
939}
940
941impl fmt::Display for UnaryRmRImmVexOpcode {
942 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
943 f.write_str(&format!("{self:?}").to_lowercase())
944 }
945}
946
947#[derive(Clone, Copy, PartialEq)]
948pub enum CmpOpcode {
950 Cmp,
952 Test,
954}
955
956#[derive(Debug)]
957pub(crate) enum InstructionSet {
958 SSE,
959 SSE2,
960 CMPXCHG16b,
961 SSSE3,
962 SSE41,
963 SSE42,
964 Popcnt,
965 Lzcnt,
966 BMI1,
967 #[allow(dead_code)] BMI2,
969 FMA,
970 AVX,
971 AVX2,
972 AVX512BITALG,
973 AVX512DQ,
974 AVX512F,
975 AVX512VBMI,
976 AVX512VL,
977}
978
979#[derive(Clone, Copy, PartialEq)]
981#[allow(dead_code)] #[allow(missing_docs)]
983pub enum SseOpcode {
984 Addps,
985 Addpd,
986 Addss,
987 Addsd,
988 Andps,
989 Andpd,
990 Andnps,
991 Andnpd,
992 Blendvpd,
993 Blendvps,
994 Comiss,
995 Comisd,
996 Cmpps,
997 Cmppd,
998 Cmpss,
999 Cmpsd,
1000 Cvtdq2ps,
1001 Cvtdq2pd,
1002 Cvtpd2ps,
1003 Cvtps2pd,
1004 Cvtsd2ss,
1005 Cvtsd2si,
1006 Cvtsi2ss,
1007 Cvtsi2sd,
1008 Cvtss2si,
1009 Cvtss2sd,
1010 Cvttpd2dq,
1011 Cvttps2dq,
1012 Cvttss2si,
1013 Cvttsd2si,
1014 Divps,
1015 Divpd,
1016 Divss,
1017 Divsd,
1018 Insertps,
1019 Maxps,
1020 Maxpd,
1021 Maxss,
1022 Maxsd,
1023 Minps,
1024 Minpd,
1025 Minss,
1026 Minsd,
1027 Movaps,
1028 Movapd,
1029 Movd,
1030 Movdqa,
1031 Movdqu,
1032 Movlhps,
1033 Movmskps,
1034 Movmskpd,
1035 Movq,
1036 Movss,
1037 Movsd,
1038 Movups,
1039 Movupd,
1040 Mulps,
1041 Mulpd,
1042 Mulss,
1043 Mulsd,
1044 Orps,
1045 Orpd,
1046 Pabsb,
1047 Pabsw,
1048 Pabsd,
1049 Packssdw,
1050 Packsswb,
1051 Packusdw,
1052 Packuswb,
1053 Paddb,
1054 Paddd,
1055 Paddq,
1056 Paddw,
1057 Paddsb,
1058 Paddsw,
1059 Paddusb,
1060 Paddusw,
1061 Palignr,
1062 Pand,
1063 Pandn,
1064 Pavgb,
1065 Pavgw,
1066 Pblendvb,
1067 Pcmpeqb,
1068 Pcmpeqw,
1069 Pcmpeqd,
1070 Pcmpeqq,
1071 Pcmpgtb,
1072 Pcmpgtw,
1073 Pcmpgtd,
1074 Pcmpgtq,
1075 Pextrb,
1076 Pextrw,
1077 Pextrd,
1078 Pextrq,
1079 Pinsrb,
1080 Pinsrw,
1081 Pinsrd,
1082 Pmaddubsw,
1083 Pmaddwd,
1084 Pmaxsb,
1085 Pmaxsw,
1086 Pmaxsd,
1087 Pmaxub,
1088 Pmaxuw,
1089 Pmaxud,
1090 Pminsb,
1091 Pminsw,
1092 Pminsd,
1093 Pminub,
1094 Pminuw,
1095 Pminud,
1096 Pmovmskb,
1097 Pmovsxbd,
1098 Pmovsxbw,
1099 Pmovsxbq,
1100 Pmovsxwd,
1101 Pmovsxwq,
1102 Pmovsxdq,
1103 Pmovzxbd,
1104 Pmovzxbw,
1105 Pmovzxbq,
1106 Pmovzxwd,
1107 Pmovzxwq,
1108 Pmovzxdq,
1109 Pmuldq,
1110 Pmulhw,
1111 Pmulhuw,
1112 Pmulhrsw,
1113 Pmulld,
1114 Pmullw,
1115 Pmuludq,
1116 Por,
1117 Pshufb,
1118 Pshufd,
1119 Psllw,
1120 Pslld,
1121 Psllq,
1122 Psraw,
1123 Psrad,
1124 Psrlw,
1125 Psrld,
1126 Psrlq,
1127 Psubb,
1128 Psubd,
1129 Psubq,
1130 Psubw,
1131 Psubsb,
1132 Psubsw,
1133 Psubusb,
1134 Psubusw,
1135 Ptest,
1136 Punpckhbw,
1137 Punpckhwd,
1138 Punpcklbw,
1139 Punpcklwd,
1140 Pxor,
1141 Rcpss,
1142 Roundps,
1143 Roundpd,
1144 Roundss,
1145 Roundsd,
1146 Rsqrtss,
1147 Shufps,
1148 Sqrtps,
1149 Sqrtpd,
1150 Sqrtss,
1151 Sqrtsd,
1152 Subps,
1153 Subpd,
1154 Subss,
1155 Subsd,
1156 Ucomiss,
1157 Ucomisd,
1158 Unpcklps,
1159 Unpcklpd,
1160 Unpckhps,
1161 Xorps,
1162 Xorpd,
1163 Phaddw,
1164 Phaddd,
1165 Punpckhdq,
1166 Punpckldq,
1167 Punpckhqdq,
1168 Punpcklqdq,
1169 Pshuflw,
1170 Pshufhw,
1171 Pblendw,
1172 Movddup,
1173}
1174
1175impl SseOpcode {
1176 pub(crate) fn available_from(&self) -> InstructionSet {
1178 use InstructionSet::*;
1179 match self {
1180 SseOpcode::Addps
1181 | SseOpcode::Addss
1182 | SseOpcode::Andps
1183 | SseOpcode::Andnps
1184 | SseOpcode::Comiss
1185 | SseOpcode::Cmpps
1186 | SseOpcode::Cmpss
1187 | SseOpcode::Cvtsi2ss
1188 | SseOpcode::Cvtss2si
1189 | SseOpcode::Cvttss2si
1190 | SseOpcode::Divps
1191 | SseOpcode::Divss
1192 | SseOpcode::Maxps
1193 | SseOpcode::Maxss
1194 | SseOpcode::Minps
1195 | SseOpcode::Minss
1196 | SseOpcode::Movaps
1197 | SseOpcode::Movlhps
1198 | SseOpcode::Movmskps
1199 | SseOpcode::Movss
1200 | SseOpcode::Movups
1201 | SseOpcode::Mulps
1202 | SseOpcode::Mulss
1203 | SseOpcode::Orps
1204 | SseOpcode::Rcpss
1205 | SseOpcode::Rsqrtss
1206 | SseOpcode::Shufps
1207 | SseOpcode::Sqrtps
1208 | SseOpcode::Sqrtss
1209 | SseOpcode::Subps
1210 | SseOpcode::Subss
1211 | SseOpcode::Ucomiss
1212 | SseOpcode::Unpcklps
1213 | SseOpcode::Unpckhps
1214 | SseOpcode::Xorps => SSE,
1215
1216 SseOpcode::Addpd
1217 | SseOpcode::Addsd
1218 | SseOpcode::Andpd
1219 | SseOpcode::Andnpd
1220 | SseOpcode::Cmppd
1221 | SseOpcode::Cmpsd
1222 | SseOpcode::Comisd
1223 | SseOpcode::Cvtdq2ps
1224 | SseOpcode::Cvtdq2pd
1225 | SseOpcode::Cvtpd2ps
1226 | SseOpcode::Cvtps2pd
1227 | SseOpcode::Cvtsd2ss
1228 | SseOpcode::Cvtsd2si
1229 | SseOpcode::Cvtsi2sd
1230 | SseOpcode::Cvtss2sd
1231 | SseOpcode::Cvttpd2dq
1232 | SseOpcode::Cvttps2dq
1233 | SseOpcode::Cvttsd2si
1234 | SseOpcode::Divpd
1235 | SseOpcode::Divsd
1236 | SseOpcode::Maxpd
1237 | SseOpcode::Maxsd
1238 | SseOpcode::Minpd
1239 | SseOpcode::Minsd
1240 | SseOpcode::Movapd
1241 | SseOpcode::Movd
1242 | SseOpcode::Movmskpd
1243 | SseOpcode::Movq
1244 | SseOpcode::Movsd
1245 | SseOpcode::Movupd
1246 | SseOpcode::Movdqa
1247 | SseOpcode::Movdqu
1248 | SseOpcode::Mulpd
1249 | SseOpcode::Mulsd
1250 | SseOpcode::Orpd
1251 | SseOpcode::Packssdw
1252 | SseOpcode::Packsswb
1253 | SseOpcode::Packuswb
1254 | SseOpcode::Paddb
1255 | SseOpcode::Paddd
1256 | SseOpcode::Paddq
1257 | SseOpcode::Paddw
1258 | SseOpcode::Paddsb
1259 | SseOpcode::Paddsw
1260 | SseOpcode::Paddusb
1261 | SseOpcode::Paddusw
1262 | SseOpcode::Pand
1263 | SseOpcode::Pandn
1264 | SseOpcode::Pavgb
1265 | SseOpcode::Pavgw
1266 | SseOpcode::Pcmpeqb
1267 | SseOpcode::Pcmpeqw
1268 | SseOpcode::Pcmpeqd
1269 | SseOpcode::Pcmpgtb
1270 | SseOpcode::Pcmpgtw
1271 | SseOpcode::Pcmpgtd
1272 | SseOpcode::Pextrw
1273 | SseOpcode::Pinsrw
1274 | SseOpcode::Pmaddwd
1275 | SseOpcode::Pmaxsw
1276 | SseOpcode::Pmaxub
1277 | SseOpcode::Pminsw
1278 | SseOpcode::Pminub
1279 | SseOpcode::Pmovmskb
1280 | SseOpcode::Pmulhw
1281 | SseOpcode::Pmulhuw
1282 | SseOpcode::Pmullw
1283 | SseOpcode::Pmuludq
1284 | SseOpcode::Por
1285 | SseOpcode::Pshufd
1286 | SseOpcode::Psllw
1287 | SseOpcode::Pslld
1288 | SseOpcode::Psllq
1289 | SseOpcode::Psraw
1290 | SseOpcode::Psrad
1291 | SseOpcode::Psrlw
1292 | SseOpcode::Psrld
1293 | SseOpcode::Psrlq
1294 | SseOpcode::Psubb
1295 | SseOpcode::Psubd
1296 | SseOpcode::Psubq
1297 | SseOpcode::Psubw
1298 | SseOpcode::Psubsb
1299 | SseOpcode::Psubsw
1300 | SseOpcode::Psubusb
1301 | SseOpcode::Psubusw
1302 | SseOpcode::Punpckhbw
1303 | SseOpcode::Punpckhwd
1304 | SseOpcode::Punpcklbw
1305 | SseOpcode::Punpcklwd
1306 | SseOpcode::Pxor
1307 | SseOpcode::Sqrtpd
1308 | SseOpcode::Sqrtsd
1309 | SseOpcode::Subpd
1310 | SseOpcode::Subsd
1311 | SseOpcode::Ucomisd
1312 | SseOpcode::Xorpd
1313 | SseOpcode::Punpckldq
1314 | SseOpcode::Punpckhdq
1315 | SseOpcode::Punpcklqdq
1316 | SseOpcode::Punpckhqdq
1317 | SseOpcode::Pshuflw
1318 | SseOpcode::Pshufhw
1319 | SseOpcode::Unpcklpd => SSE2,
1320
1321 SseOpcode::Pabsb
1322 | SseOpcode::Pabsw
1323 | SseOpcode::Pabsd
1324 | SseOpcode::Palignr
1325 | SseOpcode::Pmulhrsw
1326 | SseOpcode::Pshufb
1327 | SseOpcode::Phaddw
1328 | SseOpcode::Phaddd
1329 | SseOpcode::Pmaddubsw
1330 | SseOpcode::Movddup => SSSE3,
1331
1332 SseOpcode::Blendvpd
1333 | SseOpcode::Blendvps
1334 | SseOpcode::Insertps
1335 | SseOpcode::Packusdw
1336 | SseOpcode::Pblendvb
1337 | SseOpcode::Pcmpeqq
1338 | SseOpcode::Pextrb
1339 | SseOpcode::Pextrd
1340 | SseOpcode::Pextrq
1341 | SseOpcode::Pinsrb
1342 | SseOpcode::Pinsrd
1343 | SseOpcode::Pmaxsb
1344 | SseOpcode::Pmaxsd
1345 | SseOpcode::Pmaxuw
1346 | SseOpcode::Pmaxud
1347 | SseOpcode::Pminsb
1348 | SseOpcode::Pminsd
1349 | SseOpcode::Pminuw
1350 | SseOpcode::Pminud
1351 | SseOpcode::Pmovsxbd
1352 | SseOpcode::Pmovsxbw
1353 | SseOpcode::Pmovsxbq
1354 | SseOpcode::Pmovsxwd
1355 | SseOpcode::Pmovsxwq
1356 | SseOpcode::Pmovsxdq
1357 | SseOpcode::Pmovzxbd
1358 | SseOpcode::Pmovzxbw
1359 | SseOpcode::Pmovzxbq
1360 | SseOpcode::Pmovzxwd
1361 | SseOpcode::Pmovzxwq
1362 | SseOpcode::Pmovzxdq
1363 | SseOpcode::Pmuldq
1364 | SseOpcode::Pmulld
1365 | SseOpcode::Ptest
1366 | SseOpcode::Roundps
1367 | SseOpcode::Roundpd
1368 | SseOpcode::Roundss
1369 | SseOpcode::Roundsd
1370 | SseOpcode::Pblendw => SSE41,
1371
1372 SseOpcode::Pcmpgtq => SSE42,
1373 }
1374 }
1375
1376 pub(crate) fn src_size(&self) -> u8 {
1378 match self {
1379 SseOpcode::Movd => 4,
1380 _ => 8,
1381 }
1382 }
1383
1384 pub(crate) fn has_scalar_src2(self) -> bool {
1386 match self {
1387 SseOpcode::Pinsrb | SseOpcode::Pinsrw | SseOpcode::Pinsrd => true,
1388 SseOpcode::Pmovsxbw
1389 | SseOpcode::Pmovsxbd
1390 | SseOpcode::Pmovsxbq
1391 | SseOpcode::Pmovsxwd
1392 | SseOpcode::Pmovsxwq
1393 | SseOpcode::Pmovsxdq => true,
1394 SseOpcode::Pmovzxbw
1395 | SseOpcode::Pmovzxbd
1396 | SseOpcode::Pmovzxbq
1397 | SseOpcode::Pmovzxwd
1398 | SseOpcode::Pmovzxwq
1399 | SseOpcode::Pmovzxdq => true,
1400 _ => false,
1401 }
1402 }
1403}
1404
1405impl fmt::Debug for SseOpcode {
1406 fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
1407 let name = match self {
1408 SseOpcode::Addps => "addps",
1409 SseOpcode::Addpd => "addpd",
1410 SseOpcode::Addss => "addss",
1411 SseOpcode::Addsd => "addsd",
1412 SseOpcode::Andpd => "andpd",
1413 SseOpcode::Andps => "andps",
1414 SseOpcode::Andnps => "andnps",
1415 SseOpcode::Andnpd => "andnpd",
1416 SseOpcode::Blendvpd => "blendvpd",
1417 SseOpcode::Blendvps => "blendvps",
1418 SseOpcode::Cmpps => "cmpps",
1419 SseOpcode::Cmppd => "cmppd",
1420 SseOpcode::Cmpss => "cmpss",
1421 SseOpcode::Cmpsd => "cmpsd",
1422 SseOpcode::Comiss => "comiss",
1423 SseOpcode::Comisd => "comisd",
1424 SseOpcode::Cvtdq2ps => "cvtdq2ps",
1425 SseOpcode::Cvtdq2pd => "cvtdq2pd",
1426 SseOpcode::Cvtpd2ps => "cvtpd2ps",
1427 SseOpcode::Cvtps2pd => "cvtps2pd",
1428 SseOpcode::Cvtsd2ss => "cvtsd2ss",
1429 SseOpcode::Cvtsd2si => "cvtsd2si",
1430 SseOpcode::Cvtsi2ss => "cvtsi2ss",
1431 SseOpcode::Cvtsi2sd => "cvtsi2sd",
1432 SseOpcode::Cvtss2si => "cvtss2si",
1433 SseOpcode::Cvtss2sd => "cvtss2sd",
1434 SseOpcode::Cvttpd2dq => "cvttpd2dq",
1435 SseOpcode::Cvttps2dq => "cvttps2dq",
1436 SseOpcode::Cvttss2si => "cvttss2si",
1437 SseOpcode::Cvttsd2si => "cvttsd2si",
1438 SseOpcode::Divps => "divps",
1439 SseOpcode::Divpd => "divpd",
1440 SseOpcode::Divss => "divss",
1441 SseOpcode::Divsd => "divsd",
1442 SseOpcode::Insertps => "insertps",
1443 SseOpcode::Maxps => "maxps",
1444 SseOpcode::Maxpd => "maxpd",
1445 SseOpcode::Maxss => "maxss",
1446 SseOpcode::Maxsd => "maxsd",
1447 SseOpcode::Minps => "minps",
1448 SseOpcode::Minpd => "minpd",
1449 SseOpcode::Minss => "minss",
1450 SseOpcode::Minsd => "minsd",
1451 SseOpcode::Movaps => "movaps",
1452 SseOpcode::Movapd => "movapd",
1453 SseOpcode::Movd => "movd",
1454 SseOpcode::Movdqa => "movdqa",
1455 SseOpcode::Movdqu => "movdqu",
1456 SseOpcode::Movlhps => "movlhps",
1457 SseOpcode::Movmskps => "movmskps",
1458 SseOpcode::Movmskpd => "movmskpd",
1459 SseOpcode::Movq => "movq",
1460 SseOpcode::Movss => "movss",
1461 SseOpcode::Movsd => "movsd",
1462 SseOpcode::Movups => "movups",
1463 SseOpcode::Movupd => "movupd",
1464 SseOpcode::Mulps => "mulps",
1465 SseOpcode::Mulpd => "mulpd",
1466 SseOpcode::Mulss => "mulss",
1467 SseOpcode::Mulsd => "mulsd",
1468 SseOpcode::Orpd => "orpd",
1469 SseOpcode::Orps => "orps",
1470 SseOpcode::Pabsb => "pabsb",
1471 SseOpcode::Pabsw => "pabsw",
1472 SseOpcode::Pabsd => "pabsd",
1473 SseOpcode::Packssdw => "packssdw",
1474 SseOpcode::Packsswb => "packsswb",
1475 SseOpcode::Packusdw => "packusdw",
1476 SseOpcode::Packuswb => "packuswb",
1477 SseOpcode::Paddb => "paddb",
1478 SseOpcode::Paddd => "paddd",
1479 SseOpcode::Paddq => "paddq",
1480 SseOpcode::Paddw => "paddw",
1481 SseOpcode::Paddsb => "paddsb",
1482 SseOpcode::Paddsw => "paddsw",
1483 SseOpcode::Paddusb => "paddusb",
1484 SseOpcode::Paddusw => "paddusw",
1485 SseOpcode::Palignr => "palignr",
1486 SseOpcode::Pand => "pand",
1487 SseOpcode::Pandn => "pandn",
1488 SseOpcode::Pavgb => "pavgb",
1489 SseOpcode::Pavgw => "pavgw",
1490 SseOpcode::Pblendvb => "pblendvb",
1491 SseOpcode::Pcmpeqb => "pcmpeqb",
1492 SseOpcode::Pcmpeqw => "pcmpeqw",
1493 SseOpcode::Pcmpeqd => "pcmpeqd",
1494 SseOpcode::Pcmpeqq => "pcmpeqq",
1495 SseOpcode::Pcmpgtb => "pcmpgtb",
1496 SseOpcode::Pcmpgtw => "pcmpgtw",
1497 SseOpcode::Pcmpgtd => "pcmpgtd",
1498 SseOpcode::Pcmpgtq => "pcmpgtq",
1499 SseOpcode::Pextrb => "pextrb",
1500 SseOpcode::Pextrw => "pextrw",
1501 SseOpcode::Pextrd => "pextrd",
1502 SseOpcode::Pextrq => "pextrq",
1503 SseOpcode::Pinsrb => "pinsrb",
1504 SseOpcode::Pinsrw => "pinsrw",
1505 SseOpcode::Pinsrd => "pinsrd",
1506 SseOpcode::Pmaddubsw => "pmaddubsw",
1507 SseOpcode::Pmaddwd => "pmaddwd",
1508 SseOpcode::Pmaxsb => "pmaxsb",
1509 SseOpcode::Pmaxsw => "pmaxsw",
1510 SseOpcode::Pmaxsd => "pmaxsd",
1511 SseOpcode::Pmaxub => "pmaxub",
1512 SseOpcode::Pmaxuw => "pmaxuw",
1513 SseOpcode::Pmaxud => "pmaxud",
1514 SseOpcode::Pminsb => "pminsb",
1515 SseOpcode::Pminsw => "pminsw",
1516 SseOpcode::Pminsd => "pminsd",
1517 SseOpcode::Pminub => "pminub",
1518 SseOpcode::Pminuw => "pminuw",
1519 SseOpcode::Pminud => "pminud",
1520 SseOpcode::Pmovmskb => "pmovmskb",
1521 SseOpcode::Pmovsxbd => "pmovsxbd",
1522 SseOpcode::Pmovsxbw => "pmovsxbw",
1523 SseOpcode::Pmovsxbq => "pmovsxbq",
1524 SseOpcode::Pmovsxwd => "pmovsxwd",
1525 SseOpcode::Pmovsxwq => "pmovsxwq",
1526 SseOpcode::Pmovsxdq => "pmovsxdq",
1527 SseOpcode::Pmovzxbd => "pmovzxbd",
1528 SseOpcode::Pmovzxbw => "pmovzxbw",
1529 SseOpcode::Pmovzxbq => "pmovzxbq",
1530 SseOpcode::Pmovzxwd => "pmovzxwd",
1531 SseOpcode::Pmovzxwq => "pmovzxwq",
1532 SseOpcode::Pmovzxdq => "pmovzxdq",
1533 SseOpcode::Pmuldq => "pmuldq",
1534 SseOpcode::Pmulhw => "pmulhw",
1535 SseOpcode::Pmulhuw => "pmulhuw",
1536 SseOpcode::Pmulhrsw => "pmulhrsw",
1537 SseOpcode::Pmulld => "pmulld",
1538 SseOpcode::Pmullw => "pmullw",
1539 SseOpcode::Pmuludq => "pmuludq",
1540 SseOpcode::Por => "por",
1541 SseOpcode::Pshufb => "pshufb",
1542 SseOpcode::Pshufd => "pshufd",
1543 SseOpcode::Psllw => "psllw",
1544 SseOpcode::Pslld => "pslld",
1545 SseOpcode::Psllq => "psllq",
1546 SseOpcode::Psraw => "psraw",
1547 SseOpcode::Psrad => "psrad",
1548 SseOpcode::Psrlw => "psrlw",
1549 SseOpcode::Psrld => "psrld",
1550 SseOpcode::Psrlq => "psrlq",
1551 SseOpcode::Psubb => "psubb",
1552 SseOpcode::Psubd => "psubd",
1553 SseOpcode::Psubq => "psubq",
1554 SseOpcode::Psubw => "psubw",
1555 SseOpcode::Psubsb => "psubsb",
1556 SseOpcode::Psubsw => "psubsw",
1557 SseOpcode::Psubusb => "psubusb",
1558 SseOpcode::Psubusw => "psubusw",
1559 SseOpcode::Ptest => "ptest",
1560 SseOpcode::Punpckhbw => "punpckhbw",
1561 SseOpcode::Punpckhwd => "punpckhwd",
1562 SseOpcode::Punpcklbw => "punpcklbw",
1563 SseOpcode::Punpcklwd => "punpcklwd",
1564 SseOpcode::Pxor => "pxor",
1565 SseOpcode::Rcpss => "rcpss",
1566 SseOpcode::Roundps => "roundps",
1567 SseOpcode::Roundpd => "roundpd",
1568 SseOpcode::Roundss => "roundss",
1569 SseOpcode::Roundsd => "roundsd",
1570 SseOpcode::Rsqrtss => "rsqrtss",
1571 SseOpcode::Shufps => "shufps",
1572 SseOpcode::Sqrtps => "sqrtps",
1573 SseOpcode::Sqrtpd => "sqrtpd",
1574 SseOpcode::Sqrtss => "sqrtss",
1575 SseOpcode::Sqrtsd => "sqrtsd",
1576 SseOpcode::Subps => "subps",
1577 SseOpcode::Subpd => "subpd",
1578 SseOpcode::Subss => "subss",
1579 SseOpcode::Subsd => "subsd",
1580 SseOpcode::Ucomiss => "ucomiss",
1581 SseOpcode::Ucomisd => "ucomisd",
1582 SseOpcode::Unpcklps => "unpcklps",
1583 SseOpcode::Unpckhps => "unpckhps",
1584 SseOpcode::Xorps => "xorps",
1585 SseOpcode::Xorpd => "xorpd",
1586 SseOpcode::Phaddw => "phaddw",
1587 SseOpcode::Phaddd => "phaddd",
1588 SseOpcode::Punpckldq => "punpckldq",
1589 SseOpcode::Punpckhdq => "punpckhdq",
1590 SseOpcode::Punpcklqdq => "punpcklqdq",
1591 SseOpcode::Punpckhqdq => "punpckhqdq",
1592 SseOpcode::Pshuflw => "pshuflw",
1593 SseOpcode::Pshufhw => "pshufhw",
1594 SseOpcode::Pblendw => "pblendw",
1595 SseOpcode::Movddup => "movddup",
1596 SseOpcode::Unpcklpd => "unpcklpd",
1597 };
1598 write!(fmt, "{name}")
1599 }
1600}
1601
1602impl fmt::Display for SseOpcode {
1603 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1604 fmt::Debug::fmt(self, f)
1605 }
1606}
1607
1608pub use crate::isa::x64::lower::isle::generated_code::AvxOpcode;
1609
1610impl AvxOpcode {
1611 pub(crate) fn available_from(&self) -> SmallVec<[InstructionSet; 2]> {
1613 match self {
1614 AvxOpcode::Vfmadd213ss
1615 | AvxOpcode::Vfmadd213sd
1616 | AvxOpcode::Vfmadd213ps
1617 | AvxOpcode::Vfmadd213pd
1618 | AvxOpcode::Vfmadd132ss
1619 | AvxOpcode::Vfmadd132sd
1620 | AvxOpcode::Vfmadd132ps
1621 | AvxOpcode::Vfmadd132pd
1622 | AvxOpcode::Vfnmadd213ss
1623 | AvxOpcode::Vfnmadd213sd
1624 | AvxOpcode::Vfnmadd213ps
1625 | AvxOpcode::Vfnmadd213pd
1626 | AvxOpcode::Vfnmadd132ss
1627 | AvxOpcode::Vfnmadd132sd
1628 | AvxOpcode::Vfnmadd132ps
1629 | AvxOpcode::Vfnmadd132pd
1630 | AvxOpcode::Vfmsub213ss
1631 | AvxOpcode::Vfmsub213sd
1632 | AvxOpcode::Vfmsub213ps
1633 | AvxOpcode::Vfmsub213pd
1634 | AvxOpcode::Vfmsub132ss
1635 | AvxOpcode::Vfmsub132sd
1636 | AvxOpcode::Vfmsub132ps
1637 | AvxOpcode::Vfmsub132pd
1638 | AvxOpcode::Vfnmsub213ss
1639 | AvxOpcode::Vfnmsub213sd
1640 | AvxOpcode::Vfnmsub213ps
1641 | AvxOpcode::Vfnmsub213pd
1642 | AvxOpcode::Vfnmsub132ss
1643 | AvxOpcode::Vfnmsub132sd
1644 | AvxOpcode::Vfnmsub132ps
1645 | AvxOpcode::Vfnmsub132pd => smallvec![InstructionSet::FMA],
1646 AvxOpcode::Vminps
1647 | AvxOpcode::Vminpd
1648 | AvxOpcode::Vmaxps
1649 | AvxOpcode::Vmaxpd
1650 | AvxOpcode::Vandnps
1651 | AvxOpcode::Vandnpd
1652 | AvxOpcode::Vpandn
1653 | AvxOpcode::Vcmpps
1654 | AvxOpcode::Vcmppd
1655 | AvxOpcode::Vpsrlw
1656 | AvxOpcode::Vpsrld
1657 | AvxOpcode::Vpsrlq
1658 | AvxOpcode::Vpaddb
1659 | AvxOpcode::Vpaddw
1660 | AvxOpcode::Vpaddd
1661 | AvxOpcode::Vpaddq
1662 | AvxOpcode::Vpaddsb
1663 | AvxOpcode::Vpaddsw
1664 | AvxOpcode::Vpaddusb
1665 | AvxOpcode::Vpaddusw
1666 | AvxOpcode::Vpsubb
1667 | AvxOpcode::Vpsubw
1668 | AvxOpcode::Vpsubd
1669 | AvxOpcode::Vpsubq
1670 | AvxOpcode::Vpsubsb
1671 | AvxOpcode::Vpsubsw
1672 | AvxOpcode::Vpsubusb
1673 | AvxOpcode::Vpsubusw
1674 | AvxOpcode::Vpavgb
1675 | AvxOpcode::Vpavgw
1676 | AvxOpcode::Vpand
1677 | AvxOpcode::Vandps
1678 | AvxOpcode::Vandpd
1679 | AvxOpcode::Vpor
1680 | AvxOpcode::Vorps
1681 | AvxOpcode::Vorpd
1682 | AvxOpcode::Vpxor
1683 | AvxOpcode::Vxorps
1684 | AvxOpcode::Vxorpd
1685 | AvxOpcode::Vpmullw
1686 | AvxOpcode::Vpmulld
1687 | AvxOpcode::Vpmulhw
1688 | AvxOpcode::Vpmulhd
1689 | AvxOpcode::Vpmulhrsw
1690 | AvxOpcode::Vpmulhuw
1691 | AvxOpcode::Vpmuldq
1692 | AvxOpcode::Vpmuludq
1693 | AvxOpcode::Vpunpckhwd
1694 | AvxOpcode::Vpunpcklwd
1695 | AvxOpcode::Vunpcklps
1696 | AvxOpcode::Vunpckhps
1697 | AvxOpcode::Vaddps
1698 | AvxOpcode::Vaddpd
1699 | AvxOpcode::Vsubps
1700 | AvxOpcode::Vsubpd
1701 | AvxOpcode::Vmulps
1702 | AvxOpcode::Vmulpd
1703 | AvxOpcode::Vdivps
1704 | AvxOpcode::Vdivpd
1705 | AvxOpcode::Vpcmpeqb
1706 | AvxOpcode::Vpcmpeqw
1707 | AvxOpcode::Vpcmpeqd
1708 | AvxOpcode::Vpcmpeqq
1709 | AvxOpcode::Vpcmpgtb
1710 | AvxOpcode::Vpcmpgtw
1711 | AvxOpcode::Vpcmpgtd
1712 | AvxOpcode::Vpcmpgtq
1713 | AvxOpcode::Vblendvps
1714 | AvxOpcode::Vblendvpd
1715 | AvxOpcode::Vpblendvb
1716 | AvxOpcode::Vmovlhps
1717 | AvxOpcode::Vpminsb
1718 | AvxOpcode::Vpminsw
1719 | AvxOpcode::Vpminsd
1720 | AvxOpcode::Vpminub
1721 | AvxOpcode::Vpminuw
1722 | AvxOpcode::Vpminud
1723 | AvxOpcode::Vpmaxsb
1724 | AvxOpcode::Vpmaxsw
1725 | AvxOpcode::Vpmaxsd
1726 | AvxOpcode::Vpmaxub
1727 | AvxOpcode::Vpmaxuw
1728 | AvxOpcode::Vpmaxud
1729 | AvxOpcode::Vpunpcklbw
1730 | AvxOpcode::Vpunpckhbw
1731 | AvxOpcode::Vpacksswb
1732 | AvxOpcode::Vpackssdw
1733 | AvxOpcode::Vpackuswb
1734 | AvxOpcode::Vpackusdw
1735 | AvxOpcode::Vpalignr
1736 | AvxOpcode::Vpinsrb
1737 | AvxOpcode::Vpinsrw
1738 | AvxOpcode::Vpinsrd
1739 | AvxOpcode::Vpinsrq
1740 | AvxOpcode::Vpmaddwd
1741 | AvxOpcode::Vpmaddubsw
1742 | AvxOpcode::Vinsertps
1743 | AvxOpcode::Vpshufb
1744 | AvxOpcode::Vshufps
1745 | AvxOpcode::Vpsllw
1746 | AvxOpcode::Vpslld
1747 | AvxOpcode::Vpsllq
1748 | AvxOpcode::Vpsraw
1749 | AvxOpcode::Vpsrad
1750 | AvxOpcode::Vpmovsxbw
1751 | AvxOpcode::Vpmovzxbw
1752 | AvxOpcode::Vpmovsxwd
1753 | AvxOpcode::Vpmovzxwd
1754 | AvxOpcode::Vpmovsxdq
1755 | AvxOpcode::Vpmovzxdq
1756 | AvxOpcode::Vaddss
1757 | AvxOpcode::Vaddsd
1758 | AvxOpcode::Vmulss
1759 | AvxOpcode::Vmulsd
1760 | AvxOpcode::Vsubss
1761 | AvxOpcode::Vsubsd
1762 | AvxOpcode::Vdivss
1763 | AvxOpcode::Vdivsd
1764 | AvxOpcode::Vpabsb
1765 | AvxOpcode::Vpabsw
1766 | AvxOpcode::Vpabsd
1767 | AvxOpcode::Vminss
1768 | AvxOpcode::Vminsd
1769 | AvxOpcode::Vmaxss
1770 | AvxOpcode::Vmaxsd
1771 | AvxOpcode::Vsqrtps
1772 | AvxOpcode::Vsqrtpd
1773 | AvxOpcode::Vroundpd
1774 | AvxOpcode::Vroundps
1775 | AvxOpcode::Vcvtdq2pd
1776 | AvxOpcode::Vcvtdq2ps
1777 | AvxOpcode::Vcvtpd2ps
1778 | AvxOpcode::Vcvtps2pd
1779 | AvxOpcode::Vcvttpd2dq
1780 | AvxOpcode::Vcvttps2dq
1781 | AvxOpcode::Vphaddw
1782 | AvxOpcode::Vphaddd
1783 | AvxOpcode::Vpunpckldq
1784 | AvxOpcode::Vpunpckhdq
1785 | AvxOpcode::Vpunpcklqdq
1786 | AvxOpcode::Vpunpckhqdq
1787 | AvxOpcode::Vpshuflw
1788 | AvxOpcode::Vpshufhw
1789 | AvxOpcode::Vpshufd
1790 | AvxOpcode::Vmovss
1791 | AvxOpcode::Vmovsd
1792 | AvxOpcode::Vmovups
1793 | AvxOpcode::Vmovupd
1794 | AvxOpcode::Vmovdqu
1795 | AvxOpcode::Vpextrb
1796 | AvxOpcode::Vpextrw
1797 | AvxOpcode::Vpextrd
1798 | AvxOpcode::Vpextrq
1799 | AvxOpcode::Vpblendw
1800 | AvxOpcode::Vmovddup
1801 | AvxOpcode::Vbroadcastss
1802 | AvxOpcode::Vmovd
1803 | AvxOpcode::Vmovq
1804 | AvxOpcode::Vmovmskps
1805 | AvxOpcode::Vmovmskpd
1806 | AvxOpcode::Vpmovmskb
1807 | AvxOpcode::Vcvtsi2ss
1808 | AvxOpcode::Vcvtsi2sd
1809 | AvxOpcode::Vcvtss2sd
1810 | AvxOpcode::Vcvtsd2ss
1811 | AvxOpcode::Vsqrtss
1812 | AvxOpcode::Vsqrtsd
1813 | AvxOpcode::Vroundss
1814 | AvxOpcode::Vroundsd
1815 | AvxOpcode::Vunpcklpd
1816 | AvxOpcode::Vptest
1817 | AvxOpcode::Vucomiss
1818 | AvxOpcode::Vucomisd => {
1819 smallvec![InstructionSet::AVX]
1820 }
1821
1822 AvxOpcode::Vpbroadcastb | AvxOpcode::Vpbroadcastw | AvxOpcode::Vpbroadcastd => {
1823 smallvec![InstructionSet::AVX2]
1824 }
1825 }
1826 }
1827
1828 pub(crate) fn is_commutative(&self) -> bool {
1833 match *self {
1834 AvxOpcode::Vpaddb
1835 | AvxOpcode::Vpaddw
1836 | AvxOpcode::Vpaddd
1837 | AvxOpcode::Vpaddq
1838 | AvxOpcode::Vpaddsb
1839 | AvxOpcode::Vpaddsw
1840 | AvxOpcode::Vpaddusb
1841 | AvxOpcode::Vpaddusw
1842 | AvxOpcode::Vpand
1843 | AvxOpcode::Vandps
1844 | AvxOpcode::Vandpd
1845 | AvxOpcode::Vpor
1846 | AvxOpcode::Vorps
1847 | AvxOpcode::Vorpd
1848 | AvxOpcode::Vpxor
1849 | AvxOpcode::Vxorps
1850 | AvxOpcode::Vxorpd
1851 | AvxOpcode::Vpmuldq
1852 | AvxOpcode::Vpmuludq
1853 | AvxOpcode::Vaddps
1854 | AvxOpcode::Vaddpd
1855 | AvxOpcode::Vmulps
1856 | AvxOpcode::Vmulpd
1857 | AvxOpcode::Vpcmpeqb
1858 | AvxOpcode::Vpcmpeqw
1859 | AvxOpcode::Vpcmpeqd
1860 | AvxOpcode::Vpcmpeqq
1861 | AvxOpcode::Vaddss
1862 | AvxOpcode::Vaddsd
1863 | AvxOpcode::Vmulss
1864 | AvxOpcode::Vmulsd => true,
1865 _ => false,
1866 }
1867 }
1868}
1869
1870impl fmt::Display for AvxOpcode {
1871 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1872 format!("{self:?}").to_lowercase().fmt(f)
1873 }
1874}
1875
1876#[derive(Copy, Clone, PartialEq)]
1877#[allow(missing_docs)]
1878pub enum Avx512TupleType {
1879 Full,
1880 FullMem,
1881 Mem128,
1882}
1883
1884pub use crate::isa::x64::lower::isle::generated_code::Avx512Opcode;
1885
1886impl Avx512Opcode {
1887 pub(crate) fn available_from(&self) -> SmallVec<[InstructionSet; 2]> {
1889 match self {
1890 Avx512Opcode::Vcvtudq2ps
1891 | Avx512Opcode::Vpabsq
1892 | Avx512Opcode::Vpsraq
1893 | Avx512Opcode::VpsraqImm => {
1894 smallvec![InstructionSet::AVX512F, InstructionSet::AVX512VL]
1895 }
1896 Avx512Opcode::Vpermi2b => {
1897 smallvec![InstructionSet::AVX512VL, InstructionSet::AVX512VBMI]
1898 }
1899 Avx512Opcode::Vpmullq => smallvec![InstructionSet::AVX512VL, InstructionSet::AVX512DQ],
1900 Avx512Opcode::Vpopcntb => {
1901 smallvec![InstructionSet::AVX512VL, InstructionSet::AVX512BITALG]
1902 }
1903 }
1904 }
1905
1906 pub fn tuple_type(&self) -> Avx512TupleType {
1913 use Avx512Opcode::*;
1914 use Avx512TupleType::*;
1915
1916 match self {
1917 Vcvtudq2ps | Vpabsq | Vpmullq | VpsraqImm => Full,
1918 Vpermi2b | Vpopcntb => FullMem,
1919 Vpsraq => Mem128,
1920 }
1921 }
1922}
1923
1924impl fmt::Display for Avx512Opcode {
1925 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1926 let s = format!("{self:?}");
1927 f.write_str(&s.to_lowercase())
1928 }
1929}
1930
1931#[allow(dead_code)]
1935#[derive(Clone, PartialEq)]
1936pub enum ExtKind {
1937 None,
1939 SignExtend,
1941 ZeroExtend,
1943}
1944
1945#[derive(Clone, PartialEq)]
1948pub enum ExtMode {
1949 BL,
1951 BQ,
1953 WL,
1955 WQ,
1957 LQ,
1959}
1960
1961impl ExtMode {
1962 pub(crate) fn new(from_bits: u16, to_bits: u16) -> Option<ExtMode> {
1964 match (from_bits, to_bits) {
1965 (1, 8) | (1, 16) | (1, 32) | (8, 16) | (8, 32) => Some(ExtMode::BL),
1966 (1, 64) | (8, 64) => Some(ExtMode::BQ),
1967 (16, 32) => Some(ExtMode::WL),
1968 (16, 64) => Some(ExtMode::WQ),
1969 (32, 64) => Some(ExtMode::LQ),
1970 _ => None,
1971 }
1972 }
1973
1974 pub(crate) fn src_size(&self) -> u8 {
1976 match self {
1977 ExtMode::BL | ExtMode::BQ => 1,
1978 ExtMode::WL | ExtMode::WQ => 2,
1979 ExtMode::LQ => 4,
1980 }
1981 }
1982
1983 pub(crate) fn dst_size(&self) -> u8 {
1985 match self {
1986 ExtMode::BL | ExtMode::WL => 4,
1987 ExtMode::BQ | ExtMode::WQ | ExtMode::LQ => 8,
1988 }
1989 }
1990
1991 pub(crate) fn src_type(&self) -> Type {
1993 match self {
1994 ExtMode::BL | ExtMode::BQ => I8,
1995 ExtMode::WL | ExtMode::WQ => I16,
1996 ExtMode::LQ => I32,
1997 }
1998 }
1999}
2000
2001impl fmt::Debug for ExtMode {
2002 fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
2003 let name = match self {
2004 ExtMode::BL => "bl",
2005 ExtMode::BQ => "bq",
2006 ExtMode::WL => "wl",
2007 ExtMode::WQ => "wq",
2008 ExtMode::LQ => "lq",
2009 };
2010 write!(fmt, "{name}")
2011 }
2012}
2013
2014impl fmt::Display for ExtMode {
2015 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
2016 fmt::Debug::fmt(self, f)
2017 }
2018}
2019
2020#[derive(Clone, Copy)]
2022pub enum ShiftKind {
2023 ShiftLeft,
2025 ShiftRightLogical,
2027 ShiftRightArithmetic,
2029 RotateLeft,
2031 RotateRight,
2033}
2034
2035impl fmt::Debug for ShiftKind {
2036 fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
2037 let name = match self {
2038 ShiftKind::ShiftLeft => "shl",
2039 ShiftKind::ShiftRightLogical => "shr",
2040 ShiftKind::ShiftRightArithmetic => "sar",
2041 ShiftKind::RotateLeft => "rol",
2042 ShiftKind::RotateRight => "ror",
2043 };
2044 write!(fmt, "{name}")
2045 }
2046}
2047
2048impl fmt::Display for ShiftKind {
2049 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
2050 fmt::Debug::fmt(self, f)
2051 }
2052}
2053
2054#[derive(Copy, Clone, PartialEq, Eq)]
2057#[repr(u8)]
2058pub enum CC {
2059 O = 0,
2061 NO = 1,
2063
2064 B = 2,
2066 NB = 3,
2068
2069 Z = 4,
2071 NZ = 5,
2073
2074 BE = 6,
2076 NBE = 7,
2078
2079 S = 8,
2081 NS = 9,
2083
2084 L = 12,
2086 NL = 13,
2088
2089 LE = 14,
2091 NLE = 15,
2093
2094 P = 10,
2096
2097 NP = 11,
2099}
2100
2101impl CC {
2102 pub(crate) fn from_intcc(intcc: IntCC) -> Self {
2103 match intcc {
2104 IntCC::Equal => CC::Z,
2105 IntCC::NotEqual => CC::NZ,
2106 IntCC::SignedGreaterThanOrEqual => CC::NL,
2107 IntCC::SignedGreaterThan => CC::NLE,
2108 IntCC::SignedLessThanOrEqual => CC::LE,
2109 IntCC::SignedLessThan => CC::L,
2110 IntCC::UnsignedGreaterThanOrEqual => CC::NB,
2111 IntCC::UnsignedGreaterThan => CC::NBE,
2112 IntCC::UnsignedLessThanOrEqual => CC::BE,
2113 IntCC::UnsignedLessThan => CC::B,
2114 }
2115 }
2116
2117 pub(crate) fn invert(&self) -> Self {
2118 match self {
2119 CC::O => CC::NO,
2120 CC::NO => CC::O,
2121
2122 CC::B => CC::NB,
2123 CC::NB => CC::B,
2124
2125 CC::Z => CC::NZ,
2126 CC::NZ => CC::Z,
2127
2128 CC::BE => CC::NBE,
2129 CC::NBE => CC::BE,
2130
2131 CC::S => CC::NS,
2132 CC::NS => CC::S,
2133
2134 CC::L => CC::NL,
2135 CC::NL => CC::L,
2136
2137 CC::LE => CC::NLE,
2138 CC::NLE => CC::LE,
2139
2140 CC::P => CC::NP,
2141 CC::NP => CC::P,
2142 }
2143 }
2144
2145 pub(crate) fn get_enc(self) -> u8 {
2146 self as u8
2147 }
2148}
2149
2150impl fmt::Debug for CC {
2151 fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
2152 let name = match self {
2153 CC::O => "o",
2154 CC::NO => "no",
2155 CC::B => "b",
2156 CC::NB => "nb",
2157 CC::Z => "z",
2158 CC::NZ => "nz",
2159 CC::BE => "be",
2160 CC::NBE => "nbe",
2161 CC::S => "s",
2162 CC::NS => "ns",
2163 CC::L => "l",
2164 CC::NL => "nl",
2165 CC::LE => "le",
2166 CC::NLE => "nle",
2167 CC::P => "p",
2168 CC::NP => "np",
2169 };
2170 write!(fmt, "{name}")
2171 }
2172}
2173
2174impl fmt::Display for CC {
2175 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
2176 fmt::Debug::fmt(self, f)
2177 }
2178}
2179
2180#[derive(Clone, Copy)]
2184pub enum FcmpImm {
2185 Equal = 0x00,
2187 LessThan = 0x01,
2189 LessThanOrEqual = 0x02,
2191 Unordered = 0x03,
2193 NotEqual = 0x04,
2195 UnorderedOrGreaterThanOrEqual = 0x05,
2197 UnorderedOrGreaterThan = 0x06,
2199 Ordered = 0x07,
2201}
2202
2203impl FcmpImm {
2204 pub(crate) fn encode(self) -> u8 {
2205 self as u8
2206 }
2207}
2208
2209impl From<FloatCC> for FcmpImm {
2210 fn from(cond: FloatCC) -> Self {
2211 match cond {
2212 FloatCC::Equal => FcmpImm::Equal,
2213 FloatCC::LessThan => FcmpImm::LessThan,
2214 FloatCC::LessThanOrEqual => FcmpImm::LessThanOrEqual,
2215 FloatCC::Unordered => FcmpImm::Unordered,
2216 FloatCC::NotEqual => FcmpImm::NotEqual,
2217 FloatCC::UnorderedOrGreaterThanOrEqual => FcmpImm::UnorderedOrGreaterThanOrEqual,
2218 FloatCC::UnorderedOrGreaterThan => FcmpImm::UnorderedOrGreaterThan,
2219 FloatCC::Ordered => FcmpImm::Ordered,
2220 _ => panic!("unable to create comparison predicate for {cond}"),
2221 }
2222 }
2223}
2224
2225#[derive(Clone, Copy)]
2232pub enum RoundImm {
2233 RoundNearest = 0x00,
2235 RoundDown = 0x01,
2237 RoundUp = 0x02,
2239 RoundZero = 0x03,
2241}
2242
2243impl RoundImm {
2244 pub(crate) fn encode(self) -> u8 {
2245 self as u8
2246 }
2247}
2248
2249#[derive(Clone, Copy, PartialEq)]
2251pub enum OperandSize {
2252 Size8,
2254 Size16,
2256 Size32,
2258 Size64,
2260}
2261
2262impl OperandSize {
2263 pub(crate) fn from_bytes(num_bytes: u32) -> Self {
2264 match num_bytes {
2265 1 => OperandSize::Size8,
2266 2 => OperandSize::Size16,
2267 4 => OperandSize::Size32,
2268 8 => OperandSize::Size64,
2269 _ => unreachable!("Invalid OperandSize: {}", num_bytes),
2270 }
2271 }
2272
2273 pub(crate) fn from_ty(ty: Type) -> Self {
2276 Self::from_bytes(ty.lane_type().bytes())
2277 }
2278
2279 pub(crate) fn is_one_of(&self, sizes: &[Self]) -> bool {
2281 sizes.iter().any(|val| *self == *val)
2282 }
2283
2284 pub(crate) fn to_bytes(&self) -> u8 {
2285 match self {
2286 Self::Size8 => 1,
2287 Self::Size16 => 2,
2288 Self::Size32 => 4,
2289 Self::Size64 => 8,
2290 }
2291 }
2292
2293 pub(crate) fn to_bits(&self) -> u8 {
2294 self.to_bytes() * 8
2295 }
2296
2297 pub(crate) fn to_type(&self) -> Type {
2298 match self {
2299 Self::Size8 => I8,
2300 Self::Size16 => I16,
2301 Self::Size32 => I32,
2302 Self::Size64 => I64,
2303 }
2304 }
2305}
2306
2307#[derive(Clone)]
2309#[allow(dead_code)]
2310pub enum FenceKind {
2311 MFence,
2313 LFence,
2315 SFence,
2317}