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     AVX512BITALG,
464     AVX512DQ,
465     AVX512F,
466     AVX512VBMI,
467     AVX512VL,
468 }
469 
470 /// Some SSE operations requiring 2 operands r/m and r.
471 #[derive(Clone, Copy, PartialEq)]
472 #[allow(dead_code)] // some variants here aren't used just yet
473 pub enum SseOpcode {
474     Addps,
475     Addpd,
476     Addss,
477     Addsd,
478     Andps,
479     Andpd,
480     Andnps,
481     Andnpd,
482     Blendvpd,
483     Blendvps,
484     Comiss,
485     Comisd,
486     Cmpps,
487     Cmppd,
488     Cmpss,
489     Cmpsd,
490     Cvtdq2ps,
491     Cvtdq2pd,
492     Cvtpd2ps,
493     Cvtps2pd,
494     Cvtsd2ss,
495     Cvtsd2si,
496     Cvtsi2ss,
497     Cvtsi2sd,
498     Cvtss2si,
499     Cvtss2sd,
500     Cvttpd2dq,
501     Cvttps2dq,
502     Cvttss2si,
503     Cvttsd2si,
504     Divps,
505     Divpd,
506     Divss,
507     Divsd,
508     Insertps,
509     Maxps,
510     Maxpd,
511     Maxss,
512     Maxsd,
513     Minps,
514     Minpd,
515     Minss,
516     Minsd,
517     Movaps,
518     Movapd,
519     Movd,
520     Movdqa,
521     Movdqu,
522     Movlhps,
523     Movmskps,
524     Movmskpd,
525     Movq,
526     Movss,
527     Movsd,
528     Movups,
529     Movupd,
530     Mulps,
531     Mulpd,
532     Mulss,
533     Mulsd,
534     Orps,
535     Orpd,
536     Pabsb,
537     Pabsw,
538     Pabsd,
539     Packssdw,
540     Packsswb,
541     Packusdw,
542     Packuswb,
543     Paddb,
544     Paddd,
545     Paddq,
546     Paddw,
547     Paddsb,
548     Paddsw,
549     Paddusb,
550     Paddusw,
551     Palignr,
552     Pand,
553     Pandn,
554     Pavgb,
555     Pavgw,
556     Pblendvb,
557     Pcmpeqb,
558     Pcmpeqw,
559     Pcmpeqd,
560     Pcmpeqq,
561     Pcmpgtb,
562     Pcmpgtw,
563     Pcmpgtd,
564     Pcmpgtq,
565     Pextrb,
566     Pextrw,
567     Pextrd,
568     Pinsrb,
569     Pinsrw,
570     Pinsrd,
571     Pmaddubsw,
572     Pmaddwd,
573     Pmaxsb,
574     Pmaxsw,
575     Pmaxsd,
576     Pmaxub,
577     Pmaxuw,
578     Pmaxud,
579     Pminsb,
580     Pminsw,
581     Pminsd,
582     Pminub,
583     Pminuw,
584     Pminud,
585     Pmovmskb,
586     Pmovsxbd,
587     Pmovsxbw,
588     Pmovsxbq,
589     Pmovsxwd,
590     Pmovsxwq,
591     Pmovsxdq,
592     Pmovzxbd,
593     Pmovzxbw,
594     Pmovzxbq,
595     Pmovzxwd,
596     Pmovzxwq,
597     Pmovzxdq,
598     Pmuldq,
599     Pmulhw,
600     Pmulhuw,
601     Pmulhrsw,
602     Pmulld,
603     Pmullw,
604     Pmuludq,
605     Por,
606     Pshufb,
607     Pshufd,
608     Psllw,
609     Pslld,
610     Psllq,
611     Psraw,
612     Psrad,
613     Psrlw,
614     Psrld,
615     Psrlq,
616     Psubb,
617     Psubd,
618     Psubq,
619     Psubw,
620     Psubsb,
621     Psubsw,
622     Psubusb,
623     Psubusw,
624     Ptest,
625     Punpckhbw,
626     Punpckhwd,
627     Punpcklbw,
628     Punpcklwd,
629     Pxor,
630     Rcpss,
631     Roundps,
632     Roundpd,
633     Roundss,
634     Roundsd,
635     Rsqrtss,
636     Shufps,
637     Sqrtps,
638     Sqrtpd,
639     Sqrtss,
640     Sqrtsd,
641     Subps,
642     Subpd,
643     Subss,
644     Subsd,
645     Ucomiss,
646     Ucomisd,
647     Unpcklps,
648     Xorps,
649     Xorpd,
650 }
651 
652 impl SseOpcode {
653     /// Which `InstructionSet` is the first supporting this opcode?
available_from(&self) -> InstructionSet654     pub(crate) fn available_from(&self) -> InstructionSet {
655         use InstructionSet::*;
656         match self {
657             SseOpcode::Addps
658             | SseOpcode::Addss
659             | SseOpcode::Andps
660             | SseOpcode::Andnps
661             | SseOpcode::Comiss
662             | SseOpcode::Cmpps
663             | SseOpcode::Cmpss
664             | SseOpcode::Cvtsi2ss
665             | SseOpcode::Cvtss2si
666             | SseOpcode::Cvttss2si
667             | SseOpcode::Divps
668             | SseOpcode::Divss
669             | SseOpcode::Maxps
670             | SseOpcode::Maxss
671             | SseOpcode::Minps
672             | SseOpcode::Minss
673             | SseOpcode::Movaps
674             | SseOpcode::Movlhps
675             | SseOpcode::Movmskps
676             | SseOpcode::Movss
677             | SseOpcode::Movups
678             | SseOpcode::Mulps
679             | SseOpcode::Mulss
680             | SseOpcode::Orps
681             | SseOpcode::Rcpss
682             | SseOpcode::Rsqrtss
683             | SseOpcode::Shufps
684             | SseOpcode::Sqrtps
685             | SseOpcode::Sqrtss
686             | SseOpcode::Subps
687             | SseOpcode::Subss
688             | SseOpcode::Ucomiss
689             | SseOpcode::Unpcklps
690             | SseOpcode::Xorps => SSE,
691 
692             SseOpcode::Addpd
693             | SseOpcode::Addsd
694             | SseOpcode::Andpd
695             | SseOpcode::Andnpd
696             | SseOpcode::Cmppd
697             | SseOpcode::Cmpsd
698             | SseOpcode::Comisd
699             | SseOpcode::Cvtdq2ps
700             | SseOpcode::Cvtdq2pd
701             | SseOpcode::Cvtpd2ps
702             | SseOpcode::Cvtps2pd
703             | SseOpcode::Cvtsd2ss
704             | SseOpcode::Cvtsd2si
705             | SseOpcode::Cvtsi2sd
706             | SseOpcode::Cvtss2sd
707             | SseOpcode::Cvttpd2dq
708             | SseOpcode::Cvttps2dq
709             | SseOpcode::Cvttsd2si
710             | SseOpcode::Divpd
711             | SseOpcode::Divsd
712             | SseOpcode::Maxpd
713             | SseOpcode::Maxsd
714             | SseOpcode::Minpd
715             | SseOpcode::Minsd
716             | SseOpcode::Movapd
717             | SseOpcode::Movd
718             | SseOpcode::Movmskpd
719             | SseOpcode::Movq
720             | SseOpcode::Movsd
721             | SseOpcode::Movupd
722             | SseOpcode::Movdqa
723             | SseOpcode::Movdqu
724             | SseOpcode::Mulpd
725             | SseOpcode::Mulsd
726             | SseOpcode::Orpd
727             | SseOpcode::Packssdw
728             | SseOpcode::Packsswb
729             | SseOpcode::Packuswb
730             | SseOpcode::Paddb
731             | SseOpcode::Paddd
732             | SseOpcode::Paddq
733             | SseOpcode::Paddw
734             | SseOpcode::Paddsb
735             | SseOpcode::Paddsw
736             | SseOpcode::Paddusb
737             | SseOpcode::Paddusw
738             | SseOpcode::Pand
739             | SseOpcode::Pandn
740             | SseOpcode::Pavgb
741             | SseOpcode::Pavgw
742             | SseOpcode::Pcmpeqb
743             | SseOpcode::Pcmpeqw
744             | SseOpcode::Pcmpeqd
745             | SseOpcode::Pcmpgtb
746             | SseOpcode::Pcmpgtw
747             | SseOpcode::Pcmpgtd
748             | SseOpcode::Pextrw
749             | SseOpcode::Pinsrw
750             | SseOpcode::Pmaddubsw
751             | SseOpcode::Pmaddwd
752             | SseOpcode::Pmaxsw
753             | SseOpcode::Pmaxub
754             | SseOpcode::Pminsw
755             | SseOpcode::Pminub
756             | SseOpcode::Pmovmskb
757             | SseOpcode::Pmulhw
758             | SseOpcode::Pmulhuw
759             | SseOpcode::Pmullw
760             | SseOpcode::Pmuludq
761             | SseOpcode::Por
762             | SseOpcode::Pshufd
763             | SseOpcode::Psllw
764             | SseOpcode::Pslld
765             | SseOpcode::Psllq
766             | SseOpcode::Psraw
767             | SseOpcode::Psrad
768             | SseOpcode::Psrlw
769             | SseOpcode::Psrld
770             | SseOpcode::Psrlq
771             | SseOpcode::Psubb
772             | SseOpcode::Psubd
773             | SseOpcode::Psubq
774             | SseOpcode::Psubw
775             | SseOpcode::Psubsb
776             | SseOpcode::Psubsw
777             | SseOpcode::Psubusb
778             | SseOpcode::Psubusw
779             | SseOpcode::Punpckhbw
780             | SseOpcode::Punpckhwd
781             | SseOpcode::Punpcklbw
782             | SseOpcode::Punpcklwd
783             | SseOpcode::Pxor
784             | SseOpcode::Sqrtpd
785             | SseOpcode::Sqrtsd
786             | SseOpcode::Subpd
787             | SseOpcode::Subsd
788             | SseOpcode::Ucomisd
789             | SseOpcode::Xorpd => SSE2,
790 
791             SseOpcode::Pabsb
792             | SseOpcode::Pabsw
793             | SseOpcode::Pabsd
794             | SseOpcode::Palignr
795             | SseOpcode::Pmulhrsw
796             | SseOpcode::Pshufb => SSSE3,
797 
798             SseOpcode::Blendvpd
799             | SseOpcode::Blendvps
800             | SseOpcode::Insertps
801             | SseOpcode::Packusdw
802             | SseOpcode::Pblendvb
803             | SseOpcode::Pcmpeqq
804             | SseOpcode::Pextrb
805             | SseOpcode::Pextrd
806             | SseOpcode::Pinsrb
807             | SseOpcode::Pinsrd
808             | SseOpcode::Pmaxsb
809             | SseOpcode::Pmaxsd
810             | SseOpcode::Pmaxuw
811             | SseOpcode::Pmaxud
812             | SseOpcode::Pminsb
813             | SseOpcode::Pminsd
814             | SseOpcode::Pminuw
815             | SseOpcode::Pminud
816             | SseOpcode::Pmovsxbd
817             | SseOpcode::Pmovsxbw
818             | SseOpcode::Pmovsxbq
819             | SseOpcode::Pmovsxwd
820             | SseOpcode::Pmovsxwq
821             | SseOpcode::Pmovsxdq
822             | SseOpcode::Pmovzxbd
823             | SseOpcode::Pmovzxbw
824             | SseOpcode::Pmovzxbq
825             | SseOpcode::Pmovzxwd
826             | SseOpcode::Pmovzxwq
827             | SseOpcode::Pmovzxdq
828             | SseOpcode::Pmuldq
829             | SseOpcode::Pmulld
830             | SseOpcode::Ptest
831             | SseOpcode::Roundps
832             | SseOpcode::Roundpd
833             | SseOpcode::Roundss
834             | SseOpcode::Roundsd => SSE41,
835 
836             SseOpcode::Pcmpgtq => SSE42,
837         }
838     }
839 
840     /// Returns the src operand size for an instruction.
src_size(&self) -> u8841     pub(crate) fn src_size(&self) -> u8 {
842         match self {
843             SseOpcode::Movd => 4,
844             _ => 8,
845         }
846     }
847 }
848 
849 impl fmt::Debug for SseOpcode {
fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result850     fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
851         let name = match self {
852             SseOpcode::Addps => "addps",
853             SseOpcode::Addpd => "addpd",
854             SseOpcode::Addss => "addss",
855             SseOpcode::Addsd => "addsd",
856             SseOpcode::Andpd => "andpd",
857             SseOpcode::Andps => "andps",
858             SseOpcode::Andnps => "andnps",
859             SseOpcode::Andnpd => "andnpd",
860             SseOpcode::Blendvpd => "blendvpd",
861             SseOpcode::Blendvps => "blendvps",
862             SseOpcode::Cmpps => "cmpps",
863             SseOpcode::Cmppd => "cmppd",
864             SseOpcode::Cmpss => "cmpss",
865             SseOpcode::Cmpsd => "cmpsd",
866             SseOpcode::Comiss => "comiss",
867             SseOpcode::Comisd => "comisd",
868             SseOpcode::Cvtdq2ps => "cvtdq2ps",
869             SseOpcode::Cvtdq2pd => "cvtdq2pd",
870             SseOpcode::Cvtpd2ps => "cvtpd2ps",
871             SseOpcode::Cvtps2pd => "cvtps2pd",
872             SseOpcode::Cvtsd2ss => "cvtsd2ss",
873             SseOpcode::Cvtsd2si => "cvtsd2si",
874             SseOpcode::Cvtsi2ss => "cvtsi2ss",
875             SseOpcode::Cvtsi2sd => "cvtsi2sd",
876             SseOpcode::Cvtss2si => "cvtss2si",
877             SseOpcode::Cvtss2sd => "cvtss2sd",
878             SseOpcode::Cvttpd2dq => "cvttpd2dq",
879             SseOpcode::Cvttps2dq => "cvttps2dq",
880             SseOpcode::Cvttss2si => "cvttss2si",
881             SseOpcode::Cvttsd2si => "cvttsd2si",
882             SseOpcode::Divps => "divps",
883             SseOpcode::Divpd => "divpd",
884             SseOpcode::Divss => "divss",
885             SseOpcode::Divsd => "divsd",
886             SseOpcode::Insertps => "insertps",
887             SseOpcode::Maxps => "maxps",
888             SseOpcode::Maxpd => "maxpd",
889             SseOpcode::Maxss => "maxss",
890             SseOpcode::Maxsd => "maxsd",
891             SseOpcode::Minps => "minps",
892             SseOpcode::Minpd => "minpd",
893             SseOpcode::Minss => "minss",
894             SseOpcode::Minsd => "minsd",
895             SseOpcode::Movaps => "movaps",
896             SseOpcode::Movapd => "movapd",
897             SseOpcode::Movd => "movd",
898             SseOpcode::Movdqa => "movdqa",
899             SseOpcode::Movdqu => "movdqu",
900             SseOpcode::Movlhps => "movlhps",
901             SseOpcode::Movmskps => "movmskps",
902             SseOpcode::Movmskpd => "movmskpd",
903             SseOpcode::Movq => "movq",
904             SseOpcode::Movss => "movss",
905             SseOpcode::Movsd => "movsd",
906             SseOpcode::Movups => "movups",
907             SseOpcode::Movupd => "movupd",
908             SseOpcode::Mulps => "mulps",
909             SseOpcode::Mulpd => "mulpd",
910             SseOpcode::Mulss => "mulss",
911             SseOpcode::Mulsd => "mulsd",
912             SseOpcode::Orpd => "orpd",
913             SseOpcode::Orps => "orps",
914             SseOpcode::Pabsb => "pabsb",
915             SseOpcode::Pabsw => "pabsw",
916             SseOpcode::Pabsd => "pabsd",
917             SseOpcode::Packssdw => "packssdw",
918             SseOpcode::Packsswb => "packsswb",
919             SseOpcode::Packusdw => "packusdw",
920             SseOpcode::Packuswb => "packuswb",
921             SseOpcode::Paddb => "paddb",
922             SseOpcode::Paddd => "paddd",
923             SseOpcode::Paddq => "paddq",
924             SseOpcode::Paddw => "paddw",
925             SseOpcode::Paddsb => "paddsb",
926             SseOpcode::Paddsw => "paddsw",
927             SseOpcode::Paddusb => "paddusb",
928             SseOpcode::Paddusw => "paddusw",
929             SseOpcode::Palignr => "palignr",
930             SseOpcode::Pand => "pand",
931             SseOpcode::Pandn => "pandn",
932             SseOpcode::Pavgb => "pavgb",
933             SseOpcode::Pavgw => "pavgw",
934             SseOpcode::Pblendvb => "pblendvb",
935             SseOpcode::Pcmpeqb => "pcmpeqb",
936             SseOpcode::Pcmpeqw => "pcmpeqw",
937             SseOpcode::Pcmpeqd => "pcmpeqd",
938             SseOpcode::Pcmpeqq => "pcmpeqq",
939             SseOpcode::Pcmpgtb => "pcmpgtb",
940             SseOpcode::Pcmpgtw => "pcmpgtw",
941             SseOpcode::Pcmpgtd => "pcmpgtd",
942             SseOpcode::Pcmpgtq => "pcmpgtq",
943             SseOpcode::Pextrb => "pextrb",
944             SseOpcode::Pextrw => "pextrw",
945             SseOpcode::Pextrd => "pextrd",
946             SseOpcode::Pinsrb => "pinsrb",
947             SseOpcode::Pinsrw => "pinsrw",
948             SseOpcode::Pinsrd => "pinsrd",
949             SseOpcode::Pmaddubsw => "pmaddubsw",
950             SseOpcode::Pmaddwd => "pmaddwd",
951             SseOpcode::Pmaxsb => "pmaxsb",
952             SseOpcode::Pmaxsw => "pmaxsw",
953             SseOpcode::Pmaxsd => "pmaxsd",
954             SseOpcode::Pmaxub => "pmaxub",
955             SseOpcode::Pmaxuw => "pmaxuw",
956             SseOpcode::Pmaxud => "pmaxud",
957             SseOpcode::Pminsb => "pminsb",
958             SseOpcode::Pminsw => "pminsw",
959             SseOpcode::Pminsd => "pminsd",
960             SseOpcode::Pminub => "pminub",
961             SseOpcode::Pminuw => "pminuw",
962             SseOpcode::Pminud => "pminud",
963             SseOpcode::Pmovmskb => "pmovmskb",
964             SseOpcode::Pmovsxbd => "pmovsxbd",
965             SseOpcode::Pmovsxbw => "pmovsxbw",
966             SseOpcode::Pmovsxbq => "pmovsxbq",
967             SseOpcode::Pmovsxwd => "pmovsxwd",
968             SseOpcode::Pmovsxwq => "pmovsxwq",
969             SseOpcode::Pmovsxdq => "pmovsxdq",
970             SseOpcode::Pmovzxbd => "pmovzxbd",
971             SseOpcode::Pmovzxbw => "pmovzxbw",
972             SseOpcode::Pmovzxbq => "pmovzxbq",
973             SseOpcode::Pmovzxwd => "pmovzxwd",
974             SseOpcode::Pmovzxwq => "pmovzxwq",
975             SseOpcode::Pmovzxdq => "pmovzxdq",
976             SseOpcode::Pmuldq => "pmuldq",
977             SseOpcode::Pmulhw => "pmulhw",
978             SseOpcode::Pmulhuw => "pmulhuw",
979             SseOpcode::Pmulhrsw => "pmulhrsw",
980             SseOpcode::Pmulld => "pmulld",
981             SseOpcode::Pmullw => "pmullw",
982             SseOpcode::Pmuludq => "pmuludq",
983             SseOpcode::Por => "por",
984             SseOpcode::Pshufb => "pshufb",
985             SseOpcode::Pshufd => "pshufd",
986             SseOpcode::Psllw => "psllw",
987             SseOpcode::Pslld => "pslld",
988             SseOpcode::Psllq => "psllq",
989             SseOpcode::Psraw => "psraw",
990             SseOpcode::Psrad => "psrad",
991             SseOpcode::Psrlw => "psrlw",
992             SseOpcode::Psrld => "psrld",
993             SseOpcode::Psrlq => "psrlq",
994             SseOpcode::Psubb => "psubb",
995             SseOpcode::Psubd => "psubd",
996             SseOpcode::Psubq => "psubq",
997             SseOpcode::Psubw => "psubw",
998             SseOpcode::Psubsb => "psubsb",
999             SseOpcode::Psubsw => "psubsw",
1000             SseOpcode::Psubusb => "psubusb",
1001             SseOpcode::Psubusw => "psubusw",
1002             SseOpcode::Ptest => "ptest",
1003             SseOpcode::Punpckhbw => "punpckhbw",
1004             SseOpcode::Punpckhwd => "punpckhwd",
1005             SseOpcode::Punpcklbw => "punpcklbw",
1006             SseOpcode::Punpcklwd => "punpcklwd",
1007             SseOpcode::Pxor => "pxor",
1008             SseOpcode::Rcpss => "rcpss",
1009             SseOpcode::Roundps => "roundps",
1010             SseOpcode::Roundpd => "roundpd",
1011             SseOpcode::Roundss => "roundss",
1012             SseOpcode::Roundsd => "roundsd",
1013             SseOpcode::Rsqrtss => "rsqrtss",
1014             SseOpcode::Shufps => "shufps",
1015             SseOpcode::Sqrtps => "sqrtps",
1016             SseOpcode::Sqrtpd => "sqrtpd",
1017             SseOpcode::Sqrtss => "sqrtss",
1018             SseOpcode::Sqrtsd => "sqrtsd",
1019             SseOpcode::Subps => "subps",
1020             SseOpcode::Subpd => "subpd",
1021             SseOpcode::Subss => "subss",
1022             SseOpcode::Subsd => "subsd",
1023             SseOpcode::Ucomiss => "ucomiss",
1024             SseOpcode::Ucomisd => "ucomisd",
1025             SseOpcode::Unpcklps => "unpcklps",
1026             SseOpcode::Xorps => "xorps",
1027             SseOpcode::Xorpd => "xorpd",
1028         };
1029         write!(fmt, "{}", name)
1030     }
1031 }
1032 
1033 impl fmt::Display for SseOpcode {
fmt(&self, f: &mut fmt::Formatter) -> fmt::Result1034     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1035         fmt::Debug::fmt(self, f)
1036     }
1037 }
1038 
1039 #[derive(Clone, PartialEq)]
1040 pub enum Avx512Opcode {
1041     Vcvtudq2ps,
1042     Vpabsq,
1043     Vpermi2b,
1044     Vpmullq,
1045     Vpopcntb,
1046 }
1047 
1048 impl Avx512Opcode {
1049     /// Which `InstructionSet`s support the opcode?
available_from(&self) -> SmallVec<[InstructionSet; 2]>1050     pub(crate) fn available_from(&self) -> SmallVec<[InstructionSet; 2]> {
1051         match self {
1052             Avx512Opcode::Vcvtudq2ps => {
1053                 smallvec![InstructionSet::AVX512F, InstructionSet::AVX512VL]
1054             }
1055             Avx512Opcode::Vpabsq => smallvec![InstructionSet::AVX512F, InstructionSet::AVX512VL],
1056             Avx512Opcode::Vpermi2b => {
1057                 smallvec![InstructionSet::AVX512VL, InstructionSet::AVX512VBMI]
1058             }
1059             Avx512Opcode::Vpmullq => smallvec![InstructionSet::AVX512VL, InstructionSet::AVX512DQ],
1060             Avx512Opcode::Vpopcntb => {
1061                 smallvec![InstructionSet::AVX512VL, InstructionSet::AVX512BITALG]
1062             }
1063         }
1064     }
1065 }
1066 
1067 impl fmt::Debug for Avx512Opcode {
fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result1068     fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
1069         let name = match self {
1070             Avx512Opcode::Vcvtudq2ps => "vcvtudq2ps",
1071             Avx512Opcode::Vpabsq => "vpabsq",
1072             Avx512Opcode::Vpermi2b => "vpermi2b",
1073             Avx512Opcode::Vpmullq => "vpmullq",
1074             Avx512Opcode::Vpopcntb => "vpopcntb",
1075         };
1076         write!(fmt, "{}", name)
1077     }
1078 }
1079 
1080 impl fmt::Display for Avx512Opcode {
fmt(&self, f: &mut fmt::Formatter) -> fmt::Result1081     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1082         fmt::Debug::fmt(self, f)
1083     }
1084 }
1085 
1086 /// This defines the ways a value can be extended: either signed- or zero-extension, or none for
1087 /// types that are not extended. Contrast with [ExtMode], which defines the widths from and to which
1088 /// values can be extended.
1089 #[allow(dead_code)]
1090 #[derive(Clone, PartialEq)]
1091 pub enum ExtKind {
1092     None,
1093     SignExtend,
1094     ZeroExtend,
1095 }
1096 
1097 /// These indicate ways of extending (widening) a value, using the Intel
1098 /// naming: B(yte) = u8, W(ord) = u16, L(ong)word = u32, Q(uad)word = u64
1099 #[derive(Clone, PartialEq)]
1100 pub enum ExtMode {
1101     /// Byte -> Longword.
1102     BL,
1103     /// Byte -> Quadword.
1104     BQ,
1105     /// Word -> Longword.
1106     WL,
1107     /// Word -> Quadword.
1108     WQ,
1109     /// Longword -> Quadword.
1110     LQ,
1111 }
1112 
1113 impl ExtMode {
1114     /// Calculate the `ExtMode` from passed bit lengths of the from/to types.
new(from_bits: u16, to_bits: u16) -> Option<ExtMode>1115     pub(crate) fn new(from_bits: u16, to_bits: u16) -> Option<ExtMode> {
1116         match (from_bits, to_bits) {
1117             (1, 8) | (1, 16) | (1, 32) | (8, 16) | (8, 32) => Some(ExtMode::BL),
1118             (1, 64) | (8, 64) => Some(ExtMode::BQ),
1119             (16, 32) => Some(ExtMode::WL),
1120             (16, 64) => Some(ExtMode::WQ),
1121             (32, 64) => Some(ExtMode::LQ),
1122             _ => None,
1123         }
1124     }
1125 
1126     /// Return the source register size in bytes.
src_size(&self) -> u81127     pub(crate) fn src_size(&self) -> u8 {
1128         match self {
1129             ExtMode::BL | ExtMode::BQ => 1,
1130             ExtMode::WL | ExtMode::WQ => 2,
1131             ExtMode::LQ => 4,
1132         }
1133     }
1134 
1135     /// Return the destination register size in bytes.
dst_size(&self) -> u81136     pub(crate) fn dst_size(&self) -> u8 {
1137         match self {
1138             ExtMode::BL | ExtMode::WL => 4,
1139             ExtMode::BQ | ExtMode::WQ | ExtMode::LQ => 8,
1140         }
1141     }
1142 }
1143 
1144 impl fmt::Debug for ExtMode {
fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result1145     fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
1146         let name = match self {
1147             ExtMode::BL => "bl",
1148             ExtMode::BQ => "bq",
1149             ExtMode::WL => "wl",
1150             ExtMode::WQ => "wq",
1151             ExtMode::LQ => "lq",
1152         };
1153         write!(fmt, "{}", name)
1154     }
1155 }
1156 
1157 impl fmt::Display for ExtMode {
fmt(&self, f: &mut fmt::Formatter) -> fmt::Result1158     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1159         fmt::Debug::fmt(self, f)
1160     }
1161 }
1162 
1163 /// These indicate the form of a scalar shift/rotate: left, signed right, unsigned right.
1164 #[derive(Clone, Copy)]
1165 pub enum ShiftKind {
1166     ShiftLeft,
1167     /// Inserts zeros in the most significant bits.
1168     ShiftRightLogical,
1169     /// Replicates the sign bit in the most significant bits.
1170     ShiftRightArithmetic,
1171     RotateLeft,
1172     RotateRight,
1173 }
1174 
1175 impl fmt::Debug for ShiftKind {
fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result1176     fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
1177         let name = match self {
1178             ShiftKind::ShiftLeft => "shl",
1179             ShiftKind::ShiftRightLogical => "shr",
1180             ShiftKind::ShiftRightArithmetic => "sar",
1181             ShiftKind::RotateLeft => "rol",
1182             ShiftKind::RotateRight => "ror",
1183         };
1184         write!(fmt, "{}", name)
1185     }
1186 }
1187 
1188 impl fmt::Display for ShiftKind {
fmt(&self, f: &mut fmt::Formatter) -> fmt::Result1189     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1190         fmt::Debug::fmt(self, f)
1191     }
1192 }
1193 
1194 /// What kind of division or remainer instruction this is?
1195 #[derive(Clone)]
1196 pub enum DivOrRemKind {
1197     SignedDiv,
1198     UnsignedDiv,
1199     SignedRem,
1200     UnsignedRem,
1201 }
1202 
1203 impl DivOrRemKind {
is_signed(&self) -> bool1204     pub(crate) fn is_signed(&self) -> bool {
1205         match self {
1206             DivOrRemKind::SignedDiv | DivOrRemKind::SignedRem => true,
1207             _ => false,
1208         }
1209     }
1210 
is_div(&self) -> bool1211     pub(crate) fn is_div(&self) -> bool {
1212         match self {
1213             DivOrRemKind::SignedDiv | DivOrRemKind::UnsignedDiv => true,
1214             _ => false,
1215         }
1216     }
1217 }
1218 
1219 /// These indicate condition code tests.  Not all are represented since not all are useful in
1220 /// compiler-generated code.
1221 #[derive(Copy, Clone)]
1222 #[repr(u8)]
1223 pub enum CC {
1224     ///  overflow
1225     O = 0,
1226     /// no overflow
1227     NO = 1,
1228 
1229     /// < unsigned
1230     B = 2,
1231     /// >= unsigned
1232     NB = 3,
1233 
1234     /// zero
1235     Z = 4,
1236     /// not-zero
1237     NZ = 5,
1238 
1239     /// <= unsigned
1240     BE = 6,
1241     /// > unsigned
1242     NBE = 7,
1243 
1244     /// negative
1245     S = 8,
1246     /// not-negative
1247     NS = 9,
1248 
1249     /// < signed
1250     L = 12,
1251     /// >= signed
1252     NL = 13,
1253 
1254     /// <= signed
1255     LE = 14,
1256     /// > signed
1257     NLE = 15,
1258 
1259     /// parity
1260     P = 10,
1261 
1262     /// not parity
1263     NP = 11,
1264 }
1265 
1266 impl CC {
from_intcc(intcc: IntCC) -> Self1267     pub(crate) fn from_intcc(intcc: IntCC) -> Self {
1268         match intcc {
1269             IntCC::Equal => CC::Z,
1270             IntCC::NotEqual => CC::NZ,
1271             IntCC::SignedGreaterThanOrEqual => CC::NL,
1272             IntCC::SignedGreaterThan => CC::NLE,
1273             IntCC::SignedLessThanOrEqual => CC::LE,
1274             IntCC::SignedLessThan => CC::L,
1275             IntCC::UnsignedGreaterThanOrEqual => CC::NB,
1276             IntCC::UnsignedGreaterThan => CC::NBE,
1277             IntCC::UnsignedLessThanOrEqual => CC::BE,
1278             IntCC::UnsignedLessThan => CC::B,
1279             IntCC::Overflow => CC::O,
1280             IntCC::NotOverflow => CC::NO,
1281         }
1282     }
1283 
invert(&self) -> Self1284     pub(crate) fn invert(&self) -> Self {
1285         match self {
1286             CC::O => CC::NO,
1287             CC::NO => CC::O,
1288 
1289             CC::B => CC::NB,
1290             CC::NB => CC::B,
1291 
1292             CC::Z => CC::NZ,
1293             CC::NZ => CC::Z,
1294 
1295             CC::BE => CC::NBE,
1296             CC::NBE => CC::BE,
1297 
1298             CC::S => CC::NS,
1299             CC::NS => CC::S,
1300 
1301             CC::L => CC::NL,
1302             CC::NL => CC::L,
1303 
1304             CC::LE => CC::NLE,
1305             CC::NLE => CC::LE,
1306 
1307             CC::P => CC::NP,
1308             CC::NP => CC::P,
1309         }
1310     }
1311 
from_floatcc(floatcc: FloatCC) -> Self1312     pub(crate) fn from_floatcc(floatcc: FloatCC) -> Self {
1313         match floatcc {
1314             FloatCC::Ordered => CC::NP,
1315             FloatCC::Unordered => CC::P,
1316             // Alias for NE
1317             FloatCC::OrderedNotEqual => CC::NZ,
1318             // Alias for E
1319             FloatCC::UnorderedOrEqual => CC::Z,
1320             // Alias for A
1321             FloatCC::GreaterThan => CC::NBE,
1322             // Alias for AE
1323             FloatCC::GreaterThanOrEqual => CC::NB,
1324             FloatCC::UnorderedOrLessThan => CC::B,
1325             FloatCC::UnorderedOrLessThanOrEqual => CC::BE,
1326             FloatCC::Equal
1327             | FloatCC::NotEqual
1328             | FloatCC::LessThan
1329             | FloatCC::LessThanOrEqual
1330             | FloatCC::UnorderedOrGreaterThan
1331             | FloatCC::UnorderedOrGreaterThanOrEqual => panic!(
1332                 "{:?} can't be lowered to a CC code; treat as special case.",
1333                 floatcc
1334             ),
1335         }
1336     }
1337 
get_enc(self) -> u81338     pub(crate) fn get_enc(self) -> u8 {
1339         self as u8
1340     }
1341 }
1342 
1343 impl fmt::Debug for CC {
fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result1344     fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
1345         let name = match self {
1346             CC::O => "o",
1347             CC::NO => "no",
1348             CC::B => "b",
1349             CC::NB => "nb",
1350             CC::Z => "z",
1351             CC::NZ => "nz",
1352             CC::BE => "be",
1353             CC::NBE => "nbe",
1354             CC::S => "s",
1355             CC::NS => "ns",
1356             CC::L => "l",
1357             CC::NL => "nl",
1358             CC::LE => "le",
1359             CC::NLE => "nle",
1360             CC::P => "p",
1361             CC::NP => "np",
1362         };
1363         write!(fmt, "{}", name)
1364     }
1365 }
1366 
1367 impl fmt::Display for CC {
fmt(&self, f: &mut fmt::Formatter) -> fmt::Result1368     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1369         fmt::Debug::fmt(self, f)
1370     }
1371 }
1372 
1373 /// Encode the ways that floats can be compared. This is used in float comparisons such as `cmpps`,
1374 /// e.g.; it is distinguished from other float comparisons (e.g. `ucomiss`) in that those use EFLAGS
1375 /// whereas [FcmpImm] is used as an immediate.
1376 pub(crate) enum FcmpImm {
1377     Equal = 0x00,
1378     LessThan = 0x01,
1379     LessThanOrEqual = 0x02,
1380     Unordered = 0x03,
1381     NotEqual = 0x04,
1382     UnorderedOrGreaterThanOrEqual = 0x05,
1383     UnorderedOrGreaterThan = 0x06,
1384     Ordered = 0x07,
1385 }
1386 
1387 impl FcmpImm {
encode(self) -> u81388     pub(crate) fn encode(self) -> u8 {
1389         self as u8
1390     }
1391 }
1392 
1393 impl From<FloatCC> for FcmpImm {
from(cond: FloatCC) -> Self1394     fn from(cond: FloatCC) -> Self {
1395         match cond {
1396             FloatCC::Equal => FcmpImm::Equal,
1397             FloatCC::LessThan => FcmpImm::LessThan,
1398             FloatCC::LessThanOrEqual => FcmpImm::LessThanOrEqual,
1399             FloatCC::Unordered => FcmpImm::Unordered,
1400             FloatCC::NotEqual => FcmpImm::NotEqual,
1401             FloatCC::UnorderedOrGreaterThanOrEqual => FcmpImm::UnorderedOrGreaterThanOrEqual,
1402             FloatCC::UnorderedOrGreaterThan => FcmpImm::UnorderedOrGreaterThan,
1403             FloatCC::Ordered => FcmpImm::Ordered,
1404             _ => panic!("unable to create comparison predicate for {}", cond),
1405         }
1406     }
1407 }
1408 
1409 /// Encode the rounding modes used as part of the Rounding Control field.
1410 /// Note, these rounding immediates only consider the rounding control field
1411 /// (i.e. the rounding mode) which only take up the first two bits when encoded.
1412 /// However the rounding immediate which this field helps make up, also includes
1413 /// bits 3 and 4 which define the rounding select and precision mask respectively.
1414 /// These two bits are not defined here and are implictly set to zero when encoded.
1415 pub(crate) enum RoundImm {
1416     RoundNearest = 0x00,
1417     RoundDown = 0x01,
1418     RoundUp = 0x02,
1419     RoundZero = 0x03,
1420 }
1421 
1422 impl RoundImm {
encode(self) -> u81423     pub(crate) fn encode(self) -> u8 {
1424         self as u8
1425     }
1426 }
1427 
1428 /// An operand's size in bits.
1429 #[derive(Clone, Copy, PartialEq)]
1430 pub enum OperandSize {
1431     Size8,
1432     Size16,
1433     Size32,
1434     Size64,
1435 }
1436 
1437 impl OperandSize {
from_bytes(num_bytes: u32) -> Self1438     pub(crate) fn from_bytes(num_bytes: u32) -> Self {
1439         match num_bytes {
1440             1 => OperandSize::Size8,
1441             2 => OperandSize::Size16,
1442             4 => OperandSize::Size32,
1443             8 => OperandSize::Size64,
1444             _ => unreachable!("Invalid OperandSize: {}", num_bytes),
1445         }
1446     }
1447 
1448     // Computes the OperandSize for a given type.
1449     // For vectors, the OperandSize of the lanes is returned.
from_ty(ty: Type) -> Self1450     pub(crate) fn from_ty(ty: Type) -> Self {
1451         Self::from_bytes(ty.lane_type().bytes())
1452     }
1453 
1454     // Check that the value of self is one of the allowed sizes.
is_one_of(&self, sizes: &[Self]) -> bool1455     pub(crate) fn is_one_of(&self, sizes: &[Self]) -> bool {
1456         sizes.iter().any(|val| *self == *val)
1457     }
1458 
to_bytes(&self) -> u81459     pub(crate) fn to_bytes(&self) -> u8 {
1460         match self {
1461             Self::Size8 => 1,
1462             Self::Size16 => 2,
1463             Self::Size32 => 4,
1464             Self::Size64 => 8,
1465         }
1466     }
1467 
to_bits(&self) -> u81468     pub(crate) fn to_bits(&self) -> u8 {
1469         self.to_bytes() * 8
1470     }
1471 }
1472 
1473 /// An x64 memory fence kind.
1474 #[derive(Clone)]
1475 #[allow(dead_code)]
1476 pub enum FenceKind {
1477     /// `mfence` instruction ("Memory Fence")
1478     MFence,
1479     /// `lfence` instruction ("Load Fence")
1480     LFence,
1481     /// `sfence` instruction ("Store Fence")
1482     SFence,
1483 }
1484