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