| OLD | NEW | 
|---|
| 1 //===- subzero/src/IceInstX8632.h - x86-32 machine instructions -*- C++ -*-===// | 1 //===- subzero/src/IceInstX8632.h - x86-32 machine instructions -*- C++ -*-===// | 
| 2 // | 2 // | 
| 3 //                        The Subzero Code Generator | 3 //                        The Subzero Code Generator | 
| 4 // | 4 // | 
| 5 // This file is distributed under the University of Illinois Open Source | 5 // This file is distributed under the University of Illinois Open Source | 
| 6 // License. See LICENSE.TXT for details. | 6 // License. See LICENSE.TXT for details. | 
| 7 // | 7 // | 
| 8 //===----------------------------------------------------------------------===// | 8 //===----------------------------------------------------------------------===// | 
| 9 /// | 9 /// | 
| 10 /// \file | 10 /// \file | 
| 11 /// This file declares the InstX8632 and OperandX8632 classes and | 11 /// This file used to house all the X8632 instructions. Subzero has been | 
| 12 /// their subclasses.  This represents the machine instructions and | 12 /// modified to use templates for X86 instructions, so all those definitions are | 
| 13 /// operands used for x86-32 code selection. | 13 /// are in IceInstX86Base.h | 
|  | 14 /// | 
|  | 15 /// When interacting with the X8632 target (which should only happen in the | 
|  | 16 /// X8632 TargetLowering) clients have should use the Ice::X8632::Traits::Insts | 
|  | 17 /// traits, which hides all the template verboseness behind a type alias. | 
|  | 18 /// | 
|  | 19 /// For example, to create an X8632 MOV Instruction, clients should do | 
|  | 20 /// | 
|  | 21 /// ::Ice::X8632::Traits::Insts::Mov::create | 
|  | 22 /// | 
|  | 23 /// In the future, this file might be used to declare X8632 specific | 
|  | 24 /// instructions (e.g., FLD, and FSTP.) | 
| 14 /// | 25 /// | 
| 15 //===----------------------------------------------------------------------===// | 26 //===----------------------------------------------------------------------===// | 
| 16 | 27 | 
| 17 #ifndef SUBZERO_SRC_ICEINSTX8632_H | 28 #ifndef SUBZERO_SRC_ICEINSTX8632_H | 
| 18 #define SUBZERO_SRC_ICEINSTX8632_H | 29 #define SUBZERO_SRC_ICEINSTX8632_H | 
| 19 | 30 | 
| 20 #include "IceAssemblerX8632.h" |  | 
| 21 #include "IceConditionCodesX8632.h" |  | 
| 22 #include "IceDefs.h" | 31 #include "IceDefs.h" | 
| 23 #include "IceInst.h" | 32 #include "IceInst.h" | 
| 24 #include "IceInstX8632.def" | 33 #include "IceInstX86Base.h" | 
| 25 #include "IceOperand.h" | 34 #include "IceOperand.h" | 
| 26 #include "IceTargetLoweringX8632Traits.h" | 35 #include "IceTargetLoweringX8632Traits.h" | 
| 27 | 36 | 
| 28 namespace Ice { |  | 
| 29 |  | 
| 30 class TargetX8632; |  | 
| 31 |  | 
| 32 /// OperandX8632 extends the Operand hierarchy.  Its subclasses are |  | 
| 33 /// OperandX8632Mem and VariableSplit. |  | 
| 34 class OperandX8632 : public Operand { |  | 
| 35   OperandX8632() = delete; |  | 
| 36   OperandX8632(const OperandX8632 &) = delete; |  | 
| 37   OperandX8632 &operator=(const OperandX8632 &) = delete; |  | 
| 38 |  | 
| 39 public: |  | 
| 40   enum OperandKindX8632 { k__Start = Operand::kTarget, kMem, kSplit }; |  | 
| 41   using Operand::dump; |  | 
| 42   void dump(const Cfg *, Ostream &Str) const override { |  | 
| 43     if (BuildDefs::dump()) |  | 
| 44       Str << "<OperandX8632>"; |  | 
| 45   } |  | 
| 46 |  | 
| 47 protected: |  | 
| 48   OperandX8632(OperandKindX8632 Kind, Type Ty) |  | 
| 49       : Operand(static_cast<OperandKind>(Kind), Ty) {} |  | 
| 50 }; |  | 
| 51 |  | 
| 52 /// OperandX8632Mem represents the m32 addressing mode, with optional |  | 
| 53 /// base and index registers, a constant offset, and a fixed shift |  | 
| 54 /// value for the index register. |  | 
| 55 class OperandX8632Mem : public OperandX8632 { |  | 
| 56   OperandX8632Mem() = delete; |  | 
| 57   OperandX8632Mem(const OperandX8632Mem &) = delete; |  | 
| 58   OperandX8632Mem &operator=(const OperandX8632Mem &) = delete; |  | 
| 59 |  | 
| 60 public: |  | 
| 61   enum SegmentRegisters { |  | 
| 62     DefaultSegment = -1, |  | 
| 63 #define X(val, name, prefix) val, |  | 
| 64     SEG_REGX8632_TABLE |  | 
| 65 #undef X |  | 
| 66         SegReg_NUM |  | 
| 67   }; |  | 
| 68   static OperandX8632Mem *create(Cfg *Func, Type Ty, Variable *Base, |  | 
| 69                                  Constant *Offset, Variable *Index = nullptr, |  | 
| 70                                  uint16_t Shift = 0, |  | 
| 71                                  SegmentRegisters SegmentReg = DefaultSegment) { |  | 
| 72     return new (Func->allocate<OperandX8632Mem>()) |  | 
| 73         OperandX8632Mem(Func, Ty, Base, Offset, Index, Shift, SegmentReg); |  | 
| 74   } |  | 
| 75   Variable *getBase() const { return Base; } |  | 
| 76   Constant *getOffset() const { return Offset; } |  | 
| 77   Variable *getIndex() const { return Index; } |  | 
| 78   uint16_t getShift() const { return Shift; } |  | 
| 79   SegmentRegisters getSegmentRegister() const { return SegmentReg; } |  | 
| 80   void emitSegmentOverride(X8632::AssemblerX8632 *Asm) const; |  | 
| 81   X8632::Traits::Address toAsmAddress(Assembler *Asm) const; |  | 
| 82   void emit(const Cfg *Func) const override; |  | 
| 83   using OperandX8632::dump; |  | 
| 84   void dump(const Cfg *Func, Ostream &Str) const override; |  | 
| 85 |  | 
| 86   static bool classof(const Operand *Operand) { |  | 
| 87     return Operand->getKind() == static_cast<OperandKind>(kMem); |  | 
| 88   } |  | 
| 89 |  | 
| 90   void setRandomized(bool R) { Randomized = R; } |  | 
| 91 |  | 
| 92   bool getRandomized() const { return Randomized; } |  | 
| 93 |  | 
| 94 private: |  | 
| 95   OperandX8632Mem(Cfg *Func, Type Ty, Variable *Base, Constant *Offset, |  | 
| 96                   Variable *Index, uint16_t Shift, SegmentRegisters SegmentReg); |  | 
| 97 |  | 
| 98   Variable *Base; |  | 
| 99   Constant *Offset; |  | 
| 100   Variable *Index; |  | 
| 101   uint16_t Shift; |  | 
| 102   SegmentRegisters SegmentReg : 16; |  | 
| 103   /// A flag to show if this memory operand is a randomized one. |  | 
| 104   /// Randomized memory operands are generated in |  | 
| 105   /// TargetX8632::randomizeOrPoolImmediate() |  | 
| 106   bool Randomized; |  | 
| 107 }; |  | 
| 108 |  | 
| 109 /// VariableSplit is a way to treat an f64 memory location as a pair |  | 
| 110 /// of i32 locations (Low and High).  This is needed for some cases |  | 
| 111 /// of the Bitcast instruction.  Since it's not possible for integer |  | 
| 112 /// registers to access the XMM registers and vice versa, the |  | 
| 113 /// lowering forces the f64 to be spilled to the stack and then |  | 
| 114 /// accesses through the VariableSplit. |  | 
| 115 class VariableSplit : public OperandX8632 { |  | 
| 116   VariableSplit() = delete; |  | 
| 117   VariableSplit(const VariableSplit &) = delete; |  | 
| 118   VariableSplit &operator=(const VariableSplit &) = delete; |  | 
| 119 |  | 
| 120 public: |  | 
| 121   enum Portion { Low, High }; |  | 
| 122   static VariableSplit *create(Cfg *Func, Variable *Var, Portion Part) { |  | 
| 123     return new (Func->allocate<VariableSplit>()) VariableSplit(Func, Var, Part); |  | 
| 124   } |  | 
| 125   int32_t getOffset() const { return Part == High ? 4 : 0; } |  | 
| 126 |  | 
| 127   X8632::Traits::Address toAsmAddress(const Cfg *Func) const; |  | 
| 128   void emit(const Cfg *Func) const override; |  | 
| 129   using OperandX8632::dump; |  | 
| 130   void dump(const Cfg *Func, Ostream &Str) const override; |  | 
| 131 |  | 
| 132   static bool classof(const Operand *Operand) { |  | 
| 133     return Operand->getKind() == static_cast<OperandKind>(kSplit); |  | 
| 134   } |  | 
| 135 |  | 
| 136 private: |  | 
| 137   VariableSplit(Cfg *Func, Variable *Var, Portion Part) |  | 
| 138       : OperandX8632(kSplit, IceType_i32), Var(Var), Part(Part) { |  | 
| 139     assert(Var->getType() == IceType_f64); |  | 
| 140     Vars = Func->allocateArrayOf<Variable *>(1); |  | 
| 141     Vars[0] = Var; |  | 
| 142     NumVars = 1; |  | 
| 143   } |  | 
| 144 |  | 
| 145   Variable *Var; |  | 
| 146   Portion Part; |  | 
| 147 }; |  | 
| 148 |  | 
| 149 /// SpillVariable decorates a Variable by linking it to another |  | 
| 150 /// Variable.  When stack frame offsets are computed, the SpillVariable |  | 
| 151 /// is given a distinct stack slot only if its linked Variable has a |  | 
| 152 /// register.  If the linked Variable has a stack slot, then the |  | 
| 153 /// Variable and SpillVariable share that slot. |  | 
| 154 class SpillVariable : public Variable { |  | 
| 155   SpillVariable() = delete; |  | 
| 156   SpillVariable(const SpillVariable &) = delete; |  | 
| 157   SpillVariable &operator=(const SpillVariable &) = delete; |  | 
| 158 |  | 
| 159 public: |  | 
| 160   static SpillVariable *create(Cfg *Func, Type Ty, SizeT Index) { |  | 
| 161     return new (Func->allocate<SpillVariable>()) SpillVariable(Ty, Index); |  | 
| 162   } |  | 
| 163   const static OperandKind SpillVariableKind = |  | 
| 164       static_cast<OperandKind>(kVariable_Target); |  | 
| 165   static bool classof(const Operand *Operand) { |  | 
| 166     return Operand->getKind() == SpillVariableKind; |  | 
| 167   } |  | 
| 168   void setLinkedTo(Variable *Var) { LinkedTo = Var; } |  | 
| 169   Variable *getLinkedTo() const { return LinkedTo; } |  | 
| 170   // Inherit dump() and emit() from Variable. |  | 
| 171 private: |  | 
| 172   SpillVariable(Type Ty, SizeT Index) |  | 
| 173       : Variable(SpillVariableKind, Ty, Index), LinkedTo(nullptr) {} |  | 
| 174   Variable *LinkedTo; |  | 
| 175 }; |  | 
| 176 |  | 
| 177 class InstX8632 : public InstTarget { |  | 
| 178   InstX8632() = delete; |  | 
| 179   InstX8632(const InstX8632 &) = delete; |  | 
| 180   InstX8632 &operator=(const InstX8632 &) = delete; |  | 
| 181 |  | 
| 182 public: |  | 
| 183   enum InstKindX8632 { |  | 
| 184     k__Start = Inst::Target, |  | 
| 185     Adc, |  | 
| 186     AdcRMW, |  | 
| 187     Add, |  | 
| 188     AddRMW, |  | 
| 189     Addps, |  | 
| 190     Addss, |  | 
| 191     Adjuststack, |  | 
| 192     And, |  | 
| 193     AndRMW, |  | 
| 194     Blendvps, |  | 
| 195     Br, |  | 
| 196     Bsf, |  | 
| 197     Bsr, |  | 
| 198     Bswap, |  | 
| 199     Call, |  | 
| 200     Cbwdq, |  | 
| 201     Cmov, |  | 
| 202     Cmpps, |  | 
| 203     Cmpxchg, |  | 
| 204     Cmpxchg8b, |  | 
| 205     Cvt, |  | 
| 206     Div, |  | 
| 207     Divps, |  | 
| 208     Divss, |  | 
| 209     FakeRMW, |  | 
| 210     Fld, |  | 
| 211     Fstp, |  | 
| 212     Icmp, |  | 
| 213     Idiv, |  | 
| 214     Imul, |  | 
| 215     Insertps, |  | 
| 216     Jmp, |  | 
| 217     Label, |  | 
| 218     Lea, |  | 
| 219     Load, |  | 
| 220     Mfence, |  | 
| 221     Mov, |  | 
| 222     Movd, |  | 
| 223     Movp, |  | 
| 224     Movq, |  | 
| 225     MovssRegs, |  | 
| 226     Movsx, |  | 
| 227     Movzx, |  | 
| 228     Mul, |  | 
| 229     Mulps, |  | 
| 230     Mulss, |  | 
| 231     Neg, |  | 
| 232     Nop, |  | 
| 233     Or, |  | 
| 234     OrRMW, |  | 
| 235     Padd, |  | 
| 236     Pand, |  | 
| 237     Pandn, |  | 
| 238     Pblendvb, |  | 
| 239     Pcmpeq, |  | 
| 240     Pcmpgt, |  | 
| 241     Pextr, |  | 
| 242     Pinsr, |  | 
| 243     Pmull, |  | 
| 244     Pmuludq, |  | 
| 245     Pop, |  | 
| 246     Por, |  | 
| 247     Pshufd, |  | 
| 248     Psll, |  | 
| 249     Psra, |  | 
| 250     Psrl, |  | 
| 251     Psub, |  | 
| 252     Push, |  | 
| 253     Pxor, |  | 
| 254     Ret, |  | 
| 255     Rol, |  | 
| 256     Sar, |  | 
| 257     Sbb, |  | 
| 258     SbbRMW, |  | 
| 259     Setcc, |  | 
| 260     Shl, |  | 
| 261     Shld, |  | 
| 262     Shr, |  | 
| 263     Shrd, |  | 
| 264     Shufps, |  | 
| 265     Sqrtss, |  | 
| 266     Store, |  | 
| 267     StoreP, |  | 
| 268     StoreQ, |  | 
| 269     Sub, |  | 
| 270     SubRMW, |  | 
| 271     Subps, |  | 
| 272     Subss, |  | 
| 273     Test, |  | 
| 274     Ucomiss, |  | 
| 275     UD2, |  | 
| 276     Xadd, |  | 
| 277     Xchg, |  | 
| 278     Xor, |  | 
| 279     XorRMW |  | 
| 280   }; |  | 
| 281 |  | 
| 282   static const char *getWidthString(Type Ty); |  | 
| 283   static const char *getFldString(Type Ty); |  | 
| 284   static X8632::Traits::Cond::BrCond |  | 
| 285   getOppositeCondition(X8632::Traits::Cond::BrCond Cond); |  | 
| 286   void dump(const Cfg *Func) const override; |  | 
| 287 |  | 
| 288   /// Shared emit routines for common forms of instructions. |  | 
| 289   /// See the definition of emitTwoAddress() for a description of |  | 
| 290   /// ShiftHack. |  | 
| 291   static void emitTwoAddress(const char *Opcode, const Inst *Inst, |  | 
| 292                              const Cfg *Func, bool ShiftHack = false); |  | 
| 293 |  | 
| 294   static void |  | 
| 295   emitIASGPRShift(const Cfg *Func, Type Ty, const Variable *Var, |  | 
| 296                   const Operand *Src, |  | 
| 297                   const X8632::AssemblerX8632::GPREmitterShiftOp &Emitter); |  | 
| 298 |  | 
| 299 protected: |  | 
| 300   InstX8632(Cfg *Func, InstKindX8632 Kind, SizeT Maxsrcs, Variable *Dest) |  | 
| 301       : InstTarget(Func, static_cast<InstKind>(Kind), Maxsrcs, Dest) {} |  | 
| 302 |  | 
| 303   static bool isClassof(const Inst *Inst, InstKindX8632 MyKind) { |  | 
| 304     return Inst->getKind() == static_cast<InstKind>(MyKind); |  | 
| 305   } |  | 
| 306   /// Most instructions that operate on vector arguments require vector |  | 
| 307   /// memory operands to be fully aligned (16-byte alignment for PNaCl |  | 
| 308   /// vector types).  The stack frame layout and call ABI ensure proper |  | 
| 309   /// alignment for stack operands, but memory operands (originating |  | 
| 310   /// from load/store bitcode instructions) only have element-size |  | 
| 311   /// alignment guarantees.  This function validates that none of the |  | 
| 312   /// operands is a memory operand of vector type, calling |  | 
| 313   /// report_fatal_error() if one is found.  This function should be |  | 
| 314   /// called during emission, and maybe also in the ctor (as long as |  | 
| 315   /// that fits the lowering style). |  | 
| 316   void validateVectorAddrMode() const { |  | 
| 317     if (getDest()) |  | 
| 318       validateVectorAddrModeOpnd(getDest()); |  | 
| 319     for (SizeT i = 0; i < getSrcSize(); ++i) { |  | 
| 320       validateVectorAddrModeOpnd(getSrc(i)); |  | 
| 321     } |  | 
| 322   } |  | 
| 323 |  | 
| 324 private: |  | 
| 325   static void validateVectorAddrModeOpnd(const Operand *Opnd) { |  | 
| 326     if (llvm::isa<OperandX8632Mem>(Opnd) && isVectorType(Opnd->getType())) { |  | 
| 327       llvm::report_fatal_error("Possible misaligned vector memory operation"); |  | 
| 328     } |  | 
| 329   } |  | 
| 330 }; |  | 
| 331 |  | 
| 332 /// InstX8632FakeRMW represents a non-atomic read-modify-write operation on a |  | 
| 333 /// memory location.  An InstX8632FakeRMW is a "fake" instruction in that it |  | 
| 334 /// still needs to be lowered to some actual RMW instruction. |  | 
| 335 /// |  | 
| 336 /// If A is some memory address, D is some data value to apply, and OP is an |  | 
| 337 /// arithmetic operator, the instruction operates as: (*A) = (*A) OP D |  | 
| 338 class InstX8632FakeRMW : public InstX8632 { |  | 
| 339   InstX8632FakeRMW() = delete; |  | 
| 340   InstX8632FakeRMW(const InstX8632FakeRMW &) = delete; |  | 
| 341   InstX8632FakeRMW &operator=(const InstX8632FakeRMW &) = delete; |  | 
| 342 |  | 
| 343 public: |  | 
| 344   static InstX8632FakeRMW *create(Cfg *Func, Operand *Data, Operand *Addr, |  | 
| 345                                   Variable *Beacon, InstArithmetic::OpKind Op, |  | 
| 346                                   uint32_t Align = 1) { |  | 
| 347     // TODO(stichnot): Stop ignoring alignment specification. |  | 
| 348     (void)Align; |  | 
| 349     return new (Func->allocate<InstX8632FakeRMW>()) |  | 
| 350         InstX8632FakeRMW(Func, Data, Addr, Op, Beacon); |  | 
| 351   } |  | 
| 352   Operand *getAddr() const { return getSrc(1); } |  | 
| 353   Operand *getData() const { return getSrc(0); } |  | 
| 354   InstArithmetic::OpKind getOp() const { return Op; } |  | 
| 355   Variable *getBeacon() const { return llvm::cast<Variable>(getSrc(2)); } |  | 
| 356   void dump(const Cfg *Func) const override; |  | 
| 357   static bool classof(const Inst *Inst) { return isClassof(Inst, FakeRMW); } |  | 
| 358 |  | 
| 359 private: |  | 
| 360   InstArithmetic::OpKind Op; |  | 
| 361   InstX8632FakeRMW(Cfg *Func, Operand *Data, Operand *Addr, |  | 
| 362                    InstArithmetic::OpKind Op, Variable *Beacon); |  | 
| 363 }; |  | 
| 364 |  | 
| 365 /// InstX8632Label represents an intra-block label that is the target |  | 
| 366 /// of an intra-block branch.  The offset between the label and the |  | 
| 367 /// branch must be fit into one byte (considered "near").  These are |  | 
| 368 /// used for lowering i1 calculations, Select instructions, and 64-bit |  | 
| 369 /// compares on a 32-bit architecture, without basic block splitting. |  | 
| 370 /// Basic block splitting is not so desirable for several reasons, one |  | 
| 371 /// of which is the impact on decisions based on whether a variable's |  | 
| 372 /// live range spans multiple basic blocks. |  | 
| 373 /// |  | 
| 374 /// Intra-block control flow must be used with caution.  Consider the |  | 
| 375 /// sequence for "c = (a >= b ? x : y)". |  | 
| 376 ///     cmp a, b |  | 
| 377 ///     br lt, L1 |  | 
| 378 ///     mov c, x |  | 
| 379 ///     jmp L2 |  | 
| 380 ///   L1: |  | 
| 381 ///     mov c, y |  | 
| 382 ///   L2: |  | 
| 383 /// |  | 
| 384 /// Labels L1 and L2 are intra-block labels.  Without knowledge of the |  | 
| 385 /// intra-block control flow, liveness analysis will determine the "mov |  | 
| 386 /// c, x" instruction to be dead.  One way to prevent this is to insert |  | 
| 387 /// a "FakeUse(c)" instruction anywhere between the two "mov c, ..." |  | 
| 388 /// instructions, e.g.: |  | 
| 389 /// |  | 
| 390 ///     cmp a, b |  | 
| 391 ///     br lt, L1 |  | 
| 392 ///     mov c, x |  | 
| 393 ///     jmp L2 |  | 
| 394 ///     FakeUse(c) |  | 
| 395 ///   L1: |  | 
| 396 ///     mov c, y |  | 
| 397 ///   L2: |  | 
| 398 /// |  | 
| 399 /// The down-side is that "mov c, x" can never be dead-code eliminated |  | 
| 400 /// even if there are no uses of c.  As unlikely as this situation is, |  | 
| 401 /// it may be prevented by running dead code elimination before |  | 
| 402 /// lowering. |  | 
| 403 class InstX8632Label : public InstX8632 { |  | 
| 404   InstX8632Label() = delete; |  | 
| 405   InstX8632Label(const InstX8632Label &) = delete; |  | 
| 406   InstX8632Label &operator=(const InstX8632Label &) = delete; |  | 
| 407 |  | 
| 408 public: |  | 
| 409   static InstX8632Label *create(Cfg *Func, TargetX8632 *Target) { |  | 
| 410     return new (Func->allocate<InstX8632Label>()) InstX8632Label(Func, Target); |  | 
| 411   } |  | 
| 412   uint32_t getEmitInstCount() const override { return 0; } |  | 
| 413   IceString getName(const Cfg *Func) const; |  | 
| 414   SizeT getNumber() const { return Number; } |  | 
| 415   void emit(const Cfg *Func) const override; |  | 
| 416   void emitIAS(const Cfg *Func) const override; |  | 
| 417   void dump(const Cfg *Func) const override; |  | 
| 418 |  | 
| 419 private: |  | 
| 420   InstX8632Label(Cfg *Func, TargetX8632 *Target); |  | 
| 421 |  | 
| 422   SizeT Number; /// used for unique label generation. |  | 
| 423 }; |  | 
| 424 |  | 
| 425 /// Conditional and unconditional branch instruction. |  | 
| 426 class InstX8632Br : public InstX8632 { |  | 
| 427   InstX8632Br() = delete; |  | 
| 428   InstX8632Br(const InstX8632Br &) = delete; |  | 
| 429   InstX8632Br &operator=(const InstX8632Br &) = delete; |  | 
| 430 |  | 
| 431 public: |  | 
| 432   /// Create a conditional branch to a node. |  | 
| 433   static InstX8632Br *create(Cfg *Func, CfgNode *TargetTrue, |  | 
| 434                              CfgNode *TargetFalse, |  | 
| 435                              X8632::Traits::Cond::BrCond Condition) { |  | 
| 436     assert(Condition != X8632::Traits::Cond::Br_None); |  | 
| 437     const InstX8632Label *NoLabel = nullptr; |  | 
| 438     return new (Func->allocate<InstX8632Br>()) |  | 
| 439         InstX8632Br(Func, TargetTrue, TargetFalse, NoLabel, Condition); |  | 
| 440   } |  | 
| 441   /// Create an unconditional branch to a node. |  | 
| 442   static InstX8632Br *create(Cfg *Func, CfgNode *Target) { |  | 
| 443     const CfgNode *NoCondTarget = nullptr; |  | 
| 444     const InstX8632Label *NoLabel = nullptr; |  | 
| 445     return new (Func->allocate<InstX8632Br>()) InstX8632Br( |  | 
| 446         Func, NoCondTarget, Target, NoLabel, X8632::Traits::Cond::Br_None); |  | 
| 447   } |  | 
| 448   /// Create a non-terminator conditional branch to a node, with a |  | 
| 449   /// fallthrough to the next instruction in the current node.  This is |  | 
| 450   /// used for switch lowering. |  | 
| 451   static InstX8632Br *create(Cfg *Func, CfgNode *Target, |  | 
| 452                              X8632::Traits::Cond::BrCond Condition) { |  | 
| 453     assert(Condition != X8632::Traits::Cond::Br_None); |  | 
| 454     const CfgNode *NoUncondTarget = nullptr; |  | 
| 455     const InstX8632Label *NoLabel = nullptr; |  | 
| 456     return new (Func->allocate<InstX8632Br>()) |  | 
| 457         InstX8632Br(Func, Target, NoUncondTarget, NoLabel, Condition); |  | 
| 458   } |  | 
| 459   /// Create a conditional intra-block branch (or unconditional, if |  | 
| 460   /// Condition==Br_None) to a label in the current block. |  | 
| 461   static InstX8632Br *create(Cfg *Func, InstX8632Label *Label, |  | 
| 462                              X8632::Traits::Cond::BrCond Condition) { |  | 
| 463     const CfgNode *NoCondTarget = nullptr; |  | 
| 464     const CfgNode *NoUncondTarget = nullptr; |  | 
| 465     return new (Func->allocate<InstX8632Br>()) |  | 
| 466         InstX8632Br(Func, NoCondTarget, NoUncondTarget, Label, Condition); |  | 
| 467   } |  | 
| 468   const CfgNode *getTargetTrue() const { return TargetTrue; } |  | 
| 469   const CfgNode *getTargetFalse() const { return TargetFalse; } |  | 
| 470   bool optimizeBranch(const CfgNode *NextNode); |  | 
| 471   uint32_t getEmitInstCount() const override { |  | 
| 472     uint32_t Sum = 0; |  | 
| 473     if (Label) |  | 
| 474       ++Sum; |  | 
| 475     if (getTargetTrue()) |  | 
| 476       ++Sum; |  | 
| 477     if (getTargetFalse()) |  | 
| 478       ++Sum; |  | 
| 479     return Sum; |  | 
| 480   } |  | 
| 481   bool isUnconditionalBranch() const override { |  | 
| 482     return !Label && Condition == X8632::Traits::Cond::Br_None; |  | 
| 483   } |  | 
| 484   bool repointEdge(CfgNode *OldNode, CfgNode *NewNode) override; |  | 
| 485   void emit(const Cfg *Func) const override; |  | 
| 486   void emitIAS(const Cfg *Func) const override; |  | 
| 487   void dump(const Cfg *Func) const override; |  | 
| 488   static bool classof(const Inst *Inst) { return isClassof(Inst, Br); } |  | 
| 489 |  | 
| 490 private: |  | 
| 491   InstX8632Br(Cfg *Func, const CfgNode *TargetTrue, const CfgNode *TargetFalse, |  | 
| 492               const InstX8632Label *Label, |  | 
| 493               X8632::Traits::Cond::BrCond Condition); |  | 
| 494 |  | 
| 495   X8632::Traits::Cond::BrCond Condition; |  | 
| 496   const CfgNode *TargetTrue; |  | 
| 497   const CfgNode *TargetFalse; |  | 
| 498   const InstX8632Label *Label; /// Intra-block branch target |  | 
| 499 }; |  | 
| 500 |  | 
| 501 /// Jump to a target outside this function, such as tailcall, nacljump, |  | 
| 502 /// naclret, unreachable.  This is different from a Branch instruction |  | 
| 503 /// in that there is no intra-function control flow to represent. |  | 
| 504 class InstX8632Jmp : public InstX8632 { |  | 
| 505   InstX8632Jmp() = delete; |  | 
| 506   InstX8632Jmp(const InstX8632Jmp &) = delete; |  | 
| 507   InstX8632Jmp &operator=(const InstX8632Jmp &) = delete; |  | 
| 508 |  | 
| 509 public: |  | 
| 510   static InstX8632Jmp *create(Cfg *Func, Operand *Target) { |  | 
| 511     return new (Func->allocate<InstX8632Jmp>()) InstX8632Jmp(Func, Target); |  | 
| 512   } |  | 
| 513   Operand *getJmpTarget() const { return getSrc(0); } |  | 
| 514   void emit(const Cfg *Func) const override; |  | 
| 515   void emitIAS(const Cfg *Func) const override; |  | 
| 516   void dump(const Cfg *Func) const override; |  | 
| 517   static bool classof(const Inst *Inst) { return isClassof(Inst, Jmp); } |  | 
| 518 |  | 
| 519 private: |  | 
| 520   InstX8632Jmp(Cfg *Func, Operand *Target); |  | 
| 521 }; |  | 
| 522 |  | 
| 523 /// AdjustStack instruction - subtracts esp by the given amount and |  | 
| 524 /// updates the stack offset during code emission. |  | 
| 525 class InstX8632AdjustStack : public InstX8632 { |  | 
| 526   InstX8632AdjustStack() = delete; |  | 
| 527   InstX8632AdjustStack(const InstX8632AdjustStack &) = delete; |  | 
| 528   InstX8632AdjustStack &operator=(const InstX8632AdjustStack &) = delete; |  | 
| 529 |  | 
| 530 public: |  | 
| 531   static InstX8632AdjustStack *create(Cfg *Func, SizeT Amount, Variable *Esp) { |  | 
| 532     return new (Func->allocate<InstX8632AdjustStack>()) |  | 
| 533         InstX8632AdjustStack(Func, Amount, Esp); |  | 
| 534   } |  | 
| 535   void emit(const Cfg *Func) const override; |  | 
| 536   void emitIAS(const Cfg *Func) const override; |  | 
| 537   void dump(const Cfg *Func) const override; |  | 
| 538   static bool classof(const Inst *Inst) { return isClassof(Inst, Adjuststack); } |  | 
| 539 |  | 
| 540 private: |  | 
| 541   InstX8632AdjustStack(Cfg *Func, SizeT Amount, Variable *Esp); |  | 
| 542   SizeT Amount; |  | 
| 543 }; |  | 
| 544 |  | 
| 545 /// Call instruction.  Arguments should have already been pushed. |  | 
| 546 class InstX8632Call : public InstX8632 { |  | 
| 547   InstX8632Call() = delete; |  | 
| 548   InstX8632Call(const InstX8632Call &) = delete; |  | 
| 549   InstX8632Call &operator=(const InstX8632Call &) = delete; |  | 
| 550 |  | 
| 551 public: |  | 
| 552   static InstX8632Call *create(Cfg *Func, Variable *Dest, Operand *CallTarget) { |  | 
| 553     return new (Func->allocate<InstX8632Call>()) |  | 
| 554         InstX8632Call(Func, Dest, CallTarget); |  | 
| 555   } |  | 
| 556   Operand *getCallTarget() const { return getSrc(0); } |  | 
| 557   void emit(const Cfg *Func) const override; |  | 
| 558   void emitIAS(const Cfg *Func) const override; |  | 
| 559   void dump(const Cfg *Func) const override; |  | 
| 560   static bool classof(const Inst *Inst) { return isClassof(Inst, Call); } |  | 
| 561 |  | 
| 562 private: |  | 
| 563   InstX8632Call(Cfg *Func, Variable *Dest, Operand *CallTarget); |  | 
| 564 }; |  | 
| 565 |  | 
| 566 /// Emit a one-operand (GPR) instruction. |  | 
| 567 void emitIASOpTyGPR(const Cfg *Func, Type Ty, const Operand *Var, |  | 
| 568                     const X8632::AssemblerX8632::GPREmitterOneOp &Emitter); |  | 
| 569 void emitIASAsAddrOpTyGPR( |  | 
| 570     const Cfg *Func, Type Ty, const Operand *Op0, const Operand *Op1, |  | 
| 571     const X8632::AssemblerX8632::GPREmitterAddrOp &Emitter); |  | 
| 572 |  | 
| 573 /// Instructions of the form x := op(x). |  | 
| 574 template <InstX8632::InstKindX8632 K> |  | 
| 575 class InstX8632InplaceopGPR : public InstX8632 { |  | 
| 576   InstX8632InplaceopGPR() = delete; |  | 
| 577   InstX8632InplaceopGPR(const InstX8632InplaceopGPR &) = delete; |  | 
| 578   InstX8632InplaceopGPR &operator=(const InstX8632InplaceopGPR &) = delete; |  | 
| 579 |  | 
| 580 public: |  | 
| 581   static InstX8632InplaceopGPR *create(Cfg *Func, Operand *SrcDest) { |  | 
| 582     return new (Func->allocate<InstX8632InplaceopGPR>()) |  | 
| 583         InstX8632InplaceopGPR(Func, SrcDest); |  | 
| 584   } |  | 
| 585   void emit(const Cfg *Func) const override { |  | 
| 586     if (!BuildDefs::dump()) |  | 
| 587       return; |  | 
| 588     Ostream &Str = Func->getContext()->getStrEmit(); |  | 
| 589     assert(getSrcSize() == 1); |  | 
| 590     Str << "\t" << Opcode << "\t"; |  | 
| 591     getSrc(0)->emit(Func); |  | 
| 592   } |  | 
| 593   void emitIAS(const Cfg *Func) const override { |  | 
| 594     assert(getSrcSize() == 1); |  | 
| 595     const Variable *Var = getDest(); |  | 
| 596     Type Ty = Var->getType(); |  | 
| 597     emitIASOpTyGPR(Func, Ty, Var, Emitter); |  | 
| 598   } |  | 
| 599   void dump(const Cfg *Func) const override { |  | 
| 600     if (!BuildDefs::dump()) |  | 
| 601       return; |  | 
| 602     Ostream &Str = Func->getContext()->getStrDump(); |  | 
| 603     dumpDest(Func); |  | 
| 604     Str << " = " << Opcode << "." << getDest()->getType() << " "; |  | 
| 605     dumpSources(Func); |  | 
| 606   } |  | 
| 607   static bool classof(const Inst *Inst) { return isClassof(Inst, K); } |  | 
| 608 |  | 
| 609 private: |  | 
| 610   InstX8632InplaceopGPR(Cfg *Func, Operand *SrcDest) |  | 
| 611       : InstX8632(Func, K, 1, llvm::dyn_cast<Variable>(SrcDest)) { |  | 
| 612     addSource(SrcDest); |  | 
| 613   } |  | 
| 614 |  | 
| 615   static const char *Opcode; |  | 
| 616   static const X8632::AssemblerX8632::GPREmitterOneOp Emitter; |  | 
| 617 }; |  | 
| 618 |  | 
| 619 /// Emit a two-operand (GPR) instruction, where the dest operand is a |  | 
| 620 /// Variable that's guaranteed to be a register. |  | 
| 621 template <bool VarCanBeByte = true, bool SrcCanBeByte = true> |  | 
| 622 void emitIASRegOpTyGPR(const Cfg *Func, Type Ty, const Variable *Dst, |  | 
| 623                        const Operand *Src, |  | 
| 624                        const X8632::AssemblerX8632::GPREmitterRegOp &Emitter); |  | 
| 625 |  | 
| 626 /// Instructions of the form x := op(y). |  | 
| 627 template <InstX8632::InstKindX8632 K> |  | 
| 628 class InstX8632UnaryopGPR : public InstX8632 { |  | 
| 629   InstX8632UnaryopGPR() = delete; |  | 
| 630   InstX8632UnaryopGPR(const InstX8632UnaryopGPR &) = delete; |  | 
| 631   InstX8632UnaryopGPR &operator=(const InstX8632UnaryopGPR &) = delete; |  | 
| 632 |  | 
| 633 public: |  | 
| 634   static InstX8632UnaryopGPR *create(Cfg *Func, Variable *Dest, Operand *Src) { |  | 
| 635     return new (Func->allocate<InstX8632UnaryopGPR>()) |  | 
| 636         InstX8632UnaryopGPR(Func, Dest, Src); |  | 
| 637   } |  | 
| 638   void emit(const Cfg *Func) const override { |  | 
| 639     if (!BuildDefs::dump()) |  | 
| 640       return; |  | 
| 641     Ostream &Str = Func->getContext()->getStrEmit(); |  | 
| 642     assert(getSrcSize() == 1); |  | 
| 643     Type SrcTy = getSrc(0)->getType(); |  | 
| 644     Type DestTy = getDest()->getType(); |  | 
| 645     Str << "\t" << Opcode << getWidthString(SrcTy); |  | 
| 646     // Movsx and movzx need both the source and dest type width letter |  | 
| 647     // to define the operation.  The other unary operations have the |  | 
| 648     // same source and dest type and as a result need only one letter. |  | 
| 649     if (SrcTy != DestTy) |  | 
| 650       Str << getWidthString(DestTy); |  | 
| 651     Str << "\t"; |  | 
| 652     getSrc(0)->emit(Func); |  | 
| 653     Str << ", "; |  | 
| 654     getDest()->emit(Func); |  | 
| 655   } |  | 
| 656   void emitIAS(const Cfg *Func) const override { |  | 
| 657     assert(getSrcSize() == 1); |  | 
| 658     const Variable *Var = getDest(); |  | 
| 659     Type Ty = Var->getType(); |  | 
| 660     const Operand *Src = getSrc(0); |  | 
| 661     emitIASRegOpTyGPR(Func, Ty, Var, Src, Emitter); |  | 
| 662   } |  | 
| 663   void dump(const Cfg *Func) const override { |  | 
| 664     if (!BuildDefs::dump()) |  | 
| 665       return; |  | 
| 666     Ostream &Str = Func->getContext()->getStrDump(); |  | 
| 667     dumpDest(Func); |  | 
| 668     Str << " = " << Opcode << "." << getSrc(0)->getType() << " "; |  | 
| 669     dumpSources(Func); |  | 
| 670   } |  | 
| 671   static bool classof(const Inst *Inst) { return isClassof(Inst, K); } |  | 
| 672 |  | 
| 673 private: |  | 
| 674   InstX8632UnaryopGPR(Cfg *Func, Variable *Dest, Operand *Src) |  | 
| 675       : InstX8632(Func, K, 1, Dest) { |  | 
| 676     addSource(Src); |  | 
| 677   } |  | 
| 678 |  | 
| 679   static const char *Opcode; |  | 
| 680   static const X8632::AssemblerX8632::GPREmitterRegOp Emitter; |  | 
| 681 }; |  | 
| 682 |  | 
| 683 void emitIASRegOpTyXMM(const Cfg *Func, Type Ty, const Variable *Var, |  | 
| 684                        const Operand *Src, |  | 
| 685                        const X8632::AssemblerX8632::XmmEmitterRegOp &Emitter); |  | 
| 686 |  | 
| 687 template <InstX8632::InstKindX8632 K> |  | 
| 688 class InstX8632UnaryopXmm : public InstX8632 { |  | 
| 689   InstX8632UnaryopXmm() = delete; |  | 
| 690   InstX8632UnaryopXmm(const InstX8632UnaryopXmm &) = delete; |  | 
| 691   InstX8632UnaryopXmm &operator=(const InstX8632UnaryopXmm &) = delete; |  | 
| 692 |  | 
| 693 public: |  | 
| 694   static InstX8632UnaryopXmm *create(Cfg *Func, Variable *Dest, Operand *Src) { |  | 
| 695     return new (Func->allocate<InstX8632UnaryopXmm>()) |  | 
| 696         InstX8632UnaryopXmm(Func, Dest, Src); |  | 
| 697   } |  | 
| 698   void emit(const Cfg *Func) const override { |  | 
| 699     if (!BuildDefs::dump()) |  | 
| 700       return; |  | 
| 701     Ostream &Str = Func->getContext()->getStrEmit(); |  | 
| 702     assert(getSrcSize() == 1); |  | 
| 703     Str << "\t" << Opcode << "\t"; |  | 
| 704     getSrc(0)->emit(Func); |  | 
| 705     Str << ", "; |  | 
| 706     getDest()->emit(Func); |  | 
| 707   } |  | 
| 708   void emitIAS(const Cfg *Func) const override { |  | 
| 709     Type Ty = getDest()->getType(); |  | 
| 710     assert(getSrcSize() == 1); |  | 
| 711     emitIASRegOpTyXMM(Func, Ty, getDest(), getSrc(0), Emitter); |  | 
| 712   } |  | 
| 713   void dump(const Cfg *Func) const override { |  | 
| 714     if (!BuildDefs::dump()) |  | 
| 715       return; |  | 
| 716     Ostream &Str = Func->getContext()->getStrDump(); |  | 
| 717     dumpDest(Func); |  | 
| 718     Str << " = " << Opcode << "." << getDest()->getType() << " "; |  | 
| 719     dumpSources(Func); |  | 
| 720   } |  | 
| 721   static bool classof(const Inst *Inst) { return isClassof(Inst, K); } |  | 
| 722 |  | 
| 723 private: |  | 
| 724   InstX8632UnaryopXmm(Cfg *Func, Variable *Dest, Operand *Src) |  | 
| 725       : InstX8632(Func, K, 1, Dest) { |  | 
| 726     addSource(Src); |  | 
| 727   } |  | 
| 728 |  | 
| 729   static const char *Opcode; |  | 
| 730   static const X8632::AssemblerX8632::XmmEmitterRegOp Emitter; |  | 
| 731 }; |  | 
| 732 |  | 
| 733 template <InstX8632::InstKindX8632 K> |  | 
| 734 class InstX8632BinopGPRShift : public InstX8632 { |  | 
| 735   InstX8632BinopGPRShift() = delete; |  | 
| 736   InstX8632BinopGPRShift(const InstX8632BinopGPRShift &) = delete; |  | 
| 737   InstX8632BinopGPRShift &operator=(const InstX8632BinopGPRShift &) = delete; |  | 
| 738 |  | 
| 739 public: |  | 
| 740   /// Create a binary-op GPR shift instruction. |  | 
| 741   static InstX8632BinopGPRShift *create(Cfg *Func, Variable *Dest, |  | 
| 742                                         Operand *Source) { |  | 
| 743     return new (Func->allocate<InstX8632BinopGPRShift>()) |  | 
| 744         InstX8632BinopGPRShift(Func, Dest, Source); |  | 
| 745   } |  | 
| 746   void emit(const Cfg *Func) const override { |  | 
| 747     if (!BuildDefs::dump()) |  | 
| 748       return; |  | 
| 749     const bool ShiftHack = true; |  | 
| 750     emitTwoAddress(Opcode, this, Func, ShiftHack); |  | 
| 751   } |  | 
| 752   void emitIAS(const Cfg *Func) const override { |  | 
| 753     Type Ty = getDest()->getType(); |  | 
| 754     assert(getSrcSize() == 2); |  | 
| 755     emitIASGPRShift(Func, Ty, getDest(), getSrc(1), Emitter); |  | 
| 756   } |  | 
| 757   void dump(const Cfg *Func) const override { |  | 
| 758     if (!BuildDefs::dump()) |  | 
| 759       return; |  | 
| 760     Ostream &Str = Func->getContext()->getStrDump(); |  | 
| 761     dumpDest(Func); |  | 
| 762     Str << " = " << Opcode << "." << getDest()->getType() << " "; |  | 
| 763     dumpSources(Func); |  | 
| 764   } |  | 
| 765   static bool classof(const Inst *Inst) { return isClassof(Inst, K); } |  | 
| 766 |  | 
| 767 private: |  | 
| 768   InstX8632BinopGPRShift(Cfg *Func, Variable *Dest, Operand *Source) |  | 
| 769       : InstX8632(Func, K, 2, Dest) { |  | 
| 770     addSource(Dest); |  | 
| 771     addSource(Source); |  | 
| 772   } |  | 
| 773 |  | 
| 774   static const char *Opcode; |  | 
| 775   static const X8632::AssemblerX8632::GPREmitterShiftOp Emitter; |  | 
| 776 }; |  | 
| 777 |  | 
| 778 template <InstX8632::InstKindX8632 K> |  | 
| 779 class InstX8632BinopGPR : public InstX8632 { |  | 
| 780   InstX8632BinopGPR() = delete; |  | 
| 781   InstX8632BinopGPR(const InstX8632BinopGPR &) = delete; |  | 
| 782   InstX8632BinopGPR &operator=(const InstX8632BinopGPR &) = delete; |  | 
| 783 |  | 
| 784 public: |  | 
| 785   /// Create an ordinary binary-op instruction like add or sub. |  | 
| 786   static InstX8632BinopGPR *create(Cfg *Func, Variable *Dest, Operand *Source) { |  | 
| 787     return new (Func->allocate<InstX8632BinopGPR>()) |  | 
| 788         InstX8632BinopGPR(Func, Dest, Source); |  | 
| 789   } |  | 
| 790   void emit(const Cfg *Func) const override { |  | 
| 791     if (!BuildDefs::dump()) |  | 
| 792       return; |  | 
| 793     const bool ShiftHack = false; |  | 
| 794     emitTwoAddress(Opcode, this, Func, ShiftHack); |  | 
| 795   } |  | 
| 796   void emitIAS(const Cfg *Func) const override { |  | 
| 797     Type Ty = getDest()->getType(); |  | 
| 798     assert(getSrcSize() == 2); |  | 
| 799     emitIASRegOpTyGPR(Func, Ty, getDest(), getSrc(1), Emitter); |  | 
| 800   } |  | 
| 801   void dump(const Cfg *Func) const override { |  | 
| 802     if (!BuildDefs::dump()) |  | 
| 803       return; |  | 
| 804     Ostream &Str = Func->getContext()->getStrDump(); |  | 
| 805     dumpDest(Func); |  | 
| 806     Str << " = " << Opcode << "." << getDest()->getType() << " "; |  | 
| 807     dumpSources(Func); |  | 
| 808   } |  | 
| 809   static bool classof(const Inst *Inst) { return isClassof(Inst, K); } |  | 
| 810 |  | 
| 811 private: |  | 
| 812   InstX8632BinopGPR(Cfg *Func, Variable *Dest, Operand *Source) |  | 
| 813       : InstX8632(Func, K, 2, Dest) { |  | 
| 814     addSource(Dest); |  | 
| 815     addSource(Source); |  | 
| 816   } |  | 
| 817 |  | 
| 818   static const char *Opcode; |  | 
| 819   static const X8632::AssemblerX8632::GPREmitterRegOp Emitter; |  | 
| 820 }; |  | 
| 821 |  | 
| 822 template <InstX8632::InstKindX8632 K> |  | 
| 823 class InstX8632BinopRMW : public InstX8632 { |  | 
| 824   InstX8632BinopRMW() = delete; |  | 
| 825   InstX8632BinopRMW(const InstX8632BinopRMW &) = delete; |  | 
| 826   InstX8632BinopRMW &operator=(const InstX8632BinopRMW &) = delete; |  | 
| 827 |  | 
| 828 public: |  | 
| 829   /// Create an ordinary binary-op instruction like add or sub. |  | 
| 830   static InstX8632BinopRMW *create(Cfg *Func, OperandX8632Mem *DestSrc0, |  | 
| 831                                    Operand *Src1) { |  | 
| 832     return new (Func->allocate<InstX8632BinopRMW>()) |  | 
| 833         InstX8632BinopRMW(Func, DestSrc0, Src1); |  | 
| 834   } |  | 
| 835   void emit(const Cfg *Func) const override { |  | 
| 836     if (!BuildDefs::dump()) |  | 
| 837       return; |  | 
| 838     const bool ShiftHack = false; |  | 
| 839     emitTwoAddress(Opcode, this, Func, ShiftHack); |  | 
| 840   } |  | 
| 841   void emitIAS(const Cfg *Func) const override { |  | 
| 842     Type Ty = getSrc(0)->getType(); |  | 
| 843     assert(getSrcSize() == 2); |  | 
| 844     emitIASAsAddrOpTyGPR(Func, Ty, getSrc(0), getSrc(1), Emitter); |  | 
| 845   } |  | 
| 846   void dump(const Cfg *Func) const override { |  | 
| 847     if (!BuildDefs::dump()) |  | 
| 848       return; |  | 
| 849     Ostream &Str = Func->getContext()->getStrDump(); |  | 
| 850     Str << Opcode << "." << getSrc(0)->getType() << " "; |  | 
| 851     dumpSources(Func); |  | 
| 852   } |  | 
| 853   static bool classof(const Inst *Inst) { return isClassof(Inst, K); } |  | 
| 854 |  | 
| 855 private: |  | 
| 856   InstX8632BinopRMW(Cfg *Func, OperandX8632Mem *DestSrc0, Operand *Src1) |  | 
| 857       : InstX8632(Func, K, 2, nullptr) { |  | 
| 858     addSource(DestSrc0); |  | 
| 859     addSource(Src1); |  | 
| 860   } |  | 
| 861   static const char *Opcode; |  | 
| 862   static const X8632::AssemblerX8632::GPREmitterAddrOp Emitter; |  | 
| 863 }; |  | 
| 864 |  | 
| 865 template <InstX8632::InstKindX8632 K, bool NeedsElementType> |  | 
| 866 class InstX8632BinopXmm : public InstX8632 { |  | 
| 867   InstX8632BinopXmm() = delete; |  | 
| 868   InstX8632BinopXmm(const InstX8632BinopXmm &) = delete; |  | 
| 869   InstX8632BinopXmm &operator=(const InstX8632BinopXmm &) = delete; |  | 
| 870 |  | 
| 871 public: |  | 
| 872   /// Create an XMM binary-op instruction like addss or addps. |  | 
| 873   static InstX8632BinopXmm *create(Cfg *Func, Variable *Dest, Operand *Source) { |  | 
| 874     return new (Func->allocate<InstX8632BinopXmm>()) |  | 
| 875         InstX8632BinopXmm(Func, Dest, Source); |  | 
| 876   } |  | 
| 877   void emit(const Cfg *Func) const override { |  | 
| 878     if (!BuildDefs::dump()) |  | 
| 879       return; |  | 
| 880     validateVectorAddrMode(); |  | 
| 881     const bool ShiftHack = false; |  | 
| 882     emitTwoAddress(Opcode, this, Func, ShiftHack); |  | 
| 883   } |  | 
| 884   void emitIAS(const Cfg *Func) const override { |  | 
| 885     validateVectorAddrMode(); |  | 
| 886     Type Ty = getDest()->getType(); |  | 
| 887     if (NeedsElementType) |  | 
| 888       Ty = typeElementType(Ty); |  | 
| 889     assert(getSrcSize() == 2); |  | 
| 890     emitIASRegOpTyXMM(Func, Ty, getDest(), getSrc(1), Emitter); |  | 
| 891   } |  | 
| 892   void dump(const Cfg *Func) const override { |  | 
| 893     if (!BuildDefs::dump()) |  | 
| 894       return; |  | 
| 895     Ostream &Str = Func->getContext()->getStrDump(); |  | 
| 896     dumpDest(Func); |  | 
| 897     Str << " = " << Opcode << "." << getDest()->getType() << " "; |  | 
| 898     dumpSources(Func); |  | 
| 899   } |  | 
| 900   static bool classof(const Inst *Inst) { return isClassof(Inst, K); } |  | 
| 901 |  | 
| 902 private: |  | 
| 903   InstX8632BinopXmm(Cfg *Func, Variable *Dest, Operand *Source) |  | 
| 904       : InstX8632(Func, K, 2, Dest) { |  | 
| 905     addSource(Dest); |  | 
| 906     addSource(Source); |  | 
| 907   } |  | 
| 908 |  | 
| 909   static const char *Opcode; |  | 
| 910   static const X8632::AssemblerX8632::XmmEmitterRegOp Emitter; |  | 
| 911 }; |  | 
| 912 |  | 
| 913 void emitIASXmmShift(const Cfg *Func, Type Ty, const Variable *Var, |  | 
| 914                      const Operand *Src, |  | 
| 915                      const X8632::AssemblerX8632::XmmEmitterShiftOp &Emitter); |  | 
| 916 |  | 
| 917 template <InstX8632::InstKindX8632 K, bool AllowAllTypes = false> |  | 
| 918 class InstX8632BinopXmmShift : public InstX8632 { |  | 
| 919   InstX8632BinopXmmShift() = delete; |  | 
| 920   InstX8632BinopXmmShift(const InstX8632BinopXmmShift &) = delete; |  | 
| 921   InstX8632BinopXmmShift &operator=(const InstX8632BinopXmmShift &) = delete; |  | 
| 922 |  | 
| 923 public: |  | 
| 924   /// Create an XMM binary-op shift operation. |  | 
| 925   static InstX8632BinopXmmShift *create(Cfg *Func, Variable *Dest, |  | 
| 926                                         Operand *Source) { |  | 
| 927     return new (Func->allocate<InstX8632BinopXmmShift>()) |  | 
| 928         InstX8632BinopXmmShift(Func, Dest, Source); |  | 
| 929   } |  | 
| 930   void emit(const Cfg *Func) const override { |  | 
| 931     if (!BuildDefs::dump()) |  | 
| 932       return; |  | 
| 933     validateVectorAddrMode(); |  | 
| 934     const bool ShiftHack = false; |  | 
| 935     emitTwoAddress(Opcode, this, Func, ShiftHack); |  | 
| 936   } |  | 
| 937   void emitIAS(const Cfg *Func) const override { |  | 
| 938     validateVectorAddrMode(); |  | 
| 939     Type Ty = getDest()->getType(); |  | 
| 940     assert(AllowAllTypes || isVectorType(Ty)); |  | 
| 941     Type ElementTy = typeElementType(Ty); |  | 
| 942     assert(getSrcSize() == 2); |  | 
| 943     emitIASXmmShift(Func, ElementTy, getDest(), getSrc(1), Emitter); |  | 
| 944   } |  | 
| 945   void dump(const Cfg *Func) const override { |  | 
| 946     if (!BuildDefs::dump()) |  | 
| 947       return; |  | 
| 948     Ostream &Str = Func->getContext()->getStrDump(); |  | 
| 949     dumpDest(Func); |  | 
| 950     Str << " = " << Opcode << "." << getDest()->getType() << " "; |  | 
| 951     dumpSources(Func); |  | 
| 952   } |  | 
| 953   static bool classof(const Inst *Inst) { return isClassof(Inst, K); } |  | 
| 954 |  | 
| 955 private: |  | 
| 956   InstX8632BinopXmmShift(Cfg *Func, Variable *Dest, Operand *Source) |  | 
| 957       : InstX8632(Func, K, 2, Dest) { |  | 
| 958     addSource(Dest); |  | 
| 959     addSource(Source); |  | 
| 960   } |  | 
| 961 |  | 
| 962   static const char *Opcode; |  | 
| 963   static const X8632::AssemblerX8632::XmmEmitterShiftOp Emitter; |  | 
| 964 }; |  | 
| 965 |  | 
| 966 template <InstX8632::InstKindX8632 K> class InstX8632Ternop : public InstX8632 { |  | 
| 967   InstX8632Ternop() = delete; |  | 
| 968   InstX8632Ternop(const InstX8632Ternop &) = delete; |  | 
| 969   InstX8632Ternop &operator=(const InstX8632Ternop &) = delete; |  | 
| 970 |  | 
| 971 public: |  | 
| 972   /// Create a ternary-op instruction like div or idiv. |  | 
| 973   static InstX8632Ternop *create(Cfg *Func, Variable *Dest, Operand *Source1, |  | 
| 974                                  Operand *Source2) { |  | 
| 975     return new (Func->allocate<InstX8632Ternop>()) |  | 
| 976         InstX8632Ternop(Func, Dest, Source1, Source2); |  | 
| 977   } |  | 
| 978   void emit(const Cfg *Func) const override { |  | 
| 979     if (!BuildDefs::dump()) |  | 
| 980       return; |  | 
| 981     Ostream &Str = Func->getContext()->getStrEmit(); |  | 
| 982     assert(getSrcSize() == 3); |  | 
| 983     Str << "\t" << Opcode << "\t"; |  | 
| 984     getSrc(2)->emit(Func); |  | 
| 985     Str << ", "; |  | 
| 986     getSrc(1)->emit(Func); |  | 
| 987     Str << ", "; |  | 
| 988     getDest()->emit(Func); |  | 
| 989   } |  | 
| 990   void emitIAS(const Cfg *Func) const override; |  | 
| 991   void dump(const Cfg *Func) const override { |  | 
| 992     if (!BuildDefs::dump()) |  | 
| 993       return; |  | 
| 994     Ostream &Str = Func->getContext()->getStrDump(); |  | 
| 995     dumpDest(Func); |  | 
| 996     Str << " = " << Opcode << "." << getDest()->getType() << " "; |  | 
| 997     dumpSources(Func); |  | 
| 998   } |  | 
| 999   static bool classof(const Inst *Inst) { return isClassof(Inst, K); } |  | 
| 1000 |  | 
| 1001 private: |  | 
| 1002   InstX8632Ternop(Cfg *Func, Variable *Dest, Operand *Source1, Operand *Source2) |  | 
| 1003       : InstX8632(Func, K, 3, Dest) { |  | 
| 1004     addSource(Dest); |  | 
| 1005     addSource(Source1); |  | 
| 1006     addSource(Source2); |  | 
| 1007   } |  | 
| 1008 |  | 
| 1009   static const char *Opcode; |  | 
| 1010 }; |  | 
| 1011 |  | 
| 1012 /// Instructions of the form x := y op z |  | 
| 1013 template <InstX8632::InstKindX8632 K> |  | 
| 1014 class InstX8632ThreeAddressop : public InstX8632 { |  | 
| 1015   InstX8632ThreeAddressop() = delete; |  | 
| 1016   InstX8632ThreeAddressop(const InstX8632ThreeAddressop &) = delete; |  | 
| 1017   InstX8632ThreeAddressop &operator=(const InstX8632ThreeAddressop &) = delete; |  | 
| 1018 |  | 
| 1019 public: |  | 
| 1020   static InstX8632ThreeAddressop *create(Cfg *Func, Variable *Dest, |  | 
| 1021                                          Operand *Source0, Operand *Source1) { |  | 
| 1022     return new (Func->allocate<InstX8632ThreeAddressop>()) |  | 
| 1023         InstX8632ThreeAddressop(Func, Dest, Source0, Source1); |  | 
| 1024   } |  | 
| 1025   void emit(const Cfg *Func) const override { |  | 
| 1026     if (!BuildDefs::dump()) |  | 
| 1027       return; |  | 
| 1028     Ostream &Str = Func->getContext()->getStrEmit(); |  | 
| 1029     assert(getSrcSize() == 2); |  | 
| 1030     Str << "\t" << Opcode << "\t"; |  | 
| 1031     getSrc(1)->emit(Func); |  | 
| 1032     Str << ", "; |  | 
| 1033     getSrc(0)->emit(Func); |  | 
| 1034     Str << ", "; |  | 
| 1035     getDest()->emit(Func); |  | 
| 1036   } |  | 
| 1037   void emitIAS(const Cfg *Func) const override; |  | 
| 1038   void dump(const Cfg *Func) const override { |  | 
| 1039     if (!BuildDefs::dump()) |  | 
| 1040       return; |  | 
| 1041     Ostream &Str = Func->getContext()->getStrDump(); |  | 
| 1042     dumpDest(Func); |  | 
| 1043     Str << " = " << Opcode << "." << getDest()->getType() << " "; |  | 
| 1044     dumpSources(Func); |  | 
| 1045   } |  | 
| 1046   static bool classof(const Inst *Inst) { return isClassof(Inst, K); } |  | 
| 1047 |  | 
| 1048 private: |  | 
| 1049   InstX8632ThreeAddressop(Cfg *Func, Variable *Dest, Operand *Source0, |  | 
| 1050                           Operand *Source1) |  | 
| 1051       : InstX8632(Func, K, 2, Dest) { |  | 
| 1052     addSource(Source0); |  | 
| 1053     addSource(Source1); |  | 
| 1054   } |  | 
| 1055 |  | 
| 1056   static const char *Opcode; |  | 
| 1057 }; |  | 
| 1058 |  | 
| 1059 /// Base class for assignment instructions |  | 
| 1060 template <InstX8632::InstKindX8632 K> |  | 
| 1061 class InstX8632Movlike : public InstX8632 { |  | 
| 1062   InstX8632Movlike() = delete; |  | 
| 1063   InstX8632Movlike(const InstX8632Movlike &) = delete; |  | 
| 1064   InstX8632Movlike &operator=(const InstX8632Movlike &) = delete; |  | 
| 1065 |  | 
| 1066 public: |  | 
| 1067   static InstX8632Movlike *create(Cfg *Func, Variable *Dest, Operand *Source) { |  | 
| 1068     return new (Func->allocate<InstX8632Movlike>()) |  | 
| 1069         InstX8632Movlike(Func, Dest, Source); |  | 
| 1070   } |  | 
| 1071   bool isRedundantAssign() const override { |  | 
| 1072     return checkForRedundantAssign(getDest(), getSrc(0)); |  | 
| 1073   } |  | 
| 1074   bool isSimpleAssign() const override { return true; } |  | 
| 1075   void emit(const Cfg *Func) const override; |  | 
| 1076   void emitIAS(const Cfg *Func) const override; |  | 
| 1077   void dump(const Cfg *Func) const override { |  | 
| 1078     if (!BuildDefs::dump()) |  | 
| 1079       return; |  | 
| 1080     Ostream &Str = Func->getContext()->getStrDump(); |  | 
| 1081     Str << Opcode << "." << getDest()->getType() << " "; |  | 
| 1082     dumpDest(Func); |  | 
| 1083     Str << ", "; |  | 
| 1084     dumpSources(Func); |  | 
| 1085   } |  | 
| 1086   static bool classof(const Inst *Inst) { return isClassof(Inst, K); } |  | 
| 1087 |  | 
| 1088 private: |  | 
| 1089   InstX8632Movlike(Cfg *Func, Variable *Dest, Operand *Source) |  | 
| 1090       : InstX8632(Func, K, 1, Dest) { |  | 
| 1091     addSource(Source); |  | 
| 1092   } |  | 
| 1093 |  | 
| 1094   static const char *Opcode; |  | 
| 1095 }; |  | 
| 1096 |  | 
| 1097 typedef InstX8632InplaceopGPR<InstX8632::Bswap> InstX8632Bswap; |  | 
| 1098 typedef InstX8632InplaceopGPR<InstX8632::Neg> InstX8632Neg; |  | 
| 1099 typedef InstX8632UnaryopGPR<InstX8632::Bsf> InstX8632Bsf; |  | 
| 1100 typedef InstX8632UnaryopGPR<InstX8632::Bsr> InstX8632Bsr; |  | 
| 1101 typedef InstX8632UnaryopGPR<InstX8632::Lea> InstX8632Lea; |  | 
| 1102 /// Cbwdq instruction - wrapper for cbw, cwd, and cdq |  | 
| 1103 typedef InstX8632UnaryopGPR<InstX8632::Cbwdq> InstX8632Cbwdq; |  | 
| 1104 typedef InstX8632UnaryopGPR<InstX8632::Movsx> InstX8632Movsx; |  | 
| 1105 typedef InstX8632UnaryopGPR<InstX8632::Movzx> InstX8632Movzx; |  | 
| 1106 typedef InstX8632UnaryopXmm<InstX8632::Movd> InstX8632Movd; |  | 
| 1107 typedef InstX8632UnaryopXmm<InstX8632::Sqrtss> InstX8632Sqrtss; |  | 
| 1108 /// Move/assignment instruction - wrapper for mov/movss/movsd. |  | 
| 1109 typedef InstX8632Movlike<InstX8632::Mov> InstX8632Mov; |  | 
| 1110 /// Move packed - copy 128 bit values between XMM registers, or mem128 |  | 
| 1111 /// and XMM registers. |  | 
| 1112 typedef InstX8632Movlike<InstX8632::Movp> InstX8632Movp; |  | 
| 1113 /// Movq - copy between XMM registers, or mem64 and XMM registers. |  | 
| 1114 typedef InstX8632Movlike<InstX8632::Movq> InstX8632Movq; |  | 
| 1115 typedef InstX8632BinopGPR<InstX8632::Add> InstX8632Add; |  | 
| 1116 typedef InstX8632BinopRMW<InstX8632::AddRMW> InstX8632AddRMW; |  | 
| 1117 typedef InstX8632BinopXmm<InstX8632::Addps, true> InstX8632Addps; |  | 
| 1118 typedef InstX8632BinopGPR<InstX8632::Adc> InstX8632Adc; |  | 
| 1119 typedef InstX8632BinopRMW<InstX8632::AdcRMW> InstX8632AdcRMW; |  | 
| 1120 typedef InstX8632BinopXmm<InstX8632::Addss, false> InstX8632Addss; |  | 
| 1121 typedef InstX8632BinopXmm<InstX8632::Padd, true> InstX8632Padd; |  | 
| 1122 typedef InstX8632BinopGPR<InstX8632::Sub> InstX8632Sub; |  | 
| 1123 typedef InstX8632BinopRMW<InstX8632::SubRMW> InstX8632SubRMW; |  | 
| 1124 typedef InstX8632BinopXmm<InstX8632::Subps, true> InstX8632Subps; |  | 
| 1125 typedef InstX8632BinopXmm<InstX8632::Subss, false> InstX8632Subss; |  | 
| 1126 typedef InstX8632BinopGPR<InstX8632::Sbb> InstX8632Sbb; |  | 
| 1127 typedef InstX8632BinopRMW<InstX8632::SbbRMW> InstX8632SbbRMW; |  | 
| 1128 typedef InstX8632BinopXmm<InstX8632::Psub, true> InstX8632Psub; |  | 
| 1129 typedef InstX8632BinopGPR<InstX8632::And> InstX8632And; |  | 
| 1130 typedef InstX8632BinopRMW<InstX8632::AndRMW> InstX8632AndRMW; |  | 
| 1131 typedef InstX8632BinopXmm<InstX8632::Pand, false> InstX8632Pand; |  | 
| 1132 typedef InstX8632BinopXmm<InstX8632::Pandn, false> InstX8632Pandn; |  | 
| 1133 typedef InstX8632BinopGPR<InstX8632::Or> InstX8632Or; |  | 
| 1134 typedef InstX8632BinopRMW<InstX8632::OrRMW> InstX8632OrRMW; |  | 
| 1135 typedef InstX8632BinopXmm<InstX8632::Por, false> InstX8632Por; |  | 
| 1136 typedef InstX8632BinopGPR<InstX8632::Xor> InstX8632Xor; |  | 
| 1137 typedef InstX8632BinopRMW<InstX8632::XorRMW> InstX8632XorRMW; |  | 
| 1138 typedef InstX8632BinopXmm<InstX8632::Pxor, false> InstX8632Pxor; |  | 
| 1139 typedef InstX8632BinopGPR<InstX8632::Imul> InstX8632Imul; |  | 
| 1140 typedef InstX8632BinopXmm<InstX8632::Mulps, true> InstX8632Mulps; |  | 
| 1141 typedef InstX8632BinopXmm<InstX8632::Mulss, false> InstX8632Mulss; |  | 
| 1142 typedef InstX8632BinopXmm<InstX8632::Pmull, true> InstX8632Pmull; |  | 
| 1143 typedef InstX8632BinopXmm<InstX8632::Pmuludq, false> InstX8632Pmuludq; |  | 
| 1144 typedef InstX8632BinopXmm<InstX8632::Divps, true> InstX8632Divps; |  | 
| 1145 typedef InstX8632BinopXmm<InstX8632::Divss, false> InstX8632Divss; |  | 
| 1146 typedef InstX8632BinopGPRShift<InstX8632::Rol> InstX8632Rol; |  | 
| 1147 typedef InstX8632BinopGPRShift<InstX8632::Shl> InstX8632Shl; |  | 
| 1148 typedef InstX8632BinopXmmShift<InstX8632::Psll> InstX8632Psll; |  | 
| 1149 typedef InstX8632BinopXmmShift<InstX8632::Psrl, true> InstX8632Psrl; |  | 
| 1150 typedef InstX8632BinopGPRShift<InstX8632::Shr> InstX8632Shr; |  | 
| 1151 typedef InstX8632BinopGPRShift<InstX8632::Sar> InstX8632Sar; |  | 
| 1152 typedef InstX8632BinopXmmShift<InstX8632::Psra> InstX8632Psra; |  | 
| 1153 typedef InstX8632BinopXmm<InstX8632::Pcmpeq, true> InstX8632Pcmpeq; |  | 
| 1154 typedef InstX8632BinopXmm<InstX8632::Pcmpgt, true> InstX8632Pcmpgt; |  | 
| 1155 /// movss is only a binary operation when the source and dest |  | 
| 1156 /// operands are both registers (the high bits of dest are left untouched). |  | 
| 1157 /// In other cases, it behaves like a copy (mov-like) operation (and the |  | 
| 1158 /// high bits of dest are cleared). |  | 
| 1159 /// InstX8632Movss will assert that both its source and dest operands are |  | 
| 1160 /// registers, so the lowering code should use _mov instead of _movss |  | 
| 1161 /// in cases where a copy operation is intended. |  | 
| 1162 typedef InstX8632BinopXmm<InstX8632::MovssRegs, false> InstX8632MovssRegs; |  | 
| 1163 typedef InstX8632Ternop<InstX8632::Idiv> InstX8632Idiv; |  | 
| 1164 typedef InstX8632Ternop<InstX8632::Div> InstX8632Div; |  | 
| 1165 typedef InstX8632Ternop<InstX8632::Insertps> InstX8632Insertps; |  | 
| 1166 typedef InstX8632Ternop<InstX8632::Pinsr> InstX8632Pinsr; |  | 
| 1167 typedef InstX8632Ternop<InstX8632::Shufps> InstX8632Shufps; |  | 
| 1168 typedef InstX8632Ternop<InstX8632::Blendvps> InstX8632Blendvps; |  | 
| 1169 typedef InstX8632Ternop<InstX8632::Pblendvb> InstX8632Pblendvb; |  | 
| 1170 typedef InstX8632ThreeAddressop<InstX8632::Pextr> InstX8632Pextr; |  | 
| 1171 typedef InstX8632ThreeAddressop<InstX8632::Pshufd> InstX8632Pshufd; |  | 
| 1172 |  | 
| 1173 /// Base class for a lockable x86-32 instruction (emits a locked prefix). |  | 
| 1174 class InstX8632Lockable : public InstX8632 { |  | 
| 1175   InstX8632Lockable() = delete; |  | 
| 1176   InstX8632Lockable(const InstX8632Lockable &) = delete; |  | 
| 1177   InstX8632Lockable &operator=(const InstX8632Lockable &) = delete; |  | 
| 1178 |  | 
| 1179 protected: |  | 
| 1180   bool Locked; |  | 
| 1181 |  | 
| 1182   InstX8632Lockable(Cfg *Func, InstKindX8632 Kind, SizeT Maxsrcs, |  | 
| 1183                     Variable *Dest, bool Locked) |  | 
| 1184       : InstX8632(Func, Kind, Maxsrcs, Dest), Locked(Locked) { |  | 
| 1185     // Assume that such instructions are used for Atomics and be careful |  | 
| 1186     // with optimizations. |  | 
| 1187     HasSideEffects = Locked; |  | 
| 1188   } |  | 
| 1189 }; |  | 
| 1190 |  | 
| 1191 /// Mul instruction - unsigned multiply. |  | 
| 1192 class InstX8632Mul : public InstX8632 { |  | 
| 1193   InstX8632Mul() = delete; |  | 
| 1194   InstX8632Mul(const InstX8632Mul &) = delete; |  | 
| 1195   InstX8632Mul &operator=(const InstX8632Mul &) = delete; |  | 
| 1196 |  | 
| 1197 public: |  | 
| 1198   static InstX8632Mul *create(Cfg *Func, Variable *Dest, Variable *Source1, |  | 
| 1199                               Operand *Source2) { |  | 
| 1200     return new (Func->allocate<InstX8632Mul>()) |  | 
| 1201         InstX8632Mul(Func, Dest, Source1, Source2); |  | 
| 1202   } |  | 
| 1203   void emit(const Cfg *Func) const override; |  | 
| 1204   void emitIAS(const Cfg *Func) const override; |  | 
| 1205   void dump(const Cfg *Func) const override; |  | 
| 1206   static bool classof(const Inst *Inst) { return isClassof(Inst, Mul); } |  | 
| 1207 |  | 
| 1208 private: |  | 
| 1209   InstX8632Mul(Cfg *Func, Variable *Dest, Variable *Source1, Operand *Source2); |  | 
| 1210 }; |  | 
| 1211 |  | 
| 1212 /// Shld instruction - shift across a pair of operands. |  | 
| 1213 class InstX8632Shld : public InstX8632 { |  | 
| 1214   InstX8632Shld() = delete; |  | 
| 1215   InstX8632Shld(const InstX8632Shld &) = delete; |  | 
| 1216   InstX8632Shld &operator=(const InstX8632Shld &) = delete; |  | 
| 1217 |  | 
| 1218 public: |  | 
| 1219   static InstX8632Shld *create(Cfg *Func, Variable *Dest, Variable *Source1, |  | 
| 1220                                Variable *Source2) { |  | 
| 1221     return new (Func->allocate<InstX8632Shld>()) |  | 
| 1222         InstX8632Shld(Func, Dest, Source1, Source2); |  | 
| 1223   } |  | 
| 1224   void emit(const Cfg *Func) const override; |  | 
| 1225   void emitIAS(const Cfg *Func) const override; |  | 
| 1226   void dump(const Cfg *Func) const override; |  | 
| 1227   static bool classof(const Inst *Inst) { return isClassof(Inst, Shld); } |  | 
| 1228 |  | 
| 1229 private: |  | 
| 1230   InstX8632Shld(Cfg *Func, Variable *Dest, Variable *Source1, |  | 
| 1231                 Variable *Source2); |  | 
| 1232 }; |  | 
| 1233 |  | 
| 1234 /// Shrd instruction - shift across a pair of operands. |  | 
| 1235 class InstX8632Shrd : public InstX8632 { |  | 
| 1236   InstX8632Shrd() = delete; |  | 
| 1237   InstX8632Shrd(const InstX8632Shrd &) = delete; |  | 
| 1238   InstX8632Shrd &operator=(const InstX8632Shrd &) = delete; |  | 
| 1239 |  | 
| 1240 public: |  | 
| 1241   static InstX8632Shrd *create(Cfg *Func, Variable *Dest, Variable *Source1, |  | 
| 1242                                Variable *Source2) { |  | 
| 1243     return new (Func->allocate<InstX8632Shrd>()) |  | 
| 1244         InstX8632Shrd(Func, Dest, Source1, Source2); |  | 
| 1245   } |  | 
| 1246   void emit(const Cfg *Func) const override; |  | 
| 1247   void emitIAS(const Cfg *Func) const override; |  | 
| 1248   void dump(const Cfg *Func) const override; |  | 
| 1249   static bool classof(const Inst *Inst) { return isClassof(Inst, Shrd); } |  | 
| 1250 |  | 
| 1251 private: |  | 
| 1252   InstX8632Shrd(Cfg *Func, Variable *Dest, Variable *Source1, |  | 
| 1253                 Variable *Source2); |  | 
| 1254 }; |  | 
| 1255 |  | 
| 1256 /// Conditional move instruction. |  | 
| 1257 class InstX8632Cmov : public InstX8632 { |  | 
| 1258   InstX8632Cmov() = delete; |  | 
| 1259   InstX8632Cmov(const InstX8632Cmov &) = delete; |  | 
| 1260   InstX8632Cmov &operator=(const InstX8632Cmov &) = delete; |  | 
| 1261 |  | 
| 1262 public: |  | 
| 1263   static InstX8632Cmov *create(Cfg *Func, Variable *Dest, Operand *Source, |  | 
| 1264                                X8632::Traits::Cond::BrCond Cond) { |  | 
| 1265     return new (Func->allocate<InstX8632Cmov>()) |  | 
| 1266         InstX8632Cmov(Func, Dest, Source, Cond); |  | 
| 1267   } |  | 
| 1268   void emit(const Cfg *Func) const override; |  | 
| 1269   void emitIAS(const Cfg *Func) const override; |  | 
| 1270   void dump(const Cfg *Func) const override; |  | 
| 1271   static bool classof(const Inst *Inst) { return isClassof(Inst, Cmov); } |  | 
| 1272 |  | 
| 1273 private: |  | 
| 1274   InstX8632Cmov(Cfg *Func, Variable *Dest, Operand *Source, |  | 
| 1275                 X8632::Traits::Cond::BrCond Cond); |  | 
| 1276 |  | 
| 1277   X8632::Traits::Cond::BrCond Condition; |  | 
| 1278 }; |  | 
| 1279 |  | 
| 1280 /// Cmpps instruction - compare packed singled-precision floating point |  | 
| 1281 /// values |  | 
| 1282 class InstX8632Cmpps : public InstX8632 { |  | 
| 1283   InstX8632Cmpps() = delete; |  | 
| 1284   InstX8632Cmpps(const InstX8632Cmpps &) = delete; |  | 
| 1285   InstX8632Cmpps &operator=(const InstX8632Cmpps &) = delete; |  | 
| 1286 |  | 
| 1287 public: |  | 
| 1288   static InstX8632Cmpps *create(Cfg *Func, Variable *Dest, Operand *Source, |  | 
| 1289                                 X8632::Traits::Cond::CmppsCond Condition) { |  | 
| 1290     return new (Func->allocate<InstX8632Cmpps>()) |  | 
| 1291         InstX8632Cmpps(Func, Dest, Source, Condition); |  | 
| 1292   } |  | 
| 1293   void emit(const Cfg *Func) const override; |  | 
| 1294   void emitIAS(const Cfg *Func) const override; |  | 
| 1295   void dump(const Cfg *Func) const override; |  | 
| 1296   static bool classof(const Inst *Inst) { return isClassof(Inst, Cmpps); } |  | 
| 1297 |  | 
| 1298 private: |  | 
| 1299   InstX8632Cmpps(Cfg *Func, Variable *Dest, Operand *Source, |  | 
| 1300                  X8632::Traits::Cond::CmppsCond Cond); |  | 
| 1301 |  | 
| 1302   X8632::Traits::Cond::CmppsCond Condition; |  | 
| 1303 }; |  | 
| 1304 |  | 
| 1305 /// Cmpxchg instruction - cmpxchg <dest>, <desired> will compare if <dest> |  | 
| 1306 /// equals eax. If so, the ZF is set and <desired> is stored in <dest>. |  | 
| 1307 /// If not, ZF is cleared and <dest> is copied to eax (or subregister). |  | 
| 1308 /// <dest> can be a register or memory, while <desired> must be a register. |  | 
| 1309 /// It is the user's responsiblity to mark eax with a FakeDef. |  | 
| 1310 class InstX8632Cmpxchg : public InstX8632Lockable { |  | 
| 1311   InstX8632Cmpxchg() = delete; |  | 
| 1312   InstX8632Cmpxchg(const InstX8632Cmpxchg &) = delete; |  | 
| 1313   InstX8632Cmpxchg &operator=(const InstX8632Cmpxchg &) = delete; |  | 
| 1314 |  | 
| 1315 public: |  | 
| 1316   static InstX8632Cmpxchg *create(Cfg *Func, Operand *DestOrAddr, Variable *Eax, |  | 
| 1317                                   Variable *Desired, bool Locked) { |  | 
| 1318     return new (Func->allocate<InstX8632Cmpxchg>()) |  | 
| 1319         InstX8632Cmpxchg(Func, DestOrAddr, Eax, Desired, Locked); |  | 
| 1320   } |  | 
| 1321   void emit(const Cfg *Func) const override; |  | 
| 1322   void emitIAS(const Cfg *Func) const override; |  | 
| 1323   void dump(const Cfg *Func) const override; |  | 
| 1324   static bool classof(const Inst *Inst) { return isClassof(Inst, Cmpxchg); } |  | 
| 1325 |  | 
| 1326 private: |  | 
| 1327   InstX8632Cmpxchg(Cfg *Func, Operand *DestOrAddr, Variable *Eax, |  | 
| 1328                    Variable *Desired, bool Locked); |  | 
| 1329 }; |  | 
| 1330 |  | 
| 1331 /// Cmpxchg8b instruction - cmpxchg8b <m64> will compare if <m64> |  | 
| 1332 /// equals edx:eax. If so, the ZF is set and ecx:ebx is stored in <m64>. |  | 
| 1333 /// If not, ZF is cleared and <m64> is copied to edx:eax. |  | 
| 1334 /// The caller is responsible for inserting FakeDefs to mark edx |  | 
| 1335 /// and eax as modified. |  | 
| 1336 /// <m64> must be a memory operand. |  | 
| 1337 class InstX8632Cmpxchg8b : public InstX8632Lockable { |  | 
| 1338   InstX8632Cmpxchg8b() = delete; |  | 
| 1339   InstX8632Cmpxchg8b(const InstX8632Cmpxchg8b &) = delete; |  | 
| 1340   InstX8632Cmpxchg8b &operator=(const InstX8632Cmpxchg8b &) = delete; |  | 
| 1341 |  | 
| 1342 public: |  | 
| 1343   static InstX8632Cmpxchg8b *create(Cfg *Func, OperandX8632Mem *Dest, |  | 
| 1344                                     Variable *Edx, Variable *Eax, Variable *Ecx, |  | 
| 1345                                     Variable *Ebx, bool Locked) { |  | 
| 1346     return new (Func->allocate<InstX8632Cmpxchg8b>()) |  | 
| 1347         InstX8632Cmpxchg8b(Func, Dest, Edx, Eax, Ecx, Ebx, Locked); |  | 
| 1348   } |  | 
| 1349   void emit(const Cfg *Func) const override; |  | 
| 1350   void emitIAS(const Cfg *Func) const override; |  | 
| 1351   void dump(const Cfg *Func) const override; |  | 
| 1352   static bool classof(const Inst *Inst) { return isClassof(Inst, Cmpxchg8b); } |  | 
| 1353 |  | 
| 1354 private: |  | 
| 1355   InstX8632Cmpxchg8b(Cfg *Func, OperandX8632Mem *Dest, Variable *Edx, |  | 
| 1356                      Variable *Eax, Variable *Ecx, Variable *Ebx, bool Locked); |  | 
| 1357 }; |  | 
| 1358 |  | 
| 1359 /// Cvt instruction - wrapper for cvtsX2sY where X and Y are in {s,d,i} |  | 
| 1360 /// as appropriate.  s=float, d=double, i=int.  X and Y are determined |  | 
| 1361 /// from dest/src types.  Sign and zero extension on the integer |  | 
| 1362 /// operand needs to be done separately. |  | 
| 1363 class InstX8632Cvt : public InstX8632 { |  | 
| 1364   InstX8632Cvt() = delete; |  | 
| 1365   InstX8632Cvt(const InstX8632Cvt &) = delete; |  | 
| 1366   InstX8632Cvt &operator=(const InstX8632Cvt &) = delete; |  | 
| 1367 |  | 
| 1368 public: |  | 
| 1369   enum CvtVariant { Si2ss, Tss2si, Float2float, Dq2ps, Tps2dq }; |  | 
| 1370   static InstX8632Cvt *create(Cfg *Func, Variable *Dest, Operand *Source, |  | 
| 1371                               CvtVariant Variant) { |  | 
| 1372     return new (Func->allocate<InstX8632Cvt>()) |  | 
| 1373         InstX8632Cvt(Func, Dest, Source, Variant); |  | 
| 1374   } |  | 
| 1375   void emit(const Cfg *Func) const override; |  | 
| 1376   void emitIAS(const Cfg *Func) const override; |  | 
| 1377   void dump(const Cfg *Func) const override; |  | 
| 1378   static bool classof(const Inst *Inst) { return isClassof(Inst, Cvt); } |  | 
| 1379   bool isTruncating() const { return Variant == Tss2si || Variant == Tps2dq; } |  | 
| 1380 |  | 
| 1381 private: |  | 
| 1382   CvtVariant Variant; |  | 
| 1383   InstX8632Cvt(Cfg *Func, Variable *Dest, Operand *Source, CvtVariant Variant); |  | 
| 1384 }; |  | 
| 1385 |  | 
| 1386 /// cmp - Integer compare instruction. |  | 
| 1387 class InstX8632Icmp : public InstX8632 { |  | 
| 1388   InstX8632Icmp() = delete; |  | 
| 1389   InstX8632Icmp(const InstX8632Icmp &) = delete; |  | 
| 1390   InstX8632Icmp &operator=(const InstX8632Icmp &) = delete; |  | 
| 1391 |  | 
| 1392 public: |  | 
| 1393   static InstX8632Icmp *create(Cfg *Func, Operand *Src1, Operand *Src2) { |  | 
| 1394     return new (Func->allocate<InstX8632Icmp>()) |  | 
| 1395         InstX8632Icmp(Func, Src1, Src2); |  | 
| 1396   } |  | 
| 1397   void emit(const Cfg *Func) const override; |  | 
| 1398   void emitIAS(const Cfg *Func) const override; |  | 
| 1399   void dump(const Cfg *Func) const override; |  | 
| 1400   static bool classof(const Inst *Inst) { return isClassof(Inst, Icmp); } |  | 
| 1401 |  | 
| 1402 private: |  | 
| 1403   InstX8632Icmp(Cfg *Func, Operand *Src1, Operand *Src2); |  | 
| 1404 }; |  | 
| 1405 |  | 
| 1406 /// ucomiss/ucomisd - floating-point compare instruction. |  | 
| 1407 class InstX8632Ucomiss : public InstX8632 { |  | 
| 1408   InstX8632Ucomiss() = delete; |  | 
| 1409   InstX8632Ucomiss(const InstX8632Ucomiss &) = delete; |  | 
| 1410   InstX8632Ucomiss &operator=(const InstX8632Ucomiss &) = delete; |  | 
| 1411 |  | 
| 1412 public: |  | 
| 1413   static InstX8632Ucomiss *create(Cfg *Func, Operand *Src1, Operand *Src2) { |  | 
| 1414     return new (Func->allocate<InstX8632Ucomiss>()) |  | 
| 1415         InstX8632Ucomiss(Func, Src1, Src2); |  | 
| 1416   } |  | 
| 1417   void emit(const Cfg *Func) const override; |  | 
| 1418   void emitIAS(const Cfg *Func) const override; |  | 
| 1419   void dump(const Cfg *Func) const override; |  | 
| 1420   static bool classof(const Inst *Inst) { return isClassof(Inst, Ucomiss); } |  | 
| 1421 |  | 
| 1422 private: |  | 
| 1423   InstX8632Ucomiss(Cfg *Func, Operand *Src1, Operand *Src2); |  | 
| 1424 }; |  | 
| 1425 |  | 
| 1426 /// UD2 instruction. |  | 
| 1427 class InstX8632UD2 : public InstX8632 { |  | 
| 1428   InstX8632UD2() = delete; |  | 
| 1429   InstX8632UD2(const InstX8632UD2 &) = delete; |  | 
| 1430   InstX8632UD2 &operator=(const InstX8632UD2 &) = delete; |  | 
| 1431 |  | 
| 1432 public: |  | 
| 1433   static InstX8632UD2 *create(Cfg *Func) { |  | 
| 1434     return new (Func->allocate<InstX8632UD2>()) InstX8632UD2(Func); |  | 
| 1435   } |  | 
| 1436   void emit(const Cfg *Func) const override; |  | 
| 1437   void emitIAS(const Cfg *Func) const override; |  | 
| 1438   void dump(const Cfg *Func) const override; |  | 
| 1439   static bool classof(const Inst *Inst) { return isClassof(Inst, UD2); } |  | 
| 1440 |  | 
| 1441 private: |  | 
| 1442   explicit InstX8632UD2(Cfg *Func); |  | 
| 1443 }; |  | 
| 1444 |  | 
| 1445 /// Test instruction. |  | 
| 1446 class InstX8632Test : public InstX8632 { |  | 
| 1447   InstX8632Test() = delete; |  | 
| 1448   InstX8632Test(const InstX8632Test &) = delete; |  | 
| 1449   InstX8632Test &operator=(const InstX8632Test &) = delete; |  | 
| 1450 |  | 
| 1451 public: |  | 
| 1452   static InstX8632Test *create(Cfg *Func, Operand *Source1, Operand *Source2) { |  | 
| 1453     return new (Func->allocate<InstX8632Test>()) |  | 
| 1454         InstX8632Test(Func, Source1, Source2); |  | 
| 1455   } |  | 
| 1456   void emit(const Cfg *Func) const override; |  | 
| 1457   void emitIAS(const Cfg *Func) const override; |  | 
| 1458   void dump(const Cfg *Func) const override; |  | 
| 1459   static bool classof(const Inst *Inst) { return isClassof(Inst, Test); } |  | 
| 1460 |  | 
| 1461 private: |  | 
| 1462   InstX8632Test(Cfg *Func, Operand *Source1, Operand *Source2); |  | 
| 1463 }; |  | 
| 1464 |  | 
| 1465 /// Mfence instruction. |  | 
| 1466 class InstX8632Mfence : public InstX8632 { |  | 
| 1467   InstX8632Mfence() = delete; |  | 
| 1468   InstX8632Mfence(const InstX8632Mfence &) = delete; |  | 
| 1469   InstX8632Mfence &operator=(const InstX8632Mfence &) = delete; |  | 
| 1470 |  | 
| 1471 public: |  | 
| 1472   static InstX8632Mfence *create(Cfg *Func) { |  | 
| 1473     return new (Func->allocate<InstX8632Mfence>()) InstX8632Mfence(Func); |  | 
| 1474   } |  | 
| 1475   void emit(const Cfg *Func) const override; |  | 
| 1476   void emitIAS(const Cfg *Func) const override; |  | 
| 1477   void dump(const Cfg *Func) const override; |  | 
| 1478   static bool classof(const Inst *Inst) { return isClassof(Inst, Mfence); } |  | 
| 1479 |  | 
| 1480 private: |  | 
| 1481   explicit InstX8632Mfence(Cfg *Func); |  | 
| 1482 }; |  | 
| 1483 |  | 
| 1484 /// This is essentially a "mov" instruction with an OperandX8632Mem |  | 
| 1485 /// operand instead of Variable as the destination.  It's important |  | 
| 1486 /// for liveness that there is no Dest operand. |  | 
| 1487 class InstX8632Store : public InstX8632 { |  | 
| 1488   InstX8632Store() = delete; |  | 
| 1489   InstX8632Store(const InstX8632Store &) = delete; |  | 
| 1490   InstX8632Store &operator=(const InstX8632Store &) = delete; |  | 
| 1491 |  | 
| 1492 public: |  | 
| 1493   static InstX8632Store *create(Cfg *Func, Operand *Value, OperandX8632 *Mem) { |  | 
| 1494     return new (Func->allocate<InstX8632Store>()) |  | 
| 1495         InstX8632Store(Func, Value, Mem); |  | 
| 1496   } |  | 
| 1497   void emit(const Cfg *Func) const override; |  | 
| 1498   void emitIAS(const Cfg *Func) const override; |  | 
| 1499   void dump(const Cfg *Func) const override; |  | 
| 1500   static bool classof(const Inst *Inst) { return isClassof(Inst, Store); } |  | 
| 1501 |  | 
| 1502 private: |  | 
| 1503   InstX8632Store(Cfg *Func, Operand *Value, OperandX8632 *Mem); |  | 
| 1504 }; |  | 
| 1505 |  | 
| 1506 /// This is essentially a vector "mov" instruction with an OperandX8632Mem |  | 
| 1507 /// operand instead of Variable as the destination.  It's important |  | 
| 1508 /// for liveness that there is no Dest operand. The source must be an |  | 
| 1509 /// Xmm register, since Dest is mem. |  | 
| 1510 class InstX8632StoreP : public InstX8632 { |  | 
| 1511   InstX8632StoreP() = delete; |  | 
| 1512   InstX8632StoreP(const InstX8632StoreP &) = delete; |  | 
| 1513   InstX8632StoreP &operator=(const InstX8632StoreP &) = delete; |  | 
| 1514 |  | 
| 1515 public: |  | 
| 1516   static InstX8632StoreP *create(Cfg *Func, Variable *Value, |  | 
| 1517                                  OperandX8632Mem *Mem) { |  | 
| 1518     return new (Func->allocate<InstX8632StoreP>()) |  | 
| 1519         InstX8632StoreP(Func, Value, Mem); |  | 
| 1520   } |  | 
| 1521   void emit(const Cfg *Func) const override; |  | 
| 1522   void emitIAS(const Cfg *Func) const override; |  | 
| 1523   void dump(const Cfg *Func) const override; |  | 
| 1524   static bool classof(const Inst *Inst) { return isClassof(Inst, StoreP); } |  | 
| 1525 |  | 
| 1526 private: |  | 
| 1527   InstX8632StoreP(Cfg *Func, Variable *Value, OperandX8632Mem *Mem); |  | 
| 1528 }; |  | 
| 1529 |  | 
| 1530 class InstX8632StoreQ : public InstX8632 { |  | 
| 1531   InstX8632StoreQ() = delete; |  | 
| 1532   InstX8632StoreQ(const InstX8632StoreQ &) = delete; |  | 
| 1533   InstX8632StoreQ &operator=(const InstX8632StoreQ &) = delete; |  | 
| 1534 |  | 
| 1535 public: |  | 
| 1536   static InstX8632StoreQ *create(Cfg *Func, Variable *Value, |  | 
| 1537                                  OperandX8632Mem *Mem) { |  | 
| 1538     return new (Func->allocate<InstX8632StoreQ>()) |  | 
| 1539         InstX8632StoreQ(Func, Value, Mem); |  | 
| 1540   } |  | 
| 1541   void emit(const Cfg *Func) const override; |  | 
| 1542   void emitIAS(const Cfg *Func) const override; |  | 
| 1543   void dump(const Cfg *Func) const override; |  | 
| 1544   static bool classof(const Inst *Inst) { return isClassof(Inst, StoreQ); } |  | 
| 1545 |  | 
| 1546 private: |  | 
| 1547   InstX8632StoreQ(Cfg *Func, Variable *Value, OperandX8632Mem *Mem); |  | 
| 1548 }; |  | 
| 1549 |  | 
| 1550 /// Nop instructions of varying length |  | 
| 1551 class InstX8632Nop : public InstX8632 { |  | 
| 1552   InstX8632Nop() = delete; |  | 
| 1553   InstX8632Nop(const InstX8632Nop &) = delete; |  | 
| 1554   InstX8632Nop &operator=(const InstX8632Nop &) = delete; |  | 
| 1555 |  | 
| 1556 public: |  | 
| 1557   // TODO: Replace with enum. |  | 
| 1558   typedef unsigned NopVariant; |  | 
| 1559 |  | 
| 1560   static InstX8632Nop *create(Cfg *Func, NopVariant Variant) { |  | 
| 1561     return new (Func->allocate<InstX8632Nop>()) InstX8632Nop(Func, Variant); |  | 
| 1562   } |  | 
| 1563   void emit(const Cfg *Func) const override; |  | 
| 1564   void emitIAS(const Cfg *Func) const override; |  | 
| 1565   void dump(const Cfg *Func) const override; |  | 
| 1566   static bool classof(const Inst *Inst) { return isClassof(Inst, Nop); } |  | 
| 1567 |  | 
| 1568 private: |  | 
| 1569   InstX8632Nop(Cfg *Func, SizeT Length); |  | 
| 1570 |  | 
| 1571   NopVariant Variant; |  | 
| 1572 }; |  | 
| 1573 |  | 
| 1574 /// Fld - load a value onto the x87 FP stack. |  | 
| 1575 class InstX8632Fld : public InstX8632 { |  | 
| 1576   InstX8632Fld() = delete; |  | 
| 1577   InstX8632Fld(const InstX8632Fld &) = delete; |  | 
| 1578   InstX8632Fld &operator=(const InstX8632Fld &) = delete; |  | 
| 1579 |  | 
| 1580 public: |  | 
| 1581   static InstX8632Fld *create(Cfg *Func, Operand *Src) { |  | 
| 1582     return new (Func->allocate<InstX8632Fld>()) InstX8632Fld(Func, Src); |  | 
| 1583   } |  | 
| 1584   void emit(const Cfg *Func) const override; |  | 
| 1585   void emitIAS(const Cfg *Func) const override; |  | 
| 1586   void dump(const Cfg *Func) const override; |  | 
| 1587   static bool classof(const Inst *Inst) { return isClassof(Inst, Fld); } |  | 
| 1588 |  | 
| 1589 private: |  | 
| 1590   InstX8632Fld(Cfg *Func, Operand *Src); |  | 
| 1591 }; |  | 
| 1592 |  | 
| 1593 /// Fstp - store x87 st(0) into memory and pop st(0). |  | 
| 1594 class InstX8632Fstp : public InstX8632 { |  | 
| 1595   InstX8632Fstp() = delete; |  | 
| 1596   InstX8632Fstp(const InstX8632Fstp &) = delete; |  | 
| 1597   InstX8632Fstp &operator=(const InstX8632Fstp &) = delete; |  | 
| 1598 |  | 
| 1599 public: |  | 
| 1600   static InstX8632Fstp *create(Cfg *Func, Variable *Dest) { |  | 
| 1601     return new (Func->allocate<InstX8632Fstp>()) InstX8632Fstp(Func, Dest); |  | 
| 1602   } |  | 
| 1603   void emit(const Cfg *Func) const override; |  | 
| 1604   void emitIAS(const Cfg *Func) const override; |  | 
| 1605   void dump(const Cfg *Func) const override; |  | 
| 1606   static bool classof(const Inst *Inst) { return isClassof(Inst, Fstp); } |  | 
| 1607 |  | 
| 1608 private: |  | 
| 1609   InstX8632Fstp(Cfg *Func, Variable *Dest); |  | 
| 1610 }; |  | 
| 1611 |  | 
| 1612 class InstX8632Pop : public InstX8632 { |  | 
| 1613   InstX8632Pop() = delete; |  | 
| 1614   InstX8632Pop(const InstX8632Pop &) = delete; |  | 
| 1615   InstX8632Pop &operator=(const InstX8632Pop &) = delete; |  | 
| 1616 |  | 
| 1617 public: |  | 
| 1618   static InstX8632Pop *create(Cfg *Func, Variable *Dest) { |  | 
| 1619     return new (Func->allocate<InstX8632Pop>()) InstX8632Pop(Func, Dest); |  | 
| 1620   } |  | 
| 1621   void emit(const Cfg *Func) const override; |  | 
| 1622   void emitIAS(const Cfg *Func) const override; |  | 
| 1623   void dump(const Cfg *Func) const override; |  | 
| 1624   static bool classof(const Inst *Inst) { return isClassof(Inst, Pop); } |  | 
| 1625 |  | 
| 1626 private: |  | 
| 1627   InstX8632Pop(Cfg *Func, Variable *Dest); |  | 
| 1628 }; |  | 
| 1629 |  | 
| 1630 class InstX8632Push : public InstX8632 { |  | 
| 1631   InstX8632Push() = delete; |  | 
| 1632   InstX8632Push(const InstX8632Push &) = delete; |  | 
| 1633   InstX8632Push &operator=(const InstX8632Push &) = delete; |  | 
| 1634 |  | 
| 1635 public: |  | 
| 1636   static InstX8632Push *create(Cfg *Func, Variable *Source) { |  | 
| 1637     return new (Func->allocate<InstX8632Push>()) InstX8632Push(Func, Source); |  | 
| 1638   } |  | 
| 1639   void emit(const Cfg *Func) const override; |  | 
| 1640   void emitIAS(const Cfg *Func) const override; |  | 
| 1641   void dump(const Cfg *Func) const override; |  | 
| 1642   static bool classof(const Inst *Inst) { return isClassof(Inst, Push); } |  | 
| 1643 |  | 
| 1644 private: |  | 
| 1645   InstX8632Push(Cfg *Func, Variable *Source); |  | 
| 1646 }; |  | 
| 1647 |  | 
| 1648 /// Ret instruction.  Currently only supports the "ret" version that |  | 
| 1649 /// does not pop arguments.  This instruction takes a Source operand |  | 
| 1650 /// (for non-void returning functions) for liveness analysis, though |  | 
| 1651 /// a FakeUse before the ret would do just as well. |  | 
| 1652 class InstX8632Ret : public InstX8632 { |  | 
| 1653   InstX8632Ret() = delete; |  | 
| 1654   InstX8632Ret(const InstX8632Ret &) = delete; |  | 
| 1655   InstX8632Ret &operator=(const InstX8632Ret &) = delete; |  | 
| 1656 |  | 
| 1657 public: |  | 
| 1658   static InstX8632Ret *create(Cfg *Func, Variable *Source = nullptr) { |  | 
| 1659     return new (Func->allocate<InstX8632Ret>()) InstX8632Ret(Func, Source); |  | 
| 1660   } |  | 
| 1661   void emit(const Cfg *Func) const override; |  | 
| 1662   void emitIAS(const Cfg *Func) const override; |  | 
| 1663   void dump(const Cfg *Func) const override; |  | 
| 1664   static bool classof(const Inst *Inst) { return isClassof(Inst, Ret); } |  | 
| 1665 |  | 
| 1666 private: |  | 
| 1667   InstX8632Ret(Cfg *Func, Variable *Source); |  | 
| 1668 }; |  | 
| 1669 |  | 
| 1670 /// Conditional set-byte instruction. |  | 
| 1671 class InstX8632Setcc : public InstX8632 { |  | 
| 1672   InstX8632Setcc() = delete; |  | 
| 1673   InstX8632Setcc(const InstX8632Cmov &) = delete; |  | 
| 1674   InstX8632Setcc &operator=(const InstX8632Setcc &) = delete; |  | 
| 1675 |  | 
| 1676 public: |  | 
| 1677   static InstX8632Setcc *create(Cfg *Func, Variable *Dest, |  | 
| 1678                                 X8632::Traits::Cond::BrCond Cond) { |  | 
| 1679     return new (Func->allocate<InstX8632Setcc>()) |  | 
| 1680         InstX8632Setcc(Func, Dest, Cond); |  | 
| 1681   } |  | 
| 1682   void emit(const Cfg *Func) const override; |  | 
| 1683   void emitIAS(const Cfg *Func) const override; |  | 
| 1684   void dump(const Cfg *Func) const override; |  | 
| 1685   static bool classof(const Inst *Inst) { return isClassof(Inst, Setcc); } |  | 
| 1686 |  | 
| 1687 private: |  | 
| 1688   InstX8632Setcc(Cfg *Func, Variable *Dest, X8632::Traits::Cond::BrCond Cond); |  | 
| 1689 |  | 
| 1690   const X8632::Traits::Cond::BrCond Condition; |  | 
| 1691 }; |  | 
| 1692 |  | 
| 1693 /// Exchanging Add instruction.  Exchanges the first operand (destination |  | 
| 1694 /// operand) with the second operand (source operand), then loads the sum |  | 
| 1695 /// of the two values into the destination operand. The destination may be |  | 
| 1696 /// a register or memory, while the source must be a register. |  | 
| 1697 /// |  | 
| 1698 /// Both the dest and source are updated. The caller should then insert a |  | 
| 1699 /// FakeDef to reflect the second udpate. |  | 
| 1700 class InstX8632Xadd : public InstX8632Lockable { |  | 
| 1701   InstX8632Xadd() = delete; |  | 
| 1702   InstX8632Xadd(const InstX8632Xadd &) = delete; |  | 
| 1703   InstX8632Xadd &operator=(const InstX8632Xadd &) = delete; |  | 
| 1704 |  | 
| 1705 public: |  | 
| 1706   static InstX8632Xadd *create(Cfg *Func, Operand *Dest, Variable *Source, |  | 
| 1707                                bool Locked) { |  | 
| 1708     return new (Func->allocate<InstX8632Xadd>()) |  | 
| 1709         InstX8632Xadd(Func, Dest, Source, Locked); |  | 
| 1710   } |  | 
| 1711   void emit(const Cfg *Func) const override; |  | 
| 1712   void emitIAS(const Cfg *Func) const override; |  | 
| 1713   void dump(const Cfg *Func) const override; |  | 
| 1714   static bool classof(const Inst *Inst) { return isClassof(Inst, Xadd); } |  | 
| 1715 |  | 
| 1716 private: |  | 
| 1717   InstX8632Xadd(Cfg *Func, Operand *Dest, Variable *Source, bool Locked); |  | 
| 1718 }; |  | 
| 1719 |  | 
| 1720 /// Exchange instruction.  Exchanges the first operand (destination |  | 
| 1721 /// operand) with the second operand (source operand). At least one of |  | 
| 1722 /// the operands must be a register (and the other can be reg or mem). |  | 
| 1723 /// Both the Dest and Source are updated. If there is a memory operand, |  | 
| 1724 /// then the instruction is automatically "locked" without the need for |  | 
| 1725 /// a lock prefix. |  | 
| 1726 class InstX8632Xchg : public InstX8632 { |  | 
| 1727   InstX8632Xchg() = delete; |  | 
| 1728   InstX8632Xchg(const InstX8632Xchg &) = delete; |  | 
| 1729   InstX8632Xchg &operator=(const InstX8632Xchg &) = delete; |  | 
| 1730 |  | 
| 1731 public: |  | 
| 1732   static InstX8632Xchg *create(Cfg *Func, Operand *Dest, Variable *Source) { |  | 
| 1733     return new (Func->allocate<InstX8632Xchg>()) |  | 
| 1734         InstX8632Xchg(Func, Dest, Source); |  | 
| 1735   } |  | 
| 1736   void emit(const Cfg *Func) const override; |  | 
| 1737   void emitIAS(const Cfg *Func) const override; |  | 
| 1738   void dump(const Cfg *Func) const override; |  | 
| 1739   static bool classof(const Inst *Inst) { return isClassof(Inst, Xchg); } |  | 
| 1740 |  | 
| 1741 private: |  | 
| 1742   InstX8632Xchg(Cfg *Func, Operand *Dest, Variable *Source); |  | 
| 1743 }; |  | 
| 1744 |  | 
| 1745 /// Declare partial template specializations of emit() methods that |  | 
| 1746 /// already have default implementations.  Without this, there is the |  | 
| 1747 /// possibility of ODR violations and link errors. |  | 
| 1748 template <> void InstX8632Addss::emit(const Cfg *Func) const; |  | 
| 1749 template <> void InstX8632Blendvps::emit(const Cfg *Func) const; |  | 
| 1750 template <> void InstX8632Cbwdq::emit(const Cfg *Func) const; |  | 
| 1751 template <> void InstX8632Div::emit(const Cfg *Func) const; |  | 
| 1752 template <> void InstX8632Divss::emit(const Cfg *Func) const; |  | 
| 1753 template <> void InstX8632Idiv::emit(const Cfg *Func) const; |  | 
| 1754 template <> void InstX8632Imul::emit(const Cfg *Func) const; |  | 
| 1755 template <> void InstX8632Lea::emit(const Cfg *Func) const; |  | 
| 1756 template <> void InstX8632Mulss::emit(const Cfg *Func) const; |  | 
| 1757 template <> void InstX8632Padd::emit(const Cfg *Func) const; |  | 
| 1758 template <> void InstX8632Pblendvb::emit(const Cfg *Func) const; |  | 
| 1759 template <> void InstX8632Pcmpeq::emit(const Cfg *Func) const; |  | 
| 1760 template <> void InstX8632Pcmpgt::emit(const Cfg *Func) const; |  | 
| 1761 template <> void InstX8632Pextr::emit(const Cfg *Func) const; |  | 
| 1762 template <> void InstX8632Pinsr::emit(const Cfg *Func) const; |  | 
| 1763 template <> void InstX8632Pmull::emit(const Cfg *Func) const; |  | 
| 1764 template <> void InstX8632Pmuludq::emit(const Cfg *Func) const; |  | 
| 1765 template <> void InstX8632Psll::emit(const Cfg *Func) const; |  | 
| 1766 template <> void InstX8632Psra::emit(const Cfg *Func) const; |  | 
| 1767 template <> void InstX8632Psrl::emit(const Cfg *Func) const; |  | 
| 1768 template <> void InstX8632Psub::emit(const Cfg *Func) const; |  | 
| 1769 template <> void InstX8632Sqrtss::emit(const Cfg *Func) const; |  | 
| 1770 template <> void InstX8632Subss::emit(const Cfg *Func) const; |  | 
| 1771 |  | 
| 1772 template <> void InstX8632Blendvps::emitIAS(const Cfg *Func) const; |  | 
| 1773 template <> void InstX8632Cbwdq::emitIAS(const Cfg *Func) const; |  | 
| 1774 template <> void InstX8632Div::emitIAS(const Cfg *Func) const; |  | 
| 1775 template <> void InstX8632Idiv::emitIAS(const Cfg *Func) const; |  | 
| 1776 template <> void InstX8632Imul::emitIAS(const Cfg *Func) const; |  | 
| 1777 template <> void InstX8632Insertps::emitIAS(const Cfg *Func) const; |  | 
| 1778 template <> void InstX8632Movd::emitIAS(const Cfg *Func) const; |  | 
| 1779 template <> void InstX8632MovssRegs::emitIAS(const Cfg *Func) const; |  | 
| 1780 template <> void InstX8632Pblendvb::emitIAS(const Cfg *Func) const; |  | 
| 1781 template <> void InstX8632Pextr::emitIAS(const Cfg *Func) const; |  | 
| 1782 template <> void InstX8632Pinsr::emitIAS(const Cfg *Func) const; |  | 
| 1783 template <> void InstX8632Movsx::emitIAS(const Cfg *Func) const; |  | 
| 1784 template <> void InstX8632Movzx::emitIAS(const Cfg *Func) const; |  | 
| 1785 template <> void InstX8632Pmull::emitIAS(const Cfg *Func) const; |  | 
| 1786 template <> void InstX8632Pshufd::emitIAS(const Cfg *Func) const; |  | 
| 1787 template <> void InstX8632Shufps::emitIAS(const Cfg *Func) const; |  | 
| 1788 |  | 
| 1789 } // end of namespace Ice |  | 
| 1790 |  | 
| 1791 #endif // SUBZERO_SRC_ICEINSTX8632_H | 37 #endif // SUBZERO_SRC_ICEINSTX8632_H | 
| OLD | NEW | 
|---|