1 //===- subzero/src/IceInstX86.h - Generic x86 instructions -*- C++ -*--===// 2 // 3 // The Subzero Code Generator 4 // 5 // This file is distributed under the University of Illinois Open Source 6 // License. See LICENSE.TXT for details. 7 // 8 //===----------------------------------------------------------------------===// 9 /// 10 /// \file 11 /// \brief This file defines the InstX86Base template class, as well as the 12 /// generic X86 Instruction class hierarchy. 13 /// 14 //===----------------------------------------------------------------------===// 15 16 #ifndef SUBZERO_SRC_ICEINSTX8664_H 17 #define SUBZERO_SRC_ICEINSTX8664_H 18 19 #include "IceAssemblerX8664.h" 20 #include "IceDefs.h" 21 #include "IceInst.h" 22 #include "IceOperand.h" 23 #include "IceTargetLoweringX86.h" 24 25 namespace Ice { 26 namespace X8664 { 27 28 using Assembler = AssemblerX8664; 29 using AssemblerImmediate = Assembler::Immediate; 30 using TargetLowering = TargetX8664; 31 32 using RegisterSet = ::Ice::RegX8664; 33 using GPRRegister = RegisterSet::GPRRegister; 34 using ByteRegister = RegisterSet::ByteRegister; 35 using XmmRegister = RegisterSet::XmmRegister; 36 37 using Cond = CondX86; 38 using BrCond = Cond::BrCond; 39 using CmppsCond = Cond::CmppsCond; 40 41 template <typename SReg_t, typename DReg_t> 42 using CastEmitterRegOp = Assembler::template CastEmitterRegOp<SReg_t, DReg_t>; 43 template <typename SReg_t, typename DReg_t> 44 using ThreeOpImmEmitter = Assembler::template ThreeOpImmEmitter<SReg_t, DReg_t>; 45 using GPREmitterAddrOp = Assembler::GPREmitterAddrOp; 46 using GPREmitterRegOp = Assembler::GPREmitterRegOp; 47 using GPREmitterShiftD = Assembler::GPREmitterShiftD; 48 using GPREmitterShiftOp = Assembler::GPREmitterShiftOp; 49 using GPREmitterOneOp = Assembler::GPREmitterOneOp; 50 using XmmEmitterRegOp = Assembler::XmmEmitterRegOp; 51 using XmmEmitterShiftOp = Assembler::XmmEmitterShiftOp; 52 using XmmEmitterMovOps = Assembler::XmmEmitterMovOps; 53 54 /// X86Operand extends the Operand hierarchy. Its subclass is X86OperandMem. 55 class X86Operand : public ::Ice::Operand { 56 X86Operand() = delete; 57 X86Operand(const X86Operand &) = delete; 58 X86Operand &operator=(const X86Operand &) = delete; 59 60 public: 61 enum OperandKindX8664 { k__Start = ::Ice::Operand::kTarget, kMem, kSplit }; 62 using ::Ice::Operand::dump; 63 64 void dump(const Cfg *, Ostream &Str) const override; 65 66 protected: X86Operand(OperandKindX8664 Kind,Type Ty)67 X86Operand(OperandKindX8664 Kind, Type Ty) 68 : Operand(static_cast<::Ice::Operand::OperandKind>(Kind), Ty) {} 69 }; 70 71 /// X86OperandMem represents the m64 addressing mode, with optional base and 72 /// index registers, a constant offset, and a fixed shift value for the index 73 /// register. 74 class X86OperandMem : public X86Operand { 75 X86OperandMem() = delete; 76 X86OperandMem(const X86OperandMem &) = delete; 77 X86OperandMem &operator=(const X86OperandMem &) = delete; 78 79 public: 80 enum SegmentRegisters { DefaultSegment = -1, SegReg_NUM }; 81 static X86OperandMem * 82 create(Cfg *Func, Type Ty, Variable *Base, Constant *Offset, 83 Variable *Index = nullptr, uint16_t Shift = 0, 84 SegmentRegisters SegmentRegister = DefaultSegment, 85 bool IsRebased = false) { 86 assert(SegmentRegister == DefaultSegment); 87 (void)SegmentRegister; 88 return new (Func->allocate<X86OperandMem>()) 89 X86OperandMem(Func, Ty, Base, Offset, Index, Shift, IsRebased); 90 } create(Cfg * Func,Type Ty,Variable * Base,Constant * Offset,bool IsRebased)91 static X86OperandMem *create(Cfg *Func, Type Ty, Variable *Base, 92 Constant *Offset, bool IsRebased) { 93 constexpr Variable *NoIndex = nullptr; 94 constexpr uint16_t NoShift = 0; 95 return new (Func->allocate<X86OperandMem>()) 96 X86OperandMem(Func, Ty, Base, Offset, NoIndex, NoShift, IsRebased); 97 } getBase()98 Variable *getBase() const { return Base; } getOffset()99 Constant *getOffset() const { return Offset; } getIndex()100 Variable *getIndex() const { return Index; } getShift()101 uint16_t getShift() const { return Shift; } getSegmentRegister()102 SegmentRegisters getSegmentRegister() const { return DefaultSegment; } emitSegmentOverride(Assembler *)103 void emitSegmentOverride(Assembler *) const {} getIsRebased()104 bool getIsRebased() const { return IsRebased; } 105 106 void emit(const Cfg *Func) const override; 107 using X86Operand::dump; 108 void dump(const Cfg *Func, Ostream &Str) const override; 109 classof(const Operand * Operand)110 static bool classof(const Operand *Operand) { 111 return Operand->getKind() == static_cast<OperandKind>(kMem); 112 } 113 114 private: 115 X86OperandMem(Cfg *Func, Type Ty, Variable *Base, Constant *Offset, 116 Variable *Index, uint16_t Shift, bool IsRebased); 117 118 Variable *const Base; 119 Constant *const Offset; 120 Variable *const Index; 121 const uint16_t Shift; 122 const bool IsRebased; 123 }; 124 125 class InstX86Base : public InstTarget { 126 InstX86Base() = delete; 127 InstX86Base(const InstX86Base &) = delete; 128 InstX86Base &operator=(const InstX86Base &) = delete; 129 130 public: 131 enum InstKindX86 { 132 k__Start = Inst::Target, 133 Adc, 134 AdcRMW, 135 Add, 136 AddRMW, 137 Addps, 138 Addss, 139 And, 140 Andnps, 141 Andps, 142 AndRMW, 143 Blendvps, 144 Br, 145 Bsf, 146 Bsr, 147 Bswap, 148 Call, 149 Cbwdq, 150 Cmov, 151 Cmpps, 152 Cmpxchg, 153 Cmpxchg8b, 154 Cvt, 155 Div, 156 Divps, 157 Divss, 158 FakeRMW, 159 Icmp, 160 Idiv, 161 Imul, 162 ImulImm, 163 Insertps, 164 Int3, 165 Jmp, 166 Label, 167 Lea, 168 Load, 169 Mfence, 170 Minps, 171 Maxps, 172 Minss, 173 Maxss, 174 Mov, 175 Movd, 176 Movmsk, 177 Movp, 178 Movq, 179 MovssRegs, 180 Movsx, 181 Movzx, 182 Mul, 183 Mulps, 184 Mulss, 185 Neg, 186 Nop, 187 Or, 188 Orps, 189 OrRMW, 190 Padd, 191 Padds, 192 Paddus, 193 Pand, 194 Pandn, 195 Pblendvb, 196 Pcmpeq, 197 Pcmpgt, 198 Pextr, 199 Pinsr, 200 Pmull, 201 Pmulhw, 202 Pmulhuw, 203 Pmaddwd, 204 Pmuludq, 205 Pop, 206 Por, 207 Pshufb, 208 Pshufd, 209 Punpckl, 210 Punpckh, 211 Packss, 212 Packus, 213 Psll, 214 Psra, 215 Psrl, 216 Psub, 217 Psubs, 218 Psubus, 219 Push, 220 Pxor, 221 Ret, 222 Rol, 223 Round, 224 Sar, 225 Sbb, 226 SbbRMW, 227 Setcc, 228 Shl, 229 Shld, 230 Shr, 231 Shrd, 232 Shufps, 233 Sqrt, 234 Store, 235 StoreP, 236 StoreQ, 237 StoreD, 238 Sub, 239 SubRMW, 240 Subps, 241 Subss, 242 Test, 243 Ucomiss, 244 UD2, 245 Xadd, 246 Xchg, 247 Xor, 248 Xorps, 249 XorRMW, 250 251 /// Intel Architecture Code Analyzer markers. These are not executable so 252 /// must only be used for analysis. 253 IacaStart, 254 IacaEnd 255 }; 256 257 enum SseSuffix { None, Packed, Unpack, Scalar, Integral, Pack }; 258 259 static const char *getWidthString(Type Ty); 260 static const char *getFldString(Type Ty); 261 static const char *getSseSuffixString(Type DestTy, SseSuffix Suffix); 262 static Type getInVectorElementType(Type Ty); 263 static BrCond getOppositeCondition(BrCond Cond); 264 void dump(const Cfg *Func) const override; 265 266 // Shared emit routines for common forms of instructions. 267 void emitTwoAddress(const Cfg *Func, const char *Opcode, 268 const char *Suffix = "") const; 269 getTarget(const Cfg * Func)270 static TargetLowering *getTarget(const Cfg *Func) { 271 return reinterpret_cast<TargetLowering *>(Func->getTarget()); 272 } 273 274 protected: InstX86Base(Cfg * Func,InstKindX86 Kind,SizeT Maxsrcs,Variable * Dest)275 InstX86Base(Cfg *Func, InstKindX86 Kind, SizeT Maxsrcs, Variable *Dest) 276 : InstTarget(Func, static_cast<InstKind>(Kind), Maxsrcs, Dest) {} 277 isClassof(const Inst * Instr,InstKindX86 MyKind)278 static bool isClassof(const Inst *Instr, InstKindX86 MyKind) { 279 return Instr->getKind() == static_cast<InstKind>(MyKind); 280 } 281 // Most instructions that operate on vector arguments require vector memory 282 // operands to be fully aligned (16-byte alignment for PNaCl vector types). 283 // The stack frame layout and call ABI ensure proper alignment for stack 284 // operands, but memory operands (originating from load/store bitcode 285 // instructions) only have element-size alignment guarantees. This function 286 // validates that none of the operands is a memory operand of vector type, 287 // calling report_fatal_error() if one is found. This function should be 288 // called during emission, and maybe also in the ctor (as long as that fits 289 // the lowering style). validateVectorAddrMode()290 void validateVectorAddrMode() const { 291 if (this->getDest()) 292 this->validateVectorAddrModeOpnd(this->getDest()); 293 for (SizeT i = 0; i < this->getSrcSize(); ++i) { 294 this->validateVectorAddrModeOpnd(this->getSrc(i)); 295 } 296 } 297 298 private: validateVectorAddrModeOpnd(const Operand * Opnd)299 static void validateVectorAddrModeOpnd(const Operand *Opnd) { 300 if (llvm::isa<X86OperandMem>(Opnd) && isVectorType(Opnd->getType())) { 301 llvm::report_fatal_error("Possible misaligned vector memory operation"); 302 } 303 } 304 }; 305 306 /// InstX86FakeRMW represents a non-atomic read-modify-write operation on a 307 /// memory location. An InstX86FakeRMW is a "fake" instruction in that it 308 /// still needs to be lowered to some actual RMW instruction. 309 /// 310 /// If A is some memory address, D is some data value to apply, and OP is an 311 /// arithmetic operator, the instruction operates as: (*A) = (*A) OP D 312 class InstX86FakeRMW final : public InstX86Base { 313 InstX86FakeRMW() = delete; 314 InstX86FakeRMW(const InstX86FakeRMW &) = delete; 315 InstX86FakeRMW &operator=(const InstX86FakeRMW &) = delete; 316 317 public: 318 static InstX86FakeRMW *create(Cfg *Func, Operand *Data, Operand *Addr, 319 Variable *Beacon, InstArithmetic::OpKind Op, 320 uint32_t Align = 1) { 321 // TODO(stichnot): Stop ignoring alignment specification. 322 (void)Align; 323 return new (Func->allocate<InstX86FakeRMW>()) 324 InstX86FakeRMW(Func, Data, Addr, Op, Beacon); 325 } getAddr()326 Operand *getAddr() const { return this->getSrc(1); } getData()327 Operand *getData() const { return this->getSrc(0); } getOp()328 InstArithmetic::OpKind getOp() const { return Op; } getBeacon()329 Variable *getBeacon() const { return llvm::cast<Variable>(this->getSrc(2)); } 330 void dump(const Cfg *Func) const override; classof(const Inst * Instr)331 static bool classof(const Inst *Instr) { 332 return InstX86Base::isClassof(Instr, InstX86Base::FakeRMW); 333 } 334 335 private: 336 InstArithmetic::OpKind Op; 337 InstX86FakeRMW(Cfg *Func, Operand *Data, Operand *Addr, 338 InstArithmetic::OpKind Op, Variable *Beacon); 339 }; 340 341 /// InstX86Label represents an intra-block label that is the target of an 342 /// intra-block branch. The offset between the label and the branch must be 343 /// fit into one byte (considered "near"). These are used for lowering i1 344 /// calculations, Select instructions, and 64-bit compares on a 32-bit 345 /// architecture, without basic block splitting. Basic block splitting is not 346 /// so desirable for several reasons, one of which is the impact on decisions 347 /// based on whether a variable's live range spans multiple basic blocks. 348 /// 349 /// Intra-block control flow must be used with caution. Consider the sequence 350 /// for "c = (a >= b ? x : y)". 351 /// cmp a, b 352 /// br lt, L1 353 /// mov c, x 354 /// jmp L2 355 /// L1: 356 /// mov c, y 357 /// L2: 358 /// 359 /// Labels L1 and L2 are intra-block labels. Without knowledge of the 360 /// intra-block control flow, liveness analysis will determine the "mov c, x" 361 /// instruction to be dead. One way to prevent this is to insert a 362 /// "FakeUse(c)" instruction anywhere between the two "mov c, ..." 363 /// instructions, e.g.: 364 /// 365 /// cmp a, b 366 /// br lt, L1 367 /// mov c, x 368 /// jmp L2 369 /// FakeUse(c) 370 /// L1: 371 /// mov c, y 372 /// L2: 373 /// 374 /// The down-side is that "mov c, x" can never be dead-code eliminated even if 375 /// there are no uses of c. As unlikely as this situation is, it may be 376 /// prevented by running dead code elimination before lowering. 377 class InstX86Label final : public InstX86Base { 378 InstX86Label() = delete; 379 InstX86Label(const InstX86Label &) = delete; 380 InstX86Label &operator=(const InstX86Label &) = delete; 381 382 public: create(Cfg * Func,TargetLowering * Target)383 static InstX86Label *create(Cfg *Func, TargetLowering *Target) { 384 return new (Func->allocate<InstX86Label>()) InstX86Label(Func, Target); 385 } getEmitInstCount()386 uint32_t getEmitInstCount() const override { return 0; } getLabelName()387 GlobalString getLabelName() const { return Name; } getLabelNumber()388 SizeT getLabelNumber() const { return LabelNumber; } isLabel()389 bool isLabel() const override { return true; } 390 void emit(const Cfg *Func) const override; 391 void emitIAS(const Cfg *Func) const override; 392 void dump(const Cfg *Func) const override; setRelocOffset(RelocOffset * Value)393 void setRelocOffset(RelocOffset *Value) { OffsetReloc = Value; } 394 395 private: 396 InstX86Label(Cfg *Func, TargetLowering *Target); 397 398 SizeT LabelNumber; // used for unique label generation. 399 RelocOffset *OffsetReloc = nullptr; 400 GlobalString Name; 401 }; 402 403 /// Conditional and unconditional branch instruction. 404 class InstX86Br final : public InstX86Base { 405 InstX86Br() = delete; 406 InstX86Br(const InstX86Br &) = delete; 407 InstX86Br &operator=(const InstX86Br &) = delete; 408 409 public: 410 enum Mode { Near, Far }; 411 412 /// Create a conditional branch to a node. create(Cfg * Func,CfgNode * TargetTrue,CfgNode * TargetFalse,BrCond Condition,Mode Kind)413 static InstX86Br *create(Cfg *Func, CfgNode *TargetTrue, CfgNode *TargetFalse, 414 BrCond Condition, Mode Kind) { 415 assert(Condition != Cond::Br_None); 416 constexpr InstX86Label *NoLabel = nullptr; 417 return new (Func->allocate<InstX86Br>()) 418 InstX86Br(Func, TargetTrue, TargetFalse, NoLabel, Condition, Kind); 419 } 420 /// Create an unconditional branch to a node. create(Cfg * Func,CfgNode * Target,Mode Kind)421 static InstX86Br *create(Cfg *Func, CfgNode *Target, Mode Kind) { 422 constexpr CfgNode *NoCondTarget = nullptr; 423 constexpr InstX86Label *NoLabel = nullptr; 424 return new (Func->allocate<InstX86Br>()) 425 InstX86Br(Func, NoCondTarget, Target, NoLabel, Cond::Br_None, Kind); 426 } 427 /// Create a non-terminator conditional branch to a node, with a fallthrough 428 /// to the next instruction in the current node. This is used for switch 429 /// lowering. create(Cfg * Func,CfgNode * Target,BrCond Condition,Mode Kind)430 static InstX86Br *create(Cfg *Func, CfgNode *Target, BrCond Condition, 431 Mode Kind) { 432 assert(Condition != Cond::Br_None); 433 constexpr CfgNode *NoUncondTarget = nullptr; 434 constexpr InstX86Label *NoLabel = nullptr; 435 return new (Func->allocate<InstX86Br>()) 436 InstX86Br(Func, Target, NoUncondTarget, NoLabel, Condition, Kind); 437 } 438 /// Create a conditional intra-block branch (or unconditional, if 439 /// Condition==Br_None) to a label in the current block. create(Cfg * Func,InstX86Label * Label,BrCond Condition,Mode Kind)440 static InstX86Br *create(Cfg *Func, InstX86Label *Label, BrCond Condition, 441 Mode Kind) { 442 constexpr CfgNode *NoCondTarget = nullptr; 443 constexpr CfgNode *NoUncondTarget = nullptr; 444 return new (Func->allocate<InstX86Br>()) 445 InstX86Br(Func, NoCondTarget, NoUncondTarget, Label, Condition, Kind); 446 } getTargetTrue()447 const CfgNode *getTargetTrue() const { return TargetTrue; } getTargetFalse()448 const CfgNode *getTargetFalse() const { return TargetFalse; } isNear()449 bool isNear() const { return Kind == Near; } 450 bool optimizeBranch(const CfgNode *NextNode); getEmitInstCount()451 uint32_t getEmitInstCount() const override { 452 uint32_t Sum = 0; 453 if (Label) 454 ++Sum; 455 if (getTargetTrue()) 456 ++Sum; 457 if (getTargetFalse()) 458 ++Sum; 459 return Sum; 460 } isUnconditionalBranch()461 bool isUnconditionalBranch() const override { 462 return !Label && Condition == Cond::Br_None; 463 } getIntraBlockBranchTarget()464 const Inst *getIntraBlockBranchTarget() const override { return Label; } 465 bool repointEdges(CfgNode *OldNode, CfgNode *NewNode) override; 466 void emit(const Cfg *Func) const override; 467 void emitIAS(const Cfg *Func) const override; 468 void dump(const Cfg *Func) const override; classof(const Inst * Instr)469 static bool classof(const Inst *Instr) { 470 return InstX86Base::isClassof(Instr, InstX86Base::Br); 471 } 472 473 private: 474 InstX86Br(Cfg *Func, const CfgNode *TargetTrue, const CfgNode *TargetFalse, 475 const InstX86Label *Label, BrCond Condition, Mode Kind); 476 477 BrCond Condition; 478 const CfgNode *TargetTrue; 479 const CfgNode *TargetFalse; 480 const InstX86Label *Label; // Intra-block branch target 481 const Mode Kind; 482 }; 483 484 /// Jump to a target outside this function, such as tailcall, nacljump, 485 /// naclret, unreachable. This is different from a Branch instruction in that 486 /// there is no intra-function control flow to represent. 487 class InstX86Jmp final : public InstX86Base { 488 InstX86Jmp() = delete; 489 InstX86Jmp(const InstX86Jmp &) = delete; 490 InstX86Jmp &operator=(const InstX86Jmp &) = delete; 491 492 public: create(Cfg * Func,Operand * Target)493 static InstX86Jmp *create(Cfg *Func, Operand *Target) { 494 return new (Func->allocate<InstX86Jmp>()) InstX86Jmp(Func, Target); 495 } getJmpTarget()496 Operand *getJmpTarget() const { return this->getSrc(0); } 497 void emit(const Cfg *Func) const override; 498 void emitIAS(const Cfg *Func) const override; 499 void dump(const Cfg *Func) const override; classof(const Inst * Instr)500 static bool classof(const Inst *Instr) { 501 return InstX86Base::isClassof(Instr, InstX86Base::Jmp); 502 } 503 504 private: 505 InstX86Jmp(Cfg *Func, Operand *Target); 506 }; 507 508 /// Call instruction. Arguments should have already been pushed. 509 class InstX86Call final : public InstX86Base { 510 InstX86Call() = delete; 511 InstX86Call(const InstX86Call &) = delete; 512 InstX86Call &operator=(const InstX86Call &) = delete; 513 514 public: create(Cfg * Func,Variable * Dest,Operand * CallTarget)515 static InstX86Call *create(Cfg *Func, Variable *Dest, Operand *CallTarget) { 516 return new (Func->allocate<InstX86Call>()) 517 InstX86Call(Func, Dest, CallTarget); 518 } getCallTarget()519 Operand *getCallTarget() const { return this->getSrc(0); } 520 void emit(const Cfg *Func) const override; 521 void emitIAS(const Cfg *Func) const override; 522 void dump(const Cfg *Func) const override; classof(const Inst * Instr)523 static bool classof(const Inst *Instr) { 524 return InstX86Base::isClassof(Instr, InstX86Base::Call); 525 } 526 527 private: 528 InstX86Call(Cfg *Func, Variable *Dest, Operand *CallTarget); 529 }; 530 531 /// Emit a one-operand (GPR) instruction. 532 void emitIASOpTyGPR(const Cfg *Func, Type Ty, const Operand *Var, 533 const GPREmitterOneOp &Emitter); 534 535 void emitIASAsAddrOpTyGPR(const Cfg *Func, Type Ty, const Operand *Op0, 536 const Operand *Op1, const GPREmitterAddrOp &Emitter); 537 538 void emitIASGPRShift(const Cfg *Func, Type Ty, const Variable *Var, 539 const Operand *Src, const GPREmitterShiftOp &Emitter); 540 541 void emitIASAddrOpTyGPR(const Cfg *Func, Type Ty, const AsmAddress &Addr, 542 const Operand *Src, const GPREmitterAddrOp &Emitter); 543 544 void emitIASRegOpTyXMM(const Cfg *Func, Type Ty, const Variable *Var, 545 const Operand *Src, const XmmEmitterRegOp &Emitter); 546 547 void emitIASGPRShiftDouble(const Cfg *Func, const Variable *Dest, 548 const Operand *Src1Op, const Operand *Src2Op, 549 const GPREmitterShiftD &Emitter); 550 551 template <typename DReg_t, typename SReg_t, DReg_t (*destEnc)(RegNumT), 552 SReg_t (*srcEnc)(RegNumT)> 553 void emitIASCastRegOp(const Cfg *Func, Type DestTy, const Variable *Dest, 554 Type SrcTy, const Operand *Src, 555 const CastEmitterRegOp<DReg_t, SReg_t> &Emitter); 556 557 template <typename DReg_t, typename SReg_t, DReg_t (*destEnc)(RegNumT), 558 SReg_t (*srcEnc)(RegNumT)> 559 void emitIASThreeOpImmOps(const Cfg *Func, Type DispatchTy, 560 const Variable *Dest, const Operand *Src0, 561 const Operand *Src1, 562 const ThreeOpImmEmitter<DReg_t, SReg_t> Emitter); 563 564 void emitIASMovlikeXMM(const Cfg *Func, const Variable *Dest, 565 const Operand *Src, const XmmEmitterMovOps Emitter); 566 567 void emitVariableBlendInst(const char *Opcode, const Inst *Instr, 568 const Cfg *Func); 569 570 void emitIASVariableBlendInst(const Inst *Instr, const Cfg *Func, 571 const XmmEmitterRegOp &Emitter); 572 573 void emitIASXmmShift(const Cfg *Func, Type Ty, const Variable *Var, 574 const Operand *Src, const XmmEmitterShiftOp &Emitter); 575 576 /// Emit a two-operand (GPR) instruction, where the dest operand is a Variable 577 /// that's guaranteed to be a register. 578 template <bool VarCanBeByte = true, bool SrcCanBeByte = true> 579 void emitIASRegOpTyGPR(const Cfg *Func, Type Ty, const Variable *Dst, 580 const Operand *Src, const GPREmitterRegOp &Emitter); 581 582 /// Instructions of the form x := op(x). 583 template <typename InstX86Base::InstKindX86 K> 584 class InstX86BaseInplaceopGPR : public InstX86Base { 585 InstX86BaseInplaceopGPR() = delete; 586 InstX86BaseInplaceopGPR(const InstX86BaseInplaceopGPR &) = delete; 587 InstX86BaseInplaceopGPR &operator=(const InstX86BaseInplaceopGPR &) = delete; 588 589 public: 590 using Base = InstX86BaseInplaceopGPR<K>; 591 emit(const Cfg * Func)592 void emit(const Cfg *Func) const override { 593 if (!BuildDefs::dump()) 594 return; 595 Ostream &Str = Func->getContext()->getStrEmit(); 596 assert(this->getSrcSize() == 1); 597 Str << "\t" << Opcode << "\t"; 598 this->getSrc(0)->emit(Func); 599 } emitIAS(const Cfg * Func)600 void emitIAS(const Cfg *Func) const override { 601 assert(this->getSrcSize() == 1); 602 const Variable *Var = this->getDest(); 603 Type Ty = Var->getType(); 604 emitIASOpTyGPR(Func, Ty, Var, Emitter); 605 } dump(const Cfg * Func)606 void dump(const Cfg *Func) const override { 607 if (!BuildDefs::dump()) 608 return; 609 Ostream &Str = Func->getContext()->getStrDump(); 610 this->dumpDest(Func); 611 Str << " = " << Opcode << "." << this->getDest()->getType() << " "; 612 this->dumpSources(Func); 613 } classof(const Inst * Instr)614 static bool classof(const Inst *Instr) { 615 return InstX86Base::isClassof(Instr, K); 616 } 617 618 protected: InstX86BaseInplaceopGPR(Cfg * Func,Operand * SrcDest)619 InstX86BaseInplaceopGPR(Cfg *Func, Operand *SrcDest) 620 : InstX86Base(Func, K, 1, llvm::dyn_cast<Variable>(SrcDest)) { 621 this->addSource(SrcDest); 622 } 623 624 private: 625 static const char *const Opcode; 626 static const GPREmitterOneOp Emitter; 627 }; 628 629 /// Instructions of the form x := op(y). 630 template <typename InstX86Base::InstKindX86 K> 631 class InstX86BaseUnaryopGPR : public InstX86Base { 632 InstX86BaseUnaryopGPR() = delete; 633 InstX86BaseUnaryopGPR(const InstX86BaseUnaryopGPR &) = delete; 634 InstX86BaseUnaryopGPR &operator=(const InstX86BaseUnaryopGPR &) = delete; 635 636 public: 637 using Base = InstX86BaseUnaryopGPR<K>; 638 emit(const Cfg * Func)639 void emit(const Cfg *Func) const override { 640 if (!BuildDefs::dump()) 641 return; 642 Ostream &Str = Func->getContext()->getStrEmit(); 643 assert(this->getSrcSize() == 1); 644 Type SrcTy = this->getSrc(0)->getType(); 645 Type DestTy = this->getDest()->getType(); 646 Str << "\t" << Opcode << this->getWidthString(SrcTy); 647 // Movsx and movzx need both the source and dest type width letter to 648 // define the operation. The other unary operations have the same source 649 // and dest type and as a result need only one letter. 650 if (SrcTy != DestTy) 651 Str << this->getWidthString(DestTy); 652 Str << "\t"; 653 this->getSrc(0)->emit(Func); 654 Str << ", "; 655 this->getDest()->emit(Func); 656 } emitIAS(const Cfg * Func)657 void emitIAS(const Cfg *Func) const override { 658 assert(this->getSrcSize() == 1 && K != InstX86Base::Lea); 659 const Variable *Var = this->getDest(); 660 Type Ty = Var->getType(); 661 const Operand *Src = this->getSrc(0); 662 emitIASRegOpTyGPR(Func, Ty, Var, Src, Emitter); 663 } dump(const Cfg * Func)664 void dump(const Cfg *Func) const override { 665 if (!BuildDefs::dump()) 666 return; 667 Ostream &Str = Func->getContext()->getStrDump(); 668 this->dumpDest(Func); 669 Str << " = " << Opcode << "." << this->getSrc(0)->getType() << " "; 670 this->dumpSources(Func); 671 } 672 classof(const Inst * Instr)673 static bool classof(const Inst *Instr) { 674 return InstX86Base::isClassof(Instr, K); 675 } 676 677 protected: InstX86BaseUnaryopGPR(Cfg * Func,Variable * Dest,Operand * Src)678 InstX86BaseUnaryopGPR(Cfg *Func, Variable *Dest, Operand *Src) 679 : InstX86Base(Func, K, 1, Dest) { 680 this->addSource(Src); 681 } 682 683 static const char *const Opcode; 684 static const GPREmitterRegOp Emitter; 685 }; 686 687 template <typename InstX86Base::InstKindX86 K> 688 class InstX86BaseUnaryopXmm : public InstX86Base { 689 InstX86BaseUnaryopXmm() = delete; 690 InstX86BaseUnaryopXmm(const InstX86BaseUnaryopXmm &) = delete; 691 InstX86BaseUnaryopXmm &operator=(const InstX86BaseUnaryopXmm &) = delete; 692 693 public: 694 using Base = InstX86BaseUnaryopXmm<K>; 695 emit(const Cfg * Func)696 void emit(const Cfg *Func) const override { 697 if (!BuildDefs::dump()) 698 return; 699 Ostream &Str = Func->getContext()->getStrEmit(); 700 assert(this->getSrcSize() == 1); 701 Str << "\t" << Opcode << "\t"; 702 this->getSrc(0)->emit(Func); 703 Str << ", "; 704 this->getDest()->emit(Func); 705 } emitIAS(const Cfg * Func)706 void emitIAS(const Cfg *Func) const override { 707 Type Ty = this->getDest()->getType(); 708 assert(this->getSrcSize() == 1); 709 emitIASRegOpTyXMM(Func, Ty, this->getDest(), this->getSrc(0), Emitter); 710 } dump(const Cfg * Func)711 void dump(const Cfg *Func) const override { 712 if (!BuildDefs::dump()) 713 return; 714 Ostream &Str = Func->getContext()->getStrDump(); 715 this->dumpDest(Func); 716 Str << " = " << Opcode << "." << this->getDest()->getType() << " "; 717 this->dumpSources(Func); 718 } classof(const Inst * Instr)719 static bool classof(const Inst *Instr) { 720 return InstX86Base::isClassof(Instr, K); 721 } 722 723 protected: InstX86BaseUnaryopXmm(Cfg * Func,Variable * Dest,Operand * Src)724 InstX86BaseUnaryopXmm(Cfg *Func, Variable *Dest, Operand *Src) 725 : InstX86Base(Func, K, 1, Dest) { 726 this->addSource(Src); 727 } 728 729 static const char *const Opcode; 730 static const XmmEmitterRegOp Emitter; 731 }; 732 733 template <typename InstX86Base::InstKindX86 K> 734 class InstX86BaseBinopGPRShift : public InstX86Base { 735 InstX86BaseBinopGPRShift() = delete; 736 InstX86BaseBinopGPRShift(const InstX86BaseBinopGPRShift &) = delete; 737 InstX86BaseBinopGPRShift & 738 operator=(const InstX86BaseBinopGPRShift &) = delete; 739 740 public: 741 using Base = InstX86BaseBinopGPRShift<K>; 742 emit(const Cfg * Func)743 void emit(const Cfg *Func) const override { 744 if (!BuildDefs::dump()) 745 return; 746 this->emitTwoAddress(Func, Opcode); 747 } emitIAS(const Cfg * Func)748 void emitIAS(const Cfg *Func) const override { 749 Type Ty = this->getDest()->getType(); 750 assert(this->getSrcSize() == 2); 751 emitIASGPRShift(Func, Ty, this->getDest(), this->getSrc(1), Emitter); 752 } dump(const Cfg * Func)753 void dump(const Cfg *Func) const override { 754 if (!BuildDefs::dump()) 755 return; 756 Ostream &Str = Func->getContext()->getStrDump(); 757 this->dumpDest(Func); 758 Str << " = " << Opcode << "." << this->getDest()->getType() << " "; 759 this->dumpSources(Func); 760 } classof(const Inst * Instr)761 static bool classof(const Inst *Instr) { 762 return InstX86Base::isClassof(Instr, K); 763 } 764 765 protected: InstX86BaseBinopGPRShift(Cfg * Func,Variable * Dest,Operand * Source)766 InstX86BaseBinopGPRShift(Cfg *Func, Variable *Dest, Operand *Source) 767 : InstX86Base(Func, K, 2, Dest) { 768 this->addSource(Dest); 769 this->addSource(Source); 770 } 771 772 static const char *const Opcode; 773 static const GPREmitterShiftOp Emitter; 774 }; 775 776 template <typename InstX86Base::InstKindX86 K> 777 class InstX86BaseBinopGPR : public InstX86Base { 778 InstX86BaseBinopGPR() = delete; 779 InstX86BaseBinopGPR(const InstX86BaseBinopGPR &) = delete; 780 InstX86BaseBinopGPR &operator=(const InstX86BaseBinopGPR &) = delete; 781 782 public: 783 using Base = InstX86BaseBinopGPR<K>; 784 emit(const Cfg * Func)785 void emit(const Cfg *Func) const override { 786 if (!BuildDefs::dump()) 787 return; 788 this->emitTwoAddress(Func, Opcode); 789 } emitIAS(const Cfg * Func)790 void emitIAS(const Cfg *Func) const override { 791 Type Ty = this->getDest()->getType(); 792 assert(this->getSrcSize() == 2); 793 static_assert(K != InstX86Base::Lea, "Lea should be a unaryop."); 794 emitIASRegOpTyGPR(Func, Ty, this->getDest(), this->getSrc(1), Emitter); 795 } dump(const Cfg * Func)796 void dump(const Cfg *Func) const override { 797 if (!BuildDefs::dump()) 798 return; 799 Ostream &Str = Func->getContext()->getStrDump(); 800 this->dumpDest(Func); 801 Str << " = " << Opcode << "." << this->getDest()->getType() << " "; 802 this->dumpSources(Func); 803 } classof(const Inst * Instr)804 static bool classof(const Inst *Instr) { 805 return InstX86Base::isClassof(Instr, K); 806 } 807 808 protected: InstX86BaseBinopGPR(Cfg * Func,Variable * Dest,Operand * Source)809 InstX86BaseBinopGPR(Cfg *Func, Variable *Dest, Operand *Source) 810 : InstX86Base(Func, K, 2, Dest) { 811 this->addSource(Dest); 812 this->addSource(Source); 813 } 814 815 static const char *const Opcode; 816 static const GPREmitterRegOp Emitter; 817 }; 818 819 template <typename InstX86Base::InstKindX86 K> 820 class InstX86BaseBinopRMW : public InstX86Base { 821 InstX86BaseBinopRMW() = delete; 822 InstX86BaseBinopRMW(const InstX86BaseBinopRMW &) = delete; 823 InstX86BaseBinopRMW &operator=(const InstX86BaseBinopRMW &) = delete; 824 825 public: 826 using Base = InstX86BaseBinopRMW<K>; 827 emit(const Cfg * Func)828 void emit(const Cfg *Func) const override { 829 if (!BuildDefs::dump()) 830 return; 831 this->emitTwoAddress(Func, Opcode); 832 } emitIAS(const Cfg * Func)833 void emitIAS(const Cfg *Func) const override { 834 Type Ty = this->getSrc(0)->getType(); 835 assert(this->getSrcSize() == 2); 836 emitIASAsAddrOpTyGPR(Func, Ty, this->getSrc(0), this->getSrc(1), Emitter); 837 } dump(const Cfg * Func)838 void dump(const Cfg *Func) const override { 839 if (!BuildDefs::dump()) 840 return; 841 Ostream &Str = Func->getContext()->getStrDump(); 842 Str << Opcode << "." << this->getSrc(0)->getType() << " "; 843 this->dumpSources(Func); 844 } classof(const Inst * Instr)845 static bool classof(const Inst *Instr) { 846 return InstX86Base::isClassof(Instr, K); 847 } 848 849 protected: InstX86BaseBinopRMW(Cfg * Func,X86OperandMem * DestSrc0,Operand * Src1)850 InstX86BaseBinopRMW(Cfg *Func, X86OperandMem *DestSrc0, Operand *Src1) 851 : InstX86Base(Func, K, 2, nullptr) { 852 this->addSource(DestSrc0); 853 this->addSource(Src1); 854 } 855 856 static const char *const Opcode; 857 static const GPREmitterAddrOp Emitter; 858 }; 859 860 template <typename InstX86Base::InstKindX86 K, bool NeedsElementType, 861 typename InstX86Base::SseSuffix Suffix> 862 class InstX86BaseBinopXmm : public InstX86Base { 863 InstX86BaseBinopXmm() = delete; 864 InstX86BaseBinopXmm(const InstX86BaseBinopXmm &) = delete; 865 InstX86BaseBinopXmm &operator=(const InstX86BaseBinopXmm &) = delete; 866 867 public: 868 using Base = InstX86BaseBinopXmm<K, NeedsElementType, Suffix>; 869 emit(const Cfg * Func)870 void emit(const Cfg *Func) const override { 871 if (!BuildDefs::dump()) 872 return; 873 this->validateVectorAddrMode(); 874 const Type DestTy = ArithmeticTypeOverride == IceType_void 875 ? this->getDest()->getType() 876 : ArithmeticTypeOverride; 877 const char *SuffixString = getSseSuffixString(DestTy, Suffix); 878 this->emitTwoAddress(Func, Opcode, SuffixString); 879 } emitIAS(const Cfg * Func)880 void emitIAS(const Cfg *Func) const override { 881 this->validateVectorAddrMode(); 882 Type Ty = this->getDest()->getType(); 883 if (NeedsElementType) 884 Ty = typeElementType(Ty); 885 assert(this->getSrcSize() == 2); 886 emitIASRegOpTyXMM(Func, Ty, this->getDest(), this->getSrc(1), Emitter); 887 } dump(const Cfg * Func)888 void dump(const Cfg *Func) const override { 889 if (!BuildDefs::dump()) 890 return; 891 Ostream &Str = Func->getContext()->getStrDump(); 892 this->dumpDest(Func); 893 Str << " = " << Opcode << "." << this->getDest()->getType() << " "; 894 this->dumpSources(Func); 895 } classof(const Inst * Instr)896 static bool classof(const Inst *Instr) { 897 return InstX86Base::isClassof(Instr, K); 898 } 899 900 protected: 901 InstX86BaseBinopXmm(Cfg *Func, Variable *Dest, Operand *Source, 902 Type ArithmeticTypeOverride = IceType_void) 903 : InstX86Base(Func, K, 2, Dest), 904 ArithmeticTypeOverride(ArithmeticTypeOverride) { 905 this->addSource(Dest); 906 this->addSource(Source); 907 } 908 909 const Type ArithmeticTypeOverride; 910 static const char *const Opcode; 911 static const XmmEmitterRegOp Emitter; 912 }; 913 914 template <typename InstX86Base::InstKindX86 K, bool AllowAllTypes = false> 915 class InstX86BaseBinopXmmShift : public InstX86Base { 916 InstX86BaseBinopXmmShift() = delete; 917 InstX86BaseBinopXmmShift(const InstX86BaseBinopXmmShift &) = delete; 918 InstX86BaseBinopXmmShift & 919 operator=(const InstX86BaseBinopXmmShift &) = delete; 920 921 public: 922 using Base = InstX86BaseBinopXmmShift<K, AllowAllTypes>; 923 emit(const Cfg * Func)924 void emit(const Cfg *Func) const override { 925 if (!BuildDefs::dump()) 926 return; 927 this->validateVectorAddrMode(); 928 // Shift operations are always integral, and hence always need a suffix. 929 const Type DestTy = this->getDest()->getType(); 930 const char *SuffixString = getSseSuffixString(DestTy, SseSuffix::Integral); 931 this->emitTwoAddress(Func, this->Opcode, SuffixString); 932 } emitIAS(const Cfg * Func)933 void emitIAS(const Cfg *Func) const override { 934 this->validateVectorAddrMode(); 935 Type Ty = this->getDest()->getType(); 936 assert(AllowAllTypes || isVectorType(Ty)); 937 Type ElementTy = typeElementType(Ty); 938 assert(this->getSrcSize() == 2); 939 emitIASXmmShift(Func, ElementTy, this->getDest(), this->getSrc(1), Emitter); 940 } dump(const Cfg * Func)941 void dump(const Cfg *Func) const override { 942 if (!BuildDefs::dump()) 943 return; 944 Ostream &Str = Func->getContext()->getStrDump(); 945 this->dumpDest(Func); 946 Str << " = " << Opcode << "." << this->getDest()->getType() << " "; 947 this->dumpSources(Func); 948 } classof(const Inst * Instr)949 static bool classof(const Inst *Instr) { 950 return InstX86Base::isClassof(Instr, K); 951 } 952 953 protected: InstX86BaseBinopXmmShift(Cfg * Func,Variable * Dest,Operand * Source)954 InstX86BaseBinopXmmShift(Cfg *Func, Variable *Dest, Operand *Source) 955 : InstX86Base(Func, K, 2, Dest) { 956 this->addSource(Dest); 957 this->addSource(Source); 958 } 959 960 static const char *const Opcode; 961 static const XmmEmitterShiftOp Emitter; 962 }; 963 964 template <typename InstX86Base::InstKindX86 K> 965 class InstX86BaseTernop : public InstX86Base { 966 InstX86BaseTernop() = delete; 967 InstX86BaseTernop(const InstX86BaseTernop &) = delete; 968 InstX86BaseTernop &operator=(const InstX86BaseTernop &) = delete; 969 970 public: 971 using Base = InstX86BaseTernop<K>; 972 emit(const Cfg * Func)973 void emit(const Cfg *Func) const override { 974 if (!BuildDefs::dump()) 975 return; 976 Ostream &Str = Func->getContext()->getStrEmit(); 977 assert(this->getSrcSize() == 3); 978 Str << "\t" << Opcode << "\t"; 979 this->getSrc(2)->emit(Func); 980 Str << ", "; 981 this->getSrc(1)->emit(Func); 982 Str << ", "; 983 this->getDest()->emit(Func); 984 } dump(const Cfg * Func)985 void dump(const Cfg *Func) const override { 986 if (!BuildDefs::dump()) 987 return; 988 Ostream &Str = Func->getContext()->getStrDump(); 989 this->dumpDest(Func); 990 Str << " = " << Opcode << "." << this->getDest()->getType() << " "; 991 this->dumpSources(Func); 992 } classof(const Inst * Instr)993 static bool classof(const Inst *Instr) { 994 return InstX86Base::isClassof(Instr, K); 995 } 996 997 protected: InstX86BaseTernop(Cfg * Func,Variable * Dest,Operand * Source1,Operand * Source2)998 InstX86BaseTernop(Cfg *Func, Variable *Dest, Operand *Source1, 999 Operand *Source2) 1000 : InstX86Base(Func, K, 3, Dest) { 1001 this->addSource(Dest); 1002 this->addSource(Source1); 1003 this->addSource(Source2); 1004 } 1005 1006 static const char *const Opcode; 1007 }; 1008 1009 // Instructions of the form x := y op z 1010 template <typename InstX86Base::InstKindX86 K> 1011 class InstX86BaseThreeAddressop : public InstX86Base { 1012 InstX86BaseThreeAddressop() = delete; 1013 InstX86BaseThreeAddressop(const InstX86BaseThreeAddressop &) = delete; 1014 InstX86BaseThreeAddressop & 1015 operator=(const InstX86BaseThreeAddressop &) = delete; 1016 1017 public: 1018 using Base = InstX86BaseThreeAddressop<K>; 1019 emit(const Cfg * Func)1020 void emit(const Cfg *Func) const override { 1021 if (!BuildDefs::dump()) 1022 return; 1023 Ostream &Str = Func->getContext()->getStrEmit(); 1024 assert(this->getSrcSize() == 2); 1025 Str << "\t" << Opcode << "\t"; 1026 this->getSrc(1)->emit(Func); 1027 Str << ", "; 1028 this->getSrc(0)->emit(Func); 1029 Str << ", "; 1030 this->getDest()->emit(Func); 1031 } dump(const Cfg * Func)1032 void dump(const Cfg *Func) const override { 1033 if (!BuildDefs::dump()) 1034 return; 1035 Ostream &Str = Func->getContext()->getStrDump(); 1036 this->dumpDest(Func); 1037 Str << " = " << Opcode << "." << this->getDest()->getType() << " "; 1038 this->dumpSources(Func); 1039 } classof(const Inst * Instr)1040 static bool classof(const Inst *Instr) { 1041 return InstX86Base::isClassof(Instr, K); 1042 } 1043 1044 protected: InstX86BaseThreeAddressop(Cfg * Func,Variable * Dest,Operand * Source0,Operand * Source1)1045 InstX86BaseThreeAddressop(Cfg *Func, Variable *Dest, Operand *Source0, 1046 Operand *Source1) 1047 : InstX86Base(Func, K, 2, Dest) { 1048 this->addSource(Source0); 1049 this->addSource(Source1); 1050 } 1051 1052 static const char *const Opcode; 1053 }; 1054 1055 /// Base class for assignment instructions 1056 template <typename InstX86Base::InstKindX86 K> 1057 class InstX86BaseMovlike : public InstX86Base { 1058 InstX86BaseMovlike() = delete; 1059 InstX86BaseMovlike(const InstX86BaseMovlike &) = delete; 1060 InstX86BaseMovlike &operator=(const InstX86BaseMovlike &) = delete; 1061 1062 public: 1063 using Base = InstX86BaseMovlike<K>; 1064 isRedundantAssign()1065 bool isRedundantAssign() const override { 1066 if (const auto *SrcVar = llvm::dyn_cast<const Variable>(this->getSrc(0))) { 1067 if (SrcVar->hasReg() && this->Dest->hasReg()) { 1068 // An assignment between physical registers is considered redundant if 1069 // they have the same base register and the same encoding. E.g.: 1070 // mov cl, ecx ==> redundant 1071 // mov ch, ecx ==> not redundant due to different encodings 1072 // mov ch, ebp ==> not redundant due to different base registers 1073 // mov ecx, ecx ==> redundant, and dangerous in x86-64. i64 zexting 1074 // is handled by Inst86Zext. 1075 const auto SrcReg = SrcVar->getRegNum(); 1076 const auto DestReg = this->Dest->getRegNum(); 1077 return (RegX8664::getEncoding(SrcReg) == 1078 RegX8664::getEncoding(DestReg)) && 1079 (RegX8664::getBaseReg(SrcReg) == RegX8664::getBaseReg(DestReg)); 1080 } 1081 } 1082 return checkForRedundantAssign(this->getDest(), this->getSrc(0)); 1083 } isVarAssign()1084 bool isVarAssign() const override { 1085 return llvm::isa<Variable>(this->getSrc(0)); 1086 } dump(const Cfg * Func)1087 void dump(const Cfg *Func) const override { 1088 if (!BuildDefs::dump()) 1089 return; 1090 Ostream &Str = Func->getContext()->getStrDump(); 1091 Str << Opcode << "." << this->getDest()->getType() << " "; 1092 this->dumpDest(Func); 1093 Str << ", "; 1094 this->dumpSources(Func); 1095 } classof(const Inst * Instr)1096 static bool classof(const Inst *Instr) { 1097 return InstX86Base::isClassof(Instr, K); 1098 } 1099 1100 protected: InstX86BaseMovlike(Cfg * Func,Variable * Dest,Operand * Source)1101 InstX86BaseMovlike(Cfg *Func, Variable *Dest, Operand *Source) 1102 : InstX86Base(Func, K, 1, Dest) { 1103 this->addSource(Source); 1104 // For an integer assignment, make sure it's either a same-type assignment 1105 // or a truncation. 1106 assert(!isScalarIntegerType(Dest->getType()) || 1107 (typeWidthInBytes(Dest->getType()) <= 1108 typeWidthInBytes(Source->getType()))); 1109 } 1110 1111 static const char *const Opcode; 1112 }; 1113 1114 class InstX86Bswap : public InstX86BaseInplaceopGPR<InstX86Base::Bswap> { 1115 public: create(Cfg * Func,Operand * SrcDest)1116 static InstX86Bswap *create(Cfg *Func, Operand *SrcDest) { 1117 return new (Func->allocate<InstX86Bswap>()) InstX86Bswap(Func, SrcDest); 1118 } 1119 1120 private: InstX86Bswap(Cfg * Func,Operand * SrcDest)1121 InstX86Bswap(Cfg *Func, Operand *SrcDest) 1122 : InstX86BaseInplaceopGPR<InstX86Base::Bswap>(Func, SrcDest) {} 1123 }; 1124 1125 class InstX86Neg : public InstX86BaseInplaceopGPR<InstX86Base::Neg> { 1126 public: create(Cfg * Func,Operand * SrcDest)1127 static InstX86Neg *create(Cfg *Func, Operand *SrcDest) { 1128 return new (Func->allocate<InstX86Neg>()) InstX86Neg(Func, SrcDest); 1129 } 1130 1131 private: InstX86Neg(Cfg * Func,Operand * SrcDest)1132 InstX86Neg(Cfg *Func, Operand *SrcDest) 1133 : InstX86BaseInplaceopGPR<InstX86Base::Neg>(Func, SrcDest) {} 1134 }; 1135 1136 class InstX86Bsf : public InstX86BaseUnaryopGPR<InstX86Base::Bsf> { 1137 public: create(Cfg * Func,Variable * Dest,Operand * Src)1138 static InstX86Bsf *create(Cfg *Func, Variable *Dest, Operand *Src) { 1139 return new (Func->allocate<InstX86Bsf>()) InstX86Bsf(Func, Dest, Src); 1140 } 1141 1142 private: InstX86Bsf(Cfg * Func,Variable * Dest,Operand * Src)1143 InstX86Bsf(Cfg *Func, Variable *Dest, Operand *Src) 1144 : InstX86BaseUnaryopGPR<InstX86Base::Bsf>(Func, Dest, Src) {} 1145 }; 1146 1147 class InstX86Bsr : public InstX86BaseUnaryopGPR<InstX86Base::Bsr> { 1148 public: create(Cfg * Func,Variable * Dest,Operand * Src)1149 static InstX86Bsr *create(Cfg *Func, Variable *Dest, Operand *Src) { 1150 return new (Func->allocate<InstX86Bsr>()) InstX86Bsr(Func, Dest, Src); 1151 } 1152 1153 private: InstX86Bsr(Cfg * Func,Variable * Dest,Operand * Src)1154 InstX86Bsr(Cfg *Func, Variable *Dest, Operand *Src) 1155 : InstX86BaseUnaryopGPR<InstX86Base::Bsr>(Func, Dest, Src) {} 1156 }; 1157 1158 class InstX86Lea : public InstX86BaseUnaryopGPR<InstX86Base::Lea> { 1159 public: create(Cfg * Func,Variable * Dest,Operand * Src)1160 static InstX86Lea *create(Cfg *Func, Variable *Dest, Operand *Src) { 1161 return new (Func->allocate<InstX86Lea>()) InstX86Lea(Func, Dest, Src); 1162 } 1163 1164 void emit(const Cfg *Func) const override; 1165 void emitIAS(const Cfg *Func) const override; 1166 1167 private: InstX86Lea(Cfg * Func,Variable * Dest,Operand * Src)1168 InstX86Lea(Cfg *Func, Variable *Dest, Operand *Src) 1169 : InstX86BaseUnaryopGPR<InstX86Base::Lea>(Func, Dest, Src) {} 1170 1171 Inst *deoptToAddOrNull(const Cfg *Func) const; 1172 }; 1173 1174 // Cbwdq instruction - wrapper for cbw, cwd, and cdq 1175 class InstX86Cbwdq : public InstX86BaseUnaryopGPR<InstX86Base::Cbwdq> { 1176 public: create(Cfg * Func,Variable * Dest,Operand * Src)1177 static InstX86Cbwdq *create(Cfg *Func, Variable *Dest, Operand *Src) { 1178 return new (Func->allocate<InstX86Cbwdq>()) InstX86Cbwdq(Func, Dest, Src); 1179 } 1180 1181 void emit(const Cfg *Func) const override; 1182 void emitIAS(const Cfg *Func) const override; 1183 1184 private: InstX86Cbwdq(Cfg * Func,Variable * Dest,Operand * Src)1185 InstX86Cbwdq(Cfg *Func, Variable *Dest, Operand *Src) 1186 : InstX86BaseUnaryopGPR<InstX86Base::Cbwdq>(Func, Dest, Src) {} 1187 }; 1188 1189 class InstX86Movsx : public InstX86BaseUnaryopGPR<InstX86Base::Movsx> { 1190 public: create(Cfg * Func,Variable * Dest,Operand * Src)1191 static InstX86Movsx *create(Cfg *Func, Variable *Dest, Operand *Src) { 1192 assert(typeWidthInBytes(Dest->getType()) > 1193 typeWidthInBytes(Src->getType())); 1194 return new (Func->allocate<InstX86Movsx>()) InstX86Movsx(Func, Dest, Src); 1195 } 1196 1197 void emitIAS(const Cfg *Func) const override; 1198 1199 private: InstX86Movsx(Cfg * Func,Variable * Dest,Operand * Src)1200 InstX86Movsx(Cfg *Func, Variable *Dest, Operand *Src) 1201 : InstX86BaseUnaryopGPR<InstX86Base::Movsx>(Func, Dest, Src) {} 1202 }; 1203 1204 class InstX86Movzx : public InstX86BaseUnaryopGPR<InstX86Base::Movzx> { 1205 public: create(Cfg * Func,Variable * Dest,Operand * Src)1206 static InstX86Movzx *create(Cfg *Func, Variable *Dest, Operand *Src) { 1207 assert(typeWidthInBytes(Dest->getType()) > 1208 typeWidthInBytes(Src->getType())); 1209 return new (Func->allocate<InstX86Movzx>()) InstX86Movzx(Func, Dest, Src); 1210 } 1211 1212 void emit(const Cfg *Func) const override; 1213 1214 void emitIAS(const Cfg *Func) const override; 1215 setMustKeep()1216 void setMustKeep() { MustKeep = true; } 1217 1218 private: 1219 bool MustKeep = false; 1220 InstX86Movzx(Cfg * Func,Variable * Dest,Operand * Src)1221 InstX86Movzx(Cfg *Func, Variable *Dest, Operand *Src) 1222 : InstX86BaseUnaryopGPR<InstX86Base::Movzx>(Func, Dest, Src) {} 1223 1224 bool mayBeElided(const Variable *Dest, const Operand *Src) const; 1225 }; 1226 1227 class InstX86Movd : public InstX86BaseUnaryopXmm<InstX86Base::Movd> { 1228 public: create(Cfg * Func,Variable * Dest,Operand * Src)1229 static InstX86Movd *create(Cfg *Func, Variable *Dest, Operand *Src) { 1230 return new (Func->allocate<InstX86Movd>()) InstX86Movd(Func, Dest, Src); 1231 } 1232 1233 void emit(const Cfg *Func) const override; 1234 1235 void emitIAS(const Cfg *Func) const override; 1236 1237 private: InstX86Movd(Cfg * Func,Variable * Dest,Operand * Src)1238 InstX86Movd(Cfg *Func, Variable *Dest, Operand *Src) 1239 : InstX86BaseUnaryopXmm<InstX86Base::Movd>(Func, Dest, Src) {} 1240 }; 1241 1242 class InstX86Movmsk final : public InstX86Base { 1243 InstX86Movmsk() = delete; 1244 InstX86Movmsk(const InstX86Movmsk &) = delete; 1245 InstX86Movmsk &operator=(const InstX86Movmsk &) = delete; 1246 1247 public: create(Cfg * Func,Variable * Dest,Operand * Source)1248 static InstX86Movmsk *create(Cfg *Func, Variable *Dest, Operand *Source) { 1249 return new (Func->allocate<InstX86Movmsk>()) 1250 InstX86Movmsk(Func, Dest, Source); 1251 } 1252 void emit(const Cfg *Func) const override; 1253 void emitIAS(const Cfg *Func) const override; 1254 void dump(const Cfg *Func) const override; classof(const Inst * Instr)1255 static bool classof(const Inst *Instr) { 1256 return InstX86Base::isClassof(Instr, InstX86Base::Movmsk); 1257 } 1258 1259 private: 1260 InstX86Movmsk(Cfg *Func, Variable *Dest, Operand *Source); 1261 }; 1262 1263 class InstX86Sqrt : public InstX86BaseUnaryopXmm<InstX86Base::Sqrt> { 1264 public: create(Cfg * Func,Variable * Dest,Operand * Src)1265 static InstX86Sqrt *create(Cfg *Func, Variable *Dest, Operand *Src) { 1266 return new (Func->allocate<InstX86Sqrt>()) InstX86Sqrt(Func, Dest, Src); 1267 } 1268 1269 virtual void emit(const Cfg *Func) const override; 1270 1271 private: InstX86Sqrt(Cfg * Func,Variable * Dest,Operand * Src)1272 InstX86Sqrt(Cfg *Func, Variable *Dest, Operand *Src) 1273 : InstX86BaseUnaryopXmm<InstX86Base::Sqrt>(Func, Dest, Src) {} 1274 }; 1275 1276 /// Move/assignment instruction - wrapper for mov/movss/movsd. 1277 class InstX86Mov : public InstX86BaseMovlike<InstX86Base::Mov> { 1278 public: create(Cfg * Func,Variable * Dest,Operand * Source)1279 static InstX86Mov *create(Cfg *Func, Variable *Dest, Operand *Source) { 1280 assert(!isScalarIntegerType(Dest->getType()) || 1281 (typeWidthInBytes(Dest->getType()) <= 1282 typeWidthInBytes(Source->getType()))); 1283 return new (Func->allocate<InstX86Mov>()) InstX86Mov(Func, Dest, Source); 1284 } 1285 1286 void emit(const Cfg *Func) const override; 1287 void emitIAS(const Cfg *Func) const override; 1288 1289 private: InstX86Mov(Cfg * Func,Variable * Dest,Operand * Source)1290 InstX86Mov(Cfg *Func, Variable *Dest, Operand *Source) 1291 : InstX86BaseMovlike<InstX86Base::Mov>(Func, Dest, Source) {} 1292 }; 1293 1294 /// Move packed - copy 128 bit values between XMM registers, or mem128 and XMM 1295 /// registers. 1296 class InstX86Movp : public InstX86BaseMovlike<InstX86Base::Movp> { 1297 public: create(Cfg * Func,Variable * Dest,Operand * Source)1298 static InstX86Movp *create(Cfg *Func, Variable *Dest, Operand *Source) { 1299 return new (Func->allocate<InstX86Movp>()) InstX86Movp(Func, Dest, Source); 1300 } 1301 1302 void emit(const Cfg *Func) const override; 1303 void emitIAS(const Cfg *Func) const override; 1304 1305 private: InstX86Movp(Cfg * Func,Variable * Dest,Operand * Source)1306 InstX86Movp(Cfg *Func, Variable *Dest, Operand *Source) 1307 : InstX86BaseMovlike<InstX86Base::Movp>(Func, Dest, Source) {} 1308 }; 1309 1310 /// Movq - copy between XMM registers, or mem64 and XMM registers. 1311 class InstX86Movq : public InstX86BaseMovlike<InstX86Base::Movq> { 1312 public: create(Cfg * Func,Variable * Dest,Operand * Source)1313 static InstX86Movq *create(Cfg *Func, Variable *Dest, Operand *Source) { 1314 return new (Func->allocate<InstX86Movq>()) InstX86Movq(Func, Dest, Source); 1315 } 1316 1317 void emit(const Cfg *Func) const override; 1318 void emitIAS(const Cfg *Func) const override; 1319 1320 private: InstX86Movq(Cfg * Func,Variable * Dest,Operand * Source)1321 InstX86Movq(Cfg *Func, Variable *Dest, Operand *Source) 1322 : InstX86BaseMovlike<InstX86Base::Movq>(Func, Dest, Source) {} 1323 }; 1324 1325 class InstX86Add : public InstX86BaseBinopGPR<InstX86Base::Add> { 1326 public: create(Cfg * Func,Variable * Dest,Operand * Source)1327 static InstX86Add *create(Cfg *Func, Variable *Dest, Operand *Source) { 1328 return new (Func->allocate<InstX86Add>()) InstX86Add(Func, Dest, Source); 1329 } 1330 1331 private: InstX86Add(Cfg * Func,Variable * Dest,Operand * Source)1332 InstX86Add(Cfg *Func, Variable *Dest, Operand *Source) 1333 : InstX86BaseBinopGPR<InstX86Base::Add>(Func, Dest, Source) {} 1334 }; 1335 1336 class InstX86AddRMW : public InstX86BaseBinopRMW<InstX86Base::AddRMW> { 1337 public: create(Cfg * Func,X86OperandMem * DestSrc0,Operand * Src1)1338 static InstX86AddRMW *create(Cfg *Func, X86OperandMem *DestSrc0, 1339 Operand *Src1) { 1340 return new (Func->allocate<InstX86AddRMW>()) 1341 InstX86AddRMW(Func, DestSrc0, Src1); 1342 } 1343 1344 private: InstX86AddRMW(Cfg * Func,X86OperandMem * DestSrc0,Operand * Src1)1345 InstX86AddRMW(Cfg *Func, X86OperandMem *DestSrc0, Operand *Src1) 1346 : InstX86BaseBinopRMW<InstX86Base::AddRMW>(Func, DestSrc0, Src1) {} 1347 }; 1348 1349 class InstX86Addps 1350 : public InstX86BaseBinopXmm<InstX86Base::Addps, true, 1351 InstX86Base::SseSuffix::Packed> { 1352 public: create(Cfg * Func,Variable * Dest,Operand * Source)1353 static InstX86Addps *create(Cfg *Func, Variable *Dest, Operand *Source) { 1354 return new (Func->allocate<InstX86Addps>()) 1355 InstX86Addps(Func, Dest, Source); 1356 } 1357 1358 private: InstX86Addps(Cfg * Func,Variable * Dest,Operand * Source)1359 InstX86Addps(Cfg *Func, Variable *Dest, Operand *Source) 1360 : InstX86BaseBinopXmm<InstX86Base::Addps, true, 1361 InstX86Base::SseSuffix::Packed>(Func, Dest, 1362 Source) {} 1363 }; 1364 1365 class InstX86Adc : public InstX86BaseBinopGPR<InstX86Base::Adc> { 1366 public: create(Cfg * Func,Variable * Dest,Operand * Source)1367 static InstX86Adc *create(Cfg *Func, Variable *Dest, Operand *Source) { 1368 return new (Func->allocate<InstX86Adc>()) InstX86Adc(Func, Dest, Source); 1369 } 1370 1371 private: InstX86Adc(Cfg * Func,Variable * Dest,Operand * Source)1372 InstX86Adc(Cfg *Func, Variable *Dest, Operand *Source) 1373 : InstX86BaseBinopGPR<InstX86Base::Adc>(Func, Dest, Source) {} 1374 }; 1375 1376 class InstX86AdcRMW : public InstX86BaseBinopRMW<InstX86Base::AdcRMW> { 1377 public: create(Cfg * Func,X86OperandMem * DestSrc0,Operand * Src1)1378 static InstX86AdcRMW *create(Cfg *Func, X86OperandMem *DestSrc0, 1379 Operand *Src1) { 1380 return new (Func->allocate<InstX86AdcRMW>()) 1381 InstX86AdcRMW(Func, DestSrc0, Src1); 1382 } 1383 1384 private: InstX86AdcRMW(Cfg * Func,X86OperandMem * DestSrc0,Operand * Src1)1385 InstX86AdcRMW(Cfg *Func, X86OperandMem *DestSrc0, Operand *Src1) 1386 : InstX86BaseBinopRMW<InstX86Base::AdcRMW>(Func, DestSrc0, Src1) {} 1387 }; 1388 1389 class InstX86Addss 1390 : public InstX86BaseBinopXmm<InstX86Base::Addss, false, 1391 InstX86Base::SseSuffix::Scalar> { 1392 public: create(Cfg * Func,Variable * Dest,Operand * Source)1393 static InstX86Addss *create(Cfg *Func, Variable *Dest, Operand *Source) { 1394 return new (Func->allocate<InstX86Addss>()) 1395 InstX86Addss(Func, Dest, Source); 1396 } 1397 1398 private: InstX86Addss(Cfg * Func,Variable * Dest,Operand * Source)1399 InstX86Addss(Cfg *Func, Variable *Dest, Operand *Source) 1400 : InstX86BaseBinopXmm<InstX86Base::Addss, false, 1401 InstX86Base::SseSuffix::Scalar>(Func, Dest, 1402 Source) {} 1403 }; 1404 1405 class InstX86Padd 1406 : public InstX86BaseBinopXmm<InstX86Base::Padd, true, 1407 InstX86Base::SseSuffix::Integral> { 1408 public: create(Cfg * Func,Variable * Dest,Operand * Source)1409 static InstX86Padd *create(Cfg *Func, Variable *Dest, Operand *Source) { 1410 return new (Func->allocate<InstX86Padd>()) InstX86Padd(Func, Dest, Source); 1411 } 1412 1413 private: InstX86Padd(Cfg * Func,Variable * Dest,Operand * Source)1414 InstX86Padd(Cfg *Func, Variable *Dest, Operand *Source) 1415 : InstX86BaseBinopXmm<InstX86Base::Padd, true, 1416 InstX86Base::SseSuffix::Integral>(Func, Dest, 1417 Source) {} 1418 }; 1419 1420 class InstX86Padds 1421 : public InstX86BaseBinopXmm<InstX86Base::Padds, true, 1422 InstX86Base::SseSuffix::Integral> { 1423 public: create(Cfg * Func,Variable * Dest,Operand * Source)1424 static InstX86Padds *create(Cfg *Func, Variable *Dest, Operand *Source) { 1425 return new (Func->allocate<InstX86Padds>()) 1426 InstX86Padds(Func, Dest, Source); 1427 } 1428 1429 private: InstX86Padds(Cfg * Func,Variable * Dest,Operand * Source)1430 InstX86Padds(Cfg *Func, Variable *Dest, Operand *Source) 1431 : InstX86BaseBinopXmm<InstX86Base::Padds, true, 1432 InstX86Base::SseSuffix::Integral>(Func, Dest, 1433 Source) {} 1434 }; 1435 1436 class InstX86Paddus 1437 : public InstX86BaseBinopXmm<InstX86Base::Paddus, true, 1438 InstX86Base::SseSuffix::Integral> { 1439 public: create(Cfg * Func,Variable * Dest,Operand * Source)1440 static InstX86Paddus *create(Cfg *Func, Variable *Dest, Operand *Source) { 1441 return new (Func->allocate<InstX86Paddus>()) 1442 InstX86Paddus(Func, Dest, Source); 1443 } 1444 1445 private: InstX86Paddus(Cfg * Func,Variable * Dest,Operand * Source)1446 InstX86Paddus(Cfg *Func, Variable *Dest, Operand *Source) 1447 : InstX86BaseBinopXmm<InstX86Base::Paddus, true, 1448 InstX86Base::SseSuffix::Integral>(Func, Dest, 1449 Source) {} 1450 }; 1451 1452 class InstX86Sub : public InstX86BaseBinopGPR<InstX86Base::Sub> { 1453 public: create(Cfg * Func,Variable * Dest,Operand * Source)1454 static InstX86Sub *create(Cfg *Func, Variable *Dest, Operand *Source) { 1455 return new (Func->allocate<InstX86Sub>()) InstX86Sub(Func, Dest, Source); 1456 } 1457 1458 private: InstX86Sub(Cfg * Func,Variable * Dest,Operand * Source)1459 InstX86Sub(Cfg *Func, Variable *Dest, Operand *Source) 1460 : InstX86BaseBinopGPR<InstX86Base::Sub>(Func, Dest, Source) {} 1461 }; 1462 1463 class InstX86SubRMW : public InstX86BaseBinopRMW<InstX86Base::SubRMW> { 1464 public: create(Cfg * Func,X86OperandMem * DestSrc0,Operand * Src1)1465 static InstX86SubRMW *create(Cfg *Func, X86OperandMem *DestSrc0, 1466 Operand *Src1) { 1467 return new (Func->allocate<InstX86SubRMW>()) 1468 InstX86SubRMW(Func, DestSrc0, Src1); 1469 } 1470 1471 private: InstX86SubRMW(Cfg * Func,X86OperandMem * DestSrc0,Operand * Src1)1472 InstX86SubRMW(Cfg *Func, X86OperandMem *DestSrc0, Operand *Src1) 1473 : InstX86BaseBinopRMW<InstX86Base::SubRMW>(Func, DestSrc0, Src1) {} 1474 }; 1475 1476 class InstX86Subps 1477 : public InstX86BaseBinopXmm<InstX86Base::Subps, true, 1478 InstX86Base::SseSuffix::Packed> { 1479 public: create(Cfg * Func,Variable * Dest,Operand * Source)1480 static InstX86Subps *create(Cfg *Func, Variable *Dest, Operand *Source) { 1481 return new (Func->allocate<InstX86Subps>()) 1482 InstX86Subps(Func, Dest, Source); 1483 } 1484 1485 private: InstX86Subps(Cfg * Func,Variable * Dest,Operand * Source)1486 InstX86Subps(Cfg *Func, Variable *Dest, Operand *Source) 1487 : InstX86BaseBinopXmm<InstX86Base::Subps, true, 1488 InstX86Base::SseSuffix::Packed>(Func, Dest, 1489 Source) {} 1490 }; 1491 1492 class InstX86Subss 1493 : public InstX86BaseBinopXmm<InstX86Base::Subss, false, 1494 InstX86Base::SseSuffix::Scalar> { 1495 public: create(Cfg * Func,Variable * Dest,Operand * Source)1496 static InstX86Subss *create(Cfg *Func, Variable *Dest, Operand *Source) { 1497 return new (Func->allocate<InstX86Subss>()) 1498 InstX86Subss(Func, Dest, Source); 1499 } 1500 1501 private: InstX86Subss(Cfg * Func,Variable * Dest,Operand * Source)1502 InstX86Subss(Cfg *Func, Variable *Dest, Operand *Source) 1503 : InstX86BaseBinopXmm<InstX86Base::Subss, false, 1504 InstX86Base::SseSuffix::Scalar>(Func, Dest, 1505 Source) {} 1506 }; 1507 1508 class InstX86Sbb : public InstX86BaseBinopGPR<InstX86Base::Sbb> { 1509 public: create(Cfg * Func,Variable * Dest,Operand * Source)1510 static InstX86Sbb *create(Cfg *Func, Variable *Dest, Operand *Source) { 1511 return new (Func->allocate<InstX86Sbb>()) InstX86Sbb(Func, Dest, Source); 1512 } 1513 1514 private: InstX86Sbb(Cfg * Func,Variable * Dest,Operand * Source)1515 InstX86Sbb(Cfg *Func, Variable *Dest, Operand *Source) 1516 : InstX86BaseBinopGPR<InstX86Base::Sbb>(Func, Dest, Source) {} 1517 }; 1518 1519 class InstX86SbbRMW : public InstX86BaseBinopRMW<InstX86Base::SbbRMW> { 1520 public: create(Cfg * Func,X86OperandMem * DestSrc0,Operand * Src1)1521 static InstX86SbbRMW *create(Cfg *Func, X86OperandMem *DestSrc0, 1522 Operand *Src1) { 1523 return new (Func->allocate<InstX86SbbRMW>()) 1524 InstX86SbbRMW(Func, DestSrc0, Src1); 1525 } 1526 1527 private: InstX86SbbRMW(Cfg * Func,X86OperandMem * DestSrc0,Operand * Src1)1528 InstX86SbbRMW(Cfg *Func, X86OperandMem *DestSrc0, Operand *Src1) 1529 : InstX86BaseBinopRMW<InstX86Base::SbbRMW>(Func, DestSrc0, Src1) {} 1530 }; 1531 1532 class InstX86Psub 1533 : public InstX86BaseBinopXmm<InstX86Base::Psub, true, 1534 InstX86Base::SseSuffix::Integral> { 1535 public: create(Cfg * Func,Variable * Dest,Operand * Source)1536 static InstX86Psub *create(Cfg *Func, Variable *Dest, Operand *Source) { 1537 return new (Func->allocate<InstX86Psub>()) InstX86Psub(Func, Dest, Source); 1538 } 1539 1540 private: InstX86Psub(Cfg * Func,Variable * Dest,Operand * Source)1541 InstX86Psub(Cfg *Func, Variable *Dest, Operand *Source) 1542 : InstX86BaseBinopXmm<InstX86Base::Psub, true, 1543 InstX86Base::SseSuffix::Integral>(Func, Dest, 1544 Source) {} 1545 }; 1546 1547 class InstX86Psubs 1548 : public InstX86BaseBinopXmm<InstX86Base::Psubs, true, 1549 InstX86Base::SseSuffix::Integral> { 1550 public: create(Cfg * Func,Variable * Dest,Operand * Source)1551 static InstX86Psubs *create(Cfg *Func, Variable *Dest, Operand *Source) { 1552 return new (Func->allocate<InstX86Psubs>()) 1553 InstX86Psubs(Func, Dest, Source); 1554 } 1555 1556 private: InstX86Psubs(Cfg * Func,Variable * Dest,Operand * Source)1557 InstX86Psubs(Cfg *Func, Variable *Dest, Operand *Source) 1558 : InstX86BaseBinopXmm<InstX86Base::Psubs, true, 1559 InstX86Base::SseSuffix::Integral>(Func, Dest, 1560 Source) {} 1561 }; 1562 1563 class InstX86Psubus 1564 : public InstX86BaseBinopXmm<InstX86Base::Psubus, true, 1565 InstX86Base::SseSuffix::Integral> { 1566 public: create(Cfg * Func,Variable * Dest,Operand * Source)1567 static InstX86Psubus *create(Cfg *Func, Variable *Dest, Operand *Source) { 1568 return new (Func->allocate<InstX86Psubus>()) 1569 InstX86Psubus(Func, Dest, Source); 1570 } 1571 1572 private: InstX86Psubus(Cfg * Func,Variable * Dest,Operand * Source)1573 InstX86Psubus(Cfg *Func, Variable *Dest, Operand *Source) 1574 : InstX86BaseBinopXmm<InstX86Base::Psubus, true, 1575 InstX86Base::SseSuffix::Integral>(Func, Dest, 1576 Source) {} 1577 }; 1578 1579 class InstX86And : public InstX86BaseBinopGPR<InstX86Base::And> { 1580 public: create(Cfg * Func,Variable * Dest,Operand * Source)1581 static InstX86And *create(Cfg *Func, Variable *Dest, Operand *Source) { 1582 return new (Func->allocate<InstX86And>()) InstX86And(Func, Dest, Source); 1583 } 1584 1585 private: InstX86And(Cfg * Func,Variable * Dest,Operand * Source)1586 InstX86And(Cfg *Func, Variable *Dest, Operand *Source) 1587 : InstX86BaseBinopGPR<InstX86Base::And>(Func, Dest, Source) {} 1588 }; 1589 1590 class InstX86Andnps 1591 : public InstX86BaseBinopXmm<InstX86Base::Andnps, true, 1592 InstX86Base::SseSuffix::Packed> { 1593 public: create(Cfg * Func,Variable * Dest,Operand * Source)1594 static InstX86Andnps *create(Cfg *Func, Variable *Dest, Operand *Source) { 1595 return new (Func->allocate<InstX86Andnps>()) 1596 InstX86Andnps(Func, Dest, Source); 1597 } 1598 1599 private: InstX86Andnps(Cfg * Func,Variable * Dest,Operand * Source)1600 InstX86Andnps(Cfg *Func, Variable *Dest, Operand *Source) 1601 : InstX86BaseBinopXmm<InstX86Base::Andnps, true, 1602 InstX86Base::SseSuffix::Packed>(Func, Dest, 1603 Source) {} 1604 }; 1605 1606 class InstX86Andps 1607 : public InstX86BaseBinopXmm<InstX86Base::Andps, true, 1608 InstX86Base::SseSuffix::Packed> { 1609 public: create(Cfg * Func,Variable * Dest,Operand * Source)1610 static InstX86Andps *create(Cfg *Func, Variable *Dest, Operand *Source) { 1611 return new (Func->allocate<InstX86Andps>()) 1612 InstX86Andps(Func, Dest, Source); 1613 } 1614 1615 private: InstX86Andps(Cfg * Func,Variable * Dest,Operand * Source)1616 InstX86Andps(Cfg *Func, Variable *Dest, Operand *Source) 1617 : InstX86BaseBinopXmm<InstX86Base::Andps, true, 1618 InstX86Base::SseSuffix::Packed>(Func, Dest, 1619 Source) {} 1620 }; 1621 1622 class InstX86AndRMW : public InstX86BaseBinopRMW<InstX86Base::AndRMW> { 1623 public: create(Cfg * Func,X86OperandMem * DestSrc0,Operand * Src1)1624 static InstX86AndRMW *create(Cfg *Func, X86OperandMem *DestSrc0, 1625 Operand *Src1) { 1626 return new (Func->allocate<InstX86AndRMW>()) 1627 InstX86AndRMW(Func, DestSrc0, Src1); 1628 } 1629 1630 private: InstX86AndRMW(Cfg * Func,X86OperandMem * DestSrc0,Operand * Src1)1631 InstX86AndRMW(Cfg *Func, X86OperandMem *DestSrc0, Operand *Src1) 1632 : InstX86BaseBinopRMW<InstX86Base::AndRMW>(Func, DestSrc0, Src1) {} 1633 }; 1634 1635 class InstX86Pand : public InstX86BaseBinopXmm<InstX86Base::Pand, false, 1636 InstX86Base::SseSuffix::None> { 1637 public: create(Cfg * Func,Variable * Dest,Operand * Source)1638 static InstX86Pand *create(Cfg *Func, Variable *Dest, Operand *Source) { 1639 return new (Func->allocate<InstX86Pand>()) InstX86Pand(Func, Dest, Source); 1640 } 1641 1642 private: InstX86Pand(Cfg * Func,Variable * Dest,Operand * Source)1643 InstX86Pand(Cfg *Func, Variable *Dest, Operand *Source) 1644 : InstX86BaseBinopXmm<InstX86Base::Pand, false, 1645 InstX86Base::SseSuffix::None>(Func, Dest, Source) {} 1646 }; 1647 1648 class InstX86Pandn : public InstX86BaseBinopXmm<InstX86Base::Pandn, false, 1649 InstX86Base::SseSuffix::None> { 1650 public: create(Cfg * Func,Variable * Dest,Operand * Source)1651 static InstX86Pandn *create(Cfg *Func, Variable *Dest, Operand *Source) { 1652 return new (Func->allocate<InstX86Pandn>()) 1653 InstX86Pandn(Func, Dest, Source); 1654 } 1655 1656 private: InstX86Pandn(Cfg * Func,Variable * Dest,Operand * Source)1657 InstX86Pandn(Cfg *Func, Variable *Dest, Operand *Source) 1658 : InstX86BaseBinopXmm<InstX86Base::Pandn, false, 1659 InstX86Base::SseSuffix::None>(Func, Dest, Source) {} 1660 }; 1661 1662 class InstX86Maxss 1663 : public InstX86BaseBinopXmm<InstX86Base::Maxss, true, 1664 InstX86Base::SseSuffix::Scalar> { 1665 public: create(Cfg * Func,Variable * Dest,Operand * Source)1666 static InstX86Maxss *create(Cfg *Func, Variable *Dest, Operand *Source) { 1667 return new (Func->allocate<InstX86Maxss>()) 1668 InstX86Maxss(Func, Dest, Source); 1669 } 1670 1671 private: InstX86Maxss(Cfg * Func,Variable * Dest,Operand * Source)1672 InstX86Maxss(Cfg *Func, Variable *Dest, Operand *Source) 1673 : InstX86BaseBinopXmm<InstX86Base::Maxss, true, 1674 InstX86Base::SseSuffix::Scalar>(Func, Dest, 1675 Source) {} 1676 }; 1677 1678 class InstX86Minss 1679 : public InstX86BaseBinopXmm<InstX86Base::Minss, true, 1680 InstX86Base::SseSuffix::Scalar> { 1681 public: create(Cfg * Func,Variable * Dest,Operand * Source)1682 static InstX86Minss *create(Cfg *Func, Variable *Dest, Operand *Source) { 1683 return new (Func->allocate<InstX86Minss>()) 1684 InstX86Minss(Func, Dest, Source); 1685 } 1686 1687 private: InstX86Minss(Cfg * Func,Variable * Dest,Operand * Source)1688 InstX86Minss(Cfg *Func, Variable *Dest, Operand *Source) 1689 : InstX86BaseBinopXmm<InstX86Base::Minss, true, 1690 InstX86Base::SseSuffix::Scalar>(Func, Dest, 1691 Source) {} 1692 }; 1693 1694 class InstX86Maxps : public InstX86BaseBinopXmm<InstX86Base::Maxps, true, 1695 InstX86Base::SseSuffix::None> { 1696 public: create(Cfg * Func,Variable * Dest,Operand * Source)1697 static InstX86Maxps *create(Cfg *Func, Variable *Dest, Operand *Source) { 1698 return new (Func->allocate<InstX86Maxps>()) 1699 InstX86Maxps(Func, Dest, Source); 1700 } 1701 1702 private: InstX86Maxps(Cfg * Func,Variable * Dest,Operand * Source)1703 InstX86Maxps(Cfg *Func, Variable *Dest, Operand *Source) 1704 : InstX86BaseBinopXmm<InstX86Base::Maxps, true, 1705 InstX86Base::SseSuffix::None>(Func, Dest, Source) {} 1706 }; 1707 1708 class InstX86Minps : public InstX86BaseBinopXmm<InstX86Base::Minps, true, 1709 InstX86Base::SseSuffix::None> { 1710 public: create(Cfg * Func,Variable * Dest,Operand * Source)1711 static InstX86Minps *create(Cfg *Func, Variable *Dest, Operand *Source) { 1712 return new (Func->allocate<InstX86Minps>()) 1713 InstX86Minps(Func, Dest, Source); 1714 } 1715 1716 private: InstX86Minps(Cfg * Func,Variable * Dest,Operand * Source)1717 InstX86Minps(Cfg *Func, Variable *Dest, Operand *Source) 1718 : InstX86BaseBinopXmm<InstX86Base::Minps, true, 1719 InstX86Base::SseSuffix::None>(Func, Dest, Source) {} 1720 }; 1721 1722 class InstX86Or : public InstX86BaseBinopGPR<InstX86Base::Or> { 1723 public: create(Cfg * Func,Variable * Dest,Operand * Source)1724 static InstX86Or *create(Cfg *Func, Variable *Dest, Operand *Source) { 1725 return new (Func->allocate<InstX86Or>()) InstX86Or(Func, Dest, Source); 1726 } 1727 1728 private: InstX86Or(Cfg * Func,Variable * Dest,Operand * Source)1729 InstX86Or(Cfg *Func, Variable *Dest, Operand *Source) 1730 : InstX86BaseBinopGPR<InstX86Base::Or>(Func, Dest, Source) {} 1731 }; 1732 1733 class InstX86Orps : public InstX86BaseBinopXmm<InstX86Base::Orps, true, 1734 InstX86Base::SseSuffix::Packed> { 1735 public: create(Cfg * Func,Variable * Dest,Operand * Source)1736 static InstX86Orps *create(Cfg *Func, Variable *Dest, Operand *Source) { 1737 return new (Func->allocate<InstX86Orps>()) InstX86Orps(Func, Dest, Source); 1738 } 1739 1740 private: InstX86Orps(Cfg * Func,Variable * Dest,Operand * Source)1741 InstX86Orps(Cfg *Func, Variable *Dest, Operand *Source) 1742 : InstX86BaseBinopXmm<InstX86Base::Orps, true, 1743 InstX86Base::SseSuffix::Packed>(Func, Dest, 1744 Source) {} 1745 }; 1746 1747 class InstX86OrRMW : public InstX86BaseBinopRMW<InstX86Base::OrRMW> { 1748 public: create(Cfg * Func,X86OperandMem * DestSrc0,Operand * Src1)1749 static InstX86OrRMW *create(Cfg *Func, X86OperandMem *DestSrc0, 1750 Operand *Src1) { 1751 return new (Func->allocate<InstX86OrRMW>()) 1752 InstX86OrRMW(Func, DestSrc0, Src1); 1753 } 1754 1755 private: InstX86OrRMW(Cfg * Func,X86OperandMem * DestSrc0,Operand * Src1)1756 InstX86OrRMW(Cfg *Func, X86OperandMem *DestSrc0, Operand *Src1) 1757 : InstX86BaseBinopRMW<InstX86Base::OrRMW>(Func, DestSrc0, Src1) {} 1758 }; 1759 1760 class InstX86Por : public InstX86BaseBinopXmm<InstX86Base::Por, false, 1761 InstX86Base::SseSuffix::None> { 1762 public: create(Cfg * Func,Variable * Dest,Operand * Source)1763 static InstX86Por *create(Cfg *Func, Variable *Dest, Operand *Source) { 1764 return new (Func->allocate<InstX86Por>()) InstX86Por(Func, Dest, Source); 1765 } 1766 1767 private: InstX86Por(Cfg * Func,Variable * Dest,Operand * Source)1768 InstX86Por(Cfg *Func, Variable *Dest, Operand *Source) 1769 : InstX86BaseBinopXmm<InstX86Base::Por, false, 1770 InstX86Base::SseSuffix::None>(Func, Dest, Source) {} 1771 }; 1772 1773 class InstX86Xor : public InstX86BaseBinopGPR<InstX86Base::Xor> { 1774 public: create(Cfg * Func,Variable * Dest,Operand * Source)1775 static InstX86Xor *create(Cfg *Func, Variable *Dest, Operand *Source) { 1776 return new (Func->allocate<InstX86Xor>()) InstX86Xor(Func, Dest, Source); 1777 } 1778 1779 private: InstX86Xor(Cfg * Func,Variable * Dest,Operand * Source)1780 InstX86Xor(Cfg *Func, Variable *Dest, Operand *Source) 1781 : InstX86BaseBinopGPR<InstX86Base::Xor>(Func, Dest, Source) {} 1782 }; 1783 1784 class InstX86Xorps 1785 : public InstX86BaseBinopXmm<InstX86Base::Xorps, true, 1786 InstX86Base::SseSuffix::Packed> { 1787 public: create(Cfg * Func,Variable * Dest,Operand * Source)1788 static InstX86Xorps *create(Cfg *Func, Variable *Dest, Operand *Source) { 1789 return new (Func->allocate<InstX86Xorps>()) 1790 InstX86Xorps(Func, Dest, Source); 1791 } 1792 1793 private: InstX86Xorps(Cfg * Func,Variable * Dest,Operand * Source)1794 InstX86Xorps(Cfg *Func, Variable *Dest, Operand *Source) 1795 : InstX86BaseBinopXmm<InstX86Base::Xorps, true, 1796 InstX86Base::SseSuffix::Packed>(Func, Dest, 1797 Source) {} 1798 }; 1799 1800 class InstX86XorRMW : public InstX86BaseBinopRMW<InstX86Base::XorRMW> { 1801 public: create(Cfg * Func,X86OperandMem * DestSrc0,Operand * Src1)1802 static InstX86XorRMW *create(Cfg *Func, X86OperandMem *DestSrc0, 1803 Operand *Src1) { 1804 return new (Func->allocate<InstX86XorRMW>()) 1805 InstX86XorRMW(Func, DestSrc0, Src1); 1806 } 1807 1808 private: InstX86XorRMW(Cfg * Func,X86OperandMem * DestSrc0,Operand * Src1)1809 InstX86XorRMW(Cfg *Func, X86OperandMem *DestSrc0, Operand *Src1) 1810 : InstX86BaseBinopRMW<InstX86Base::XorRMW>(Func, DestSrc0, Src1) {} 1811 }; 1812 1813 class InstX86Pxor : public InstX86BaseBinopXmm<InstX86Base::Pxor, false, 1814 InstX86Base::SseSuffix::None> { 1815 public: create(Cfg * Func,Variable * Dest,Operand * Source)1816 static InstX86Pxor *create(Cfg *Func, Variable *Dest, Operand *Source) { 1817 return new (Func->allocate<InstX86Pxor>()) InstX86Pxor(Func, Dest, Source); 1818 } 1819 1820 private: InstX86Pxor(Cfg * Func,Variable * Dest,Operand * Source)1821 InstX86Pxor(Cfg *Func, Variable *Dest, Operand *Source) 1822 : InstX86BaseBinopXmm<InstX86Base::Pxor, false, 1823 InstX86Base::SseSuffix::None>(Func, Dest, Source) {} 1824 }; 1825 1826 class InstX86Imul : public InstX86BaseBinopGPR<InstX86Base::Imul> { 1827 public: create(Cfg * Func,Variable * Dest,Operand * Source)1828 static InstX86Imul *create(Cfg *Func, Variable *Dest, Operand *Source) { 1829 return new (Func->allocate<InstX86Imul>()) InstX86Imul(Func, Dest, Source); 1830 } 1831 1832 void emit(const Cfg *Func) const override; 1833 void emitIAS(const Cfg *Func) const override; 1834 1835 private: InstX86Imul(Cfg * Func,Variable * Dest,Operand * Source)1836 InstX86Imul(Cfg *Func, Variable *Dest, Operand *Source) 1837 : InstX86BaseBinopGPR<InstX86Base::Imul>(Func, Dest, Source) {} 1838 }; 1839 1840 class InstX86ImulImm : public InstX86BaseThreeAddressop<InstX86Base::ImulImm> { 1841 public: create(Cfg * Func,Variable * Dest,Operand * Source0,Operand * Source1)1842 static InstX86ImulImm *create(Cfg *Func, Variable *Dest, Operand *Source0, 1843 Operand *Source1) { 1844 return new (Func->allocate<InstX86ImulImm>()) 1845 InstX86ImulImm(Func, Dest, Source0, Source1); 1846 } 1847 1848 void emit(const Cfg *Func) const override; 1849 void emitIAS(const Cfg *Func) const override; 1850 1851 private: InstX86ImulImm(Cfg * Func,Variable * Dest,Operand * Source0,Operand * Source1)1852 InstX86ImulImm(Cfg *Func, Variable *Dest, Operand *Source0, Operand *Source1) 1853 : InstX86BaseThreeAddressop<InstX86Base::ImulImm>(Func, Dest, Source0, 1854 Source1) {} 1855 }; 1856 1857 class InstX86Mulps 1858 : public InstX86BaseBinopXmm<InstX86Base::Mulps, true, 1859 InstX86Base::SseSuffix::Packed> { 1860 public: create(Cfg * Func,Variable * Dest,Operand * Source)1861 static InstX86Mulps *create(Cfg *Func, Variable *Dest, Operand *Source) { 1862 return new (Func->allocate<InstX86Mulps>()) 1863 InstX86Mulps(Func, Dest, Source); 1864 } 1865 1866 private: InstX86Mulps(Cfg * Func,Variable * Dest,Operand * Source)1867 InstX86Mulps(Cfg *Func, Variable *Dest, Operand *Source) 1868 : InstX86BaseBinopXmm<InstX86Base::Mulps, true, 1869 InstX86Base::SseSuffix::Packed>(Func, Dest, 1870 Source) {} 1871 }; 1872 1873 class InstX86Mulss 1874 : public InstX86BaseBinopXmm<InstX86Base::Mulss, false, 1875 InstX86Base::SseSuffix::Scalar> { 1876 public: create(Cfg * Func,Variable * Dest,Operand * Source)1877 static InstX86Mulss *create(Cfg *Func, Variable *Dest, Operand *Source) { 1878 return new (Func->allocate<InstX86Mulss>()) 1879 InstX86Mulss(Func, Dest, Source); 1880 } 1881 1882 private: InstX86Mulss(Cfg * Func,Variable * Dest,Operand * Source)1883 InstX86Mulss(Cfg *Func, Variable *Dest, Operand *Source) 1884 : InstX86BaseBinopXmm<InstX86Base::Mulss, false, 1885 InstX86Base::SseSuffix::Scalar>(Func, Dest, 1886 Source) {} 1887 }; 1888 1889 class InstX86Pmull 1890 : public InstX86BaseBinopXmm<InstX86Base::Pmull, true, 1891 InstX86Base::SseSuffix::Integral> { 1892 public: create(Cfg * Func,Variable * Dest,Operand * Source)1893 static InstX86Pmull *create(Cfg *Func, Variable *Dest, Operand *Source) { 1894 bool TypesAreValid = 1895 Dest->getType() == IceType_v4i32 || Dest->getType() == IceType_v8i16; 1896 bool InstructionSetIsValid = 1897 Dest->getType() == IceType_v8i16 || getInstructionSet(Func) >= SSE4_1; 1898 (void)TypesAreValid; 1899 (void)InstructionSetIsValid; 1900 assert(TypesAreValid); 1901 assert(InstructionSetIsValid); 1902 return new (Func->allocate<InstX86Pmull>()) 1903 InstX86Pmull(Func, Dest, Source); 1904 } 1905 1906 private: InstX86Pmull(Cfg * Func,Variable * Dest,Operand * Source)1907 InstX86Pmull(Cfg *Func, Variable *Dest, Operand *Source) 1908 : InstX86BaseBinopXmm<InstX86Base::Pmull, true, 1909 InstX86Base::SseSuffix::Integral>(Func, Dest, 1910 Source) {} 1911 }; 1912 1913 class InstX86Pmulhw : public InstX86BaseBinopXmm<InstX86Base::Pmulhw, false, 1914 InstX86Base::SseSuffix::None> { 1915 public: create(Cfg * Func,Variable * Dest,Operand * Source)1916 static InstX86Pmulhw *create(Cfg *Func, Variable *Dest, Operand *Source) { 1917 assert(Dest->getType() == IceType_v8i16 && 1918 Source->getType() == IceType_v8i16); 1919 return new (Func->allocate<InstX86Pmulhw>()) 1920 InstX86Pmulhw(Func, Dest, Source); 1921 } 1922 1923 private: InstX86Pmulhw(Cfg * Func,Variable * Dest,Operand * Source)1924 InstX86Pmulhw(Cfg *Func, Variable *Dest, Operand *Source) 1925 : InstX86BaseBinopXmm<InstX86Base::Pmulhw, false, 1926 InstX86Base::SseSuffix::None>(Func, Dest, Source) {} 1927 }; 1928 1929 class InstX86Pmulhuw 1930 : public InstX86BaseBinopXmm<InstX86Base::Pmulhuw, false, 1931 InstX86Base::SseSuffix::None> { 1932 public: create(Cfg * Func,Variable * Dest,Operand * Source)1933 static InstX86Pmulhuw *create(Cfg *Func, Variable *Dest, Operand *Source) { 1934 assert(Dest->getType() == IceType_v8i16 && 1935 Source->getType() == IceType_v8i16); 1936 return new (Func->allocate<InstX86Pmulhuw>()) 1937 InstX86Pmulhuw(Func, Dest, Source); 1938 } 1939 1940 private: InstX86Pmulhuw(Cfg * Func,Variable * Dest,Operand * Source)1941 InstX86Pmulhuw(Cfg *Func, Variable *Dest, Operand *Source) 1942 : InstX86BaseBinopXmm<InstX86Base::Pmulhuw, false, 1943 InstX86Base::SseSuffix::None>(Func, Dest, Source) {} 1944 }; 1945 1946 class InstX86Pmaddwd 1947 : public InstX86BaseBinopXmm<InstX86Base::Pmaddwd, false, 1948 InstX86Base::SseSuffix::None> { 1949 public: create(Cfg * Func,Variable * Dest,Operand * Source)1950 static InstX86Pmaddwd *create(Cfg *Func, Variable *Dest, Operand *Source) { 1951 assert(Dest->getType() == IceType_v8i16 && 1952 Source->getType() == IceType_v8i16); 1953 return new (Func->allocate<InstX86Pmaddwd>()) 1954 InstX86Pmaddwd(Func, Dest, Source); 1955 } 1956 1957 private: InstX86Pmaddwd(Cfg * Func,Variable * Dest,Operand * Source)1958 InstX86Pmaddwd(Cfg *Func, Variable *Dest, Operand *Source) 1959 : InstX86BaseBinopXmm<InstX86Base::Pmaddwd, false, 1960 InstX86Base::SseSuffix::None>(Func, Dest, Source) {} 1961 }; 1962 1963 class InstX86Pmuludq 1964 : public InstX86BaseBinopXmm<InstX86Base::Pmuludq, false, 1965 InstX86Base::SseSuffix::None> { 1966 public: create(Cfg * Func,Variable * Dest,Operand * Source)1967 static InstX86Pmuludq *create(Cfg *Func, Variable *Dest, Operand *Source) { 1968 assert(Dest->getType() == IceType_v4i32 && 1969 Source->getType() == IceType_v4i32); 1970 return new (Func->allocate<InstX86Pmuludq>()) 1971 InstX86Pmuludq(Func, Dest, Source); 1972 } 1973 1974 private: InstX86Pmuludq(Cfg * Func,Variable * Dest,Operand * Source)1975 InstX86Pmuludq(Cfg *Func, Variable *Dest, Operand *Source) 1976 : InstX86BaseBinopXmm<InstX86Base::Pmuludq, false, 1977 InstX86Base::SseSuffix::None>(Func, Dest, Source) {} 1978 }; 1979 1980 class InstX86Divps 1981 : public InstX86BaseBinopXmm<InstX86Base::Divps, true, 1982 InstX86Base::SseSuffix::Packed> { 1983 public: create(Cfg * Func,Variable * Dest,Operand * Source)1984 static InstX86Divps *create(Cfg *Func, Variable *Dest, Operand *Source) { 1985 return new (Func->allocate<InstX86Divps>()) 1986 InstX86Divps(Func, Dest, Source); 1987 } 1988 1989 private: InstX86Divps(Cfg * Func,Variable * Dest,Operand * Source)1990 InstX86Divps(Cfg *Func, Variable *Dest, Operand *Source) 1991 : InstX86BaseBinopXmm<InstX86Base::Divps, true, 1992 InstX86Base::SseSuffix::Packed>(Func, Dest, 1993 Source) {} 1994 }; 1995 1996 class InstX86Divss 1997 : public InstX86BaseBinopXmm<InstX86Base::Divss, false, 1998 InstX86Base::SseSuffix::Scalar> { 1999 public: create(Cfg * Func,Variable * Dest,Operand * Source)2000 static InstX86Divss *create(Cfg *Func, Variable *Dest, Operand *Source) { 2001 return new (Func->allocate<InstX86Divss>()) 2002 InstX86Divss(Func, Dest, Source); 2003 } 2004 2005 private: InstX86Divss(Cfg * Func,Variable * Dest,Operand * Source)2006 InstX86Divss(Cfg *Func, Variable *Dest, Operand *Source) 2007 : InstX86BaseBinopXmm<InstX86Base::Divss, false, 2008 InstX86Base::SseSuffix::Scalar>(Func, Dest, 2009 Source) {} 2010 }; 2011 2012 class InstX86Rol : public InstX86BaseBinopGPRShift<InstX86Base::Rol> { 2013 public: create(Cfg * Func,Variable * Dest,Operand * Source)2014 static InstX86Rol *create(Cfg *Func, Variable *Dest, Operand *Source) { 2015 return new (Func->allocate<InstX86Rol>()) InstX86Rol(Func, Dest, Source); 2016 } 2017 2018 private: InstX86Rol(Cfg * Func,Variable * Dest,Operand * Source)2019 InstX86Rol(Cfg *Func, Variable *Dest, Operand *Source) 2020 : InstX86BaseBinopGPRShift<InstX86Base::Rol>(Func, Dest, Source) {} 2021 }; 2022 2023 class InstX86Shl : public InstX86BaseBinopGPRShift<InstX86Base::Shl> { 2024 public: create(Cfg * Func,Variable * Dest,Operand * Source)2025 static InstX86Shl *create(Cfg *Func, Variable *Dest, Operand *Source) { 2026 return new (Func->allocate<InstX86Shl>()) InstX86Shl(Func, Dest, Source); 2027 } 2028 2029 private: InstX86Shl(Cfg * Func,Variable * Dest,Operand * Source)2030 InstX86Shl(Cfg *Func, Variable *Dest, Operand *Source) 2031 : InstX86BaseBinopGPRShift<InstX86Base::Shl>(Func, Dest, Source) {} 2032 }; 2033 2034 class InstX86Psll : public InstX86BaseBinopXmmShift<InstX86Base::Psll> { 2035 public: create(Cfg * Func,Variable * Dest,Operand * Source)2036 static InstX86Psll *create(Cfg *Func, Variable *Dest, Operand *Source) { 2037 assert(Dest->getType() == IceType_v8i16 || 2038 Dest->getType() == IceType_v8i1 || 2039 Dest->getType() == IceType_v4i32 || Dest->getType() == IceType_v4i1); 2040 return new (Func->allocate<InstX86Psll>()) InstX86Psll(Func, Dest, Source); 2041 } 2042 2043 private: InstX86Psll(Cfg * Func,Variable * Dest,Operand * Source)2044 InstX86Psll(Cfg *Func, Variable *Dest, Operand *Source) 2045 : InstX86BaseBinopXmmShift<InstX86Base::Psll>(Func, Dest, Source) {} 2046 }; 2047 2048 class InstX86Psrl : public InstX86BaseBinopXmmShift<InstX86Base::Psrl, true> { 2049 public: create(Cfg * Func,Variable * Dest,Operand * Source)2050 static InstX86Psrl *create(Cfg *Func, Variable *Dest, Operand *Source) { 2051 return new (Func->allocate<InstX86Psrl>()) InstX86Psrl(Func, Dest, Source); 2052 } 2053 2054 private: InstX86Psrl(Cfg * Func,Variable * Dest,Operand * Source)2055 InstX86Psrl(Cfg *Func, Variable *Dest, Operand *Source) 2056 : InstX86BaseBinopXmmShift<InstX86Base::Psrl, true>(Func, Dest, Source) {} 2057 }; 2058 2059 class InstX86Shr : public InstX86BaseBinopGPRShift<InstX86Base::Shr> { 2060 public: create(Cfg * Func,Variable * Dest,Operand * Source)2061 static InstX86Shr *create(Cfg *Func, Variable *Dest, Operand *Source) { 2062 return new (Func->allocate<InstX86Shr>()) InstX86Shr(Func, Dest, Source); 2063 } 2064 2065 private: InstX86Shr(Cfg * Func,Variable * Dest,Operand * Source)2066 InstX86Shr(Cfg *Func, Variable *Dest, Operand *Source) 2067 : InstX86BaseBinopGPRShift<InstX86Base::Shr>(Func, Dest, Source) {} 2068 }; 2069 2070 class InstX86Sar : public InstX86BaseBinopGPRShift<InstX86Base::Sar> { 2071 public: create(Cfg * Func,Variable * Dest,Operand * Source)2072 static InstX86Sar *create(Cfg *Func, Variable *Dest, Operand *Source) { 2073 return new (Func->allocate<InstX86Sar>()) InstX86Sar(Func, Dest, Source); 2074 } 2075 2076 private: InstX86Sar(Cfg * Func,Variable * Dest,Operand * Source)2077 InstX86Sar(Cfg *Func, Variable *Dest, Operand *Source) 2078 : InstX86BaseBinopGPRShift<InstX86Base::Sar>(Func, Dest, Source) {} 2079 }; 2080 2081 class InstX86Psra : public InstX86BaseBinopXmmShift<InstX86Base::Psra> { 2082 public: create(Cfg * Func,Variable * Dest,Operand * Source)2083 static InstX86Psra *create(Cfg *Func, Variable *Dest, Operand *Source) { 2084 assert(Dest->getType() == IceType_v8i16 || 2085 Dest->getType() == IceType_v8i1 || 2086 Dest->getType() == IceType_v4i32 || Dest->getType() == IceType_v4i1); 2087 return new (Func->allocate<InstX86Psra>()) InstX86Psra(Func, Dest, Source); 2088 } 2089 2090 private: InstX86Psra(Cfg * Func,Variable * Dest,Operand * Source)2091 InstX86Psra(Cfg *Func, Variable *Dest, Operand *Source) 2092 : InstX86BaseBinopXmmShift<InstX86Base::Psra>(Func, Dest, Source) {} 2093 }; 2094 2095 class InstX86Pcmpeq 2096 : public InstX86BaseBinopXmm<InstX86Base::Pcmpeq, true, 2097 InstX86Base::SseSuffix::Integral> { 2098 public: 2099 static InstX86Pcmpeq *create(Cfg *Func, Variable *Dest, Operand *Source, 2100 Type ArithmeticTypeOverride = IceType_void) { 2101 const Type Ty = ArithmeticTypeOverride == IceType_void 2102 ? Dest->getType() 2103 : ArithmeticTypeOverride; 2104 (void)Ty; 2105 assert((Ty != IceType_f64 && Ty != IceType_i64) || 2106 getInstructionSet(Func) >= SSE4_1); 2107 return new (Func->allocate<InstX86Pcmpeq>()) 2108 InstX86Pcmpeq(Func, Dest, Source, ArithmeticTypeOverride); 2109 } 2110 2111 private: InstX86Pcmpeq(Cfg * Func,Variable * Dest,Operand * Source,Type ArithmeticTypeOverride)2112 InstX86Pcmpeq(Cfg *Func, Variable *Dest, Operand *Source, 2113 Type ArithmeticTypeOverride) 2114 : InstX86BaseBinopXmm<InstX86Base::Pcmpeq, true, 2115 InstX86Base::SseSuffix::Integral>( 2116 Func, Dest, Source, ArithmeticTypeOverride) {} 2117 }; 2118 2119 class InstX86Pcmpgt 2120 : public InstX86BaseBinopXmm<InstX86Base::Pcmpgt, true, 2121 InstX86Base::SseSuffix::Integral> { 2122 public: create(Cfg * Func,Variable * Dest,Operand * Source)2123 static InstX86Pcmpgt *create(Cfg *Func, Variable *Dest, Operand *Source) { 2124 assert(Dest->getType() != IceType_f64 || getInstructionSet(Func) >= SSE4_1); 2125 return new (Func->allocate<InstX86Pcmpgt>()) 2126 InstX86Pcmpgt(Func, Dest, Source); 2127 } 2128 2129 private: InstX86Pcmpgt(Cfg * Func,Variable * Dest,Operand * Source)2130 InstX86Pcmpgt(Cfg *Func, Variable *Dest, Operand *Source) 2131 : InstX86BaseBinopXmm<InstX86Base::Pcmpgt, true, 2132 InstX86Base::SseSuffix::Integral>(Func, Dest, 2133 Source) {} 2134 }; 2135 2136 /// movss is only a binary operation when the source and dest operands are 2137 /// both registers (the high bits of dest are left untouched). In other cases, 2138 /// it behaves like a copy (mov-like) operation (and the high bits of dest are 2139 /// cleared). InstX86Movss will assert that both its source and dest operands 2140 /// are registers, so the lowering code should use _mov instead of _movss in 2141 /// cases where a copy operation is intended. 2142 class InstX86MovssRegs 2143 : public InstX86BaseBinopXmm<InstX86Base::MovssRegs, false, 2144 InstX86Base::SseSuffix::None> { 2145 public: create(Cfg * Func,Variable * Dest,Operand * Source)2146 static InstX86MovssRegs *create(Cfg *Func, Variable *Dest, Operand *Source) { 2147 return new (Func->allocate<InstX86MovssRegs>()) 2148 InstX86MovssRegs(Func, Dest, Source); 2149 } 2150 2151 void emitIAS(const Cfg *Func) const override; 2152 2153 private: InstX86MovssRegs(Cfg * Func,Variable * Dest,Operand * Source)2154 InstX86MovssRegs(Cfg *Func, Variable *Dest, Operand *Source) 2155 : InstX86BaseBinopXmm<InstX86Base::MovssRegs, false, 2156 InstX86Base::SseSuffix::None>(Func, Dest, Source) {} 2157 }; 2158 2159 class InstX86Idiv : public InstX86BaseTernop<InstX86Base::Idiv> { 2160 public: create(Cfg * Func,Variable * Dest,Operand * Source1,Operand * Source2)2161 static InstX86Idiv *create(Cfg *Func, Variable *Dest, Operand *Source1, 2162 Operand *Source2) { 2163 return new (Func->allocate<InstX86Idiv>()) 2164 InstX86Idiv(Func, Dest, Source1, Source2); 2165 } 2166 2167 void emit(const Cfg *Func) const override; 2168 void emitIAS(const Cfg *Func) const override; 2169 2170 private: InstX86Idiv(Cfg * Func,Variable * Dest,Operand * Source1,Operand * Source2)2171 InstX86Idiv(Cfg *Func, Variable *Dest, Operand *Source1, Operand *Source2) 2172 : InstX86BaseTernop<InstX86Base::Idiv>(Func, Dest, Source1, Source2) {} 2173 }; 2174 2175 class InstX86Div : public InstX86BaseTernop<InstX86Base::Div> { 2176 public: create(Cfg * Func,Variable * Dest,Operand * Source1,Operand * Source2)2177 static InstX86Div *create(Cfg *Func, Variable *Dest, Operand *Source1, 2178 Operand *Source2) { 2179 return new (Func->allocate<InstX86Div>()) 2180 InstX86Div(Func, Dest, Source1, Source2); 2181 } 2182 2183 void emit(const Cfg *Func) const override; 2184 void emitIAS(const Cfg *Func) const override; 2185 2186 private: InstX86Div(Cfg * Func,Variable * Dest,Operand * Source1,Operand * Source2)2187 InstX86Div(Cfg *Func, Variable *Dest, Operand *Source1, Operand *Source2) 2188 : InstX86BaseTernop<InstX86Base::Div>(Func, Dest, Source1, Source2) {} 2189 }; 2190 2191 class InstX86Insertps : public InstX86BaseTernop<InstX86Base::Insertps> { 2192 public: create(Cfg * Func,Variable * Dest,Operand * Source1,Operand * Source2)2193 static InstX86Insertps *create(Cfg *Func, Variable *Dest, Operand *Source1, 2194 Operand *Source2) { 2195 return new (Func->allocate<InstX86Insertps>()) 2196 InstX86Insertps(Func, Dest, Source1, Source2); 2197 } 2198 2199 void emitIAS(const Cfg *Func) const override; 2200 2201 private: InstX86Insertps(Cfg * Func,Variable * Dest,Operand * Source1,Operand * Source2)2202 InstX86Insertps(Cfg *Func, Variable *Dest, Operand *Source1, Operand *Source2) 2203 : InstX86BaseTernop<InstX86Base::Insertps>(Func, Dest, Source1, Source2) { 2204 } 2205 }; 2206 2207 class InstX86Pinsr : public InstX86BaseTernop<InstX86Base::Pinsr> { 2208 public: create(Cfg * Func,Variable * Dest,Operand * Source1,Operand * Source2)2209 static InstX86Pinsr *create(Cfg *Func, Variable *Dest, Operand *Source1, 2210 Operand *Source2) { 2211 // pinsrb and pinsrd are SSE4.1 instructions. 2212 assert(Dest->getType() == IceType_v8i16 || 2213 Dest->getType() == IceType_v8i1 || 2214 getInstructionSet(Func) >= SSE4_1); 2215 return new (Func->allocate<InstX86Pinsr>()) 2216 InstX86Pinsr(Func, Dest, Source1, Source2); 2217 } 2218 2219 void emit(const Cfg *Func) const override; 2220 void emitIAS(const Cfg *Func) const override; 2221 2222 private: InstX86Pinsr(Cfg * Func,Variable * Dest,Operand * Source1,Operand * Source2)2223 InstX86Pinsr(Cfg *Func, Variable *Dest, Operand *Source1, Operand *Source2) 2224 : InstX86BaseTernop<InstX86Base::Pinsr>(Func, Dest, Source1, Source2) {} 2225 }; 2226 2227 class InstX86Shufps : public InstX86BaseTernop<InstX86Base::Shufps> { 2228 public: create(Cfg * Func,Variable * Dest,Operand * Source1,Operand * Source2)2229 static InstX86Shufps *create(Cfg *Func, Variable *Dest, Operand *Source1, 2230 Operand *Source2) { 2231 return new (Func->allocate<InstX86Shufps>()) 2232 InstX86Shufps(Func, Dest, Source1, Source2); 2233 } 2234 2235 void emitIAS(const Cfg *Func) const override; 2236 2237 private: InstX86Shufps(Cfg * Func,Variable * Dest,Operand * Source1,Operand * Source2)2238 InstX86Shufps(Cfg *Func, Variable *Dest, Operand *Source1, Operand *Source2) 2239 : InstX86BaseTernop<InstX86Base::Shufps>(Func, Dest, Source1, Source2) {} 2240 }; 2241 2242 class InstX86Blendvps : public InstX86BaseTernop<InstX86Base::Blendvps> { 2243 public: create(Cfg * Func,Variable * Dest,Operand * Source1,Operand * Source2)2244 static InstX86Blendvps *create(Cfg *Func, Variable *Dest, Operand *Source1, 2245 Operand *Source2) { 2246 assert(getInstructionSet(Func) >= SSE4_1); 2247 return new (Func->allocate<InstX86Blendvps>()) 2248 InstX86Blendvps(Func, Dest, Source1, Source2); 2249 } 2250 2251 void emit(const Cfg *Func) const override; 2252 void emitIAS(const Cfg *Fund) const override; 2253 2254 private: InstX86Blendvps(Cfg * Func,Variable * Dest,Operand * Source1,Operand * Source2)2255 InstX86Blendvps(Cfg *Func, Variable *Dest, Operand *Source1, Operand *Source2) 2256 : InstX86BaseTernop<InstX86Base::Blendvps>(Func, Dest, Source1, Source2) { 2257 } 2258 }; 2259 2260 class InstX86Pblendvb : public InstX86BaseTernop<InstX86Base::Pblendvb> { 2261 public: create(Cfg * Func,Variable * Dest,Operand * Source1,Operand * Source2)2262 static InstX86Pblendvb *create(Cfg *Func, Variable *Dest, Operand *Source1, 2263 Operand *Source2) { 2264 assert(getInstructionSet(Func) >= SSE4_1); 2265 return new (Func->allocate<InstX86Pblendvb>()) 2266 InstX86Pblendvb(Func, Dest, Source1, Source2); 2267 } 2268 2269 void emit(const Cfg *Func) const override; 2270 void emitIAS(const Cfg *Func) const override; 2271 2272 private: InstX86Pblendvb(Cfg * Func,Variable * Dest,Operand * Source1,Operand * Source2)2273 InstX86Pblendvb(Cfg *Func, Variable *Dest, Operand *Source1, Operand *Source2) 2274 : InstX86BaseTernop<InstX86Base::Pblendvb>(Func, Dest, Source1, Source2) { 2275 } 2276 }; 2277 2278 class InstX86Pextr : public InstX86BaseThreeAddressop<InstX86Base::Pextr> { 2279 public: create(Cfg * Func,Variable * Dest,Operand * Source0,Operand * Source1)2280 static InstX86Pextr *create(Cfg *Func, Variable *Dest, Operand *Source0, 2281 Operand *Source1) { 2282 assert(Source0->getType() == IceType_v8i16 || 2283 Source0->getType() == IceType_v8i1 || 2284 getInstructionSet(Func) >= SSE4_1); 2285 return new (Func->allocate<InstX86Pextr>()) 2286 InstX86Pextr(Func, Dest, Source0, Source1); 2287 } 2288 2289 void emit(const Cfg *Func) const override; 2290 void emitIAS(const Cfg *Func) const override; 2291 2292 private: InstX86Pextr(Cfg * Func,Variable * Dest,Operand * Source0,Operand * Source1)2293 InstX86Pextr(Cfg *Func, Variable *Dest, Operand *Source0, Operand *Source1) 2294 : InstX86BaseThreeAddressop<InstX86Base::Pextr>(Func, Dest, Source0, 2295 Source1) {} 2296 }; 2297 2298 class InstX86Pshufd : public InstX86BaseThreeAddressop<InstX86Base::Pshufd> { 2299 public: create(Cfg * Func,Variable * Dest,Operand * Source0,Operand * Source1)2300 static InstX86Pshufd *create(Cfg *Func, Variable *Dest, Operand *Source0, 2301 Operand *Source1) { 2302 return new (Func->allocate<InstX86Pshufd>()) 2303 InstX86Pshufd(Func, Dest, Source0, Source1); 2304 } 2305 2306 void emitIAS(const Cfg *Func) const override; 2307 2308 private: InstX86Pshufd(Cfg * Func,Variable * Dest,Operand * Source0,Operand * Source1)2309 InstX86Pshufd(Cfg *Func, Variable *Dest, Operand *Source0, Operand *Source1) 2310 : InstX86BaseThreeAddressop<InstX86Base::Pshufd>(Func, Dest, Source0, 2311 Source1) {} 2312 }; 2313 2314 /// Base class for a lockable x86-64 instruction (emits a locked prefix). 2315 class InstX86BaseLockable : public InstX86Base { 2316 InstX86BaseLockable() = delete; 2317 InstX86BaseLockable(const InstX86BaseLockable &) = delete; 2318 InstX86BaseLockable &operator=(const InstX86BaseLockable &) = delete; 2319 2320 protected: 2321 bool Locked; 2322 InstX86BaseLockable(Cfg * Func,typename InstX86Base::InstKindX86 Kind,SizeT Maxsrcs,Variable * Dest,bool Locked)2323 InstX86BaseLockable(Cfg *Func, typename InstX86Base::InstKindX86 Kind, 2324 SizeT Maxsrcs, Variable *Dest, bool Locked) 2325 : InstX86Base(Func, Kind, Maxsrcs, Dest), Locked(Locked) { 2326 // Assume that such instructions are used for Atomics and be careful with 2327 // optimizations. 2328 this->HasSideEffects = Locked; 2329 } 2330 }; 2331 2332 /// Mul instruction - unsigned multiply. 2333 class InstX86Mul final : public InstX86Base { 2334 InstX86Mul() = delete; 2335 InstX86Mul(const InstX86Mul &) = delete; 2336 InstX86Mul &operator=(const InstX86Mul &) = delete; 2337 2338 public: create(Cfg * Func,Variable * Dest,Variable * Source1,Operand * Source2)2339 static InstX86Mul *create(Cfg *Func, Variable *Dest, Variable *Source1, 2340 Operand *Source2) { 2341 return new (Func->allocate<InstX86Mul>()) 2342 InstX86Mul(Func, Dest, Source1, Source2); 2343 } 2344 void emit(const Cfg *Func) const override; 2345 void emitIAS(const Cfg *Func) const override; 2346 void dump(const Cfg *Func) const override; classof(const Inst * Instr)2347 static bool classof(const Inst *Instr) { 2348 return InstX86Base::isClassof(Instr, InstX86Base::Mul); 2349 } 2350 2351 private: 2352 InstX86Mul(Cfg *Func, Variable *Dest, Variable *Source1, Operand *Source2); 2353 }; 2354 2355 /// Shld instruction - shift across a pair of operands. 2356 class InstX86Shld final : public InstX86Base { 2357 InstX86Shld() = delete; 2358 InstX86Shld(const InstX86Shld &) = delete; 2359 InstX86Shld &operator=(const InstX86Shld &) = delete; 2360 2361 public: create(Cfg * Func,Variable * Dest,Variable * Source1,Operand * Source2)2362 static InstX86Shld *create(Cfg *Func, Variable *Dest, Variable *Source1, 2363 Operand *Source2) { 2364 return new (Func->allocate<InstX86Shld>()) 2365 InstX86Shld(Func, Dest, Source1, Source2); 2366 } 2367 void emit(const Cfg *Func) const override; 2368 void emitIAS(const Cfg *Func) const override; 2369 void dump(const Cfg *Func) const override; classof(const Inst * Instr)2370 static bool classof(const Inst *Instr) { 2371 return InstX86Base::isClassof(Instr, InstX86Base::Shld); 2372 } 2373 2374 private: 2375 InstX86Shld(Cfg *Func, Variable *Dest, Variable *Source1, Operand *Source2); 2376 }; 2377 2378 /// Shrd instruction - shift across a pair of operands. 2379 class InstX86Shrd final : public InstX86Base { 2380 InstX86Shrd() = delete; 2381 InstX86Shrd(const InstX86Shrd &) = delete; 2382 InstX86Shrd &operator=(const InstX86Shrd &) = delete; 2383 2384 public: create(Cfg * Func,Variable * Dest,Variable * Source1,Operand * Source2)2385 static InstX86Shrd *create(Cfg *Func, Variable *Dest, Variable *Source1, 2386 Operand *Source2) { 2387 return new (Func->allocate<InstX86Shrd>()) 2388 InstX86Shrd(Func, Dest, Source1, Source2); 2389 } 2390 void emit(const Cfg *Func) const override; 2391 void emitIAS(const Cfg *Func) const override; 2392 void dump(const Cfg *Func) const override; classof(const Inst * Instr)2393 static bool classof(const Inst *Instr) { 2394 return InstX86Base::isClassof(Instr, InstX86Base::Shrd); 2395 } 2396 2397 private: 2398 InstX86Shrd(Cfg *Func, Variable *Dest, Variable *Source1, Operand *Source2); 2399 }; 2400 2401 /// Conditional move instruction. 2402 class InstX86Cmov final : public InstX86Base { 2403 InstX86Cmov() = delete; 2404 InstX86Cmov(const InstX86Cmov &) = delete; 2405 InstX86Cmov &operator=(const InstX86Cmov &) = delete; 2406 2407 public: create(Cfg * Func,Variable * Dest,Operand * Source,BrCond Cond)2408 static InstX86Cmov *create(Cfg *Func, Variable *Dest, Operand *Source, 2409 BrCond Cond) { 2410 return new (Func->allocate<InstX86Cmov>()) 2411 InstX86Cmov(Func, Dest, Source, Cond); 2412 } 2413 void emit(const Cfg *Func) const override; 2414 void emitIAS(const Cfg *Func) const override; 2415 void dump(const Cfg *Func) const override; classof(const Inst * Instr)2416 static bool classof(const Inst *Instr) { 2417 return InstX86Base::isClassof(Instr, InstX86Base::Cmov); 2418 } 2419 2420 private: 2421 InstX86Cmov(Cfg *Func, Variable *Dest, Operand *Source, BrCond Cond); 2422 2423 BrCond Condition; 2424 }; 2425 2426 /// Cmpps instruction - compare packed singled-precision floating point values 2427 class InstX86Cmpps final : public InstX86Base { 2428 InstX86Cmpps() = delete; 2429 InstX86Cmpps(const InstX86Cmpps &) = delete; 2430 InstX86Cmpps &operator=(const InstX86Cmpps &) = delete; 2431 2432 public: create(Cfg * Func,Variable * Dest,Operand * Source,CmppsCond Condition)2433 static InstX86Cmpps *create(Cfg *Func, Variable *Dest, Operand *Source, 2434 CmppsCond Condition) { 2435 return new (Func->allocate<InstX86Cmpps>()) 2436 InstX86Cmpps(Func, Dest, Source, Condition); 2437 } 2438 void emit(const Cfg *Func) const override; 2439 void emitIAS(const Cfg *Func) const override; 2440 void dump(const Cfg *Func) const override; classof(const Inst * Instr)2441 static bool classof(const Inst *Instr) { 2442 return InstX86Base::isClassof(Instr, InstX86Base::Cmpps); 2443 } 2444 2445 private: 2446 InstX86Cmpps(Cfg *Func, Variable *Dest, Operand *Source, CmppsCond Cond); 2447 2448 CmppsCond Condition; 2449 }; 2450 2451 /// Cmpxchg instruction - cmpxchg <dest>, <desired> will compare if <dest> 2452 /// equals eax. If so, the ZF is set and <desired> is stored in <dest>. If 2453 /// not, ZF is cleared and <dest> is copied to eax (or subregister). <dest> 2454 /// can be a register or memory, while <desired> must be a register. It is 2455 /// the user's responsibility to mark eax with a FakeDef. 2456 class InstX86Cmpxchg final : public InstX86BaseLockable { 2457 InstX86Cmpxchg() = delete; 2458 InstX86Cmpxchg(const InstX86Cmpxchg &) = delete; 2459 InstX86Cmpxchg &operator=(const InstX86Cmpxchg &) = delete; 2460 2461 public: create(Cfg * Func,Operand * DestOrAddr,Variable * Eax,Variable * Desired,bool Locked)2462 static InstX86Cmpxchg *create(Cfg *Func, Operand *DestOrAddr, Variable *Eax, 2463 Variable *Desired, bool Locked) { 2464 return new (Func->allocate<InstX86Cmpxchg>()) 2465 InstX86Cmpxchg(Func, DestOrAddr, Eax, Desired, Locked); 2466 } 2467 void emit(const Cfg *Func) const override; 2468 void emitIAS(const Cfg *Func) const override; 2469 void dump(const Cfg *Func) const override; classof(const Inst * Instr)2470 static bool classof(const Inst *Instr) { 2471 return InstX86Base::isClassof(Instr, InstX86Base::Cmpxchg); 2472 } 2473 2474 private: 2475 InstX86Cmpxchg(Cfg *Func, Operand *DestOrAddr, Variable *Eax, 2476 Variable *Desired, bool Locked); 2477 }; 2478 2479 /// Cmpxchg8b instruction - cmpxchg8b <m64> will compare if <m64> equals 2480 /// edx:eax. If so, the ZF is set and ecx:ebx is stored in <m64>. If not, ZF 2481 /// is cleared and <m64> is copied to edx:eax. The caller is responsible for 2482 /// inserting FakeDefs to mark edx and eax as modified. <m64> must be a memory 2483 /// operand. 2484 class InstX86Cmpxchg8b final : public InstX86BaseLockable { 2485 InstX86Cmpxchg8b() = delete; 2486 InstX86Cmpxchg8b(const InstX86Cmpxchg8b &) = delete; 2487 InstX86Cmpxchg8b &operator=(const InstX86Cmpxchg8b &) = delete; 2488 2489 public: create(Cfg * Func,X86OperandMem * Dest,Variable * Edx,Variable * Eax,Variable * Ecx,Variable * Ebx,bool Locked)2490 static InstX86Cmpxchg8b *create(Cfg *Func, X86OperandMem *Dest, Variable *Edx, 2491 Variable *Eax, Variable *Ecx, Variable *Ebx, 2492 bool Locked) { 2493 return new (Func->allocate<InstX86Cmpxchg8b>()) 2494 InstX86Cmpxchg8b(Func, Dest, Edx, Eax, Ecx, Ebx, Locked); 2495 } 2496 void emit(const Cfg *Func) const override; 2497 void emitIAS(const Cfg *Func) const override; 2498 void dump(const Cfg *Func) const override; classof(const Inst * Instr)2499 static bool classof(const Inst *Instr) { 2500 return InstX86Base::isClassof(Instr, InstX86Base::Cmpxchg8b); 2501 } 2502 2503 private: 2504 InstX86Cmpxchg8b(Cfg *Func, X86OperandMem *Dest, Variable *Edx, Variable *Eax, 2505 Variable *Ecx, Variable *Ebx, bool Locked); 2506 }; 2507 2508 /// Cvt instruction - wrapper for cvtsX2sY where X and Y are in {s,d,i} as 2509 /// appropriate. s=float, d=double, i=int. X and Y are determined from 2510 /// dest/src types. Sign and zero extension on the integer operand needs to be 2511 /// done separately. 2512 class InstX86Cvt final : public InstX86Base { 2513 InstX86Cvt() = delete; 2514 InstX86Cvt(const InstX86Cvt &) = delete; 2515 InstX86Cvt &operator=(const InstX86Cvt &) = delete; 2516 2517 public: 2518 enum CvtVariant { Si2ss, Tss2si, Ss2si, Float2float, Dq2ps, Tps2dq, Ps2dq }; create(Cfg * Func,Variable * Dest,Operand * Source,CvtVariant Variant)2519 static InstX86Cvt *create(Cfg *Func, Variable *Dest, Operand *Source, 2520 CvtVariant Variant) { 2521 return new (Func->allocate<InstX86Cvt>()) 2522 InstX86Cvt(Func, Dest, Source, Variant); 2523 } 2524 void emit(const Cfg *Func) const override; 2525 void emitIAS(const Cfg *Func) const override; 2526 void dump(const Cfg *Func) const override; classof(const Inst * Instr)2527 static bool classof(const Inst *Instr) { 2528 return InstX86Base::isClassof(Instr, InstX86Base::Cvt); 2529 } isTruncating()2530 bool isTruncating() const { return Variant == Tss2si || Variant == Tps2dq; } 2531 2532 private: 2533 CvtVariant Variant; 2534 InstX86Cvt(Cfg *Func, Variable *Dest, Operand *Source, CvtVariant Variant); 2535 }; 2536 2537 /// Round instruction 2538 class InstX86Round final 2539 : public InstX86BaseThreeAddressop<InstX86Base::Round> { 2540 public: create(Cfg * Func,Variable * Dest,Operand * Source,Operand * Imm)2541 static InstX86Round *create(Cfg *Func, Variable *Dest, Operand *Source, 2542 Operand *Imm) { 2543 return new (Func->allocate<InstX86Round>()) 2544 InstX86Round(Func, Dest, Source, Imm); 2545 } 2546 2547 void emit(const Cfg *Func) const override; 2548 void emitIAS(const Cfg *Func) const override; 2549 2550 private: InstX86Round(Cfg * Func,Variable * Dest,Operand * Source,Operand * Imm)2551 InstX86Round(Cfg *Func, Variable *Dest, Operand *Source, Operand *Imm) 2552 : InstX86BaseThreeAddressop<InstX86Base::Round>(Func, Dest, Source, Imm) { 2553 } 2554 }; 2555 2556 /// cmp - Integer compare instruction. 2557 class InstX86Icmp final : public InstX86Base { 2558 InstX86Icmp() = delete; 2559 InstX86Icmp(const InstX86Icmp &) = delete; 2560 InstX86Icmp &operator=(const InstX86Icmp &) = delete; 2561 2562 public: create(Cfg * Func,Operand * Src1,Operand * Src2)2563 static InstX86Icmp *create(Cfg *Func, Operand *Src1, Operand *Src2) { 2564 return new (Func->allocate<InstX86Icmp>()) InstX86Icmp(Func, Src1, Src2); 2565 } 2566 void emit(const Cfg *Func) const override; 2567 void emitIAS(const Cfg *Func) const override; 2568 void dump(const Cfg *Func) const override; classof(const Inst * Instr)2569 static bool classof(const Inst *Instr) { 2570 return InstX86Base::isClassof(Instr, InstX86Base::Icmp); 2571 } 2572 2573 private: 2574 InstX86Icmp(Cfg *Func, Operand *Src1, Operand *Src2); 2575 }; 2576 2577 /// ucomiss/ucomisd - floating-point compare instruction. 2578 class InstX86Ucomiss final : public InstX86Base { 2579 InstX86Ucomiss() = delete; 2580 InstX86Ucomiss(const InstX86Ucomiss &) = delete; 2581 InstX86Ucomiss &operator=(const InstX86Ucomiss &) = delete; 2582 2583 public: create(Cfg * Func,Operand * Src1,Operand * Src2)2584 static InstX86Ucomiss *create(Cfg *Func, Operand *Src1, Operand *Src2) { 2585 return new (Func->allocate<InstX86Ucomiss>()) 2586 InstX86Ucomiss(Func, Src1, Src2); 2587 } 2588 void emit(const Cfg *Func) const override; 2589 void emitIAS(const Cfg *Func) const override; 2590 void dump(const Cfg *Func) const override; classof(const Inst * Instr)2591 static bool classof(const Inst *Instr) { 2592 return InstX86Base::isClassof(Instr, InstX86Base::Ucomiss); 2593 } 2594 2595 private: 2596 InstX86Ucomiss(Cfg *Func, Operand *Src1, Operand *Src2); 2597 }; 2598 2599 /// UD2 instruction. 2600 class InstX86UD2 final : public InstX86Base { 2601 InstX86UD2() = delete; 2602 InstX86UD2(const InstX86UD2 &) = delete; 2603 InstX86UD2 &operator=(const InstX86UD2 &) = delete; 2604 2605 public: create(Cfg * Func)2606 static InstX86UD2 *create(Cfg *Func) { 2607 return new (Func->allocate<InstX86UD2>()) InstX86UD2(Func); 2608 } 2609 void emit(const Cfg *Func) const override; 2610 void emitIAS(const Cfg *Func) const override; 2611 void dump(const Cfg *Func) const override; classof(const Inst * Instr)2612 static bool classof(const Inst *Instr) { 2613 return InstX86Base::isClassof(Instr, InstX86Base::UD2); 2614 } 2615 2616 private: 2617 explicit InstX86UD2(Cfg *Func); 2618 }; 2619 2620 /// Int3 instruction. 2621 class InstX86Int3 final : public InstX86Base { 2622 InstX86Int3() = delete; 2623 InstX86Int3(const InstX86Int3 &) = delete; 2624 InstX86Int3 &operator=(const InstX86Int3 &) = delete; 2625 2626 public: create(Cfg * Func)2627 static InstX86Int3 *create(Cfg *Func) { 2628 return new (Func->allocate<InstX86Int3>()) InstX86Int3(Func); 2629 } 2630 void emit(const Cfg *Func) const override; 2631 void emitIAS(const Cfg *Func) const override; 2632 void dump(const Cfg *Func) const override; classof(const Inst * Instr)2633 static bool classof(const Inst *Instr) { 2634 return InstX86Base::isClassof(Instr, InstX86Base::Int3); 2635 } 2636 2637 private: 2638 explicit InstX86Int3(Cfg *Func); 2639 }; 2640 2641 /// Test instruction. 2642 class InstX86Test final : public InstX86Base { 2643 InstX86Test() = delete; 2644 InstX86Test(const InstX86Test &) = delete; 2645 InstX86Test &operator=(const InstX86Test &) = delete; 2646 2647 public: create(Cfg * Func,Operand * Source1,Operand * Source2)2648 static InstX86Test *create(Cfg *Func, Operand *Source1, Operand *Source2) { 2649 return new (Func->allocate<InstX86Test>()) 2650 InstX86Test(Func, Source1, Source2); 2651 } 2652 void emit(const Cfg *Func) const override; 2653 void emitIAS(const Cfg *Func) const override; 2654 void dump(const Cfg *Func) const override; classof(const Inst * Instr)2655 static bool classof(const Inst *Instr) { 2656 return InstX86Base::isClassof(Instr, InstX86Base::Test); 2657 } 2658 2659 private: 2660 InstX86Test(Cfg *Func, Operand *Source1, Operand *Source2); 2661 }; 2662 2663 /// Mfence instruction. 2664 class InstX86Mfence final : public InstX86Base { 2665 InstX86Mfence() = delete; 2666 InstX86Mfence(const InstX86Mfence &) = delete; 2667 InstX86Mfence &operator=(const InstX86Mfence &) = delete; 2668 2669 public: create(Cfg * Func)2670 static InstX86Mfence *create(Cfg *Func) { 2671 return new (Func->allocate<InstX86Mfence>()) InstX86Mfence(Func); 2672 } 2673 void emit(const Cfg *Func) const override; 2674 void emitIAS(const Cfg *Func) const override; 2675 void dump(const Cfg *Func) const override; classof(const Inst * Instr)2676 static bool classof(const Inst *Instr) { 2677 return InstX86Base::isClassof(Instr, InstX86Base::Mfence); 2678 } 2679 2680 private: 2681 explicit InstX86Mfence(Cfg *Func); 2682 }; 2683 2684 /// This is essentially a "mov" instruction with anX86OperandMem operand 2685 /// instead of Variable as the destination. It's important for liveness that 2686 /// there is no Dest operand. 2687 class InstX86Store final : public InstX86Base { 2688 InstX86Store() = delete; 2689 InstX86Store(const InstX86Store &) = delete; 2690 InstX86Store &operator=(const InstX86Store &) = delete; 2691 2692 public: create(Cfg * Func,Operand * Value,X86Operand * Mem)2693 static InstX86Store *create(Cfg *Func, Operand *Value, X86Operand *Mem) { 2694 return new (Func->allocate<InstX86Store>()) InstX86Store(Func, Value, Mem); 2695 } 2696 void emit(const Cfg *Func) const override; 2697 void emitIAS(const Cfg *Func) const override; 2698 void dump(const Cfg *Func) const override; classof(const Inst * Instr)2699 static bool classof(const Inst *Instr) { 2700 return InstX86Base::isClassof(Instr, InstX86Base::Store); 2701 } 2702 2703 private: 2704 InstX86Store(Cfg *Func, Operand *Value, X86Operand *Mem); 2705 }; 2706 2707 /// This is essentially a vector "mov" instruction with an X86OperandMem operand 2708 /// instead of Variable as the destination. It's important for liveness that 2709 /// there is no Dest operand. The source must be an Xmm register, since Dest is 2710 /// mem. 2711 class InstX86StoreP final : public InstX86Base { 2712 InstX86StoreP() = delete; 2713 InstX86StoreP(const InstX86StoreP &) = delete; 2714 InstX86StoreP &operator=(const InstX86StoreP &) = delete; 2715 2716 public: create(Cfg * Func,Variable * Value,X86OperandMem * Mem)2717 static InstX86StoreP *create(Cfg *Func, Variable *Value, X86OperandMem *Mem) { 2718 return new (Func->allocate<InstX86StoreP>()) 2719 InstX86StoreP(Func, Value, Mem); 2720 } 2721 void emit(const Cfg *Func) const override; 2722 void emitIAS(const Cfg *Func) const override; 2723 void dump(const Cfg *Func) const override; classof(const Inst * Instr)2724 static bool classof(const Inst *Instr) { 2725 return InstX86Base::isClassof(Instr, InstX86Base::StoreP); 2726 } 2727 2728 private: 2729 InstX86StoreP(Cfg *Func, Variable *Value, X86OperandMem *Mem); 2730 }; 2731 2732 class InstX86StoreQ final : public InstX86Base { 2733 InstX86StoreQ() = delete; 2734 InstX86StoreQ(const InstX86StoreQ &) = delete; 2735 InstX86StoreQ &operator=(const InstX86StoreQ &) = delete; 2736 2737 public: create(Cfg * Func,Operand * Value,X86OperandMem * Mem)2738 static InstX86StoreQ *create(Cfg *Func, Operand *Value, X86OperandMem *Mem) { 2739 return new (Func->allocate<InstX86StoreQ>()) 2740 InstX86StoreQ(Func, Value, Mem); 2741 } 2742 void emit(const Cfg *Func) const override; 2743 void emitIAS(const Cfg *Func) const override; 2744 void dump(const Cfg *Func) const override; classof(const Inst * Instr)2745 static bool classof(const Inst *Instr) { 2746 return InstX86Base::isClassof(Instr, InstX86Base::StoreQ); 2747 } 2748 2749 private: 2750 InstX86StoreQ(Cfg *Func, Operand *Value, X86OperandMem *Mem); 2751 }; 2752 2753 class InstX86StoreD final : public InstX86Base { 2754 InstX86StoreD() = delete; 2755 InstX86StoreD(const InstX86StoreD &) = delete; 2756 InstX86StoreD &operator=(const InstX86StoreD &) = delete; 2757 2758 public: create(Cfg * Func,Operand * Value,X86OperandMem * Mem)2759 static InstX86StoreD *create(Cfg *Func, Operand *Value, X86OperandMem *Mem) { 2760 return new (Func->allocate<InstX86StoreD>()) 2761 InstX86StoreD(Func, Value, Mem); 2762 } 2763 void emit(const Cfg *Func) const override; 2764 void emitIAS(const Cfg *Func) const override; 2765 void dump(const Cfg *Func) const override; classof(const Inst * Instr)2766 static bool classof(const Inst *Instr) { 2767 return InstX86Base::isClassof(Instr, InstX86Base::StoreQ); 2768 } 2769 2770 private: 2771 InstX86StoreD(Cfg *Func, Operand *Value, X86OperandMem *Mem); 2772 }; 2773 2774 /// Nop instructions of varying length 2775 class InstX86Nop final : public InstX86Base { 2776 InstX86Nop() = delete; 2777 InstX86Nop(const InstX86Nop &) = delete; 2778 InstX86Nop &operator=(const InstX86Nop &) = delete; 2779 2780 public: 2781 // TODO: Replace with enum. 2782 using NopVariant = unsigned; 2783 create(Cfg * Func,NopVariant Variant)2784 static InstX86Nop *create(Cfg *Func, NopVariant Variant) { 2785 return new (Func->allocate<InstX86Nop>()) InstX86Nop(Func, Variant); 2786 } 2787 void emit(const Cfg *Func) const override; 2788 void emitIAS(const Cfg *Func) const override; 2789 void dump(const Cfg *Func) const override; classof(const Inst * Instr)2790 static bool classof(const Inst *Instr) { 2791 return InstX86Base::isClassof(Instr, InstX86Base::Nop); 2792 } 2793 2794 private: 2795 InstX86Nop(Cfg *Func, NopVariant Length); 2796 2797 NopVariant Variant; 2798 }; 2799 2800 class InstX86Pop final : public InstX86Base { 2801 InstX86Pop() = delete; 2802 InstX86Pop(const InstX86Pop &) = delete; 2803 InstX86Pop &operator=(const InstX86Pop &) = delete; 2804 2805 public: create(Cfg * Func,Variable * Dest)2806 static InstX86Pop *create(Cfg *Func, Variable *Dest) { 2807 return new (Func->allocate<InstX86Pop>()) InstX86Pop(Func, Dest); 2808 } 2809 void emit(const Cfg *Func) const override; 2810 void emitIAS(const Cfg *Func) const override; 2811 void dump(const Cfg *Func) const override; classof(const Inst * Instr)2812 static bool classof(const Inst *Instr) { 2813 return InstX86Base::isClassof(Instr, InstX86Base::Pop); 2814 } 2815 2816 private: 2817 InstX86Pop(Cfg *Func, Variable *Dest); 2818 }; 2819 2820 class InstX86Push final : public InstX86Base { 2821 InstX86Push() = delete; 2822 InstX86Push(const InstX86Push &) = delete; 2823 InstX86Push &operator=(const InstX86Push &) = delete; 2824 2825 public: create(Cfg * Func,Operand * Source)2826 static InstX86Push *create(Cfg *Func, Operand *Source) { 2827 return new (Func->allocate<InstX86Push>()) InstX86Push(Func, Source); 2828 } 2829 void emit(const Cfg *Func) const override; 2830 void emitIAS(const Cfg *Func) const override; 2831 void dump(const Cfg *Func) const override; classof(const Inst * Instr)2832 static bool classof(const Inst *Instr) { 2833 return InstX86Base::isClassof(Instr, InstX86Base::Push); 2834 } 2835 2836 private: 2837 InstX86Push(Cfg *Func, Operand *Source); 2838 }; 2839 2840 /// Ret instruction. Currently only supports the "ret" version that does not 2841 /// pop arguments. This instruction takes a Source operand (for non-void 2842 /// returning functions) for liveness analysis, though a FakeUse before the 2843 /// ret would do just as well. 2844 class InstX86Ret final : public InstX86Base { 2845 InstX86Ret() = delete; 2846 InstX86Ret(const InstX86Ret &) = delete; 2847 InstX86Ret &operator=(const InstX86Ret &) = delete; 2848 2849 public: 2850 static InstX86Ret *create(Cfg *Func, Variable *Source = nullptr) { 2851 return new (Func->allocate<InstX86Ret>()) InstX86Ret(Func, Source); 2852 } 2853 void emit(const Cfg *Func) const override; 2854 void emitIAS(const Cfg *Func) const override; 2855 void dump(const Cfg *Func) const override; classof(const Inst * Instr)2856 static bool classof(const Inst *Instr) { 2857 return InstX86Base::isClassof(Instr, InstX86Base::Ret); 2858 } 2859 2860 private: 2861 InstX86Ret(Cfg *Func, Variable *Source); 2862 }; 2863 2864 /// Conditional set-byte instruction. 2865 class InstX86Setcc final : public InstX86Base { 2866 InstX86Setcc() = delete; 2867 InstX86Setcc(const InstX86Cmov &) = delete; 2868 InstX86Setcc &operator=(const InstX86Setcc &) = delete; 2869 2870 public: create(Cfg * Func,Variable * Dest,BrCond Cond)2871 static InstX86Setcc *create(Cfg *Func, Variable *Dest, BrCond Cond) { 2872 return new (Func->allocate<InstX86Setcc>()) InstX86Setcc(Func, Dest, Cond); 2873 } 2874 void emit(const Cfg *Func) const override; 2875 void emitIAS(const Cfg *Func) const override; 2876 void dump(const Cfg *Func) const override; classof(const Inst * Instr)2877 static bool classof(const Inst *Instr) { 2878 return InstX86Base::isClassof(Instr, InstX86Base::Setcc); 2879 } 2880 2881 private: 2882 InstX86Setcc(Cfg *Func, Variable *Dest, BrCond Cond); 2883 2884 const BrCond Condition; 2885 }; 2886 2887 /// Exchanging Add instruction. Exchanges the first operand (destination 2888 /// operand) with the second operand (source operand), then loads the sum of 2889 /// the two values into the destination operand. The destination may be a 2890 /// register or memory, while the source must be a register. 2891 /// 2892 /// Both the dest and source are updated. The caller should then insert a 2893 /// FakeDef to reflect the second udpate. 2894 class InstX86Xadd final : public InstX86BaseLockable { 2895 InstX86Xadd() = delete; 2896 InstX86Xadd(const InstX86Xadd &) = delete; 2897 InstX86Xadd &operator=(const InstX86Xadd &) = delete; 2898 2899 public: create(Cfg * Func,Operand * Dest,Variable * Source,bool Locked)2900 static InstX86Xadd *create(Cfg *Func, Operand *Dest, Variable *Source, 2901 bool Locked) { 2902 return new (Func->allocate<InstX86Xadd>()) 2903 InstX86Xadd(Func, Dest, Source, Locked); 2904 } 2905 void emit(const Cfg *Func) const override; 2906 void emitIAS(const Cfg *Func) const override; 2907 void dump(const Cfg *Func) const override; classof(const Inst * Instr)2908 static bool classof(const Inst *Instr) { 2909 return InstX86Base::isClassof(Instr, InstX86Base::Xadd); 2910 } 2911 2912 private: 2913 InstX86Xadd(Cfg *Func, Operand *Dest, Variable *Source, bool Locked); 2914 }; 2915 2916 /// Exchange instruction. Exchanges the first operand (destination operand) 2917 /// with the second operand (source operand). At least one of the operands 2918 /// must be a register (and the other can be reg or mem). Both the Dest and 2919 /// Source are updated. If there is a memory operand, then the instruction is 2920 /// automatically "locked" without the need for a lock prefix. 2921 class InstX86Xchg final : public InstX86Base { 2922 InstX86Xchg() = delete; 2923 InstX86Xchg(const InstX86Xchg &) = delete; 2924 InstX86Xchg &operator=(const InstX86Xchg &) = delete; 2925 2926 public: create(Cfg * Func,Operand * Dest,Variable * Source)2927 static InstX86Xchg *create(Cfg *Func, Operand *Dest, Variable *Source) { 2928 return new (Func->allocate<InstX86Xchg>()) InstX86Xchg(Func, Dest, Source); 2929 } 2930 void emit(const Cfg *Func) const override; 2931 void emitIAS(const Cfg *Func) const override; 2932 void dump(const Cfg *Func) const override; classof(const Inst * Instr)2933 static bool classof(const Inst *Instr) { 2934 return InstX86Base::isClassof(Instr, InstX86Base::Xchg); 2935 } 2936 2937 private: 2938 InstX86Xchg(Cfg *Func, Operand *Dest, Variable *Source); 2939 }; 2940 2941 /// Start marker for the Intel Architecture Code Analyzer. This is not an 2942 /// executable instruction and must only be used for analysis. 2943 class InstX86IacaStart final : public InstX86Base { 2944 InstX86IacaStart() = delete; 2945 InstX86IacaStart(const InstX86IacaStart &) = delete; 2946 InstX86IacaStart &operator=(const InstX86IacaStart &) = delete; 2947 2948 public: create(Cfg * Func)2949 static InstX86IacaStart *create(Cfg *Func) { 2950 return new (Func->allocate<InstX86IacaStart>()) InstX86IacaStart(Func); 2951 } 2952 void emit(const Cfg *Func) const override; 2953 void emitIAS(const Cfg *Func) const override; 2954 void dump(const Cfg *Func) const override; classof(const Inst * Instr)2955 static bool classof(const Inst *Instr) { 2956 return InstX86Base::isClassof(Instr, InstX86Base::IacaStart); 2957 } 2958 2959 private: 2960 InstX86IacaStart(Cfg *Func); 2961 }; 2962 2963 /// End marker for the Intel Architecture Code Analyzer. This is not an 2964 /// executable instruction and must only be used for analysis. 2965 class InstX86IacaEnd final : public InstX86Base { 2966 InstX86IacaEnd() = delete; 2967 InstX86IacaEnd(const InstX86IacaEnd &) = delete; 2968 InstX86IacaEnd &operator=(const InstX86IacaEnd &) = delete; 2969 2970 public: create(Cfg * Func)2971 static InstX86IacaEnd *create(Cfg *Func) { 2972 return new (Func->allocate<InstX86IacaEnd>()) InstX86IacaEnd(Func); 2973 } 2974 void emit(const Cfg *Func) const override; 2975 void emitIAS(const Cfg *Func) const override; 2976 void dump(const Cfg *Func) const override; classof(const Inst * Instr)2977 static bool classof(const Inst *Instr) { 2978 return InstX86Base::isClassof(Instr, InstX86Base::IacaEnd); 2979 } 2980 2981 private: 2982 InstX86IacaEnd(Cfg *Func); 2983 }; 2984 2985 class InstX86Pshufb : public InstX86BaseBinopXmm<InstX86Base::Pshufb, false, 2986 InstX86Base::SseSuffix::None> { 2987 public: create(Cfg * Func,Variable * Dest,Operand * Source)2988 static InstX86Pshufb *create(Cfg *Func, Variable *Dest, Operand *Source) { 2989 return new (Func->allocate<InstX86Pshufb>()) 2990 InstX86Pshufb(Func, Dest, Source); 2991 } 2992 2993 private: InstX86Pshufb(Cfg * Func,Variable * Dest,Operand * Source)2994 InstX86Pshufb(Cfg *Func, Variable *Dest, Operand *Source) 2995 : InstX86BaseBinopXmm<InstX86Base::Pshufb, false, 2996 InstX86Base::SseSuffix::None>(Func, Dest, Source) {} 2997 }; 2998 2999 class InstX86Punpckl 3000 : public InstX86BaseBinopXmm<InstX86Base::Punpckl, false, 3001 InstX86Base::SseSuffix::Unpack> { 3002 public: create(Cfg * Func,Variable * Dest,Operand * Source)3003 static InstX86Punpckl *create(Cfg *Func, Variable *Dest, Operand *Source) { 3004 return new (Func->allocate<InstX86Punpckl>()) 3005 InstX86Punpckl(Func, Dest, Source); 3006 } 3007 3008 private: InstX86Punpckl(Cfg * Func,Variable * Dest,Operand * Source)3009 InstX86Punpckl(Cfg *Func, Variable *Dest, Operand *Source) 3010 : InstX86BaseBinopXmm<InstX86Base::Punpckl, false, 3011 InstX86Base::SseSuffix::Unpack>(Func, Dest, 3012 Source) {} 3013 }; 3014 3015 class InstX86Punpckh 3016 : public InstX86BaseBinopXmm<InstX86Base::Punpckh, false, 3017 InstX86Base::SseSuffix::Unpack> { 3018 public: create(Cfg * Func,Variable * Dest,Operand * Source)3019 static InstX86Punpckh *create(Cfg *Func, Variable *Dest, Operand *Source) { 3020 return new (Func->allocate<InstX86Punpckh>()) 3021 InstX86Punpckh(Func, Dest, Source); 3022 } 3023 3024 private: InstX86Punpckh(Cfg * Func,Variable * Dest,Operand * Source)3025 InstX86Punpckh(Cfg *Func, Variable *Dest, Operand *Source) 3026 : InstX86BaseBinopXmm<InstX86Base::Punpckh, false, 3027 InstX86Base::SseSuffix::Unpack>(Func, Dest, 3028 Source) {} 3029 }; 3030 3031 class InstX86Packss : public InstX86BaseBinopXmm<InstX86Base::Packss, false, 3032 InstX86Base::SseSuffix::Pack> { 3033 public: create(Cfg * Func,Variable * Dest,Operand * Source)3034 static InstX86Packss *create(Cfg *Func, Variable *Dest, Operand *Source) { 3035 return new (Func->allocate<InstX86Packss>()) 3036 InstX86Packss(Func, Dest, Source); 3037 } 3038 3039 private: InstX86Packss(Cfg * Func,Variable * Dest,Operand * Source)3040 InstX86Packss(Cfg *Func, Variable *Dest, Operand *Source) 3041 : InstX86BaseBinopXmm<InstX86Base::Packss, false, 3042 InstX86Base::SseSuffix::Pack>(Func, Dest, Source) {} 3043 }; 3044 3045 class InstX86Packus : public InstX86BaseBinopXmm<InstX86Base::Packus, false, 3046 InstX86Base::SseSuffix::Pack> { 3047 public: create(Cfg * Func,Variable * Dest,Operand * Source)3048 static InstX86Packus *create(Cfg *Func, Variable *Dest, Operand *Source) { 3049 return new (Func->allocate<InstX86Packus>()) 3050 InstX86Packus(Func, Dest, Source); 3051 } 3052 3053 private: InstX86Packus(Cfg * Func,Variable * Dest,Operand * Source)3054 InstX86Packus(Cfg *Func, Variable *Dest, Operand *Source) 3055 : InstX86BaseBinopXmm<InstX86Base::Packus, false, 3056 InstX86Base::SseSuffix::Pack>(Func, Dest, Source) {} 3057 }; 3058 3059 struct Insts { 3060 using FakeRMW = InstX86FakeRMW; 3061 using Label = InstX86Label; 3062 3063 using Call = InstX86Call; 3064 3065 using Br = InstX86Br; 3066 using Jmp = InstX86Jmp; 3067 using Bswap = InstX86Bswap; 3068 using Neg = InstX86Neg; 3069 using Bsf = InstX86Bsf; 3070 using Bsr = InstX86Bsr; 3071 using Lea = InstX86Lea; 3072 using Cbwdq = InstX86Cbwdq; 3073 using Movsx = InstX86Movsx; 3074 using Movzx = InstX86Movzx; 3075 using Movd = InstX86Movd; 3076 using Movmsk = InstX86Movmsk; 3077 using Sqrt = InstX86Sqrt; 3078 using Mov = InstX86Mov; 3079 using Movp = InstX86Movp; 3080 using Movq = InstX86Movq; 3081 using Add = InstX86Add; 3082 using AddRMW = InstX86AddRMW; 3083 using Addps = InstX86Addps; 3084 using Adc = InstX86Adc; 3085 using AdcRMW = InstX86AdcRMW; 3086 using Addss = InstX86Addss; 3087 using Andnps = InstX86Andnps; 3088 using Andps = InstX86Andps; 3089 using Padd = InstX86Padd; 3090 using Padds = InstX86Padds; 3091 using Paddus = InstX86Paddus; 3092 using Sub = InstX86Sub; 3093 using SubRMW = InstX86SubRMW; 3094 using Subps = InstX86Subps; 3095 using Subss = InstX86Subss; 3096 using Sbb = InstX86Sbb; 3097 using SbbRMW = InstX86SbbRMW; 3098 using Psub = InstX86Psub; 3099 using Psubs = InstX86Psubs; 3100 using Psubus = InstX86Psubus; 3101 using And = InstX86And; 3102 using AndRMW = InstX86AndRMW; 3103 using Pand = InstX86Pand; 3104 using Pandn = InstX86Pandn; 3105 using Or = InstX86Or; 3106 using Orps = InstX86Orps; 3107 using OrRMW = InstX86OrRMW; 3108 using Por = InstX86Por; 3109 using Xor = InstX86Xor; 3110 using Xorps = InstX86Xorps; 3111 using XorRMW = InstX86XorRMW; 3112 using Pxor = InstX86Pxor; 3113 using Maxss = InstX86Maxss; 3114 using Minss = InstX86Minss; 3115 using Maxps = InstX86Maxps; 3116 using Minps = InstX86Minps; 3117 using Imul = InstX86Imul; 3118 using ImulImm = InstX86ImulImm; 3119 using Mulps = InstX86Mulps; 3120 using Mulss = InstX86Mulss; 3121 using Pmull = InstX86Pmull; 3122 using Pmulhw = InstX86Pmulhw; 3123 using Pmulhuw = InstX86Pmulhuw; 3124 using Pmaddwd = InstX86Pmaddwd; 3125 using Pmuludq = InstX86Pmuludq; 3126 using Divps = InstX86Divps; 3127 using Divss = InstX86Divss; 3128 using Rol = InstX86Rol; 3129 using Shl = InstX86Shl; 3130 using Psll = InstX86Psll; 3131 using Psrl = InstX86Psrl; 3132 using Shr = InstX86Shr; 3133 using Sar = InstX86Sar; 3134 using Psra = InstX86Psra; 3135 using Pcmpeq = InstX86Pcmpeq; 3136 using Pcmpgt = InstX86Pcmpgt; 3137 using MovssRegs = InstX86MovssRegs; 3138 using Idiv = InstX86Idiv; 3139 using Div = InstX86Div; 3140 using Insertps = InstX86Insertps; 3141 using Pinsr = InstX86Pinsr; 3142 using Shufps = InstX86Shufps; 3143 using Blendvps = InstX86Blendvps; 3144 using Pblendvb = InstX86Pblendvb; 3145 using Pextr = InstX86Pextr; 3146 using Pshufd = InstX86Pshufd; 3147 using Lockable = InstX86BaseLockable; 3148 using Mul = InstX86Mul; 3149 using Shld = InstX86Shld; 3150 using Shrd = InstX86Shrd; 3151 using Cmov = InstX86Cmov; 3152 using Cmpps = InstX86Cmpps; 3153 using Cmpxchg = InstX86Cmpxchg; 3154 using Cmpxchg8b = InstX86Cmpxchg8b; 3155 using Cvt = InstX86Cvt; 3156 using Round = InstX86Round; 3157 using Icmp = InstX86Icmp; 3158 using Ucomiss = InstX86Ucomiss; 3159 using UD2 = InstX86UD2; 3160 using Int3 = InstX86Int3; 3161 using Test = InstX86Test; 3162 using Mfence = InstX86Mfence; 3163 using Store = InstX86Store; 3164 using StoreP = InstX86StoreP; 3165 using StoreQ = InstX86StoreQ; 3166 using StoreD = InstX86StoreD; 3167 using Nop = InstX86Nop; 3168 using Pop = InstX86Pop; 3169 using Push = InstX86Push; 3170 using Ret = InstX86Ret; 3171 using Setcc = InstX86Setcc; 3172 using Xadd = InstX86Xadd; 3173 using Xchg = InstX86Xchg; 3174 3175 using IacaStart = InstX86IacaStart; 3176 using IacaEnd = InstX86IacaEnd; 3177 3178 using Pshufb = InstX86Pshufb; 3179 using Punpckl = InstX86Punpckl; 3180 using Punpckh = InstX86Punpckh; 3181 using Packss = InstX86Packss; 3182 using Packus = InstX86Packus; 3183 }; 3184 3185 /// X86 Instructions have static data (particularly, opcodes and instruction 3186 /// emitters). Each X86 target needs to define all of these, so this macro is 3187 /// provided so that, if something changes, then all X86 targets will be updated 3188 /// automatically. 3189 /* In-place ops */ 3190 template <> constexpr const char *InstX86Bswap::Base::Opcode = "bswap"; 3191 template <> constexpr const char *InstX86Neg::Base::Opcode = "neg"; 3192 /* Unary ops */ 3193 template <> constexpr const char *InstX86Bsf::Base::Opcode = "bsf"; 3194 template <> constexpr const char *InstX86Bsr::Base::Opcode = "bsr"; 3195 template <> constexpr const char *InstX86Lea::Base::Opcode = "lea"; 3196 template <> constexpr const char *InstX86Movd::Base::Opcode = "movd"; 3197 template <> constexpr const char *InstX86Movsx::Base::Opcode = "movs"; 3198 template <> constexpr const char *InstX86Movzx::Base::Opcode = "movz"; 3199 template <> constexpr const char *InstX86Sqrt::Base::Opcode = "sqrt"; 3200 template <> constexpr const char *InstX86Cbwdq::Base::Opcode = "cbw/cwd/cdq"; 3201 /* Mov-like ops */ 3202 template <> constexpr const char *InstX86Mov::Base::Opcode = "mov"; 3203 template <> constexpr const char *InstX86Movp::Base::Opcode = "movups"; 3204 template <> constexpr const char *InstX86Movq::Base::Opcode = "movq"; 3205 /* Binary ops */ 3206 template <> constexpr const char *InstX86Add::Base::Opcode = "add"; 3207 template <> constexpr const char *InstX86AddRMW::Base::Opcode = "add"; 3208 template <> constexpr const char *InstX86Addps::Base::Opcode = "add"; 3209 template <> constexpr const char *InstX86Adc::Base::Opcode = "adc"; 3210 template <> constexpr const char *InstX86AdcRMW::Base::Opcode = "adc"; 3211 template <> constexpr const char *InstX86Addss::Base::Opcode = "add"; 3212 template <> constexpr const char *InstX86Andnps::Base::Opcode = "andn"; 3213 template <> constexpr const char *InstX86Andps::Base::Opcode = "and"; 3214 template <> constexpr const char *InstX86Maxss::Base::Opcode = "max"; 3215 template <> constexpr const char *InstX86Minss::Base::Opcode = "min"; 3216 template <> constexpr const char *InstX86Maxps::Base::Opcode = "max"; 3217 template <> constexpr const char *InstX86Minps::Base::Opcode = "min"; 3218 template <> constexpr const char *InstX86Padd::Base::Opcode = "padd"; 3219 template <> constexpr const char *InstX86Padds::Base::Opcode = "padds"; 3220 template <> constexpr const char *InstX86Paddus::Base::Opcode = "paddus"; 3221 template <> constexpr const char *InstX86Sub::Base::Opcode = "sub"; 3222 template <> constexpr const char *InstX86SubRMW::Base::Opcode = "sub"; 3223 template <> constexpr const char *InstX86Subps::Base::Opcode = "sub"; 3224 template <> constexpr const char *InstX86Subss::Base::Opcode = "sub"; 3225 template <> constexpr const char *InstX86Sbb::Base::Opcode = "sbb"; 3226 template <> constexpr const char *InstX86SbbRMW::Base::Opcode = "sbb"; 3227 template <> constexpr const char *InstX86Psub::Base::Opcode = "psub"; 3228 template <> constexpr const char *InstX86Psubs::Base::Opcode = "psubs"; 3229 template <> constexpr const char *InstX86Psubus::Base::Opcode = "psubus"; 3230 template <> constexpr const char *InstX86And::Base::Opcode = "and"; 3231 template <> constexpr const char *InstX86AndRMW::Base::Opcode = "and"; 3232 template <> constexpr const char *InstX86Pand::Base::Opcode = "pand"; 3233 template <> constexpr const char *InstX86Pandn::Base::Opcode = "pandn"; 3234 template <> constexpr const char *InstX86Or::Base::Opcode = "or"; 3235 template <> constexpr const char *InstX86Orps::Base::Opcode = "or"; 3236 template <> constexpr const char *InstX86OrRMW::Base::Opcode = "or"; 3237 template <> constexpr const char *InstX86Por::Base::Opcode = "por"; 3238 template <> constexpr const char *InstX86Xor::Base::Opcode = "xor"; 3239 template <> constexpr const char *InstX86Xorps::Base::Opcode = "xor"; 3240 template <> constexpr const char *InstX86XorRMW::Base::Opcode = "xor"; 3241 template <> constexpr const char *InstX86Pxor::Base::Opcode = "pxor"; 3242 template <> constexpr const char *InstX86Imul::Base::Opcode = "imul"; 3243 template <> constexpr const char *InstX86ImulImm::Base::Opcode = "imul"; 3244 template <> constexpr const char *InstX86Mulps::Base::Opcode = "mul"; 3245 template <> constexpr const char *InstX86Mulss::Base::Opcode = "mul"; 3246 template <> constexpr const char *InstX86Pmull::Base::Opcode = "pmull"; 3247 template <> constexpr const char *InstX86Pmulhw::Base::Opcode = "pmulhw"; 3248 template <> constexpr const char *InstX86Pmulhuw::Base::Opcode = "pmulhuw"; 3249 template <> constexpr const char *InstX86Pmaddwd::Base::Opcode = "pmaddwd"; 3250 template <> constexpr const char *InstX86Pmuludq::Base::Opcode = "pmuludq"; 3251 template <> constexpr const char *InstX86Div::Base::Opcode = "div"; 3252 template <> constexpr const char *InstX86Divps::Base::Opcode = "div"; 3253 template <> constexpr const char *InstX86Divss::Base::Opcode = "div"; 3254 template <> constexpr const char *InstX86Idiv::Base::Opcode = "idiv"; 3255 template <> constexpr const char *InstX86Rol::Base::Opcode = "rol"; 3256 template <> constexpr const char *InstX86Shl::Base::Opcode = "shl"; 3257 template <> constexpr const char *InstX86Psll::Base::Opcode = "psll"; 3258 template <> constexpr const char *InstX86Shr::Base::Opcode = "shr"; 3259 template <> constexpr const char *InstX86Sar::Base::Opcode = "sar"; 3260 template <> constexpr const char *InstX86Psra::Base::Opcode = "psra"; 3261 template <> constexpr const char *InstX86Psrl::Base::Opcode = "psrl"; 3262 template <> constexpr const char *InstX86Pcmpeq::Base::Opcode = "pcmpeq"; 3263 template <> constexpr const char *InstX86Pcmpgt::Base::Opcode = "pcmpgt"; 3264 template <> constexpr const char *InstX86MovssRegs::Base::Opcode = "movss"; 3265 /* Ternary ops */ 3266 template <> constexpr const char *InstX86Insertps::Base::Opcode = "insertps"; 3267 template <> constexpr const char *InstX86Round::Base::Opcode = "round"; 3268 template <> constexpr const char *InstX86Shufps::Base::Opcode = "shufps"; 3269 template <> constexpr const char *InstX86Pinsr::Base::Opcode = "pinsr"; 3270 template <> constexpr const char *InstX86Blendvps::Base::Opcode = "blendvps"; 3271 template <> constexpr const char *InstX86Pblendvb::Base::Opcode = "pblendvb"; 3272 /* Three address ops */ 3273 template <> constexpr const char *InstX86Pextr::Base::Opcode = "pextr"; 3274 template <> constexpr const char *InstX86Pshufd::Base::Opcode = "pshufd"; 3275 template <> constexpr const char *InstX86Pshufb::Base::Opcode = "pshufb"; 3276 template <> constexpr const char *InstX86Punpckl::Base::Opcode = "punpckl"; 3277 template <> constexpr const char *InstX86Punpckh::Base::Opcode = "punpckh"; 3278 template <> constexpr const char *InstX86Packss::Base::Opcode = "packss"; 3279 template <> constexpr const char *InstX86Packus::Base::Opcode = "packus"; 3280 /* Inplace GPR ops */ 3281 template <> 3282 constexpr const Assembler::GPREmitterOneOp InstX86Bswap::Base::Emitter = { 3283 &Assembler::bswap, nullptr /* only a reg form exists */ 3284 }; 3285 template <> 3286 constexpr const Assembler::GPREmitterOneOp InstX86Neg::Base::Emitter = { 3287 &Assembler::neg, &Assembler::neg}; 3288 /* Unary GPR ops */ 3289 /* uses specialized emitter. */ 3290 template <> 3291 constexpr const Assembler::GPREmitterRegOp InstX86Cbwdq::Base::Emitter = { 3292 nullptr, nullptr, nullptr}; 3293 template <> 3294 constexpr const Assembler::GPREmitterRegOp InstX86Bsf::Base::Emitter = { 3295 &Assembler::bsf, &Assembler::bsf, nullptr}; 3296 template <> 3297 constexpr const Assembler::GPREmitterRegOp InstX86Bsr::Base::Emitter = { 3298 &Assembler::bsr, &Assembler::bsr, nullptr}; 3299 template <> 3300 constexpr const Assembler::GPREmitterRegOp InstX86Lea::Base::Emitter = { 3301 /* reg/reg and reg/imm are illegal */ nullptr, &Assembler::lea, nullptr}; 3302 template <> 3303 constexpr const Assembler::GPREmitterRegOp InstX86Movsx::Base::Emitter = { 3304 &Assembler::movsx, &Assembler::movsx, nullptr}; 3305 template <> 3306 constexpr const Assembler::GPREmitterRegOp InstX86Movzx::Base::Emitter = { 3307 &Assembler::movzx, &Assembler::movzx, nullptr}; 3308 /* Unary XMM ops */ 3309 /* uses specialized emitter. */ 3310 template <> 3311 constexpr const Assembler::XmmEmitterRegOp InstX86Movd::Base::Emitter = { 3312 nullptr, nullptr}; 3313 template <> 3314 constexpr const Assembler::XmmEmitterRegOp InstX86Sqrt::Base::Emitter = { 3315 &Assembler::sqrt, &Assembler::sqrt}; 3316 /* Binary GPR ops */ 3317 /* uses specialized emitter. */ 3318 template <> 3319 constexpr const Assembler::GPREmitterRegOp InstX86Imul::Base::Emitter = { 3320 nullptr, nullptr, nullptr}; 3321 template <> 3322 constexpr const Assembler::GPREmitterRegOp InstX86Add::Base::Emitter = { 3323 &Assembler::add, &Assembler::add, &Assembler::add}; 3324 template <> 3325 constexpr const Assembler::GPREmitterAddrOp InstX86AddRMW::Base::Emitter = { 3326 &Assembler::add, &Assembler::add}; 3327 template <> 3328 constexpr const Assembler::GPREmitterRegOp InstX86Adc::Base::Emitter = { 3329 &Assembler::adc, &Assembler::adc, &Assembler::adc}; 3330 template <> 3331 constexpr const Assembler::GPREmitterAddrOp InstX86AdcRMW::Base::Emitter = { 3332 &Assembler::adc, &Assembler::adc}; 3333 template <> 3334 constexpr const Assembler::GPREmitterRegOp InstX86And::Base::Emitter = { 3335 &Assembler::And, &Assembler::And, &Assembler::And}; 3336 template <> 3337 constexpr const Assembler::GPREmitterAddrOp InstX86AndRMW::Base::Emitter = { 3338 &Assembler::And, &Assembler::And}; 3339 template <> 3340 constexpr const Assembler::GPREmitterRegOp InstX86Or::Base::Emitter = { 3341 &Assembler::Or, &Assembler::Or, &Assembler::Or}; 3342 template <> 3343 constexpr const Assembler::GPREmitterAddrOp InstX86OrRMW::Base::Emitter = { 3344 &Assembler::Or, &Assembler::Or}; 3345 template <> 3346 constexpr const Assembler::GPREmitterRegOp InstX86Sbb::Base::Emitter = { 3347 &Assembler::sbb, &Assembler::sbb, &Assembler::sbb}; 3348 template <> 3349 constexpr const Assembler::GPREmitterAddrOp InstX86SbbRMW::Base::Emitter = { 3350 &Assembler::sbb, &Assembler::sbb}; 3351 template <> 3352 constexpr const Assembler::GPREmitterRegOp InstX86Sub::Base::Emitter = { 3353 &Assembler::sub, &Assembler::sub, &Assembler::sub}; 3354 template <> 3355 constexpr const Assembler::GPREmitterAddrOp InstX86SubRMW::Base::Emitter = { 3356 &Assembler::sub, &Assembler::sub}; 3357 template <> 3358 constexpr const Assembler::GPREmitterRegOp InstX86Xor::Base::Emitter = { 3359 &Assembler::Xor, &Assembler::Xor, &Assembler::Xor}; 3360 template <> 3361 constexpr const Assembler::GPREmitterAddrOp InstX86XorRMW::Base::Emitter = { 3362 &Assembler::Xor, &Assembler::Xor}; 3363 /* Binary Shift GPR ops */ 3364 template <> 3365 constexpr const Assembler::GPREmitterShiftOp InstX86Rol::Base::Emitter = { 3366 &Assembler::rol, &Assembler::rol}; 3367 template <> 3368 constexpr const Assembler::GPREmitterShiftOp InstX86Sar::Base::Emitter = { 3369 &Assembler::sar, &Assembler::sar}; 3370 template <> 3371 constexpr const Assembler::GPREmitterShiftOp InstX86Shl::Base::Emitter = { 3372 &Assembler::shl, &Assembler::shl}; 3373 template <> 3374 constexpr const Assembler::GPREmitterShiftOp InstX86Shr::Base::Emitter = { 3375 &Assembler::shr, &Assembler::shr}; 3376 /* Binary XMM ops */ 3377 /* uses specialized emitter. */ 3378 template <> 3379 constexpr const Assembler::XmmEmitterRegOp InstX86MovssRegs::Base::Emitter = { 3380 nullptr, nullptr}; 3381 template <> 3382 constexpr const Assembler::XmmEmitterRegOp InstX86Addss::Base::Emitter = { 3383 &Assembler::addss, &Assembler::addss}; 3384 template <> 3385 constexpr const Assembler::XmmEmitterRegOp InstX86Addps::Base::Emitter = { 3386 &Assembler::addps, &Assembler::addps}; 3387 template <> 3388 constexpr const Assembler::XmmEmitterRegOp InstX86Divss::Base::Emitter = { 3389 &Assembler::divss, &Assembler::divss}; 3390 template <> 3391 constexpr const Assembler::XmmEmitterRegOp InstX86Divps::Base::Emitter = { 3392 &Assembler::divps, &Assembler::divps}; 3393 template <> 3394 constexpr const Assembler::XmmEmitterRegOp InstX86Mulss::Base::Emitter = { 3395 &Assembler::mulss, &Assembler::mulss}; 3396 template <> 3397 constexpr const Assembler::XmmEmitterRegOp InstX86Mulps::Base::Emitter = { 3398 &Assembler::mulps, &Assembler::mulps}; 3399 template <> 3400 constexpr const Assembler::XmmEmitterRegOp InstX86Padd::Base::Emitter = { 3401 &Assembler::padd, &Assembler::padd}; 3402 template <> 3403 constexpr const Assembler::XmmEmitterRegOp InstX86Padds::Base::Emitter = { 3404 &Assembler::padds, &Assembler::padds}; 3405 template <> 3406 constexpr const Assembler::XmmEmitterRegOp InstX86Paddus::Base::Emitter = { 3407 &Assembler::paddus, &Assembler::paddus}; 3408 template <> 3409 constexpr const Assembler::XmmEmitterRegOp InstX86Pand::Base::Emitter = { 3410 &Assembler::pand, &Assembler::pand}; 3411 template <> 3412 constexpr const Assembler::XmmEmitterRegOp InstX86Pandn::Base::Emitter = { 3413 &Assembler::pandn, &Assembler::pandn}; 3414 template <> 3415 constexpr const Assembler::XmmEmitterRegOp InstX86Pcmpeq::Base::Emitter = { 3416 &Assembler::pcmpeq, &Assembler::pcmpeq}; 3417 template <> 3418 constexpr const Assembler::XmmEmitterRegOp InstX86Pcmpgt::Base::Emitter = { 3419 &Assembler::pcmpgt, &Assembler::pcmpgt}; 3420 template <> 3421 constexpr const Assembler::XmmEmitterRegOp InstX86Pmull::Base::Emitter = { 3422 &Assembler::pmull, &Assembler::pmull}; 3423 template <> 3424 constexpr const Assembler::XmmEmitterRegOp InstX86Pmulhw::Base::Emitter = { 3425 &Assembler::pmulhw, &Assembler::pmulhw}; 3426 template <> 3427 constexpr const Assembler::XmmEmitterRegOp InstX86Pmulhuw::Base::Emitter = { 3428 &Assembler::pmulhuw, &Assembler::pmulhuw}; 3429 template <> 3430 constexpr const Assembler::XmmEmitterRegOp InstX86Pmaddwd::Base::Emitter = { 3431 &Assembler::pmaddwd, &Assembler::pmaddwd}; 3432 template <> 3433 constexpr const Assembler::XmmEmitterRegOp InstX86Pmuludq::Base::Emitter = { 3434 &Assembler::pmuludq, &Assembler::pmuludq}; 3435 template <> 3436 constexpr const Assembler::XmmEmitterRegOp InstX86Por::Base::Emitter = { 3437 &Assembler::por, &Assembler::por}; 3438 template <> 3439 constexpr const Assembler::XmmEmitterRegOp InstX86Psub::Base::Emitter = { 3440 &Assembler::psub, &Assembler::psub}; 3441 template <> 3442 constexpr const Assembler::XmmEmitterRegOp InstX86Psubs::Base::Emitter = { 3443 &Assembler::psubs, &Assembler::psubs}; 3444 template <> 3445 constexpr const Assembler::XmmEmitterRegOp InstX86Psubus::Base::Emitter = { 3446 &Assembler::psubus, &Assembler::psubus}; 3447 template <> 3448 constexpr const Assembler::XmmEmitterRegOp InstX86Pxor::Base::Emitter = { 3449 &Assembler::pxor, &Assembler::pxor}; 3450 template <> 3451 constexpr const Assembler::XmmEmitterRegOp InstX86Subss::Base::Emitter = { 3452 &Assembler::subss, &Assembler::subss}; 3453 template <> 3454 constexpr const Assembler::XmmEmitterRegOp InstX86Subps::Base::Emitter = { 3455 &Assembler::subps, &Assembler::subps}; 3456 template <> 3457 constexpr const Assembler::XmmEmitterRegOp InstX86Andnps::Base::Emitter = { 3458 &Assembler::andnps, &Assembler::andnps}; 3459 template <> 3460 constexpr const Assembler::XmmEmitterRegOp InstX86Andps::Base::Emitter = { 3461 &Assembler::andps, &Assembler::andps}; 3462 template <> 3463 constexpr const Assembler::XmmEmitterRegOp InstX86Maxss::Base::Emitter = { 3464 &Assembler::maxss, &Assembler::maxss}; 3465 template <> 3466 constexpr const Assembler::XmmEmitterRegOp InstX86Minss::Base::Emitter = { 3467 &Assembler::minss, &Assembler::minss}; 3468 template <> 3469 constexpr const Assembler::XmmEmitterRegOp InstX86Maxps::Base::Emitter = { 3470 &Assembler::maxps, &Assembler::maxps}; 3471 template <> 3472 constexpr const Assembler::XmmEmitterRegOp InstX86Minps::Base::Emitter = { 3473 &Assembler::minps, &Assembler::minps}; 3474 template <> 3475 constexpr const Assembler::XmmEmitterRegOp InstX86Orps::Base::Emitter = { 3476 &Assembler::orps, &Assembler::orps}; 3477 template <> 3478 constexpr const Assembler::XmmEmitterRegOp InstX86Xorps::Base::Emitter = { 3479 &Assembler::xorps, &Assembler::xorps}; /* Binary XMM Shift ops */ 3480 template <> 3481 constexpr const Assembler::XmmEmitterShiftOp InstX86Psll::Base::Emitter = { 3482 &Assembler::psll, &Assembler::psll, &Assembler::psll}; 3483 template <> 3484 constexpr const Assembler::XmmEmitterShiftOp InstX86Psra::Base::Emitter = { 3485 &Assembler::psra, &Assembler::psra, &Assembler::psra}; 3486 template <> 3487 constexpr const Assembler::XmmEmitterShiftOp InstX86Psrl::Base::Emitter = { 3488 &Assembler::psrl, &Assembler::psrl, &Assembler::psrl}; 3489 template <> 3490 constexpr const Assembler::XmmEmitterRegOp InstX86Pshufb::Base::Emitter = { 3491 &Assembler::pshufb, &Assembler::pshufb}; 3492 template <> 3493 constexpr const Assembler::XmmEmitterRegOp InstX86Punpckl::Base::Emitter = { 3494 &Assembler::punpckl, &Assembler::punpckl}; 3495 template <> 3496 constexpr const Assembler::XmmEmitterRegOp InstX86Punpckh::Base::Emitter = { 3497 &Assembler::punpckh, &Assembler::punpckh}; 3498 template <> 3499 constexpr const Assembler::XmmEmitterRegOp InstX86Packss::Base::Emitter = { 3500 &Assembler::packss, &Assembler::packss}; 3501 template <> 3502 constexpr const Assembler::XmmEmitterRegOp InstX86Packus::Base::Emitter = { 3503 &Assembler::packus, &Assembler::packus}; 3504 3505 } // end of namespace X8664 3506 } // end of namespace Ice 3507 3508 #endif // SUBZERO_SRC_ICEINSTX8664_H 3509