Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 //===- subzero/src/IceInstX8632.h - Low-level x86 instructions --*- C++ -*-===// | 1 //===- subzero/src/IceInstX8632.h - Low-level x86 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 // This file declares the InstX8632 and OperandX8632 classes and | 10 // This file declares the InstX8632 and OperandX8632 classes and |
| (...skipping 12 matching lines...) Expand all Loading... | |
| 23 #include "IceInstX8632.def" | 23 #include "IceInstX8632.def" |
| 24 #include "IceOperand.h" | 24 #include "IceOperand.h" |
| 25 | 25 |
| 26 namespace Ice { | 26 namespace Ice { |
| 27 | 27 |
| 28 class TargetX8632; | 28 class TargetX8632; |
| 29 | 29 |
| 30 // OperandX8632 extends the Operand hierarchy. Its subclasses are | 30 // OperandX8632 extends the Operand hierarchy. Its subclasses are |
| 31 // OperandX8632Mem and VariableSplit. | 31 // OperandX8632Mem and VariableSplit. |
| 32 class OperandX8632 : public Operand { | 32 class OperandX8632 : public Operand { |
| 33 OperandX8632(const OperandX8632 &) = delete; | |
| 34 OperandX8632 &operator=(const OperandX8632 &) = delete; | |
| 35 | |
| 33 public: | 36 public: |
| 34 enum OperandKindX8632 { | 37 enum OperandKindX8632 { |
| 35 k__Start = Operand::kTarget, | 38 k__Start = Operand::kTarget, |
| 36 kMem, | 39 kMem, |
| 37 kSplit | 40 kSplit |
| 38 }; | 41 }; |
| 39 using Operand::dump; | 42 using Operand::dump; |
| 40 void dump(const Cfg *, Ostream &Str) const override { | 43 void dump(const Cfg *, Ostream &Str) const override { |
| 41 Str << "<OperandX8632>"; | 44 Str << "<OperandX8632>"; |
| 42 } | 45 } |
| 43 | 46 |
| 44 protected: | 47 protected: |
| 45 OperandX8632(OperandKindX8632 Kind, Type Ty) | 48 OperandX8632(OperandKindX8632 Kind, Type Ty) |
| 46 : Operand(static_cast<OperandKind>(Kind), Ty) {} | 49 : Operand(static_cast<OperandKind>(Kind), Ty) {} |
| 47 ~OperandX8632() override {} | 50 ~OperandX8632() override {} |
| 48 | |
| 49 private: | |
| 50 OperandX8632(const OperandX8632 &) = delete; | |
| 51 OperandX8632 &operator=(const OperandX8632 &) = delete; | |
| 52 }; | 51 }; |
| 53 | 52 |
| 54 // OperandX8632Mem represents the m32 addressing mode, with optional | 53 // OperandX8632Mem represents the m32 addressing mode, with optional |
| 55 // base and index registers, a constant offset, and a fixed shift | 54 // base and index registers, a constant offset, and a fixed shift |
| 56 // value for the index register. | 55 // value for the index register. |
| 57 class OperandX8632Mem : public OperandX8632 { | 56 class OperandX8632Mem : public OperandX8632 { |
| 57 OperandX8632Mem(const OperandX8632Mem &) = delete; | |
| 58 OperandX8632Mem &operator=(const OperandX8632Mem &) = delete; | |
| 59 | |
| 58 public: | 60 public: |
| 59 enum SegmentRegisters { | 61 enum SegmentRegisters { |
| 60 DefaultSegment = -1, | 62 DefaultSegment = -1, |
| 61 #define X(val, name, prefix) val, | 63 #define X(val, name, prefix) val, |
| 62 SEG_REGX8632_TABLE | 64 SEG_REGX8632_TABLE |
| 63 #undef X | 65 #undef X |
| 64 SegReg_NUM | 66 SegReg_NUM |
| 65 }; | 67 }; |
| 66 static OperandX8632Mem *create(Cfg *Func, Type Ty, Variable *Base, | 68 static OperandX8632Mem *create(Cfg *Func, Type Ty, Variable *Base, |
| 67 Constant *Offset, Variable *Index = NULL, | 69 Constant *Offset, Variable *Index = NULL, |
| (...skipping 13 matching lines...) Expand all Loading... | |
| 81 using OperandX8632::dump; | 83 using OperandX8632::dump; |
| 82 void dump(const Cfg *Func, Ostream &Str) const override; | 84 void dump(const Cfg *Func, Ostream &Str) const override; |
| 83 | 85 |
| 84 static bool classof(const Operand *Operand) { | 86 static bool classof(const Operand *Operand) { |
| 85 return Operand->getKind() == static_cast<OperandKind>(kMem); | 87 return Operand->getKind() == static_cast<OperandKind>(kMem); |
| 86 } | 88 } |
| 87 | 89 |
| 88 private: | 90 private: |
| 89 OperandX8632Mem(Cfg *Func, Type Ty, Variable *Base, Constant *Offset, | 91 OperandX8632Mem(Cfg *Func, Type Ty, Variable *Base, Constant *Offset, |
| 90 Variable *Index, uint16_t Shift, SegmentRegisters SegmentReg); | 92 Variable *Index, uint16_t Shift, SegmentRegisters SegmentReg); |
| 91 OperandX8632Mem(const OperandX8632Mem &) = delete; | |
| 92 OperandX8632Mem &operator=(const OperandX8632Mem &) = delete; | |
| 93 ~OperandX8632Mem() override {} | 93 ~OperandX8632Mem() override {} |
| 94 Variable *Base; | 94 Variable *Base; |
| 95 Constant *Offset; | 95 Constant *Offset; |
| 96 Variable *Index; | 96 Variable *Index; |
| 97 uint16_t Shift; | 97 uint16_t Shift; |
| 98 SegmentRegisters SegmentReg : 16; | 98 SegmentRegisters SegmentReg : 16; |
| 99 }; | 99 }; |
| 100 | 100 |
| 101 // VariableSplit is a way to treat an f64 memory location as a pair | 101 // VariableSplit is a way to treat an f64 memory location as a pair |
| 102 // of i32 locations (Low and High). This is needed for some cases | 102 // of i32 locations (Low and High). This is needed for some cases |
| 103 // of the Bitcast instruction. Since it's not possible for integer | 103 // of the Bitcast instruction. Since it's not possible for integer |
| 104 // registers to access the XMM registers and vice versa, the | 104 // registers to access the XMM registers and vice versa, the |
| 105 // lowering forces the f64 to be spilled to the stack and then | 105 // lowering forces the f64 to be spilled to the stack and then |
| 106 // accesses through the VariableSplit. | 106 // accesses through the VariableSplit. |
| 107 class VariableSplit : public OperandX8632 { | 107 class VariableSplit : public OperandX8632 { |
| 108 VariableSplit(const VariableSplit &) = delete; | |
| 109 VariableSplit &operator=(const VariableSplit &) = delete; | |
| 110 | |
| 108 public: | 111 public: |
| 109 enum Portion { | 112 enum Portion { |
| 110 Low, | 113 Low, |
| 111 High | 114 High |
| 112 }; | 115 }; |
| 113 static VariableSplit *create(Cfg *Func, Variable *Var, Portion Part) { | 116 static VariableSplit *create(Cfg *Func, Variable *Var, Portion Part) { |
| 114 return new (Func->allocate<VariableSplit>()) VariableSplit(Func, Var, Part); | 117 return new (Func->allocate<VariableSplit>()) VariableSplit(Func, Var, Part); |
| 115 } | 118 } |
| 116 int32_t getOffset() const { return Part == High ? 4 : 0; } | 119 int32_t getOffset() const { return Part == High ? 4 : 0; } |
| 117 | 120 |
| 118 x86::Address toAsmAddress(const Cfg *Func) const; | 121 x86::Address toAsmAddress(const Cfg *Func) const; |
| 119 void emit(const Cfg *Func) const override; | 122 void emit(const Cfg *Func) const override; |
| 120 using OperandX8632::dump; | 123 using OperandX8632::dump; |
| 121 void dump(const Cfg *Func, Ostream &Str) const override; | 124 void dump(const Cfg *Func, Ostream &Str) const override; |
| 122 | 125 |
| 123 static bool classof(const Operand *Operand) { | 126 static bool classof(const Operand *Operand) { |
| 124 return Operand->getKind() == static_cast<OperandKind>(kSplit); | 127 return Operand->getKind() == static_cast<OperandKind>(kSplit); |
| 125 } | 128 } |
| 126 | 129 |
| 127 private: | 130 private: |
| 128 VariableSplit(Cfg *Func, Variable *Var, Portion Part) | 131 VariableSplit(Cfg *Func, Variable *Var, Portion Part) |
| 129 : OperandX8632(kSplit, IceType_i32), Func(Func), Var(Var), Part(Part) { | 132 : OperandX8632(kSplit, IceType_i32), Func(Func), Var(Var), Part(Part) { |
| 130 assert(Var->getType() == IceType_f64); | 133 assert(Var->getType() == IceType_f64); |
| 131 Vars = Func->allocateArrayOf<Variable *>(1); | 134 Vars = Func->allocateArrayOf<Variable *>(1); |
| 132 Vars[0] = Var; | 135 Vars[0] = Var; |
| 133 NumVars = 1; | 136 NumVars = 1; |
| 134 } | 137 } |
| 135 VariableSplit(const VariableSplit &) = delete; | |
| 136 VariableSplit &operator=(const VariableSplit &) = delete; | |
| 137 ~VariableSplit() override { Func->deallocateArrayOf<Variable *>(Vars); } | 138 ~VariableSplit() override { Func->deallocateArrayOf<Variable *>(Vars); } |
| 138 Cfg *Func; // Held only for the destructor. | 139 Cfg *Func; // Held only for the destructor. |
| 139 Variable *Var; | 140 Variable *Var; |
| 140 Portion Part; | 141 Portion Part; |
| 141 }; | 142 }; |
| 142 | 143 |
| 143 // SpillVariable decorates a Variable by linking it to another | 144 // SpillVariable decorates a Variable by linking it to another |
| 144 // Variable. When stack frame offsets are computed, the SpillVariable | 145 // Variable. When stack frame offsets are computed, the SpillVariable |
| 145 // is given a distinct stack slot only if its linked Variable has a | 146 // is given a distinct stack slot only if its linked Variable has a |
| 146 // register. If the linked Variable has a stack slot, then the | 147 // register. If the linked Variable has a stack slot, then the |
| 147 // Variable and SpillVariable share that slot. | 148 // Variable and SpillVariable share that slot. |
| 148 class SpillVariable : public Variable { | 149 class SpillVariable : public Variable { |
|
Karl
2014/10/15 19:59:12
What about delete for default constructor/assignme
Jim Stichnoth
2014/10/15 20:23:43
Done.
| |
| 149 public: | 150 public: |
| 150 static SpillVariable *create(Cfg *Func, Type Ty, SizeT Index, | 151 static SpillVariable *create(Cfg *Func, Type Ty, SizeT Index, |
| 151 const IceString &Name) { | 152 const IceString &Name) { |
| 152 return new (Func->allocate<SpillVariable>()) SpillVariable(Ty, Index, Name); | 153 return new (Func->allocate<SpillVariable>()) SpillVariable(Ty, Index, Name); |
| 153 } | 154 } |
| 154 const static OperandKind SpillVariableKind = | 155 const static OperandKind SpillVariableKind = |
| 155 static_cast<OperandKind>(kVariable_Target); | 156 static_cast<OperandKind>(kVariable_Target); |
| 156 static bool classof(const Operand *Operand) { | 157 static bool classof(const Operand *Operand) { |
| 157 return Operand->getKind() == SpillVariableKind; | 158 return Operand->getKind() == SpillVariableKind; |
| 158 } | 159 } |
| 159 void setLinkedTo(Variable *Var) { LinkedTo = Var; } | 160 void setLinkedTo(Variable *Var) { LinkedTo = Var; } |
| 160 Variable *getLinkedTo() const { return LinkedTo; } | 161 Variable *getLinkedTo() const { return LinkedTo; } |
| 161 // Inherit dump() and emit() from Variable. | 162 // Inherit dump() and emit() from Variable. |
| 162 private: | 163 private: |
| 163 SpillVariable(Type Ty, SizeT Index, const IceString &Name) | 164 SpillVariable(Type Ty, SizeT Index, const IceString &Name) |
| 164 : Variable(SpillVariableKind, Ty, Index, Name), LinkedTo(NULL) {} | 165 : Variable(SpillVariableKind, Ty, Index, Name), LinkedTo(NULL) {} |
| 165 Variable *LinkedTo; | 166 Variable *LinkedTo; |
| 166 }; | 167 }; |
| 167 | 168 |
| 168 class InstX8632 : public InstTarget { | 169 class InstX8632 : public InstTarget { |
| 170 InstX8632(const InstX8632 &) = delete; | |
| 171 InstX8632 &operator=(const InstX8632 &) = delete; | |
| 172 | |
| 169 public: | 173 public: |
| 170 enum InstKindX8632 { | 174 enum InstKindX8632 { |
| 171 k__Start = Inst::Target, | 175 k__Start = Inst::Target, |
| 172 Adc, | 176 Adc, |
| 173 Add, | 177 Add, |
| 174 Addps, | 178 Addps, |
| 175 Addss, | 179 Addss, |
| 176 Adjuststack, | 180 Adjuststack, |
| 177 And, | 181 And, |
| 178 Blendvps, | 182 Blendvps, |
| (...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 258 static const char *getWidthString(Type Ty); | 262 static const char *getWidthString(Type Ty); |
| 259 void dump(const Cfg *Func) const override; | 263 void dump(const Cfg *Func) const override; |
| 260 | 264 |
| 261 protected: | 265 protected: |
| 262 InstX8632(Cfg *Func, InstKindX8632 Kind, SizeT Maxsrcs, Variable *Dest) | 266 InstX8632(Cfg *Func, InstKindX8632 Kind, SizeT Maxsrcs, Variable *Dest) |
| 263 : InstTarget(Func, static_cast<InstKind>(Kind), Maxsrcs, Dest) {} | 267 : InstTarget(Func, static_cast<InstKind>(Kind), Maxsrcs, Dest) {} |
| 264 ~InstX8632() override {} | 268 ~InstX8632() override {} |
| 265 static bool isClassof(const Inst *Inst, InstKindX8632 MyKind) { | 269 static bool isClassof(const Inst *Inst, InstKindX8632 MyKind) { |
| 266 return Inst->getKind() == static_cast<InstKind>(MyKind); | 270 return Inst->getKind() == static_cast<InstKind>(MyKind); |
| 267 } | 271 } |
| 268 | |
| 269 private: | |
| 270 InstX8632(const InstX8632 &) = delete; | |
| 271 InstX8632 &operator=(const InstX8632 &) = delete; | |
| 272 }; | 272 }; |
| 273 | 273 |
| 274 // InstX8632Label represents an intra-block label that is the | 274 // InstX8632Label represents an intra-block label that is the |
| 275 // target of an intra-block branch. These are used for lowering i1 | 275 // target of an intra-block branch. These are used for lowering i1 |
| 276 // calculations, Select instructions, and 64-bit compares on a 32-bit | 276 // calculations, Select instructions, and 64-bit compares on a 32-bit |
| 277 // architecture, without basic block splitting. Basic block splitting | 277 // architecture, without basic block splitting. Basic block splitting |
| 278 // is not so desirable for several reasons, one of which is the impact | 278 // is not so desirable for several reasons, one of which is the impact |
| 279 // on decisions based on whether a variable's live range spans | 279 // on decisions based on whether a variable's live range spans |
| 280 // multiple basic blocks. | 280 // multiple basic blocks. |
| 281 // | 281 // |
| (...skipping 20 matching lines...) Expand all Loading... | |
| 302 // FakeUse(c) | 302 // FakeUse(c) |
| 303 // L1: | 303 // L1: |
| 304 // mov c, y | 304 // mov c, y |
| 305 // L2: | 305 // L2: |
| 306 // | 306 // |
| 307 // The down-side is that "mov c, x" can never be dead-code eliminated | 307 // The down-side is that "mov c, x" can never be dead-code eliminated |
| 308 // even if there are no uses of c. As unlikely as this situation is, | 308 // even if there are no uses of c. As unlikely as this situation is, |
| 309 // it may be prevented by running dead code elimination before | 309 // it may be prevented by running dead code elimination before |
| 310 // lowering. | 310 // lowering. |
| 311 class InstX8632Label : public InstX8632 { | 311 class InstX8632Label : public InstX8632 { |
| 312 InstX8632Label(const InstX8632Label &) = delete; | |
| 313 InstX8632Label &operator=(const InstX8632Label &) = delete; | |
| 314 | |
| 312 public: | 315 public: |
| 313 static InstX8632Label *create(Cfg *Func, TargetX8632 *Target) { | 316 static InstX8632Label *create(Cfg *Func, TargetX8632 *Target) { |
| 314 return new (Func->allocate<InstX8632Label>()) InstX8632Label(Func, Target); | 317 return new (Func->allocate<InstX8632Label>()) InstX8632Label(Func, Target); |
| 315 } | 318 } |
| 316 uint32_t getEmitInstCount() const override { return 0; } | 319 uint32_t getEmitInstCount() const override { return 0; } |
| 317 IceString getName(const Cfg *Func) const; | 320 IceString getName(const Cfg *Func) const; |
| 318 void emit(const Cfg *Func) const override; | 321 void emit(const Cfg *Func) const override; |
| 319 void dump(const Cfg *Func) const override; | 322 void dump(const Cfg *Func) const override; |
| 320 | 323 |
| 321 private: | 324 private: |
| 322 InstX8632Label(Cfg *Func, TargetX8632 *Target); | 325 InstX8632Label(Cfg *Func, TargetX8632 *Target); |
| 323 InstX8632Label(const InstX8632Label &) = delete; | |
| 324 InstX8632Label &operator=(const InstX8632Label &) = delete; | |
| 325 ~InstX8632Label() override {} | 326 ~InstX8632Label() override {} |
| 326 SizeT Number; // used only for unique label string generation | 327 SizeT Number; // used only for unique label string generation |
| 327 }; | 328 }; |
| 328 | 329 |
| 329 // Conditional and unconditional branch instruction. | 330 // Conditional and unconditional branch instruction. |
| 330 class InstX8632Br : public InstX8632 { | 331 class InstX8632Br : public InstX8632 { |
| 332 InstX8632Br(const InstX8632Br &) = delete; | |
| 333 InstX8632Br &operator=(const InstX8632Br &) = delete; | |
| 334 | |
| 331 public: | 335 public: |
| 332 // Create a conditional branch to a node. | 336 // Create a conditional branch to a node. |
| 333 static InstX8632Br *create(Cfg *Func, CfgNode *TargetTrue, | 337 static InstX8632Br *create(Cfg *Func, CfgNode *TargetTrue, |
| 334 CfgNode *TargetFalse, CondX86::BrCond Condition) { | 338 CfgNode *TargetFalse, CondX86::BrCond Condition) { |
| 335 const InstX8632Label *NoLabel = NULL; | 339 const InstX8632Label *NoLabel = NULL; |
| 336 return new (Func->allocate<InstX8632Br>()) | 340 return new (Func->allocate<InstX8632Br>()) |
| 337 InstX8632Br(Func, TargetTrue, TargetFalse, NoLabel, Condition); | 341 InstX8632Br(Func, TargetTrue, TargetFalse, NoLabel, Condition); |
| 338 } | 342 } |
| 339 // Create an unconditional branch to a node. | 343 // Create an unconditional branch to a node. |
| 340 static InstX8632Br *create(Cfg *Func, CfgNode *Target) { | 344 static InstX8632Br *create(Cfg *Func, CfgNode *Target) { |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 375 ++Sum; | 379 ++Sum; |
| 376 return Sum; | 380 return Sum; |
| 377 } | 381 } |
| 378 void emit(const Cfg *Func) const override; | 382 void emit(const Cfg *Func) const override; |
| 379 void dump(const Cfg *Func) const override; | 383 void dump(const Cfg *Func) const override; |
| 380 static bool classof(const Inst *Inst) { return isClassof(Inst, Br); } | 384 static bool classof(const Inst *Inst) { return isClassof(Inst, Br); } |
| 381 | 385 |
| 382 private: | 386 private: |
| 383 InstX8632Br(Cfg *Func, const CfgNode *TargetTrue, const CfgNode *TargetFalse, | 387 InstX8632Br(Cfg *Func, const CfgNode *TargetTrue, const CfgNode *TargetFalse, |
| 384 const InstX8632Label *Label, CondX86::BrCond Condition); | 388 const InstX8632Label *Label, CondX86::BrCond Condition); |
| 385 InstX8632Br(const InstX8632Br &) = delete; | |
| 386 InstX8632Br &operator=(const InstX8632Br &) = delete; | |
| 387 ~InstX8632Br() override {} | 389 ~InstX8632Br() override {} |
| 388 CondX86::BrCond Condition; | 390 CondX86::BrCond Condition; |
| 389 const CfgNode *TargetTrue; | 391 const CfgNode *TargetTrue; |
| 390 const CfgNode *TargetFalse; | 392 const CfgNode *TargetFalse; |
| 391 const InstX8632Label *Label; // Intra-block branch target | 393 const InstX8632Label *Label; // Intra-block branch target |
| 392 }; | 394 }; |
| 393 | 395 |
| 394 // AdjustStack instruction - subtracts esp by the given amount and | 396 // AdjustStack instruction - subtracts esp by the given amount and |
| 395 // updates the stack offset during code emission. | 397 // updates the stack offset during code emission. |
| 396 class InstX8632AdjustStack : public InstX8632 { | 398 class InstX8632AdjustStack : public InstX8632 { |
| 399 InstX8632AdjustStack(const InstX8632AdjustStack &) = delete; | |
| 400 InstX8632AdjustStack &operator=(const InstX8632AdjustStack &) = delete; | |
| 401 | |
| 397 public: | 402 public: |
| 398 static InstX8632AdjustStack *create(Cfg *Func, SizeT Amount, Variable *Esp) { | 403 static InstX8632AdjustStack *create(Cfg *Func, SizeT Amount, Variable *Esp) { |
| 399 return new (Func->allocate<InstX8632AdjustStack>()) | 404 return new (Func->allocate<InstX8632AdjustStack>()) |
| 400 InstX8632AdjustStack(Func, Amount, Esp); | 405 InstX8632AdjustStack(Func, Amount, Esp); |
| 401 } | 406 } |
| 402 void emit(const Cfg *Func) const override; | 407 void emit(const Cfg *Func) const override; |
| 403 void emitIAS(const Cfg *Func) const override; | 408 void emitIAS(const Cfg *Func) const override; |
| 404 void dump(const Cfg *Func) const override; | 409 void dump(const Cfg *Func) const override; |
| 405 static bool classof(const Inst *Inst) { return isClassof(Inst, Adjuststack); } | 410 static bool classof(const Inst *Inst) { return isClassof(Inst, Adjuststack); } |
| 406 | 411 |
| 407 private: | 412 private: |
| 408 InstX8632AdjustStack(Cfg *Func, SizeT Amount, Variable *Esp); | 413 InstX8632AdjustStack(Cfg *Func, SizeT Amount, Variable *Esp); |
| 409 InstX8632AdjustStack(const InstX8632AdjustStack &) = delete; | |
| 410 InstX8632AdjustStack &operator=(const InstX8632AdjustStack &) = delete; | |
| 411 SizeT Amount; | 414 SizeT Amount; |
| 412 }; | 415 }; |
| 413 | 416 |
| 414 // Call instruction. Arguments should have already been pushed. | 417 // Call instruction. Arguments should have already been pushed. |
| 415 class InstX8632Call : public InstX8632 { | 418 class InstX8632Call : public InstX8632 { |
| 419 InstX8632Call(const InstX8632Call &) = delete; | |
| 420 InstX8632Call &operator=(const InstX8632Call &) = delete; | |
| 421 | |
| 416 public: | 422 public: |
| 417 static InstX8632Call *create(Cfg *Func, Variable *Dest, Operand *CallTarget) { | 423 static InstX8632Call *create(Cfg *Func, Variable *Dest, Operand *CallTarget) { |
| 418 return new (Func->allocate<InstX8632Call>()) | 424 return new (Func->allocate<InstX8632Call>()) |
| 419 InstX8632Call(Func, Dest, CallTarget); | 425 InstX8632Call(Func, Dest, CallTarget); |
| 420 } | 426 } |
| 421 Operand *getCallTarget() const { return getSrc(0); } | 427 Operand *getCallTarget() const { return getSrc(0); } |
| 422 void emit(const Cfg *Func) const override; | 428 void emit(const Cfg *Func) const override; |
| 423 void dump(const Cfg *Func) const override; | 429 void dump(const Cfg *Func) const override; |
| 424 static bool classof(const Inst *Inst) { return isClassof(Inst, Call); } | 430 static bool classof(const Inst *Inst) { return isClassof(Inst, Call); } |
| 425 | 431 |
| 426 private: | 432 private: |
| 427 InstX8632Call(Cfg *Func, Variable *Dest, Operand *CallTarget); | 433 InstX8632Call(Cfg *Func, Variable *Dest, Operand *CallTarget); |
| 428 InstX8632Call(const InstX8632Call &) = delete; | |
| 429 InstX8632Call &operator=(const InstX8632Call &) = delete; | |
| 430 ~InstX8632Call() override {} | 434 ~InstX8632Call() override {} |
| 431 }; | 435 }; |
| 432 | 436 |
| 433 // Emit a one-operand (GPR) instruction. | 437 // Emit a one-operand (GPR) instruction. |
| 434 void emitIASOpTyGPR(const Cfg *Func, Type Ty, const Operand *Var, | 438 void emitIASOpTyGPR(const Cfg *Func, Type Ty, const Operand *Var, |
| 435 const x86::AssemblerX86::GPREmitterOneOp &Emitter); | 439 const x86::AssemblerX86::GPREmitterOneOp &Emitter); |
| 436 | 440 |
| 437 // Instructions of the form x := op(x). | 441 // Instructions of the form x := op(x). |
| 438 template <InstX8632::InstKindX8632 K> | 442 template <InstX8632::InstKindX8632 K> |
| 439 class InstX8632InplaceopGPR : public InstX8632 { | 443 class InstX8632InplaceopGPR : public InstX8632 { |
| 444 InstX8632InplaceopGPR(const InstX8632InplaceopGPR &) = delete; | |
| 445 InstX8632InplaceopGPR &operator=(const InstX8632InplaceopGPR &) = delete; | |
| 446 | |
| 440 public: | 447 public: |
| 441 static InstX8632InplaceopGPR *create(Cfg *Func, Operand *SrcDest) { | 448 static InstX8632InplaceopGPR *create(Cfg *Func, Operand *SrcDest) { |
| 442 return new (Func->allocate<InstX8632InplaceopGPR>()) | 449 return new (Func->allocate<InstX8632InplaceopGPR>()) |
| 443 InstX8632InplaceopGPR(Func, SrcDest); | 450 InstX8632InplaceopGPR(Func, SrcDest); |
| 444 } | 451 } |
| 445 void emit(const Cfg *Func) const override { | 452 void emit(const Cfg *Func) const override { |
| 446 Ostream &Str = Func->getContext()->getStrEmit(); | 453 Ostream &Str = Func->getContext()->getStrEmit(); |
| 447 assert(getSrcSize() == 1); | 454 assert(getSrcSize() == 1); |
| 448 Str << "\t" << Opcode << "\t"; | 455 Str << "\t" << Opcode << "\t"; |
| 449 getSrc(0)->emit(Func); | 456 getSrc(0)->emit(Func); |
| (...skipping 11 matching lines...) Expand all Loading... | |
| 461 Str << " = " << Opcode << "." << getDest()->getType() << " "; | 468 Str << " = " << Opcode << "." << getDest()->getType() << " "; |
| 462 dumpSources(Func); | 469 dumpSources(Func); |
| 463 } | 470 } |
| 464 static bool classof(const Inst *Inst) { return isClassof(Inst, K); } | 471 static bool classof(const Inst *Inst) { return isClassof(Inst, K); } |
| 465 | 472 |
| 466 private: | 473 private: |
| 467 InstX8632InplaceopGPR(Cfg *Func, Operand *SrcDest) | 474 InstX8632InplaceopGPR(Cfg *Func, Operand *SrcDest) |
| 468 : InstX8632(Func, K, 1, llvm::dyn_cast<Variable>(SrcDest)) { | 475 : InstX8632(Func, K, 1, llvm::dyn_cast<Variable>(SrcDest)) { |
| 469 addSource(SrcDest); | 476 addSource(SrcDest); |
| 470 } | 477 } |
| 471 InstX8632InplaceopGPR(const InstX8632InplaceopGPR &) = delete; | |
| 472 InstX8632InplaceopGPR &operator=(const InstX8632InplaceopGPR &) = delete; | |
| 473 ~InstX8632InplaceopGPR() override {} | 478 ~InstX8632InplaceopGPR() override {} |
| 474 static const char *Opcode; | 479 static const char *Opcode; |
| 475 static const x86::AssemblerX86::GPREmitterOneOp Emitter; | 480 static const x86::AssemblerX86::GPREmitterOneOp Emitter; |
| 476 }; | 481 }; |
| 477 | 482 |
| 478 // Emit a two-operand (GPR) instruction, where the dest operand is a | 483 // Emit a two-operand (GPR) instruction, where the dest operand is a |
| 479 // Variable that's guaranteed to be a register. | 484 // Variable that's guaranteed to be a register. |
| 480 void emitIASRegOpTyGPR(const Cfg *Func, Type Ty, const Variable *Dst, | 485 void emitIASRegOpTyGPR(const Cfg *Func, Type Ty, const Variable *Dst, |
| 481 const Operand *Src, | 486 const Operand *Src, |
| 482 const x86::AssemblerX86::GPREmitterRegOp &Emitter); | 487 const x86::AssemblerX86::GPREmitterRegOp &Emitter); |
| 483 | 488 |
| 484 // Instructions of the form x := op(y) | 489 // Instructions of the form x := op(y) |
| 485 template <InstX8632::InstKindX8632 K> | 490 template <InstX8632::InstKindX8632 K> |
| 486 class InstX8632UnaryopGPR : public InstX8632 { | 491 class InstX8632UnaryopGPR : public InstX8632 { |
| 492 InstX8632UnaryopGPR(const InstX8632UnaryopGPR &) = delete; | |
| 493 InstX8632UnaryopGPR &operator=(const InstX8632UnaryopGPR &) = delete; | |
| 494 | |
| 487 public: | 495 public: |
| 488 static InstX8632UnaryopGPR *create(Cfg *Func, Variable *Dest, Operand *Src) { | 496 static InstX8632UnaryopGPR *create(Cfg *Func, Variable *Dest, Operand *Src) { |
| 489 return new (Func->allocate<InstX8632UnaryopGPR>()) | 497 return new (Func->allocate<InstX8632UnaryopGPR>()) |
| 490 InstX8632UnaryopGPR(Func, Dest, Src); | 498 InstX8632UnaryopGPR(Func, Dest, Src); |
| 491 } | 499 } |
| 492 void emit(const Cfg *Func) const override { | 500 void emit(const Cfg *Func) const override { |
| 493 Ostream &Str = Func->getContext()->getStrEmit(); | 501 Ostream &Str = Func->getContext()->getStrEmit(); |
| 494 assert(getSrcSize() == 1); | 502 assert(getSrcSize() == 1); |
| 495 Str << "\t" << Opcode << "\t"; | 503 Str << "\t" << Opcode << "\t"; |
| 496 getDest()->emit(Func); | 504 getDest()->emit(Func); |
| (...skipping 14 matching lines...) Expand all Loading... | |
| 511 Str << " = " << Opcode << "." << getDest()->getType() << " "; | 519 Str << " = " << Opcode << "." << getDest()->getType() << " "; |
| 512 dumpSources(Func); | 520 dumpSources(Func); |
| 513 } | 521 } |
| 514 static bool classof(const Inst *Inst) { return isClassof(Inst, K); } | 522 static bool classof(const Inst *Inst) { return isClassof(Inst, K); } |
| 515 | 523 |
| 516 private: | 524 private: |
| 517 InstX8632UnaryopGPR(Cfg *Func, Variable *Dest, Operand *Src) | 525 InstX8632UnaryopGPR(Cfg *Func, Variable *Dest, Operand *Src) |
| 518 : InstX8632(Func, K, 1, Dest) { | 526 : InstX8632(Func, K, 1, Dest) { |
| 519 addSource(Src); | 527 addSource(Src); |
| 520 } | 528 } |
| 521 InstX8632UnaryopGPR(const InstX8632UnaryopGPR &) = delete; | |
| 522 InstX8632UnaryopGPR &operator=(const InstX8632UnaryopGPR &) = delete; | |
| 523 ~InstX8632UnaryopGPR() override {} | 529 ~InstX8632UnaryopGPR() override {} |
| 524 static const char *Opcode; | 530 static const char *Opcode; |
| 525 static const x86::AssemblerX86::GPREmitterRegOp Emitter; | 531 static const x86::AssemblerX86::GPREmitterRegOp Emitter; |
| 526 }; | 532 }; |
| 527 | 533 |
| 528 void emitIASRegOpTyXMM(const Cfg *Func, Type Ty, const Variable *Var, | 534 void emitIASRegOpTyXMM(const Cfg *Func, Type Ty, const Variable *Var, |
| 529 const Operand *Src, | 535 const Operand *Src, |
| 530 const x86::AssemblerX86::XmmEmitterRegOp &Emitter); | 536 const x86::AssemblerX86::XmmEmitterRegOp &Emitter); |
| 531 | 537 |
| 532 template <InstX8632::InstKindX8632 K> | 538 template <InstX8632::InstKindX8632 K> |
| 533 class InstX8632UnaryopXmm : public InstX8632 { | 539 class InstX8632UnaryopXmm : public InstX8632 { |
| 540 InstX8632UnaryopXmm(const InstX8632UnaryopXmm &) = delete; | |
| 541 InstX8632UnaryopXmm &operator=(const InstX8632UnaryopXmm &) = delete; | |
| 542 | |
| 534 public: | 543 public: |
| 535 static InstX8632UnaryopXmm *create(Cfg *Func, Variable *Dest, Operand *Src) { | 544 static InstX8632UnaryopXmm *create(Cfg *Func, Variable *Dest, Operand *Src) { |
| 536 return new (Func->allocate<InstX8632UnaryopXmm>()) | 545 return new (Func->allocate<InstX8632UnaryopXmm>()) |
| 537 InstX8632UnaryopXmm(Func, Dest, Src); | 546 InstX8632UnaryopXmm(Func, Dest, Src); |
| 538 } | 547 } |
| 539 void emit(const Cfg *Func) const override { | 548 void emit(const Cfg *Func) const override { |
| 540 Ostream &Str = Func->getContext()->getStrEmit(); | 549 Ostream &Str = Func->getContext()->getStrEmit(); |
| 541 assert(getSrcSize() == 1); | 550 assert(getSrcSize() == 1); |
| 542 Str << "\t" << Opcode << "\t"; | 551 Str << "\t" << Opcode << "\t"; |
| 543 getDest()->emit(Func); | 552 getDest()->emit(Func); |
| (...skipping 12 matching lines...) Expand all Loading... | |
| 556 Str << " = " << Opcode << "." << getDest()->getType() << " "; | 565 Str << " = " << Opcode << "." << getDest()->getType() << " "; |
| 557 dumpSources(Func); | 566 dumpSources(Func); |
| 558 } | 567 } |
| 559 static bool classof(const Inst *Inst) { return isClassof(Inst, K); } | 568 static bool classof(const Inst *Inst) { return isClassof(Inst, K); } |
| 560 | 569 |
| 561 private: | 570 private: |
| 562 InstX8632UnaryopXmm(Cfg *Func, Variable *Dest, Operand *Src) | 571 InstX8632UnaryopXmm(Cfg *Func, Variable *Dest, Operand *Src) |
| 563 : InstX8632(Func, K, 1, Dest) { | 572 : InstX8632(Func, K, 1, Dest) { |
| 564 addSource(Src); | 573 addSource(Src); |
| 565 } | 574 } |
| 566 InstX8632UnaryopXmm(const InstX8632UnaryopXmm &) = delete; | |
| 567 InstX8632UnaryopXmm &operator=(const InstX8632UnaryopXmm &) = delete; | |
| 568 ~InstX8632UnaryopXmm() override {} | 575 ~InstX8632UnaryopXmm() override {} |
| 569 static const char *Opcode; | 576 static const char *Opcode; |
| 570 static const x86::AssemblerX86::XmmEmitterRegOp Emitter; | 577 static const x86::AssemblerX86::XmmEmitterRegOp Emitter; |
| 571 }; | 578 }; |
| 572 | 579 |
| 573 // See the definition of emitTwoAddress() for a description of | 580 // See the definition of emitTwoAddress() for a description of |
| 574 // ShiftHack. | 581 // ShiftHack. |
| 575 void emitTwoAddress(const char *Opcode, const Inst *Inst, const Cfg *Func, | 582 void emitTwoAddress(const char *Opcode, const Inst *Inst, const Cfg *Func, |
| 576 bool ShiftHack = false); | 583 bool ShiftHack = false); |
| 577 | 584 |
| 578 void emitIASGPRShift(const Cfg *Func, Type Ty, const Variable *Var, | 585 void emitIASGPRShift(const Cfg *Func, Type Ty, const Variable *Var, |
| 579 const Operand *Src, | 586 const Operand *Src, |
| 580 const x86::AssemblerX86::GPREmitterShiftOp &Emitter); | 587 const x86::AssemblerX86::GPREmitterShiftOp &Emitter); |
| 581 | 588 |
| 582 template <InstX8632::InstKindX8632 K> | 589 template <InstX8632::InstKindX8632 K> |
| 583 class InstX8632BinopGPRShift : public InstX8632 { | 590 class InstX8632BinopGPRShift : public InstX8632 { |
| 591 InstX8632BinopGPRShift(const InstX8632BinopGPRShift &) = delete; | |
| 592 InstX8632BinopGPRShift &operator=(const InstX8632BinopGPRShift &) = delete; | |
| 593 | |
| 584 public: | 594 public: |
| 585 // Create a binary-op GPR shift instruction. | 595 // Create a binary-op GPR shift instruction. |
| 586 static InstX8632BinopGPRShift *create(Cfg *Func, Variable *Dest, | 596 static InstX8632BinopGPRShift *create(Cfg *Func, Variable *Dest, |
| 587 Operand *Source) { | 597 Operand *Source) { |
| 588 return new (Func->allocate<InstX8632BinopGPRShift>()) | 598 return new (Func->allocate<InstX8632BinopGPRShift>()) |
| 589 InstX8632BinopGPRShift(Func, Dest, Source); | 599 InstX8632BinopGPRShift(Func, Dest, Source); |
| 590 } | 600 } |
| 591 void emit(const Cfg *Func) const override { | 601 void emit(const Cfg *Func) const override { |
| 592 const bool ShiftHack = true; | 602 const bool ShiftHack = true; |
| 593 emitTwoAddress(Opcode, this, Func, ShiftHack); | 603 emitTwoAddress(Opcode, this, Func, ShiftHack); |
| (...skipping 10 matching lines...) Expand all Loading... | |
| 604 dumpSources(Func); | 614 dumpSources(Func); |
| 605 } | 615 } |
| 606 static bool classof(const Inst *Inst) { return isClassof(Inst, K); } | 616 static bool classof(const Inst *Inst) { return isClassof(Inst, K); } |
| 607 | 617 |
| 608 private: | 618 private: |
| 609 InstX8632BinopGPRShift(Cfg *Func, Variable *Dest, Operand *Source) | 619 InstX8632BinopGPRShift(Cfg *Func, Variable *Dest, Operand *Source) |
| 610 : InstX8632(Func, K, 2, Dest) { | 620 : InstX8632(Func, K, 2, Dest) { |
| 611 addSource(Dest); | 621 addSource(Dest); |
| 612 addSource(Source); | 622 addSource(Source); |
| 613 } | 623 } |
| 614 InstX8632BinopGPRShift(const InstX8632BinopGPRShift &) = delete; | |
| 615 InstX8632BinopGPRShift &operator=(const InstX8632BinopGPRShift &) = delete; | |
| 616 ~InstX8632BinopGPRShift() override {} | 624 ~InstX8632BinopGPRShift() override {} |
| 617 static const char *Opcode; | 625 static const char *Opcode; |
| 618 static const x86::AssemblerX86::GPREmitterShiftOp Emitter; | 626 static const x86::AssemblerX86::GPREmitterShiftOp Emitter; |
| 619 }; | 627 }; |
| 620 | 628 |
| 621 template <InstX8632::InstKindX8632 K> | 629 template <InstX8632::InstKindX8632 K> |
| 622 class InstX8632BinopGPR : public InstX8632 { | 630 class InstX8632BinopGPR : public InstX8632 { |
| 631 InstX8632BinopGPR(const InstX8632BinopGPR &) = delete; | |
| 632 InstX8632BinopGPR &operator=(const InstX8632BinopGPR &) = delete; | |
| 633 | |
| 623 public: | 634 public: |
| 624 // Create an ordinary binary-op instruction like add or sub. | 635 // Create an ordinary binary-op instruction like add or sub. |
| 625 static InstX8632BinopGPR *create(Cfg *Func, Variable *Dest, Operand *Source) { | 636 static InstX8632BinopGPR *create(Cfg *Func, Variable *Dest, Operand *Source) { |
| 626 return new (Func->allocate<InstX8632BinopGPR>()) | 637 return new (Func->allocate<InstX8632BinopGPR>()) |
| 627 InstX8632BinopGPR(Func, Dest, Source); | 638 InstX8632BinopGPR(Func, Dest, Source); |
| 628 } | 639 } |
| 629 void emit(const Cfg *Func) const override { | 640 void emit(const Cfg *Func) const override { |
| 630 const bool ShiftHack = false; | 641 const bool ShiftHack = false; |
| 631 emitTwoAddress(Opcode, this, Func, ShiftHack); | 642 emitTwoAddress(Opcode, this, Func, ShiftHack); |
| 632 } | 643 } |
| 633 void emitIAS(const Cfg *Func) const override { | 644 void emitIAS(const Cfg *Func) const override { |
| 634 Type Ty = getDest()->getType(); | 645 Type Ty = getDest()->getType(); |
| 635 assert(getSrcSize() == 2); | 646 assert(getSrcSize() == 2); |
| 636 emitIASRegOpTyGPR(Func, Ty, getDest(), getSrc(1), Emitter); | 647 emitIASRegOpTyGPR(Func, Ty, getDest(), getSrc(1), Emitter); |
| 637 } | 648 } |
| 638 void dump(const Cfg *Func) const override { | 649 void dump(const Cfg *Func) const override { |
| 639 Ostream &Str = Func->getContext()->getStrDump(); | 650 Ostream &Str = Func->getContext()->getStrDump(); |
| 640 dumpDest(Func); | 651 dumpDest(Func); |
| 641 Str << " = " << Opcode << "." << getDest()->getType() << " "; | 652 Str << " = " << Opcode << "." << getDest()->getType() << " "; |
| 642 dumpSources(Func); | 653 dumpSources(Func); |
| 643 } | 654 } |
| 644 static bool classof(const Inst *Inst) { return isClassof(Inst, K); } | 655 static bool classof(const Inst *Inst) { return isClassof(Inst, K); } |
| 645 | 656 |
| 646 private: | 657 private: |
| 647 InstX8632BinopGPR(Cfg *Func, Variable *Dest, Operand *Source) | 658 InstX8632BinopGPR(Cfg *Func, Variable *Dest, Operand *Source) |
| 648 : InstX8632(Func, K, 2, Dest) { | 659 : InstX8632(Func, K, 2, Dest) { |
| 649 addSource(Dest); | 660 addSource(Dest); |
| 650 addSource(Source); | 661 addSource(Source); |
| 651 } | 662 } |
| 652 InstX8632BinopGPR(const InstX8632BinopGPR &) = delete; | |
| 653 InstX8632BinopGPR &operator=(const InstX8632BinopGPR &) = delete; | |
| 654 ~InstX8632BinopGPR() override {} | 663 ~InstX8632BinopGPR() override {} |
| 655 static const char *Opcode; | 664 static const char *Opcode; |
| 656 static const x86::AssemblerX86::GPREmitterRegOp Emitter; | 665 static const x86::AssemblerX86::GPREmitterRegOp Emitter; |
| 657 }; | 666 }; |
| 658 | 667 |
| 659 template <InstX8632::InstKindX8632 K, bool NeedsElementType> | 668 template <InstX8632::InstKindX8632 K, bool NeedsElementType> |
| 660 class InstX8632BinopXmm : public InstX8632 { | 669 class InstX8632BinopXmm : public InstX8632 { |
| 670 InstX8632BinopXmm(const InstX8632BinopXmm &) = delete; | |
| 671 InstX8632BinopXmm &operator=(const InstX8632BinopXmm &) = delete; | |
| 672 | |
| 661 public: | 673 public: |
| 662 // Create an XMM binary-op instruction like addss or addps. | 674 // Create an XMM binary-op instruction like addss or addps. |
| 663 static InstX8632BinopXmm *create(Cfg *Func, Variable *Dest, Operand *Source) { | 675 static InstX8632BinopXmm *create(Cfg *Func, Variable *Dest, Operand *Source) { |
| 664 return new (Func->allocate<InstX8632BinopXmm>()) | 676 return new (Func->allocate<InstX8632BinopXmm>()) |
| 665 InstX8632BinopXmm(Func, Dest, Source); | 677 InstX8632BinopXmm(Func, Dest, Source); |
| 666 } | 678 } |
| 667 void emit(const Cfg *Func) const override { | 679 void emit(const Cfg *Func) const override { |
| 668 const bool ShiftHack = false; | 680 const bool ShiftHack = false; |
| 669 emitTwoAddress(Opcode, this, Func, ShiftHack); | 681 emitTwoAddress(Opcode, this, Func, ShiftHack); |
| 670 } | 682 } |
| (...skipping 11 matching lines...) Expand all Loading... | |
| 682 dumpSources(Func); | 694 dumpSources(Func); |
| 683 } | 695 } |
| 684 static bool classof(const Inst *Inst) { return isClassof(Inst, K); } | 696 static bool classof(const Inst *Inst) { return isClassof(Inst, K); } |
| 685 | 697 |
| 686 private: | 698 private: |
| 687 InstX8632BinopXmm(Cfg *Func, Variable *Dest, Operand *Source) | 699 InstX8632BinopXmm(Cfg *Func, Variable *Dest, Operand *Source) |
| 688 : InstX8632(Func, K, 2, Dest) { | 700 : InstX8632(Func, K, 2, Dest) { |
| 689 addSource(Dest); | 701 addSource(Dest); |
| 690 addSource(Source); | 702 addSource(Source); |
| 691 } | 703 } |
| 692 InstX8632BinopXmm(const InstX8632BinopXmm &) = delete; | |
| 693 InstX8632BinopXmm &operator=(const InstX8632BinopXmm &) = delete; | |
| 694 ~InstX8632BinopXmm() override {} | 704 ~InstX8632BinopXmm() override {} |
| 695 static const char *Opcode; | 705 static const char *Opcode; |
| 696 static const x86::AssemblerX86::XmmEmitterRegOp Emitter; | 706 static const x86::AssemblerX86::XmmEmitterRegOp Emitter; |
| 697 }; | 707 }; |
| 698 | 708 |
| 699 void emitIASXmmShift(const Cfg *Func, Type Ty, const Variable *Var, | 709 void emitIASXmmShift(const Cfg *Func, Type Ty, const Variable *Var, |
| 700 const Operand *Src, | 710 const Operand *Src, |
| 701 const x86::AssemblerX86::XmmEmitterShiftOp &Emitter); | 711 const x86::AssemblerX86::XmmEmitterShiftOp &Emitter); |
| 702 | 712 |
| 703 template <InstX8632::InstKindX8632 K> | 713 template <InstX8632::InstKindX8632 K> |
| 704 class InstX8632BinopXmmShift : public InstX8632 { | 714 class InstX8632BinopXmmShift : public InstX8632 { |
| 715 InstX8632BinopXmmShift(const InstX8632BinopXmmShift &) = delete; | |
| 716 InstX8632BinopXmmShift &operator=(const InstX8632BinopXmmShift &) = delete; | |
| 717 | |
| 705 public: | 718 public: |
| 706 // Create an XMM binary-op shift operation. | 719 // Create an XMM binary-op shift operation. |
| 707 static InstX8632BinopXmmShift *create(Cfg *Func, Variable *Dest, | 720 static InstX8632BinopXmmShift *create(Cfg *Func, Variable *Dest, |
| 708 Operand *Source) { | 721 Operand *Source) { |
| 709 return new (Func->allocate<InstX8632BinopXmmShift>()) | 722 return new (Func->allocate<InstX8632BinopXmmShift>()) |
| 710 InstX8632BinopXmmShift(Func, Dest, Source); | 723 InstX8632BinopXmmShift(Func, Dest, Source); |
| 711 } | 724 } |
| 712 void emit(const Cfg *Func) const override { | 725 void emit(const Cfg *Func) const override { |
| 713 const bool ShiftHack = false; | 726 const bool ShiftHack = false; |
| 714 emitTwoAddress(Opcode, this, Func, ShiftHack); | 727 emitTwoAddress(Opcode, this, Func, ShiftHack); |
| (...skipping 13 matching lines...) Expand all Loading... | |
| 728 dumpSources(Func); | 741 dumpSources(Func); |
| 729 } | 742 } |
| 730 static bool classof(const Inst *Inst) { return isClassof(Inst, K); } | 743 static bool classof(const Inst *Inst) { return isClassof(Inst, K); } |
| 731 | 744 |
| 732 private: | 745 private: |
| 733 InstX8632BinopXmmShift(Cfg *Func, Variable *Dest, Operand *Source) | 746 InstX8632BinopXmmShift(Cfg *Func, Variable *Dest, Operand *Source) |
| 734 : InstX8632(Func, K, 2, Dest) { | 747 : InstX8632(Func, K, 2, Dest) { |
| 735 addSource(Dest); | 748 addSource(Dest); |
| 736 addSource(Source); | 749 addSource(Source); |
| 737 } | 750 } |
| 738 InstX8632BinopXmmShift(const InstX8632BinopXmmShift &) = delete; | |
| 739 InstX8632BinopXmmShift &operator=(const InstX8632BinopXmmShift &) = delete; | |
| 740 ~InstX8632BinopXmmShift() override {} | 751 ~InstX8632BinopXmmShift() override {} |
| 741 static const char *Opcode; | 752 static const char *Opcode; |
| 742 static const x86::AssemblerX86::XmmEmitterShiftOp Emitter; | 753 static const x86::AssemblerX86::XmmEmitterShiftOp Emitter; |
| 743 }; | 754 }; |
| 744 | 755 |
| 745 template <InstX8632::InstKindX8632 K> class InstX8632Ternop : public InstX8632 { | 756 template <InstX8632::InstKindX8632 K> class InstX8632Ternop : public InstX8632 { |
| 757 InstX8632Ternop(const InstX8632Ternop &) = delete; | |
| 758 InstX8632Ternop &operator=(const InstX8632Ternop &) = delete; | |
| 759 | |
| 746 public: | 760 public: |
| 747 // Create a ternary-op instruction like div or idiv. | 761 // Create a ternary-op instruction like div or idiv. |
| 748 static InstX8632Ternop *create(Cfg *Func, Variable *Dest, Operand *Source1, | 762 static InstX8632Ternop *create(Cfg *Func, Variable *Dest, Operand *Source1, |
| 749 Operand *Source2) { | 763 Operand *Source2) { |
| 750 return new (Func->allocate<InstX8632Ternop>()) | 764 return new (Func->allocate<InstX8632Ternop>()) |
| 751 InstX8632Ternop(Func, Dest, Source1, Source2); | 765 InstX8632Ternop(Func, Dest, Source1, Source2); |
| 752 } | 766 } |
| 753 void emit(const Cfg *Func) const override { | 767 void emit(const Cfg *Func) const override { |
| 754 Ostream &Str = Func->getContext()->getStrEmit(); | 768 Ostream &Str = Func->getContext()->getStrEmit(); |
| 755 assert(getSrcSize() == 3); | 769 assert(getSrcSize() == 3); |
| (...skipping 14 matching lines...) Expand all Loading... | |
| 770 } | 784 } |
| 771 static bool classof(const Inst *Inst) { return isClassof(Inst, K); } | 785 static bool classof(const Inst *Inst) { return isClassof(Inst, K); } |
| 772 | 786 |
| 773 private: | 787 private: |
| 774 InstX8632Ternop(Cfg *Func, Variable *Dest, Operand *Source1, Operand *Source2) | 788 InstX8632Ternop(Cfg *Func, Variable *Dest, Operand *Source1, Operand *Source2) |
| 775 : InstX8632(Func, K, 3, Dest) { | 789 : InstX8632(Func, K, 3, Dest) { |
| 776 addSource(Dest); | 790 addSource(Dest); |
| 777 addSource(Source1); | 791 addSource(Source1); |
| 778 addSource(Source2); | 792 addSource(Source2); |
| 779 } | 793 } |
| 780 InstX8632Ternop(const InstX8632Ternop &) = delete; | |
| 781 InstX8632Ternop &operator=(const InstX8632Ternop &) = delete; | |
| 782 ~InstX8632Ternop() override {} | 794 ~InstX8632Ternop() override {} |
| 783 static const char *Opcode; | 795 static const char *Opcode; |
| 784 }; | 796 }; |
| 785 | 797 |
| 786 // Instructions of the form x := y op z | 798 // Instructions of the form x := y op z |
| 787 template <InstX8632::InstKindX8632 K> | 799 template <InstX8632::InstKindX8632 K> |
| 788 class InstX8632ThreeAddressop : public InstX8632 { | 800 class InstX8632ThreeAddressop : public InstX8632 { |
| 801 InstX8632ThreeAddressop(const InstX8632ThreeAddressop &) = delete; | |
| 802 InstX8632ThreeAddressop &operator=(const InstX8632ThreeAddressop &) = delete; | |
| 803 | |
| 789 public: | 804 public: |
| 790 static InstX8632ThreeAddressop *create(Cfg *Func, Variable *Dest, | 805 static InstX8632ThreeAddressop *create(Cfg *Func, Variable *Dest, |
| 791 Operand *Source0, Operand *Source1) { | 806 Operand *Source0, Operand *Source1) { |
| 792 return new (Func->allocate<InstX8632ThreeAddressop>()) | 807 return new (Func->allocate<InstX8632ThreeAddressop>()) |
| 793 InstX8632ThreeAddressop(Func, Dest, Source0, Source1); | 808 InstX8632ThreeAddressop(Func, Dest, Source0, Source1); |
| 794 } | 809 } |
| 795 void emit(const Cfg *Func) const override { | 810 void emit(const Cfg *Func) const override { |
| 796 Ostream &Str = Func->getContext()->getStrEmit(); | 811 Ostream &Str = Func->getContext()->getStrEmit(); |
| 797 assert(getSrcSize() == 2); | 812 assert(getSrcSize() == 2); |
| 798 Str << "\t" << Opcode << "\t"; | 813 Str << "\t" << Opcode << "\t"; |
| (...skipping 13 matching lines...) Expand all Loading... | |
| 812 } | 827 } |
| 813 static bool classof(const Inst *Inst) { return isClassof(Inst, K); } | 828 static bool classof(const Inst *Inst) { return isClassof(Inst, K); } |
| 814 | 829 |
| 815 private: | 830 private: |
| 816 InstX8632ThreeAddressop(Cfg *Func, Variable *Dest, Operand *Source0, | 831 InstX8632ThreeAddressop(Cfg *Func, Variable *Dest, Operand *Source0, |
| 817 Operand *Source1) | 832 Operand *Source1) |
| 818 : InstX8632(Func, K, 2, Dest) { | 833 : InstX8632(Func, K, 2, Dest) { |
| 819 addSource(Source0); | 834 addSource(Source0); |
| 820 addSource(Source1); | 835 addSource(Source1); |
| 821 } | 836 } |
| 822 InstX8632ThreeAddressop(const InstX8632ThreeAddressop &) = delete; | |
| 823 InstX8632ThreeAddressop &operator=(const InstX8632ThreeAddressop &) = delete; | |
| 824 ~InstX8632ThreeAddressop() override {} | 837 ~InstX8632ThreeAddressop() override {} |
| 825 static const char *Opcode; | 838 static const char *Opcode; |
| 826 }; | 839 }; |
| 827 | 840 |
| 828 bool checkForRedundantAssign(const Variable *Dest, const Operand *Source); | 841 bool checkForRedundantAssign(const Variable *Dest, const Operand *Source); |
| 829 | 842 |
| 830 // Base class for assignment instructions | 843 // Base class for assignment instructions |
| 831 template <InstX8632::InstKindX8632 K> | 844 template <InstX8632::InstKindX8632 K> |
| 832 class InstX8632Movlike : public InstX8632 { | 845 class InstX8632Movlike : public InstX8632 { |
| 846 InstX8632Movlike(const InstX8632Movlike &) = delete; | |
| 847 InstX8632Movlike &operator=(const InstX8632Movlike &) = delete; | |
| 848 | |
| 833 public: | 849 public: |
| 834 static InstX8632Movlike *create(Cfg *Func, Variable *Dest, Operand *Source) { | 850 static InstX8632Movlike *create(Cfg *Func, Variable *Dest, Operand *Source) { |
| 835 return new (Func->allocate<InstX8632Movlike>()) | 851 return new (Func->allocate<InstX8632Movlike>()) |
| 836 InstX8632Movlike(Func, Dest, Source); | 852 InstX8632Movlike(Func, Dest, Source); |
| 837 } | 853 } |
| 838 bool isRedundantAssign() const override { | 854 bool isRedundantAssign() const override { |
| 839 return checkForRedundantAssign(getDest(), getSrc(0)); | 855 return checkForRedundantAssign(getDest(), getSrc(0)); |
| 840 } | 856 } |
| 841 bool isSimpleAssign() const override { return true; } | 857 bool isSimpleAssign() const override { return true; } |
| 842 void emit(const Cfg *Func) const override; | 858 void emit(const Cfg *Func) const override; |
| 843 void emitIAS(const Cfg *Func) const override; | 859 void emitIAS(const Cfg *Func) const override; |
| 844 void dump(const Cfg *Func) const override { | 860 void dump(const Cfg *Func) const override { |
| 845 Ostream &Str = Func->getContext()->getStrDump(); | 861 Ostream &Str = Func->getContext()->getStrDump(); |
| 846 Str << Opcode << "." << getDest()->getType() << " "; | 862 Str << Opcode << "." << getDest()->getType() << " "; |
| 847 dumpDest(Func); | 863 dumpDest(Func); |
| 848 Str << ", "; | 864 Str << ", "; |
| 849 dumpSources(Func); | 865 dumpSources(Func); |
| 850 } | 866 } |
| 851 static bool classof(const Inst *Inst) { return isClassof(Inst, K); } | 867 static bool classof(const Inst *Inst) { return isClassof(Inst, K); } |
| 852 | 868 |
| 853 private: | 869 private: |
| 854 InstX8632Movlike(Cfg *Func, Variable *Dest, Operand *Source) | 870 InstX8632Movlike(Cfg *Func, Variable *Dest, Operand *Source) |
| 855 : InstX8632(Func, K, 1, Dest) { | 871 : InstX8632(Func, K, 1, Dest) { |
| 856 addSource(Source); | 872 addSource(Source); |
| 857 } | 873 } |
| 858 InstX8632Movlike(const InstX8632Movlike &) = delete; | |
| 859 InstX8632Movlike &operator=(const InstX8632Movlike &) = delete; | |
| 860 ~InstX8632Movlike() override {} | 874 ~InstX8632Movlike() override {} |
| 861 | 875 |
| 862 static const char *Opcode; | 876 static const char *Opcode; |
| 863 }; | 877 }; |
| 864 | 878 |
| 865 typedef InstX8632InplaceopGPR<InstX8632::Bswap> InstX8632Bswap; | 879 typedef InstX8632InplaceopGPR<InstX8632::Bswap> InstX8632Bswap; |
| 866 typedef InstX8632InplaceopGPR<InstX8632::Neg> InstX8632Neg; | 880 typedef InstX8632InplaceopGPR<InstX8632::Neg> InstX8632Neg; |
| 867 typedef InstX8632UnaryopGPR<InstX8632::Bsf> InstX8632Bsf; | 881 typedef InstX8632UnaryopGPR<InstX8632::Bsf> InstX8632Bsf; |
| 868 typedef InstX8632UnaryopGPR<InstX8632::Bsr> InstX8632Bsr; | 882 typedef InstX8632UnaryopGPR<InstX8632::Bsr> InstX8632Bsr; |
| 869 typedef InstX8632UnaryopGPR<InstX8632::Lea> InstX8632Lea; | 883 typedef InstX8632UnaryopGPR<InstX8632::Lea> InstX8632Lea; |
| (...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 923 typedef InstX8632Ternop<InstX8632::Insertps> InstX8632Insertps; | 937 typedef InstX8632Ternop<InstX8632::Insertps> InstX8632Insertps; |
| 924 typedef InstX8632Ternop<InstX8632::Pinsr> InstX8632Pinsr; | 938 typedef InstX8632Ternop<InstX8632::Pinsr> InstX8632Pinsr; |
| 925 typedef InstX8632Ternop<InstX8632::Shufps> InstX8632Shufps; | 939 typedef InstX8632Ternop<InstX8632::Shufps> InstX8632Shufps; |
| 926 typedef InstX8632Ternop<InstX8632::Blendvps> InstX8632Blendvps; | 940 typedef InstX8632Ternop<InstX8632::Blendvps> InstX8632Blendvps; |
| 927 typedef InstX8632Ternop<InstX8632::Pblendvb> InstX8632Pblendvb; | 941 typedef InstX8632Ternop<InstX8632::Pblendvb> InstX8632Pblendvb; |
| 928 typedef InstX8632ThreeAddressop<InstX8632::Pextr> InstX8632Pextr; | 942 typedef InstX8632ThreeAddressop<InstX8632::Pextr> InstX8632Pextr; |
| 929 typedef InstX8632ThreeAddressop<InstX8632::Pshufd> InstX8632Pshufd; | 943 typedef InstX8632ThreeAddressop<InstX8632::Pshufd> InstX8632Pshufd; |
| 930 | 944 |
| 931 // Base class for a lockable x86-32 instruction (emits a locked prefix). | 945 // Base class for a lockable x86-32 instruction (emits a locked prefix). |
| 932 class InstX8632Lockable : public InstX8632 { | 946 class InstX8632Lockable : public InstX8632 { |
| 947 InstX8632Lockable(const InstX8632Lockable &) = delete; | |
| 948 InstX8632Lockable &operator=(const InstX8632Lockable &) = delete; | |
| 949 | |
| 933 protected: | 950 protected: |
| 934 bool Locked; | 951 bool Locked; |
| 935 | 952 |
| 936 InstX8632Lockable(Cfg *Func, InstKindX8632 Kind, SizeT Maxsrcs, | 953 InstX8632Lockable(Cfg *Func, InstKindX8632 Kind, SizeT Maxsrcs, |
| 937 Variable *Dest, bool Locked) | 954 Variable *Dest, bool Locked) |
| 938 : InstX8632(Func, Kind, Maxsrcs, Dest), Locked(Locked) { | 955 : InstX8632(Func, Kind, Maxsrcs, Dest), Locked(Locked) { |
| 939 // Assume that such instructions are used for Atomics and be careful | 956 // Assume that such instructions are used for Atomics and be careful |
| 940 // with optimizations. | 957 // with optimizations. |
| 941 HasSideEffects = Locked; | 958 HasSideEffects = Locked; |
| 942 } | 959 } |
| 943 ~InstX8632Lockable() override {} | 960 ~InstX8632Lockable() override {} |
| 944 | |
| 945 private: | |
| 946 InstX8632Lockable(const InstX8632Lockable &) = delete; | |
| 947 InstX8632Lockable &operator=(const InstX8632Lockable &) = delete; | |
| 948 }; | 961 }; |
| 949 | 962 |
| 950 // Mul instruction - unsigned multiply. | 963 // Mul instruction - unsigned multiply. |
| 951 class InstX8632Mul : public InstX8632 { | 964 class InstX8632Mul : public InstX8632 { |
| 965 InstX8632Mul(const InstX8632Mul &) = delete; | |
| 966 InstX8632Mul &operator=(const InstX8632Mul &) = delete; | |
| 967 | |
| 952 public: | 968 public: |
| 953 static InstX8632Mul *create(Cfg *Func, Variable *Dest, Variable *Source1, | 969 static InstX8632Mul *create(Cfg *Func, Variable *Dest, Variable *Source1, |
| 954 Operand *Source2) { | 970 Operand *Source2) { |
| 955 return new (Func->allocate<InstX8632Mul>()) | 971 return new (Func->allocate<InstX8632Mul>()) |
| 956 InstX8632Mul(Func, Dest, Source1, Source2); | 972 InstX8632Mul(Func, Dest, Source1, Source2); |
| 957 } | 973 } |
| 958 void emit(const Cfg *Func) const override; | 974 void emit(const Cfg *Func) const override; |
| 959 void emitIAS(const Cfg *Func) const override; | 975 void emitIAS(const Cfg *Func) const override; |
| 960 void dump(const Cfg *Func) const override; | 976 void dump(const Cfg *Func) const override; |
| 961 static bool classof(const Inst *Inst) { return isClassof(Inst, Mul); } | 977 static bool classof(const Inst *Inst) { return isClassof(Inst, Mul); } |
| 962 | 978 |
| 963 private: | 979 private: |
| 964 InstX8632Mul(Cfg *Func, Variable *Dest, Variable *Source1, Operand *Source2); | 980 InstX8632Mul(Cfg *Func, Variable *Dest, Variable *Source1, Operand *Source2); |
| 965 InstX8632Mul(const InstX8632Mul &) = delete; | |
| 966 InstX8632Mul &operator=(const InstX8632Mul &) = delete; | |
| 967 ~InstX8632Mul() override {} | 981 ~InstX8632Mul() override {} |
| 968 }; | 982 }; |
| 969 | 983 |
| 970 // Shld instruction - shift across a pair of operands. TODO: Verify | 984 // Shld instruction - shift across a pair of operands. TODO: Verify |
| 971 // that the validator accepts the shld instruction. | 985 // that the validator accepts the shld instruction. |
| 972 class InstX8632Shld : public InstX8632 { | 986 class InstX8632Shld : public InstX8632 { |
| 987 InstX8632Shld(const InstX8632Shld &) = delete; | |
| 988 InstX8632Shld &operator=(const InstX8632Shld &) = delete; | |
| 989 | |
| 973 public: | 990 public: |
| 974 static InstX8632Shld *create(Cfg *Func, Variable *Dest, Variable *Source1, | 991 static InstX8632Shld *create(Cfg *Func, Variable *Dest, Variable *Source1, |
| 975 Variable *Source2) { | 992 Variable *Source2) { |
| 976 return new (Func->allocate<InstX8632Shld>()) | 993 return new (Func->allocate<InstX8632Shld>()) |
| 977 InstX8632Shld(Func, Dest, Source1, Source2); | 994 InstX8632Shld(Func, Dest, Source1, Source2); |
| 978 } | 995 } |
| 979 void emit(const Cfg *Func) const override; | 996 void emit(const Cfg *Func) const override; |
| 980 void emitIAS(const Cfg *Func) const override; | 997 void emitIAS(const Cfg *Func) const override; |
| 981 void dump(const Cfg *Func) const override; | 998 void dump(const Cfg *Func) const override; |
| 982 static bool classof(const Inst *Inst) { return isClassof(Inst, Shld); } | 999 static bool classof(const Inst *Inst) { return isClassof(Inst, Shld); } |
| 983 | 1000 |
| 984 private: | 1001 private: |
| 985 InstX8632Shld(Cfg *Func, Variable *Dest, Variable *Source1, | 1002 InstX8632Shld(Cfg *Func, Variable *Dest, Variable *Source1, |
| 986 Variable *Source2); | 1003 Variable *Source2); |
| 987 InstX8632Shld(const InstX8632Shld &) = delete; | |
| 988 InstX8632Shld &operator=(const InstX8632Shld &) = delete; | |
| 989 ~InstX8632Shld() override {} | 1004 ~InstX8632Shld() override {} |
| 990 }; | 1005 }; |
| 991 | 1006 |
| 992 // Shrd instruction - shift across a pair of operands. TODO: Verify | 1007 // Shrd instruction - shift across a pair of operands. TODO: Verify |
| 993 // that the validator accepts the shrd instruction. | 1008 // that the validator accepts the shrd instruction. |
| 994 class InstX8632Shrd : public InstX8632 { | 1009 class InstX8632Shrd : public InstX8632 { |
| 1010 InstX8632Shrd(const InstX8632Shrd &) = delete; | |
| 1011 InstX8632Shrd &operator=(const InstX8632Shrd &) = delete; | |
| 1012 | |
| 995 public: | 1013 public: |
| 996 static InstX8632Shrd *create(Cfg *Func, Variable *Dest, Variable *Source1, | 1014 static InstX8632Shrd *create(Cfg *Func, Variable *Dest, Variable *Source1, |
| 997 Variable *Source2) { | 1015 Variable *Source2) { |
| 998 return new (Func->allocate<InstX8632Shrd>()) | 1016 return new (Func->allocate<InstX8632Shrd>()) |
| 999 InstX8632Shrd(Func, Dest, Source1, Source2); | 1017 InstX8632Shrd(Func, Dest, Source1, Source2); |
| 1000 } | 1018 } |
| 1001 void emit(const Cfg *Func) const override; | 1019 void emit(const Cfg *Func) const override; |
| 1002 void emitIAS(const Cfg *Func) const override; | 1020 void emitIAS(const Cfg *Func) const override; |
| 1003 void dump(const Cfg *Func) const override; | 1021 void dump(const Cfg *Func) const override; |
| 1004 static bool classof(const Inst *Inst) { return isClassof(Inst, Shrd); } | 1022 static bool classof(const Inst *Inst) { return isClassof(Inst, Shrd); } |
| 1005 | 1023 |
| 1006 private: | 1024 private: |
| 1007 InstX8632Shrd(Cfg *Func, Variable *Dest, Variable *Source1, | 1025 InstX8632Shrd(Cfg *Func, Variable *Dest, Variable *Source1, |
| 1008 Variable *Source2); | 1026 Variable *Source2); |
| 1009 InstX8632Shrd(const InstX8632Shrd &) = delete; | |
| 1010 InstX8632Shrd &operator=(const InstX8632Shrd &) = delete; | |
| 1011 ~InstX8632Shrd() override {} | 1027 ~InstX8632Shrd() override {} |
| 1012 }; | 1028 }; |
| 1013 | 1029 |
| 1014 // Conditional move instruction. | 1030 // Conditional move instruction. |
| 1015 class InstX8632Cmov : public InstX8632 { | 1031 class InstX8632Cmov : public InstX8632 { |
| 1032 InstX8632Cmov(const InstX8632Cmov &) = delete; | |
| 1033 InstX8632Cmov &operator=(const InstX8632Cmov &) = delete; | |
| 1034 | |
| 1016 public: | 1035 public: |
| 1017 static InstX8632Cmov *create(Cfg *Func, Variable *Dest, Operand *Source, | 1036 static InstX8632Cmov *create(Cfg *Func, Variable *Dest, Operand *Source, |
| 1018 CondX86::BrCond Cond) { | 1037 CondX86::BrCond Cond) { |
| 1019 return new (Func->allocate<InstX8632Cmov>()) | 1038 return new (Func->allocate<InstX8632Cmov>()) |
| 1020 InstX8632Cmov(Func, Dest, Source, Cond); | 1039 InstX8632Cmov(Func, Dest, Source, Cond); |
| 1021 } | 1040 } |
| 1022 void emit(const Cfg *Func) const override; | 1041 void emit(const Cfg *Func) const override; |
| 1023 void emitIAS(const Cfg *Func) const override; | 1042 void emitIAS(const Cfg *Func) const override; |
| 1024 void dump(const Cfg *Func) const override; | 1043 void dump(const Cfg *Func) const override; |
| 1025 static bool classof(const Inst *Inst) { return isClassof(Inst, Cmov); } | 1044 static bool classof(const Inst *Inst) { return isClassof(Inst, Cmov); } |
| 1026 | 1045 |
| 1027 private: | 1046 private: |
| 1028 InstX8632Cmov(Cfg *Func, Variable *Dest, Operand *Source, | 1047 InstX8632Cmov(Cfg *Func, Variable *Dest, Operand *Source, |
| 1029 CondX86::BrCond Cond); | 1048 CondX86::BrCond Cond); |
| 1030 InstX8632Cmov(const InstX8632Cmov &) = delete; | |
| 1031 InstX8632Cmov &operator=(const InstX8632Cmov &) = delete; | |
| 1032 ~InstX8632Cmov() override {} | 1049 ~InstX8632Cmov() override {} |
| 1033 | 1050 |
| 1034 CondX86::BrCond Condition; | 1051 CondX86::BrCond Condition; |
| 1035 }; | 1052 }; |
| 1036 | 1053 |
| 1037 // Cmpps instruction - compare packed singled-precision floating point | 1054 // Cmpps instruction - compare packed singled-precision floating point |
| 1038 // values | 1055 // values |
| 1039 class InstX8632Cmpps : public InstX8632 { | 1056 class InstX8632Cmpps : public InstX8632 { |
| 1057 InstX8632Cmpps(const InstX8632Cmpps &) = delete; | |
| 1058 InstX8632Cmpps &operator=(const InstX8632Cmpps &) = delete; | |
| 1059 | |
| 1040 public: | 1060 public: |
| 1041 static InstX8632Cmpps *create(Cfg *Func, Variable *Dest, Operand *Source, | 1061 static InstX8632Cmpps *create(Cfg *Func, Variable *Dest, Operand *Source, |
| 1042 CondX86::CmppsCond Condition) { | 1062 CondX86::CmppsCond Condition) { |
| 1043 return new (Func->allocate<InstX8632Cmpps>()) | 1063 return new (Func->allocate<InstX8632Cmpps>()) |
| 1044 InstX8632Cmpps(Func, Dest, Source, Condition); | 1064 InstX8632Cmpps(Func, Dest, Source, Condition); |
| 1045 } | 1065 } |
| 1046 void emit(const Cfg *Func) const override; | 1066 void emit(const Cfg *Func) const override; |
| 1047 void emitIAS(const Cfg *Func) const override; | 1067 void emitIAS(const Cfg *Func) const override; |
| 1048 void dump(const Cfg *Func) const override; | 1068 void dump(const Cfg *Func) const override; |
| 1049 static bool classof(const Inst *Inst) { return isClassof(Inst, Cmpps); } | 1069 static bool classof(const Inst *Inst) { return isClassof(Inst, Cmpps); } |
| 1050 | 1070 |
| 1051 private: | 1071 private: |
| 1052 InstX8632Cmpps(Cfg *Func, Variable *Dest, Operand *Source, | 1072 InstX8632Cmpps(Cfg *Func, Variable *Dest, Operand *Source, |
| 1053 CondX86::CmppsCond Cond); | 1073 CondX86::CmppsCond Cond); |
| 1054 InstX8632Cmpps(const InstX8632Cmpps &) = delete; | |
| 1055 InstX8632Cmpps &operator=(const InstX8632Cmpps &) = delete; | |
| 1056 ~InstX8632Cmpps() override {} | 1074 ~InstX8632Cmpps() override {} |
| 1057 | 1075 |
| 1058 CondX86::CmppsCond Condition; | 1076 CondX86::CmppsCond Condition; |
| 1059 }; | 1077 }; |
| 1060 | 1078 |
| 1061 // Cmpxchg instruction - cmpxchg <dest>, <desired> will compare if <dest> | 1079 // Cmpxchg instruction - cmpxchg <dest>, <desired> will compare if <dest> |
| 1062 // equals eax. If so, the ZF is set and <desired> is stored in <dest>. | 1080 // equals eax. If so, the ZF is set and <desired> is stored in <dest>. |
| 1063 // If not, ZF is cleared and <dest> is copied to eax (or subregister). | 1081 // If not, ZF is cleared and <dest> is copied to eax (or subregister). |
| 1064 // <dest> can be a register or memory, while <desired> must be a register. | 1082 // <dest> can be a register or memory, while <desired> must be a register. |
| 1065 // It is the user's responsiblity to mark eax with a FakeDef. | 1083 // It is the user's responsiblity to mark eax with a FakeDef. |
| 1066 class InstX8632Cmpxchg : public InstX8632Lockable { | 1084 class InstX8632Cmpxchg : public InstX8632Lockable { |
| 1085 InstX8632Cmpxchg(const InstX8632Cmpxchg &) = delete; | |
| 1086 InstX8632Cmpxchg &operator=(const InstX8632Cmpxchg &) = delete; | |
| 1087 | |
| 1067 public: | 1088 public: |
| 1068 static InstX8632Cmpxchg *create(Cfg *Func, Operand *DestOrAddr, Variable *Eax, | 1089 static InstX8632Cmpxchg *create(Cfg *Func, Operand *DestOrAddr, Variable *Eax, |
| 1069 Variable *Desired, bool Locked) { | 1090 Variable *Desired, bool Locked) { |
| 1070 return new (Func->allocate<InstX8632Cmpxchg>()) | 1091 return new (Func->allocate<InstX8632Cmpxchg>()) |
| 1071 InstX8632Cmpxchg(Func, DestOrAddr, Eax, Desired, Locked); | 1092 InstX8632Cmpxchg(Func, DestOrAddr, Eax, Desired, Locked); |
| 1072 } | 1093 } |
| 1073 void emit(const Cfg *Func) const override; | 1094 void emit(const Cfg *Func) const override; |
| 1074 void emitIAS(const Cfg *Func) const override; | 1095 void emitIAS(const Cfg *Func) const override; |
| 1075 void dump(const Cfg *Func) const override; | 1096 void dump(const Cfg *Func) const override; |
| 1076 static bool classof(const Inst *Inst) { return isClassof(Inst, Cmpxchg); } | 1097 static bool classof(const Inst *Inst) { return isClassof(Inst, Cmpxchg); } |
| 1077 | 1098 |
| 1078 private: | 1099 private: |
| 1079 InstX8632Cmpxchg(Cfg *Func, Operand *DestOrAddr, Variable *Eax, | 1100 InstX8632Cmpxchg(Cfg *Func, Operand *DestOrAddr, Variable *Eax, |
| 1080 Variable *Desired, bool Locked); | 1101 Variable *Desired, bool Locked); |
| 1081 InstX8632Cmpxchg(const InstX8632Cmpxchg &) = delete; | |
| 1082 InstX8632Cmpxchg &operator=(const InstX8632Cmpxchg &) = delete; | |
| 1083 ~InstX8632Cmpxchg() override {} | 1102 ~InstX8632Cmpxchg() override {} |
| 1084 }; | 1103 }; |
| 1085 | 1104 |
| 1086 // Cmpxchg8b instruction - cmpxchg8b <m64> will compare if <m64> | 1105 // Cmpxchg8b instruction - cmpxchg8b <m64> will compare if <m64> |
| 1087 // equals edx:eax. If so, the ZF is set and ecx:ebx is stored in <m64>. | 1106 // equals edx:eax. If so, the ZF is set and ecx:ebx is stored in <m64>. |
| 1088 // If not, ZF is cleared and <m64> is copied to edx:eax. | 1107 // If not, ZF is cleared and <m64> is copied to edx:eax. |
| 1089 // The caller is responsible for inserting FakeDefs to mark edx | 1108 // The caller is responsible for inserting FakeDefs to mark edx |
| 1090 // and eax as modified. | 1109 // and eax as modified. |
| 1091 // <m64> must be a memory operand. | 1110 // <m64> must be a memory operand. |
| 1092 class InstX8632Cmpxchg8b : public InstX8632Lockable { | 1111 class InstX8632Cmpxchg8b : public InstX8632Lockable { |
| 1112 InstX8632Cmpxchg8b(const InstX8632Cmpxchg8b &) = delete; | |
| 1113 InstX8632Cmpxchg8b &operator=(const InstX8632Cmpxchg8b &) = delete; | |
| 1114 | |
| 1093 public: | 1115 public: |
| 1094 static InstX8632Cmpxchg8b *create(Cfg *Func, OperandX8632Mem *Dest, | 1116 static InstX8632Cmpxchg8b *create(Cfg *Func, OperandX8632Mem *Dest, |
| 1095 Variable *Edx, Variable *Eax, Variable *Ecx, | 1117 Variable *Edx, Variable *Eax, Variable *Ecx, |
| 1096 Variable *Ebx, bool Locked) { | 1118 Variable *Ebx, bool Locked) { |
| 1097 return new (Func->allocate<InstX8632Cmpxchg8b>()) | 1119 return new (Func->allocate<InstX8632Cmpxchg8b>()) |
| 1098 InstX8632Cmpxchg8b(Func, Dest, Edx, Eax, Ecx, Ebx, Locked); | 1120 InstX8632Cmpxchg8b(Func, Dest, Edx, Eax, Ecx, Ebx, Locked); |
| 1099 } | 1121 } |
| 1100 void emit(const Cfg *Func) const override; | 1122 void emit(const Cfg *Func) const override; |
| 1101 void emitIAS(const Cfg *Func) const override; | 1123 void emitIAS(const Cfg *Func) const override; |
| 1102 void dump(const Cfg *Func) const override; | 1124 void dump(const Cfg *Func) const override; |
| 1103 static bool classof(const Inst *Inst) { return isClassof(Inst, Cmpxchg8b); } | 1125 static bool classof(const Inst *Inst) { return isClassof(Inst, Cmpxchg8b); } |
| 1104 | 1126 |
| 1105 private: | 1127 private: |
| 1106 InstX8632Cmpxchg8b(Cfg *Func, OperandX8632Mem *Dest, Variable *Edx, | 1128 InstX8632Cmpxchg8b(Cfg *Func, OperandX8632Mem *Dest, Variable *Edx, |
| 1107 Variable *Eax, Variable *Ecx, Variable *Ebx, bool Locked); | 1129 Variable *Eax, Variable *Ecx, Variable *Ebx, bool Locked); |
| 1108 InstX8632Cmpxchg8b(const InstX8632Cmpxchg8b &) = delete; | |
| 1109 InstX8632Cmpxchg8b &operator=(const InstX8632Cmpxchg8b &) = delete; | |
| 1110 ~InstX8632Cmpxchg8b() override {} | 1130 ~InstX8632Cmpxchg8b() override {} |
| 1111 }; | 1131 }; |
| 1112 | 1132 |
| 1113 // Cvt instruction - wrapper for cvtsX2sY where X and Y are in {s,d,i} | 1133 // Cvt instruction - wrapper for cvtsX2sY where X and Y are in {s,d,i} |
| 1114 // as appropriate. s=float, d=double, i=int. X and Y are determined | 1134 // as appropriate. s=float, d=double, i=int. X and Y are determined |
| 1115 // from dest/src types. Sign and zero extension on the integer | 1135 // from dest/src types. Sign and zero extension on the integer |
| 1116 // operand needs to be done separately. | 1136 // operand needs to be done separately. |
| 1117 class InstX8632Cvt : public InstX8632 { | 1137 class InstX8632Cvt : public InstX8632 { |
| 1138 InstX8632Cvt(const InstX8632Cvt &) = delete; | |
| 1139 InstX8632Cvt &operator=(const InstX8632Cvt &) = delete; | |
| 1140 | |
| 1118 public: | 1141 public: |
| 1119 enum CvtVariant { Si2ss, Tss2si, Float2float, Dq2ps, Tps2dq }; | 1142 enum CvtVariant { Si2ss, Tss2si, Float2float, Dq2ps, Tps2dq }; |
| 1120 static InstX8632Cvt *create(Cfg *Func, Variable *Dest, Operand *Source, | 1143 static InstX8632Cvt *create(Cfg *Func, Variable *Dest, Operand *Source, |
| 1121 CvtVariant Variant) { | 1144 CvtVariant Variant) { |
| 1122 return new (Func->allocate<InstX8632Cvt>()) | 1145 return new (Func->allocate<InstX8632Cvt>()) |
| 1123 InstX8632Cvt(Func, Dest, Source, Variant); | 1146 InstX8632Cvt(Func, Dest, Source, Variant); |
| 1124 } | 1147 } |
| 1125 void emit(const Cfg *Func) const override; | 1148 void emit(const Cfg *Func) const override; |
| 1126 void emitIAS(const Cfg *Func) const override; | 1149 void emitIAS(const Cfg *Func) const override; |
| 1127 void dump(const Cfg *Func) const override; | 1150 void dump(const Cfg *Func) const override; |
| 1128 static bool classof(const Inst *Inst) { return isClassof(Inst, Cvt); } | 1151 static bool classof(const Inst *Inst) { return isClassof(Inst, Cvt); } |
| 1129 bool isTruncating() const { return Variant == Tss2si || Variant == Tps2dq; } | 1152 bool isTruncating() const { return Variant == Tss2si || Variant == Tps2dq; } |
| 1130 | 1153 |
| 1131 private: | 1154 private: |
| 1132 CvtVariant Variant; | 1155 CvtVariant Variant; |
| 1133 InstX8632Cvt(Cfg *Func, Variable *Dest, Operand *Source, CvtVariant Variant); | 1156 InstX8632Cvt(Cfg *Func, Variable *Dest, Operand *Source, CvtVariant Variant); |
| 1134 InstX8632Cvt(const InstX8632Cvt &) = delete; | |
| 1135 InstX8632Cvt &operator=(const InstX8632Cvt &) = delete; | |
| 1136 ~InstX8632Cvt() override {} | 1157 ~InstX8632Cvt() override {} |
| 1137 }; | 1158 }; |
| 1138 | 1159 |
| 1139 // cmp - Integer compare instruction. | 1160 // cmp - Integer compare instruction. |
| 1140 class InstX8632Icmp : public InstX8632 { | 1161 class InstX8632Icmp : public InstX8632 { |
| 1162 InstX8632Icmp(const InstX8632Icmp &) = delete; | |
| 1163 InstX8632Icmp &operator=(const InstX8632Icmp &) = delete; | |
| 1164 | |
| 1141 public: | 1165 public: |
| 1142 static InstX8632Icmp *create(Cfg *Func, Operand *Src1, Operand *Src2) { | 1166 static InstX8632Icmp *create(Cfg *Func, Operand *Src1, Operand *Src2) { |
| 1143 return new (Func->allocate<InstX8632Icmp>()) | 1167 return new (Func->allocate<InstX8632Icmp>()) |
| 1144 InstX8632Icmp(Func, Src1, Src2); | 1168 InstX8632Icmp(Func, Src1, Src2); |
| 1145 } | 1169 } |
| 1146 void emit(const Cfg *Func) const override; | 1170 void emit(const Cfg *Func) const override; |
| 1147 void emitIAS(const Cfg *Func) const override; | 1171 void emitIAS(const Cfg *Func) const override; |
| 1148 void dump(const Cfg *Func) const override; | 1172 void dump(const Cfg *Func) const override; |
| 1149 static bool classof(const Inst *Inst) { return isClassof(Inst, Icmp); } | 1173 static bool classof(const Inst *Inst) { return isClassof(Inst, Icmp); } |
| 1150 | 1174 |
| 1151 private: | 1175 private: |
| 1152 InstX8632Icmp(Cfg *Func, Operand *Src1, Operand *Src2); | 1176 InstX8632Icmp(Cfg *Func, Operand *Src1, Operand *Src2); |
| 1153 InstX8632Icmp(const InstX8632Icmp &) = delete; | |
| 1154 InstX8632Icmp &operator=(const InstX8632Icmp &) = delete; | |
| 1155 ~InstX8632Icmp() override {} | 1177 ~InstX8632Icmp() override {} |
| 1156 }; | 1178 }; |
| 1157 | 1179 |
| 1158 // ucomiss/ucomisd - floating-point compare instruction. | 1180 // ucomiss/ucomisd - floating-point compare instruction. |
| 1159 class InstX8632Ucomiss : public InstX8632 { | 1181 class InstX8632Ucomiss : public InstX8632 { |
| 1182 InstX8632Ucomiss(const InstX8632Ucomiss &) = delete; | |
| 1183 InstX8632Ucomiss &operator=(const InstX8632Ucomiss &) = delete; | |
| 1184 | |
| 1160 public: | 1185 public: |
| 1161 static InstX8632Ucomiss *create(Cfg *Func, Operand *Src1, Operand *Src2) { | 1186 static InstX8632Ucomiss *create(Cfg *Func, Operand *Src1, Operand *Src2) { |
| 1162 return new (Func->allocate<InstX8632Ucomiss>()) | 1187 return new (Func->allocate<InstX8632Ucomiss>()) |
| 1163 InstX8632Ucomiss(Func, Src1, Src2); | 1188 InstX8632Ucomiss(Func, Src1, Src2); |
| 1164 } | 1189 } |
| 1165 void emit(const Cfg *Func) const override; | 1190 void emit(const Cfg *Func) const override; |
| 1166 void emitIAS(const Cfg *Func) const override; | 1191 void emitIAS(const Cfg *Func) const override; |
| 1167 void dump(const Cfg *Func) const override; | 1192 void dump(const Cfg *Func) const override; |
| 1168 static bool classof(const Inst *Inst) { return isClassof(Inst, Ucomiss); } | 1193 static bool classof(const Inst *Inst) { return isClassof(Inst, Ucomiss); } |
| 1169 | 1194 |
| 1170 private: | 1195 private: |
| 1171 InstX8632Ucomiss(Cfg *Func, Operand *Src1, Operand *Src2); | 1196 InstX8632Ucomiss(Cfg *Func, Operand *Src1, Operand *Src2); |
| 1172 InstX8632Ucomiss(const InstX8632Ucomiss &) = delete; | |
| 1173 InstX8632Ucomiss &operator=(const InstX8632Ucomiss &) = delete; | |
| 1174 ~InstX8632Ucomiss() override {} | 1197 ~InstX8632Ucomiss() override {} |
| 1175 }; | 1198 }; |
| 1176 | 1199 |
| 1177 // UD2 instruction. | 1200 // UD2 instruction. |
| 1178 class InstX8632UD2 : public InstX8632 { | 1201 class InstX8632UD2 : public InstX8632 { |
| 1202 InstX8632UD2(const InstX8632UD2 &) = delete; | |
| 1203 InstX8632UD2 &operator=(const InstX8632UD2 &) = delete; | |
| 1204 | |
| 1179 public: | 1205 public: |
| 1180 static InstX8632UD2 *create(Cfg *Func) { | 1206 static InstX8632UD2 *create(Cfg *Func) { |
| 1181 return new (Func->allocate<InstX8632UD2>()) InstX8632UD2(Func); | 1207 return new (Func->allocate<InstX8632UD2>()) InstX8632UD2(Func); |
| 1182 } | 1208 } |
| 1183 void emit(const Cfg *Func) const override; | 1209 void emit(const Cfg *Func) const override; |
| 1184 void emitIAS(const Cfg *Func) const override; | 1210 void emitIAS(const Cfg *Func) const override; |
| 1185 void dump(const Cfg *Func) const override; | 1211 void dump(const Cfg *Func) const override; |
| 1186 static bool classof(const Inst *Inst) { return isClassof(Inst, UD2); } | 1212 static bool classof(const Inst *Inst) { return isClassof(Inst, UD2); } |
| 1187 | 1213 |
| 1188 private: | 1214 private: |
| 1189 InstX8632UD2(Cfg *Func); | 1215 InstX8632UD2(Cfg *Func); |
| 1190 InstX8632UD2(const InstX8632UD2 &) = delete; | |
| 1191 InstX8632UD2 &operator=(const InstX8632UD2 &) = delete; | |
| 1192 ~InstX8632UD2() override {} | 1216 ~InstX8632UD2() override {} |
| 1193 }; | 1217 }; |
| 1194 | 1218 |
| 1195 // Test instruction. | 1219 // Test instruction. |
| 1196 class InstX8632Test : public InstX8632 { | 1220 class InstX8632Test : public InstX8632 { |
| 1221 InstX8632Test(const InstX8632Test &) = delete; | |
| 1222 InstX8632Test &operator=(const InstX8632Test &) = delete; | |
| 1223 | |
| 1197 public: | 1224 public: |
| 1198 static InstX8632Test *create(Cfg *Func, Operand *Source1, Operand *Source2) { | 1225 static InstX8632Test *create(Cfg *Func, Operand *Source1, Operand *Source2) { |
| 1199 return new (Func->allocate<InstX8632Test>()) | 1226 return new (Func->allocate<InstX8632Test>()) |
| 1200 InstX8632Test(Func, Source1, Source2); | 1227 InstX8632Test(Func, Source1, Source2); |
| 1201 } | 1228 } |
| 1202 void emit(const Cfg *Func) const override; | 1229 void emit(const Cfg *Func) const override; |
| 1203 void emitIAS(const Cfg *Func) const override; | 1230 void emitIAS(const Cfg *Func) const override; |
| 1204 void dump(const Cfg *Func) const override; | 1231 void dump(const Cfg *Func) const override; |
| 1205 static bool classof(const Inst *Inst) { return isClassof(Inst, Test); } | 1232 static bool classof(const Inst *Inst) { return isClassof(Inst, Test); } |
| 1206 | 1233 |
| 1207 private: | 1234 private: |
| 1208 InstX8632Test(Cfg *Func, Operand *Source1, Operand *Source2); | 1235 InstX8632Test(Cfg *Func, Operand *Source1, Operand *Source2); |
| 1209 InstX8632Test(const InstX8632Test &) = delete; | |
| 1210 InstX8632Test &operator=(const InstX8632Test &) = delete; | |
| 1211 ~InstX8632Test() override {} | 1236 ~InstX8632Test() override {} |
| 1212 }; | 1237 }; |
| 1213 | 1238 |
| 1214 // Mfence instruction. | 1239 // Mfence instruction. |
| 1215 class InstX8632Mfence : public InstX8632 { | 1240 class InstX8632Mfence : public InstX8632 { |
| 1241 InstX8632Mfence(const InstX8632Mfence &) = delete; | |
| 1242 InstX8632Mfence &operator=(const InstX8632Mfence &) = delete; | |
| 1243 | |
| 1216 public: | 1244 public: |
| 1217 static InstX8632Mfence *create(Cfg *Func) { | 1245 static InstX8632Mfence *create(Cfg *Func) { |
| 1218 return new (Func->allocate<InstX8632Mfence>()) InstX8632Mfence(Func); | 1246 return new (Func->allocate<InstX8632Mfence>()) InstX8632Mfence(Func); |
| 1219 } | 1247 } |
| 1220 void emit(const Cfg *Func) const override; | 1248 void emit(const Cfg *Func) const override; |
| 1221 void emitIAS(const Cfg *Func) const override; | 1249 void emitIAS(const Cfg *Func) const override; |
| 1222 void dump(const Cfg *Func) const override; | 1250 void dump(const Cfg *Func) const override; |
| 1223 static bool classof(const Inst *Inst) { return isClassof(Inst, Mfence); } | 1251 static bool classof(const Inst *Inst) { return isClassof(Inst, Mfence); } |
| 1224 | 1252 |
| 1225 private: | 1253 private: |
| 1226 InstX8632Mfence(Cfg *Func); | 1254 InstX8632Mfence(Cfg *Func); |
| 1227 InstX8632Mfence(const InstX8632Mfence &) = delete; | |
| 1228 InstX8632Mfence &operator=(const InstX8632Mfence &) = delete; | |
| 1229 ~InstX8632Mfence() override {} | 1255 ~InstX8632Mfence() override {} |
| 1230 }; | 1256 }; |
| 1231 | 1257 |
| 1232 // This is essentially a "mov" instruction with an OperandX8632Mem | 1258 // This is essentially a "mov" instruction with an OperandX8632Mem |
| 1233 // operand instead of Variable as the destination. It's important | 1259 // operand instead of Variable as the destination. It's important |
| 1234 // for liveness that there is no Dest operand. | 1260 // for liveness that there is no Dest operand. |
| 1235 class InstX8632Store : public InstX8632 { | 1261 class InstX8632Store : public InstX8632 { |
| 1262 InstX8632Store(const InstX8632Store &) = delete; | |
| 1263 InstX8632Store &operator=(const InstX8632Store &) = delete; | |
| 1264 | |
| 1236 public: | 1265 public: |
| 1237 static InstX8632Store *create(Cfg *Func, Operand *Value, OperandX8632 *Mem) { | 1266 static InstX8632Store *create(Cfg *Func, Operand *Value, OperandX8632 *Mem) { |
| 1238 return new (Func->allocate<InstX8632Store>()) | 1267 return new (Func->allocate<InstX8632Store>()) |
| 1239 InstX8632Store(Func, Value, Mem); | 1268 InstX8632Store(Func, Value, Mem); |
| 1240 } | 1269 } |
| 1241 void emit(const Cfg *Func) const override; | 1270 void emit(const Cfg *Func) const override; |
| 1242 void dump(const Cfg *Func) const override; | 1271 void dump(const Cfg *Func) const override; |
| 1243 static bool classof(const Inst *Inst) { return isClassof(Inst, Store); } | 1272 static bool classof(const Inst *Inst) { return isClassof(Inst, Store); } |
| 1244 | 1273 |
| 1245 private: | 1274 private: |
| 1246 InstX8632Store(Cfg *Func, Operand *Value, OperandX8632 *Mem); | 1275 InstX8632Store(Cfg *Func, Operand *Value, OperandX8632 *Mem); |
| 1247 InstX8632Store(const InstX8632Store &) = delete; | |
| 1248 InstX8632Store &operator=(const InstX8632Store &) = delete; | |
| 1249 ~InstX8632Store() override {} | 1276 ~InstX8632Store() override {} |
| 1250 }; | 1277 }; |
| 1251 | 1278 |
| 1252 // This is essentially a vector "mov" instruction with an OperandX8632Mem | 1279 // This is essentially a vector "mov" instruction with an OperandX8632Mem |
| 1253 // operand instead of Variable as the destination. It's important | 1280 // operand instead of Variable as the destination. It's important |
| 1254 // for liveness that there is no Dest operand. The source must be an | 1281 // for liveness that there is no Dest operand. The source must be an |
| 1255 // Xmm register, since Dest is mem. | 1282 // Xmm register, since Dest is mem. |
| 1256 class InstX8632StoreP : public InstX8632 { | 1283 class InstX8632StoreP : public InstX8632 { |
| 1284 InstX8632StoreP(const InstX8632StoreP &) = delete; | |
| 1285 InstX8632StoreP &operator=(const InstX8632StoreP &) = delete; | |
| 1286 | |
| 1257 public: | 1287 public: |
| 1258 static InstX8632StoreP *create(Cfg *Func, Variable *Value, | 1288 static InstX8632StoreP *create(Cfg *Func, Variable *Value, |
| 1259 OperandX8632Mem *Mem) { | 1289 OperandX8632Mem *Mem) { |
| 1260 return new (Func->allocate<InstX8632StoreP>()) | 1290 return new (Func->allocate<InstX8632StoreP>()) |
| 1261 InstX8632StoreP(Func, Value, Mem); | 1291 InstX8632StoreP(Func, Value, Mem); |
| 1262 } | 1292 } |
| 1263 void emit(const Cfg *Func) const override; | 1293 void emit(const Cfg *Func) const override; |
| 1264 void emitIAS(const Cfg *Func) const override; | 1294 void emitIAS(const Cfg *Func) const override; |
| 1265 void dump(const Cfg *Func) const override; | 1295 void dump(const Cfg *Func) const override; |
| 1266 static bool classof(const Inst *Inst) { return isClassof(Inst, StoreP); } | 1296 static bool classof(const Inst *Inst) { return isClassof(Inst, StoreP); } |
| 1267 | 1297 |
| 1268 private: | 1298 private: |
| 1269 InstX8632StoreP(Cfg *Func, Variable *Value, OperandX8632Mem *Mem); | 1299 InstX8632StoreP(Cfg *Func, Variable *Value, OperandX8632Mem *Mem); |
| 1270 InstX8632StoreP(const InstX8632StoreP &) = delete; | |
| 1271 InstX8632StoreP &operator=(const InstX8632StoreP &) = delete; | |
| 1272 ~InstX8632StoreP() override {} | 1300 ~InstX8632StoreP() override {} |
| 1273 }; | 1301 }; |
| 1274 | 1302 |
| 1275 class InstX8632StoreQ : public InstX8632 { | 1303 class InstX8632StoreQ : public InstX8632 { |
| 1304 InstX8632StoreQ(const InstX8632StoreQ &) = delete; | |
| 1305 InstX8632StoreQ &operator=(const InstX8632StoreQ &) = delete; | |
| 1306 | |
| 1276 public: | 1307 public: |
| 1277 static InstX8632StoreQ *create(Cfg *Func, Variable *Value, | 1308 static InstX8632StoreQ *create(Cfg *Func, Variable *Value, |
| 1278 OperandX8632Mem *Mem) { | 1309 OperandX8632Mem *Mem) { |
| 1279 return new (Func->allocate<InstX8632StoreQ>()) | 1310 return new (Func->allocate<InstX8632StoreQ>()) |
| 1280 InstX8632StoreQ(Func, Value, Mem); | 1311 InstX8632StoreQ(Func, Value, Mem); |
| 1281 } | 1312 } |
| 1282 void emit(const Cfg *Func) const override; | 1313 void emit(const Cfg *Func) const override; |
| 1283 void emitIAS(const Cfg *Func) const override; | 1314 void emitIAS(const Cfg *Func) const override; |
| 1284 void dump(const Cfg *Func) const override; | 1315 void dump(const Cfg *Func) const override; |
| 1285 static bool classof(const Inst *Inst) { return isClassof(Inst, StoreQ); } | 1316 static bool classof(const Inst *Inst) { return isClassof(Inst, StoreQ); } |
| 1286 | 1317 |
| 1287 private: | 1318 private: |
| 1288 InstX8632StoreQ(Cfg *Func, Variable *Value, OperandX8632Mem *Mem); | 1319 InstX8632StoreQ(Cfg *Func, Variable *Value, OperandX8632Mem *Mem); |
| 1289 InstX8632StoreQ(const InstX8632StoreQ &) = delete; | |
| 1290 InstX8632StoreQ &operator=(const InstX8632StoreQ &) = delete; | |
| 1291 ~InstX8632StoreQ() override {} | 1320 ~InstX8632StoreQ() override {} |
| 1292 }; | 1321 }; |
| 1293 | 1322 |
| 1294 // Movsx - copy from a narrower integer type to a wider integer | 1323 // Movsx - copy from a narrower integer type to a wider integer |
| 1295 // type, with sign extension. | 1324 // type, with sign extension. |
| 1296 class InstX8632Movsx : public InstX8632 { | 1325 class InstX8632Movsx : public InstX8632 { |
| 1326 InstX8632Movsx(const InstX8632Movsx &) = delete; | |
| 1327 InstX8632Movsx &operator=(const InstX8632Movsx &) = delete; | |
| 1328 | |
| 1297 public: | 1329 public: |
| 1298 static InstX8632Movsx *create(Cfg *Func, Variable *Dest, Operand *Source) { | 1330 static InstX8632Movsx *create(Cfg *Func, Variable *Dest, Operand *Source) { |
| 1299 return new (Func->allocate<InstX8632Movsx>()) | 1331 return new (Func->allocate<InstX8632Movsx>()) |
| 1300 InstX8632Movsx(Func, Dest, Source); | 1332 InstX8632Movsx(Func, Dest, Source); |
| 1301 } | 1333 } |
| 1302 void emit(const Cfg *Func) const override; | 1334 void emit(const Cfg *Func) const override; |
| 1303 void dump(const Cfg *Func) const override; | 1335 void dump(const Cfg *Func) const override; |
| 1304 static bool classof(const Inst *Inst) { return isClassof(Inst, Movsx); } | 1336 static bool classof(const Inst *Inst) { return isClassof(Inst, Movsx); } |
| 1305 | 1337 |
| 1306 private: | 1338 private: |
| 1307 InstX8632Movsx(Cfg *Func, Variable *Dest, Operand *Source); | 1339 InstX8632Movsx(Cfg *Func, Variable *Dest, Operand *Source); |
| 1308 InstX8632Movsx(const InstX8632Movsx &) = delete; | |
| 1309 InstX8632Movsx &operator=(const InstX8632Movsx &) = delete; | |
| 1310 ~InstX8632Movsx() override {} | 1340 ~InstX8632Movsx() override {} |
| 1311 }; | 1341 }; |
| 1312 | 1342 |
| 1313 // Movzx - copy from a narrower integer type to a wider integer | 1343 // Movzx - copy from a narrower integer type to a wider integer |
| 1314 // type, with zero extension. | 1344 // type, with zero extension. |
| 1315 class InstX8632Movzx : public InstX8632 { | 1345 class InstX8632Movzx : public InstX8632 { |
| 1346 InstX8632Movzx(const InstX8632Movzx &) = delete; | |
| 1347 InstX8632Movzx &operator=(const InstX8632Movzx &) = delete; | |
| 1348 | |
| 1316 public: | 1349 public: |
| 1317 static InstX8632Movzx *create(Cfg *Func, Variable *Dest, Operand *Source) { | 1350 static InstX8632Movzx *create(Cfg *Func, Variable *Dest, Operand *Source) { |
| 1318 return new (Func->allocate<InstX8632Movzx>()) | 1351 return new (Func->allocate<InstX8632Movzx>()) |
| 1319 InstX8632Movzx(Func, Dest, Source); | 1352 InstX8632Movzx(Func, Dest, Source); |
| 1320 } | 1353 } |
| 1321 void emit(const Cfg *Func) const override; | 1354 void emit(const Cfg *Func) const override; |
| 1322 void dump(const Cfg *Func) const override; | 1355 void dump(const Cfg *Func) const override; |
| 1323 static bool classof(const Inst *Inst) { return isClassof(Inst, Movzx); } | 1356 static bool classof(const Inst *Inst) { return isClassof(Inst, Movzx); } |
| 1324 | 1357 |
| 1325 private: | 1358 private: |
| 1326 InstX8632Movzx(Cfg *Func, Variable *Dest, Operand *Source); | 1359 InstX8632Movzx(Cfg *Func, Variable *Dest, Operand *Source); |
| 1327 InstX8632Movzx(const InstX8632Movzx &) = delete; | |
| 1328 InstX8632Movzx &operator=(const InstX8632Movzx &) = delete; | |
| 1329 ~InstX8632Movzx() override {} | 1360 ~InstX8632Movzx() override {} |
| 1330 }; | 1361 }; |
| 1331 | 1362 |
| 1332 // Nop instructions of varying length | 1363 // Nop instructions of varying length |
| 1333 class InstX8632Nop : public InstX8632 { | 1364 class InstX8632Nop : public InstX8632 { |
| 1365 InstX8632Nop(const InstX8632Nop &) = delete; | |
| 1366 InstX8632Nop &operator=(const InstX8632Nop &) = delete; | |
| 1367 | |
| 1334 public: | 1368 public: |
| 1335 // TODO: Replace with enum. | 1369 // TODO: Replace with enum. |
| 1336 typedef unsigned NopVariant; | 1370 typedef unsigned NopVariant; |
| 1337 | 1371 |
| 1338 static InstX8632Nop *create(Cfg *Func, NopVariant Variant) { | 1372 static InstX8632Nop *create(Cfg *Func, NopVariant Variant) { |
| 1339 return new (Func->allocate<InstX8632Nop>()) InstX8632Nop(Func, Variant); | 1373 return new (Func->allocate<InstX8632Nop>()) InstX8632Nop(Func, Variant); |
| 1340 } | 1374 } |
| 1341 void emit(const Cfg *Func) const override; | 1375 void emit(const Cfg *Func) const override; |
| 1342 void emitIAS(const Cfg *Func) const override; | 1376 void emitIAS(const Cfg *Func) const override; |
| 1343 void dump(const Cfg *Func) const override; | 1377 void dump(const Cfg *Func) const override; |
| 1344 static bool classof(const Inst *Inst) { return isClassof(Inst, Nop); } | 1378 static bool classof(const Inst *Inst) { return isClassof(Inst, Nop); } |
| 1345 | 1379 |
| 1346 private: | 1380 private: |
| 1347 InstX8632Nop(Cfg *Func, SizeT Length); | 1381 InstX8632Nop(Cfg *Func, SizeT Length); |
| 1348 InstX8632Nop(const InstX8632Nop &) = delete; | |
| 1349 InstX8632Nop &operator=(const InstX8632Nop &) = delete; | |
| 1350 ~InstX8632Nop() override {} | 1382 ~InstX8632Nop() override {} |
| 1351 | 1383 |
| 1352 NopVariant Variant; | 1384 NopVariant Variant; |
| 1353 }; | 1385 }; |
| 1354 | 1386 |
| 1355 // Fld - load a value onto the x87 FP stack. | 1387 // Fld - load a value onto the x87 FP stack. |
| 1356 class InstX8632Fld : public InstX8632 { | 1388 class InstX8632Fld : public InstX8632 { |
| 1389 InstX8632Fld(const InstX8632Fld &) = delete; | |
| 1390 InstX8632Fld &operator=(const InstX8632Fld &) = delete; | |
| 1391 | |
| 1357 public: | 1392 public: |
| 1358 static InstX8632Fld *create(Cfg *Func, Operand *Src) { | 1393 static InstX8632Fld *create(Cfg *Func, Operand *Src) { |
| 1359 return new (Func->allocate<InstX8632Fld>()) InstX8632Fld(Func, Src); | 1394 return new (Func->allocate<InstX8632Fld>()) InstX8632Fld(Func, Src); |
| 1360 } | 1395 } |
| 1361 void emit(const Cfg *Func) const override; | 1396 void emit(const Cfg *Func) const override; |
| 1362 void emitIAS(const Cfg *Func) const override; | 1397 void emitIAS(const Cfg *Func) const override; |
| 1363 void dump(const Cfg *Func) const override; | 1398 void dump(const Cfg *Func) const override; |
| 1364 static bool classof(const Inst *Inst) { return isClassof(Inst, Fld); } | 1399 static bool classof(const Inst *Inst) { return isClassof(Inst, Fld); } |
| 1365 | 1400 |
| 1366 private: | 1401 private: |
| 1367 InstX8632Fld(Cfg *Func, Operand *Src); | 1402 InstX8632Fld(Cfg *Func, Operand *Src); |
| 1368 InstX8632Fld(const InstX8632Fld &) = delete; | |
| 1369 InstX8632Fld &operator=(const InstX8632Fld &) = delete; | |
| 1370 ~InstX8632Fld() override {} | 1403 ~InstX8632Fld() override {} |
| 1371 }; | 1404 }; |
| 1372 | 1405 |
| 1373 // Fstp - store x87 st(0) into memory and pop st(0). | 1406 // Fstp - store x87 st(0) into memory and pop st(0). |
| 1374 class InstX8632Fstp : public InstX8632 { | 1407 class InstX8632Fstp : public InstX8632 { |
| 1408 InstX8632Fstp(const InstX8632Fstp &) = delete; | |
| 1409 InstX8632Fstp &operator=(const InstX8632Fstp &) = delete; | |
| 1410 | |
| 1375 public: | 1411 public: |
| 1376 static InstX8632Fstp *create(Cfg *Func, Variable *Dest) { | 1412 static InstX8632Fstp *create(Cfg *Func, Variable *Dest) { |
| 1377 return new (Func->allocate<InstX8632Fstp>()) InstX8632Fstp(Func, Dest); | 1413 return new (Func->allocate<InstX8632Fstp>()) InstX8632Fstp(Func, Dest); |
| 1378 } | 1414 } |
| 1379 void emit(const Cfg *Func) const override; | 1415 void emit(const Cfg *Func) const override; |
| 1380 void emitIAS(const Cfg *Func) const override; | 1416 void emitIAS(const Cfg *Func) const override; |
| 1381 void dump(const Cfg *Func) const override; | 1417 void dump(const Cfg *Func) const override; |
| 1382 static bool classof(const Inst *Inst) { return isClassof(Inst, Fstp); } | 1418 static bool classof(const Inst *Inst) { return isClassof(Inst, Fstp); } |
| 1383 | 1419 |
| 1384 private: | 1420 private: |
| 1385 InstX8632Fstp(Cfg *Func, Variable *Dest); | 1421 InstX8632Fstp(Cfg *Func, Variable *Dest); |
| 1386 InstX8632Fstp(const InstX8632Fstp &) = delete; | |
| 1387 InstX8632Fstp &operator=(const InstX8632Fstp &) = delete; | |
| 1388 ~InstX8632Fstp() override {} | 1422 ~InstX8632Fstp() override {} |
| 1389 }; | 1423 }; |
| 1390 | 1424 |
| 1391 class InstX8632Pop : public InstX8632 { | 1425 class InstX8632Pop : public InstX8632 { |
| 1426 InstX8632Pop(const InstX8632Pop &) = delete; | |
| 1427 InstX8632Pop &operator=(const InstX8632Pop &) = delete; | |
| 1428 | |
| 1392 public: | 1429 public: |
| 1393 static InstX8632Pop *create(Cfg *Func, Variable *Dest) { | 1430 static InstX8632Pop *create(Cfg *Func, Variable *Dest) { |
| 1394 return new (Func->allocate<InstX8632Pop>()) InstX8632Pop(Func, Dest); | 1431 return new (Func->allocate<InstX8632Pop>()) InstX8632Pop(Func, Dest); |
| 1395 } | 1432 } |
| 1396 void emit(const Cfg *Func) const override; | 1433 void emit(const Cfg *Func) const override; |
| 1397 void emitIAS(const Cfg *Func) const override; | 1434 void emitIAS(const Cfg *Func) const override; |
| 1398 void dump(const Cfg *Func) const override; | 1435 void dump(const Cfg *Func) const override; |
| 1399 static bool classof(const Inst *Inst) { return isClassof(Inst, Pop); } | 1436 static bool classof(const Inst *Inst) { return isClassof(Inst, Pop); } |
| 1400 | 1437 |
| 1401 private: | 1438 private: |
| 1402 InstX8632Pop(Cfg *Func, Variable *Dest); | 1439 InstX8632Pop(Cfg *Func, Variable *Dest); |
| 1403 InstX8632Pop(const InstX8632Pop &) = delete; | |
| 1404 InstX8632Pop &operator=(const InstX8632Pop &) = delete; | |
| 1405 ~InstX8632Pop() override {} | 1440 ~InstX8632Pop() override {} |
| 1406 }; | 1441 }; |
| 1407 | 1442 |
| 1408 class InstX8632Push : public InstX8632 { | 1443 class InstX8632Push : public InstX8632 { |
| 1444 InstX8632Push(const InstX8632Push &) = delete; | |
| 1445 InstX8632Push &operator=(const InstX8632Push &) = delete; | |
| 1446 | |
| 1409 public: | 1447 public: |
| 1410 static InstX8632Push *create(Cfg *Func, Variable *Source) { | 1448 static InstX8632Push *create(Cfg *Func, Variable *Source) { |
| 1411 return new (Func->allocate<InstX8632Push>()) | 1449 return new (Func->allocate<InstX8632Push>()) |
| 1412 InstX8632Push(Func, Source); | 1450 InstX8632Push(Func, Source); |
| 1413 } | 1451 } |
| 1414 void emit(const Cfg *Func) const override; | 1452 void emit(const Cfg *Func) const override; |
| 1415 void emitIAS(const Cfg *Func) const override; | 1453 void emitIAS(const Cfg *Func) const override; |
| 1416 void dump(const Cfg *Func) const override; | 1454 void dump(const Cfg *Func) const override; |
| 1417 static bool classof(const Inst *Inst) { return isClassof(Inst, Push); } | 1455 static bool classof(const Inst *Inst) { return isClassof(Inst, Push); } |
| 1418 | 1456 |
| 1419 private: | 1457 private: |
| 1420 InstX8632Push(Cfg *Func, Variable *Source); | 1458 InstX8632Push(Cfg *Func, Variable *Source); |
| 1421 InstX8632Push(const InstX8632Push &) = delete; | |
| 1422 InstX8632Push &operator=(const InstX8632Push &) = delete; | |
| 1423 ~InstX8632Push() override {} | 1459 ~InstX8632Push() override {} |
| 1424 }; | 1460 }; |
| 1425 | 1461 |
| 1426 // Ret instruction. Currently only supports the "ret" version that | 1462 // Ret instruction. Currently only supports the "ret" version that |
| 1427 // does not pop arguments. This instruction takes a Source operand | 1463 // does not pop arguments. This instruction takes a Source operand |
| 1428 // (for non-void returning functions) for liveness analysis, though | 1464 // (for non-void returning functions) for liveness analysis, though |
| 1429 // a FakeUse before the ret would do just as well. | 1465 // a FakeUse before the ret would do just as well. |
| 1430 class InstX8632Ret : public InstX8632 { | 1466 class InstX8632Ret : public InstX8632 { |
| 1467 InstX8632Ret(const InstX8632Ret &) = delete; | |
| 1468 InstX8632Ret &operator=(const InstX8632Ret &) = delete; | |
| 1469 | |
| 1431 public: | 1470 public: |
| 1432 static InstX8632Ret *create(Cfg *Func, Variable *Source = NULL) { | 1471 static InstX8632Ret *create(Cfg *Func, Variable *Source = NULL) { |
| 1433 return new (Func->allocate<InstX8632Ret>()) InstX8632Ret(Func, Source); | 1472 return new (Func->allocate<InstX8632Ret>()) InstX8632Ret(Func, Source); |
| 1434 } | 1473 } |
| 1435 void emit(const Cfg *Func) const override; | 1474 void emit(const Cfg *Func) const override; |
| 1436 void emitIAS(const Cfg *Func) const override; | 1475 void emitIAS(const Cfg *Func) const override; |
| 1437 void dump(const Cfg *Func) const override; | 1476 void dump(const Cfg *Func) const override; |
| 1438 static bool classof(const Inst *Inst) { return isClassof(Inst, Ret); } | 1477 static bool classof(const Inst *Inst) { return isClassof(Inst, Ret); } |
| 1439 | 1478 |
| 1440 private: | 1479 private: |
| 1441 InstX8632Ret(Cfg *Func, Variable *Source); | 1480 InstX8632Ret(Cfg *Func, Variable *Source); |
| 1442 InstX8632Ret(const InstX8632Ret &) = delete; | |
| 1443 InstX8632Ret &operator=(const InstX8632Ret &) = delete; | |
| 1444 ~InstX8632Ret() override {} | 1481 ~InstX8632Ret() override {} |
| 1445 }; | 1482 }; |
| 1446 | 1483 |
| 1447 // Exchanging Add instruction. Exchanges the first operand (destination | 1484 // Exchanging Add instruction. Exchanges the first operand (destination |
| 1448 // operand) with the second operand (source operand), then loads the sum | 1485 // operand) with the second operand (source operand), then loads the sum |
| 1449 // of the two values into the destination operand. The destination may be | 1486 // of the two values into the destination operand. The destination may be |
| 1450 // a register or memory, while the source must be a register. | 1487 // a register or memory, while the source must be a register. |
| 1451 // | 1488 // |
| 1452 // Both the dest and source are updated. The caller should then insert a | 1489 // Both the dest and source are updated. The caller should then insert a |
| 1453 // FakeDef to reflect the second udpate. | 1490 // FakeDef to reflect the second udpate. |
| 1454 class InstX8632Xadd : public InstX8632Lockable { | 1491 class InstX8632Xadd : public InstX8632Lockable { |
| 1492 InstX8632Xadd(const InstX8632Xadd &) = delete; | |
| 1493 InstX8632Xadd &operator=(const InstX8632Xadd &) = delete; | |
| 1494 | |
| 1455 public: | 1495 public: |
| 1456 static InstX8632Xadd *create(Cfg *Func, Operand *Dest, Variable *Source, | 1496 static InstX8632Xadd *create(Cfg *Func, Operand *Dest, Variable *Source, |
| 1457 bool Locked) { | 1497 bool Locked) { |
| 1458 return new (Func->allocate<InstX8632Xadd>()) | 1498 return new (Func->allocate<InstX8632Xadd>()) |
| 1459 InstX8632Xadd(Func, Dest, Source, Locked); | 1499 InstX8632Xadd(Func, Dest, Source, Locked); |
| 1460 } | 1500 } |
| 1461 void emit(const Cfg *Func) const override; | 1501 void emit(const Cfg *Func) const override; |
| 1462 void emitIAS(const Cfg *Func) const override; | 1502 void emitIAS(const Cfg *Func) const override; |
| 1463 void dump(const Cfg *Func) const override; | 1503 void dump(const Cfg *Func) const override; |
| 1464 static bool classof(const Inst *Inst) { return isClassof(Inst, Xadd); } | 1504 static bool classof(const Inst *Inst) { return isClassof(Inst, Xadd); } |
| 1465 | 1505 |
| 1466 private: | 1506 private: |
| 1467 InstX8632Xadd(Cfg *Func, Operand *Dest, Variable *Source, bool Locked); | 1507 InstX8632Xadd(Cfg *Func, Operand *Dest, Variable *Source, bool Locked); |
| 1468 InstX8632Xadd(const InstX8632Xadd &) = delete; | |
| 1469 InstX8632Xadd &operator=(const InstX8632Xadd &) = delete; | |
| 1470 ~InstX8632Xadd() override {} | 1508 ~InstX8632Xadd() override {} |
| 1471 }; | 1509 }; |
| 1472 | 1510 |
| 1473 // Exchange instruction. Exchanges the first operand (destination | 1511 // Exchange instruction. Exchanges the first operand (destination |
| 1474 // operand) with the second operand (source operand). At least one of | 1512 // operand) with the second operand (source operand). At least one of |
| 1475 // the operands must be a register (and the other can be reg or mem). | 1513 // the operands must be a register (and the other can be reg or mem). |
| 1476 // Both the Dest and Source are updated. If there is a memory operand, | 1514 // Both the Dest and Source are updated. If there is a memory operand, |
| 1477 // then the instruction is automatically "locked" without the need for | 1515 // then the instruction is automatically "locked" without the need for |
| 1478 // a lock prefix. | 1516 // a lock prefix. |
| 1479 class InstX8632Xchg : public InstX8632 { | 1517 class InstX8632Xchg : public InstX8632 { |
| 1518 InstX8632Xchg(const InstX8632Xchg &) = delete; | |
| 1519 InstX8632Xchg &operator=(const InstX8632Xchg &) = delete; | |
| 1520 | |
| 1480 public: | 1521 public: |
| 1481 static InstX8632Xchg *create(Cfg *Func, Operand *Dest, Variable *Source) { | 1522 static InstX8632Xchg *create(Cfg *Func, Operand *Dest, Variable *Source) { |
| 1482 return new (Func->allocate<InstX8632Xchg>()) | 1523 return new (Func->allocate<InstX8632Xchg>()) |
| 1483 InstX8632Xchg(Func, Dest, Source); | 1524 InstX8632Xchg(Func, Dest, Source); |
| 1484 } | 1525 } |
| 1485 void emit(const Cfg *Func) const override; | 1526 void emit(const Cfg *Func) const override; |
| 1486 void emitIAS(const Cfg *Func) const override; | 1527 void emitIAS(const Cfg *Func) const override; |
| 1487 void dump(const Cfg *Func) const override; | 1528 void dump(const Cfg *Func) const override; |
| 1488 static bool classof(const Inst *Inst) { return isClassof(Inst, Xchg); } | 1529 static bool classof(const Inst *Inst) { return isClassof(Inst, Xchg); } |
| 1489 | 1530 |
| 1490 private: | 1531 private: |
| 1491 InstX8632Xchg(Cfg *Func, Operand *Dest, Variable *Source); | 1532 InstX8632Xchg(Cfg *Func, Operand *Dest, Variable *Source); |
| 1492 InstX8632Xchg(const InstX8632Xchg &) = delete; | |
| 1493 InstX8632Xchg &operator=(const InstX8632Xchg &) = delete; | |
| 1494 ~InstX8632Xchg() override {} | 1533 ~InstX8632Xchg() override {} |
| 1495 }; | 1534 }; |
| 1496 | 1535 |
| 1497 // Declare partial template specializations of emit() methods that | 1536 // Declare partial template specializations of emit() methods that |
| 1498 // already have default implementations. Without this, there is the | 1537 // already have default implementations. Without this, there is the |
| 1499 // possibility of ODR violations and link errors. | 1538 // possibility of ODR violations and link errors. |
| 1500 template <> void InstX8632Addss::emit(const Cfg *Func) const; | 1539 template <> void InstX8632Addss::emit(const Cfg *Func) const; |
| 1501 template <> void InstX8632Blendvps::emit(const Cfg *Func) const; | 1540 template <> void InstX8632Blendvps::emit(const Cfg *Func) const; |
| 1502 template <> void InstX8632Cbwdq::emit(const Cfg *Func) const; | 1541 template <> void InstX8632Cbwdq::emit(const Cfg *Func) const; |
| 1503 template <> void InstX8632Div::emit(const Cfg *Func) const; | 1542 template <> void InstX8632Div::emit(const Cfg *Func) const; |
| (...skipping 27 matching lines...) Expand all Loading... | |
| 1531 template <> void InstX8632Pblendvb::emitIAS(const Cfg *Func) const; | 1570 template <> void InstX8632Pblendvb::emitIAS(const Cfg *Func) const; |
| 1532 template <> void InstX8632Pextr::emitIAS(const Cfg *Func) const; | 1571 template <> void InstX8632Pextr::emitIAS(const Cfg *Func) const; |
| 1533 template <> void InstX8632Pinsr::emitIAS(const Cfg *Func) const; | 1572 template <> void InstX8632Pinsr::emitIAS(const Cfg *Func) const; |
| 1534 template <> void InstX8632Pmull::emitIAS(const Cfg *Func) const; | 1573 template <> void InstX8632Pmull::emitIAS(const Cfg *Func) const; |
| 1535 template <> void InstX8632Pshufd::emitIAS(const Cfg *Func) const; | 1574 template <> void InstX8632Pshufd::emitIAS(const Cfg *Func) const; |
| 1536 template <> void InstX8632Shufps::emitIAS(const Cfg *Func) const; | 1575 template <> void InstX8632Shufps::emitIAS(const Cfg *Func) const; |
| 1537 | 1576 |
| 1538 } // end of namespace Ice | 1577 } // end of namespace Ice |
| 1539 | 1578 |
| 1540 #endif // SUBZERO_SRC_ICEINSTX8632_H | 1579 #endif // SUBZERO_SRC_ICEINSTX8632_H |
| OLD | NEW |