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