1 //! Instruction operand sub-components (aka "parts"): definitions and printing.
2 
3 use super::regs::{self, show_ireg_sized};
4 use super::EmitState;
5 use crate::ir::condcodes::{FloatCC, IntCC};
6 use crate::ir::{MemFlags, Type};
7 use crate::isa::x64::inst::Inst;
8 use crate::machinst::*;
9 use regalloc::{
10     PrettyPrint, PrettyPrintSized, RealRegUniverse, Reg, RegClass, RegUsageCollector,
11     RegUsageMapper, Writable,
12 };
13 use smallvec::{smallvec, SmallVec};
14 use std::fmt;
15 use std::string::String;
16 
17 /// A possible addressing mode (amode) that can be used in instructions.
18 /// These denote a 64-bit value only.
19 #[derive(Clone, Debug)]
20 pub enum Amode {
21     /// Immediate sign-extended and a Register.
22     ImmReg {
23         simm32: u32,
24         base: Reg,
25         flags: MemFlags,
26     },
27 
28     /// sign-extend-32-to-64(Immediate) + Register1 + (Register2 << Shift)
29     ImmRegRegShift {
30         simm32: u32,
31         base: Reg,
32         index: Reg,
33         shift: u8, /* 0 .. 3 only */
34         flags: MemFlags,
35     },
36 
37     /// sign-extend-32-to-64(Immediate) + RIP (instruction pointer).
38     /// To wit: not supported in 32-bits mode.
39     RipRelative { target: MachLabel },
40 }
41 
42 impl Amode {
imm_reg(simm32: u32, base: Reg) -> Self43     pub(crate) fn imm_reg(simm32: u32, base: Reg) -> Self {
44         debug_assert!(base.get_class() == RegClass::I64);
45         Self::ImmReg {
46             simm32,
47             base,
48             flags: MemFlags::trusted(),
49         }
50     }
51 
imm_reg_reg_shift(simm32: u32, base: Reg, index: Reg, shift: u8) -> Self52     pub(crate) fn imm_reg_reg_shift(simm32: u32, base: Reg, index: Reg, shift: u8) -> Self {
53         debug_assert!(base.get_class() == RegClass::I64);
54         debug_assert!(index.get_class() == RegClass::I64);
55         debug_assert!(shift <= 3);
56         Self::ImmRegRegShift {
57             simm32,
58             base,
59             index,
60             shift,
61             flags: MemFlags::trusted(),
62         }
63     }
64 
rip_relative(target: MachLabel) -> Self65     pub(crate) fn rip_relative(target: MachLabel) -> Self {
66         Self::RipRelative { target }
67     }
68 
with_flags(&self, flags: MemFlags) -> Self69     pub(crate) fn with_flags(&self, flags: MemFlags) -> Self {
70         match self {
71             &Self::ImmReg { simm32, base, .. } => Self::ImmReg {
72                 simm32,
73                 base,
74                 flags,
75             },
76             &Self::ImmRegRegShift {
77                 simm32,
78                 base,
79                 index,
80                 shift,
81                 ..
82             } => Self::ImmRegRegShift {
83                 simm32,
84                 base,
85                 index,
86                 shift,
87                 flags,
88             },
89             _ => panic!("Amode {:?} cannot take memflags", self),
90         }
91     }
92 
93     /// Add the regs mentioned by `self` to `collector`.
get_regs_as_uses(&self, collector: &mut RegUsageCollector)94     pub(crate) fn get_regs_as_uses(&self, collector: &mut RegUsageCollector) {
95         match self {
96             Amode::ImmReg { base, .. } => {
97                 collector.add_use(*base);
98             }
99             Amode::ImmRegRegShift { base, index, .. } => {
100                 collector.add_use(*base);
101                 collector.add_use(*index);
102             }
103             Amode::RipRelative { .. } => {
104                 // RIP isn't involved in regalloc.
105             }
106         }
107     }
108 
get_flags(&self) -> MemFlags109     pub(crate) fn get_flags(&self) -> MemFlags {
110         match self {
111             Amode::ImmReg { flags, .. } => *flags,
112             Amode::ImmRegRegShift { flags, .. } => *flags,
113             Amode::RipRelative { .. } => MemFlags::trusted(),
114         }
115     }
116 
can_trap(&self) -> bool117     pub(crate) fn can_trap(&self) -> bool {
118         !self.get_flags().notrap()
119     }
120 }
121 
122 impl PrettyPrint for Amode {
show_rru(&self, mb_rru: Option<&RealRegUniverse>) -> String123     fn show_rru(&self, mb_rru: Option<&RealRegUniverse>) -> String {
124         match self {
125             Amode::ImmReg { simm32, base, .. } => {
126                 format!("{}({})", *simm32 as i32, base.show_rru(mb_rru))
127             }
128             Amode::ImmRegRegShift {
129                 simm32,
130                 base,
131                 index,
132                 shift,
133                 ..
134             } => format!(
135                 "{}({},{},{})",
136                 *simm32 as i32,
137                 base.show_rru(mb_rru),
138                 index.show_rru(mb_rru),
139                 1 << shift
140             ),
141             Amode::RipRelative { ref target } => format!("label{}(%rip)", target.get()),
142         }
143     }
144 }
145 
146 /// A Memory Address. These denote a 64-bit value only.
147 /// Used for usual addressing modes as well as addressing modes used during compilation, when the
148 /// moving SP offset is not known.
149 #[derive(Clone, Debug)]
150 pub enum SyntheticAmode {
151     /// A real amode.
152     Real(Amode),
153 
154     /// A (virtual) offset to the "nominal SP" value, which will be recomputed as we push and pop
155     /// within the function.
156     NominalSPOffset { simm32: u32 },
157 
158     /// A virtual offset to a constant that will be emitted in the constant section of the buffer.
159     ConstantOffset(VCodeConstant),
160 }
161 
162 impl SyntheticAmode {
nominal_sp_offset(simm32: u32) -> Self163     pub(crate) fn nominal_sp_offset(simm32: u32) -> Self {
164         SyntheticAmode::NominalSPOffset { simm32 }
165     }
166 
167     /// Add the regs mentioned by `self` to `collector`.
get_regs_as_uses(&self, collector: &mut RegUsageCollector)168     pub(crate) fn get_regs_as_uses(&self, collector: &mut RegUsageCollector) {
169         match self {
170             SyntheticAmode::Real(addr) => addr.get_regs_as_uses(collector),
171             SyntheticAmode::NominalSPOffset { .. } => {
172                 // Nothing to do; the base is SP and isn't involved in regalloc.
173             }
174             SyntheticAmode::ConstantOffset(_) => {}
175         }
176     }
177 
map_uses<RUM: RegUsageMapper>(&mut self, map: &RUM)178     pub(crate) fn map_uses<RUM: RegUsageMapper>(&mut self, map: &RUM) {
179         match self {
180             SyntheticAmode::Real(addr) => addr.map_uses(map),
181             SyntheticAmode::NominalSPOffset { .. } => {
182                 // Nothing to do.
183             }
184             SyntheticAmode::ConstantOffset(_) => {}
185         }
186     }
187 
finalize(&self, state: &mut EmitState, buffer: &MachBuffer<Inst>) -> Amode188     pub(crate) fn finalize(&self, state: &mut EmitState, buffer: &MachBuffer<Inst>) -> Amode {
189         match self {
190             SyntheticAmode::Real(addr) => addr.clone(),
191             SyntheticAmode::NominalSPOffset { simm32 } => {
192                 let off = *simm32 as i64 + state.virtual_sp_offset;
193                 // TODO will require a sequence of add etc.
194                 assert!(
195                     off <= u32::max_value() as i64,
196                     "amode finalize: add sequence NYI"
197                 );
198                 Amode::imm_reg(off as u32, regs::rsp())
199             }
200             SyntheticAmode::ConstantOffset(c) => {
201                 Amode::rip_relative(buffer.get_label_for_constant(*c))
202             }
203         }
204     }
205 }
206 
207 impl Into<SyntheticAmode> for Amode {
into(self) -> SyntheticAmode208     fn into(self) -> SyntheticAmode {
209         SyntheticAmode::Real(self)
210     }
211 }
212 
213 impl PrettyPrint for SyntheticAmode {
show_rru(&self, mb_rru: Option<&RealRegUniverse>) -> String214     fn show_rru(&self, mb_rru: Option<&RealRegUniverse>) -> String {
215         match self {
216             SyntheticAmode::Real(addr) => addr.show_rru(mb_rru),
217             SyntheticAmode::NominalSPOffset { simm32 } => {
218                 format!("rsp({} + virtual offset)", *simm32 as i32)
219             }
220             SyntheticAmode::ConstantOffset(c) => format!("const({:?})", c),
221         }
222     }
223 }
224 
225 /// An operand which is either an integer Register, a value in Memory or an Immediate.  This can
226 /// denote an 8, 16, 32 or 64 bit value.  For the Immediate form, in the 8- and 16-bit case, only
227 /// the lower 8 or 16 bits of `simm32` is relevant.  In the 64-bit case, the value denoted by
228 /// `simm32` is its sign-extension out to 64 bits.
229 #[derive(Clone)]
230 pub enum RegMemImm {
231     Reg { reg: Reg },
232     Mem { addr: SyntheticAmode },
233     Imm { simm32: u32 },
234 }
235 
236 impl RegMemImm {
reg(reg: Reg) -> Self237     pub(crate) fn reg(reg: Reg) -> Self {
238         debug_assert!(reg.get_class() == RegClass::I64 || reg.get_class() == RegClass::V128);
239         Self::Reg { reg }
240     }
mem(addr: impl Into<SyntheticAmode>) -> Self241     pub(crate) fn mem(addr: impl Into<SyntheticAmode>) -> Self {
242         Self::Mem { addr: addr.into() }
243     }
imm(simm32: u32) -> Self244     pub(crate) fn imm(simm32: u32) -> Self {
245         Self::Imm { simm32 }
246     }
247 
248     /// Asserts that in register mode, the reg class is the one that's expected.
assert_regclass_is(&self, expected_reg_class: RegClass)249     pub(crate) fn assert_regclass_is(&self, expected_reg_class: RegClass) {
250         if let Self::Reg { reg } = self {
251             debug_assert_eq!(reg.get_class(), expected_reg_class);
252         }
253     }
254 
255     /// Add the regs mentioned by `self` to `collector`.
get_regs_as_uses(&self, collector: &mut RegUsageCollector)256     pub(crate) fn get_regs_as_uses(&self, collector: &mut RegUsageCollector) {
257         match self {
258             Self::Reg { reg } => collector.add_use(*reg),
259             Self::Mem { addr } => addr.get_regs_as_uses(collector),
260             Self::Imm { .. } => {}
261         }
262     }
263 
to_reg(&self) -> Option<Reg>264     pub(crate) fn to_reg(&self) -> Option<Reg> {
265         match self {
266             Self::Reg { reg } => Some(*reg),
267             _ => None,
268         }
269     }
270 }
271 
272 impl PrettyPrint for RegMemImm {
show_rru(&self, mb_rru: Option<&RealRegUniverse>) -> String273     fn show_rru(&self, mb_rru: Option<&RealRegUniverse>) -> String {
274         self.show_rru_sized(mb_rru, 8)
275     }
276 }
277 
278 impl PrettyPrintSized for RegMemImm {
show_rru_sized(&self, mb_rru: Option<&RealRegUniverse>, size: u8) -> String279     fn show_rru_sized(&self, mb_rru: Option<&RealRegUniverse>, size: u8) -> String {
280         match self {
281             Self::Reg { reg } => show_ireg_sized(*reg, mb_rru, size),
282             Self::Mem { addr } => addr.show_rru(mb_rru),
283             Self::Imm { simm32 } => format!("${}", *simm32 as i32),
284         }
285     }
286 }
287 
288 /// An operand which is either an integer Register or a value in Memory.  This can denote an 8, 16,
289 /// 32, 64, or 128 bit value.
290 #[derive(Clone, Debug)]
291 pub enum RegMem {
292     Reg { reg: Reg },
293     Mem { addr: SyntheticAmode },
294 }
295 
296 impl RegMem {
reg(reg: Reg) -> Self297     pub(crate) fn reg(reg: Reg) -> Self {
298         debug_assert!(reg.get_class() == RegClass::I64 || reg.get_class() == RegClass::V128);
299         Self::Reg { reg }
300     }
mem(addr: impl Into<SyntheticAmode>) -> Self301     pub(crate) fn mem(addr: impl Into<SyntheticAmode>) -> Self {
302         Self::Mem { addr: addr.into() }
303     }
304     /// Asserts that in register mode, the reg class is the one that's expected.
assert_regclass_is(&self, expected_reg_class: RegClass)305     pub(crate) fn assert_regclass_is(&self, expected_reg_class: RegClass) {
306         if let Self::Reg { reg } = self {
307             debug_assert_eq!(reg.get_class(), expected_reg_class);
308         }
309     }
310     /// Add the regs mentioned by `self` to `collector`.
get_regs_as_uses(&self, collector: &mut RegUsageCollector)311     pub(crate) fn get_regs_as_uses(&self, collector: &mut RegUsageCollector) {
312         match self {
313             RegMem::Reg { reg } => collector.add_use(*reg),
314             RegMem::Mem { addr, .. } => addr.get_regs_as_uses(collector),
315         }
316     }
to_reg(&self) -> Option<Reg>317     pub(crate) fn to_reg(&self) -> Option<Reg> {
318         match self {
319             RegMem::Reg { reg } => Some(*reg),
320             _ => None,
321         }
322     }
323 }
324 
325 impl From<Writable<Reg>> for RegMem {
from(r: Writable<Reg>) -> Self326     fn from(r: Writable<Reg>) -> Self {
327         RegMem::reg(r.to_reg())
328     }
329 }
330 
331 impl PrettyPrint for RegMem {
show_rru(&self, mb_rru: Option<&RealRegUniverse>) -> String332     fn show_rru(&self, mb_rru: Option<&RealRegUniverse>) -> String {
333         self.show_rru_sized(mb_rru, 8)
334     }
335 }
336 
337 impl PrettyPrintSized for RegMem {
show_rru_sized(&self, mb_rru: Option<&RealRegUniverse>, size: u8) -> String338     fn show_rru_sized(&self, mb_rru: Option<&RealRegUniverse>, size: u8) -> String {
339         match self {
340             RegMem::Reg { reg } => show_ireg_sized(*reg, mb_rru, size),
341             RegMem::Mem { addr, .. } => addr.show_rru(mb_rru),
342         }
343     }
344 }
345 
346 /// Some basic ALU operations.  TODO: maybe add Adc, Sbb.
347 #[derive(Copy, Clone, PartialEq)]
348 pub enum AluRmiROpcode {
349     Add,
350     Adc,
351     Sub,
352     Sbb,
353     And,
354     Or,
355     Xor,
356     /// The signless, non-extending (N x N -> N, for N in {32,64}) variant.
357     Mul,
358     /// 8-bit form of And. Handled separately as we don't have full 8-bit op
359     /// support (we just use wider instructions). Used only with some sequences
360     /// with SETcc.
361     And8,
362     /// 8-bit form of Or.
363     Or8,
364 }
365 
366 impl fmt::Debug for AluRmiROpcode {
fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result367     fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
368         let name = match self {
369             AluRmiROpcode::Add => "add",
370             AluRmiROpcode::Adc => "adc",
371             AluRmiROpcode::Sub => "sub",
372             AluRmiROpcode::Sbb => "sbb",
373             AluRmiROpcode::And => "and",
374             AluRmiROpcode::Or => "or",
375             AluRmiROpcode::Xor => "xor",
376             AluRmiROpcode::Mul => "imul",
377             AluRmiROpcode::And8 => "and",
378             AluRmiROpcode::Or8 => "or",
379         };
380         write!(fmt, "{}", name)
381     }
382 }
383 
384 impl fmt::Display for AluRmiROpcode {
fmt(&self, f: &mut fmt::Formatter) -> fmt::Result385     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
386         fmt::Debug::fmt(self, f)
387     }
388 }
389 
390 impl AluRmiROpcode {
391     /// Is this a special-cased 8-bit ALU op?
is_8bit(self) -> bool392     pub fn is_8bit(self) -> bool {
393         match self {
394             AluRmiROpcode::And8 | AluRmiROpcode::Or8 => true,
395             _ => false,
396         }
397     }
398 }
399 
400 #[derive(Clone, PartialEq)]
401 pub enum UnaryRmROpcode {
402     /// Bit-scan reverse.
403     Bsr,
404     /// Bit-scan forward.
405     Bsf,
406     /// Counts leading zeroes (Leading Zero CouNT).
407     Lzcnt,
408     /// Counts trailing zeroes (Trailing Zero CouNT).
409     Tzcnt,
410     /// Counts the number of ones (POPulation CouNT).
411     Popcnt,
412 }
413 
414 impl UnaryRmROpcode {
available_from(&self) -> SmallVec<[InstructionSet; 2]>415     pub(crate) fn available_from(&self) -> SmallVec<[InstructionSet; 2]> {
416         match self {
417             UnaryRmROpcode::Bsr | UnaryRmROpcode::Bsf => smallvec![],
418             UnaryRmROpcode::Lzcnt => smallvec![InstructionSet::Lzcnt],
419             UnaryRmROpcode::Tzcnt => smallvec![InstructionSet::BMI1],
420             UnaryRmROpcode::Popcnt => smallvec![InstructionSet::Popcnt],
421         }
422     }
423 }
424 
425 impl fmt::Debug for UnaryRmROpcode {
fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result426     fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
427         match self {
428             UnaryRmROpcode::Bsr => write!(fmt, "bsr"),
429             UnaryRmROpcode::Bsf => write!(fmt, "bsf"),
430             UnaryRmROpcode::Lzcnt => write!(fmt, "lzcnt"),
431             UnaryRmROpcode::Tzcnt => write!(fmt, "tzcnt"),
432             UnaryRmROpcode::Popcnt => write!(fmt, "popcnt"),
433         }
434     }
435 }
436 
437 impl fmt::Display for UnaryRmROpcode {
fmt(&self, f: &mut fmt::Formatter) -> fmt::Result438     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
439         fmt::Debug::fmt(self, f)
440     }
441 }
442 
443 #[derive(Clone, Copy, PartialEq)]
444 pub enum CmpOpcode {
445     /// CMP instruction: compute `a - b` and set flags from result.
446     Cmp,
447     /// TEST instruction: compute `a & b` and set flags from result.
448     Test,
449 }
450 
451 #[derive(Debug)]
452 pub(crate) enum InstructionSet {
453     SSE,
454     SSE2,
455     SSSE3,
456     SSE41,
457     SSE42,
458     Popcnt,
459     Lzcnt,
460     BMI1,
461     #[allow(dead_code)] // never constructed (yet).
462     BMI2,
463     AVX512F,
464     AVX512VL,
465     AVX512DQ,
466 }
467 
468 /// Some SSE operations requiring 2 operands r/m and r.
469 #[derive(Clone, Copy, PartialEq)]
470 #[allow(dead_code)] // some variants here aren't used just yet
471 pub enum SseOpcode {
472     Addps,
473     Addpd,
474     Addss,
475     Addsd,
476     Andps,
477     Andpd,
478     Andnps,
479     Andnpd,
480     Blendvpd,
481     Blendvps,
482     Comiss,
483     Comisd,
484     Cmpps,
485     Cmppd,
486     Cmpss,
487     Cmpsd,
488     Cvtdq2ps,
489     Cvtdq2pd,
490     Cvtsd2ss,
491     Cvtsd2si,
492     Cvtsi2ss,
493     Cvtsi2sd,
494     Cvtss2si,
495     Cvtss2sd,
496     Cvttps2dq,
497     Cvttss2si,
498     Cvttsd2si,
499     Divps,
500     Divpd,
501     Divss,
502     Divsd,
503     Insertps,
504     Maxps,
505     Maxpd,
506     Maxss,
507     Maxsd,
508     Minps,
509     Minpd,
510     Minss,
511     Minsd,
512     Movaps,
513     Movapd,
514     Movd,
515     Movdqa,
516     Movdqu,
517     Movlhps,
518     Movmskps,
519     Movmskpd,
520     Movq,
521     Movss,
522     Movsd,
523     Movups,
524     Movupd,
525     Mulps,
526     Mulpd,
527     Mulss,
528     Mulsd,
529     Orps,
530     Orpd,
531     Pabsb,
532     Pabsw,
533     Pabsd,
534     Packssdw,
535     Packsswb,
536     Packusdw,
537     Packuswb,
538     Paddb,
539     Paddd,
540     Paddq,
541     Paddw,
542     Paddsb,
543     Paddsw,
544     Paddusb,
545     Paddusw,
546     Palignr,
547     Pand,
548     Pandn,
549     Pavgb,
550     Pavgw,
551     Pblendvb,
552     Pcmpeqb,
553     Pcmpeqw,
554     Pcmpeqd,
555     Pcmpeqq,
556     Pcmpgtb,
557     Pcmpgtw,
558     Pcmpgtd,
559     Pcmpgtq,
560     Pextrb,
561     Pextrw,
562     Pextrd,
563     Pinsrb,
564     Pinsrw,
565     Pinsrd,
566     Pmaddwd,
567     Pmaxsb,
568     Pmaxsw,
569     Pmaxsd,
570     Pmaxub,
571     Pmaxuw,
572     Pmaxud,
573     Pminsb,
574     Pminsw,
575     Pminsd,
576     Pminub,
577     Pminuw,
578     Pminud,
579     Pmovmskb,
580     Pmovsxbd,
581     Pmovsxbw,
582     Pmovsxbq,
583     Pmovsxwd,
584     Pmovsxwq,
585     Pmovsxdq,
586     Pmovzxbd,
587     Pmovzxbw,
588     Pmovzxbq,
589     Pmovzxwd,
590     Pmovzxwq,
591     Pmovzxdq,
592     Pmulld,
593     Pmullw,
594     Pmuludq,
595     Por,
596     Pshufb,
597     Pshufd,
598     Psllw,
599     Pslld,
600     Psllq,
601     Psraw,
602     Psrad,
603     Psrlw,
604     Psrld,
605     Psrlq,
606     Psubb,
607     Psubd,
608     Psubq,
609     Psubw,
610     Psubsb,
611     Psubsw,
612     Psubusb,
613     Psubusw,
614     Ptest,
615     Punpckhbw,
616     Punpcklbw,
617     Pxor,
618     Rcpss,
619     Roundps,
620     Roundpd,
621     Roundss,
622     Roundsd,
623     Rsqrtss,
624     Sqrtps,
625     Sqrtpd,
626     Sqrtss,
627     Sqrtsd,
628     Subps,
629     Subpd,
630     Subss,
631     Subsd,
632     Ucomiss,
633     Ucomisd,
634     Xorps,
635     Xorpd,
636 }
637 
638 impl SseOpcode {
639     /// Which `InstructionSet` is the first supporting this opcode?
available_from(&self) -> InstructionSet640     pub(crate) fn available_from(&self) -> InstructionSet {
641         use InstructionSet::*;
642         match self {
643             SseOpcode::Addps
644             | SseOpcode::Addss
645             | SseOpcode::Andps
646             | SseOpcode::Andnps
647             | SseOpcode::Comiss
648             | SseOpcode::Cmpps
649             | SseOpcode::Cmpss
650             | SseOpcode::Cvtsi2ss
651             | SseOpcode::Cvtss2si
652             | SseOpcode::Cvttss2si
653             | SseOpcode::Divps
654             | SseOpcode::Divss
655             | SseOpcode::Maxps
656             | SseOpcode::Maxss
657             | SseOpcode::Minps
658             | SseOpcode::Minss
659             | SseOpcode::Movaps
660             | SseOpcode::Movlhps
661             | SseOpcode::Movmskps
662             | SseOpcode::Movss
663             | SseOpcode::Movups
664             | SseOpcode::Mulps
665             | SseOpcode::Mulss
666             | SseOpcode::Orps
667             | SseOpcode::Rcpss
668             | SseOpcode::Rsqrtss
669             | SseOpcode::Sqrtps
670             | SseOpcode::Sqrtss
671             | SseOpcode::Subps
672             | SseOpcode::Subss
673             | SseOpcode::Ucomiss
674             | SseOpcode::Xorps => SSE,
675 
676             SseOpcode::Addpd
677             | SseOpcode::Addsd
678             | SseOpcode::Andpd
679             | SseOpcode::Andnpd
680             | SseOpcode::Cmppd
681             | SseOpcode::Cmpsd
682             | SseOpcode::Comisd
683             | SseOpcode::Cvtdq2ps
684             | SseOpcode::Cvtdq2pd
685             | SseOpcode::Cvtsd2ss
686             | SseOpcode::Cvtsd2si
687             | SseOpcode::Cvtsi2sd
688             | SseOpcode::Cvtss2sd
689             | SseOpcode::Cvttps2dq
690             | SseOpcode::Cvttsd2si
691             | SseOpcode::Divpd
692             | SseOpcode::Divsd
693             | SseOpcode::Maxpd
694             | SseOpcode::Maxsd
695             | SseOpcode::Minpd
696             | SseOpcode::Minsd
697             | SseOpcode::Movapd
698             | SseOpcode::Movd
699             | SseOpcode::Movmskpd
700             | SseOpcode::Movq
701             | SseOpcode::Movsd
702             | SseOpcode::Movupd
703             | SseOpcode::Movdqa
704             | SseOpcode::Movdqu
705             | SseOpcode::Mulpd
706             | SseOpcode::Mulsd
707             | SseOpcode::Orpd
708             | SseOpcode::Packssdw
709             | SseOpcode::Packsswb
710             | SseOpcode::Packuswb
711             | SseOpcode::Paddb
712             | SseOpcode::Paddd
713             | SseOpcode::Paddq
714             | SseOpcode::Paddw
715             | SseOpcode::Paddsb
716             | SseOpcode::Paddsw
717             | SseOpcode::Paddusb
718             | SseOpcode::Paddusw
719             | SseOpcode::Pand
720             | SseOpcode::Pandn
721             | SseOpcode::Pavgb
722             | SseOpcode::Pavgw
723             | SseOpcode::Pcmpeqb
724             | SseOpcode::Pcmpeqw
725             | SseOpcode::Pcmpeqd
726             | SseOpcode::Pcmpgtb
727             | SseOpcode::Pcmpgtw
728             | SseOpcode::Pcmpgtd
729             | SseOpcode::Pextrw
730             | SseOpcode::Pinsrw
731             | SseOpcode::Pmaddwd
732             | SseOpcode::Pmaxsw
733             | SseOpcode::Pmaxub
734             | SseOpcode::Pminsw
735             | SseOpcode::Pminub
736             | SseOpcode::Pmovmskb
737             | SseOpcode::Pmullw
738             | SseOpcode::Pmuludq
739             | SseOpcode::Por
740             | SseOpcode::Pshufd
741             | SseOpcode::Psllw
742             | SseOpcode::Pslld
743             | SseOpcode::Psllq
744             | SseOpcode::Psraw
745             | SseOpcode::Psrad
746             | SseOpcode::Psrlw
747             | SseOpcode::Psrld
748             | SseOpcode::Psrlq
749             | SseOpcode::Psubb
750             | SseOpcode::Psubd
751             | SseOpcode::Psubq
752             | SseOpcode::Psubw
753             | SseOpcode::Psubsb
754             | SseOpcode::Psubsw
755             | SseOpcode::Psubusb
756             | SseOpcode::Psubusw
757             | SseOpcode::Punpckhbw
758             | SseOpcode::Punpcklbw
759             | SseOpcode::Pxor
760             | SseOpcode::Sqrtpd
761             | SseOpcode::Sqrtsd
762             | SseOpcode::Subpd
763             | SseOpcode::Subsd
764             | SseOpcode::Ucomisd
765             | SseOpcode::Xorpd => SSE2,
766 
767             SseOpcode::Pabsb
768             | SseOpcode::Pabsw
769             | SseOpcode::Pabsd
770             | SseOpcode::Palignr
771             | SseOpcode::Pshufb => SSSE3,
772 
773             SseOpcode::Blendvpd
774             | SseOpcode::Blendvps
775             | SseOpcode::Insertps
776             | SseOpcode::Packusdw
777             | SseOpcode::Pblendvb
778             | SseOpcode::Pcmpeqq
779             | SseOpcode::Pextrb
780             | SseOpcode::Pextrd
781             | SseOpcode::Pinsrb
782             | SseOpcode::Pinsrd
783             | SseOpcode::Pmaxsb
784             | SseOpcode::Pmaxsd
785             | SseOpcode::Pmaxuw
786             | SseOpcode::Pmaxud
787             | SseOpcode::Pminsb
788             | SseOpcode::Pminsd
789             | SseOpcode::Pminuw
790             | SseOpcode::Pminud
791             | SseOpcode::Pmovsxbd
792             | SseOpcode::Pmovsxbw
793             | SseOpcode::Pmovsxbq
794             | SseOpcode::Pmovsxwd
795             | SseOpcode::Pmovsxwq
796             | SseOpcode::Pmovsxdq
797             | SseOpcode::Pmovzxbd
798             | SseOpcode::Pmovzxbw
799             | SseOpcode::Pmovzxbq
800             | SseOpcode::Pmovzxwd
801             | SseOpcode::Pmovzxwq
802             | SseOpcode::Pmovzxdq
803             | SseOpcode::Pmulld
804             | SseOpcode::Ptest
805             | SseOpcode::Roundps
806             | SseOpcode::Roundpd
807             | SseOpcode::Roundss
808             | SseOpcode::Roundsd => SSE41,
809 
810             SseOpcode::Pcmpgtq => SSE42,
811         }
812     }
813 
814     /// Returns the src operand size for an instruction.
src_size(&self) -> u8815     pub(crate) fn src_size(&self) -> u8 {
816         match self {
817             SseOpcode::Movd => 4,
818             _ => 8,
819         }
820     }
821 }
822 
823 impl fmt::Debug for SseOpcode {
fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result824     fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
825         let name = match self {
826             SseOpcode::Addps => "addps",
827             SseOpcode::Addpd => "addpd",
828             SseOpcode::Addss => "addss",
829             SseOpcode::Addsd => "addsd",
830             SseOpcode::Andpd => "andpd",
831             SseOpcode::Andps => "andps",
832             SseOpcode::Andnps => "andnps",
833             SseOpcode::Andnpd => "andnpd",
834             SseOpcode::Blendvpd => "blendvpd",
835             SseOpcode::Blendvps => "blendvps",
836             SseOpcode::Cmpps => "cmpps",
837             SseOpcode::Cmppd => "cmppd",
838             SseOpcode::Cmpss => "cmpss",
839             SseOpcode::Cmpsd => "cmpsd",
840             SseOpcode::Comiss => "comiss",
841             SseOpcode::Comisd => "comisd",
842             SseOpcode::Cvtdq2ps => "cvtdq2ps",
843             SseOpcode::Cvtdq2pd => "cvtdq2pd",
844             SseOpcode::Cvtsd2ss => "cvtsd2ss",
845             SseOpcode::Cvtsd2si => "cvtsd2si",
846             SseOpcode::Cvtsi2ss => "cvtsi2ss",
847             SseOpcode::Cvtsi2sd => "cvtsi2sd",
848             SseOpcode::Cvtss2si => "cvtss2si",
849             SseOpcode::Cvtss2sd => "cvtss2sd",
850             SseOpcode::Cvttps2dq => "cvttps2dq",
851             SseOpcode::Cvttss2si => "cvttss2si",
852             SseOpcode::Cvttsd2si => "cvttsd2si",
853             SseOpcode::Divps => "divps",
854             SseOpcode::Divpd => "divpd",
855             SseOpcode::Divss => "divss",
856             SseOpcode::Divsd => "divsd",
857             SseOpcode::Insertps => "insertps",
858             SseOpcode::Maxps => "maxps",
859             SseOpcode::Maxpd => "maxpd",
860             SseOpcode::Maxss => "maxss",
861             SseOpcode::Maxsd => "maxsd",
862             SseOpcode::Minps => "minps",
863             SseOpcode::Minpd => "minpd",
864             SseOpcode::Minss => "minss",
865             SseOpcode::Minsd => "minsd",
866             SseOpcode::Movaps => "movaps",
867             SseOpcode::Movapd => "movapd",
868             SseOpcode::Movd => "movd",
869             SseOpcode::Movdqa => "movdqa",
870             SseOpcode::Movdqu => "movdqu",
871             SseOpcode::Movlhps => "movlhps",
872             SseOpcode::Movmskps => "movmskps",
873             SseOpcode::Movmskpd => "movmskpd",
874             SseOpcode::Movq => "movq",
875             SseOpcode::Movss => "movss",
876             SseOpcode::Movsd => "movsd",
877             SseOpcode::Movups => "movups",
878             SseOpcode::Movupd => "movupd",
879             SseOpcode::Mulps => "mulps",
880             SseOpcode::Mulpd => "mulpd",
881             SseOpcode::Mulss => "mulss",
882             SseOpcode::Mulsd => "mulsd",
883             SseOpcode::Orpd => "orpd",
884             SseOpcode::Orps => "orps",
885             SseOpcode::Pabsb => "pabsb",
886             SseOpcode::Pabsw => "pabsw",
887             SseOpcode::Pabsd => "pabsd",
888             SseOpcode::Packssdw => "packssdw",
889             SseOpcode::Packsswb => "packsswb",
890             SseOpcode::Packusdw => "packusdw",
891             SseOpcode::Packuswb => "packuswb",
892             SseOpcode::Paddb => "paddb",
893             SseOpcode::Paddd => "paddd",
894             SseOpcode::Paddq => "paddq",
895             SseOpcode::Paddw => "paddw",
896             SseOpcode::Paddsb => "paddsb",
897             SseOpcode::Paddsw => "paddsw",
898             SseOpcode::Paddusb => "paddusb",
899             SseOpcode::Paddusw => "paddusw",
900             SseOpcode::Palignr => "palignr",
901             SseOpcode::Pand => "pand",
902             SseOpcode::Pandn => "pandn",
903             SseOpcode::Pavgb => "pavgb",
904             SseOpcode::Pavgw => "pavgw",
905             SseOpcode::Pblendvb => "pblendvb",
906             SseOpcode::Pcmpeqb => "pcmpeqb",
907             SseOpcode::Pcmpeqw => "pcmpeqw",
908             SseOpcode::Pcmpeqd => "pcmpeqd",
909             SseOpcode::Pcmpeqq => "pcmpeqq",
910             SseOpcode::Pcmpgtb => "pcmpgtb",
911             SseOpcode::Pcmpgtw => "pcmpgtw",
912             SseOpcode::Pcmpgtd => "pcmpgtd",
913             SseOpcode::Pcmpgtq => "pcmpgtq",
914             SseOpcode::Pextrb => "pextrb",
915             SseOpcode::Pextrw => "pextrw",
916             SseOpcode::Pextrd => "pextrd",
917             SseOpcode::Pinsrb => "pinsrb",
918             SseOpcode::Pinsrw => "pinsrw",
919             SseOpcode::Pinsrd => "pinsrd",
920             SseOpcode::Pmaddwd => "pmaddwd",
921             SseOpcode::Pmaxsb => "pmaxsb",
922             SseOpcode::Pmaxsw => "pmaxsw",
923             SseOpcode::Pmaxsd => "pmaxsd",
924             SseOpcode::Pmaxub => "pmaxub",
925             SseOpcode::Pmaxuw => "pmaxuw",
926             SseOpcode::Pmaxud => "pmaxud",
927             SseOpcode::Pminsb => "pminsb",
928             SseOpcode::Pminsw => "pminsw",
929             SseOpcode::Pminsd => "pminsd",
930             SseOpcode::Pminub => "pminub",
931             SseOpcode::Pminuw => "pminuw",
932             SseOpcode::Pminud => "pminud",
933             SseOpcode::Pmovmskb => "pmovmskb",
934             SseOpcode::Pmovsxbd => "pmovsxbd",
935             SseOpcode::Pmovsxbw => "pmovsxbw",
936             SseOpcode::Pmovsxbq => "pmovsxbq",
937             SseOpcode::Pmovsxwd => "pmovsxwd",
938             SseOpcode::Pmovsxwq => "pmovsxwq",
939             SseOpcode::Pmovsxdq => "pmovsxdq",
940             SseOpcode::Pmovzxbd => "pmovzxbd",
941             SseOpcode::Pmovzxbw => "pmovzxbw",
942             SseOpcode::Pmovzxbq => "pmovzxbq",
943             SseOpcode::Pmovzxwd => "pmovzxwd",
944             SseOpcode::Pmovzxwq => "pmovzxwq",
945             SseOpcode::Pmovzxdq => "pmovzxdq",
946             SseOpcode::Pmulld => "pmulld",
947             SseOpcode::Pmullw => "pmullw",
948             SseOpcode::Pmuludq => "pmuludq",
949             SseOpcode::Por => "por",
950             SseOpcode::Pshufb => "pshufb",
951             SseOpcode::Pshufd => "pshufd",
952             SseOpcode::Psllw => "psllw",
953             SseOpcode::Pslld => "pslld",
954             SseOpcode::Psllq => "psllq",
955             SseOpcode::Psraw => "psraw",
956             SseOpcode::Psrad => "psrad",
957             SseOpcode::Psrlw => "psrlw",
958             SseOpcode::Psrld => "psrld",
959             SseOpcode::Psrlq => "psrlq",
960             SseOpcode::Psubb => "psubb",
961             SseOpcode::Psubd => "psubd",
962             SseOpcode::Psubq => "psubq",
963             SseOpcode::Psubw => "psubw",
964             SseOpcode::Psubsb => "psubsb",
965             SseOpcode::Psubsw => "psubsw",
966             SseOpcode::Psubusb => "psubusb",
967             SseOpcode::Psubusw => "psubusw",
968             SseOpcode::Ptest => "ptest",
969             SseOpcode::Punpckhbw => "punpckhbw",
970             SseOpcode::Punpcklbw => "punpcklbw",
971             SseOpcode::Pxor => "pxor",
972             SseOpcode::Rcpss => "rcpss",
973             SseOpcode::Roundps => "roundps",
974             SseOpcode::Roundpd => "roundpd",
975             SseOpcode::Roundss => "roundss",
976             SseOpcode::Roundsd => "roundsd",
977             SseOpcode::Rsqrtss => "rsqrtss",
978             SseOpcode::Sqrtps => "sqrtps",
979             SseOpcode::Sqrtpd => "sqrtpd",
980             SseOpcode::Sqrtss => "sqrtss",
981             SseOpcode::Sqrtsd => "sqrtsd",
982             SseOpcode::Subps => "subps",
983             SseOpcode::Subpd => "subpd",
984             SseOpcode::Subss => "subss",
985             SseOpcode::Subsd => "subsd",
986             SseOpcode::Ucomiss => "ucomiss",
987             SseOpcode::Ucomisd => "ucomisd",
988             SseOpcode::Xorps => "xorps",
989             SseOpcode::Xorpd => "xorpd",
990         };
991         write!(fmt, "{}", name)
992     }
993 }
994 
995 impl fmt::Display for SseOpcode {
fmt(&self, f: &mut fmt::Formatter) -> fmt::Result996     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
997         fmt::Debug::fmt(self, f)
998     }
999 }
1000 
1001 #[derive(Clone)]
1002 pub enum Avx512Opcode {
1003     Vcvtudq2ps,
1004     Vpabsq,
1005     Vpmullq,
1006 }
1007 
1008 impl Avx512Opcode {
1009     /// Which `InstructionSet`s support the opcode?
available_from(&self) -> SmallVec<[InstructionSet; 2]>1010     pub(crate) fn available_from(&self) -> SmallVec<[InstructionSet; 2]> {
1011         match self {
1012             Avx512Opcode::Vcvtudq2ps => {
1013                 smallvec![InstructionSet::AVX512F, InstructionSet::AVX512VL]
1014             }
1015             Avx512Opcode::Vpabsq => smallvec![InstructionSet::AVX512F, InstructionSet::AVX512VL],
1016             Avx512Opcode::Vpmullq => smallvec![InstructionSet::AVX512VL, InstructionSet::AVX512DQ],
1017         }
1018     }
1019 }
1020 
1021 impl fmt::Debug for Avx512Opcode {
fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result1022     fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
1023         let name = match self {
1024             Avx512Opcode::Vcvtudq2ps => "vcvtudq2ps",
1025             Avx512Opcode::Vpabsq => "vpabsq",
1026             Avx512Opcode::Vpmullq => "vpmullq",
1027         };
1028         write!(fmt, "{}", name)
1029     }
1030 }
1031 
1032 impl fmt::Display for Avx512Opcode {
fmt(&self, f: &mut fmt::Formatter) -> fmt::Result1033     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1034         fmt::Debug::fmt(self, f)
1035     }
1036 }
1037 
1038 /// This defines the ways a value can be extended: either signed- or zero-extension, or none for
1039 /// types that are not extended. Contrast with [ExtMode], which defines the widths from and to which
1040 /// values can be extended.
1041 #[allow(dead_code)]
1042 #[derive(Clone, PartialEq)]
1043 pub enum ExtKind {
1044     None,
1045     SignExtend,
1046     ZeroExtend,
1047 }
1048 
1049 /// These indicate ways of extending (widening) a value, using the Intel
1050 /// naming: B(yte) = u8, W(ord) = u16, L(ong)word = u32, Q(uad)word = u64
1051 #[derive(Clone, PartialEq)]
1052 pub enum ExtMode {
1053     /// Byte -> Longword.
1054     BL,
1055     /// Byte -> Quadword.
1056     BQ,
1057     /// Word -> Longword.
1058     WL,
1059     /// Word -> Quadword.
1060     WQ,
1061     /// Longword -> Quadword.
1062     LQ,
1063 }
1064 
1065 impl ExtMode {
1066     /// Calculate the `ExtMode` from passed bit lengths of the from/to types.
new(from_bits: u16, to_bits: u16) -> Option<ExtMode>1067     pub(crate) fn new(from_bits: u16, to_bits: u16) -> Option<ExtMode> {
1068         match (from_bits, to_bits) {
1069             (1, 8) | (1, 16) | (1, 32) | (8, 16) | (8, 32) => Some(ExtMode::BL),
1070             (1, 64) | (8, 64) => Some(ExtMode::BQ),
1071             (16, 32) => Some(ExtMode::WL),
1072             (16, 64) => Some(ExtMode::WQ),
1073             (32, 64) => Some(ExtMode::LQ),
1074             _ => None,
1075         }
1076     }
1077 
1078     /// Return the source register size in bytes.
src_size(&self) -> u81079     pub(crate) fn src_size(&self) -> u8 {
1080         match self {
1081             ExtMode::BL | ExtMode::BQ => 1,
1082             ExtMode::WL | ExtMode::WQ => 2,
1083             ExtMode::LQ => 4,
1084         }
1085     }
1086 
1087     /// Return the destination register size in bytes.
dst_size(&self) -> u81088     pub(crate) fn dst_size(&self) -> u8 {
1089         match self {
1090             ExtMode::BL | ExtMode::WL => 4,
1091             ExtMode::BQ | ExtMode::WQ | ExtMode::LQ => 8,
1092         }
1093     }
1094 }
1095 
1096 impl fmt::Debug for ExtMode {
fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result1097     fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
1098         let name = match self {
1099             ExtMode::BL => "bl",
1100             ExtMode::BQ => "bq",
1101             ExtMode::WL => "wl",
1102             ExtMode::WQ => "wq",
1103             ExtMode::LQ => "lq",
1104         };
1105         write!(fmt, "{}", name)
1106     }
1107 }
1108 
1109 impl fmt::Display for ExtMode {
fmt(&self, f: &mut fmt::Formatter) -> fmt::Result1110     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1111         fmt::Debug::fmt(self, f)
1112     }
1113 }
1114 
1115 /// These indicate the form of a scalar shift/rotate: left, signed right, unsigned right.
1116 #[derive(Clone, Copy)]
1117 pub enum ShiftKind {
1118     ShiftLeft,
1119     /// Inserts zeros in the most significant bits.
1120     ShiftRightLogical,
1121     /// Replicates the sign bit in the most significant bits.
1122     ShiftRightArithmetic,
1123     RotateLeft,
1124     RotateRight,
1125 }
1126 
1127 impl fmt::Debug for ShiftKind {
fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result1128     fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
1129         let name = match self {
1130             ShiftKind::ShiftLeft => "shl",
1131             ShiftKind::ShiftRightLogical => "shr",
1132             ShiftKind::ShiftRightArithmetic => "sar",
1133             ShiftKind::RotateLeft => "rol",
1134             ShiftKind::RotateRight => "ror",
1135         };
1136         write!(fmt, "{}", name)
1137     }
1138 }
1139 
1140 impl fmt::Display for ShiftKind {
fmt(&self, f: &mut fmt::Formatter) -> fmt::Result1141     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1142         fmt::Debug::fmt(self, f)
1143     }
1144 }
1145 
1146 /// What kind of division or remainer instruction this is?
1147 #[derive(Clone)]
1148 pub enum DivOrRemKind {
1149     SignedDiv,
1150     UnsignedDiv,
1151     SignedRem,
1152     UnsignedRem,
1153 }
1154 
1155 impl DivOrRemKind {
is_signed(&self) -> bool1156     pub(crate) fn is_signed(&self) -> bool {
1157         match self {
1158             DivOrRemKind::SignedDiv | DivOrRemKind::SignedRem => true,
1159             _ => false,
1160         }
1161     }
1162 
is_div(&self) -> bool1163     pub(crate) fn is_div(&self) -> bool {
1164         match self {
1165             DivOrRemKind::SignedDiv | DivOrRemKind::UnsignedDiv => true,
1166             _ => false,
1167         }
1168     }
1169 }
1170 
1171 /// These indicate condition code tests.  Not all are represented since not all are useful in
1172 /// compiler-generated code.
1173 #[derive(Copy, Clone)]
1174 #[repr(u8)]
1175 pub enum CC {
1176     ///  overflow
1177     O = 0,
1178     /// no overflow
1179     NO = 1,
1180 
1181     /// < unsigned
1182     B = 2,
1183     /// >= unsigned
1184     NB = 3,
1185 
1186     /// zero
1187     Z = 4,
1188     /// not-zero
1189     NZ = 5,
1190 
1191     /// <= unsigned
1192     BE = 6,
1193     /// > unsigned
1194     NBE = 7,
1195 
1196     /// negative
1197     S = 8,
1198     /// not-negative
1199     NS = 9,
1200 
1201     /// < signed
1202     L = 12,
1203     /// >= signed
1204     NL = 13,
1205 
1206     /// <= signed
1207     LE = 14,
1208     /// > signed
1209     NLE = 15,
1210 
1211     /// parity
1212     P = 10,
1213 
1214     /// not parity
1215     NP = 11,
1216 }
1217 
1218 impl CC {
from_intcc(intcc: IntCC) -> Self1219     pub(crate) fn from_intcc(intcc: IntCC) -> Self {
1220         match intcc {
1221             IntCC::Equal => CC::Z,
1222             IntCC::NotEqual => CC::NZ,
1223             IntCC::SignedGreaterThanOrEqual => CC::NL,
1224             IntCC::SignedGreaterThan => CC::NLE,
1225             IntCC::SignedLessThanOrEqual => CC::LE,
1226             IntCC::SignedLessThan => CC::L,
1227             IntCC::UnsignedGreaterThanOrEqual => CC::NB,
1228             IntCC::UnsignedGreaterThan => CC::NBE,
1229             IntCC::UnsignedLessThanOrEqual => CC::BE,
1230             IntCC::UnsignedLessThan => CC::B,
1231             IntCC::Overflow => CC::O,
1232             IntCC::NotOverflow => CC::NO,
1233         }
1234     }
1235 
invert(&self) -> Self1236     pub(crate) fn invert(&self) -> Self {
1237         match self {
1238             CC::O => CC::NO,
1239             CC::NO => CC::O,
1240 
1241             CC::B => CC::NB,
1242             CC::NB => CC::B,
1243 
1244             CC::Z => CC::NZ,
1245             CC::NZ => CC::Z,
1246 
1247             CC::BE => CC::NBE,
1248             CC::NBE => CC::BE,
1249 
1250             CC::S => CC::NS,
1251             CC::NS => CC::S,
1252 
1253             CC::L => CC::NL,
1254             CC::NL => CC::L,
1255 
1256             CC::LE => CC::NLE,
1257             CC::NLE => CC::LE,
1258 
1259             CC::P => CC::NP,
1260             CC::NP => CC::P,
1261         }
1262     }
1263 
from_floatcc(floatcc: FloatCC) -> Self1264     pub(crate) fn from_floatcc(floatcc: FloatCC) -> Self {
1265         match floatcc {
1266             FloatCC::Ordered => CC::NP,
1267             FloatCC::Unordered => CC::P,
1268             // Alias for NE
1269             FloatCC::OrderedNotEqual => CC::NZ,
1270             // Alias for E
1271             FloatCC::UnorderedOrEqual => CC::Z,
1272             // Alias for A
1273             FloatCC::GreaterThan => CC::NBE,
1274             // Alias for AE
1275             FloatCC::GreaterThanOrEqual => CC::NB,
1276             FloatCC::UnorderedOrLessThan => CC::B,
1277             FloatCC::UnorderedOrLessThanOrEqual => CC::BE,
1278             FloatCC::Equal
1279             | FloatCC::NotEqual
1280             | FloatCC::LessThan
1281             | FloatCC::LessThanOrEqual
1282             | FloatCC::UnorderedOrGreaterThan
1283             | FloatCC::UnorderedOrGreaterThanOrEqual => panic!(
1284                 "{:?} can't be lowered to a CC code; treat as special case.",
1285                 floatcc
1286             ),
1287         }
1288     }
1289 
get_enc(self) -> u81290     pub(crate) fn get_enc(self) -> u8 {
1291         self as u8
1292     }
1293 }
1294 
1295 impl fmt::Debug for CC {
fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result1296     fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
1297         let name = match self {
1298             CC::O => "o",
1299             CC::NO => "no",
1300             CC::B => "b",
1301             CC::NB => "nb",
1302             CC::Z => "z",
1303             CC::NZ => "nz",
1304             CC::BE => "be",
1305             CC::NBE => "nbe",
1306             CC::S => "s",
1307             CC::NS => "ns",
1308             CC::L => "l",
1309             CC::NL => "nl",
1310             CC::LE => "le",
1311             CC::NLE => "nle",
1312             CC::P => "p",
1313             CC::NP => "np",
1314         };
1315         write!(fmt, "{}", name)
1316     }
1317 }
1318 
1319 impl fmt::Display for CC {
fmt(&self, f: &mut fmt::Formatter) -> fmt::Result1320     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1321         fmt::Debug::fmt(self, f)
1322     }
1323 }
1324 
1325 /// Encode the ways that floats can be compared. This is used in float comparisons such as `cmpps`,
1326 /// e.g.; it is distinguished from other float comparisons (e.g. `ucomiss`) in that those use EFLAGS
1327 /// whereas [FcmpImm] is used as an immediate.
1328 pub(crate) enum FcmpImm {
1329     Equal = 0x00,
1330     LessThan = 0x01,
1331     LessThanOrEqual = 0x02,
1332     Unordered = 0x03,
1333     NotEqual = 0x04,
1334     UnorderedOrGreaterThanOrEqual = 0x05,
1335     UnorderedOrGreaterThan = 0x06,
1336     Ordered = 0x07,
1337 }
1338 
1339 impl FcmpImm {
encode(self) -> u81340     pub(crate) fn encode(self) -> u8 {
1341         self as u8
1342     }
1343 }
1344 
1345 impl From<FloatCC> for FcmpImm {
from(cond: FloatCC) -> Self1346     fn from(cond: FloatCC) -> Self {
1347         match cond {
1348             FloatCC::Equal => FcmpImm::Equal,
1349             FloatCC::LessThan => FcmpImm::LessThan,
1350             FloatCC::LessThanOrEqual => FcmpImm::LessThanOrEqual,
1351             FloatCC::Unordered => FcmpImm::Unordered,
1352             FloatCC::NotEqual => FcmpImm::NotEqual,
1353             FloatCC::UnorderedOrGreaterThanOrEqual => FcmpImm::UnorderedOrGreaterThanOrEqual,
1354             FloatCC::UnorderedOrGreaterThan => FcmpImm::UnorderedOrGreaterThan,
1355             FloatCC::Ordered => FcmpImm::Ordered,
1356             _ => panic!("unable to create comparison predicate for {}", cond),
1357         }
1358     }
1359 }
1360 
1361 /// Encode the rounding modes used as part of the Rounding Control field.
1362 /// Note, these rounding immediates only consider the rounding control field
1363 /// (i.e. the rounding mode) which only take up the first two bits when encoded.
1364 /// However the rounding immediate which this field helps make up, also includes
1365 /// bits 3 and 4 which define the rounding select and precision mask respectively.
1366 /// These two bits are not defined here and are implictly set to zero when encoded.
1367 pub(crate) enum RoundImm {
1368     RoundNearest = 0x00,
1369     RoundDown = 0x01,
1370     RoundUp = 0x02,
1371     RoundZero = 0x03,
1372 }
1373 
1374 impl RoundImm {
encode(self) -> u81375     pub(crate) fn encode(self) -> u8 {
1376         self as u8
1377     }
1378 }
1379 
1380 /// An operand's size in bits.
1381 #[derive(Clone, Copy, PartialEq)]
1382 pub enum OperandSize {
1383     Size8,
1384     Size16,
1385     Size32,
1386     Size64,
1387 }
1388 
1389 impl OperandSize {
from_bytes(num_bytes: u32) -> Self1390     pub(crate) fn from_bytes(num_bytes: u32) -> Self {
1391         match num_bytes {
1392             1 => OperandSize::Size8,
1393             2 => OperandSize::Size16,
1394             4 => OperandSize::Size32,
1395             8 => OperandSize::Size64,
1396             _ => unreachable!("Invalid OperandSize: {}", num_bytes),
1397         }
1398     }
1399 
1400     // Computes the OperandSize for a given type.
1401     // For vectors, the OperandSize of the lanes is returned.
from_ty(ty: Type) -> Self1402     pub(crate) fn from_ty(ty: Type) -> Self {
1403         Self::from_bytes(ty.lane_type().bytes())
1404     }
1405 
1406     // Check that the value of self is one of the allowed sizes.
is_one_of(&self, sizes: &[Self]) -> bool1407     pub(crate) fn is_one_of(&self, sizes: &[Self]) -> bool {
1408         sizes.iter().any(|val| *self == *val)
1409     }
1410 
to_bytes(&self) -> u81411     pub(crate) fn to_bytes(&self) -> u8 {
1412         match self {
1413             Self::Size8 => 1,
1414             Self::Size16 => 2,
1415             Self::Size32 => 4,
1416             Self::Size64 => 8,
1417         }
1418     }
1419 
to_bits(&self) -> u81420     pub(crate) fn to_bits(&self) -> u8 {
1421         self.to_bytes() * 8
1422     }
1423 }
1424 
1425 /// An x64 memory fence kind.
1426 #[derive(Clone)]
1427 #[allow(dead_code)]
1428 pub enum FenceKind {
1429     /// `mfence` instruction ("Memory Fence")
1430     MFence,
1431     /// `lfence` instruction ("Load Fence")
1432     LFence,
1433     /// `sfence` instruction ("Store Fence")
1434     SFence,
1435 }
1436