Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 //===- subzero/src/IceInstX86Base.h - Generic x86 instructions -*- C++ -*--===// | 1 //===- subzero/src/IceInstX86Base.h - Generic 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 /// \file | 10 /// \file |
| (...skipping 128 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 139 IacaStart, | 139 IacaStart, |
| 140 IacaEnd | 140 IacaEnd |
| 141 }; | 141 }; |
| 142 | 142 |
| 143 static const char *getWidthString(Type Ty); | 143 static const char *getWidthString(Type Ty); |
| 144 static const char *getFldString(Type Ty); | 144 static const char *getFldString(Type Ty); |
| 145 static typename Traits::Cond::BrCond | 145 static typename Traits::Cond::BrCond |
| 146 getOppositeCondition(typename Traits::Cond::BrCond Cond); | 146 getOppositeCondition(typename Traits::Cond::BrCond Cond); |
| 147 void dump(const Cfg *Func) const override; | 147 void dump(const Cfg *Func) const override; |
| 148 | 148 |
| 149 // Shared emit routines for common forms of instructions. | 149 // Shared emit routines for common forms of instructions. See the definition |
| 150 // See the definition of emitTwoAddress() for a description of | 150 // of emitTwoAddress() for a description of ShiftHack. |
| 151 // ShiftHack. | |
| 152 static void emitTwoAddress(const char *Opcode, const Inst *Inst, | 151 static void emitTwoAddress(const char *Opcode, const Inst *Inst, |
| 153 const Cfg *Func, bool ShiftHack = false); | 152 const Cfg *Func, bool ShiftHack = false); |
| 154 | 153 |
| 155 static void | 154 static void |
| 156 emitIASGPRShift(const Cfg *Func, Type Ty, const Variable *Var, | 155 emitIASGPRShift(const Cfg *Func, Type Ty, const Variable *Var, |
| 157 const Operand *Src, | 156 const Operand *Src, |
| 158 const typename Traits::Assembler::GPREmitterShiftOp &Emitter); | 157 const typename Traits::Assembler::GPREmitterShiftOp &Emitter); |
| 159 | 158 |
| 160 protected: | 159 protected: |
| 161 InstX86Base<Machine>(Cfg *Func, InstKindX86 Kind, SizeT Maxsrcs, | 160 InstX86Base<Machine>(Cfg *Func, InstKindX86 Kind, SizeT Maxsrcs, |
| 162 Variable *Dest) | 161 Variable *Dest) |
| 163 : InstTarget(Func, static_cast<InstKind>(Kind), Maxsrcs, Dest) {} | 162 : InstTarget(Func, static_cast<InstKind>(Kind), Maxsrcs, Dest) {} |
| 164 | 163 |
| 165 static bool isClassof(const Inst *Inst, InstKindX86 MyKind) { | 164 static bool isClassof(const Inst *Inst, InstKindX86 MyKind) { |
| 166 return Inst->getKind() == static_cast<InstKind>(MyKind); | 165 return Inst->getKind() == static_cast<InstKind>(MyKind); |
| 167 } | 166 } |
| 168 // Most instructions that operate on vector arguments require vector | 167 // Most instructions that operate on vector arguments require vector memory |
| 169 // memory operands to be fully aligned (16-byte alignment for PNaCl | 168 // operands to be fully aligned (16-byte alignment for PNaCl vector types). |
| 170 // vector types). The stack frame layout and call ABI ensure proper | 169 // The stack frame layout and call ABI ensure proper alignment for stack |
| 171 // alignment for stack operands, but memory operands (originating | 170 // operands, but memory operands (originating from load/store bitcode |
| 172 // from load/store bitcode instructions) only have element-size | 171 // instructions) only have element-size alignment guarantees. This function |
| 173 // alignment guarantees. This function validates that none of the | 172 // validates that none of the operands is a memory operand of vector type, |
| 174 // operands is a memory operand of vector type, calling | 173 // calling report_fatal_error() if one is found. This function should be |
| 175 // report_fatal_error() if one is found. This function should be | 174 // called during emission, and maybe also in the ctor (as long as that fits |
| 176 // called during emission, and maybe also in the ctor (as long as | 175 // the lowering style). |
| 177 // that fits the lowering style). | |
| 178 void validateVectorAddrMode() const { | 176 void validateVectorAddrMode() const { |
| 179 if (this->getDest()) | 177 if (this->getDest()) |
| 180 this->validateVectorAddrModeOpnd(this->getDest()); | 178 this->validateVectorAddrModeOpnd(this->getDest()); |
| 181 for (SizeT i = 0; i < this->getSrcSize(); ++i) { | 179 for (SizeT i = 0; i < this->getSrcSize(); ++i) { |
| 182 this->validateVectorAddrModeOpnd(this->getSrc(i)); | 180 this->validateVectorAddrModeOpnd(this->getSrc(i)); |
| 183 } | 181 } |
| 184 } | 182 } |
| 185 | 183 |
| 186 private: | 184 private: |
| 187 static void validateVectorAddrModeOpnd(const Operand *Opnd) { | 185 static void validateVectorAddrModeOpnd(const Operand *Opnd) { |
| 188 if (llvm::isa<typename InstX86Base<Machine>::Traits::X86OperandMem>(Opnd) && | 186 if (llvm::isa<typename InstX86Base<Machine>::Traits::X86OperandMem>(Opnd) && |
| 189 isVectorType(Opnd->getType())) { | 187 isVectorType(Opnd->getType())) { |
| 190 llvm::report_fatal_error("Possible misaligned vector memory operation"); | 188 llvm::report_fatal_error("Possible misaligned vector memory operation"); |
| 191 } | 189 } |
| 192 } | 190 } |
| 193 }; | 191 }; |
| 194 | 192 |
| 195 /// InstX86FakeRMW represents a non-atomic read-modify-write operation on a | 193 /// InstX86FakeRMW represents a non-atomic read-modify-write operation on a |
| 196 /// memory location. An InstX86FakeRMW is a "fake" instruction in that it | 194 /// memory location. An InstX86FakeRMW is a "fake" instruction in that it still |
| 197 /// still needs to be lowered to some actual RMW instruction. | 195 /// needs to be lowered to some actual RMW instruction. |
| 198 /// | 196 /// |
| 199 /// If A is some memory address, D is some data value to apply, and OP is an | 197 /// If A is some memory address, D is some data value to apply, and OP is an |
| 200 /// arithmetic operator, the instruction operates as: (*A) = (*A) OP D | 198 /// arithmetic operator, the instruction operates as: (*A) = (*A) OP D |
| 201 template <class Machine> | 199 template <class Machine> |
| 202 class InstX86FakeRMW final : public InstX86Base<Machine> { | 200 class InstX86FakeRMW final : public InstX86Base<Machine> { |
| 203 InstX86FakeRMW() = delete; | 201 InstX86FakeRMW() = delete; |
| 204 InstX86FakeRMW(const InstX86FakeRMW &) = delete; | 202 InstX86FakeRMW(const InstX86FakeRMW &) = delete; |
| 205 InstX86FakeRMW &operator=(const InstX86FakeRMW &) = delete; | 203 InstX86FakeRMW &operator=(const InstX86FakeRMW &) = delete; |
| 206 | 204 |
| 207 public: | 205 public: |
| (...skipping 13 matching lines...) Expand all Loading... | |
| 221 static bool classof(const Inst *Inst) { | 219 static bool classof(const Inst *Inst) { |
| 222 return InstX86Base<Machine>::isClassof(Inst, InstX86Base<Machine>::FakeRMW); | 220 return InstX86Base<Machine>::isClassof(Inst, InstX86Base<Machine>::FakeRMW); |
| 223 } | 221 } |
| 224 | 222 |
| 225 private: | 223 private: |
| 226 InstArithmetic::OpKind Op; | 224 InstArithmetic::OpKind Op; |
| 227 InstX86FakeRMW(Cfg *Func, Operand *Data, Operand *Addr, | 225 InstX86FakeRMW(Cfg *Func, Operand *Data, Operand *Addr, |
| 228 InstArithmetic::OpKind Op, Variable *Beacon); | 226 InstArithmetic::OpKind Op, Variable *Beacon); |
| 229 }; | 227 }; |
| 230 | 228 |
| 231 /// InstX86Label represents an intra-block label that is the target | 229 /// InstX86Label represents an intra-block label that is the target of an |
| 232 /// of an intra-block branch. The offset between the label and the | 230 /// intra-block branch. The offset between the label and the branch must be fit |
| 233 /// branch must be fit into one byte (considered "near"). These are | 231 /// into one byte (considered "near"). These are used for lowering i1 |
| 234 /// used for lowering i1 calculations, Select instructions, and 64-bit | 232 /// calculations, Select instructions, and 64-bit compares on a 32-bit |
| 235 /// compares on a 32-bit architecture, without basic block splitting. | 233 /// architecture, without basic block splitting. Basic block splitting is not so |
| 236 /// Basic block splitting is not so desirable for several reasons, one | 234 /// desirable for several reasons, one of which is the impact on decisions based |
| 237 /// of which is the impact on decisions based on whether a variable's | 235 /// on whether a variable's live range spans multiple basic blocks. |
| 238 /// live range spans multiple basic blocks. | |
| 239 /// | 236 /// |
| 240 /// Intra-block control flow must be used with caution. Consider the | 237 /// Intra-block control flow must be used with caution. Consider the sequence |
| 241 /// sequence for "c = (a >= b ? x : y)". | 238 /// for "c = (a >= b ? x : y)". |
| 242 /// cmp a, b | 239 /// cmp a, b |
| 243 /// br lt, L1 | 240 /// br lt, L1 |
| 244 /// mov c, x | 241 /// mov c, x |
| 245 /// jmp L2 | 242 /// jmp L2 |
| 246 /// L1: | 243 /// L1: |
| 247 /// mov c, y | 244 /// mov c, y |
| 248 /// L2: | 245 /// L2: |
| 249 /// | 246 /// |
| 250 /// Labels L1 and L2 are intra-block labels. Without knowledge of the | 247 /// Labels L1 and L2 are intra-block labels. Without knowledge of the |
| 251 /// intra-block control flow, liveness analysis will determine the "mov | 248 /// intra-block control flow, liveness analysis will determine the "mov c, x" |
| 252 /// c, x" instruction to be dead. One way to prevent this is to insert | 249 /// instruction to be dead. One way to prevent this is to insert a "FakeUse(c)" |
| 253 /// a "FakeUse(c)" instruction anywhere between the two "mov c, ..." | 250 /// instruction anywhere between the two "mov c, ..." instructions, e.g.: |
| 254 /// instructions, e.g.: | |
| 255 /// | 251 /// |
| 256 /// cmp a, b | 252 /// cmp a, b |
| 257 /// br lt, L1 | 253 /// br lt, L1 |
| 258 /// mov c, x | 254 /// mov c, x |
| 259 /// jmp L2 | 255 /// jmp L2 |
| 260 /// FakeUse(c) | 256 /// FakeUse(c) |
| 261 /// L1: | 257 /// L1: |
| 262 /// mov c, y | 258 /// mov c, y |
| 263 /// L2: | 259 /// L2: |
| 264 /// | 260 /// |
| 265 /// The down-side is that "mov c, x" can never be dead-code eliminated | 261 /// The down-side is that "mov c, x" can never be dead-code eliminated even if |
| 266 /// even if there are no uses of c. As unlikely as this situation is, | 262 /// there are no uses of c. As unlikely as this situation is, it may be |
| 267 /// it may be prevented by running dead code elimination before | 263 /// prevented by running dead code elimination before lowering. |
| 268 /// lowering. | |
| 269 template <class Machine> | 264 template <class Machine> |
| 270 class InstX86Label final : public InstX86Base<Machine> { | 265 class InstX86Label final : public InstX86Base<Machine> { |
| 271 InstX86Label() = delete; | 266 InstX86Label() = delete; |
| 272 InstX86Label(const InstX86Label &) = delete; | 267 InstX86Label(const InstX86Label &) = delete; |
| 273 InstX86Label &operator=(const InstX86Label &) = delete; | 268 InstX86Label &operator=(const InstX86Label &) = delete; |
| 274 | 269 |
| 275 public: | 270 public: |
| 276 static InstX86Label * | 271 static InstX86Label * |
| 277 create(Cfg *Func, | 272 create(Cfg *Func, |
| 278 typename InstX86Base<Machine>::Traits::TargetLowering *Target) { | 273 typename InstX86Base<Machine>::Traits::TargetLowering *Target) { |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 312 InstX86Br(Func, TargetTrue, TargetFalse, NoLabel, Condition, Kind); | 307 InstX86Br(Func, TargetTrue, TargetFalse, NoLabel, Condition, Kind); |
| 313 } | 308 } |
| 314 /// Create an unconditional branch to a node. | 309 /// Create an unconditional branch to a node. |
| 315 static InstX86Br *create(Cfg *Func, CfgNode *Target, Mode Kind) { | 310 static InstX86Br *create(Cfg *Func, CfgNode *Target, Mode Kind) { |
| 316 const CfgNode *NoCondTarget = nullptr; | 311 const CfgNode *NoCondTarget = nullptr; |
| 317 const InstX86Label<Machine> *NoLabel = nullptr; | 312 const InstX86Label<Machine> *NoLabel = nullptr; |
| 318 return new (Func->allocate<InstX86Br>()) | 313 return new (Func->allocate<InstX86Br>()) |
| 319 InstX86Br(Func, NoCondTarget, Target, NoLabel, | 314 InstX86Br(Func, NoCondTarget, Target, NoLabel, |
| 320 InstX86Base<Machine>::Traits::Cond::Br_None, Kind); | 315 InstX86Base<Machine>::Traits::Cond::Br_None, Kind); |
| 321 } | 316 } |
| 322 /// Create a non-terminator conditional branch to a node, with a | 317 /// Create a non-terminator conditional branch to a node, with a fallthrough |
| 323 /// fallthrough to the next instruction in the current node. This is | 318 /// to the next instruction in the current node. This is used for switch |
| 324 /// used for switch lowering. | 319 /// lowering. |
| 325 static InstX86Br * | 320 static InstX86Br * |
| 326 create(Cfg *Func, CfgNode *Target, | 321 create(Cfg *Func, CfgNode *Target, |
| 327 typename InstX86Base<Machine>::Traits::Cond::BrCond Condition, | 322 typename InstX86Base<Machine>::Traits::Cond::BrCond Condition, |
| 328 Mode Kind) { | 323 Mode Kind) { |
| 329 assert(Condition != InstX86Base<Machine>::Traits::Cond::Br_None); | 324 assert(Condition != InstX86Base<Machine>::Traits::Cond::Br_None); |
| 330 const CfgNode *NoUncondTarget = nullptr; | 325 const CfgNode *NoUncondTarget = nullptr; |
| 331 const InstX86Label<Machine> *NoLabel = nullptr; | 326 const InstX86Label<Machine> *NoLabel = nullptr; |
| 332 return new (Func->allocate<InstX86Br>()) | 327 return new (Func->allocate<InstX86Br>()) |
| 333 InstX86Br(Func, Target, NoUncondTarget, NoLabel, Condition, Kind); | 328 InstX86Br(Func, Target, NoUncondTarget, NoLabel, Condition, Kind); |
| 334 } | 329 } |
| (...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 374 typename InstX86Base<Machine>::Traits::Cond::BrCond Condition, | 369 typename InstX86Base<Machine>::Traits::Cond::BrCond Condition, |
| 375 Mode Kind); | 370 Mode Kind); |
| 376 | 371 |
| 377 typename InstX86Base<Machine>::Traits::Cond::BrCond Condition; | 372 typename InstX86Base<Machine>::Traits::Cond::BrCond Condition; |
| 378 const CfgNode *TargetTrue; | 373 const CfgNode *TargetTrue; |
| 379 const CfgNode *TargetFalse; | 374 const CfgNode *TargetFalse; |
| 380 const InstX86Label<Machine> *Label; // Intra-block branch target | 375 const InstX86Label<Machine> *Label; // Intra-block branch target |
| 381 const Mode Kind; | 376 const Mode Kind; |
| 382 }; | 377 }; |
| 383 | 378 |
| 384 /// Jump to a target outside this function, such as tailcall, nacljump, | 379 /// Jump to a target outside this function, such as tailcall, nacljump, naclret, |
| 385 /// naclret, unreachable. This is different from a Branch instruction | 380 /// unreachable. This is different from a Branch instruction in that there is no |
| 386 /// in that there is no intra-function control flow to represent. | 381 /// intra-function control flow to represent. |
| 387 template <class Machine> class InstX86Jmp final : public InstX86Base<Machine> { | 382 template <class Machine> class InstX86Jmp final : public InstX86Base<Machine> { |
| 388 InstX86Jmp() = delete; | 383 InstX86Jmp() = delete; |
| 389 InstX86Jmp(const InstX86Jmp &) = delete; | 384 InstX86Jmp(const InstX86Jmp &) = delete; |
| 390 InstX86Jmp &operator=(const InstX86Jmp &) = delete; | 385 InstX86Jmp &operator=(const InstX86Jmp &) = delete; |
| 391 | 386 |
| 392 public: | 387 public: |
| 393 static InstX86Jmp *create(Cfg *Func, Operand *Target) { | 388 static InstX86Jmp *create(Cfg *Func, Operand *Target) { |
| 394 return new (Func->allocate<InstX86Jmp>()) InstX86Jmp(Func, Target); | 389 return new (Func->allocate<InstX86Jmp>()) InstX86Jmp(Func, Target); |
| 395 } | 390 } |
| 396 Operand *getJmpTarget() const { return this->getSrc(0); } | 391 Operand *getJmpTarget() const { return this->getSrc(0); } |
| 397 void emit(const Cfg *Func) const override; | 392 void emit(const Cfg *Func) const override; |
| 398 void emitIAS(const Cfg *Func) const override; | 393 void emitIAS(const Cfg *Func) const override; |
| 399 void dump(const Cfg *Func) const override; | 394 void dump(const Cfg *Func) const override; |
| 400 static bool classof(const Inst *Inst) { | 395 static bool classof(const Inst *Inst) { |
| 401 return InstX86Base<Machine>::isClassof(Inst, InstX86Base<Machine>::Jmp); | 396 return InstX86Base<Machine>::isClassof(Inst, InstX86Base<Machine>::Jmp); |
| 402 } | 397 } |
| 403 | 398 |
| 404 private: | 399 private: |
| 405 InstX86Jmp(Cfg *Func, Operand *Target); | 400 InstX86Jmp(Cfg *Func, Operand *Target); |
| 406 }; | 401 }; |
| 407 | 402 |
| 408 /// AdjustStack instruction - subtracts esp by the given amount and | 403 /// AdjustStack instruction - subtracts esp by the given amount and updates the |
| 409 /// updates the stack offset during code emission. | 404 /// stack offset during code emission. |
| 410 template <class Machine> | 405 template <class Machine> |
| 411 class InstX86AdjustStack final : public InstX86Base<Machine> { | 406 class InstX86AdjustStack final : public InstX86Base<Machine> { |
| 412 InstX86AdjustStack() = delete; | 407 InstX86AdjustStack() = delete; |
| 413 InstX86AdjustStack(const InstX86AdjustStack &) = delete; | 408 InstX86AdjustStack(const InstX86AdjustStack &) = delete; |
| 414 InstX86AdjustStack &operator=(const InstX86AdjustStack &) = delete; | 409 InstX86AdjustStack &operator=(const InstX86AdjustStack &) = delete; |
| 415 | 410 |
| 416 public: | 411 public: |
| 417 static InstX86AdjustStack *create(Cfg *Func, SizeT Amount, Variable *Esp) { | 412 static InstX86AdjustStack *create(Cfg *Func, SizeT Amount, Variable *Esp) { |
| 418 return new (Func->allocate<InstX86AdjustStack>()) | 413 return new (Func->allocate<InstX86AdjustStack>()) |
| 419 InstX86AdjustStack(Func, Amount, Esp); | 414 InstX86AdjustStack(Func, Amount, Esp); |
| 420 } | 415 } |
| 421 void emit(const Cfg *Func) const override; | 416 void emit(const Cfg *Func) const override; |
| 422 void emitIAS(const Cfg *Func) const override; | 417 void emitIAS(const Cfg *Func) const override; |
| 423 void dump(const Cfg *Func) const override; | 418 void dump(const Cfg *Func) const override; |
| 424 static bool classof(const Inst *Inst) { | 419 static bool classof(const Inst *Inst) { |
| 425 return InstX86Base<Machine>::isClassof(Inst, | 420 return InstX86Base<Machine>::isClassof(Inst, |
| 426 InstX86Base<Machine>::Adjuststack); | 421 InstX86Base<Machine>::Adjuststack); |
| 427 } | 422 } |
| 428 | 423 |
| 429 private: | 424 private: |
| 430 InstX86AdjustStack(Cfg *Func, SizeT Amount, Variable *Esp); | 425 InstX86AdjustStack(Cfg *Func, SizeT Amount, Variable *Esp); |
| 431 SizeT Amount; | 426 SizeT Amount; |
| 432 }; | 427 }; |
| 433 | 428 |
| 434 /// Call instruction. Arguments should have already been pushed. | 429 /// Call instruction. Arguments should have already been pushed. |
| 435 template <class Machine> class InstX86Call final : public InstX86Base<Machine> { | 430 template <class Machine> class InstX86Call final : public InstX86Base<Machine> { |
| 436 InstX86Call() = delete; | 431 InstX86Call() = delete; |
| 437 InstX86Call(const InstX86Call &) = delete; | 432 InstX86Call(const InstX86Call &) = delete; |
| 438 InstX86Call &operator=(const InstX86Call &) = delete; | 433 InstX86Call &operator=(const InstX86Call &) = delete; |
| 439 | 434 |
| 440 public: | 435 public: |
| 441 static InstX86Call *create(Cfg *Func, Variable *Dest, Operand *CallTarget) { | 436 static InstX86Call *create(Cfg *Func, Variable *Dest, Operand *CallTarget) { |
| 442 return new (Func->allocate<InstX86Call>()) | 437 return new (Func->allocate<InstX86Call>()) |
| 443 InstX86Call(Func, Dest, CallTarget); | 438 InstX86Call(Func, Dest, CallTarget); |
| 444 } | 439 } |
| (...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 507 : InstX86Base<Machine>(Func, K, 1, llvm::dyn_cast<Variable>(SrcDest)) { | 502 : InstX86Base<Machine>(Func, K, 1, llvm::dyn_cast<Variable>(SrcDest)) { |
| 508 this->addSource(SrcDest); | 503 this->addSource(SrcDest); |
| 509 } | 504 } |
| 510 | 505 |
| 511 private: | 506 private: |
| 512 static const char *Opcode; | 507 static const char *Opcode; |
| 513 static const typename InstX86Base<Machine>::Traits::Assembler::GPREmitterOneOp | 508 static const typename InstX86Base<Machine>::Traits::Assembler::GPREmitterOneOp |
| 514 Emitter; | 509 Emitter; |
| 515 }; | 510 }; |
| 516 | 511 |
| 517 /// Emit a two-operand (GPR) instruction, where the dest operand is a | 512 /// Emit a two-operand (GPR) instruction, where the dest operand is a Variable |
| 518 /// Variable that's guaranteed to be a register. | 513 /// that's guaranteed to be a register. |
| 519 template <class Machine, bool VarCanBeByte = true, bool SrcCanBeByte = true> | 514 template <class Machine, bool VarCanBeByte = true, bool SrcCanBeByte = true> |
| 520 void emitIASRegOpTyGPR( | 515 void emitIASRegOpTyGPR( |
| 521 const Cfg *Func, Type Ty, const Variable *Dst, const Operand *Src, | 516 const Cfg *Func, Type Ty, const Variable *Dst, const Operand *Src, |
| 522 const typename InstX86Base<Machine>::Traits::Assembler::GPREmitterRegOp | 517 const typename InstX86Base<Machine>::Traits::Assembler::GPREmitterRegOp |
| 523 &Emitter); | 518 &Emitter); |
| 524 | 519 |
| 525 /// Instructions of the form x := op(y). | 520 /// Instructions of the form x := op(y). |
| 526 template <class Machine, typename InstX86Base<Machine>::InstKindX86 K> | 521 template <class Machine, typename InstX86Base<Machine>::InstKindX86 K> |
| 527 class InstX86BaseUnaryopGPR : public InstX86Base<Machine> { | 522 class InstX86BaseUnaryopGPR : public InstX86Base<Machine> { |
| 528 InstX86BaseUnaryopGPR() = delete; | 523 InstX86BaseUnaryopGPR() = delete; |
| 529 InstX86BaseUnaryopGPR(const InstX86BaseUnaryopGPR &) = delete; | 524 InstX86BaseUnaryopGPR(const InstX86BaseUnaryopGPR &) = delete; |
| 530 InstX86BaseUnaryopGPR &operator=(const InstX86BaseUnaryopGPR &) = delete; | 525 InstX86BaseUnaryopGPR &operator=(const InstX86BaseUnaryopGPR &) = delete; |
| 531 | 526 |
| 532 public: | 527 public: |
| 533 using Base = InstX86BaseUnaryopGPR<Machine, K>; | 528 using Base = InstX86BaseUnaryopGPR<Machine, K>; |
| 534 | 529 |
| 535 void emit(const Cfg *Func) const override { | 530 void emit(const Cfg *Func) const override { |
| 536 if (!BuildDefs::dump()) | 531 if (!BuildDefs::dump()) |
| 537 return; | 532 return; |
| 538 Ostream &Str = Func->getContext()->getStrEmit(); | 533 Ostream &Str = Func->getContext()->getStrEmit(); |
| 539 assert(this->getSrcSize() == 1); | 534 assert(this->getSrcSize() == 1); |
| 540 Type SrcTy = this->getSrc(0)->getType(); | 535 Type SrcTy = this->getSrc(0)->getType(); |
| 541 Type DestTy = this->getDest()->getType(); | 536 Type DestTy = this->getDest()->getType(); |
| 542 Str << "\t" << Opcode << this->getWidthString(SrcTy); | 537 Str << "\t" << Opcode << this->getWidthString(SrcTy); |
| 543 // Movsx and movzx need both the source and dest type width letter | 538 // Movsx and movzx need both the source and dest type width letter to |
| 544 // to define the operation. The other unary operations have the | 539 // define the operation. The other unary operations have the same source |
| 545 // same source and dest type and as a result need only one letter. | 540 // and dest type and as a result need only one letter. |
| 546 if (SrcTy != DestTy) | 541 if (SrcTy != DestTy) |
| 547 Str << this->getWidthString(DestTy); | 542 Str << this->getWidthString(DestTy); |
| 548 Str << "\t"; | 543 Str << "\t"; |
| 549 this->getSrc(0)->emit(Func); | 544 this->getSrc(0)->emit(Func); |
| 550 Str << ", "; | 545 Str << ", "; |
| 551 this->getDest()->emit(Func); | 546 this->getDest()->emit(Func); |
| 552 } | 547 } |
| 553 void emitIAS(const Cfg *Func) const override { | 548 void emitIAS(const Cfg *Func) const override { |
| 554 assert(this->getSrcSize() == 1); | 549 assert(this->getSrcSize() == 1); |
| 555 const Variable *Var = this->getDest(); | 550 const Variable *Var = this->getDest(); |
| (...skipping 618 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1174 | 1169 |
| 1175 void emit(const Cfg *Func) const override; | 1170 void emit(const Cfg *Func) const override; |
| 1176 void emitIAS(const Cfg *Func) const override; | 1171 void emitIAS(const Cfg *Func) const override; |
| 1177 | 1172 |
| 1178 private: | 1173 private: |
| 1179 InstX86Mov(Cfg *Func, Variable *Dest, Operand *Source) | 1174 InstX86Mov(Cfg *Func, Variable *Dest, Operand *Source) |
| 1180 : InstX86BaseMovlike<Machine, InstX86Base<Machine>::Mov>(Func, Dest, | 1175 : InstX86BaseMovlike<Machine, InstX86Base<Machine>::Mov>(Func, Dest, |
| 1181 Source) {} | 1176 Source) {} |
| 1182 }; | 1177 }; |
| 1183 | 1178 |
| 1184 /// Move packed - copy 128 bit values between XMM registers, or mem128 | 1179 /// Move packed - copy 128 bit values between XMM registers, or mem128 and XMM |
| 1185 /// and XMM registers. | 1180 /// registers. |
| 1186 template <class Machine> | 1181 template <class Machine> |
| 1187 class InstX86Movp | 1182 class InstX86Movp |
| 1188 : public InstX86BaseMovlike<Machine, InstX86Base<Machine>::Movp> { | 1183 : public InstX86BaseMovlike<Machine, InstX86Base<Machine>::Movp> { |
| 1189 public: | 1184 public: |
| 1190 static InstX86Movp *create(Cfg *Func, Variable *Dest, Operand *Source) { | 1185 static InstX86Movp *create(Cfg *Func, Variable *Dest, Operand *Source) { |
| 1191 return new (Func->allocate<InstX86Movp>()) InstX86Movp(Func, Dest, Source); | 1186 return new (Func->allocate<InstX86Movp>()) InstX86Movp(Func, Dest, Source); |
| 1192 } | 1187 } |
| 1193 | 1188 |
| 1194 void emit(const Cfg *Func) const override; | 1189 void emit(const Cfg *Func) const override; |
| 1195 void emitIAS(const Cfg *Func) const override; | 1190 void emitIAS(const Cfg *Func) const override; |
| (...skipping 662 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1858 } | 1853 } |
| 1859 | 1854 |
| 1860 void emit(const Cfg *Func) const override; | 1855 void emit(const Cfg *Func) const override; |
| 1861 | 1856 |
| 1862 private: | 1857 private: |
| 1863 InstX86Pcmpgt(Cfg *Func, Variable *Dest, Operand *Source) | 1858 InstX86Pcmpgt(Cfg *Func, Variable *Dest, Operand *Source) |
| 1864 : InstX86BaseBinopXmm<Machine, InstX86Base<Machine>::Pcmpgt, true>( | 1859 : InstX86BaseBinopXmm<Machine, InstX86Base<Machine>::Pcmpgt, true>( |
| 1865 Func, Dest, Source) {} | 1860 Func, Dest, Source) {} |
| 1866 }; | 1861 }; |
| 1867 | 1862 |
| 1868 /// movss is only a binary operation when the source and dest | 1863 /// movss is only a binary operation when the source and dest operands are both |
| 1869 /// operands are both registers (the high bits of dest are left untouched). | 1864 /// registers (the high bits of dest are left untouched). In other cases, it |
| 1870 /// In other cases, it behaves like a copy (mov-like) operation (and the | 1865 /// behaves like a copy (mov-like) operation (and the high bits of dest are |
| 1871 /// high bits of dest are cleared). | 1866 /// cleared). InstX86Movss will assert that both its source and dest operands |
| 1872 /// InstX86Movss will assert that both its source and dest operands are | 1867 /// are registers, so the lowering code should use _mov instead of _movss in |
| 1873 /// registers, so the lowering code should use _mov instead of _movss | 1868 /// cases where a copy operation is intended. |
| 1874 /// in cases where a copy operation is intended. | |
| 1875 template <class Machine> | 1869 template <class Machine> |
| 1876 class InstX86MovssRegs | 1870 class InstX86MovssRegs |
| 1877 : public InstX86BaseBinopXmm<Machine, InstX86Base<Machine>::MovssRegs, | 1871 : public InstX86BaseBinopXmm<Machine, InstX86Base<Machine>::MovssRegs, |
| 1878 false> { | 1872 false> { |
| 1879 public: | 1873 public: |
| 1880 static InstX86MovssRegs *create(Cfg *Func, Variable *Dest, Operand *Source) { | 1874 static InstX86MovssRegs *create(Cfg *Func, Variable *Dest, Operand *Source) { |
| 1881 return new (Func->allocate<InstX86MovssRegs>()) | 1875 return new (Func->allocate<InstX86MovssRegs>()) |
| 1882 InstX86MovssRegs(Func, Dest, Source); | 1876 InstX86MovssRegs(Func, Dest, Source); |
| 1883 } | 1877 } |
| 1884 | 1878 |
| (...skipping 180 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2065 InstX86BaseLockable(const InstX86BaseLockable &) = delete; | 2059 InstX86BaseLockable(const InstX86BaseLockable &) = delete; |
| 2066 InstX86BaseLockable &operator=(const InstX86BaseLockable &) = delete; | 2060 InstX86BaseLockable &operator=(const InstX86BaseLockable &) = delete; |
| 2067 | 2061 |
| 2068 protected: | 2062 protected: |
| 2069 bool Locked; | 2063 bool Locked; |
| 2070 | 2064 |
| 2071 InstX86BaseLockable(Cfg *Func, | 2065 InstX86BaseLockable(Cfg *Func, |
| 2072 typename InstX86Base<Machine>::InstKindX86 Kind, | 2066 typename InstX86Base<Machine>::InstKindX86 Kind, |
| 2073 SizeT Maxsrcs, Variable *Dest, bool Locked) | 2067 SizeT Maxsrcs, Variable *Dest, bool Locked) |
| 2074 : InstX86Base<Machine>(Func, Kind, Maxsrcs, Dest), Locked(Locked) { | 2068 : InstX86Base<Machine>(Func, Kind, Maxsrcs, Dest), Locked(Locked) { |
| 2075 // Assume that such instructions are used for Atomics and be careful | 2069 // Assume that such instructions are used for Atomics and be careful with |
| 2076 // with optimizations. | 2070 // optimizations. |
| 2077 this->HasSideEffects = Locked; | 2071 this->HasSideEffects = Locked; |
| 2078 } | 2072 } |
| 2079 }; | 2073 }; |
| 2080 | 2074 |
| 2081 /// Mul instruction - unsigned multiply. | 2075 /// Mul instruction - unsigned multiply. |
| 2082 template <class Machine> class InstX86Mul final : public InstX86Base<Machine> { | 2076 template <class Machine> class InstX86Mul final : public InstX86Base<Machine> { |
| 2083 InstX86Mul() = delete; | 2077 InstX86Mul() = delete; |
| 2084 InstX86Mul(const InstX86Mul &) = delete; | 2078 InstX86Mul(const InstX86Mul &) = delete; |
| 2085 InstX86Mul &operator=(const InstX86Mul &) = delete; | 2079 InstX86Mul &operator=(const InstX86Mul &) = delete; |
| 2086 | 2080 |
| (...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2167 return InstX86Base<Machine>::isClassof(Inst, InstX86Base<Machine>::Cmov); | 2161 return InstX86Base<Machine>::isClassof(Inst, InstX86Base<Machine>::Cmov); |
| 2168 } | 2162 } |
| 2169 | 2163 |
| 2170 private: | 2164 private: |
| 2171 InstX86Cmov(Cfg *Func, Variable *Dest, Operand *Source, | 2165 InstX86Cmov(Cfg *Func, Variable *Dest, Operand *Source, |
| 2172 typename InstX86Base<Machine>::Traits::Cond::BrCond Cond); | 2166 typename InstX86Base<Machine>::Traits::Cond::BrCond Cond); |
| 2173 | 2167 |
| 2174 typename InstX86Base<Machine>::Traits::Cond::BrCond Condition; | 2168 typename InstX86Base<Machine>::Traits::Cond::BrCond Condition; |
| 2175 }; | 2169 }; |
| 2176 | 2170 |
| 2177 /// Cmpps instruction - compare packed singled-precision floating point | 2171 /// Cmpps instruction - compare packed singled-precision floating point values |
| 2178 /// values | |
| 2179 template <class Machine> | 2172 template <class Machine> |
| 2180 class InstX86Cmpps final : public InstX86Base<Machine> { | 2173 class InstX86Cmpps final : public InstX86Base<Machine> { |
| 2181 InstX86Cmpps() = delete; | 2174 InstX86Cmpps() = delete; |
| 2182 InstX86Cmpps(const InstX86Cmpps &) = delete; | 2175 InstX86Cmpps(const InstX86Cmpps &) = delete; |
| 2183 InstX86Cmpps &operator=(const InstX86Cmpps &) = delete; | 2176 InstX86Cmpps &operator=(const InstX86Cmpps &) = delete; |
| 2184 | 2177 |
| 2185 public: | 2178 public: |
| 2186 static InstX86Cmpps * | 2179 static InstX86Cmpps * |
| 2187 create(Cfg *Func, Variable *Dest, Operand *Source, | 2180 create(Cfg *Func, Variable *Dest, Operand *Source, |
| 2188 typename InstX86Base<Machine>::Traits::Cond::CmppsCond Condition) { | 2181 typename InstX86Base<Machine>::Traits::Cond::CmppsCond Condition) { |
| 2189 return new (Func->allocate<InstX86Cmpps>()) | 2182 return new (Func->allocate<InstX86Cmpps>()) |
| 2190 InstX86Cmpps(Func, Dest, Source, Condition); | 2183 InstX86Cmpps(Func, Dest, Source, Condition); |
| 2191 } | 2184 } |
| 2192 void emit(const Cfg *Func) const override; | 2185 void emit(const Cfg *Func) const override; |
| 2193 void emitIAS(const Cfg *Func) const override; | 2186 void emitIAS(const Cfg *Func) const override; |
| 2194 void dump(const Cfg *Func) const override; | 2187 void dump(const Cfg *Func) const override; |
| 2195 static bool classof(const Inst *Inst) { | 2188 static bool classof(const Inst *Inst) { |
| 2196 return InstX86Base<Machine>::isClassof(Inst, InstX86Base<Machine>::Cmpps); | 2189 return InstX86Base<Machine>::isClassof(Inst, InstX86Base<Machine>::Cmpps); |
| 2197 } | 2190 } |
| 2198 | 2191 |
| 2199 private: | 2192 private: |
| 2200 InstX86Cmpps(Cfg *Func, Variable *Dest, Operand *Source, | 2193 InstX86Cmpps(Cfg *Func, Variable *Dest, Operand *Source, |
| 2201 typename InstX86Base<Machine>::Traits::Cond::CmppsCond Cond); | 2194 typename InstX86Base<Machine>::Traits::Cond::CmppsCond Cond); |
| 2202 | 2195 |
| 2203 typename InstX86Base<Machine>::Traits::Cond::CmppsCond Condition; | 2196 typename InstX86Base<Machine>::Traits::Cond::CmppsCond Condition; |
| 2204 }; | 2197 }; |
| 2205 | 2198 |
| 2206 /// Cmpxchg instruction - cmpxchg <dest>, <desired> will compare if <dest> | 2199 /// Cmpxchg instruction - cmpxchg <dest>, <desired> will compare if <dest> |
| 2207 /// equals eax. If so, the ZF is set and <desired> is stored in <dest>. | 2200 /// equals eax. If so, the ZF is set and <desired> is stored in <dest>. If not, |
| 2208 /// If not, ZF is cleared and <dest> is copied to eax (or subregister). | 2201 /// ZF is cleared and <dest> is copied to eax (or subregister). <dest> can be a |
| 2209 /// <dest> can be a register or memory, while <desired> must be a register. | 2202 /// register or memory, while <desired> must be a register. It is the user's |
| 2210 /// It is the user's responsiblity to mark eax with a FakeDef. | 2203 /// responsiblity to mark eax with a FakeDef. |
|
Jim Stichnoth
2015/09/16 00:01:29
responsibility
ascull
2015/09/16 18:30:09
Done.
| |
| 2211 template <class Machine> | 2204 template <class Machine> |
| 2212 class InstX86Cmpxchg final : public InstX86BaseLockable<Machine> { | 2205 class InstX86Cmpxchg final : public InstX86BaseLockable<Machine> { |
| 2213 InstX86Cmpxchg() = delete; | 2206 InstX86Cmpxchg() = delete; |
| 2214 InstX86Cmpxchg(const InstX86Cmpxchg &) = delete; | 2207 InstX86Cmpxchg(const InstX86Cmpxchg &) = delete; |
| 2215 InstX86Cmpxchg &operator=(const InstX86Cmpxchg &) = delete; | 2208 InstX86Cmpxchg &operator=(const InstX86Cmpxchg &) = delete; |
| 2216 | 2209 |
| 2217 public: | 2210 public: |
| 2218 static InstX86Cmpxchg *create(Cfg *Func, Operand *DestOrAddr, Variable *Eax, | 2211 static InstX86Cmpxchg *create(Cfg *Func, Operand *DestOrAddr, Variable *Eax, |
| 2219 Variable *Desired, bool Locked) { | 2212 Variable *Desired, bool Locked) { |
| 2220 return new (Func->allocate<InstX86Cmpxchg>()) | 2213 return new (Func->allocate<InstX86Cmpxchg>()) |
| 2221 InstX86Cmpxchg(Func, DestOrAddr, Eax, Desired, Locked); | 2214 InstX86Cmpxchg(Func, DestOrAddr, Eax, Desired, Locked); |
| 2222 } | 2215 } |
| 2223 void emit(const Cfg *Func) const override; | 2216 void emit(const Cfg *Func) const override; |
| 2224 void emitIAS(const Cfg *Func) const override; | 2217 void emitIAS(const Cfg *Func) const override; |
| 2225 void dump(const Cfg *Func) const override; | 2218 void dump(const Cfg *Func) const override; |
| 2226 static bool classof(const Inst *Inst) { | 2219 static bool classof(const Inst *Inst) { |
| 2227 return InstX86Base<Machine>::isClassof(Inst, InstX86Base<Machine>::Cmpxchg); | 2220 return InstX86Base<Machine>::isClassof(Inst, InstX86Base<Machine>::Cmpxchg); |
| 2228 } | 2221 } |
| 2229 | 2222 |
| 2230 private: | 2223 private: |
| 2231 InstX86Cmpxchg(Cfg *Func, Operand *DestOrAddr, Variable *Eax, | 2224 InstX86Cmpxchg(Cfg *Func, Operand *DestOrAddr, Variable *Eax, |
| 2232 Variable *Desired, bool Locked); | 2225 Variable *Desired, bool Locked); |
| 2233 }; | 2226 }; |
| 2234 | 2227 |
| 2235 /// Cmpxchg8b instruction - cmpxchg8b <m64> will compare if <m64> | 2228 /// Cmpxchg8b instruction - cmpxchg8b <m64> will compare if <m64> equals |
| 2236 /// equals edx:eax. If so, the ZF is set and ecx:ebx is stored in <m64>. | 2229 /// edx:eax. If so, the ZF is set and ecx:ebx is stored in <m64>. If not, ZF is |
| 2237 /// If not, ZF is cleared and <m64> is copied to edx:eax. | 2230 /// cleared and <m64> is copied to edx:eax. The caller is responsible for |
| 2238 /// The caller is responsible for inserting FakeDefs to mark edx | 2231 /// inserting FakeDefs to mark edx and eax as modified. <m64> must be a memory |
| 2239 /// and eax as modified. | 2232 /// operand. |
| 2240 /// <m64> must be a memory operand. | |
| 2241 template <class Machine> | 2233 template <class Machine> |
| 2242 class InstX86Cmpxchg8b final : public InstX86BaseLockable<Machine> { | 2234 class InstX86Cmpxchg8b final : public InstX86BaseLockable<Machine> { |
| 2243 InstX86Cmpxchg8b() = delete; | 2235 InstX86Cmpxchg8b() = delete; |
| 2244 InstX86Cmpxchg8b(const InstX86Cmpxchg8b &) = delete; | 2236 InstX86Cmpxchg8b(const InstX86Cmpxchg8b &) = delete; |
| 2245 InstX86Cmpxchg8b &operator=(const InstX86Cmpxchg8b &) = delete; | 2237 InstX86Cmpxchg8b &operator=(const InstX86Cmpxchg8b &) = delete; |
| 2246 | 2238 |
| 2247 public: | 2239 public: |
| 2248 static InstX86Cmpxchg8b * | 2240 static InstX86Cmpxchg8b * |
| 2249 create(Cfg *Func, typename InstX86Base<Machine>::Traits::X86OperandMem *Dest, | 2241 create(Cfg *Func, typename InstX86Base<Machine>::Traits::X86OperandMem *Dest, |
| 2250 Variable *Edx, Variable *Eax, Variable *Ecx, Variable *Ebx, | 2242 Variable *Edx, Variable *Eax, Variable *Ecx, Variable *Ebx, |
| 2251 bool Locked) { | 2243 bool Locked) { |
| 2252 return new (Func->allocate<InstX86Cmpxchg8b>()) | 2244 return new (Func->allocate<InstX86Cmpxchg8b>()) |
| 2253 InstX86Cmpxchg8b(Func, Dest, Edx, Eax, Ecx, Ebx, Locked); | 2245 InstX86Cmpxchg8b(Func, Dest, Edx, Eax, Ecx, Ebx, Locked); |
| 2254 } | 2246 } |
| 2255 void emit(const Cfg *Func) const override; | 2247 void emit(const Cfg *Func) const override; |
| 2256 void emitIAS(const Cfg *Func) const override; | 2248 void emitIAS(const Cfg *Func) const override; |
| 2257 void dump(const Cfg *Func) const override; | 2249 void dump(const Cfg *Func) const override; |
| 2258 static bool classof(const Inst *Inst) { | 2250 static bool classof(const Inst *Inst) { |
| 2259 return InstX86Base<Machine>::isClassof(Inst, | 2251 return InstX86Base<Machine>::isClassof(Inst, |
| 2260 InstX86Base<Machine>::Cmpxchg8b); | 2252 InstX86Base<Machine>::Cmpxchg8b); |
| 2261 } | 2253 } |
| 2262 | 2254 |
| 2263 private: | 2255 private: |
| 2264 InstX86Cmpxchg8b(Cfg *Func, | 2256 InstX86Cmpxchg8b(Cfg *Func, |
| 2265 typename InstX86Base<Machine>::Traits::X86OperandMem *Dest, | 2257 typename InstX86Base<Machine>::Traits::X86OperandMem *Dest, |
| 2266 Variable *Edx, Variable *Eax, Variable *Ecx, Variable *Ebx, | 2258 Variable *Edx, Variable *Eax, Variable *Ecx, Variable *Ebx, |
| 2267 bool Locked); | 2259 bool Locked); |
| 2268 }; | 2260 }; |
| 2269 | 2261 |
| 2270 /// Cvt instruction - wrapper for cvtsX2sY where X and Y are in {s,d,i} | 2262 /// Cvt instruction - wrapper for cvtsX2sY where X and Y are in {s,d,i} as |
| 2271 /// as appropriate. s=float, d=double, i=int. X and Y are determined | 2263 /// appropriate. s=float, d=double, i=int. X and Y are determined from dest/src |
| 2272 /// from dest/src types. Sign and zero extension on the integer | 2264 /// types. Sign and zero extension on the integer operand needs to be done |
| 2273 /// operand needs to be done separately. | 2265 /// separately. |
| 2274 template <class Machine> class InstX86Cvt final : public InstX86Base<Machine> { | 2266 template <class Machine> class InstX86Cvt final : public InstX86Base<Machine> { |
| 2275 InstX86Cvt() = delete; | 2267 InstX86Cvt() = delete; |
| 2276 InstX86Cvt(const InstX86Cvt &) = delete; | 2268 InstX86Cvt(const InstX86Cvt &) = delete; |
| 2277 InstX86Cvt &operator=(const InstX86Cvt &) = delete; | 2269 InstX86Cvt &operator=(const InstX86Cvt &) = delete; |
| 2278 | 2270 |
| 2279 public: | 2271 public: |
| 2280 enum CvtVariant { Si2ss, Tss2si, Float2float, Dq2ps, Tps2dq }; | 2272 enum CvtVariant { Si2ss, Tss2si, Float2float, Dq2ps, Tps2dq }; |
| 2281 static InstX86Cvt *create(Cfg *Func, Variable *Dest, Operand *Source, | 2273 static InstX86Cvt *create(Cfg *Func, Variable *Dest, Operand *Source, |
| 2282 CvtVariant Variant) { | 2274 CvtVariant Variant) { |
| 2283 return new (Func->allocate<InstX86Cvt>()) | 2275 return new (Func->allocate<InstX86Cvt>()) |
| (...skipping 115 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2399 void dump(const Cfg *Func) const override; | 2391 void dump(const Cfg *Func) const override; |
| 2400 static bool classof(const Inst *Inst) { | 2392 static bool classof(const Inst *Inst) { |
| 2401 return InstX86Base<Machine>::isClassof(Inst, InstX86Base<Machine>::Mfence); | 2393 return InstX86Base<Machine>::isClassof(Inst, InstX86Base<Machine>::Mfence); |
| 2402 } | 2394 } |
| 2403 | 2395 |
| 2404 private: | 2396 private: |
| 2405 explicit InstX86Mfence(Cfg *Func); | 2397 explicit InstX86Mfence(Cfg *Func); |
| 2406 }; | 2398 }; |
| 2407 | 2399 |
| 2408 /// This is essentially a "mov" instruction with an | 2400 /// This is essentially a "mov" instruction with an |
| 2409 /// InstX86Base<Machine>::Traits::X86OperandMem | 2401 /// InstX86Base<Machine>::Traits::X86OperandMem operand instead of Variable as |
| 2410 /// operand instead of Variable as the destination. It's important | 2402 /// the destination. It's important for liveness that there is no Dest operand. |
| 2411 /// for liveness that there is no Dest operand. | |
| 2412 template <class Machine> | 2403 template <class Machine> |
| 2413 class InstX86Store final : public InstX86Base<Machine> { | 2404 class InstX86Store final : public InstX86Base<Machine> { |
| 2414 InstX86Store() = delete; | 2405 InstX86Store() = delete; |
| 2415 InstX86Store(const InstX86Store &) = delete; | 2406 InstX86Store(const InstX86Store &) = delete; |
| 2416 InstX86Store &operator=(const InstX86Store &) = delete; | 2407 InstX86Store &operator=(const InstX86Store &) = delete; |
| 2417 | 2408 |
| 2418 public: | 2409 public: |
| 2419 static InstX86Store * | 2410 static InstX86Store * |
| 2420 create(Cfg *Func, Operand *Value, | 2411 create(Cfg *Func, Operand *Value, |
| 2421 typename InstX86Base<Machine>::Traits::X86Operand *Mem) { | 2412 typename InstX86Base<Machine>::Traits::X86Operand *Mem) { |
| 2422 return new (Func->allocate<InstX86Store>()) InstX86Store(Func, Value, Mem); | 2413 return new (Func->allocate<InstX86Store>()) InstX86Store(Func, Value, Mem); |
| 2423 } | 2414 } |
| 2424 void emit(const Cfg *Func) const override; | 2415 void emit(const Cfg *Func) const override; |
| 2425 void emitIAS(const Cfg *Func) const override; | 2416 void emitIAS(const Cfg *Func) const override; |
| 2426 void dump(const Cfg *Func) const override; | 2417 void dump(const Cfg *Func) const override; |
| 2427 static bool classof(const Inst *Inst) { | 2418 static bool classof(const Inst *Inst) { |
| 2428 return InstX86Base<Machine>::isClassof(Inst, InstX86Base<Machine>::Store); | 2419 return InstX86Base<Machine>::isClassof(Inst, InstX86Base<Machine>::Store); |
| 2429 } | 2420 } |
| 2430 | 2421 |
| 2431 private: | 2422 private: |
| 2432 InstX86Store(Cfg *Func, Operand *Value, | 2423 InstX86Store(Cfg *Func, Operand *Value, |
| 2433 typename InstX86Base<Machine>::Traits::X86Operand *Mem); | 2424 typename InstX86Base<Machine>::Traits::X86Operand *Mem); |
| 2434 }; | 2425 }; |
| 2435 | 2426 |
| 2436 /// This is essentially a vector "mov" instruction with an typename | 2427 /// This is essentially a vector "mov" instruction with an typename |
| 2437 /// InstX86Base<Machine>::Traits::X86OperandMem | 2428 /// InstX86Base<Machine>::Traits::X86OperandMem operand instead of Variable as |
| 2438 /// operand instead of Variable as the destination. It's important | 2429 /// the destination. It's important for liveness that there is no Dest operand. |
| 2439 /// for liveness that there is no Dest operand. The source must be an | 2430 /// The source must be an Xmm register, since Dest is mem. |
| 2440 /// Xmm register, since Dest is mem. | |
| 2441 template <class Machine> | 2431 template <class Machine> |
| 2442 class InstX86StoreP final : public InstX86Base<Machine> { | 2432 class InstX86StoreP final : public InstX86Base<Machine> { |
| 2443 InstX86StoreP() = delete; | 2433 InstX86StoreP() = delete; |
| 2444 InstX86StoreP(const InstX86StoreP &) = delete; | 2434 InstX86StoreP(const InstX86StoreP &) = delete; |
| 2445 InstX86StoreP &operator=(const InstX86StoreP &) = delete; | 2435 InstX86StoreP &operator=(const InstX86StoreP &) = delete; |
| 2446 | 2436 |
| 2447 public: | 2437 public: |
| 2448 static InstX86StoreP * | 2438 static InstX86StoreP * |
| 2449 create(Cfg *Func, Variable *Value, | 2439 create(Cfg *Func, Variable *Value, |
| 2450 typename InstX86Base<Machine>::Traits::X86OperandMem *Mem) { | 2440 typename InstX86Base<Machine>::Traits::X86OperandMem *Mem) { |
| (...skipping 138 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2589 void emitIAS(const Cfg *Func) const override; | 2579 void emitIAS(const Cfg *Func) const override; |
| 2590 void dump(const Cfg *Func) const override; | 2580 void dump(const Cfg *Func) const override; |
| 2591 static bool classof(const Inst *Inst) { | 2581 static bool classof(const Inst *Inst) { |
| 2592 return InstX86Base<Machine>::isClassof(Inst, InstX86Base<Machine>::Push); | 2582 return InstX86Base<Machine>::isClassof(Inst, InstX86Base<Machine>::Push); |
| 2593 } | 2583 } |
| 2594 | 2584 |
| 2595 private: | 2585 private: |
| 2596 InstX86Push(Cfg *Func, Variable *Source); | 2586 InstX86Push(Cfg *Func, Variable *Source); |
| 2597 }; | 2587 }; |
| 2598 | 2588 |
| 2599 /// Ret instruction. Currently only supports the "ret" version that | 2589 /// Ret instruction. Currently only supports the "ret" version that does not pop |
| 2600 /// does not pop arguments. This instruction takes a Source operand | 2590 /// arguments. This instruction takes a Source operand (for non-void returning |
| 2601 /// (for non-void returning functions) for liveness analysis, though | 2591 /// functions) for liveness analysis, though a FakeUse before the ret would do |
| 2602 /// a FakeUse before the ret would do just as well. | 2592 /// just as well. |
| 2603 template <class Machine> class InstX86Ret final : public InstX86Base<Machine> { | 2593 template <class Machine> class InstX86Ret final : public InstX86Base<Machine> { |
| 2604 InstX86Ret() = delete; | 2594 InstX86Ret() = delete; |
| 2605 InstX86Ret(const InstX86Ret &) = delete; | 2595 InstX86Ret(const InstX86Ret &) = delete; |
| 2606 InstX86Ret &operator=(const InstX86Ret &) = delete; | 2596 InstX86Ret &operator=(const InstX86Ret &) = delete; |
| 2607 | 2597 |
| 2608 public: | 2598 public: |
| 2609 static InstX86Ret *create(Cfg *Func, Variable *Source = nullptr) { | 2599 static InstX86Ret *create(Cfg *Func, Variable *Source = nullptr) { |
| 2610 return new (Func->allocate<InstX86Ret>()) InstX86Ret(Func, Source); | 2600 return new (Func->allocate<InstX86Ret>()) InstX86Ret(Func, Source); |
| 2611 } | 2601 } |
| 2612 void emit(const Cfg *Func) const override; | 2602 void emit(const Cfg *Func) const override; |
| (...skipping 27 matching lines...) Expand all Loading... | |
| 2640 return InstX86Base<Machine>::isClassof(Inst, InstX86Base<Machine>::Setcc); | 2630 return InstX86Base<Machine>::isClassof(Inst, InstX86Base<Machine>::Setcc); |
| 2641 } | 2631 } |
| 2642 | 2632 |
| 2643 private: | 2633 private: |
| 2644 InstX86Setcc(Cfg *Func, Variable *Dest, | 2634 InstX86Setcc(Cfg *Func, Variable *Dest, |
| 2645 typename InstX86Base<Machine>::Traits::Cond::BrCond Cond); | 2635 typename InstX86Base<Machine>::Traits::Cond::BrCond Cond); |
| 2646 | 2636 |
| 2647 const typename InstX86Base<Machine>::Traits::Cond::BrCond Condition; | 2637 const typename InstX86Base<Machine>::Traits::Cond::BrCond Condition; |
| 2648 }; | 2638 }; |
| 2649 | 2639 |
| 2650 /// Exchanging Add instruction. Exchanges the first operand (destination | 2640 /// Exchanging Add instruction. Exchanges the first operand (destination |
| 2651 /// operand) with the second operand (source operand), then loads the sum | 2641 /// operand) with the second operand (source operand), then loads the sum of the |
| 2652 /// of the two values into the destination operand. The destination may be | 2642 /// two values into the destination operand. The destination may be a register |
| 2653 /// a register or memory, while the source must be a register. | 2643 /// or memory, while the source must be a register. |
| 2654 /// | 2644 /// |
| 2655 /// Both the dest and source are updated. The caller should then insert a | 2645 /// Both the dest and source are updated. The caller should then insert a |
| 2656 /// FakeDef to reflect the second udpate. | 2646 /// FakeDef to reflect the second udpate. |
| 2657 template <class Machine> | 2647 template <class Machine> |
| 2658 class InstX86Xadd final : public InstX86BaseLockable<Machine> { | 2648 class InstX86Xadd final : public InstX86BaseLockable<Machine> { |
| 2659 InstX86Xadd() = delete; | 2649 InstX86Xadd() = delete; |
| 2660 InstX86Xadd(const InstX86Xadd &) = delete; | 2650 InstX86Xadd(const InstX86Xadd &) = delete; |
| 2661 InstX86Xadd &operator=(const InstX86Xadd &) = delete; | 2651 InstX86Xadd &operator=(const InstX86Xadd &) = delete; |
| 2662 | 2652 |
| 2663 public: | 2653 public: |
| 2664 static InstX86Xadd *create(Cfg *Func, Operand *Dest, Variable *Source, | 2654 static InstX86Xadd *create(Cfg *Func, Operand *Dest, Variable *Source, |
| 2665 bool Locked) { | 2655 bool Locked) { |
| 2666 return new (Func->allocate<InstX86Xadd>()) | 2656 return new (Func->allocate<InstX86Xadd>()) |
| 2667 InstX86Xadd(Func, Dest, Source, Locked); | 2657 InstX86Xadd(Func, Dest, Source, Locked); |
| 2668 } | 2658 } |
| 2669 void emit(const Cfg *Func) const override; | 2659 void emit(const Cfg *Func) const override; |
| 2670 void emitIAS(const Cfg *Func) const override; | 2660 void emitIAS(const Cfg *Func) const override; |
| 2671 void dump(const Cfg *Func) const override; | 2661 void dump(const Cfg *Func) const override; |
| 2672 static bool classof(const Inst *Inst) { | 2662 static bool classof(const Inst *Inst) { |
| 2673 return InstX86Base<Machine>::isClassof(Inst, InstX86Base<Machine>::Xadd); | 2663 return InstX86Base<Machine>::isClassof(Inst, InstX86Base<Machine>::Xadd); |
| 2674 } | 2664 } |
| 2675 | 2665 |
| 2676 private: | 2666 private: |
| 2677 InstX86Xadd(Cfg *Func, Operand *Dest, Variable *Source, bool Locked); | 2667 InstX86Xadd(Cfg *Func, Operand *Dest, Variable *Source, bool Locked); |
| 2678 }; | 2668 }; |
| 2679 | 2669 |
| 2680 /// Exchange instruction. Exchanges the first operand (destination | 2670 /// Exchange instruction. Exchanges the first operand (destination operand) with |
| 2681 /// operand) with the second operand (source operand). At least one of | 2671 /// the second operand (source operand). At least one of the operands must be a |
| 2682 /// the operands must be a register (and the other can be reg or mem). | 2672 /// register (and the other can be reg or mem). Both the Dest and Source are |
| 2683 /// Both the Dest and Source are updated. If there is a memory operand, | 2673 /// updated. If there is a memory operand, then the instruction is automatically |
| 2684 /// then the instruction is automatically "locked" without the need for | 2674 /// "locked" without the need for a lock prefix. |
| 2685 /// a lock prefix. | |
| 2686 template <class Machine> class InstX86Xchg final : public InstX86Base<Machine> { | 2675 template <class Machine> class InstX86Xchg final : public InstX86Base<Machine> { |
| 2687 InstX86Xchg() = delete; | 2676 InstX86Xchg() = delete; |
| 2688 InstX86Xchg(const InstX86Xchg &) = delete; | 2677 InstX86Xchg(const InstX86Xchg &) = delete; |
| 2689 InstX86Xchg &operator=(const InstX86Xchg &) = delete; | 2678 InstX86Xchg &operator=(const InstX86Xchg &) = delete; |
| 2690 | 2679 |
| 2691 public: | 2680 public: |
| 2692 static InstX86Xchg *create(Cfg *Func, Operand *Dest, Variable *Source) { | 2681 static InstX86Xchg *create(Cfg *Func, Operand *Dest, Variable *Source) { |
| 2693 return new (Func->allocate<InstX86Xchg>()) InstX86Xchg(Func, Dest, Source); | 2682 return new (Func->allocate<InstX86Xchg>()) InstX86Xchg(Func, Dest, Source); |
| 2694 } | 2683 } |
| 2695 void emit(const Cfg *Func) const override; | 2684 void emit(const Cfg *Func) const override; |
| (...skipping 512 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 3208 &InstX86Base<Machine>::Traits::Assembler::psrl}; \ | 3197 &InstX86Base<Machine>::Traits::Assembler::psrl}; \ |
| 3209 } \ | 3198 } \ |
| 3210 } | 3199 } |
| 3211 | 3200 |
| 3212 } // end of namespace X86Internal | 3201 } // end of namespace X86Internal |
| 3213 } // end of namespace Ice | 3202 } // end of namespace Ice |
| 3214 | 3203 |
| 3215 #include "IceInstX86BaseImpl.h" | 3204 #include "IceInstX86BaseImpl.h" |
| 3216 | 3205 |
| 3217 #endif // SUBZERO_SRC_ICEINSTX86BASE_H | 3206 #endif // SUBZERO_SRC_ICEINSTX86BASE_H |
| OLD | NEW |