Chromium Code Reviews| Index: src/IceInstX86Base.h | 
| diff --git a/src/IceInstX86Base.h b/src/IceInstX86Base.h | 
| index de7b4052f8f1b9a2003d8958142e9cb0d202473b..8cefabb3afdeea7ff2d9e0a8952fc7ded8365ab2 100644 | 
| --- a/src/IceInstX86Base.h | 
| +++ b/src/IceInstX86Base.h | 
| @@ -25,3423 +25,3458 @@ | 
| namespace Ice { | 
| -namespace X86Internal { | 
| - | 
| -template <class Machine> struct MachineTraits; | 
| - | 
| -template <class Machine> class InstX86Base : public InstTarget { | 
| - InstX86Base<Machine>() = delete; | 
| - InstX86Base<Machine>(const InstX86Base &) = delete; | 
| - InstX86Base &operator=(const InstX86Base &) = delete; | 
| - | 
| -public: | 
| - using Traits = MachineTraits<Machine>; | 
| - using X86TargetLowering = typename Traits::TargetLowering; | 
| - | 
| - enum InstKindX86 { | 
| - k__Start = Inst::Target, | 
| - Adc, | 
| - AdcRMW, | 
| - Add, | 
| - AddRMW, | 
| - Addps, | 
| - Addss, | 
| - And, | 
| - Andnps, | 
| - Andps, | 
| - AndRMW, | 
| - Blendvps, | 
| - Br, | 
| - Bsf, | 
| - Bsr, | 
| - Bswap, | 
| - Call, | 
| - Cbwdq, | 
| - Cmov, | 
| - Cmpps, | 
| - Cmpxchg, | 
| - Cmpxchg8b, | 
| - Cvt, | 
| - Div, | 
| - Divps, | 
| - Divss, | 
| - FakeRMW, | 
| - Fld, | 
| - Fstp, | 
| - Icmp, | 
| - Idiv, | 
| - Imul, | 
| - ImulImm, | 
| - Insertps, | 
| - Jmp, | 
| - Label, | 
| - Lea, | 
| - Load, | 
| - Mfence, | 
| - Minss, | 
| - Maxss, | 
| - Mov, | 
| - Movd, | 
| - Movp, | 
| - Movq, | 
| - MovssRegs, | 
| - Movsx, | 
| - Movzx, | 
| - Mul, | 
| - Mulps, | 
| - Mulss, | 
| - Neg, | 
| - Nop, | 
| - Or, | 
| - Orps, | 
| - OrRMW, | 
| - Padd, | 
| - Pand, | 
| - Pandn, | 
| - Pblendvb, | 
| - Pcmpeq, | 
| - Pcmpgt, | 
| - Pextr, | 
| - Pinsr, | 
| - Pmull, | 
| - Pmuludq, | 
| - Pop, | 
| - Por, | 
| - Pshufd, | 
| - Psll, | 
| - Psra, | 
| - Psrl, | 
| - Psub, | 
| - Push, | 
| - Pxor, | 
| - Ret, | 
| - Rol, | 
| - Sar, | 
| - Sbb, | 
| - SbbRMW, | 
| - Setcc, | 
| - Shl, | 
| - Shld, | 
| - Shr, | 
| - Shrd, | 
| - Shufps, | 
| - Sqrtss, | 
| - Store, | 
| - StoreP, | 
| - StoreQ, | 
| - Sub, | 
| - SubRMW, | 
| - Subps, | 
| - Subss, | 
| - Test, | 
| - Ucomiss, | 
| - UD2, | 
| - Xadd, | 
| - Xchg, | 
| - Xor, | 
| - Xorps, | 
| - XorRMW, | 
| - | 
| - /// Intel Architecture Code Analyzer markers. These are not executable so | 
| - /// must only be used for analysis. | 
| - IacaStart, | 
| - IacaEnd | 
| - }; | 
| - | 
| - enum SseSuffix { None, Packed, Scalar, Integral }; | 
| - | 
| - static const char *getWidthString(Type Ty); | 
| - static const char *getFldString(Type Ty); | 
| - static typename Traits::Cond::BrCond | 
| - getOppositeCondition(typename Traits::Cond::BrCond Cond); | 
| - void dump(const Cfg *Func) const override; | 
| - | 
| - // Shared emit routines for common forms of instructions. | 
| - void emitTwoAddress(const Cfg *Func, const char *Opcode, | 
| - const char *Suffix = "") const; | 
| - | 
| - static void | 
| - emitIASGPRShift(const Cfg *Func, Type Ty, const Variable *Var, | 
| - const Operand *Src, | 
| - const typename Traits::Assembler::GPREmitterShiftOp &Emitter); | 
| +#ifndef X86NAMESPACE | 
| +#error "You must define the X86 Target namespace." | 
| +#endif | 
| + | 
| +namespace X86NAMESPACE { | 
| + | 
| 
 
John
2015/12/30 22:07:52
The diff seems worse than it is because of changes
 
 | 
| +template <typename TraitsType> struct InstImpl { | 
| + using Traits = TraitsType; | 
| + using Assembler = typename Traits::Assembler; | 
| + using AssemblerLabel = typename Assembler::Label; | 
| + using AssemblerImmediate = typename Assembler::Immediate; | 
| + using TargetLowering = typename Traits::TargetLowering; | 
| + using Address = typename Traits::Address; | 
| + using X86Operand = typename Traits::X86Operand; | 
| + using X86OperandMem = typename Traits::X86OperandMem; | 
| + using VariableSplit = typename Traits::VariableSplit; | 
| + | 
| + using GPRRegister = typename Traits::RegisterSet::GPRRegister; | 
| + using RegisterSet = typename Traits::RegisterSet; | 
| + using XmmRegister = typename Traits::RegisterSet::XmmRegister; | 
| + | 
| + using Cond = typename Traits::Cond; | 
| + using BrCond = typename Traits::Cond::BrCond; | 
| + using CmppsCond = typename Traits::Cond::CmppsCond; | 
| + | 
| + template <typename SReg_t, typename DReg_t> | 
| + using CastEmitterRegOp = | 
| + typename Traits::Assembler::template CastEmitterRegOp<SReg_t, DReg_t>; | 
| + template <typename SReg_t, typename DReg_t> | 
| + using ThreeOpImmEmitter = | 
| + typename Traits::Assembler::template ThreeOpImmEmitter<SReg_t, DReg_t>; | 
| + using GPREmitterAddrOp = typename Traits::Assembler::GPREmitterAddrOp; | 
| + using GPREmitterRegOp = typename Traits::Assembler::GPREmitterRegOp; | 
| + using GPREmitterShiftD = typename Traits::Assembler::GPREmitterShiftD; | 
| + using GPREmitterShiftOp = typename Traits::Assembler::GPREmitterShiftOp; | 
| + using GPREmitterOneOp = typename Traits::Assembler::GPREmitterOneOp; | 
| + using XmmEmitterRegOp = typename Traits::Assembler::XmmEmitterRegOp; | 
| + using XmmEmitterShiftOp = typename Traits::Assembler::XmmEmitterShiftOp; | 
| + using XmmEmitterMovOps = typename Traits::Assembler::XmmEmitterMovOps; | 
| + | 
| + class InstX86Base : public InstTarget { | 
| + InstX86Base() = delete; | 
| + InstX86Base(const InstX86Base &) = delete; | 
| + InstX86Base &operator=(const InstX86Base &) = delete; | 
| + | 
| + public: | 
| + enum InstKindX86 { | 
| + k__Start = Inst::Target, | 
| + Adc, | 
| + AdcRMW, | 
| + Add, | 
| + AddRMW, | 
| + Addps, | 
| + Addss, | 
| + And, | 
| + Andnps, | 
| + Andps, | 
| + AndRMW, | 
| + Blendvps, | 
| + Br, | 
| + Bsf, | 
| + Bsr, | 
| + Bswap, | 
| + Call, | 
| + Cbwdq, | 
| + Cmov, | 
| + Cmpps, | 
| + Cmpxchg, | 
| + Cmpxchg8b, | 
| + Cvt, | 
| + Div, | 
| + Divps, | 
| + Divss, | 
| + FakeRMW, | 
| + Fld, | 
| + Fstp, | 
| + Icmp, | 
| + Idiv, | 
| + Imul, | 
| + ImulImm, | 
| + Insertps, | 
| + Jmp, | 
| + Label, | 
| + Lea, | 
| + Load, | 
| + Mfence, | 
| + Minss, | 
| + Maxss, | 
| + Mov, | 
| + Movd, | 
| + Movp, | 
| + Movq, | 
| + MovssRegs, | 
| + Movsx, | 
| + Movzx, | 
| + Mul, | 
| + Mulps, | 
| + Mulss, | 
| + Neg, | 
| + Nop, | 
| + Or, | 
| + Orps, | 
| + OrRMW, | 
| + Padd, | 
| + Pand, | 
| + Pandn, | 
| + Pblendvb, | 
| + Pcmpeq, | 
| + Pcmpgt, | 
| + Pextr, | 
| + Pinsr, | 
| + Pmull, | 
| + Pmuludq, | 
| + Pop, | 
| + Por, | 
| + Pshufd, | 
| + Psll, | 
| + Psra, | 
| + Psrl, | 
| + Psub, | 
| + Push, | 
| + Pxor, | 
| + Ret, | 
| + Rol, | 
| + Sar, | 
| + Sbb, | 
| + SbbRMW, | 
| + Setcc, | 
| + Shl, | 
| + Shld, | 
| + Shr, | 
| + Shrd, | 
| + Shufps, | 
| + Sqrtss, | 
| + Store, | 
| + StoreP, | 
| + StoreQ, | 
| + Sub, | 
| + SubRMW, | 
| + Subps, | 
| + Subss, | 
| + Test, | 
| + Ucomiss, | 
| + UD2, | 
| + Xadd, | 
| + Xchg, | 
| + Xor, | 
| + Xorps, | 
| + XorRMW, | 
| + | 
| + /// Intel Architecture Code Analyzer markers. These are not executable so | 
| + /// must only be used for analysis. | 
| + IacaStart, | 
| + IacaEnd | 
| + }; | 
| + | 
| + enum SseSuffix { None, Packed, Scalar, Integral }; | 
| + | 
| + static const char *getWidthString(Type Ty); | 
| + static const char *getFldString(Type Ty); | 
| + static BrCond getOppositeCondition(BrCond Cond); | 
| + void dump(const Cfg *Func) const override; | 
| + | 
| + // Shared emit routines for common forms of instructions. | 
| + void emitTwoAddress(const Cfg *Func, const char *Opcode, | 
| + const char *Suffix = "") const; | 
| + | 
| + static TargetLowering *getTarget(const Cfg *Func) { | 
| + return static_cast<TargetLowering *>(Func->getTarget()); | 
| + } | 
| - static X86TargetLowering *getTarget(const Cfg *Func) { | 
| - return static_cast<X86TargetLowering *>(Func->getTarget()); | 
| - } | 
| + protected: | 
| + InstX86Base(Cfg *Func, InstKindX86 Kind, SizeT Maxsrcs, Variable *Dest) | 
| + : InstTarget(Func, static_cast<InstKind>(Kind), Maxsrcs, Dest) {} | 
| -protected: | 
| - InstX86Base<Machine>(Cfg *Func, InstKindX86 Kind, SizeT Maxsrcs, | 
| - Variable *Dest) | 
| - : InstTarget(Func, static_cast<InstKind>(Kind), Maxsrcs, Dest) {} | 
| + static bool isClassof(const Inst *Inst, InstKindX86 MyKind) { | 
| + return Inst->getKind() == static_cast<InstKind>(MyKind); | 
| + } | 
| + // Most instructions that operate on vector arguments require vector memory | 
| + // operands to be fully aligned (16-byte alignment for PNaCl vector types). | 
| + // The stack frame layout and call ABI ensure proper alignment for stack | 
| + // operands, but memory operands (originating from load/store bitcode | 
| + // instructions) only have element-size alignment guarantees. This function | 
| + // validates that none of the operands is a memory operand of vector type, | 
| + // calling report_fatal_error() if one is found. This function should be | 
| + // called during emission, and maybe also in the ctor (as long as that fits | 
| + // the lowering style). | 
| + void validateVectorAddrMode() const { | 
| + if (this->getDest()) | 
| 
 
Jim Stichnoth
2016/01/03 18:20:02
It looks like the "this->" in this method can be r
 
 | 
| + this->validateVectorAddrModeOpnd(this->getDest()); | 
| + for (SizeT i = 0; i < this->getSrcSize(); ++i) { | 
| + this->validateVectorAddrModeOpnd(this->getSrc(i)); | 
| + } | 
| + } | 
| - static bool isClassof(const Inst *Inst, InstKindX86 MyKind) { | 
| - return Inst->getKind() == static_cast<InstKind>(MyKind); | 
| - } | 
| - // Most instructions that operate on vector arguments require vector memory | 
| - // operands to be fully aligned (16-byte alignment for PNaCl vector types). | 
| - // The stack frame layout and call ABI ensure proper alignment for stack | 
| - // operands, but memory operands (originating from load/store bitcode | 
| - // instructions) only have element-size alignment guarantees. This function | 
| - // validates that none of the operands is a memory operand of vector type, | 
| - // calling report_fatal_error() if one is found. This function should be | 
| - // called during emission, and maybe also in the ctor (as long as that fits | 
| - // the lowering style). | 
| - void validateVectorAddrMode() const { | 
| - if (this->getDest()) | 
| - this->validateVectorAddrModeOpnd(this->getDest()); | 
| - for (SizeT i = 0; i < this->getSrcSize(); ++i) { | 
| - this->validateVectorAddrModeOpnd(this->getSrc(i)); | 
| + private: | 
| + static void validateVectorAddrModeOpnd(const Operand *Opnd) { | 
| + if (llvm::isa<X86OperandMem>(Opnd) && isVectorType(Opnd->getType())) { | 
| + llvm::report_fatal_error("Possible misaligned vector memory operation"); | 
| + } | 
| } | 
| - } | 
| + }; | 
| -private: | 
| - static void validateVectorAddrModeOpnd(const Operand *Opnd) { | 
| - if (llvm::isa<typename InstX86Base<Machine>::Traits::X86OperandMem>(Opnd) && | 
| - isVectorType(Opnd->getType())) { | 
| - llvm::report_fatal_error("Possible misaligned vector memory operation"); | 
| + /// InstX86FakeRMW represents a non-atomic read-modify-write operation on a | 
| + /// memory location. An InstX86FakeRMW is a "fake" instruction in that it | 
| + /// still needs to be lowered to some actual RMW instruction. | 
| + /// | 
| + /// If A is some memory address, D is some data value to apply, and OP is an | 
| + /// arithmetic operator, the instruction operates as: (*A) = (*A) OP D | 
| + class InstX86FakeRMW final : public InstX86Base { | 
| + InstX86FakeRMW() = delete; | 
| + InstX86FakeRMW(const InstX86FakeRMW &) = delete; | 
| + InstX86FakeRMW &operator=(const InstX86FakeRMW &) = delete; | 
| + | 
| + public: | 
| + static InstX86FakeRMW *create(Cfg *Func, Operand *Data, Operand *Addr, | 
| + Variable *Beacon, InstArithmetic::OpKind Op, | 
| + uint32_t Align = 1) { | 
| + // TODO(stichnot): Stop ignoring alignment specification. | 
| + (void)Align; | 
| + return new (Func->allocate<InstX86FakeRMW>()) | 
| + InstX86FakeRMW(Func, Data, Addr, Op, Beacon); | 
| + } | 
| + Operand *getAddr() const { return this->getSrc(1); } | 
| + Operand *getData() const { return this->getSrc(0); } | 
| + InstArithmetic::OpKind getOp() const { return Op; } | 
| + Variable *getBeacon() const { | 
| + return llvm::cast<Variable>(this->getSrc(2)); | 
| + } | 
| + void dump(const Cfg *Func) const override; | 
| + static bool classof(const Inst *Inst) { | 
| + return InstX86Base::isClassof(Inst, InstX86Base::FakeRMW); | 
| } | 
| - } | 
| -}; | 
| -/// InstX86FakeRMW represents a non-atomic read-modify-write operation on a | 
| -/// memory location. An InstX86FakeRMW is a "fake" instruction in that it still | 
| -/// needs to be lowered to some actual RMW instruction. | 
| -/// | 
| -/// If A is some memory address, D is some data value to apply, and OP is an | 
| -/// arithmetic operator, the instruction operates as: (*A) = (*A) OP D | 
| -template <class Machine> | 
| -class InstX86FakeRMW final : public InstX86Base<Machine> { | 
| - InstX86FakeRMW() = delete; | 
| - InstX86FakeRMW(const InstX86FakeRMW &) = delete; | 
| - InstX86FakeRMW &operator=(const InstX86FakeRMW &) = delete; | 
| - | 
| -public: | 
| - static InstX86FakeRMW *create(Cfg *Func, Operand *Data, Operand *Addr, | 
| - Variable *Beacon, InstArithmetic::OpKind Op, | 
| - uint32_t Align = 1) { | 
| - // TODO(stichnot): Stop ignoring alignment specification. | 
| - (void)Align; | 
| - return new (Func->allocate<InstX86FakeRMW>()) | 
| - InstX86FakeRMW(Func, Data, Addr, Op, Beacon); | 
| - } | 
| - Operand *getAddr() const { return this->getSrc(1); } | 
| - Operand *getData() const { return this->getSrc(0); } | 
| - InstArithmetic::OpKind getOp() const { return Op; } | 
| - Variable *getBeacon() const { return llvm::cast<Variable>(this->getSrc(2)); } | 
| - void dump(const Cfg *Func) const override; | 
| - static bool classof(const Inst *Inst) { | 
| - return InstX86Base<Machine>::isClassof(Inst, InstX86Base<Machine>::FakeRMW); | 
| - } | 
| + private: | 
| + InstArithmetic::OpKind Op; | 
| + InstX86FakeRMW(Cfg *Func, Operand *Data, Operand *Addr, | 
| + InstArithmetic::OpKind Op, Variable *Beacon); | 
| + }; | 
| -private: | 
| - InstArithmetic::OpKind Op; | 
| - InstX86FakeRMW(Cfg *Func, Operand *Data, Operand *Addr, | 
| - InstArithmetic::OpKind Op, Variable *Beacon); | 
| -}; | 
| + /// InstX86Label represents an intra-block label that is the target of an | 
| + /// intra-block branch. The offset between the label and the branch must be | 
| + /// fit into one byte (considered "near"). These are used for lowering i1 | 
| + /// calculations, Select instructions, and 64-bit compares on a 32-bit | 
| + /// architecture, without basic block splitting. Basic block splitting is not | 
| + /// so desirable for several reasons, one of which is the impact on decisions | 
| + /// based on whether a variable's live range spans multiple basic blocks. | 
| + /// | 
| + /// Intra-block control flow must be used with caution. Consider the sequence | 
| + /// for "c = (a >= b ? x : y)". | 
| + /// cmp a, b | 
| + /// br lt, L1 | 
| + /// mov c, x | 
| + /// jmp L2 | 
| + /// L1: | 
| + /// mov c, y | 
| + /// L2: | 
| + /// | 
| + /// Labels L1 and L2 are intra-block labels. Without knowledge of the | 
| + /// intra-block control flow, liveness analysis will determine the "mov c, x" | 
| + /// instruction to be dead. One way to prevent this is to insert a | 
| + /// "FakeUse(c)" instruction anywhere between the two "mov c, ..." | 
| + /// instructions, e.g.: | 
| + /// | 
| + /// cmp a, b | 
| + /// br lt, L1 | 
| + /// mov c, x | 
| + /// jmp L2 | 
| + /// FakeUse(c) | 
| + /// L1: | 
| + /// mov c, y | 
| + /// L2: | 
| + /// | 
| + /// The down-side is that "mov c, x" can never be dead-code eliminated even if | 
| + /// there are no uses of c. As unlikely as this situation is, it may be | 
| + /// prevented by running dead code elimination before lowering. | 
| + class InstX86Label final : public InstX86Base { | 
| + InstX86Label() = delete; | 
| + InstX86Label(const InstX86Label &) = delete; | 
| + InstX86Label &operator=(const InstX86Label &) = delete; | 
| + | 
| + public: | 
| + static InstX86Label *create(Cfg *Func, TargetLowering *Target) { | 
| + return new (Func->allocate<InstX86Label>()) InstX86Label(Func, Target); | 
| + } | 
| + uint32_t getEmitInstCount() const override { return 0; } | 
| + IceString getName(const Cfg *Func) const; | 
| + SizeT getNumber() const { return Number; } | 
| + void emit(const Cfg *Func) const override; | 
| + void emitIAS(const Cfg *Func) const override; | 
| + void dump(const Cfg *Func) const override; | 
| -/// InstX86Label represents an intra-block label that is the target of an | 
| -/// intra-block branch. The offset between the label and the branch must be fit | 
| -/// into one byte (considered "near"). These are used for lowering i1 | 
| -/// calculations, Select instructions, and 64-bit compares on a 32-bit | 
| -/// architecture, without basic block splitting. Basic block splitting is not so | 
| -/// desirable for several reasons, one of which is the impact on decisions based | 
| -/// on whether a variable's live range spans multiple basic blocks. | 
| -/// | 
| -/// Intra-block control flow must be used with caution. Consider the sequence | 
| -/// for "c = (a >= b ? x : y)". | 
| -/// cmp a, b | 
| -/// br lt, L1 | 
| -/// mov c, x | 
| -/// jmp L2 | 
| -/// L1: | 
| -/// mov c, y | 
| -/// L2: | 
| -/// | 
| -/// Labels L1 and L2 are intra-block labels. Without knowledge of the | 
| -/// intra-block control flow, liveness analysis will determine the "mov c, x" | 
| -/// instruction to be dead. One way to prevent this is to insert a "FakeUse(c)" | 
| -/// instruction anywhere between the two "mov c, ..." instructions, e.g.: | 
| -/// | 
| -/// cmp a, b | 
| -/// br lt, L1 | 
| -/// mov c, x | 
| -/// jmp L2 | 
| -/// FakeUse(c) | 
| -/// L1: | 
| -/// mov c, y | 
| -/// L2: | 
| -/// | 
| -/// The down-side is that "mov c, x" can never be dead-code eliminated even if | 
| -/// there are no uses of c. As unlikely as this situation is, it may be | 
| -/// prevented by running dead code elimination before lowering. | 
| -template <class Machine> | 
| -class InstX86Label final : public InstX86Base<Machine> { | 
| - InstX86Label() = delete; | 
| - InstX86Label(const InstX86Label &) = delete; | 
| - InstX86Label &operator=(const InstX86Label &) = delete; | 
| - | 
| -public: | 
| - static InstX86Label * | 
| - create(Cfg *Func, | 
| - typename InstX86Base<Machine>::Traits::TargetLowering *Target) { | 
| - return new (Func->allocate<InstX86Label>()) InstX86Label(Func, Target); | 
| - } | 
| - uint32_t getEmitInstCount() const override { return 0; } | 
| - IceString getName(const Cfg *Func) const; | 
| - SizeT getNumber() const { return Number; } | 
| - void emit(const Cfg *Func) const override; | 
| - void emitIAS(const Cfg *Func) const override; | 
| - void dump(const Cfg *Func) const override; | 
| - | 
| -private: | 
| - InstX86Label(Cfg *Func, | 
| - typename InstX86Base<Machine>::Traits::TargetLowering *Target); | 
| - | 
| - SizeT Number; // used for unique label generation. | 
| -}; | 
| + private: | 
| + InstX86Label(Cfg *Func, TargetLowering *Target); | 
| -/// Conditional and unconditional branch instruction. | 
| -template <class Machine> class InstX86Br final : public InstX86Base<Machine> { | 
| - InstX86Br() = delete; | 
| - InstX86Br(const InstX86Br &) = delete; | 
| - InstX86Br &operator=(const InstX86Br &) = delete; | 
| - | 
| -public: | 
| - enum Mode { Near, Far }; | 
| - | 
| - /// Create a conditional branch to a node. | 
| - static InstX86Br * | 
| - create(Cfg *Func, CfgNode *TargetTrue, CfgNode *TargetFalse, | 
| - typename InstX86Base<Machine>::Traits::Cond::BrCond Condition, | 
| - Mode Kind) { | 
| - assert(Condition != InstX86Base<Machine>::Traits::Cond::Br_None); | 
| - constexpr InstX86Label<Machine> *NoLabel = nullptr; | 
| - return new (Func->allocate<InstX86Br>()) | 
| - InstX86Br(Func, TargetTrue, TargetFalse, NoLabel, Condition, Kind); | 
| - } | 
| - /// Create an unconditional branch to a node. | 
| - static InstX86Br *create(Cfg *Func, CfgNode *Target, Mode Kind) { | 
| - constexpr CfgNode *NoCondTarget = nullptr; | 
| - constexpr InstX86Label<Machine> *NoLabel = nullptr; | 
| - return new (Func->allocate<InstX86Br>()) | 
| - InstX86Br(Func, NoCondTarget, Target, NoLabel, | 
| - InstX86Base<Machine>::Traits::Cond::Br_None, Kind); | 
| - } | 
| - /// Create a non-terminator conditional branch to a node, with a fallthrough | 
| - /// to the next instruction in the current node. This is used for switch | 
| - /// lowering. | 
| - static InstX86Br * | 
| - create(Cfg *Func, CfgNode *Target, | 
| - typename InstX86Base<Machine>::Traits::Cond::BrCond Condition, | 
| - Mode Kind) { | 
| - assert(Condition != InstX86Base<Machine>::Traits::Cond::Br_None); | 
| - constexpr CfgNode *NoUncondTarget = nullptr; | 
| - constexpr InstX86Label<Machine> *NoLabel = nullptr; | 
| - return new (Func->allocate<InstX86Br>()) | 
| - InstX86Br(Func, Target, NoUncondTarget, NoLabel, Condition, Kind); | 
| - } | 
| - /// Create a conditional intra-block branch (or unconditional, if | 
| - /// Condition==Br_None) to a label in the current block. | 
| - static InstX86Br * | 
| - create(Cfg *Func, InstX86Label<Machine> *Label, | 
| - typename InstX86Base<Machine>::Traits::Cond::BrCond Condition, | 
| - Mode Kind) { | 
| - constexpr CfgNode *NoCondTarget = nullptr; | 
| - constexpr CfgNode *NoUncondTarget = nullptr; | 
| - return new (Func->allocate<InstX86Br>()) | 
| - InstX86Br(Func, NoCondTarget, NoUncondTarget, Label, Condition, Kind); | 
| - } | 
| - const CfgNode *getTargetTrue() const { return TargetTrue; } | 
| - const CfgNode *getTargetFalse() const { return TargetFalse; } | 
| - bool isNear() const { return Kind == Near; } | 
| - bool optimizeBranch(const CfgNode *NextNode); | 
| - uint32_t getEmitInstCount() const override { | 
| - uint32_t Sum = 0; | 
| - if (Label) | 
| - ++Sum; | 
| - if (getTargetTrue()) | 
| - ++Sum; | 
| - if (getTargetFalse()) | 
| - ++Sum; | 
| - return Sum; | 
| - } | 
| - bool isUnconditionalBranch() const override { | 
| - return !Label && Condition == InstX86Base<Machine>::Traits::Cond::Br_None; | 
| - } | 
| - bool repointEdges(CfgNode *OldNode, CfgNode *NewNode) override; | 
| - void emit(const Cfg *Func) const override; | 
| - void emitIAS(const Cfg *Func) const override; | 
| - void dump(const Cfg *Func) const override; | 
| - static bool classof(const Inst *Inst) { | 
| - return InstX86Base<Machine>::isClassof(Inst, InstX86Base<Machine>::Br); | 
| - } | 
| + SizeT Number; // used for unique label generation. | 
| + }; | 
| -private: | 
| - InstX86Br(Cfg *Func, const CfgNode *TargetTrue, const CfgNode *TargetFalse, | 
| - const InstX86Label<Machine> *Label, | 
| - typename InstX86Base<Machine>::Traits::Cond::BrCond Condition, | 
| - Mode Kind); | 
| - | 
| - typename InstX86Base<Machine>::Traits::Cond::BrCond Condition; | 
| - const CfgNode *TargetTrue; | 
| - const CfgNode *TargetFalse; | 
| - const InstX86Label<Machine> *Label; // Intra-block branch target | 
| - const Mode Kind; | 
| -}; | 
| + /// Conditional and unconditional branch instruction. | 
| + class InstX86Br final : public InstX86Base { | 
| + InstX86Br() = delete; | 
| + InstX86Br(const InstX86Br &) = delete; | 
| + InstX86Br &operator=(const InstX86Br &) = delete; | 
| + | 
| + public: | 
| + enum Mode { Near, Far }; | 
| + | 
| + /// Create a conditional branch to a node. | 
| + static InstX86Br *create(Cfg *Func, CfgNode *TargetTrue, | 
| + CfgNode *TargetFalse, BrCond Condition, | 
| + Mode Kind) { | 
| + assert(Condition != Cond::Br_None); | 
| + constexpr InstX86Label *NoLabel = nullptr; | 
| + return new (Func->allocate<InstX86Br>()) | 
| + InstX86Br(Func, TargetTrue, TargetFalse, NoLabel, Condition, Kind); | 
| + } | 
| + /// Create an unconditional branch to a node. | 
| + static InstX86Br *create(Cfg *Func, CfgNode *Target, Mode Kind) { | 
| + constexpr CfgNode *NoCondTarget = nullptr; | 
| + constexpr InstX86Label *NoLabel = nullptr; | 
| + return new (Func->allocate<InstX86Br>()) | 
| + InstX86Br(Func, NoCondTarget, Target, NoLabel, Cond::Br_None, Kind); | 
| + } | 
| + /// Create a non-terminator conditional branch to a node, with a fallthrough | 
| + /// to the next instruction in the current node. This is used for switch | 
| + /// lowering. | 
| + static InstX86Br *create(Cfg *Func, CfgNode *Target, BrCond Condition, | 
| + Mode Kind) { | 
| + assert(Condition != Cond::Br_None); | 
| + constexpr CfgNode *NoUncondTarget = nullptr; | 
| + constexpr InstX86Label *NoLabel = nullptr; | 
| + return new (Func->allocate<InstX86Br>()) | 
| + InstX86Br(Func, Target, NoUncondTarget, NoLabel, Condition, Kind); | 
| + } | 
| + /// Create a conditional intra-block branch (or unconditional, if | 
| + /// Condition==Br_None) to a label in the current block. | 
| + static InstX86Br *create(Cfg *Func, InstX86Label *Label, BrCond Condition, | 
| + Mode Kind) { | 
| + constexpr CfgNode *NoCondTarget = nullptr; | 
| + constexpr CfgNode *NoUncondTarget = nullptr; | 
| + return new (Func->allocate<InstX86Br>()) | 
| + InstX86Br(Func, NoCondTarget, NoUncondTarget, Label, Condition, Kind); | 
| + } | 
| + const CfgNode *getTargetTrue() const { return TargetTrue; } | 
| + const CfgNode *getTargetFalse() const { return TargetFalse; } | 
| + bool isNear() const { return Kind == Near; } | 
| + bool optimizeBranch(const CfgNode *NextNode); | 
| + uint32_t getEmitInstCount() const override { | 
| + uint32_t Sum = 0; | 
| + if (Label) | 
| + ++Sum; | 
| + if (getTargetTrue()) | 
| + ++Sum; | 
| + if (getTargetFalse()) | 
| + ++Sum; | 
| + return Sum; | 
| + } | 
| + bool isUnconditionalBranch() const override { | 
| + return !Label && Condition == Cond::Br_None; | 
| + } | 
| + bool repointEdges(CfgNode *OldNode, CfgNode *NewNode) override; | 
| + void emit(const Cfg *Func) const override; | 
| + void emitIAS(const Cfg *Func) const override; | 
| + void dump(const Cfg *Func) const override; | 
| + static bool classof(const Inst *Inst) { | 
| + return InstX86Base::isClassof(Inst, InstX86Base::Br); | 
| + } | 
| -/// Jump to a target outside this function, such as tailcall, nacljump, naclret, | 
| -/// unreachable. This is different from a Branch instruction in that there is no | 
| -/// intra-function control flow to represent. | 
| -template <class Machine> class InstX86Jmp final : public InstX86Base<Machine> { | 
| - InstX86Jmp() = delete; | 
| - InstX86Jmp(const InstX86Jmp &) = delete; | 
| - InstX86Jmp &operator=(const InstX86Jmp &) = delete; | 
| - | 
| -public: | 
| - static InstX86Jmp *create(Cfg *Func, Operand *Target) { | 
| - return new (Func->allocate<InstX86Jmp>()) InstX86Jmp(Func, Target); | 
| - } | 
| - Operand *getJmpTarget() const { return this->getSrc(0); } | 
| - void emit(const Cfg *Func) const override; | 
| - void emitIAS(const Cfg *Func) const override; | 
| - void dump(const Cfg *Func) const override; | 
| - static bool classof(const Inst *Inst) { | 
| - return InstX86Base<Machine>::isClassof(Inst, InstX86Base<Machine>::Jmp); | 
| - } | 
| + private: | 
| + InstX86Br(Cfg *Func, const CfgNode *TargetTrue, const CfgNode *TargetFalse, | 
| + const InstX86Label *Label, BrCond Condition, Mode Kind); | 
| -private: | 
| - InstX86Jmp(Cfg *Func, Operand *Target); | 
| -}; | 
| + BrCond Condition; | 
| + const CfgNode *TargetTrue; | 
| + const CfgNode *TargetFalse; | 
| + const InstX86Label *Label; // Intra-block branch target | 
| + const Mode Kind; | 
| + }; | 
| -/// Call instruction. Arguments should have already been pushed. | 
| -template <class Machine> class InstX86Call final : public InstX86Base<Machine> { | 
| - InstX86Call() = delete; | 
| - InstX86Call(const InstX86Call &) = delete; | 
| - InstX86Call &operator=(const InstX86Call &) = delete; | 
| + /// Jump to a target outside this function, such as tailcall, nacljump, | 
| + /// naclret, unreachable. This is different from a Branch instruction in that | 
| + /// there is no intra-function control flow to represent. | 
| + class InstX86Jmp final : public InstX86Base { | 
| + InstX86Jmp() = delete; | 
| + InstX86Jmp(const InstX86Jmp &) = delete; | 
| + InstX86Jmp &operator=(const InstX86Jmp &) = delete; | 
| + | 
| + public: | 
| + static InstX86Jmp *create(Cfg *Func, Operand *Target) { | 
| + return new (Func->allocate<InstX86Jmp>()) InstX86Jmp(Func, Target); | 
| + } | 
| + Operand *getJmpTarget() const { return this->getSrc(0); } | 
| + void emit(const Cfg *Func) const override; | 
| + void emitIAS(const Cfg *Func) const override; | 
| + void dump(const Cfg *Func) const override; | 
| + static bool classof(const Inst *Inst) { | 
| + return InstX86Base::isClassof(Inst, InstX86Base::Jmp); | 
| + } | 
| -public: | 
| - static InstX86Call *create(Cfg *Func, Variable *Dest, Operand *CallTarget) { | 
| - return new (Func->allocate<InstX86Call>()) | 
| - InstX86Call(Func, Dest, CallTarget); | 
| - } | 
| - Operand *getCallTarget() const { return this->getSrc(0); } | 
| - void emit(const Cfg *Func) const override; | 
| - void emitIAS(const Cfg *Func) const override; | 
| - void dump(const Cfg *Func) const override; | 
| - static bool classof(const Inst *Inst) { | 
| - return InstX86Base<Machine>::isClassof(Inst, InstX86Base<Machine>::Call); | 
| - } | 
| + private: | 
| + InstX86Jmp(Cfg *Func, Operand *Target); | 
| + }; | 
| -private: | 
| - InstX86Call(Cfg *Func, Variable *Dest, Operand *CallTarget); | 
| -}; | 
| + /// Call instruction. Arguments should have already been pushed. | 
| + class InstX86Call final : public InstX86Base { | 
| + InstX86Call() = delete; | 
| + InstX86Call(const InstX86Call &) = delete; | 
| + InstX86Call &operator=(const InstX86Call &) = delete; | 
| -/// Emit a one-operand (GPR) instruction. | 
| -template <class Machine> | 
| -void emitIASOpTyGPR(const Cfg *Func, Type Ty, const Operand *Var, | 
| - const typename InstX86Base< | 
| - Machine>::Traits::Assembler::GPREmitterOneOp &Emitter); | 
| - | 
| -template <class Machine> | 
| -void emitIASAsAddrOpTyGPR( | 
| - const Cfg *Func, Type Ty, const Operand *Op0, const Operand *Op1, | 
| - const typename InstX86Base<Machine>::Traits::Assembler::GPREmitterAddrOp | 
| - &Emitter); | 
| - | 
| -/// Instructions of the form x := op(x). | 
| -template <class Machine, typename InstX86Base<Machine>::InstKindX86 K> | 
| -class InstX86BaseInplaceopGPR : public InstX86Base<Machine> { | 
| - InstX86BaseInplaceopGPR() = delete; | 
| - InstX86BaseInplaceopGPR(const InstX86BaseInplaceopGPR &) = delete; | 
| - InstX86BaseInplaceopGPR &operator=(const InstX86BaseInplaceopGPR &) = delete; | 
| - | 
| -public: | 
| - using Base = InstX86BaseInplaceopGPR<Machine, K>; | 
| - | 
| - void emit(const Cfg *Func) const override { | 
| - if (!BuildDefs::dump()) | 
| - return; | 
| - Ostream &Str = Func->getContext()->getStrEmit(); | 
| - assert(this->getSrcSize() == 1); | 
| - Str << "\t" << Opcode << "\t"; | 
| - this->getSrc(0)->emit(Func); | 
| - } | 
| - void emitIAS(const Cfg *Func) const override { | 
| - assert(this->getSrcSize() == 1); | 
| - const Variable *Var = this->getDest(); | 
| - Type Ty = Var->getType(); | 
| - emitIASOpTyGPR<Machine>(Func, Ty, Var, Emitter); | 
| - } | 
| - void dump(const Cfg *Func) const override { | 
| - if (!BuildDefs::dump()) | 
| - return; | 
| - Ostream &Str = Func->getContext()->getStrDump(); | 
| - this->dumpDest(Func); | 
| - Str << " = " << Opcode << "." << this->getDest()->getType() << " "; | 
| - this->dumpSources(Func); | 
| - } | 
| - static bool classof(const Inst *Inst) { | 
| - return InstX86Base<Machine>::isClassof(Inst, InstX86Base<Machine>::K); | 
| - } | 
| + public: | 
| + static InstX86Call *create(Cfg *Func, Variable *Dest, Operand *CallTarget) { | 
| + return new (Func->allocate<InstX86Call>()) | 
| + InstX86Call(Func, Dest, CallTarget); | 
| + } | 
| + Operand *getCallTarget() const { return this->getSrc(0); } | 
| + void emit(const Cfg *Func) const override; | 
| + void emitIAS(const Cfg *Func) const override; | 
| + void dump(const Cfg *Func) const override; | 
| + static bool classof(const Inst *Inst) { | 
| + return InstX86Base::isClassof(Inst, InstX86Base::Call); | 
| + } | 
| -protected: | 
| - InstX86BaseInplaceopGPR(Cfg *Func, Operand *SrcDest) | 
| - : InstX86Base<Machine>(Func, K, 1, llvm::dyn_cast<Variable>(SrcDest)) { | 
| - this->addSource(SrcDest); | 
| - } | 
| + private: | 
| + InstX86Call(Cfg *Func, Variable *Dest, Operand *CallTarget); | 
| + }; | 
| -private: | 
| - static const char *Opcode; | 
| - static const typename InstX86Base<Machine>::Traits::Assembler::GPREmitterOneOp | 
| - Emitter; | 
| -}; | 
| + /// Emit a one-operand (GPR) instruction. | 
| + static void emitIASOpTyGPR(const Cfg *Func, Type Ty, const Operand *Var, | 
| + const GPREmitterOneOp &Emitter); | 
| -/// Emit a two-operand (GPR) instruction, where the dest operand is a Variable | 
| -/// that's guaranteed to be a register. | 
| -template <class Machine, bool VarCanBeByte = true, bool SrcCanBeByte = true> | 
| -void emitIASRegOpTyGPR( | 
| - const Cfg *Func, Type Ty, const Variable *Dst, const Operand *Src, | 
| - const typename InstX86Base<Machine>::Traits::Assembler::GPREmitterRegOp | 
| - &Emitter); | 
| - | 
| -/// Instructions of the form x := op(y). | 
| -template <class Machine, typename InstX86Base<Machine>::InstKindX86 K> | 
| -class InstX86BaseUnaryopGPR : public InstX86Base<Machine> { | 
| - InstX86BaseUnaryopGPR() = delete; | 
| - InstX86BaseUnaryopGPR(const InstX86BaseUnaryopGPR &) = delete; | 
| - InstX86BaseUnaryopGPR &operator=(const InstX86BaseUnaryopGPR &) = delete; | 
| - | 
| -public: | 
| - using Base = InstX86BaseUnaryopGPR<Machine, K>; | 
| - | 
| - void emit(const Cfg *Func) const override { | 
| - if (!BuildDefs::dump()) | 
| - return; | 
| - Ostream &Str = Func->getContext()->getStrEmit(); | 
| - assert(this->getSrcSize() == 1); | 
| - Type SrcTy = this->getSrc(0)->getType(); | 
| - Type DestTy = this->getDest()->getType(); | 
| - Str << "\t" << Opcode << this->getWidthString(SrcTy); | 
| - // Movsx and movzx need both the source and dest type width letter to | 
| - // define the operation. The other unary operations have the same source | 
| - // and dest type and as a result need only one letter. | 
| - if (SrcTy != DestTy) | 
| - Str << this->getWidthString(DestTy); | 
| - Str << "\t"; | 
| - this->getSrc(0)->emit(Func); | 
| - Str << ", "; | 
| - this->getDest()->emit(Func); | 
| - } | 
| - void emitIAS(const Cfg *Func) const override { | 
| - assert(this->getSrcSize() == 1); | 
| - const Variable *Var = this->getDest(); | 
| - Type Ty = Var->getType(); | 
| - const Operand *Src = this->getSrc(0); | 
| - emitIASRegOpTyGPR<Machine>(Func, Ty, Var, Src, Emitter); | 
| - } | 
| - void dump(const Cfg *Func) const override { | 
| - if (!BuildDefs::dump()) | 
| - return; | 
| - Ostream &Str = Func->getContext()->getStrDump(); | 
| - this->dumpDest(Func); | 
| - Str << " = " << Opcode << "." << this->getSrc(0)->getType() << " "; | 
| - this->dumpSources(Func); | 
| - } | 
| - static bool classof(const Inst *Inst) { | 
| - return InstX86Base<Machine>::isClassof(Inst, InstX86Base<Machine>::K); | 
| - } | 
| + static void emitIASAsAddrOpTyGPR(const Cfg *Func, Type Ty, const Operand *Op0, | 
| + const Operand *Op1, | 
| + const GPREmitterAddrOp &Emitter); | 
| -protected: | 
| - InstX86BaseUnaryopGPR(Cfg *Func, Variable *Dest, Operand *Src) | 
| - : InstX86Base<Machine>(Func, K, 1, Dest) { | 
| - this->addSource(Src); | 
| - } | 
| + static void emitIASGPRShift(const Cfg *Func, Type Ty, const Variable *Var, | 
| + const Operand *Src, | 
| + const GPREmitterShiftOp &Emitter); | 
| - static const char *Opcode; | 
| - static const typename InstX86Base<Machine>::Traits::Assembler::GPREmitterRegOp | 
| - Emitter; | 
| -}; | 
| + static void emitIASAddrOpTyGPR(const Cfg *Func, Type Ty, const Address &Addr, | 
| + const Operand *Src, | 
| + const GPREmitterAddrOp &Emitter); | 
| -template <class Machine> | 
| -void emitIASRegOpTyXMM( | 
| - const Cfg *Func, Type Ty, const Variable *Var, const Operand *Src, | 
| - const typename InstX86Base<Machine>::Traits::Assembler::XmmEmitterRegOp | 
| - &Emitter); | 
| - | 
| -template <class Machine, typename InstX86Base<Machine>::InstKindX86 K> | 
| -class InstX86BaseUnaryopXmm : public InstX86Base<Machine> { | 
| - InstX86BaseUnaryopXmm() = delete; | 
| - InstX86BaseUnaryopXmm(const InstX86BaseUnaryopXmm &) = delete; | 
| - InstX86BaseUnaryopXmm &operator=(const InstX86BaseUnaryopXmm &) = delete; | 
| - | 
| -public: | 
| - using Base = InstX86BaseUnaryopXmm<Machine, K>; | 
| - | 
| - void emit(const Cfg *Func) const override { | 
| - if (!BuildDefs::dump()) | 
| - return; | 
| - Ostream &Str = Func->getContext()->getStrEmit(); | 
| - assert(this->getSrcSize() == 1); | 
| - Str << "\t" << Opcode << "\t"; | 
| - this->getSrc(0)->emit(Func); | 
| - Str << ", "; | 
| - this->getDest()->emit(Func); | 
| - } | 
| - void emitIAS(const Cfg *Func) const override { | 
| - Type Ty = this->getDest()->getType(); | 
| - assert(this->getSrcSize() == 1); | 
| - emitIASRegOpTyXMM<Machine>(Func, Ty, this->getDest(), this->getSrc(0), | 
| - Emitter); | 
| - } | 
| - void dump(const Cfg *Func) const override { | 
| - if (!BuildDefs::dump()) | 
| - return; | 
| - Ostream &Str = Func->getContext()->getStrDump(); | 
| - this->dumpDest(Func); | 
| - Str << " = " << Opcode << "." << this->getDest()->getType() << " "; | 
| - this->dumpSources(Func); | 
| - } | 
| - static bool classof(const Inst *Inst) { | 
| - return InstX86Base<Machine>::isClassof(Inst, InstX86Base<Machine>::K); | 
| - } | 
| + static void emitIASRegOpTyXMM(const Cfg *Func, Type Ty, const Variable *Var, | 
| + const Operand *Src, | 
| + const XmmEmitterRegOp &Emitter); | 
| -protected: | 
| - InstX86BaseUnaryopXmm(Cfg *Func, Variable *Dest, Operand *Src) | 
| - : InstX86Base<Machine>(Func, K, 1, Dest) { | 
| - this->addSource(Src); | 
| - } | 
| + static void emitIASGPRShiftDouble(const Cfg *Func, const Variable *Dest, | 
| + const Operand *Src1Op, | 
| + const Operand *Src2Op, | 
| + const GPREmitterShiftD &Emitter); | 
| - static const char *Opcode; | 
| - static const typename InstX86Base<Machine>::Traits::Assembler::XmmEmitterRegOp | 
| - Emitter; | 
| -}; | 
| + template <typename DReg_t, typename SReg_t, DReg_t (*destEnc)(int32_t), | 
| + SReg_t (*srcEnc)(int32_t)> | 
| + static void emitIASCastRegOp(const Cfg *Func, Type DestTy, | 
| + const Variable *Dest, Type SrcTy, | 
| + const Operand *Src, | 
| + const CastEmitterRegOp<DReg_t, SReg_t> &Emitter); | 
| + | 
| + template <typename DReg_t, typename SReg_t, DReg_t (*destEnc)(int32_t), | 
| + SReg_t (*srcEnc)(int32_t)> | 
| + static void | 
| + emitIASThreeOpImmOps(const Cfg *Func, Type DispatchTy, const Variable *Dest, | 
| + const Operand *Src0, const Operand *Src1, | 
| + const ThreeOpImmEmitter<DReg_t, SReg_t> Emitter); | 
| + | 
| + static void emitIASMovlikeXMM(const Cfg *Func, const Variable *Dest, | 
| + const Operand *Src, | 
| + const XmmEmitterMovOps Emitter); | 
| + | 
| + static void emitVariableBlendInst(const char *Opcode, const Inst *Inst, | 
| + const Cfg *Func); | 
| + | 
| + static void emitIASVariableBlendInst(const Inst *Inst, const Cfg *Func, | 
| + const XmmEmitterRegOp &Emitter); | 
| + | 
| + static void emitIASXmmShift(const Cfg *Func, Type Ty, const Variable *Var, | 
| + const Operand *Src, | 
| + const XmmEmitterShiftOp &Emitter); | 
| + | 
| + /// Emit a two-operand (GPR) instruction, where the dest operand is a Variable | 
| + /// that's guaranteed to be a register. | 
| + template <bool VarCanBeByte = true, bool SrcCanBeByte = true> | 
| + static void emitIASRegOpTyGPR(const Cfg *Func, Type Ty, const Variable *Dst, | 
| + const Operand *Src, | 
| + const GPREmitterRegOp &Emitter); | 
| + | 
| + /// Instructions of the form x := op(x). | 
| + template <typename InstX86Base::InstKindX86 K> | 
| + class InstX86BaseInplaceopGPR : public InstX86Base { | 
| + InstX86BaseInplaceopGPR() = delete; | 
| + InstX86BaseInplaceopGPR(const InstX86BaseInplaceopGPR &) = delete; | 
| + InstX86BaseInplaceopGPR & | 
| + operator=(const InstX86BaseInplaceopGPR &) = delete; | 
| + | 
| + public: | 
| + using Base = InstX86BaseInplaceopGPR<K>; | 
| + | 
| + void emit(const Cfg *Func) const override { | 
| + if (!BuildDefs::dump()) | 
| + return; | 
| + Ostream &Str = Func->getContext()->getStrEmit(); | 
| + assert(this->getSrcSize() == 1); | 
| + Str << "\t" << Opcode << "\t"; | 
| + this->getSrc(0)->emit(Func); | 
| + } | 
| + void emitIAS(const Cfg *Func) const override { | 
| + assert(this->getSrcSize() == 1); | 
| + const Variable *Var = this->getDest(); | 
| + Type Ty = Var->getType(); | 
| + emitIASOpTyGPR(Func, Ty, Var, Emitter); | 
| + } | 
| + void dump(const Cfg *Func) const override { | 
| + if (!BuildDefs::dump()) | 
| + return; | 
| + Ostream &Str = Func->getContext()->getStrDump(); | 
| + this->dumpDest(Func); | 
| + Str << " = " << Opcode << "." << this->getDest()->getType() << " "; | 
| + this->dumpSources(Func); | 
| + } | 
| + static bool classof(const Inst *Inst) { | 
| + return InstX86Base::isClassof(Inst, InstX86Base::K); | 
| + } | 
| -template <class Machine, typename InstX86Base<Machine>::InstKindX86 K> | 
| -class InstX86BaseBinopGPRShift : public InstX86Base<Machine> { | 
| - InstX86BaseBinopGPRShift() = delete; | 
| - InstX86BaseBinopGPRShift(const InstX86BaseBinopGPRShift &) = delete; | 
| - InstX86BaseBinopGPRShift & | 
| - operator=(const InstX86BaseBinopGPRShift &) = delete; | 
| + protected: | 
| + InstX86BaseInplaceopGPR(Cfg *Func, Operand *SrcDest) | 
| + : InstX86Base(Func, K, 1, llvm::dyn_cast<Variable>(SrcDest)) { | 
| + this->addSource(SrcDest); | 
| + } | 
| -public: | 
| - using Base = InstX86BaseBinopGPRShift<Machine, K>; | 
| + private: | 
| + static const char *Opcode; | 
| + static const GPREmitterOneOp Emitter; | 
| + }; | 
| - void emit(const Cfg *Func) const override { | 
| - if (!BuildDefs::dump()) | 
| - return; | 
| - this->emitTwoAddress(Func, Opcode); | 
| - } | 
| - void emitIAS(const Cfg *Func) const override { | 
| - Type Ty = this->getDest()->getType(); | 
| - assert(this->getSrcSize() == 2); | 
| - this->emitIASGPRShift(Func, Ty, this->getDest(), this->getSrc(1), Emitter); | 
| - } | 
| - void dump(const Cfg *Func) const override { | 
| - if (!BuildDefs::dump()) | 
| - return; | 
| - Ostream &Str = Func->getContext()->getStrDump(); | 
| - this->dumpDest(Func); | 
| - Str << " = " << Opcode << "." << this->getDest()->getType() << " "; | 
| - this->dumpSources(Func); | 
| - } | 
| - static bool classof(const Inst *Inst) { | 
| - return InstX86Base<Machine>::isClassof(Inst, InstX86Base<Machine>::K); | 
| - } | 
| + /// Instructions of the form x := op(y). | 
| + template <typename InstX86Base::InstKindX86 K> | 
| + class InstX86BaseUnaryopGPR : public InstX86Base { | 
| + InstX86BaseUnaryopGPR() = delete; | 
| + InstX86BaseUnaryopGPR(const InstX86BaseUnaryopGPR &) = delete; | 
| + InstX86BaseUnaryopGPR &operator=(const InstX86BaseUnaryopGPR &) = delete; | 
| + | 
| + public: | 
| + using Base = InstX86BaseUnaryopGPR<K>; | 
| + | 
| + void emit(const Cfg *Func) const override { | 
| + if (!BuildDefs::dump()) | 
| + return; | 
| + Ostream &Str = Func->getContext()->getStrEmit(); | 
| + assert(this->getSrcSize() == 1); | 
| + Type SrcTy = this->getSrc(0)->getType(); | 
| + Type DestTy = this->getDest()->getType(); | 
| + Str << "\t" << Opcode << this->getWidthString(SrcTy); | 
| + // Movsx and movzx need both the source and dest type width letter to | 
| + // define the operation. The other unary operations have the same source | 
| + // and dest type and as a result need only one letter. | 
| + if (SrcTy != DestTy) | 
| + Str << this->getWidthString(DestTy); | 
| + Str << "\t"; | 
| + this->getSrc(0)->emit(Func); | 
| + Str << ", "; | 
| + this->getDest()->emit(Func); | 
| + } | 
| + void emitIAS(const Cfg *Func) const override { | 
| + assert(this->getSrcSize() == 1); | 
| + const Variable *Var = this->getDest(); | 
| + Type Ty = Var->getType(); | 
| + const Operand *Src = this->getSrc(0); | 
| + emitIASRegOpTyGPR(Func, Ty, Var, Src, Emitter); | 
| + } | 
| + void dump(const Cfg *Func) const override { | 
| + if (!BuildDefs::dump()) | 
| + return; | 
| + Ostream &Str = Func->getContext()->getStrDump(); | 
| + this->dumpDest(Func); | 
| + Str << " = " << Opcode << "." << this->getSrc(0)->getType() << " "; | 
| + this->dumpSources(Func); | 
| + } | 
| + static bool classof(const Inst *Inst) { | 
| + return InstX86Base::isClassof(Inst, InstX86Base::K); | 
| + } | 
| -protected: | 
| - InstX86BaseBinopGPRShift(Cfg *Func, Variable *Dest, Operand *Source) | 
| - : InstX86Base<Machine>(Func, K, 2, Dest) { | 
| - this->addSource(Dest); | 
| - this->addSource(Source); | 
| - } | 
| + protected: | 
| + InstX86BaseUnaryopGPR(Cfg *Func, Variable *Dest, Operand *Src) | 
| + : InstX86Base(Func, K, 1, Dest) { | 
| + this->addSource(Src); | 
| + } | 
| - static const char *Opcode; | 
| - static const typename InstX86Base< | 
| - Machine>::Traits::Assembler::GPREmitterShiftOp Emitter; | 
| -}; | 
| + static const char *Opcode; | 
| + static const GPREmitterRegOp Emitter; | 
| + }; | 
| -template <class Machine, typename InstX86Base<Machine>::InstKindX86 K> | 
| -class InstX86BaseBinopGPR : public InstX86Base<Machine> { | 
| - InstX86BaseBinopGPR() = delete; | 
| - InstX86BaseBinopGPR(const InstX86BaseBinopGPR &) = delete; | 
| - InstX86BaseBinopGPR &operator=(const InstX86BaseBinopGPR &) = delete; | 
| + template <typename InstX86Base::InstKindX86 K> | 
| + class InstX86BaseUnaryopXmm : public InstX86Base { | 
| + InstX86BaseUnaryopXmm() = delete; | 
| + InstX86BaseUnaryopXmm(const InstX86BaseUnaryopXmm &) = delete; | 
| + InstX86BaseUnaryopXmm &operator=(const InstX86BaseUnaryopXmm &) = delete; | 
| + | 
| + public: | 
| + using Base = InstX86BaseUnaryopXmm<K>; | 
| + | 
| + void emit(const Cfg *Func) const override { | 
| + if (!BuildDefs::dump()) | 
| + return; | 
| + Ostream &Str = Func->getContext()->getStrEmit(); | 
| + assert(this->getSrcSize() == 1); | 
| + Str << "\t" << Opcode << "\t"; | 
| + this->getSrc(0)->emit(Func); | 
| + Str << ", "; | 
| + this->getDest()->emit(Func); | 
| + } | 
| + void emitIAS(const Cfg *Func) const override { | 
| + Type Ty = this->getDest()->getType(); | 
| + assert(this->getSrcSize() == 1); | 
| + emitIASRegOpTyXMM(Func, Ty, this->getDest(), this->getSrc(0), Emitter); | 
| + } | 
| + void dump(const Cfg *Func) const override { | 
| + if (!BuildDefs::dump()) | 
| + return; | 
| + Ostream &Str = Func->getContext()->getStrDump(); | 
| + this->dumpDest(Func); | 
| + Str << " = " << Opcode << "." << this->getDest()->getType() << " "; | 
| + this->dumpSources(Func); | 
| + } | 
| + static bool classof(const Inst *Inst) { | 
| + return InstX86Base::isClassof(Inst, InstX86Base::K); | 
| + } | 
| -public: | 
| - using Base = InstX86BaseBinopGPR<Machine, K>; | 
| + protected: | 
| + InstX86BaseUnaryopXmm(Cfg *Func, Variable *Dest, Operand *Src) | 
| + : InstX86Base(Func, K, 1, Dest) { | 
| + this->addSource(Src); | 
| + } | 
| - void emit(const Cfg *Func) const override { | 
| - if (!BuildDefs::dump()) | 
| - return; | 
| - this->emitTwoAddress(Func, Opcode); | 
| - } | 
| - void emitIAS(const Cfg *Func) const override { | 
| - Type Ty = this->getDest()->getType(); | 
| - assert(this->getSrcSize() == 2); | 
| - emitIASRegOpTyGPR<Machine>(Func, Ty, this->getDest(), this->getSrc(1), | 
| - Emitter); | 
| - } | 
| - void dump(const Cfg *Func) const override { | 
| - if (!BuildDefs::dump()) | 
| - return; | 
| - Ostream &Str = Func->getContext()->getStrDump(); | 
| - this->dumpDest(Func); | 
| - Str << " = " << Opcode << "." << this->getDest()->getType() << " "; | 
| - this->dumpSources(Func); | 
| - } | 
| - static bool classof(const Inst *Inst) { | 
| - return InstX86Base<Machine>::isClassof(Inst, InstX86Base<Machine>::K); | 
| - } | 
| + static const char *Opcode; | 
| + static const XmmEmitterRegOp Emitter; | 
| + }; | 
| -protected: | 
| - InstX86BaseBinopGPR(Cfg *Func, Variable *Dest, Operand *Source) | 
| - : InstX86Base<Machine>(Func, K, 2, Dest) { | 
| - this->addSource(Dest); | 
| - this->addSource(Source); | 
| - } | 
| + template <typename InstX86Base::InstKindX86 K> | 
| + class InstX86BaseBinopGPRShift : public InstX86Base { | 
| + InstX86BaseBinopGPRShift() = delete; | 
| + InstX86BaseBinopGPRShift(const InstX86BaseBinopGPRShift &) = delete; | 
| + InstX86BaseBinopGPRShift & | 
| + operator=(const InstX86BaseBinopGPRShift &) = delete; | 
| - static const char *Opcode; | 
| - static const typename InstX86Base<Machine>::Traits::Assembler::GPREmitterRegOp | 
| - Emitter; | 
| -}; | 
| + public: | 
| + using Base = InstX86BaseBinopGPRShift<K>; | 
| -template <class Machine, typename InstX86Base<Machine>::InstKindX86 K> | 
| -class InstX86BaseBinopRMW : public InstX86Base<Machine> { | 
| - InstX86BaseBinopRMW() = delete; | 
| - InstX86BaseBinopRMW(const InstX86BaseBinopRMW &) = delete; | 
| - InstX86BaseBinopRMW &operator=(const InstX86BaseBinopRMW &) = delete; | 
| + void emit(const Cfg *Func) const override { | 
| + if (!BuildDefs::dump()) | 
| + return; | 
| + this->emitTwoAddress(Func, Opcode); | 
| + } | 
| + void emitIAS(const Cfg *Func) const override { | 
| + Type Ty = this->getDest()->getType(); | 
| + assert(this->getSrcSize() == 2); | 
| + emitIASGPRShift(Func, Ty, this->getDest(), this->getSrc(1), Emitter); | 
| + } | 
| + void dump(const Cfg *Func) const override { | 
| + if (!BuildDefs::dump()) | 
| + return; | 
| + Ostream &Str = Func->getContext()->getStrDump(); | 
| + this->dumpDest(Func); | 
| + Str << " = " << Opcode << "." << this->getDest()->getType() << " "; | 
| + this->dumpSources(Func); | 
| + } | 
| + static bool classof(const Inst *Inst) { | 
| + return InstX86Base::isClassof(Inst, InstX86Base::K); | 
| + } | 
| -public: | 
| - using Base = InstX86BaseBinopRMW<Machine, K>; | 
| + protected: | 
| + InstX86BaseBinopGPRShift(Cfg *Func, Variable *Dest, Operand *Source) | 
| + : InstX86Base(Func, K, 2, Dest) { | 
| + this->addSource(Dest); | 
| + this->addSource(Source); | 
| + } | 
| - void emit(const Cfg *Func) const override { | 
| - if (!BuildDefs::dump()) | 
| - return; | 
| - this->emitTwoAddress(Func, Opcode); | 
| - } | 
| - void emitIAS(const Cfg *Func) const override { | 
| - Type Ty = this->getSrc(0)->getType(); | 
| - assert(this->getSrcSize() == 2); | 
| - emitIASAsAddrOpTyGPR<Machine>(Func, Ty, this->getSrc(0), this->getSrc(1), | 
| - Emitter); | 
| - } | 
| - void dump(const Cfg *Func) const override { | 
| - if (!BuildDefs::dump()) | 
| - return; | 
| - Ostream &Str = Func->getContext()->getStrDump(); | 
| - Str << Opcode << "." << this->getSrc(0)->getType() << " "; | 
| - this->dumpSources(Func); | 
| - } | 
| - static bool classof(const Inst *Inst) { | 
| - return InstX86Base<Machine>::isClassof(Inst, InstX86Base<Machine>::K); | 
| - } | 
| + static const char *Opcode; | 
| + static const GPREmitterShiftOp Emitter; | 
| + }; | 
| -protected: | 
| - InstX86BaseBinopRMW( | 
| - Cfg *Func, typename InstX86Base<Machine>::Traits::X86OperandMem *DestSrc0, | 
| - Operand *Src1) | 
| - : InstX86Base<Machine>(Func, K, 2, nullptr) { | 
| - this->addSource(DestSrc0); | 
| - this->addSource(Src1); | 
| - } | 
| + template <typename InstX86Base::InstKindX86 K> | 
| + class InstX86BaseBinopGPR : public InstX86Base { | 
| + InstX86BaseBinopGPR() = delete; | 
| + InstX86BaseBinopGPR(const InstX86BaseBinopGPR &) = delete; | 
| + InstX86BaseBinopGPR &operator=(const InstX86BaseBinopGPR &) = delete; | 
| - static const char *Opcode; | 
| - static const typename InstX86Base< | 
| - Machine>::Traits::Assembler::GPREmitterAddrOp Emitter; | 
| -}; | 
| + public: | 
| + using Base = InstX86BaseBinopGPR<K>; | 
| -template <class Machine, typename InstX86Base<Machine>::InstKindX86 K, | 
| - bool NeedsElementType, | 
| - typename InstX86Base<Machine>::SseSuffix Suffix> | 
| -class InstX86BaseBinopXmm : public InstX86Base<Machine> { | 
| - InstX86BaseBinopXmm() = delete; | 
| - InstX86BaseBinopXmm(const InstX86BaseBinopXmm &) = delete; | 
| - InstX86BaseBinopXmm &operator=(const InstX86BaseBinopXmm &) = delete; | 
| - | 
| -public: | 
| - using Base = InstX86BaseBinopXmm<Machine, K, NeedsElementType, Suffix>; | 
| - | 
| - void emit(const Cfg *Func) const override { | 
| - if (!BuildDefs::dump()) | 
| - return; | 
| - this->validateVectorAddrMode(); | 
| - switch (Suffix) { | 
| - case InstX86Base<Machine>::SseSuffix::None: | 
| + void emit(const Cfg *Func) const override { | 
| + if (!BuildDefs::dump()) | 
| + return; | 
| this->emitTwoAddress(Func, Opcode); | 
| - break; | 
| - case InstX86Base<Machine>::SseSuffix::Packed: { | 
| - const Type DestTy = this->getDest()->getType(); | 
| - this->emitTwoAddress( | 
| - Func, this->Opcode, | 
| - InstX86Base<Machine>::Traits::TypeAttributes[DestTy].PdPsString); | 
| - } break; | 
| - case InstX86Base<Machine>::SseSuffix::Scalar: { | 
| - const Type DestTy = this->getDest()->getType(); | 
| - this->emitTwoAddress( | 
| - Func, this->Opcode, | 
| - InstX86Base<Machine>::Traits::TypeAttributes[DestTy].SdSsString); | 
| - } break; | 
| - case InstX86Base<Machine>::SseSuffix::Integral: { | 
| - const Type DestTy = this->getDest()->getType(); | 
| - this->emitTwoAddress( | 
| - Func, this->Opcode, | 
| - InstX86Base<Machine>::Traits::TypeAttributes[DestTy].PackString); | 
| - } break; | 
| } | 
| - } | 
| - void emitIAS(const Cfg *Func) const override { | 
| - this->validateVectorAddrMode(); | 
| - Type Ty = this->getDest()->getType(); | 
| - if (NeedsElementType) | 
| - Ty = typeElementType(Ty); | 
| - assert(this->getSrcSize() == 2); | 
| - emitIASRegOpTyXMM<Machine>(Func, Ty, this->getDest(), this->getSrc(1), | 
| - Emitter); | 
| - } | 
| - void dump(const Cfg *Func) const override { | 
| - if (!BuildDefs::dump()) | 
| - return; | 
| - Ostream &Str = Func->getContext()->getStrDump(); | 
| - this->dumpDest(Func); | 
| - Str << " = " << Opcode << "." << this->getDest()->getType() << " "; | 
| - this->dumpSources(Func); | 
| - } | 
| - static bool classof(const Inst *Inst) { | 
| - return InstX86Base<Machine>::isClassof(Inst, InstX86Base<Machine>::K); | 
| - } | 
| + void emitIAS(const Cfg *Func) const override { | 
| + Type Ty = this->getDest()->getType(); | 
| + assert(this->getSrcSize() == 2); | 
| + emitIASRegOpTyGPR(Func, Ty, this->getDest(), this->getSrc(1), Emitter); | 
| + } | 
| + void dump(const Cfg *Func) const override { | 
| + if (!BuildDefs::dump()) | 
| + return; | 
| + Ostream &Str = Func->getContext()->getStrDump(); | 
| + this->dumpDest(Func); | 
| + Str << " = " << Opcode << "." << this->getDest()->getType() << " "; | 
| + this->dumpSources(Func); | 
| + } | 
| + static bool classof(const Inst *Inst) { | 
| + return InstX86Base::isClassof(Inst, InstX86Base::K); | 
| + } | 
| -protected: | 
| - InstX86BaseBinopXmm(Cfg *Func, Variable *Dest, Operand *Source) | 
| - : InstX86Base<Machine>(Func, K, 2, Dest) { | 
| - this->addSource(Dest); | 
| - this->addSource(Source); | 
| - } | 
| + protected: | 
| + InstX86BaseBinopGPR(Cfg *Func, Variable *Dest, Operand *Source) | 
| + : InstX86Base(Func, K, 2, Dest) { | 
| + this->addSource(Dest); | 
| + this->addSource(Source); | 
| + } | 
| - static const char *Opcode; | 
| - static const typename InstX86Base<Machine>::Traits::Assembler::XmmEmitterRegOp | 
| - Emitter; | 
| -}; | 
| + static const char *Opcode; | 
| + static const GPREmitterRegOp Emitter; | 
| + }; | 
| -template <class Machine> | 
| -void emitIASXmmShift( | 
| - const Cfg *Func, Type Ty, const Variable *Var, const Operand *Src, | 
| - const typename InstX86Base<Machine>::Traits::Assembler::XmmEmitterShiftOp | 
| - &Emitter); | 
| - | 
| -template <class Machine, typename InstX86Base<Machine>::InstKindX86 K, | 
| - bool AllowAllTypes = false> | 
| -class InstX86BaseBinopXmmShift : public InstX86Base<Machine> { | 
| - InstX86BaseBinopXmmShift() = delete; | 
| - InstX86BaseBinopXmmShift(const InstX86BaseBinopXmmShift &) = delete; | 
| - InstX86BaseBinopXmmShift & | 
| - operator=(const InstX86BaseBinopXmmShift &) = delete; | 
| - | 
| -public: | 
| - using Base = InstX86BaseBinopXmmShift<Machine, K, AllowAllTypes>; | 
| - | 
| - void emit(const Cfg *Func) const override { | 
| - if (!BuildDefs::dump()) | 
| - return; | 
| - this->validateVectorAddrMode(); | 
| - // Shift operations are always integral, and hence always need a suffix. | 
| - const Type DestTy = this->getDest()->getType(); | 
| - this->emitTwoAddress( | 
| - Func, this->Opcode, | 
| - InstX86Base<Machine>::Traits::TypeAttributes[DestTy].PackString); | 
| - } | 
| - void emitIAS(const Cfg *Func) const override { | 
| - this->validateVectorAddrMode(); | 
| - Type Ty = this->getDest()->getType(); | 
| - assert(AllowAllTypes || isVectorType(Ty)); | 
| - Type ElementTy = typeElementType(Ty); | 
| - assert(this->getSrcSize() == 2); | 
| - emitIASXmmShift<Machine>(Func, ElementTy, this->getDest(), this->getSrc(1), | 
| - Emitter); | 
| - } | 
| - void dump(const Cfg *Func) const override { | 
| - if (!BuildDefs::dump()) | 
| - return; | 
| - Ostream &Str = Func->getContext()->getStrDump(); | 
| - this->dumpDest(Func); | 
| - Str << " = " << Opcode << "." << this->getDest()->getType() << " "; | 
| - this->dumpSources(Func); | 
| - } | 
| - static bool classof(const Inst *Inst) { | 
| - return InstX86Base<Machine>::isClassof(Inst, InstX86Base<Machine>::K); | 
| - } | 
| + template <typename InstX86Base::InstKindX86 K> | 
| + class InstX86BaseBinopRMW : public InstX86Base { | 
| + InstX86BaseBinopRMW() = delete; | 
| + InstX86BaseBinopRMW(const InstX86BaseBinopRMW &) = delete; | 
| + InstX86BaseBinopRMW &operator=(const InstX86BaseBinopRMW &) = delete; | 
| -protected: | 
| - InstX86BaseBinopXmmShift(Cfg *Func, Variable *Dest, Operand *Source) | 
| - : InstX86Base<Machine>(Func, K, 2, Dest) { | 
| - this->addSource(Dest); | 
| - this->addSource(Source); | 
| - } | 
| + public: | 
| + using Base = InstX86BaseBinopRMW<K>; | 
| - static const char *Opcode; | 
| - static const typename InstX86Base< | 
| - Machine>::Traits::Assembler::XmmEmitterShiftOp Emitter; | 
| -}; | 
| + void emit(const Cfg *Func) const override { | 
| + if (!BuildDefs::dump()) | 
| + return; | 
| + this->emitTwoAddress(Func, Opcode); | 
| + } | 
| + void emitIAS(const Cfg *Func) const override { | 
| + Type Ty = this->getSrc(0)->getType(); | 
| + assert(this->getSrcSize() == 2); | 
| + emitIASAsAddrOpTyGPR(Func, Ty, this->getSrc(0), this->getSrc(1), Emitter); | 
| + } | 
| + void dump(const Cfg *Func) const override { | 
| + if (!BuildDefs::dump()) | 
| + return; | 
| + Ostream &Str = Func->getContext()->getStrDump(); | 
| + Str << Opcode << "." << this->getSrc(0)->getType() << " "; | 
| + this->dumpSources(Func); | 
| + } | 
| + static bool classof(const Inst *Inst) { | 
| + return InstX86Base::isClassof(Inst, InstX86Base::K); | 
| + } | 
| -template <class Machine, typename InstX86Base<Machine>::InstKindX86 K> | 
| -class InstX86BaseTernop : public InstX86Base<Machine> { | 
| - InstX86BaseTernop() = delete; | 
| - InstX86BaseTernop(const InstX86BaseTernop &) = delete; | 
| - InstX86BaseTernop &operator=(const InstX86BaseTernop &) = delete; | 
| - | 
| -public: | 
| - using Base = InstX86BaseTernop<Machine, K>; | 
| - | 
| - void emit(const Cfg *Func) const override { | 
| - if (!BuildDefs::dump()) | 
| - return; | 
| - Ostream &Str = Func->getContext()->getStrEmit(); | 
| - assert(this->getSrcSize() == 3); | 
| - Str << "\t" << Opcode << "\t"; | 
| - this->getSrc(2)->emit(Func); | 
| - Str << ", "; | 
| - this->getSrc(1)->emit(Func); | 
| - Str << ", "; | 
| - this->getDest()->emit(Func); | 
| - } | 
| - void dump(const Cfg *Func) const override { | 
| - if (!BuildDefs::dump()) | 
| - return; | 
| - Ostream &Str = Func->getContext()->getStrDump(); | 
| - this->dumpDest(Func); | 
| - Str << " = " << Opcode << "." << this->getDest()->getType() << " "; | 
| - this->dumpSources(Func); | 
| - } | 
| - static bool classof(const Inst *Inst) { | 
| - return InstX86Base<Machine>::isClassof(Inst, InstX86Base<Machine>::K); | 
| - } | 
| + protected: | 
| + InstX86BaseBinopRMW(Cfg *Func, X86OperandMem *DestSrc0, Operand *Src1) | 
| + : InstX86Base(Func, K, 2, nullptr) { | 
| + this->addSource(DestSrc0); | 
| + this->addSource(Src1); | 
| + } | 
| -protected: | 
| - InstX86BaseTernop(Cfg *Func, Variable *Dest, Operand *Source1, | 
| - Operand *Source2) | 
| - : InstX86Base<Machine>(Func, K, 3, Dest) { | 
| - this->addSource(Dest); | 
| - this->addSource(Source1); | 
| - this->addSource(Source2); | 
| - } | 
| + static const char *Opcode; | 
| + static const GPREmitterAddrOp Emitter; | 
| + }; | 
| - static const char *Opcode; | 
| -}; | 
| + template <typename InstX86Base::InstKindX86 K, bool NeedsElementType, | 
| + typename InstX86Base::SseSuffix Suffix> | 
| + class InstX86BaseBinopXmm : public InstX86Base { | 
| + InstX86BaseBinopXmm() = delete; | 
| + InstX86BaseBinopXmm(const InstX86BaseBinopXmm &) = delete; | 
| + InstX86BaseBinopXmm &operator=(const InstX86BaseBinopXmm &) = delete; | 
| + | 
| + public: | 
| + using Base = InstX86BaseBinopXmm<K, NeedsElementType, Suffix>; | 
| + | 
| + void emit(const Cfg *Func) const override { | 
| + if (!BuildDefs::dump()) | 
| + return; | 
| + this->validateVectorAddrMode(); | 
| + switch (Suffix) { | 
| + case InstX86Base::SseSuffix::None: | 
| + this->emitTwoAddress(Func, Opcode); | 
| + break; | 
| + case InstX86Base::SseSuffix::Packed: { | 
| + const Type DestTy = this->getDest()->getType(); | 
| + this->emitTwoAddress(Func, this->Opcode, | 
| + Traits::TypeAttributes[DestTy].PdPsString); | 
| + } break; | 
| + case InstX86Base::SseSuffix::Scalar: { | 
| + const Type DestTy = this->getDest()->getType(); | 
| + this->emitTwoAddress(Func, this->Opcode, | 
| + Traits::TypeAttributes[DestTy].SdSsString); | 
| + } break; | 
| + case InstX86Base::SseSuffix::Integral: { | 
| + const Type DestTy = this->getDest()->getType(); | 
| + this->emitTwoAddress(Func, this->Opcode, | 
| + Traits::TypeAttributes[DestTy].PackString); | 
| + } break; | 
| + } | 
| + } | 
| + void emitIAS(const Cfg *Func) const override { | 
| + this->validateVectorAddrMode(); | 
| + Type Ty = this->getDest()->getType(); | 
| + if (NeedsElementType) | 
| + Ty = typeElementType(Ty); | 
| + assert(this->getSrcSize() == 2); | 
| + emitIASRegOpTyXMM(Func, Ty, this->getDest(), this->getSrc(1), Emitter); | 
| + } | 
| + void dump(const Cfg *Func) const override { | 
| + if (!BuildDefs::dump()) | 
| + return; | 
| + Ostream &Str = Func->getContext()->getStrDump(); | 
| + this->dumpDest(Func); | 
| + Str << " = " << Opcode << "." << this->getDest()->getType() << " "; | 
| + this->dumpSources(Func); | 
| + } | 
| + static bool classof(const Inst *Inst) { | 
| + return InstX86Base::isClassof(Inst, InstX86Base::K); | 
| + } | 
| -// Instructions of the form x := y op z | 
| -template <class Machine, typename InstX86Base<Machine>::InstKindX86 K> | 
| -class InstX86BaseThreeAddressop : public InstX86Base<Machine> { | 
| - InstX86BaseThreeAddressop() = delete; | 
| - InstX86BaseThreeAddressop(const InstX86BaseThreeAddressop &) = delete; | 
| - InstX86BaseThreeAddressop & | 
| - operator=(const InstX86BaseThreeAddressop &) = delete; | 
| - | 
| -public: | 
| - using Base = InstX86BaseThreeAddressop<Machine, K>; | 
| - | 
| - void emit(const Cfg *Func) const override { | 
| - if (!BuildDefs::dump()) | 
| - return; | 
| - Ostream &Str = Func->getContext()->getStrEmit(); | 
| - assert(this->getSrcSize() == 2); | 
| - Str << "\t" << Opcode << "\t"; | 
| - this->getSrc(1)->emit(Func); | 
| - Str << ", "; | 
| - this->getSrc(0)->emit(Func); | 
| - Str << ", "; | 
| - this->getDest()->emit(Func); | 
| - } | 
| - void dump(const Cfg *Func) const override { | 
| - if (!BuildDefs::dump()) | 
| - return; | 
| - Ostream &Str = Func->getContext()->getStrDump(); | 
| - this->dumpDest(Func); | 
| - Str << " = " << Opcode << "." << this->getDest()->getType() << " "; | 
| - this->dumpSources(Func); | 
| - } | 
| - static bool classof(const Inst *Inst) { | 
| - return InstX86Base<Machine>::isClassof(Inst, InstX86Base<Machine>::K); | 
| - } | 
| + protected: | 
| + InstX86BaseBinopXmm(Cfg *Func, Variable *Dest, Operand *Source) | 
| + : InstX86Base(Func, K, 2, Dest) { | 
| + this->addSource(Dest); | 
| + this->addSource(Source); | 
| + } | 
| -protected: | 
| - InstX86BaseThreeAddressop(Cfg *Func, Variable *Dest, Operand *Source0, | 
| - Operand *Source1) | 
| - : InstX86Base<Machine>(Func, K, 2, Dest) { | 
| - this->addSource(Source0); | 
| - this->addSource(Source1); | 
| - } | 
| + static const char *Opcode; | 
| + static const XmmEmitterRegOp Emitter; | 
| + }; | 
| - static const char *Opcode; | 
| -}; | 
| + template <typename InstX86Base::InstKindX86 K, bool AllowAllTypes = false> | 
| + class InstX86BaseBinopXmmShift : public InstX86Base { | 
| + InstX86BaseBinopXmmShift() = delete; | 
| + InstX86BaseBinopXmmShift(const InstX86BaseBinopXmmShift &) = delete; | 
| + InstX86BaseBinopXmmShift & | 
| + operator=(const InstX86BaseBinopXmmShift &) = delete; | 
| + | 
| + public: | 
| + using Base = InstX86BaseBinopXmmShift<K, AllowAllTypes>; | 
| + | 
| + void emit(const Cfg *Func) const override { | 
| + if (!BuildDefs::dump()) | 
| + return; | 
| + this->validateVectorAddrMode(); | 
| + // Shift operations are always integral, and hence always need a suffix. | 
| + const Type DestTy = this->getDest()->getType(); | 
| + this->emitTwoAddress(Func, this->Opcode, | 
| + Traits::TypeAttributes[DestTy].PackString); | 
| + } | 
| + void emitIAS(const Cfg *Func) const override { | 
| + this->validateVectorAddrMode(); | 
| + Type Ty = this->getDest()->getType(); | 
| + assert(AllowAllTypes || isVectorType(Ty)); | 
| + Type ElementTy = typeElementType(Ty); | 
| + assert(this->getSrcSize() == 2); | 
| + emitIASXmmShift(Func, ElementTy, this->getDest(), this->getSrc(1), | 
| + Emitter); | 
| + } | 
| + void dump(const Cfg *Func) const override { | 
| + if (!BuildDefs::dump()) | 
| + return; | 
| + Ostream &Str = Func->getContext()->getStrDump(); | 
| + this->dumpDest(Func); | 
| + Str << " = " << Opcode << "." << this->getDest()->getType() << " "; | 
| + this->dumpSources(Func); | 
| + } | 
| + static bool classof(const Inst *Inst) { | 
| + return InstX86Base::isClassof(Inst, InstX86Base::K); | 
| + } | 
| -/// Base class for assignment instructions | 
| -template <class Machine, typename InstX86Base<Machine>::InstKindX86 K> | 
| -class InstX86BaseMovlike : public InstX86Base<Machine> { | 
| - InstX86BaseMovlike() = delete; | 
| - InstX86BaseMovlike(const InstX86BaseMovlike &) = delete; | 
| - InstX86BaseMovlike &operator=(const InstX86BaseMovlike &) = delete; | 
| - | 
| -public: | 
| - using Base = InstX86BaseMovlike<Machine, K>; | 
| - | 
| - bool isRedundantAssign() const override { | 
| - if (const auto *SrcVar = llvm::dyn_cast<const Variable>(this->getSrc(0))) { | 
| - if (SrcVar->hasReg() && this->Dest->hasReg()) { | 
| - // An assignment between physical registers is considered redundant if | 
| - // they have the same base register and the same encoding. E.g.: | 
| - // mov cl, ecx ==> redundant | 
| - // mov ch, ecx ==> not redundant due to different encodings | 
| - // mov ch, ebp ==> not redundant due to different base registers | 
| - // mov ecx, ecx ==> redundant, and dangerous in x86-64. i64 zexting | 
| - // is handled by Inst86Zext. | 
| - const int32_t SrcReg = SrcVar->getRegNum(); | 
| - const int32_t DestReg = this->Dest->getRegNum(); | 
| - return (InstX86Base<Machine>::Traits::getEncoding(SrcReg) == | 
| - InstX86Base<Machine>::Traits::getEncoding(DestReg)) && | 
| - (InstX86Base<Machine>::Traits::getBaseReg(SrcReg) == | 
| - InstX86Base<Machine>::Traits::getBaseReg(DestReg)); | 
| - } | 
| + protected: | 
| + InstX86BaseBinopXmmShift(Cfg *Func, Variable *Dest, Operand *Source) | 
| + : InstX86Base(Func, K, 2, Dest) { | 
| + this->addSource(Dest); | 
| + this->addSource(Source); | 
| } | 
| - return checkForRedundantAssign(this->getDest(), this->getSrc(0)); | 
| - } | 
| - bool isVarAssign() const override { | 
| - return llvm::isa<Variable>(this->getSrc(0)); | 
| - } | 
| - void dump(const Cfg *Func) const override { | 
| - if (!BuildDefs::dump()) | 
| - return; | 
| - Ostream &Str = Func->getContext()->getStrDump(); | 
| - Str << Opcode << "." << this->getDest()->getType() << " "; | 
| - this->dumpDest(Func); | 
| - Str << ", "; | 
| - this->dumpSources(Func); | 
| - } | 
| - static bool classof(const Inst *Inst) { | 
| - return InstX86Base<Machine>::isClassof(Inst, InstX86Base<Machine>::K); | 
| - } | 
| -protected: | 
| - InstX86BaseMovlike(Cfg *Func, Variable *Dest, Operand *Source) | 
| - : InstX86Base<Machine>(Func, K, 1, Dest) { | 
| - this->addSource(Source); | 
| - // For an integer assignment, make sure it's either a same-type assignment | 
| - // or a truncation. | 
| - assert(!isScalarIntegerType(Dest->getType()) || | 
| - (typeWidthInBytes(Dest->getType()) <= | 
| - typeWidthInBytes(Source->getType()))); | 
| - } | 
| + static const char *Opcode; | 
| + static const XmmEmitterShiftOp Emitter; | 
| + }; | 
| - static const char *Opcode; | 
| -}; | 
| + template <typename InstX86Base::InstKindX86 K> | 
| + class InstX86BaseTernop : public InstX86Base { | 
| + InstX86BaseTernop() = delete; | 
| + InstX86BaseTernop(const InstX86BaseTernop &) = delete; | 
| + InstX86BaseTernop &operator=(const InstX86BaseTernop &) = delete; | 
| + | 
| + public: | 
| + using Base = InstX86BaseTernop<K>; | 
| + | 
| + void emit(const Cfg *Func) const override { | 
| + if (!BuildDefs::dump()) | 
| + return; | 
| + Ostream &Str = Func->getContext()->getStrEmit(); | 
| + assert(this->getSrcSize() == 3); | 
| + Str << "\t" << Opcode << "\t"; | 
| + this->getSrc(2)->emit(Func); | 
| + Str << ", "; | 
| + this->getSrc(1)->emit(Func); | 
| + Str << ", "; | 
| + this->getDest()->emit(Func); | 
| + } | 
| + void dump(const Cfg *Func) const override { | 
| + if (!BuildDefs::dump()) | 
| + return; | 
| + Ostream &Str = Func->getContext()->getStrDump(); | 
| + this->dumpDest(Func); | 
| + Str << " = " << Opcode << "." << this->getDest()->getType() << " "; | 
| + this->dumpSources(Func); | 
| + } | 
| + static bool classof(const Inst *Inst) { | 
| + return InstX86Base::isClassof(Inst, InstX86Base::K); | 
| + } | 
| -template <class Machine> | 
| -class InstX86Bswap | 
| - : public InstX86BaseInplaceopGPR<Machine, InstX86Base<Machine>::Bswap> { | 
| -public: | 
| - static InstX86Bswap *create(Cfg *Func, Operand *SrcDest) { | 
| - return new (Func->allocate<InstX86Bswap>()) InstX86Bswap(Func, SrcDest); | 
| - } | 
| + protected: | 
| + InstX86BaseTernop(Cfg *Func, Variable *Dest, Operand *Source1, | 
| + Operand *Source2) | 
| + : InstX86Base(Func, K, 3, Dest) { | 
| + this->addSource(Dest); | 
| + this->addSource(Source1); | 
| + this->addSource(Source2); | 
| + } | 
| -private: | 
| - InstX86Bswap(Cfg *Func, Operand *SrcDest) | 
| - : InstX86BaseInplaceopGPR<Machine, InstX86Base<Machine>::Bswap>(Func, | 
| - SrcDest) { | 
| - } | 
| -}; | 
| + static const char *Opcode; | 
| + }; | 
| -template <class Machine> | 
| -class InstX86Neg | 
| - : public InstX86BaseInplaceopGPR<Machine, InstX86Base<Machine>::Neg> { | 
| -public: | 
| - static InstX86Neg *create(Cfg *Func, Operand *SrcDest) { | 
| - return new (Func->allocate<InstX86Neg>()) InstX86Neg(Func, SrcDest); | 
| - } | 
| + // Instructions of the form x := y op z | 
| + template <typename InstX86Base::InstKindX86 K> | 
| + class InstX86BaseThreeAddressop : public InstX86Base { | 
| + InstX86BaseThreeAddressop() = delete; | 
| + InstX86BaseThreeAddressop(const InstX86BaseThreeAddressop &) = delete; | 
| + InstX86BaseThreeAddressop & | 
| + operator=(const InstX86BaseThreeAddressop &) = delete; | 
| + | 
| + public: | 
| + using Base = InstX86BaseThreeAddressop<K>; | 
| + | 
| + void emit(const Cfg *Func) const override { | 
| + if (!BuildDefs::dump()) | 
| + return; | 
| + Ostream &Str = Func->getContext()->getStrEmit(); | 
| + assert(this->getSrcSize() == 2); | 
| + Str << "\t" << Opcode << "\t"; | 
| + this->getSrc(1)->emit(Func); | 
| + Str << ", "; | 
| + this->getSrc(0)->emit(Func); | 
| + Str << ", "; | 
| + this->getDest()->emit(Func); | 
| + } | 
| + void dump(const Cfg *Func) const override { | 
| + if (!BuildDefs::dump()) | 
| + return; | 
| + Ostream &Str = Func->getContext()->getStrDump(); | 
| + this->dumpDest(Func); | 
| + Str << " = " << Opcode << "." << this->getDest()->getType() << " "; | 
| + this->dumpSources(Func); | 
| + } | 
| + static bool classof(const Inst *Inst) { | 
| + return InstX86Base::isClassof(Inst, InstX86Base::K); | 
| + } | 
| -private: | 
| - InstX86Neg(Cfg *Func, Operand *SrcDest) | 
| - : InstX86BaseInplaceopGPR<Machine, InstX86Base<Machine>::Neg>(Func, | 
| - SrcDest) {} | 
| -}; | 
| + protected: | 
| + InstX86BaseThreeAddressop(Cfg *Func, Variable *Dest, Operand *Source0, | 
| + Operand *Source1) | 
| + : InstX86Base(Func, K, 2, Dest) { | 
| + this->addSource(Source0); | 
| + this->addSource(Source1); | 
| + } | 
| -template <class Machine> | 
| -class InstX86Bsf | 
| - : public InstX86BaseUnaryopGPR<Machine, InstX86Base<Machine>::Bsf> { | 
| -public: | 
| - static InstX86Bsf *create(Cfg *Func, Variable *Dest, Operand *Src) { | 
| - return new (Func->allocate<InstX86Bsf>()) InstX86Bsf(Func, Dest, Src); | 
| - } | 
| + static const char *Opcode; | 
| + }; | 
| -private: | 
| - InstX86Bsf(Cfg *Func, Variable *Dest, Operand *Src) | 
| - : InstX86BaseUnaryopGPR<Machine, InstX86Base<Machine>::Bsf>(Func, Dest, | 
| - Src) {} | 
| -}; | 
| + /// Base class for assignment instructions | 
| + template <typename InstX86Base::InstKindX86 K> | 
| + class InstX86BaseMovlike : public InstX86Base { | 
| + InstX86BaseMovlike() = delete; | 
| + InstX86BaseMovlike(const InstX86BaseMovlike &) = delete; | 
| + InstX86BaseMovlike &operator=(const InstX86BaseMovlike &) = delete; | 
| + | 
| + public: | 
| + using Base = InstX86BaseMovlike<K>; | 
| + | 
| + bool isRedundantAssign() const override { | 
| + if (const auto *SrcVar = | 
| + llvm::dyn_cast<const Variable>(this->getSrc(0))) { | 
| + if (SrcVar->hasReg() && this->Dest->hasReg()) { | 
| + // An assignment between physical registers is considered redundant if | 
| + // they have the same base register and the same encoding. E.g.: | 
| + // mov cl, ecx ==> redundant | 
| + // mov ch, ecx ==> not redundant due to different encodings | 
| + // mov ch, ebp ==> not redundant due to different base registers | 
| + // mov ecx, ecx ==> redundant, and dangerous in x86-64. i64 zexting | 
| + // is handled by Inst86Zext. | 
| + const int32_t SrcReg = SrcVar->getRegNum(); | 
| + const int32_t DestReg = this->Dest->getRegNum(); | 
| + return (Traits::getEncoding(SrcReg) == | 
| + Traits::getEncoding(DestReg)) && | 
| + (Traits::getBaseReg(SrcReg) == Traits::getBaseReg(DestReg)); | 
| + } | 
| + } | 
| + return checkForRedundantAssign(this->getDest(), this->getSrc(0)); | 
| + } | 
| + bool isVarAssign() const override { | 
| + return llvm::isa<Variable>(this->getSrc(0)); | 
| + } | 
| + void dump(const Cfg *Func) const override { | 
| + if (!BuildDefs::dump()) | 
| + return; | 
| + Ostream &Str = Func->getContext()->getStrDump(); | 
| + Str << Opcode << "." << this->getDest()->getType() << " "; | 
| + this->dumpDest(Func); | 
| + Str << ", "; | 
| + this->dumpSources(Func); | 
| + } | 
| + static bool classof(const Inst *Inst) { | 
| + return InstX86Base::isClassof(Inst, InstX86Base::K); | 
| + } | 
| -template <class Machine> | 
| -class InstX86Bsr | 
| - : public InstX86BaseUnaryopGPR<Machine, InstX86Base<Machine>::Bsr> { | 
| -public: | 
| - static InstX86Bsr *create(Cfg *Func, Variable *Dest, Operand *Src) { | 
| - return new (Func->allocate<InstX86Bsr>()) InstX86Bsr(Func, Dest, Src); | 
| - } | 
| + protected: | 
| + InstX86BaseMovlike(Cfg *Func, Variable *Dest, Operand *Source) | 
| + : InstX86Base(Func, K, 1, Dest) { | 
| + this->addSource(Source); | 
| + // For an integer assignment, make sure it's either a same-type assignment | 
| + // or a truncation. | 
| + assert(!isScalarIntegerType(Dest->getType()) || | 
| + (typeWidthInBytes(Dest->getType()) <= | 
| + typeWidthInBytes(Source->getType()))); | 
| + } | 
| -private: | 
| - InstX86Bsr(Cfg *Func, Variable *Dest, Operand *Src) | 
| - : InstX86BaseUnaryopGPR<Machine, InstX86Base<Machine>::Bsr>(Func, Dest, | 
| - Src) {} | 
| -}; | 
| + static const char *Opcode; | 
| + }; | 
| -template <class Machine> | 
| -class InstX86Lea | 
| - : public InstX86BaseUnaryopGPR<Machine, InstX86Base<Machine>::Lea> { | 
| -public: | 
| - static InstX86Lea *create(Cfg *Func, Variable *Dest, Operand *Src) { | 
| - return new (Func->allocate<InstX86Lea>()) InstX86Lea(Func, Dest, Src); | 
| - } | 
| + class InstX86Bswap : public InstX86BaseInplaceopGPR<InstX86Base::Bswap> { | 
| + public: | 
| + static InstX86Bswap *create(Cfg *Func, Operand *SrcDest) { | 
| + return new (Func->allocate<InstX86Bswap>()) InstX86Bswap(Func, SrcDest); | 
| + } | 
| - void emit(const Cfg *Func) const override; | 
| + private: | 
| + InstX86Bswap(Cfg *Func, Operand *SrcDest) | 
| + : InstX86BaseInplaceopGPR<InstX86Base::Bswap>(Func, SrcDest) {} | 
| + }; | 
| -private: | 
| - InstX86Lea(Cfg *Func, Variable *Dest, Operand *Src) | 
| - : InstX86BaseUnaryopGPR<Machine, InstX86Base<Machine>::Lea>(Func, Dest, | 
| - Src) {} | 
| -}; | 
| + class InstX86Neg : public InstX86BaseInplaceopGPR<InstX86Base::Neg> { | 
| + public: | 
| + static InstX86Neg *create(Cfg *Func, Operand *SrcDest) { | 
| + return new (Func->allocate<InstX86Neg>()) InstX86Neg(Func, SrcDest); | 
| + } | 
| -// Cbwdq instruction - wrapper for cbw, cwd, and cdq | 
| -template <class Machine> | 
| -class InstX86Cbwdq | 
| - : public InstX86BaseUnaryopGPR<Machine, InstX86Base<Machine>::Cbwdq> { | 
| -public: | 
| - static InstX86Cbwdq *create(Cfg *Func, Variable *Dest, Operand *Src) { | 
| - return new (Func->allocate<InstX86Cbwdq>()) InstX86Cbwdq(Func, Dest, Src); | 
| - } | 
| + private: | 
| + InstX86Neg(Cfg *Func, Operand *SrcDest) | 
| + : InstX86BaseInplaceopGPR<InstX86Base::Neg>(Func, SrcDest) {} | 
| + }; | 
| - void emit(const Cfg *Func) const override; | 
| - void emitIAS(const Cfg *Func) const override; | 
| + class InstX86Bsf : public InstX86BaseUnaryopGPR<InstX86Base::Bsf> { | 
| + public: | 
| + static InstX86Bsf *create(Cfg *Func, Variable *Dest, Operand *Src) { | 
| + return new (Func->allocate<InstX86Bsf>()) InstX86Bsf(Func, Dest, Src); | 
| + } | 
| -private: | 
| - InstX86Cbwdq(Cfg *Func, Variable *Dest, Operand *Src) | 
| - : InstX86BaseUnaryopGPR<Machine, InstX86Base<Machine>::Cbwdq>(Func, Dest, | 
| - Src) {} | 
| -}; | 
| + private: | 
| + InstX86Bsf(Cfg *Func, Variable *Dest, Operand *Src) | 
| + : InstX86BaseUnaryopGPR<InstX86Base::Bsf>(Func, Dest, Src) {} | 
| + }; | 
| -template <class Machine> | 
| -class InstX86Movsx | 
| - : public InstX86BaseUnaryopGPR<Machine, InstX86Base<Machine>::Movsx> { | 
| -public: | 
| - static InstX86Movsx *create(Cfg *Func, Variable *Dest, Operand *Src) { | 
| - assert(typeWidthInBytes(Dest->getType()) > | 
| - typeWidthInBytes(Src->getType())); | 
| - return new (Func->allocate<InstX86Movsx>()) InstX86Movsx(Func, Dest, Src); | 
| - } | 
| + class InstX86Bsr : public InstX86BaseUnaryopGPR<InstX86Base::Bsr> { | 
| + public: | 
| + static InstX86Bsr *create(Cfg *Func, Variable *Dest, Operand *Src) { | 
| + return new (Func->allocate<InstX86Bsr>()) InstX86Bsr(Func, Dest, Src); | 
| + } | 
| - void emitIAS(const Cfg *Func) const override; | 
| + private: | 
| + InstX86Bsr(Cfg *Func, Variable *Dest, Operand *Src) | 
| + : InstX86BaseUnaryopGPR<InstX86Base::Bsr>(Func, Dest, Src) {} | 
| + }; | 
| -private: | 
| - InstX86Movsx(Cfg *Func, Variable *Dest, Operand *Src) | 
| - : InstX86BaseUnaryopGPR<Machine, InstX86Base<Machine>::Movsx>(Func, Dest, | 
| - Src) {} | 
| -}; | 
| + class InstX86Lea : public InstX86BaseUnaryopGPR<InstX86Base::Lea> { | 
| + public: | 
| + static InstX86Lea *create(Cfg *Func, Variable *Dest, Operand *Src) { | 
| + return new (Func->allocate<InstX86Lea>()) InstX86Lea(Func, Dest, Src); | 
| + } | 
| -template <class Machine> | 
| -class InstX86Movzx | 
| - : public InstX86BaseUnaryopGPR<Machine, InstX86Base<Machine>::Movzx> { | 
| -public: | 
| - static InstX86Movzx *create(Cfg *Func, Variable *Dest, Operand *Src) { | 
| - assert(typeWidthInBytes(Dest->getType()) > | 
| - typeWidthInBytes(Src->getType())); | 
| - return new (Func->allocate<InstX86Movzx>()) InstX86Movzx(Func, Dest, Src); | 
| - } | 
| + void emit(const Cfg *Func) const override; | 
| - void emit(const Cfg *Func) const override; | 
| + private: | 
| + InstX86Lea(Cfg *Func, Variable *Dest, Operand *Src) | 
| + : InstX86BaseUnaryopGPR<InstX86Base::Lea>(Func, Dest, Src) {} | 
| + }; | 
| - void emitIAS(const Cfg *Func) const override; | 
| + // Cbwdq instruction - wrapper for cbw, cwd, and cdq | 
| + class InstX86Cbwdq : public InstX86BaseUnaryopGPR<InstX86Base::Cbwdq> { | 
| + public: | 
| + static InstX86Cbwdq *create(Cfg *Func, Variable *Dest, Operand *Src) { | 
| + return new (Func->allocate<InstX86Cbwdq>()) InstX86Cbwdq(Func, Dest, Src); | 
| + } | 
| -private: | 
| - InstX86Movzx(Cfg *Func, Variable *Dest, Operand *Src) | 
| - : InstX86BaseUnaryopGPR<Machine, InstX86Base<Machine>::Movzx>(Func, Dest, | 
| - Src) {} | 
| -}; | 
| + void emit(const Cfg *Func) const override; | 
| + void emitIAS(const Cfg *Func) const override; | 
| -template <class Machine> | 
| -class InstX86Movd | 
| - : public InstX86BaseUnaryopXmm<Machine, InstX86Base<Machine>::Movd> { | 
| -public: | 
| - static InstX86Movd *create(Cfg *Func, Variable *Dest, Operand *Src) { | 
| - return new (Func->allocate<InstX86Movd>()) InstX86Movd(Func, Dest, Src); | 
| - } | 
| + private: | 
| + InstX86Cbwdq(Cfg *Func, Variable *Dest, Operand *Src) | 
| + : InstX86BaseUnaryopGPR<InstX86Base::Cbwdq>(Func, Dest, Src) {} | 
| + }; | 
| - void emit(const Cfg *Func) const override; | 
| + class InstX86Movsx : public InstX86BaseUnaryopGPR<InstX86Base::Movsx> { | 
| + public: | 
| + static InstX86Movsx *create(Cfg *Func, Variable *Dest, Operand *Src) { | 
| + assert(typeWidthInBytes(Dest->getType()) > | 
| + typeWidthInBytes(Src->getType())); | 
| + return new (Func->allocate<InstX86Movsx>()) InstX86Movsx(Func, Dest, Src); | 
| + } | 
| - void emitIAS(const Cfg *Func) const override; | 
| + void emitIAS(const Cfg *Func) const override; | 
| -private: | 
| - InstX86Movd(Cfg *Func, Variable *Dest, Operand *Src) | 
| - : InstX86BaseUnaryopXmm<Machine, InstX86Base<Machine>::Movd>(Func, Dest, | 
| - Src) {} | 
| -}; | 
| + private: | 
| + InstX86Movsx(Cfg *Func, Variable *Dest, Operand *Src) | 
| + : InstX86BaseUnaryopGPR<InstX86Base::Movsx>(Func, Dest, Src) {} | 
| + }; | 
| -template <class Machine> | 
| -class InstX86Sqrtss | 
| - : public InstX86BaseUnaryopXmm<Machine, InstX86Base<Machine>::Sqrtss> { | 
| -public: | 
| - static InstX86Sqrtss *create(Cfg *Func, Variable *Dest, Operand *Src) { | 
| - return new (Func->allocate<InstX86Sqrtss>()) InstX86Sqrtss(Func, Dest, Src); | 
| - } | 
| + class InstX86Movzx : public InstX86BaseUnaryopGPR<InstX86Base::Movzx> { | 
| + public: | 
| + static InstX86Movzx *create(Cfg *Func, Variable *Dest, Operand *Src) { | 
| + assert(typeWidthInBytes(Dest->getType()) > | 
| + typeWidthInBytes(Src->getType())); | 
| + return new (Func->allocate<InstX86Movzx>()) InstX86Movzx(Func, Dest, Src); | 
| + } | 
| - virtual void emit(const Cfg *Func) const override; | 
| + void emit(const Cfg *Func) const override; | 
| -private: | 
| - InstX86Sqrtss(Cfg *Func, Variable *Dest, Operand *Src) | 
| - : InstX86BaseUnaryopXmm<Machine, InstX86Base<Machine>::Sqrtss>(Func, Dest, | 
| - Src) {} | 
| -}; | 
| + void emitIAS(const Cfg *Func) const override; | 
| -/// Move/assignment instruction - wrapper for mov/movss/movsd. | 
| -template <class Machine> | 
| -class InstX86Mov | 
| - : public InstX86BaseMovlike<Machine, InstX86Base<Machine>::Mov> { | 
| -public: | 
| - static InstX86Mov *create(Cfg *Func, Variable *Dest, Operand *Source) { | 
| - assert(!isScalarIntegerType(Dest->getType()) || | 
| - (typeWidthInBytes(Dest->getType()) <= | 
| - typeWidthInBytes(Source->getType()))); | 
| - return new (Func->allocate<InstX86Mov>()) InstX86Mov(Func, Dest, Source); | 
| - } | 
| + private: | 
| + InstX86Movzx(Cfg *Func, Variable *Dest, Operand *Src) | 
| + : InstX86BaseUnaryopGPR<InstX86Base::Movzx>(Func, Dest, Src) {} | 
| + }; | 
| - void emit(const Cfg *Func) const override; | 
| - void emitIAS(const Cfg *Func) const override; | 
| + class InstX86Movd : public InstX86BaseUnaryopXmm<InstX86Base::Movd> { | 
| + public: | 
| + static InstX86Movd *create(Cfg *Func, Variable *Dest, Operand *Src) { | 
| + return new (Func->allocate<InstX86Movd>()) InstX86Movd(Func, Dest, Src); | 
| + } | 
| -private: | 
| - InstX86Mov(Cfg *Func, Variable *Dest, Operand *Source) | 
| - : InstX86BaseMovlike<Machine, InstX86Base<Machine>::Mov>(Func, Dest, | 
| - Source) {} | 
| -}; | 
| + void emit(const Cfg *Func) const override; | 
| -/// Move packed - copy 128 bit values between XMM registers, or mem128 and XMM | 
| -/// registers. | 
| -template <class Machine> | 
| -class InstX86Movp | 
| - : public InstX86BaseMovlike<Machine, InstX86Base<Machine>::Movp> { | 
| -public: | 
| - static InstX86Movp *create(Cfg *Func, Variable *Dest, Operand *Source) { | 
| - return new (Func->allocate<InstX86Movp>()) InstX86Movp(Func, Dest, Source); | 
| - } | 
| + void emitIAS(const Cfg *Func) const override; | 
| - void emit(const Cfg *Func) const override; | 
| - void emitIAS(const Cfg *Func) const override; | 
| + private: | 
| + InstX86Movd(Cfg *Func, Variable *Dest, Operand *Src) | 
| + : InstX86BaseUnaryopXmm<InstX86Base::Movd>(Func, Dest, Src) {} | 
| + }; | 
| -private: | 
| - InstX86Movp(Cfg *Func, Variable *Dest, Operand *Source) | 
| - : InstX86BaseMovlike<Machine, InstX86Base<Machine>::Movp>(Func, Dest, | 
| - Source) {} | 
| -}; | 
| + class InstX86Sqrtss : public InstX86BaseUnaryopXmm<InstX86Base::Sqrtss> { | 
| + public: | 
| + static InstX86Sqrtss *create(Cfg *Func, Variable *Dest, Operand *Src) { | 
| + return new (Func->allocate<InstX86Sqrtss>()) | 
| + InstX86Sqrtss(Func, Dest, Src); | 
| + } | 
| -/// Movq - copy between XMM registers, or mem64 and XMM registers. | 
| -template <class Machine> | 
| -class InstX86Movq | 
| - : public InstX86BaseMovlike<Machine, InstX86Base<Machine>::Movq> { | 
| -public: | 
| - static InstX86Movq *create(Cfg *Func, Variable *Dest, Operand *Source) { | 
| - return new (Func->allocate<InstX86Movq>()) InstX86Movq(Func, Dest, Source); | 
| - } | 
| + virtual void emit(const Cfg *Func) const override; | 
| - void emit(const Cfg *Func) const override; | 
| - void emitIAS(const Cfg *Func) const override; | 
| + private: | 
| + InstX86Sqrtss(Cfg *Func, Variable *Dest, Operand *Src) | 
| + : InstX86BaseUnaryopXmm<InstX86Base::Sqrtss>(Func, Dest, Src) {} | 
| + }; | 
| -private: | 
| - InstX86Movq(Cfg *Func, Variable *Dest, Operand *Source) | 
| - : InstX86BaseMovlike<Machine, InstX86Base<Machine>::Movq>(Func, Dest, | 
| - Source) {} | 
| -}; | 
| + /// Move/assignment instruction - wrapper for mov/movss/movsd. | 
| + class InstX86Mov : public InstX86BaseMovlike<InstX86Base::Mov> { | 
| + public: | 
| + static InstX86Mov *create(Cfg *Func, Variable *Dest, Operand *Source) { | 
| + assert(!isScalarIntegerType(Dest->getType()) || | 
| + (typeWidthInBytes(Dest->getType()) <= | 
| + typeWidthInBytes(Source->getType()))); | 
| + return new (Func->allocate<InstX86Mov>()) InstX86Mov(Func, Dest, Source); | 
| + } | 
| -template <class Machine> | 
| -class InstX86Add | 
| - : public InstX86BaseBinopGPR<Machine, InstX86Base<Machine>::Add> { | 
| -public: | 
| - static InstX86Add *create(Cfg *Func, Variable *Dest, Operand *Source) { | 
| - return new (Func->allocate<InstX86Add>()) InstX86Add(Func, Dest, Source); | 
| - } | 
| + void emit(const Cfg *Func) const override; | 
| + void emitIAS(const Cfg *Func) const override; | 
| -private: | 
| - InstX86Add(Cfg *Func, Variable *Dest, Operand *Source) | 
| - : InstX86BaseBinopGPR<Machine, InstX86Base<Machine>::Add>(Func, Dest, | 
| - Source) {} | 
| -}; | 
| + private: | 
| + InstX86Mov(Cfg *Func, Variable *Dest, Operand *Source) | 
| + : InstX86BaseMovlike<InstX86Base::Mov>(Func, Dest, Source) {} | 
| + }; | 
| -template <class Machine> | 
| -class InstX86AddRMW | 
| - : public InstX86BaseBinopRMW<Machine, InstX86Base<Machine>::AddRMW> { | 
| -public: | 
| - static InstX86AddRMW * | 
| - create(Cfg *Func, | 
| - typename InstX86Base<Machine>::Traits::X86OperandMem *DestSrc0, | 
| - Operand *Src1) { | 
| - return new (Func->allocate<InstX86AddRMW>()) | 
| - InstX86AddRMW(Func, DestSrc0, Src1); | 
| - } | 
| + /// Move packed - copy 128 bit values between XMM registers, or mem128 and XMM | 
| + /// registers. | 
| + class InstX86Movp : public InstX86BaseMovlike<InstX86Base::Movp> { | 
| + public: | 
| + static InstX86Movp *create(Cfg *Func, Variable *Dest, Operand *Source) { | 
| + return new (Func->allocate<InstX86Movp>()) | 
| + InstX86Movp(Func, Dest, Source); | 
| + } | 
| -private: | 
| - InstX86AddRMW(Cfg *Func, | 
| - typename InstX86Base<Machine>::Traits::X86OperandMem *DestSrc0, | 
| - Operand *Src1) | 
| - : InstX86BaseBinopRMW<Machine, InstX86Base<Machine>::AddRMW>( | 
| - Func, DestSrc0, Src1) {} | 
| -}; | 
| + void emit(const Cfg *Func) const override; | 
| + void emitIAS(const Cfg *Func) const override; | 
| -template <class Machine> | 
| -class InstX86Addps | 
| - : public InstX86BaseBinopXmm<Machine, InstX86Base<Machine>::Addps, true, | 
| - InstX86Base<Machine>::SseSuffix::Packed> { | 
| -public: | 
| - static InstX86Addps *create(Cfg *Func, Variable *Dest, Operand *Source) { | 
| - return new (Func->allocate<InstX86Addps>()) | 
| - InstX86Addps(Func, Dest, Source); | 
| - } | 
| + private: | 
| + InstX86Movp(Cfg *Func, Variable *Dest, Operand *Source) | 
| + : InstX86BaseMovlike<InstX86Base::Movp>(Func, Dest, Source) {} | 
| + }; | 
| -private: | 
| - InstX86Addps(Cfg *Func, Variable *Dest, Operand *Source) | 
| - : InstX86BaseBinopXmm<Machine, InstX86Base<Machine>::Addps, true, | 
| - InstX86Base<Machine>::SseSuffix::Packed>(Func, Dest, | 
| - Source) {} | 
| -}; | 
| + /// Movq - copy between XMM registers, or mem64 and XMM registers. | 
| + class InstX86Movq : public InstX86BaseMovlike<InstX86Base::Movq> { | 
| + public: | 
| + static InstX86Movq *create(Cfg *Func, Variable *Dest, Operand *Source) { | 
| + return new (Func->allocate<InstX86Movq>()) | 
| + InstX86Movq(Func, Dest, Source); | 
| + } | 
| -template <class Machine> | 
| -class InstX86Adc | 
| - : public InstX86BaseBinopGPR<Machine, InstX86Base<Machine>::Adc> { | 
| -public: | 
| - static InstX86Adc *create(Cfg *Func, Variable *Dest, Operand *Source) { | 
| - return new (Func->allocate<InstX86Adc>()) InstX86Adc(Func, Dest, Source); | 
| - } | 
| + void emit(const Cfg *Func) const override; | 
| + void emitIAS(const Cfg *Func) const override; | 
| -private: | 
| - InstX86Adc(Cfg *Func, Variable *Dest, Operand *Source) | 
| - : InstX86BaseBinopGPR<Machine, InstX86Base<Machine>::Adc>(Func, Dest, | 
| - Source) {} | 
| -}; | 
| + private: | 
| + InstX86Movq(Cfg *Func, Variable *Dest, Operand *Source) | 
| + : InstX86BaseMovlike<InstX86Base::Movq>(Func, Dest, Source) {} | 
| + }; | 
| -template <class Machine> | 
| -class InstX86AdcRMW | 
| - : public InstX86BaseBinopRMW<Machine, InstX86Base<Machine>::AdcRMW> { | 
| -public: | 
| - static InstX86AdcRMW * | 
| - create(Cfg *Func, | 
| - typename InstX86Base<Machine>::Traits::X86OperandMem *DestSrc0, | 
| - Operand *Src1) { | 
| - return new (Func->allocate<InstX86AdcRMW>()) | 
| - InstX86AdcRMW(Func, DestSrc0, Src1); | 
| - } | 
| + class InstX86Add : public InstX86BaseBinopGPR<InstX86Base::Add> { | 
| + public: | 
| + static InstX86Add *create(Cfg *Func, Variable *Dest, Operand *Source) { | 
| + return new (Func->allocate<InstX86Add>()) InstX86Add(Func, Dest, Source); | 
| + } | 
| -private: | 
| - InstX86AdcRMW(Cfg *Func, | 
| - typename InstX86Base<Machine>::Traits::X86OperandMem *DestSrc0, | 
| - Operand *Src1) | 
| - : InstX86BaseBinopRMW<Machine, InstX86Base<Machine>::AdcRMW>( | 
| - Func, DestSrc0, Src1) {} | 
| -}; | 
| + private: | 
| + InstX86Add(Cfg *Func, Variable *Dest, Operand *Source) | 
| + : InstX86BaseBinopGPR<InstX86Base::Add>(Func, Dest, Source) {} | 
| + }; | 
| -template <class Machine> | 
| -class InstX86Addss | 
| - : public InstX86BaseBinopXmm<Machine, InstX86Base<Machine>::Addss, false, | 
| - InstX86Base<Machine>::SseSuffix::Scalar> { | 
| -public: | 
| - static InstX86Addss *create(Cfg *Func, Variable *Dest, Operand *Source) { | 
| - return new (Func->allocate<InstX86Addss>()) | 
| - InstX86Addss(Func, Dest, Source); | 
| - } | 
| + class InstX86AddRMW : public InstX86BaseBinopRMW<InstX86Base::AddRMW> { | 
| + public: | 
| + static InstX86AddRMW *create(Cfg *Func, X86OperandMem *DestSrc0, | 
| + Operand *Src1) { | 
| + return new (Func->allocate<InstX86AddRMW>()) | 
| + InstX86AddRMW(Func, DestSrc0, Src1); | 
| + } | 
| -private: | 
| - InstX86Addss(Cfg *Func, Variable *Dest, Operand *Source) | 
| - : InstX86BaseBinopXmm<Machine, InstX86Base<Machine>::Addss, false, | 
| - InstX86Base<Machine>::SseSuffix::Scalar>(Func, Dest, | 
| - Source) {} | 
| -}; | 
| + private: | 
| + InstX86AddRMW(Cfg *Func, X86OperandMem *DestSrc0, Operand *Src1) | 
| + : InstX86BaseBinopRMW<InstX86Base::AddRMW>(Func, DestSrc0, Src1) {} | 
| + }; | 
| -template <class Machine> | 
| -class InstX86Padd | 
| - : public InstX86BaseBinopXmm<Machine, InstX86Base<Machine>::Padd, true, | 
| - InstX86Base<Machine>::SseSuffix::Integral> { | 
| -public: | 
| - static InstX86Padd *create(Cfg *Func, Variable *Dest, Operand *Source) { | 
| - return new (Func->allocate<InstX86Padd>()) InstX86Padd(Func, Dest, Source); | 
| - } | 
| + class InstX86Addps | 
| + : public InstX86BaseBinopXmm<InstX86Base::Addps, true, | 
| + InstX86Base::SseSuffix::Packed> { | 
| + public: | 
| + static InstX86Addps *create(Cfg *Func, Variable *Dest, Operand *Source) { | 
| + return new (Func->allocate<InstX86Addps>()) | 
| + InstX86Addps(Func, Dest, Source); | 
| + } | 
| -private: | 
| - InstX86Padd(Cfg *Func, Variable *Dest, Operand *Source) | 
| - : InstX86BaseBinopXmm<Machine, InstX86Base<Machine>::Padd, true, | 
| - InstX86Base<Machine>::SseSuffix::Integral>( | 
| - Func, Dest, Source) {} | 
| -}; | 
| + private: | 
| + InstX86Addps(Cfg *Func, Variable *Dest, Operand *Source) | 
| + : InstX86BaseBinopXmm<InstX86Base::Addps, true, | 
| + InstX86Base::SseSuffix::Packed>(Func, Dest, | 
| + Source) {} | 
| + }; | 
| -template <class Machine> | 
| -class InstX86Sub | 
| - : public InstX86BaseBinopGPR<Machine, InstX86Base<Machine>::Sub> { | 
| -public: | 
| - static InstX86Sub *create(Cfg *Func, Variable *Dest, Operand *Source) { | 
| - return new (Func->allocate<InstX86Sub>()) InstX86Sub(Func, Dest, Source); | 
| - } | 
| + class InstX86Adc : public InstX86BaseBinopGPR<InstX86Base::Adc> { | 
| + public: | 
| + static InstX86Adc *create(Cfg *Func, Variable *Dest, Operand *Source) { | 
| + return new (Func->allocate<InstX86Adc>()) InstX86Adc(Func, Dest, Source); | 
| + } | 
| -private: | 
| - InstX86Sub(Cfg *Func, Variable *Dest, Operand *Source) | 
| - : InstX86BaseBinopGPR<Machine, InstX86Base<Machine>::Sub>(Func, Dest, | 
| - Source) {} | 
| -}; | 
| + private: | 
| + InstX86Adc(Cfg *Func, Variable *Dest, Operand *Source) | 
| + : InstX86BaseBinopGPR<InstX86Base::Adc>(Func, Dest, Source) {} | 
| + }; | 
| -template <class Machine> | 
| -class InstX86SubRMW | 
| - : public InstX86BaseBinopRMW<Machine, InstX86Base<Machine>::SubRMW> { | 
| -public: | 
| - static InstX86SubRMW * | 
| - create(Cfg *Func, | 
| - typename InstX86Base<Machine>::Traits::X86OperandMem *DestSrc0, | 
| - Operand *Src1) { | 
| - return new (Func->allocate<InstX86SubRMW>()) | 
| - InstX86SubRMW(Func, DestSrc0, Src1); | 
| - } | 
| + class InstX86AdcRMW : public InstX86BaseBinopRMW<InstX86Base::AdcRMW> { | 
| + public: | 
| + static InstX86AdcRMW *create(Cfg *Func, X86OperandMem *DestSrc0, | 
| + Operand *Src1) { | 
| + return new (Func->allocate<InstX86AdcRMW>()) | 
| + InstX86AdcRMW(Func, DestSrc0, Src1); | 
| + } | 
| -private: | 
| - InstX86SubRMW(Cfg *Func, | 
| - typename InstX86Base<Machine>::Traits::X86OperandMem *DestSrc0, | 
| - Operand *Src1) | 
| - : InstX86BaseBinopRMW<Machine, InstX86Base<Machine>::SubRMW>( | 
| - Func, DestSrc0, Src1) {} | 
| -}; | 
| + private: | 
| + InstX86AdcRMW(Cfg *Func, X86OperandMem *DestSrc0, Operand *Src1) | 
| + : InstX86BaseBinopRMW<InstX86Base::AdcRMW>(Func, DestSrc0, Src1) {} | 
| + }; | 
| -template <class Machine> | 
| -class InstX86Subps | 
| - : public InstX86BaseBinopXmm<Machine, InstX86Base<Machine>::Subps, true, | 
| - InstX86Base<Machine>::SseSuffix::Packed> { | 
| -public: | 
| - static InstX86Subps *create(Cfg *Func, Variable *Dest, Operand *Source) { | 
| - return new (Func->allocate<InstX86Subps>()) | 
| - InstX86Subps(Func, Dest, Source); | 
| - } | 
| + class InstX86Addss | 
| + : public InstX86BaseBinopXmm<InstX86Base::Addss, false, | 
| + InstX86Base::SseSuffix::Scalar> { | 
| + public: | 
| + static InstX86Addss *create(Cfg *Func, Variable *Dest, Operand *Source) { | 
| + return new (Func->allocate<InstX86Addss>()) | 
| + InstX86Addss(Func, Dest, Source); | 
| + } | 
| -private: | 
| - InstX86Subps(Cfg *Func, Variable *Dest, Operand *Source) | 
| - : InstX86BaseBinopXmm<Machine, InstX86Base<Machine>::Subps, true, | 
| - InstX86Base<Machine>::SseSuffix::Packed>(Func, Dest, | 
| - Source) {} | 
| -}; | 
| + private: | 
| + InstX86Addss(Cfg *Func, Variable *Dest, Operand *Source) | 
| + : InstX86BaseBinopXmm<InstX86Base::Addss, false, | 
| + InstX86Base::SseSuffix::Scalar>(Func, Dest, | 
| + Source) {} | 
| + }; | 
| -template <class Machine> | 
| -class InstX86Subss | 
| - : public InstX86BaseBinopXmm<Machine, InstX86Base<Machine>::Subss, false, | 
| - InstX86Base<Machine>::SseSuffix::Scalar> { | 
| -public: | 
| - static InstX86Subss *create(Cfg *Func, Variable *Dest, Operand *Source) { | 
| - return new (Func->allocate<InstX86Subss>()) | 
| - InstX86Subss(Func, Dest, Source); | 
| - } | 
| + class InstX86Padd | 
| + : public InstX86BaseBinopXmm<InstX86Base::Padd, true, | 
| + InstX86Base::SseSuffix::Integral> { | 
| + public: | 
| + static InstX86Padd *create(Cfg *Func, Variable *Dest, Operand *Source) { | 
| + return new (Func->allocate<InstX86Padd>()) | 
| + InstX86Padd(Func, Dest, Source); | 
| + } | 
| -private: | 
| - InstX86Subss(Cfg *Func, Variable *Dest, Operand *Source) | 
| - : InstX86BaseBinopXmm<Machine, InstX86Base<Machine>::Subss, false, | 
| - InstX86Base<Machine>::SseSuffix::Scalar>(Func, Dest, | 
| - Source) {} | 
| -}; | 
| + private: | 
| + InstX86Padd(Cfg *Func, Variable *Dest, Operand *Source) | 
| + : InstX86BaseBinopXmm<InstX86Base::Padd, true, | 
| + InstX86Base::SseSuffix::Integral>(Func, Dest, | 
| + Source) {} | 
| + }; | 
| -template <class Machine> | 
| -class InstX86Sbb | 
| - : public InstX86BaseBinopGPR<Machine, InstX86Base<Machine>::Sbb> { | 
| -public: | 
| - static InstX86Sbb *create(Cfg *Func, Variable *Dest, Operand *Source) { | 
| - return new (Func->allocate<InstX86Sbb>()) InstX86Sbb(Func, Dest, Source); | 
| - } | 
| + class InstX86Sub : public InstX86BaseBinopGPR<InstX86Base::Sub> { | 
| + public: | 
| + static InstX86Sub *create(Cfg *Func, Variable *Dest, Operand *Source) { | 
| + return new (Func->allocate<InstX86Sub>()) InstX86Sub(Func, Dest, Source); | 
| + } | 
| -private: | 
| - InstX86Sbb(Cfg *Func, Variable *Dest, Operand *Source) | 
| - : InstX86BaseBinopGPR<Machine, InstX86Base<Machine>::Sbb>(Func, Dest, | 
| - Source) {} | 
| -}; | 
| + private: | 
| + InstX86Sub(Cfg *Func, Variable *Dest, Operand *Source) | 
| + : InstX86BaseBinopGPR<InstX86Base::Sub>(Func, Dest, Source) {} | 
| + }; | 
| -template <class Machine> | 
| -class InstX86SbbRMW | 
| - : public InstX86BaseBinopRMW<Machine, InstX86Base<Machine>::SbbRMW> { | 
| -public: | 
| - static InstX86SbbRMW * | 
| - create(Cfg *Func, | 
| - typename InstX86Base<Machine>::Traits::X86OperandMem *DestSrc0, | 
| - Operand *Src1) { | 
| - return new (Func->allocate<InstX86SbbRMW>()) | 
| - InstX86SbbRMW(Func, DestSrc0, Src1); | 
| - } | 
| + class InstX86SubRMW : public InstX86BaseBinopRMW<InstX86Base::SubRMW> { | 
| + public: | 
| + static InstX86SubRMW *create(Cfg *Func, X86OperandMem *DestSrc0, | 
| + Operand *Src1) { | 
| + return new (Func->allocate<InstX86SubRMW>()) | 
| + InstX86SubRMW(Func, DestSrc0, Src1); | 
| + } | 
| -private: | 
| - InstX86SbbRMW(Cfg *Func, | 
| - typename InstX86Base<Machine>::Traits::X86OperandMem *DestSrc0, | 
| - Operand *Src1) | 
| - : InstX86BaseBinopRMW<Machine, InstX86Base<Machine>::SbbRMW>( | 
| - Func, DestSrc0, Src1) {} | 
| -}; | 
| + private: | 
| + InstX86SubRMW(Cfg *Func, X86OperandMem *DestSrc0, Operand *Src1) | 
| + : InstX86BaseBinopRMW<InstX86Base::SubRMW>(Func, DestSrc0, Src1) {} | 
| + }; | 
| -template <class Machine> | 
| -class InstX86Psub | 
| - : public InstX86BaseBinopXmm<Machine, InstX86Base<Machine>::Psub, true, | 
| - InstX86Base<Machine>::SseSuffix::Integral> { | 
| -public: | 
| - static InstX86Psub *create(Cfg *Func, Variable *Dest, Operand *Source) { | 
| - return new (Func->allocate<InstX86Psub>()) InstX86Psub(Func, Dest, Source); | 
| - } | 
| + class InstX86Subps | 
| + : public InstX86BaseBinopXmm<InstX86Base::Subps, true, | 
| + InstX86Base::SseSuffix::Packed> { | 
| + public: | 
| + static InstX86Subps *create(Cfg *Func, Variable *Dest, Operand *Source) { | 
| + return new (Func->allocate<InstX86Subps>()) | 
| + InstX86Subps(Func, Dest, Source); | 
| + } | 
| -private: | 
| - InstX86Psub(Cfg *Func, Variable *Dest, Operand *Source) | 
| - : InstX86BaseBinopXmm<Machine, InstX86Base<Machine>::Psub, true, | 
| - InstX86Base<Machine>::SseSuffix::Integral>( | 
| - Func, Dest, Source) {} | 
| -}; | 
| + private: | 
| + InstX86Subps(Cfg *Func, Variable *Dest, Operand *Source) | 
| + : InstX86BaseBinopXmm<InstX86Base::Subps, true, | 
| + InstX86Base::SseSuffix::Packed>(Func, Dest, | 
| + Source) {} | 
| + }; | 
| -template <class Machine> | 
| -class InstX86And | 
| - : public InstX86BaseBinopGPR<Machine, InstX86Base<Machine>::And> { | 
| -public: | 
| - static InstX86And *create(Cfg *Func, Variable *Dest, Operand *Source) { | 
| - return new (Func->allocate<InstX86And>()) InstX86And(Func, Dest, Source); | 
| - } | 
| + class InstX86Subss | 
| + : public InstX86BaseBinopXmm<InstX86Base::Subss, false, | 
| + InstX86Base::SseSuffix::Scalar> { | 
| + public: | 
| + static InstX86Subss *create(Cfg *Func, Variable *Dest, Operand *Source) { | 
| + return new (Func->allocate<InstX86Subss>()) | 
| + InstX86Subss(Func, Dest, Source); | 
| + } | 
| -private: | 
| - InstX86And(Cfg *Func, Variable *Dest, Operand *Source) | 
| - : InstX86BaseBinopGPR<Machine, InstX86Base<Machine>::And>(Func, Dest, | 
| - Source) {} | 
| -}; | 
| + private: | 
| + InstX86Subss(Cfg *Func, Variable *Dest, Operand *Source) | 
| + : InstX86BaseBinopXmm<InstX86Base::Subss, false, | 
| + InstX86Base::SseSuffix::Scalar>(Func, Dest, | 
| + Source) {} | 
| + }; | 
| -template <class Machine> | 
| -class InstX86Andnps | 
| - : public InstX86BaseBinopXmm<Machine, InstX86Base<Machine>::Andnps, true, | 
| - InstX86Base<Machine>::SseSuffix::Packed> { | 
| -public: | 
| - static InstX86Andnps *create(Cfg *Func, Variable *Dest, Operand *Source) { | 
| - return new (Func->allocate<InstX86Andnps>()) | 
| - InstX86Andnps(Func, Dest, Source); | 
| - } | 
| + class InstX86Sbb : public InstX86BaseBinopGPR<InstX86Base::Sbb> { | 
| + public: | 
| + static InstX86Sbb *create(Cfg *Func, Variable *Dest, Operand *Source) { | 
| + return new (Func->allocate<InstX86Sbb>()) InstX86Sbb(Func, Dest, Source); | 
| + } | 
| -private: | 
| - InstX86Andnps(Cfg *Func, Variable *Dest, Operand *Source) | 
| - : InstX86BaseBinopXmm<Machine, InstX86Base<Machine>::Andnps, true, | 
| - InstX86Base<Machine>::SseSuffix::Packed>(Func, Dest, | 
| - Source) {} | 
| -}; | 
| + private: | 
| + InstX86Sbb(Cfg *Func, Variable *Dest, Operand *Source) | 
| + : InstX86BaseBinopGPR<InstX86Base::Sbb>(Func, Dest, Source) {} | 
| + }; | 
| -template <class Machine> | 
| -class InstX86Andps | 
| - : public InstX86BaseBinopXmm<Machine, InstX86Base<Machine>::Andps, true, | 
| - InstX86Base<Machine>::SseSuffix::Packed> { | 
| -public: | 
| - static InstX86Andps *create(Cfg *Func, Variable *Dest, Operand *Source) { | 
| - return new (Func->allocate<InstX86Andps>()) | 
| - InstX86Andps(Func, Dest, Source); | 
| - } | 
| + class InstX86SbbRMW : public InstX86BaseBinopRMW<InstX86Base::SbbRMW> { | 
| + public: | 
| + static InstX86SbbRMW *create(Cfg *Func, X86OperandMem *DestSrc0, | 
| + Operand *Src1) { | 
| + return new (Func->allocate<InstX86SbbRMW>()) | 
| + InstX86SbbRMW(Func, DestSrc0, Src1); | 
| + } | 
| -private: | 
| - InstX86Andps(Cfg *Func, Variable *Dest, Operand *Source) | 
| - : InstX86BaseBinopXmm<Machine, InstX86Base<Machine>::Andps, true, | 
| - InstX86Base<Machine>::SseSuffix::Packed>(Func, Dest, | 
| - Source) {} | 
| -}; | 
| + private: | 
| + InstX86SbbRMW(Cfg *Func, X86OperandMem *DestSrc0, Operand *Src1) | 
| + : InstX86BaseBinopRMW<InstX86Base::SbbRMW>(Func, DestSrc0, Src1) {} | 
| + }; | 
| -template <class Machine> | 
| -class InstX86AndRMW | 
| - : public InstX86BaseBinopRMW<Machine, InstX86Base<Machine>::AndRMW> { | 
| -public: | 
| - static InstX86AndRMW * | 
| - create(Cfg *Func, | 
| - typename InstX86Base<Machine>::Traits::X86OperandMem *DestSrc0, | 
| - Operand *Src1) { | 
| - return new (Func->allocate<InstX86AndRMW>()) | 
| - InstX86AndRMW(Func, DestSrc0, Src1); | 
| - } | 
| + class InstX86Psub | 
| + : public InstX86BaseBinopXmm<InstX86Base::Psub, true, | 
| + InstX86Base::SseSuffix::Integral> { | 
| + public: | 
| + static InstX86Psub *create(Cfg *Func, Variable *Dest, Operand *Source) { | 
| + return new (Func->allocate<InstX86Psub>()) | 
| + InstX86Psub(Func, Dest, Source); | 
| + } | 
| -private: | 
| - InstX86AndRMW(Cfg *Func, | 
| - typename InstX86Base<Machine>::Traits::X86OperandMem *DestSrc0, | 
| - Operand *Src1) | 
| - : InstX86BaseBinopRMW<Machine, InstX86Base<Machine>::AndRMW>( | 
| - Func, DestSrc0, Src1) {} | 
| -}; | 
| + private: | 
| + InstX86Psub(Cfg *Func, Variable *Dest, Operand *Source) | 
| + : InstX86BaseBinopXmm<InstX86Base::Psub, true, | 
| + InstX86Base::SseSuffix::Integral>(Func, Dest, | 
| + Source) {} | 
| + }; | 
| -template <class Machine> | 
| -class InstX86Pand | 
| - : public InstX86BaseBinopXmm<Machine, InstX86Base<Machine>::Pand, false, | 
| - InstX86Base<Machine>::SseSuffix::None> { | 
| -public: | 
| - static InstX86Pand *create(Cfg *Func, Variable *Dest, Operand *Source) { | 
| - return new (Func->allocate<InstX86Pand>()) InstX86Pand(Func, Dest, Source); | 
| - } | 
| + class InstX86And : public InstX86BaseBinopGPR<InstX86Base::And> { | 
| + public: | 
| + static InstX86And *create(Cfg *Func, Variable *Dest, Operand *Source) { | 
| + return new (Func->allocate<InstX86And>()) InstX86And(Func, Dest, Source); | 
| + } | 
| -private: | 
| - InstX86Pand(Cfg *Func, Variable *Dest, Operand *Source) | 
| - : InstX86BaseBinopXmm<Machine, InstX86Base<Machine>::Pand, false, | 
| - InstX86Base<Machine>::SseSuffix::None>(Func, Dest, | 
| - Source) {} | 
| -}; | 
| + private: | 
| + InstX86And(Cfg *Func, Variable *Dest, Operand *Source) | 
| + : InstX86BaseBinopGPR<InstX86Base::And>(Func, Dest, Source) {} | 
| + }; | 
| -template <class Machine> | 
| -class InstX86Pandn | 
| - : public InstX86BaseBinopXmm<Machine, InstX86Base<Machine>::Pandn, false, | 
| - InstX86Base<Machine>::SseSuffix::None> { | 
| -public: | 
| - static InstX86Pandn *create(Cfg *Func, Variable *Dest, Operand *Source) { | 
| - return new (Func->allocate<InstX86Pandn>()) | 
| - InstX86Pandn(Func, Dest, Source); | 
| - } | 
| + class InstX86Andnps | 
| + : public InstX86BaseBinopXmm<InstX86Base::Andnps, true, | 
| + InstX86Base::SseSuffix::Packed> { | 
| + public: | 
| + static InstX86Andnps *create(Cfg *Func, Variable *Dest, Operand *Source) { | 
| + return new (Func->allocate<InstX86Andnps>()) | 
| + InstX86Andnps(Func, Dest, Source); | 
| + } | 
| -private: | 
| - InstX86Pandn(Cfg *Func, Variable *Dest, Operand *Source) | 
| - : InstX86BaseBinopXmm<Machine, InstX86Base<Machine>::Pandn, false, | 
| - InstX86Base<Machine>::SseSuffix::None>(Func, Dest, | 
| - Source) {} | 
| -}; | 
| + private: | 
| + InstX86Andnps(Cfg *Func, Variable *Dest, Operand *Source) | 
| + : InstX86BaseBinopXmm<InstX86Base::Andnps, true, | 
| + InstX86Base::SseSuffix::Packed>(Func, Dest, | 
| + Source) {} | 
| + }; | 
| -template <class Machine> | 
| -class InstX86Maxss | 
| - : public InstX86BaseBinopXmm<Machine, InstX86Base<Machine>::Maxss, true, | 
| - InstX86Base<Machine>::SseSuffix::Scalar> { | 
| -public: | 
| - static InstX86Maxss *create(Cfg *Func, Variable *Dest, Operand *Source) { | 
| - return new (Func->allocate<InstX86Maxss>()) | 
| - InstX86Maxss(Func, Dest, Source); | 
| - } | 
| + class InstX86Andps | 
| + : public InstX86BaseBinopXmm<InstX86Base::Andps, true, | 
| + InstX86Base::SseSuffix::Packed> { | 
| + public: | 
| + static InstX86Andps *create(Cfg *Func, Variable *Dest, Operand *Source) { | 
| + return new (Func->allocate<InstX86Andps>()) | 
| + InstX86Andps(Func, Dest, Source); | 
| + } | 
| -private: | 
| - InstX86Maxss(Cfg *Func, Variable *Dest, Operand *Source) | 
| - : InstX86BaseBinopXmm<Machine, InstX86Base<Machine>::Maxss, true, | 
| - InstX86Base<Machine>::SseSuffix::Scalar>(Func, Dest, | 
| - Source) {} | 
| -}; | 
| + private: | 
| + InstX86Andps(Cfg *Func, Variable *Dest, Operand *Source) | 
| + : InstX86BaseBinopXmm<InstX86Base::Andps, true, | 
| + InstX86Base::SseSuffix::Packed>(Func, Dest, | 
| + Source) {} | 
| + }; | 
| -template <class Machine> | 
| -class InstX86Minss | 
| - : public InstX86BaseBinopXmm<Machine, InstX86Base<Machine>::Minss, true, | 
| - InstX86Base<Machine>::SseSuffix::Scalar> { | 
| -public: | 
| - static InstX86Minss *create(Cfg *Func, Variable *Dest, Operand *Source) { | 
| - return new (Func->allocate<InstX86Minss>()) | 
| - InstX86Minss(Func, Dest, Source); | 
| - } | 
| + class InstX86AndRMW : public InstX86BaseBinopRMW<InstX86Base::AndRMW> { | 
| + public: | 
| + static InstX86AndRMW *create(Cfg *Func, X86OperandMem *DestSrc0, | 
| + Operand *Src1) { | 
| + return new (Func->allocate<InstX86AndRMW>()) | 
| + InstX86AndRMW(Func, DestSrc0, Src1); | 
| + } | 
| -private: | 
| - InstX86Minss(Cfg *Func, Variable *Dest, Operand *Source) | 
| - : InstX86BaseBinopXmm<Machine, InstX86Base<Machine>::Minss, true, | 
| - InstX86Base<Machine>::SseSuffix::Scalar>(Func, Dest, | 
| - Source) {} | 
| -}; | 
| + private: | 
| + InstX86AndRMW(Cfg *Func, X86OperandMem *DestSrc0, Operand *Src1) | 
| + : InstX86BaseBinopRMW<InstX86Base::AndRMW>(Func, DestSrc0, Src1) {} | 
| + }; | 
| -template <class Machine> | 
| -class InstX86Or | 
| - : public InstX86BaseBinopGPR<Machine, InstX86Base<Machine>::Or> { | 
| -public: | 
| - static InstX86Or *create(Cfg *Func, Variable *Dest, Operand *Source) { | 
| - return new (Func->allocate<InstX86Or>()) InstX86Or(Func, Dest, Source); | 
| - } | 
| + class InstX86Pand : public InstX86BaseBinopXmm<InstX86Base::Pand, false, | 
| + InstX86Base::SseSuffix::None> { | 
| + public: | 
| + static InstX86Pand *create(Cfg *Func, Variable *Dest, Operand *Source) { | 
| + return new (Func->allocate<InstX86Pand>()) | 
| + InstX86Pand(Func, Dest, Source); | 
| + } | 
| -private: | 
| - InstX86Or(Cfg *Func, Variable *Dest, Operand *Source) | 
| - : InstX86BaseBinopGPR<Machine, InstX86Base<Machine>::Or>(Func, Dest, | 
| - Source) {} | 
| -}; | 
| + private: | 
| + InstX86Pand(Cfg *Func, Variable *Dest, Operand *Source) | 
| + : InstX86BaseBinopXmm<InstX86Base::Pand, false, | 
| + InstX86Base::SseSuffix::None>(Func, Dest, | 
| + Source) {} | 
| + }; | 
| -template <class Machine> | 
| -class InstX86Orps | 
| - : public InstX86BaseBinopXmm<Machine, InstX86Base<Machine>::Orps, true, | 
| - InstX86Base<Machine>::SseSuffix::Packed> { | 
| -public: | 
| - static InstX86Orps *create(Cfg *Func, Variable *Dest, Operand *Source) { | 
| - return new (Func->allocate<InstX86Orps>()) InstX86Orps(Func, Dest, Source); | 
| - } | 
| + class InstX86Pandn | 
| + : public InstX86BaseBinopXmm<InstX86Base::Pandn, false, | 
| + InstX86Base::SseSuffix::None> { | 
| + public: | 
| + static InstX86Pandn *create(Cfg *Func, Variable *Dest, Operand *Source) { | 
| + return new (Func->allocate<InstX86Pandn>()) | 
| + InstX86Pandn(Func, Dest, Source); | 
| + } | 
| -private: | 
| - InstX86Orps(Cfg *Func, Variable *Dest, Operand *Source) | 
| - : InstX86BaseBinopXmm<Machine, InstX86Base<Machine>::Orps, true, | 
| - InstX86Base<Machine>::SseSuffix::Packed>(Func, Dest, | 
| - Source) {} | 
| -}; | 
| + private: | 
| + InstX86Pandn(Cfg *Func, Variable *Dest, Operand *Source) | 
| + : InstX86BaseBinopXmm<InstX86Base::Pandn, false, | 
| + InstX86Base::SseSuffix::None>(Func, Dest, | 
| + Source) {} | 
| + }; | 
| -template <class Machine> | 
| -class InstX86OrRMW | 
| - : public InstX86BaseBinopRMW<Machine, InstX86Base<Machine>::OrRMW> { | 
| -public: | 
| - static InstX86OrRMW * | 
| - create(Cfg *Func, | 
| - typename InstX86Base<Machine>::Traits::X86OperandMem *DestSrc0, | 
| - Operand *Src1) { | 
| - return new (Func->allocate<InstX86OrRMW>()) | 
| - InstX86OrRMW(Func, DestSrc0, Src1); | 
| - } | 
| + class InstX86Maxss | 
| + : public InstX86BaseBinopXmm<InstX86Base::Maxss, true, | 
| + InstX86Base::SseSuffix::Scalar> { | 
| + public: | 
| + static InstX86Maxss *create(Cfg *Func, Variable *Dest, Operand *Source) { | 
| + return new (Func->allocate<InstX86Maxss>()) | 
| + InstX86Maxss(Func, Dest, Source); | 
| + } | 
| -private: | 
| - InstX86OrRMW(Cfg *Func, | 
| - typename InstX86Base<Machine>::Traits::X86OperandMem *DestSrc0, | 
| - Operand *Src1) | 
| - : InstX86BaseBinopRMW<Machine, InstX86Base<Machine>::OrRMW>( | 
| - Func, DestSrc0, Src1) {} | 
| -}; | 
| + private: | 
| + InstX86Maxss(Cfg *Func, Variable *Dest, Operand *Source) | 
| + : InstX86BaseBinopXmm<InstX86Base::Maxss, true, | 
| + InstX86Base::SseSuffix::Scalar>(Func, Dest, | 
| + Source) {} | 
| + }; | 
| -template <class Machine> | 
| -class InstX86Por | 
| - : public InstX86BaseBinopXmm<Machine, InstX86Base<Machine>::Por, false, | 
| - InstX86Base<Machine>::SseSuffix::None> { | 
| -public: | 
| - static InstX86Por *create(Cfg *Func, Variable *Dest, Operand *Source) { | 
| - return new (Func->allocate<InstX86Por>()) InstX86Por(Func, Dest, Source); | 
| - } | 
| + class InstX86Minss | 
| + : public InstX86BaseBinopXmm<InstX86Base::Minss, true, | 
| + InstX86Base::SseSuffix::Scalar> { | 
| + public: | 
| + static InstX86Minss *create(Cfg *Func, Variable *Dest, Operand *Source) { | 
| + return new (Func->allocate<InstX86Minss>()) | 
| + InstX86Minss(Func, Dest, Source); | 
| + } | 
| -private: | 
| - InstX86Por(Cfg *Func, Variable *Dest, Operand *Source) | 
| - : InstX86BaseBinopXmm<Machine, InstX86Base<Machine>::Por, false, | 
| - InstX86Base<Machine>::SseSuffix::None>(Func, Dest, | 
| - Source) {} | 
| -}; | 
| + private: | 
| + InstX86Minss(Cfg *Func, Variable *Dest, Operand *Source) | 
| + : InstX86BaseBinopXmm<InstX86Base::Minss, true, | 
| + InstX86Base::SseSuffix::Scalar>(Func, Dest, | 
| + Source) {} | 
| + }; | 
| -template <class Machine> | 
| -class InstX86Xor | 
| - : public InstX86BaseBinopGPR<Machine, InstX86Base<Machine>::Xor> { | 
| -public: | 
| - static InstX86Xor *create(Cfg *Func, Variable *Dest, Operand *Source) { | 
| - return new (Func->allocate<InstX86Xor>()) InstX86Xor(Func, Dest, Source); | 
| - } | 
| + class InstX86Or : public InstX86BaseBinopGPR<InstX86Base::Or> { | 
| + public: | 
| + static InstX86Or *create(Cfg *Func, Variable *Dest, Operand *Source) { | 
| + return new (Func->allocate<InstX86Or>()) InstX86Or(Func, Dest, Source); | 
| + } | 
| -private: | 
| - InstX86Xor(Cfg *Func, Variable *Dest, Operand *Source) | 
| - : InstX86BaseBinopGPR<Machine, InstX86Base<Machine>::Xor>(Func, Dest, | 
| - Source) {} | 
| -}; | 
| + private: | 
| + InstX86Or(Cfg *Func, Variable *Dest, Operand *Source) | 
| + : InstX86BaseBinopGPR<InstX86Base::Or>(Func, Dest, Source) {} | 
| + }; | 
| -template <class Machine> | 
| -class InstX86Xorps | 
| - : public InstX86BaseBinopXmm<Machine, InstX86Base<Machine>::Xorps, true, | 
| - InstX86Base<Machine>::SseSuffix::Packed> { | 
| -public: | 
| - static InstX86Xorps *create(Cfg *Func, Variable *Dest, Operand *Source) { | 
| - return new (Func->allocate<InstX86Xorps>()) | 
| - InstX86Xorps(Func, Dest, Source); | 
| - } | 
| + class InstX86Orps | 
| + : public InstX86BaseBinopXmm<InstX86Base::Orps, true, | 
| + InstX86Base::SseSuffix::Packed> { | 
| + public: | 
| + static InstX86Orps *create(Cfg *Func, Variable *Dest, Operand *Source) { | 
| + return new (Func->allocate<InstX86Orps>()) | 
| + InstX86Orps(Func, Dest, Source); | 
| + } | 
| -private: | 
| - InstX86Xorps(Cfg *Func, Variable *Dest, Operand *Source) | 
| - : InstX86BaseBinopXmm<Machine, InstX86Base<Machine>::Xorps, true, | 
| - InstX86Base<Machine>::SseSuffix::Packed>(Func, Dest, | 
| - Source) {} | 
| -}; | 
| + private: | 
| + InstX86Orps(Cfg *Func, Variable *Dest, Operand *Source) | 
| + : InstX86BaseBinopXmm<InstX86Base::Orps, true, | 
| + InstX86Base::SseSuffix::Packed>(Func, Dest, | 
| + Source) {} | 
| + }; | 
| -template <class Machine> | 
| -class InstX86XorRMW | 
| - : public InstX86BaseBinopRMW<Machine, InstX86Base<Machine>::XorRMW> { | 
| -public: | 
| - static InstX86XorRMW * | 
| - create(Cfg *Func, | 
| - typename InstX86Base<Machine>::Traits::X86OperandMem *DestSrc0, | 
| - Operand *Src1) { | 
| - return new (Func->allocate<InstX86XorRMW>()) | 
| - InstX86XorRMW(Func, DestSrc0, Src1); | 
| - } | 
| + class InstX86OrRMW : public InstX86BaseBinopRMW<InstX86Base::OrRMW> { | 
| + public: | 
| + static InstX86OrRMW *create(Cfg *Func, X86OperandMem *DestSrc0, | 
| + Operand *Src1) { | 
| + return new (Func->allocate<InstX86OrRMW>()) | 
| + InstX86OrRMW(Func, DestSrc0, Src1); | 
| + } | 
| -private: | 
| - InstX86XorRMW(Cfg *Func, | 
| - typename InstX86Base<Machine>::Traits::X86OperandMem *DestSrc0, | 
| - Operand *Src1) | 
| - : InstX86BaseBinopRMW<Machine, InstX86Base<Machine>::XorRMW>( | 
| - Func, DestSrc0, Src1) {} | 
| -}; | 
| + private: | 
| + InstX86OrRMW(Cfg *Func, X86OperandMem *DestSrc0, Operand *Src1) | 
| + : InstX86BaseBinopRMW<InstX86Base::OrRMW>(Func, DestSrc0, Src1) {} | 
| + }; | 
| -template <class Machine> | 
| -class InstX86Pxor | 
| - : public InstX86BaseBinopXmm<Machine, InstX86Base<Machine>::Pxor, false, | 
| - InstX86Base<Machine>::SseSuffix::None> { | 
| -public: | 
| - static InstX86Pxor *create(Cfg *Func, Variable *Dest, Operand *Source) { | 
| - return new (Func->allocate<InstX86Pxor>()) InstX86Pxor(Func, Dest, Source); | 
| - } | 
| + class InstX86Por : public InstX86BaseBinopXmm<InstX86Base::Por, false, | 
| + InstX86Base::SseSuffix::None> { | 
| + public: | 
| + static InstX86Por *create(Cfg *Func, Variable *Dest, Operand *Source) { | 
| + return new (Func->allocate<InstX86Por>()) InstX86Por(Func, Dest, Source); | 
| + } | 
| -private: | 
| - InstX86Pxor(Cfg *Func, Variable *Dest, Operand *Source) | 
| - : InstX86BaseBinopXmm<Machine, InstX86Base<Machine>::Pxor, false, | 
| - InstX86Base<Machine>::SseSuffix::None>(Func, Dest, | 
| - Source) {} | 
| -}; | 
| + private: | 
| + InstX86Por(Cfg *Func, Variable *Dest, Operand *Source) | 
| + : InstX86BaseBinopXmm<InstX86Base::Por, false, | 
| + InstX86Base::SseSuffix::None>(Func, Dest, | 
| + Source) {} | 
| + }; | 
| -template <class Machine> | 
| -class InstX86Imul | 
| - : public InstX86BaseBinopGPR<Machine, InstX86Base<Machine>::Imul> { | 
| -public: | 
| - static InstX86Imul *create(Cfg *Func, Variable *Dest, Operand *Source) { | 
| - return new (Func->allocate<InstX86Imul>()) InstX86Imul(Func, Dest, Source); | 
| - } | 
| + class InstX86Xor : public InstX86BaseBinopGPR<InstX86Base::Xor> { | 
| + public: | 
| + static InstX86Xor *create(Cfg *Func, Variable *Dest, Operand *Source) { | 
| + return new (Func->allocate<InstX86Xor>()) InstX86Xor(Func, Dest, Source); | 
| + } | 
| - void emit(const Cfg *Func) const override; | 
| - void emitIAS(const Cfg *Func) const override; | 
| + private: | 
| + InstX86Xor(Cfg *Func, Variable *Dest, Operand *Source) | 
| + : InstX86BaseBinopGPR<InstX86Base::Xor>(Func, Dest, Source) {} | 
| + }; | 
| -private: | 
| - InstX86Imul(Cfg *Func, Variable *Dest, Operand *Source) | 
| - : InstX86BaseBinopGPR<Machine, InstX86Base<Machine>::Imul>(Func, Dest, | 
| - Source) {} | 
| -}; | 
| + class InstX86Xorps | 
| + : public InstX86BaseBinopXmm<InstX86Base::Xorps, true, | 
| + InstX86Base::SseSuffix::Packed> { | 
| + public: | 
| + static InstX86Xorps *create(Cfg *Func, Variable *Dest, Operand *Source) { | 
| + return new (Func->allocate<InstX86Xorps>()) | 
| + InstX86Xorps(Func, Dest, Source); | 
| + } | 
| -template <class Machine> | 
| -class InstX86ImulImm | 
| - : public InstX86BaseThreeAddressop<Machine, InstX86Base<Machine>::ImulImm> { | 
| -public: | 
| - static InstX86ImulImm *create(Cfg *Func, Variable *Dest, Operand *Source0, | 
| - Operand *Source1) { | 
| - return new (Func->allocate<InstX86ImulImm>()) | 
| - InstX86ImulImm(Func, Dest, Source0, Source1); | 
| - } | 
| + private: | 
| + InstX86Xorps(Cfg *Func, Variable *Dest, Operand *Source) | 
| + : InstX86BaseBinopXmm<InstX86Base::Xorps, true, | 
| + InstX86Base::SseSuffix::Packed>(Func, Dest, | 
| + Source) {} | 
| + }; | 
| - void emit(const Cfg *Func) const override; | 
| - void emitIAS(const Cfg *Func) const override; | 
| + class InstX86XorRMW : public InstX86BaseBinopRMW<InstX86Base::XorRMW> { | 
| + public: | 
| + static InstX86XorRMW *create(Cfg *Func, X86OperandMem *DestSrc0, | 
| + Operand *Src1) { | 
| + return new (Func->allocate<InstX86XorRMW>()) | 
| + InstX86XorRMW(Func, DestSrc0, Src1); | 
| + } | 
| -private: | 
| - InstX86ImulImm(Cfg *Func, Variable *Dest, Operand *Source0, Operand *Source1) | 
| - : InstX86BaseThreeAddressop<Machine, InstX86Base<Machine>::ImulImm>( | 
| - Func, Dest, Source0, Source1) {} | 
| -}; | 
| + private: | 
| + InstX86XorRMW(Cfg *Func, X86OperandMem *DestSrc0, Operand *Src1) | 
| + : InstX86BaseBinopRMW<InstX86Base::XorRMW>(Func, DestSrc0, Src1) {} | 
| + }; | 
| -template <class Machine> | 
| -class InstX86Mulps | 
| - : public InstX86BaseBinopXmm<Machine, InstX86Base<Machine>::Mulps, true, | 
| - InstX86Base<Machine>::SseSuffix::Packed> { | 
| -public: | 
| - static InstX86Mulps *create(Cfg *Func, Variable *Dest, Operand *Source) { | 
| - return new (Func->allocate<InstX86Mulps>()) | 
| - InstX86Mulps(Func, Dest, Source); | 
| - } | 
| + class InstX86Pxor : public InstX86BaseBinopXmm<InstX86Base::Pxor, false, | 
| + InstX86Base::SseSuffix::None> { | 
| + public: | 
| + static InstX86Pxor *create(Cfg *Func, Variable *Dest, Operand *Source) { | 
| + return new (Func->allocate<InstX86Pxor>()) | 
| + InstX86Pxor(Func, Dest, Source); | 
| + } | 
| -private: | 
| - InstX86Mulps(Cfg *Func, Variable *Dest, Operand *Source) | 
| - : InstX86BaseBinopXmm<Machine, InstX86Base<Machine>::Mulps, true, | 
| - InstX86Base<Machine>::SseSuffix::Packed>(Func, Dest, | 
| - Source) {} | 
| -}; | 
| + private: | 
| + InstX86Pxor(Cfg *Func, Variable *Dest, Operand *Source) | 
| + : InstX86BaseBinopXmm<InstX86Base::Pxor, false, | 
| + InstX86Base::SseSuffix::None>(Func, Dest, | 
| + Source) {} | 
| + }; | 
| -template <class Machine> | 
| -class InstX86Mulss | 
| - : public InstX86BaseBinopXmm<Machine, InstX86Base<Machine>::Mulss, false, | 
| - InstX86Base<Machine>::SseSuffix::Scalar> { | 
| -public: | 
| - static InstX86Mulss *create(Cfg *Func, Variable *Dest, Operand *Source) { | 
| - return new (Func->allocate<InstX86Mulss>()) | 
| - InstX86Mulss(Func, Dest, Source); | 
| - } | 
| + class InstX86Imul : public InstX86BaseBinopGPR<InstX86Base::Imul> { | 
| + public: | 
| + static InstX86Imul *create(Cfg *Func, Variable *Dest, Operand *Source) { | 
| + return new (Func->allocate<InstX86Imul>()) | 
| + InstX86Imul(Func, Dest, Source); | 
| + } | 
| -private: | 
| - InstX86Mulss(Cfg *Func, Variable *Dest, Operand *Source) | 
| - : InstX86BaseBinopXmm<Machine, InstX86Base<Machine>::Mulss, false, | 
| - InstX86Base<Machine>::SseSuffix::Scalar>(Func, Dest, | 
| - Source) {} | 
| -}; | 
| + void emit(const Cfg *Func) const override; | 
| + void emitIAS(const Cfg *Func) const override; | 
| -template <class Machine> | 
| -class InstX86Pmull | 
| - : public InstX86BaseBinopXmm<Machine, InstX86Base<Machine>::Pmull, true, | 
| - InstX86Base<Machine>::SseSuffix::Integral> { | 
| -public: | 
| - static InstX86Pmull *create(Cfg *Func, Variable *Dest, Operand *Source) { | 
| - bool TypesAreValid = | 
| - Dest->getType() == IceType_v4i32 || Dest->getType() == IceType_v8i16; | 
| - auto *Target = InstX86Base<Machine>::getTarget(Func); | 
| - bool InstructionSetIsValid = | 
| - Dest->getType() == IceType_v8i16 || | 
| - Target->getInstructionSet() >= InstX86Base<Machine>::Traits::SSE4_1; | 
| - (void)TypesAreValid; | 
| - (void)InstructionSetIsValid; | 
| - assert(TypesAreValid); | 
| - assert(InstructionSetIsValid); | 
| - return new (Func->allocate<InstX86Pmull>()) | 
| - InstX86Pmull(Func, Dest, Source); | 
| - } | 
| + private: | 
| + InstX86Imul(Cfg *Func, Variable *Dest, Operand *Source) | 
| + : InstX86BaseBinopGPR<InstX86Base::Imul>(Func, Dest, Source) {} | 
| + }; | 
| -private: | 
| - InstX86Pmull(Cfg *Func, Variable *Dest, Operand *Source) | 
| - : InstX86BaseBinopXmm<Machine, InstX86Base<Machine>::Pmull, true, | 
| - InstX86Base<Machine>::SseSuffix::Integral>( | 
| - Func, Dest, Source) {} | 
| -}; | 
| + class InstX86ImulImm | 
| + : public InstX86BaseThreeAddressop<InstX86Base::ImulImm> { | 
| + public: | 
| + static InstX86ImulImm *create(Cfg *Func, Variable *Dest, Operand *Source0, | 
| + Operand *Source1) { | 
| + return new (Func->allocate<InstX86ImulImm>()) | 
| + InstX86ImulImm(Func, Dest, Source0, Source1); | 
| + } | 
| -template <class Machine> | 
| -class InstX86Pmuludq | 
| - : public InstX86BaseBinopXmm<Machine, InstX86Base<Machine>::Pmuludq, false, | 
| - InstX86Base<Machine>::SseSuffix::None> { | 
| -public: | 
| - static InstX86Pmuludq *create(Cfg *Func, Variable *Dest, Operand *Source) { | 
| - assert(Dest->getType() == IceType_v4i32 && | 
| - Source->getType() == IceType_v4i32); | 
| - return new (Func->allocate<InstX86Pmuludq>()) | 
| - InstX86Pmuludq(Func, Dest, Source); | 
| - } | 
| + void emit(const Cfg *Func) const override; | 
| + void emitIAS(const Cfg *Func) const override; | 
| -private: | 
| - InstX86Pmuludq(Cfg *Func, Variable *Dest, Operand *Source) | 
| - : InstX86BaseBinopXmm<Machine, InstX86Base<Machine>::Pmuludq, false, | 
| - InstX86Base<Machine>::SseSuffix::None>(Func, Dest, | 
| - Source) {} | 
| -}; | 
| + private: | 
| + InstX86ImulImm(Cfg *Func, Variable *Dest, Operand *Source0, | 
| + Operand *Source1) | 
| + : InstX86BaseThreeAddressop<InstX86Base::ImulImm>(Func, Dest, Source0, | 
| + Source1) {} | 
| + }; | 
| -template <class Machine> | 
| -class InstX86Divps | 
| - : public InstX86BaseBinopXmm<Machine, InstX86Base<Machine>::Divps, true, | 
| - InstX86Base<Machine>::SseSuffix::Packed> { | 
| -public: | 
| - static InstX86Divps *create(Cfg *Func, Variable *Dest, Operand *Source) { | 
| - return new (Func->allocate<InstX86Divps>()) | 
| - InstX86Divps(Func, Dest, Source); | 
| - } | 
| + class InstX86Mulps | 
| + : public InstX86BaseBinopXmm<InstX86Base::Mulps, true, | 
| + InstX86Base::SseSuffix::Packed> { | 
| + public: | 
| + static InstX86Mulps *create(Cfg *Func, Variable *Dest, Operand *Source) { | 
| + return new (Func->allocate<InstX86Mulps>()) | 
| + InstX86Mulps(Func, Dest, Source); | 
| + } | 
| -private: | 
| - InstX86Divps(Cfg *Func, Variable *Dest, Operand *Source) | 
| - : InstX86BaseBinopXmm<Machine, InstX86Base<Machine>::Divps, true, | 
| - InstX86Base<Machine>::SseSuffix::Packed>(Func, Dest, | 
| - Source) {} | 
| -}; | 
| + private: | 
| + InstX86Mulps(Cfg *Func, Variable *Dest, Operand *Source) | 
| + : InstX86BaseBinopXmm<InstX86Base::Mulps, true, | 
| + InstX86Base::SseSuffix::Packed>(Func, Dest, | 
| + Source) {} | 
| + }; | 
| -template <class Machine> | 
| -class InstX86Divss | 
| - : public InstX86BaseBinopXmm<Machine, InstX86Base<Machine>::Divss, false, | 
| - InstX86Base<Machine>::SseSuffix::Scalar> { | 
| -public: | 
| - static InstX86Divss *create(Cfg *Func, Variable *Dest, Operand *Source) { | 
| - return new (Func->allocate<InstX86Divss>()) | 
| - InstX86Divss(Func, Dest, Source); | 
| - } | 
| + class InstX86Mulss | 
| + : public InstX86BaseBinopXmm<InstX86Base::Mulss, false, | 
| + InstX86Base::SseSuffix::Scalar> { | 
| + public: | 
| + static InstX86Mulss *create(Cfg *Func, Variable *Dest, Operand *Source) { | 
| + return new (Func->allocate<InstX86Mulss>()) | 
| + InstX86Mulss(Func, Dest, Source); | 
| + } | 
| -private: | 
| - InstX86Divss(Cfg *Func, Variable *Dest, Operand *Source) | 
| - : InstX86BaseBinopXmm<Machine, InstX86Base<Machine>::Divss, false, | 
| - InstX86Base<Machine>::SseSuffix::Scalar>(Func, Dest, | 
| - Source) {} | 
| -}; | 
| + private: | 
| + InstX86Mulss(Cfg *Func, Variable *Dest, Operand *Source) | 
| + : InstX86BaseBinopXmm<InstX86Base::Mulss, false, | 
| + InstX86Base::SseSuffix::Scalar>(Func, Dest, | 
| + Source) {} | 
| + }; | 
| -template <class Machine> | 
| -class InstX86Rol | 
| - : public InstX86BaseBinopGPRShift<Machine, InstX86Base<Machine>::Rol> { | 
| -public: | 
| - static InstX86Rol *create(Cfg *Func, Variable *Dest, Operand *Source) { | 
| - return new (Func->allocate<InstX86Rol>()) InstX86Rol(Func, Dest, Source); | 
| - } | 
| + class InstX86Pmull | 
| + : public InstX86BaseBinopXmm<InstX86Base::Pmull, true, | 
| + InstX86Base::SseSuffix::Integral> { | 
| + public: | 
| + static InstX86Pmull *create(Cfg *Func, Variable *Dest, Operand *Source) { | 
| + bool TypesAreValid = | 
| + Dest->getType() == IceType_v4i32 || Dest->getType() == IceType_v8i16; | 
| + auto *Target = InstX86Base::getTarget(Func); | 
| + bool InstructionSetIsValid = | 
| + Dest->getType() == IceType_v8i16 || | 
| + Target->getInstructionSet() >= Traits::SSE4_1; | 
| + (void)TypesAreValid; | 
| + (void)InstructionSetIsValid; | 
| + assert(TypesAreValid); | 
| + assert(InstructionSetIsValid); | 
| + return new (Func->allocate<InstX86Pmull>()) | 
| + InstX86Pmull(Func, Dest, Source); | 
| + } | 
| -private: | 
| - InstX86Rol(Cfg *Func, Variable *Dest, Operand *Source) | 
| - : InstX86BaseBinopGPRShift<Machine, InstX86Base<Machine>::Rol>(Func, Dest, | 
| - Source) {} | 
| -}; | 
| + private: | 
| + InstX86Pmull(Cfg *Func, Variable *Dest, Operand *Source) | 
| + : InstX86BaseBinopXmm<InstX86Base::Pmull, true, | 
| + InstX86Base::SseSuffix::Integral>(Func, Dest, | 
| + Source) {} | 
| + }; | 
| -template <class Machine> | 
| -class InstX86Shl | 
| - : public InstX86BaseBinopGPRShift<Machine, InstX86Base<Machine>::Shl> { | 
| -public: | 
| - static InstX86Shl *create(Cfg *Func, Variable *Dest, Operand *Source) { | 
| - return new (Func->allocate<InstX86Shl>()) InstX86Shl(Func, Dest, Source); | 
| - } | 
| + class InstX86Pmuludq | 
| + : public InstX86BaseBinopXmm<InstX86Base::Pmuludq, false, | 
| + InstX86Base::SseSuffix::None> { | 
| + public: | 
| + static InstX86Pmuludq *create(Cfg *Func, Variable *Dest, Operand *Source) { | 
| + assert(Dest->getType() == IceType_v4i32 && | 
| + Source->getType() == IceType_v4i32); | 
| + return new (Func->allocate<InstX86Pmuludq>()) | 
| + InstX86Pmuludq(Func, Dest, Source); | 
| + } | 
| -private: | 
| - InstX86Shl(Cfg *Func, Variable *Dest, Operand *Source) | 
| - : InstX86BaseBinopGPRShift<Machine, InstX86Base<Machine>::Shl>(Func, Dest, | 
| - Source) {} | 
| -}; | 
| + private: | 
| + InstX86Pmuludq(Cfg *Func, Variable *Dest, Operand *Source) | 
| + : InstX86BaseBinopXmm<InstX86Base::Pmuludq, false, | 
| + InstX86Base::SseSuffix::None>(Func, Dest, | 
| + Source) {} | 
| + }; | 
| -template <class Machine> | 
| -class InstX86Psll | 
| - : public InstX86BaseBinopXmmShift<Machine, InstX86Base<Machine>::Psll> { | 
| -public: | 
| - static InstX86Psll *create(Cfg *Func, Variable *Dest, Operand *Source) { | 
| - assert(Dest->getType() == IceType_v8i16 || | 
| - Dest->getType() == IceType_v8i1 || | 
| - Dest->getType() == IceType_v4i32 || Dest->getType() == IceType_v4i1); | 
| - return new (Func->allocate<InstX86Psll>()) InstX86Psll(Func, Dest, Source); | 
| - } | 
| + class InstX86Divps | 
| + : public InstX86BaseBinopXmm<InstX86Base::Divps, true, | 
| + InstX86Base::SseSuffix::Packed> { | 
| + public: | 
| + static InstX86Divps *create(Cfg *Func, Variable *Dest, Operand *Source) { | 
| + return new (Func->allocate<InstX86Divps>()) | 
| + InstX86Divps(Func, Dest, Source); | 
| + } | 
| -private: | 
| - InstX86Psll(Cfg *Func, Variable *Dest, Operand *Source) | 
| - : InstX86BaseBinopXmmShift<Machine, InstX86Base<Machine>::Psll>( | 
| - Func, Dest, Source) {} | 
| -}; | 
| + private: | 
| + InstX86Divps(Cfg *Func, Variable *Dest, Operand *Source) | 
| + : InstX86BaseBinopXmm<InstX86Base::Divps, true, | 
| + InstX86Base::SseSuffix::Packed>(Func, Dest, | 
| + Source) {} | 
| + }; | 
| -template <class Machine> | 
| -class InstX86Psrl | 
| - : public InstX86BaseBinopXmmShift<Machine, InstX86Base<Machine>::Psrl, | 
| - true> { | 
| -public: | 
| - static InstX86Psrl *create(Cfg *Func, Variable *Dest, Operand *Source) { | 
| - return new (Func->allocate<InstX86Psrl>()) InstX86Psrl(Func, Dest, Source); | 
| - } | 
| + class InstX86Divss | 
| + : public InstX86BaseBinopXmm<InstX86Base::Divss, false, | 
| + InstX86Base::SseSuffix::Scalar> { | 
| + public: | 
| + static InstX86Divss *create(Cfg *Func, Variable *Dest, Operand *Source) { | 
| + return new (Func->allocate<InstX86Divss>()) | 
| + InstX86Divss(Func, Dest, Source); | 
| + } | 
| -private: | 
| - InstX86Psrl(Cfg *Func, Variable *Dest, Operand *Source) | 
| - : InstX86BaseBinopXmmShift<Machine, InstX86Base<Machine>::Psrl, true>( | 
| - Func, Dest, Source) {} | 
| -}; | 
| + private: | 
| + InstX86Divss(Cfg *Func, Variable *Dest, Operand *Source) | 
| + : InstX86BaseBinopXmm<InstX86Base::Divss, false, | 
| + InstX86Base::SseSuffix::Scalar>(Func, Dest, | 
| + Source) {} | 
| + }; | 
| -template <class Machine> | 
| -class InstX86Shr | 
| - : public InstX86BaseBinopGPRShift<Machine, InstX86Base<Machine>::Shr> { | 
| -public: | 
| - static InstX86Shr *create(Cfg *Func, Variable *Dest, Operand *Source) { | 
| - return new (Func->allocate<InstX86Shr>()) InstX86Shr(Func, Dest, Source); | 
| - } | 
| + class InstX86Rol : public InstX86BaseBinopGPRShift<InstX86Base::Rol> { | 
| + public: | 
| + static InstX86Rol *create(Cfg *Func, Variable *Dest, Operand *Source) { | 
| + return new (Func->allocate<InstX86Rol>()) InstX86Rol(Func, Dest, Source); | 
| + } | 
| -private: | 
| - InstX86Shr(Cfg *Func, Variable *Dest, Operand *Source) | 
| - : InstX86BaseBinopGPRShift<Machine, InstX86Base<Machine>::Shr>(Func, Dest, | 
| - Source) {} | 
| -}; | 
| + private: | 
| + InstX86Rol(Cfg *Func, Variable *Dest, Operand *Source) | 
| + : InstX86BaseBinopGPRShift<InstX86Base::Rol>(Func, Dest, Source) {} | 
| + }; | 
| -template <class Machine> | 
| -class InstX86Sar | 
| - : public InstX86BaseBinopGPRShift<Machine, InstX86Base<Machine>::Sar> { | 
| -public: | 
| - static InstX86Sar *create(Cfg *Func, Variable *Dest, Operand *Source) { | 
| - return new (Func->allocate<InstX86Sar>()) InstX86Sar(Func, Dest, Source); | 
| - } | 
| + class InstX86Shl : public InstX86BaseBinopGPRShift<InstX86Base::Shl> { | 
| + public: | 
| + static InstX86Shl *create(Cfg *Func, Variable *Dest, Operand *Source) { | 
| + return new (Func->allocate<InstX86Shl>()) InstX86Shl(Func, Dest, Source); | 
| + } | 
| -private: | 
| - InstX86Sar(Cfg *Func, Variable *Dest, Operand *Source) | 
| - : InstX86BaseBinopGPRShift<Machine, InstX86Base<Machine>::Sar>(Func, Dest, | 
| - Source) {} | 
| -}; | 
| + private: | 
| + InstX86Shl(Cfg *Func, Variable *Dest, Operand *Source) | 
| + : InstX86BaseBinopGPRShift<InstX86Base::Shl>(Func, Dest, Source) {} | 
| + }; | 
| -template <class Machine> | 
| -class InstX86Psra | 
| - : public InstX86BaseBinopXmmShift<Machine, InstX86Base<Machine>::Psra> { | 
| -public: | 
| - static InstX86Psra *create(Cfg *Func, Variable *Dest, Operand *Source) { | 
| - assert(Dest->getType() == IceType_v8i16 || | 
| - Dest->getType() == IceType_v8i1 || | 
| - Dest->getType() == IceType_v4i32 || Dest->getType() == IceType_v4i1); | 
| - return new (Func->allocate<InstX86Psra>()) InstX86Psra(Func, Dest, Source); | 
| - } | 
| + class InstX86Psll : public InstX86BaseBinopXmmShift<InstX86Base::Psll> { | 
| + public: | 
| + static InstX86Psll *create(Cfg *Func, Variable *Dest, Operand *Source) { | 
| + assert( | 
| + Dest->getType() == IceType_v8i16 || Dest->getType() == IceType_v8i1 || | 
| + Dest->getType() == IceType_v4i32 || Dest->getType() == IceType_v4i1); | 
| + return new (Func->allocate<InstX86Psll>()) | 
| + InstX86Psll(Func, Dest, Source); | 
| + } | 
| -private: | 
| - InstX86Psra(Cfg *Func, Variable *Dest, Operand *Source) | 
| - : InstX86BaseBinopXmmShift<Machine, InstX86Base<Machine>::Psra>( | 
| - Func, Dest, Source) {} | 
| -}; | 
| + private: | 
| + InstX86Psll(Cfg *Func, Variable *Dest, Operand *Source) | 
| + : InstX86BaseBinopXmmShift<InstX86Base::Psll>(Func, Dest, Source) {} | 
| + }; | 
| -template <class Machine> | 
| -class InstX86Pcmpeq | 
| - : public InstX86BaseBinopXmm<Machine, InstX86Base<Machine>::Pcmpeq, true, | 
| - InstX86Base<Machine>::SseSuffix::Integral> { | 
| -public: | 
| - static InstX86Pcmpeq *create(Cfg *Func, Variable *Dest, Operand *Source) { | 
| - return new (Func->allocate<InstX86Pcmpeq>()) | 
| - InstX86Pcmpeq(Func, Dest, Source); | 
| - } | 
| + class InstX86Psrl : public InstX86BaseBinopXmmShift<InstX86Base::Psrl, true> { | 
| + public: | 
| + static InstX86Psrl *create(Cfg *Func, Variable *Dest, Operand *Source) { | 
| + return new (Func->allocate<InstX86Psrl>()) | 
| + InstX86Psrl(Func, Dest, Source); | 
| + } | 
| -private: | 
| - InstX86Pcmpeq(Cfg *Func, Variable *Dest, Operand *Source) | 
| - : InstX86BaseBinopXmm<Machine, InstX86Base<Machine>::Pcmpeq, true, | 
| - InstX86Base<Machine>::SseSuffix::Integral>( | 
| - Func, Dest, Source) {} | 
| -}; | 
| + private: | 
| + InstX86Psrl(Cfg *Func, Variable *Dest, Operand *Source) | 
| + : InstX86BaseBinopXmmShift<InstX86Base::Psrl, true>(Func, Dest, | 
| + Source) {} | 
| + }; | 
| -template <class Machine> | 
| -class InstX86Pcmpgt | 
| - : public InstX86BaseBinopXmm<Machine, InstX86Base<Machine>::Pcmpgt, true, | 
| - InstX86Base<Machine>::SseSuffix::Integral> { | 
| -public: | 
| - static InstX86Pcmpgt *create(Cfg *Func, Variable *Dest, Operand *Source) { | 
| - return new (Func->allocate<InstX86Pcmpgt>()) | 
| - InstX86Pcmpgt(Func, Dest, Source); | 
| - } | 
| + class InstX86Shr : public InstX86BaseBinopGPRShift<InstX86Base::Shr> { | 
| + public: | 
| + static InstX86Shr *create(Cfg *Func, Variable *Dest, Operand *Source) { | 
| + return new (Func->allocate<InstX86Shr>()) InstX86Shr(Func, Dest, Source); | 
| + } | 
| -private: | 
| - InstX86Pcmpgt(Cfg *Func, Variable *Dest, Operand *Source) | 
| - : InstX86BaseBinopXmm<Machine, InstX86Base<Machine>::Pcmpgt, true, | 
| - InstX86Base<Machine>::SseSuffix::Integral>( | 
| - Func, Dest, Source) {} | 
| -}; | 
| + private: | 
| + InstX86Shr(Cfg *Func, Variable *Dest, Operand *Source) | 
| + : InstX86BaseBinopGPRShift<InstX86Base::Shr>(Func, Dest, Source) {} | 
| + }; | 
| -/// movss is only a binary operation when the source and dest operands are both | 
| -/// registers (the high bits of dest are left untouched). In other cases, it | 
| -/// behaves like a copy (mov-like) operation (and the high bits of dest are | 
| -/// cleared). InstX86Movss will assert that both its source and dest operands | 
| -/// are registers, so the lowering code should use _mov instead of _movss in | 
| -/// cases where a copy operation is intended. | 
| -template <class Machine> | 
| -class InstX86MovssRegs | 
| - : public InstX86BaseBinopXmm<Machine, InstX86Base<Machine>::MovssRegs, | 
| - false, InstX86Base<Machine>::SseSuffix::None> { | 
| -public: | 
| - static InstX86MovssRegs *create(Cfg *Func, Variable *Dest, Operand *Source) { | 
| - return new (Func->allocate<InstX86MovssRegs>()) | 
| - InstX86MovssRegs(Func, Dest, Source); | 
| - } | 
| + class InstX86Sar : public InstX86BaseBinopGPRShift<InstX86Base::Sar> { | 
| + public: | 
| + static InstX86Sar *create(Cfg *Func, Variable *Dest, Operand *Source) { | 
| + return new (Func->allocate<InstX86Sar>()) InstX86Sar(Func, Dest, Source); | 
| + } | 
| - void emitIAS(const Cfg *Func) const override; | 
| + private: | 
| + InstX86Sar(Cfg *Func, Variable *Dest, Operand *Source) | 
| + : InstX86BaseBinopGPRShift<InstX86Base::Sar>(Func, Dest, Source) {} | 
| + }; | 
| -private: | 
| - InstX86MovssRegs(Cfg *Func, Variable *Dest, Operand *Source) | 
| - : InstX86BaseBinopXmm<Machine, InstX86Base<Machine>::MovssRegs, false, | 
| - InstX86Base<Machine>::SseSuffix::None>(Func, Dest, | 
| - Source) {} | 
| -}; | 
| + class InstX86Psra : public InstX86BaseBinopXmmShift<InstX86Base::Psra> { | 
| + public: | 
| + static InstX86Psra *create(Cfg *Func, Variable *Dest, Operand *Source) { | 
| + assert( | 
| + Dest->getType() == IceType_v8i16 || Dest->getType() == IceType_v8i1 || | 
| + Dest->getType() == IceType_v4i32 || Dest->getType() == IceType_v4i1); | 
| + return new (Func->allocate<InstX86Psra>()) | 
| + InstX86Psra(Func, Dest, Source); | 
| + } | 
| -template <class Machine> | 
| -class InstX86Idiv | 
| - : public InstX86BaseTernop<Machine, InstX86Base<Machine>::Idiv> { | 
| -public: | 
| - static InstX86Idiv *create(Cfg *Func, Variable *Dest, Operand *Source1, | 
| - Operand *Source2) { | 
| - return new (Func->allocate<InstX86Idiv>()) | 
| - InstX86Idiv(Func, Dest, Source1, Source2); | 
| - } | 
| + private: | 
| + InstX86Psra(Cfg *Func, Variable *Dest, Operand *Source) | 
| + : InstX86BaseBinopXmmShift<InstX86Base::Psra>(Func, Dest, Source) {} | 
| + }; | 
| - void emit(const Cfg *Func) const override; | 
| - void emitIAS(const Cfg *Func) const override; | 
| + class InstX86Pcmpeq | 
| + : public InstX86BaseBinopXmm<InstX86Base::Pcmpeq, true, | 
| + InstX86Base::SseSuffix::Integral> { | 
| + public: | 
| + static InstX86Pcmpeq *create(Cfg *Func, Variable *Dest, Operand *Source) { | 
| + return new (Func->allocate<InstX86Pcmpeq>()) | 
| + InstX86Pcmpeq(Func, Dest, Source); | 
| + } | 
| -private: | 
| - InstX86Idiv(Cfg *Func, Variable *Dest, Operand *Source1, Operand *Source2) | 
| - : InstX86BaseTernop<Machine, InstX86Base<Machine>::Idiv>( | 
| - Func, Dest, Source1, Source2) {} | 
| -}; | 
| + private: | 
| + InstX86Pcmpeq(Cfg *Func, Variable *Dest, Operand *Source) | 
| + : InstX86BaseBinopXmm<InstX86Base::Pcmpeq, true, | 
| + InstX86Base::SseSuffix::Integral>(Func, Dest, | 
| + Source) {} | 
| + }; | 
| -template <class Machine> | 
| -class InstX86Div | 
| - : public InstX86BaseTernop<Machine, InstX86Base<Machine>::Div> { | 
| -public: | 
| - static InstX86Div *create(Cfg *Func, Variable *Dest, Operand *Source1, | 
| - Operand *Source2) { | 
| - return new (Func->allocate<InstX86Div>()) | 
| - InstX86Div(Func, Dest, Source1, Source2); | 
| - } | 
| + class InstX86Pcmpgt | 
| + : public InstX86BaseBinopXmm<InstX86Base::Pcmpgt, true, | 
| + InstX86Base::SseSuffix::Integral> { | 
| + public: | 
| + static InstX86Pcmpgt *create(Cfg *Func, Variable *Dest, Operand *Source) { | 
| + return new (Func->allocate<InstX86Pcmpgt>()) | 
| + InstX86Pcmpgt(Func, Dest, Source); | 
| + } | 
| - void emit(const Cfg *Func) const override; | 
| - void emitIAS(const Cfg *Func) const override; | 
| + private: | 
| + InstX86Pcmpgt(Cfg *Func, Variable *Dest, Operand *Source) | 
| + : InstX86BaseBinopXmm<InstX86Base::Pcmpgt, true, | 
| + InstX86Base::SseSuffix::Integral>(Func, Dest, | 
| + Source) {} | 
| + }; | 
| -private: | 
| - InstX86Div(Cfg *Func, Variable *Dest, Operand *Source1, Operand *Source2) | 
| - : InstX86BaseTernop<Machine, InstX86Base<Machine>::Div>( | 
| - Func, Dest, Source1, Source2) {} | 
| -}; | 
| + /// movss is only a binary operation when the source and dest operands are | 
| + /// both registers (the high bits of dest are left untouched). In other cases, | 
| + /// it behaves like a copy (mov-like) operation (and the high bits of dest are | 
| + /// cleared). InstX86Movss will assert that both its source and dest operands | 
| + /// are registers, so the lowering code should use _mov instead of _movss in | 
| + /// cases where a copy operation is intended. | 
| + class InstX86MovssRegs | 
| + : public InstX86BaseBinopXmm<InstX86Base::MovssRegs, false, | 
| + InstX86Base::SseSuffix::None> { | 
| + public: | 
| + static InstX86MovssRegs *create(Cfg *Func, Variable *Dest, | 
| + Operand *Source) { | 
| + return new (Func->allocate<InstX86MovssRegs>()) | 
| + InstX86MovssRegs(Func, Dest, Source); | 
| + } | 
| -template <class Machine> | 
| -class InstX86Insertps | 
| - : public InstX86BaseTernop<Machine, InstX86Base<Machine>::Insertps> { | 
| -public: | 
| - static InstX86Insertps *create(Cfg *Func, Variable *Dest, Operand *Source1, | 
| - Operand *Source2) { | 
| - return new (Func->allocate<InstX86Insertps>()) | 
| - InstX86Insertps(Func, Dest, Source1, Source2); | 
| - } | 
| + void emitIAS(const Cfg *Func) const override; | 
| - void emitIAS(const Cfg *Func) const override; | 
| + private: | 
| + InstX86MovssRegs(Cfg *Func, Variable *Dest, Operand *Source) | 
| + : InstX86BaseBinopXmm<InstX86Base::MovssRegs, false, | 
| + InstX86Base::SseSuffix::None>(Func, Dest, | 
| + Source) {} | 
| + }; | 
| -private: | 
| - InstX86Insertps(Cfg *Func, Variable *Dest, Operand *Source1, Operand *Source2) | 
| - : InstX86BaseTernop<Machine, InstX86Base<Machine>::Insertps>( | 
| - Func, Dest, Source1, Source2) {} | 
| -}; | 
| + class InstX86Idiv : public InstX86BaseTernop<InstX86Base::Idiv> { | 
| + public: | 
| + static InstX86Idiv *create(Cfg *Func, Variable *Dest, Operand *Source1, | 
| + Operand *Source2) { | 
| + return new (Func->allocate<InstX86Idiv>()) | 
| + InstX86Idiv(Func, Dest, Source1, Source2); | 
| + } | 
| + | 
| + void emit(const Cfg *Func) const override; | 
| + void emitIAS(const Cfg *Func) const override; | 
| + | 
| + private: | 
| + InstX86Idiv(Cfg *Func, Variable *Dest, Operand *Source1, Operand *Source2) | 
| + : InstX86BaseTernop<InstX86Base::Idiv>(Func, Dest, Source1, Source2) {} | 
| + }; | 
| -template <class Machine> | 
| -class InstX86Pinsr | 
| - : public InstX86BaseTernop<Machine, InstX86Base<Machine>::Pinsr> { | 
| -public: | 
| - static InstX86Pinsr *create(Cfg *Func, Variable *Dest, Operand *Source1, | 
| + class InstX86Div : public InstX86BaseTernop<InstX86Base::Div> { | 
| + public: | 
| + static InstX86Div *create(Cfg *Func, Variable *Dest, Operand *Source1, | 
| Operand *Source2) { | 
| - // pinsrb and pinsrd are SSE4.1 instructions. | 
| - assert(Dest->getType() == IceType_v8i16 || | 
| - Dest->getType() == IceType_v8i1 || | 
| - InstX86Base<Machine>::getTarget(Func)->getInstructionSet() >= | 
| - InstX86Base<Machine>::Traits::SSE4_1); | 
| - return new (Func->allocate<InstX86Pinsr>()) | 
| - InstX86Pinsr(Func, Dest, Source1, Source2); | 
| - } | 
| + return new (Func->allocate<InstX86Div>()) | 
| + InstX86Div(Func, Dest, Source1, Source2); | 
| + } | 
| - void emit(const Cfg *Func) const override; | 
| - void emitIAS(const Cfg *Func) const override; | 
| + void emit(const Cfg *Func) const override; | 
| + void emitIAS(const Cfg *Func) const override; | 
| -private: | 
| - InstX86Pinsr(Cfg *Func, Variable *Dest, Operand *Source1, Operand *Source2) | 
| - : InstX86BaseTernop<Machine, InstX86Base<Machine>::Pinsr>( | 
| - Func, Dest, Source1, Source2) {} | 
| -}; | 
| + private: | 
| + InstX86Div(Cfg *Func, Variable *Dest, Operand *Source1, Operand *Source2) | 
| + : InstX86BaseTernop<InstX86Base::Div>(Func, Dest, Source1, Source2) {} | 
| + }; | 
| -template <class Machine> | 
| -class InstX86Shufps | 
| - : public InstX86BaseTernop<Machine, InstX86Base<Machine>::Shufps> { | 
| -public: | 
| - static InstX86Shufps *create(Cfg *Func, Variable *Dest, Operand *Source1, | 
| - Operand *Source2) { | 
| - return new (Func->allocate<InstX86Shufps>()) | 
| - InstX86Shufps(Func, Dest, Source1, Source2); | 
| - } | 
| + class InstX86Insertps : public InstX86BaseTernop<InstX86Base::Insertps> { | 
| + public: | 
| + static InstX86Insertps *create(Cfg *Func, Variable *Dest, Operand *Source1, | 
| + Operand *Source2) { | 
| + return new (Func->allocate<InstX86Insertps>()) | 
| + InstX86Insertps(Func, Dest, Source1, Source2); | 
| + } | 
| - void emitIAS(const Cfg *Func) const override; | 
| + void emitIAS(const Cfg *Func) const override; | 
| -private: | 
| - InstX86Shufps(Cfg *Func, Variable *Dest, Operand *Source1, Operand *Source2) | 
| - : InstX86BaseTernop<Machine, InstX86Base<Machine>::Shufps>( | 
| - Func, Dest, Source1, Source2) {} | 
| -}; | 
| + private: | 
| + InstX86Insertps(Cfg *Func, Variable *Dest, Operand *Source1, | 
| + Operand *Source2) | 
| + : InstX86BaseTernop<InstX86Base::Insertps>(Func, Dest, Source1, | 
| + Source2) {} | 
| + }; | 
| -template <class Machine> | 
| -class InstX86Blendvps | 
| - : public InstX86BaseTernop<Machine, InstX86Base<Machine>::Blendvps> { | 
| -public: | 
| - static InstX86Blendvps *create(Cfg *Func, Variable *Dest, Operand *Source1, | 
| - Operand *Source2) { | 
| - assert(InstX86Base<Machine>::getTarget(Func)->getInstructionSet() >= | 
| - InstX86Base<Machine>::Traits::SSE4_1); | 
| - return new (Func->allocate<InstX86Blendvps>()) | 
| - InstX86Blendvps(Func, Dest, Source1, Source2); | 
| - } | 
| + class InstX86Pinsr : public InstX86BaseTernop<InstX86Base::Pinsr> { | 
| + public: | 
| + static InstX86Pinsr *create(Cfg *Func, Variable *Dest, Operand *Source1, | 
| + Operand *Source2) { | 
| + // pinsrb and pinsrd are SSE4.1 instructions. | 
| + assert( | 
| + Dest->getType() == IceType_v8i16 || Dest->getType() == IceType_v8i1 || | 
| + InstX86Base::getTarget(Func)->getInstructionSet() >= Traits::SSE4_1); | 
| + return new (Func->allocate<InstX86Pinsr>()) | 
| + InstX86Pinsr(Func, Dest, Source1, Source2); | 
| + } | 
| - void emit(const Cfg *Func) const override; | 
| - void emitIAS(const Cfg *Fund) const override; | 
| + void emit(const Cfg *Func) const override; | 
| + void emitIAS(const Cfg *Func) const override; | 
| -private: | 
| - InstX86Blendvps(Cfg *Func, Variable *Dest, Operand *Source1, Operand *Source2) | 
| - : InstX86BaseTernop<Machine, InstX86Base<Machine>::Blendvps>( | 
| - Func, Dest, Source1, Source2) {} | 
| -}; | 
| + private: | 
| + InstX86Pinsr(Cfg *Func, Variable *Dest, Operand *Source1, Operand *Source2) | 
| + : InstX86BaseTernop<InstX86Base::Pinsr>(Func, Dest, Source1, Source2) {} | 
| + }; | 
| -template <class Machine> | 
| -class InstX86Pblendvb | 
| - : public InstX86BaseTernop<Machine, InstX86Base<Machine>::Pblendvb> { | 
| -public: | 
| - static InstX86Pblendvb *create(Cfg *Func, Variable *Dest, Operand *Source1, | 
| + class InstX86Shufps : public InstX86BaseTernop<InstX86Base::Shufps> { | 
| + public: | 
| + static InstX86Shufps *create(Cfg *Func, Variable *Dest, Operand *Source1, | 
| Operand *Source2) { | 
| - assert(InstX86Base<Machine>::getTarget(Func)->getInstructionSet() >= | 
| - InstX86Base<Machine>::Traits::SSE4_1); | 
| - return new (Func->allocate<InstX86Pblendvb>()) | 
| - InstX86Pblendvb(Func, Dest, Source1, Source2); | 
| - } | 
| - | 
| - void emit(const Cfg *Func) const override; | 
| - void emitIAS(const Cfg *Func) const override; | 
| + return new (Func->allocate<InstX86Shufps>()) | 
| + InstX86Shufps(Func, Dest, Source1, Source2); | 
| + } | 
| -private: | 
| - InstX86Pblendvb(Cfg *Func, Variable *Dest, Operand *Source1, Operand *Source2) | 
| - : InstX86BaseTernop<Machine, InstX86Base<Machine>::Pblendvb>( | 
| - Func, Dest, Source1, Source2) {} | 
| -}; | 
| + void emitIAS(const Cfg *Func) const override; | 
| -template <class Machine> | 
| -class InstX86Pextr | 
| - : public InstX86BaseThreeAddressop<Machine, InstX86Base<Machine>::Pextr> { | 
| -public: | 
| - static InstX86Pextr *create(Cfg *Func, Variable *Dest, Operand *Source0, | 
| - Operand *Source1) { | 
| - assert(Source0->getType() == IceType_v8i16 || | 
| - Source0->getType() == IceType_v8i1 || | 
| - InstX86Base<Machine>::getTarget(Func)->getInstructionSet() >= | 
| - InstX86Base<Machine>::Traits::SSE4_1); | 
| - return new (Func->allocate<InstX86Pextr>()) | 
| - InstX86Pextr(Func, Dest, Source0, Source1); | 
| - } | 
| + private: | 
| + InstX86Shufps(Cfg *Func, Variable *Dest, Operand *Source1, Operand *Source2) | 
| + : InstX86BaseTernop<InstX86Base::Shufps>(Func, Dest, Source1, Source2) { | 
| + } | 
| + }; | 
| - void emit(const Cfg *Func) const override; | 
| - void emitIAS(const Cfg *Func) const override; | 
| + class InstX86Blendvps : public InstX86BaseTernop<InstX86Base::Blendvps> { | 
| + public: | 
| + static InstX86Blendvps *create(Cfg *Func, Variable *Dest, Operand *Source1, | 
| + Operand *Source2) { | 
| + assert(InstX86Base::getTarget(Func)->getInstructionSet() >= | 
| + Traits::SSE4_1); | 
| + return new (Func->allocate<InstX86Blendvps>()) | 
| + InstX86Blendvps(Func, Dest, Source1, Source2); | 
| + } | 
| -private: | 
| - InstX86Pextr(Cfg *Func, Variable *Dest, Operand *Source0, Operand *Source1) | 
| - : InstX86BaseThreeAddressop<Machine, InstX86Base<Machine>::Pextr>( | 
| - Func, Dest, Source0, Source1) {} | 
| -}; | 
| + void emit(const Cfg *Func) const override; | 
| + void emitIAS(const Cfg *Fund) const override; | 
| -template <class Machine> | 
| -class InstX86Pshufd | 
| - : public InstX86BaseThreeAddressop<Machine, InstX86Base<Machine>::Pshufd> { | 
| -public: | 
| - static InstX86Pshufd *create(Cfg *Func, Variable *Dest, Operand *Source0, | 
| - Operand *Source1) { | 
| - return new (Func->allocate<InstX86Pshufd>()) | 
| - InstX86Pshufd(Func, Dest, Source0, Source1); | 
| - } | 
| + private: | 
| + InstX86Blendvps(Cfg *Func, Variable *Dest, Operand *Source1, | 
| + Operand *Source2) | 
| + : InstX86BaseTernop<InstX86Base::Blendvps>(Func, Dest, Source1, | 
| + Source2) {} | 
| + }; | 
| - void emitIAS(const Cfg *Func) const override; | 
| + class InstX86Pblendvb : public InstX86BaseTernop<InstX86Base::Pblendvb> { | 
| + public: | 
| + static InstX86Pblendvb *create(Cfg *Func, Variable *Dest, Operand *Source1, | 
| + Operand *Source2) { | 
| + assert(InstX86Base::getTarget(Func)->getInstructionSet() >= | 
| + Traits::SSE4_1); | 
| + return new (Func->allocate<InstX86Pblendvb>()) | 
| + InstX86Pblendvb(Func, Dest, Source1, Source2); | 
| + } | 
| -private: | 
| - InstX86Pshufd(Cfg *Func, Variable *Dest, Operand *Source0, Operand *Source1) | 
| - : InstX86BaseThreeAddressop<Machine, InstX86Base<Machine>::Pshufd>( | 
| - Func, Dest, Source0, Source1) {} | 
| -}; | 
| + void emit(const Cfg *Func) const override; | 
| + void emitIAS(const Cfg *Func) const override; | 
| -/// Base class for a lockable x86-32 instruction (emits a locked prefix). | 
| -template <class Machine> | 
| -class InstX86BaseLockable : public InstX86Base<Machine> { | 
| - InstX86BaseLockable() = delete; | 
| - InstX86BaseLockable(const InstX86BaseLockable &) = delete; | 
| - InstX86BaseLockable &operator=(const InstX86BaseLockable &) = delete; | 
| - | 
| -protected: | 
| - bool Locked; | 
| - | 
| - InstX86BaseLockable(Cfg *Func, | 
| - typename InstX86Base<Machine>::InstKindX86 Kind, | 
| - SizeT Maxsrcs, Variable *Dest, bool Locked) | 
| - : InstX86Base<Machine>(Func, Kind, Maxsrcs, Dest), Locked(Locked) { | 
| - // Assume that such instructions are used for Atomics and be careful with | 
| - // optimizations. | 
| - this->HasSideEffects = Locked; | 
| - } | 
| -}; | 
| + private: | 
| + InstX86Pblendvb(Cfg *Func, Variable *Dest, Operand *Source1, | 
| + Operand *Source2) | 
| + : InstX86BaseTernop<InstX86Base::Pblendvb>(Func, Dest, Source1, | 
| + Source2) {} | 
| + }; | 
| -/// Mul instruction - unsigned multiply. | 
| -template <class Machine> class InstX86Mul final : public InstX86Base<Machine> { | 
| - InstX86Mul() = delete; | 
| - InstX86Mul(const InstX86Mul &) = delete; | 
| - InstX86Mul &operator=(const InstX86Mul &) = delete; | 
| - | 
| -public: | 
| - static InstX86Mul *create(Cfg *Func, Variable *Dest, Variable *Source1, | 
| - Operand *Source2) { | 
| - return new (Func->allocate<InstX86Mul>()) | 
| - InstX86Mul(Func, Dest, Source1, Source2); | 
| - } | 
| - void emit(const Cfg *Func) const override; | 
| - void emitIAS(const Cfg *Func) const override; | 
| - void dump(const Cfg *Func) const override; | 
| - static bool classof(const Inst *Inst) { | 
| - return InstX86Base<Machine>::isClassof(Inst, InstX86Base<Machine>::Mul); | 
| - } | 
| + class InstX86Pextr : public InstX86BaseThreeAddressop<InstX86Base::Pextr> { | 
| + public: | 
| + static InstX86Pextr *create(Cfg *Func, Variable *Dest, Operand *Source0, | 
| + Operand *Source1) { | 
| + assert(Source0->getType() == IceType_v8i16 || | 
| + Source0->getType() == IceType_v8i1 || | 
| + InstX86Base::getTarget(Func)->getInstructionSet() >= | 
| + Traits::SSE4_1); | 
| + return new (Func->allocate<InstX86Pextr>()) | 
| + InstX86Pextr(Func, Dest, Source0, Source1); | 
| + } | 
| -private: | 
| - InstX86Mul(Cfg *Func, Variable *Dest, Variable *Source1, Operand *Source2); | 
| -}; | 
| + void emit(const Cfg *Func) const override; | 
| + void emitIAS(const Cfg *Func) const override; | 
| -/// Shld instruction - shift across a pair of operands. | 
| -template <class Machine> class InstX86Shld final : public InstX86Base<Machine> { | 
| - InstX86Shld() = delete; | 
| - InstX86Shld(const InstX86Shld &) = delete; | 
| - InstX86Shld &operator=(const InstX86Shld &) = delete; | 
| - | 
| -public: | 
| - static InstX86Shld *create(Cfg *Func, Variable *Dest, Variable *Source1, | 
| - Operand *Source2) { | 
| - return new (Func->allocate<InstX86Shld>()) | 
| - InstX86Shld(Func, Dest, Source1, Source2); | 
| - } | 
| - void emit(const Cfg *Func) const override; | 
| - void emitIAS(const Cfg *Func) const override; | 
| - void dump(const Cfg *Func) const override; | 
| - static bool classof(const Inst *Inst) { | 
| - return InstX86Base<Machine>::isClassof(Inst, InstX86Base<Machine>::Shld); | 
| - } | 
| + private: | 
| + InstX86Pextr(Cfg *Func, Variable *Dest, Operand *Source0, Operand *Source1) | 
| + : InstX86BaseThreeAddressop<InstX86Base::Pextr>(Func, Dest, Source0, | 
| + Source1) {} | 
| + }; | 
| -private: | 
| - InstX86Shld(Cfg *Func, Variable *Dest, Variable *Source1, Operand *Source2); | 
| -}; | 
| + class InstX86Pshufd : public InstX86BaseThreeAddressop<InstX86Base::Pshufd> { | 
| + public: | 
| + static InstX86Pshufd *create(Cfg *Func, Variable *Dest, Operand *Source0, | 
| + Operand *Source1) { | 
| + return new (Func->allocate<InstX86Pshufd>()) | 
| + InstX86Pshufd(Func, Dest, Source0, Source1); | 
| + } | 
| -/// Shrd instruction - shift across a pair of operands. | 
| -template <class Machine> class InstX86Shrd final : public InstX86Base<Machine> { | 
| - InstX86Shrd() = delete; | 
| - InstX86Shrd(const InstX86Shrd &) = delete; | 
| - InstX86Shrd &operator=(const InstX86Shrd &) = delete; | 
| - | 
| -public: | 
| - static InstX86Shrd *create(Cfg *Func, Variable *Dest, Variable *Source1, | 
| - Operand *Source2) { | 
| - return new (Func->allocate<InstX86Shrd>()) | 
| - InstX86Shrd(Func, Dest, Source1, Source2); | 
| - } | 
| - void emit(const Cfg *Func) const override; | 
| - void emitIAS(const Cfg *Func) const override; | 
| - void dump(const Cfg *Func) const override; | 
| - static bool classof(const Inst *Inst) { | 
| - return InstX86Base<Machine>::isClassof(Inst, InstX86Base<Machine>::Shrd); | 
| - } | 
| + void emitIAS(const Cfg *Func) const override; | 
| -private: | 
| - InstX86Shrd(Cfg *Func, Variable *Dest, Variable *Source1, Operand *Source2); | 
| -}; | 
| + private: | 
| + InstX86Pshufd(Cfg *Func, Variable *Dest, Operand *Source0, Operand *Source1) | 
| + : InstX86BaseThreeAddressop<InstX86Base::Pshufd>(Func, Dest, Source0, | 
| + Source1) {} | 
| + }; | 
| -/// Conditional move instruction. | 
| -template <class Machine> class InstX86Cmov final : public InstX86Base<Machine> { | 
| - InstX86Cmov() = delete; | 
| - InstX86Cmov(const InstX86Cmov &) = delete; | 
| - InstX86Cmov &operator=(const InstX86Cmov &) = delete; | 
| - | 
| -public: | 
| - static InstX86Cmov * | 
| - create(Cfg *Func, Variable *Dest, Operand *Source, | 
| - typename InstX86Base<Machine>::Traits::Cond::BrCond Cond) { | 
| - return new (Func->allocate<InstX86Cmov>()) | 
| - InstX86Cmov(Func, Dest, Source, Cond); | 
| - } | 
| - void emit(const Cfg *Func) const override; | 
| - void emitIAS(const Cfg *Func) const override; | 
| - void dump(const Cfg *Func) const override; | 
| - static bool classof(const Inst *Inst) { | 
| - return InstX86Base<Machine>::isClassof(Inst, InstX86Base<Machine>::Cmov); | 
| - } | 
| + /// Base class for a lockable x86-32 instruction (emits a locked prefix). | 
| + class InstX86BaseLockable : public InstX86Base { | 
| + InstX86BaseLockable() = delete; | 
| + InstX86BaseLockable(const InstX86BaseLockable &) = delete; | 
| + InstX86BaseLockable &operator=(const InstX86BaseLockable &) = delete; | 
| + | 
| + protected: | 
| + bool Locked; | 
| + | 
| + InstX86BaseLockable(Cfg *Func, typename InstX86Base::InstKindX86 Kind, | 
| + SizeT Maxsrcs, Variable *Dest, bool Locked) | 
| + : InstX86Base(Func, Kind, Maxsrcs, Dest), Locked(Locked) { | 
| + // Assume that such instructions are used for Atomics and be careful with | 
| + // optimizations. | 
| + this->HasSideEffects = Locked; | 
| + } | 
| + }; | 
| -private: | 
| - InstX86Cmov(Cfg *Func, Variable *Dest, Operand *Source, | 
| - typename InstX86Base<Machine>::Traits::Cond::BrCond Cond); | 
| + /// Mul instruction - unsigned multiply. | 
| + class InstX86Mul final : public InstX86Base { | 
| + InstX86Mul() = delete; | 
| + InstX86Mul(const InstX86Mul &) = delete; | 
| + InstX86Mul &operator=(const InstX86Mul &) = delete; | 
| - typename InstX86Base<Machine>::Traits::Cond::BrCond Condition; | 
| -}; | 
| + public: | 
| + static InstX86Mul *create(Cfg *Func, Variable *Dest, Variable *Source1, | 
| + Operand *Source2) { | 
| + return new (Func->allocate<InstX86Mul>()) | 
| + InstX86Mul(Func, Dest, Source1, Source2); | 
| + } | 
| + void emit(const Cfg *Func) const override; | 
| + void emitIAS(const Cfg *Func) const override; | 
| + void dump(const Cfg *Func) const override; | 
| + static bool classof(const Inst *Inst) { | 
| + return InstX86Base::isClassof(Inst, InstX86Base::Mul); | 
| + } | 
| -/// Cmpps instruction - compare packed singled-precision floating point values | 
| -template <class Machine> | 
| -class InstX86Cmpps final : public InstX86Base<Machine> { | 
| - InstX86Cmpps() = delete; | 
| - InstX86Cmpps(const InstX86Cmpps &) = delete; | 
| - InstX86Cmpps &operator=(const InstX86Cmpps &) = delete; | 
| - | 
| -public: | 
| - static InstX86Cmpps * | 
| - create(Cfg *Func, Variable *Dest, Operand *Source, | 
| - typename InstX86Base<Machine>::Traits::Cond::CmppsCond Condition) { | 
| - return new (Func->allocate<InstX86Cmpps>()) | 
| - InstX86Cmpps(Func, Dest, Source, Condition); | 
| - } | 
| - void emit(const Cfg *Func) const override; | 
| - void emitIAS(const Cfg *Func) const override; | 
| - void dump(const Cfg *Func) const override; | 
| - static bool classof(const Inst *Inst) { | 
| - return InstX86Base<Machine>::isClassof(Inst, InstX86Base<Machine>::Cmpps); | 
| - } | 
| + private: | 
| + InstX86Mul(Cfg *Func, Variable *Dest, Variable *Source1, Operand *Source2); | 
| + }; | 
| -private: | 
| - InstX86Cmpps(Cfg *Func, Variable *Dest, Operand *Source, | 
| - typename InstX86Base<Machine>::Traits::Cond::CmppsCond Cond); | 
| + /// Shld instruction - shift across a pair of operands. | 
| + class InstX86Shld final : public InstX86Base { | 
| + InstX86Shld() = delete; | 
| + InstX86Shld(const InstX86Shld &) = delete; | 
| + InstX86Shld &operator=(const InstX86Shld &) = delete; | 
| - typename InstX86Base<Machine>::Traits::Cond::CmppsCond Condition; | 
| -}; | 
| + public: | 
| + static InstX86Shld *create(Cfg *Func, Variable *Dest, Variable *Source1, | 
| + Operand *Source2) { | 
| + return new (Func->allocate<InstX86Shld>()) | 
| + InstX86Shld(Func, Dest, Source1, Source2); | 
| + } | 
| + void emit(const Cfg *Func) const override; | 
| + void emitIAS(const Cfg *Func) const override; | 
| + void dump(const Cfg *Func) const override; | 
| + static bool classof(const Inst *Inst) { | 
| + return InstX86Base::isClassof(Inst, InstX86Base::Shld); | 
| + } | 
| -/// Cmpxchg instruction - cmpxchg <dest>, <desired> will compare if <dest> | 
| -/// equals eax. If so, the ZF is set and <desired> is stored in <dest>. If not, | 
| -/// ZF is cleared and <dest> is copied to eax (or subregister). <dest> can be a | 
| -/// register or memory, while <desired> must be a register. It is the user's | 
| -/// responsibility to mark eax with a FakeDef. | 
| -template <class Machine> | 
| -class InstX86Cmpxchg final : public InstX86BaseLockable<Machine> { | 
| - InstX86Cmpxchg() = delete; | 
| - InstX86Cmpxchg(const InstX86Cmpxchg &) = delete; | 
| - InstX86Cmpxchg &operator=(const InstX86Cmpxchg &) = delete; | 
| - | 
| -public: | 
| - static InstX86Cmpxchg *create(Cfg *Func, Operand *DestOrAddr, Variable *Eax, | 
| - Variable *Desired, bool Locked) { | 
| - return new (Func->allocate<InstX86Cmpxchg>()) | 
| - InstX86Cmpxchg(Func, DestOrAddr, Eax, Desired, Locked); | 
| - } | 
| - void emit(const Cfg *Func) const override; | 
| - void emitIAS(const Cfg *Func) const override; | 
| - void dump(const Cfg *Func) const override; | 
| - static bool classof(const Inst *Inst) { | 
| - return InstX86Base<Machine>::isClassof(Inst, InstX86Base<Machine>::Cmpxchg); | 
| - } | 
| + private: | 
| + InstX86Shld(Cfg *Func, Variable *Dest, Variable *Source1, Operand *Source2); | 
| + }; | 
| -private: | 
| - InstX86Cmpxchg(Cfg *Func, Operand *DestOrAddr, Variable *Eax, | 
| - Variable *Desired, bool Locked); | 
| -}; | 
| + /// Shrd instruction - shift across a pair of operands. | 
| + class InstX86Shrd final : public InstX86Base { | 
| + InstX86Shrd() = delete; | 
| + InstX86Shrd(const InstX86Shrd &) = delete; | 
| + InstX86Shrd &operator=(const InstX86Shrd &) = delete; | 
| -/// Cmpxchg8b instruction - cmpxchg8b <m64> will compare if <m64> equals | 
| -/// edx:eax. If so, the ZF is set and ecx:ebx is stored in <m64>. If not, ZF is | 
| -/// cleared and <m64> is copied to edx:eax. The caller is responsible for | 
| -/// inserting FakeDefs to mark edx and eax as modified. <m64> must be a memory | 
| -/// operand. | 
| -template <class Machine> | 
| -class InstX86Cmpxchg8b final : public InstX86BaseLockable<Machine> { | 
| - InstX86Cmpxchg8b() = delete; | 
| - InstX86Cmpxchg8b(const InstX86Cmpxchg8b &) = delete; | 
| - InstX86Cmpxchg8b &operator=(const InstX86Cmpxchg8b &) = delete; | 
| - | 
| -public: | 
| - static InstX86Cmpxchg8b * | 
| - create(Cfg *Func, typename InstX86Base<Machine>::Traits::X86OperandMem *Dest, | 
| - Variable *Edx, Variable *Eax, Variable *Ecx, Variable *Ebx, | 
| - bool Locked) { | 
| - return new (Func->allocate<InstX86Cmpxchg8b>()) | 
| - InstX86Cmpxchg8b(Func, Dest, Edx, Eax, Ecx, Ebx, Locked); | 
| - } | 
| - void emit(const Cfg *Func) const override; | 
| - void emitIAS(const Cfg *Func) const override; | 
| - void dump(const Cfg *Func) const override; | 
| - static bool classof(const Inst *Inst) { | 
| - return InstX86Base<Machine>::isClassof(Inst, | 
| - InstX86Base<Machine>::Cmpxchg8b); | 
| - } | 
| + public: | 
| + static InstX86Shrd *create(Cfg *Func, Variable *Dest, Variable *Source1, | 
| + Operand *Source2) { | 
| + return new (Func->allocate<InstX86Shrd>()) | 
| + InstX86Shrd(Func, Dest, Source1, Source2); | 
| + } | 
| + void emit(const Cfg *Func) const override; | 
| + void emitIAS(const Cfg *Func) const override; | 
| + void dump(const Cfg *Func) const override; | 
| + static bool classof(const Inst *Inst) { | 
| + return InstX86Base::isClassof(Inst, InstX86Base::Shrd); | 
| + } | 
| -private: | 
| - InstX86Cmpxchg8b(Cfg *Func, | 
| - typename InstX86Base<Machine>::Traits::X86OperandMem *Dest, | 
| - Variable *Edx, Variable *Eax, Variable *Ecx, Variable *Ebx, | 
| - bool Locked); | 
| -}; | 
| + private: | 
| + InstX86Shrd(Cfg *Func, Variable *Dest, Variable *Source1, Operand *Source2); | 
| + }; | 
| -/// Cvt instruction - wrapper for cvtsX2sY where X and Y are in {s,d,i} as | 
| -/// appropriate. s=float, d=double, i=int. X and Y are determined from dest/src | 
| -/// types. Sign and zero extension on the integer operand needs to be done | 
| -/// separately. | 
| -template <class Machine> class InstX86Cvt final : public InstX86Base<Machine> { | 
| - InstX86Cvt() = delete; | 
| - InstX86Cvt(const InstX86Cvt &) = delete; | 
| - InstX86Cvt &operator=(const InstX86Cvt &) = delete; | 
| - | 
| -public: | 
| - enum CvtVariant { Si2ss, Tss2si, Float2float, Dq2ps, Tps2dq }; | 
| - static InstX86Cvt *create(Cfg *Func, Variable *Dest, Operand *Source, | 
| - CvtVariant Variant) { | 
| - return new (Func->allocate<InstX86Cvt>()) | 
| - InstX86Cvt(Func, Dest, Source, Variant); | 
| - } | 
| - void emit(const Cfg *Func) const override; | 
| - void emitIAS(const Cfg *Func) const override; | 
| - void dump(const Cfg *Func) const override; | 
| - static bool classof(const Inst *Inst) { | 
| - return InstX86Base<Machine>::isClassof(Inst, InstX86Base<Machine>::Cvt); | 
| - } | 
| - bool isTruncating() const { return Variant == Tss2si || Variant == Tps2dq; } | 
| + /// Conditional move instruction. | 
| + class InstX86Cmov final : public InstX86Base { | 
| + InstX86Cmov() = delete; | 
| + InstX86Cmov(const InstX86Cmov &) = delete; | 
| + InstX86Cmov &operator=(const InstX86Cmov &) = delete; | 
| + | 
| + public: | 
| + static InstX86Cmov *create(Cfg *Func, Variable *Dest, Operand *Source, | 
| + BrCond Cond) { | 
| + return new (Func->allocate<InstX86Cmov>()) | 
| + InstX86Cmov(Func, Dest, Source, Cond); | 
| + } | 
| + void emit(const Cfg *Func) const override; | 
| + void emitIAS(const Cfg *Func) const override; | 
| + void dump(const Cfg *Func) const override; | 
| + static bool classof(const Inst *Inst) { | 
| + return InstX86Base::isClassof(Inst, InstX86Base::Cmov); | 
| + } | 
| -private: | 
| - CvtVariant Variant; | 
| - InstX86Cvt(Cfg *Func, Variable *Dest, Operand *Source, CvtVariant Variant); | 
| -}; | 
| + private: | 
| + InstX86Cmov(Cfg *Func, Variable *Dest, Operand *Source, BrCond Cond); | 
| -/// cmp - Integer compare instruction. | 
| -template <class Machine> class InstX86Icmp final : public InstX86Base<Machine> { | 
| - InstX86Icmp() = delete; | 
| - InstX86Icmp(const InstX86Icmp &) = delete; | 
| - InstX86Icmp &operator=(const InstX86Icmp &) = delete; | 
| + BrCond Condition; | 
| + }; | 
| -public: | 
| - static InstX86Icmp *create(Cfg *Func, Operand *Src1, Operand *Src2) { | 
| - return new (Func->allocate<InstX86Icmp>()) InstX86Icmp(Func, Src1, Src2); | 
| - } | 
| - void emit(const Cfg *Func) const override; | 
| - void emitIAS(const Cfg *Func) const override; | 
| - void dump(const Cfg *Func) const override; | 
| - static bool classof(const Inst *Inst) { | 
| - return InstX86Base<Machine>::isClassof(Inst, InstX86Base<Machine>::Icmp); | 
| - } | 
| + /// Cmpps instruction - compare packed singled-precision floating point values | 
| + class InstX86Cmpps final : public InstX86Base { | 
| + InstX86Cmpps() = delete; | 
| + InstX86Cmpps(const InstX86Cmpps &) = delete; | 
| + InstX86Cmpps &operator=(const InstX86Cmpps &) = delete; | 
| + | 
| + public: | 
| + static InstX86Cmpps *create(Cfg *Func, Variable *Dest, Operand *Source, | 
| + CmppsCond Condition) { | 
| + return new (Func->allocate<InstX86Cmpps>()) | 
| + InstX86Cmpps(Func, Dest, Source, Condition); | 
| + } | 
| + void emit(const Cfg *Func) const override; | 
| + void emitIAS(const Cfg *Func) const override; | 
| + void dump(const Cfg *Func) const override; | 
| + static bool classof(const Inst *Inst) { | 
| + return InstX86Base::isClassof(Inst, InstX86Base::Cmpps); | 
| + } | 
| -private: | 
| - InstX86Icmp(Cfg *Func, Operand *Src1, Operand *Src2); | 
| -}; | 
| + private: | 
| + InstX86Cmpps(Cfg *Func, Variable *Dest, Operand *Source, CmppsCond Cond); | 
| -/// ucomiss/ucomisd - floating-point compare instruction. | 
| -template <class Machine> | 
| -class InstX86Ucomiss final : public InstX86Base<Machine> { | 
| - InstX86Ucomiss() = delete; | 
| - InstX86Ucomiss(const InstX86Ucomiss &) = delete; | 
| - InstX86Ucomiss &operator=(const InstX86Ucomiss &) = delete; | 
| - | 
| -public: | 
| - static InstX86Ucomiss *create(Cfg *Func, Operand *Src1, Operand *Src2) { | 
| - return new (Func->allocate<InstX86Ucomiss>()) | 
| - InstX86Ucomiss(Func, Src1, Src2); | 
| - } | 
| - void emit(const Cfg *Func) const override; | 
| - void emitIAS(const Cfg *Func) const override; | 
| - void dump(const Cfg *Func) const override; | 
| - static bool classof(const Inst *Inst) { | 
| - return InstX86Base<Machine>::isClassof(Inst, InstX86Base<Machine>::Ucomiss); | 
| - } | 
| + CmppsCond Condition; | 
| + }; | 
| -private: | 
| - InstX86Ucomiss(Cfg *Func, Operand *Src1, Operand *Src2); | 
| -}; | 
| + /// Cmpxchg instruction - cmpxchg <dest>, <desired> will compare if <dest> | 
| + /// equals eax. If so, the ZF is set and <desired> is stored in <dest>. If | 
| + /// not, ZF is cleared and <dest> is copied to eax (or subregister). <dest> | 
| + /// can be a register or memory, while <desired> must be a register. It is | 
| + /// the user's responsibility to mark eax with a FakeDef. | 
| + class InstX86Cmpxchg final : public InstX86BaseLockable { | 
| + InstX86Cmpxchg() = delete; | 
| + InstX86Cmpxchg(const InstX86Cmpxchg &) = delete; | 
| + InstX86Cmpxchg &operator=(const InstX86Cmpxchg &) = delete; | 
| + | 
| + public: | 
| + static InstX86Cmpxchg *create(Cfg *Func, Operand *DestOrAddr, Variable *Eax, | 
| + Variable *Desired, bool Locked) { | 
| + return new (Func->allocate<InstX86Cmpxchg>()) | 
| + InstX86Cmpxchg(Func, DestOrAddr, Eax, Desired, Locked); | 
| + } | 
| + void emit(const Cfg *Func) const override; | 
| + void emitIAS(const Cfg *Func) const override; | 
| + void dump(const Cfg *Func) const override; | 
| + static bool classof(const Inst *Inst) { | 
| + return InstX86Base::isClassof(Inst, InstX86Base::Cmpxchg); | 
| + } | 
| -/// UD2 instruction. | 
| -template <class Machine> class InstX86UD2 final : public InstX86Base<Machine> { | 
| - InstX86UD2() = delete; | 
| - InstX86UD2(const InstX86UD2 &) = delete; | 
| - InstX86UD2 &operator=(const InstX86UD2 &) = delete; | 
| + private: | 
| + InstX86Cmpxchg(Cfg *Func, Operand *DestOrAddr, Variable *Eax, | 
| + Variable *Desired, bool Locked); | 
| + }; | 
| -public: | 
| - static InstX86UD2 *create(Cfg *Func) { | 
| - return new (Func->allocate<InstX86UD2>()) InstX86UD2(Func); | 
| - } | 
| - void emit(const Cfg *Func) const override; | 
| - void emitIAS(const Cfg *Func) const override; | 
| - void dump(const Cfg *Func) const override; | 
| - static bool classof(const Inst *Inst) { | 
| - return InstX86Base<Machine>::isClassof(Inst, InstX86Base<Machine>::UD2); | 
| - } | 
| + /// Cmpxchg8b instruction - cmpxchg8b <m64> will compare if <m64> equals | 
| + /// edx:eax. If so, the ZF is set and ecx:ebx is stored in <m64>. If not, ZF | 
| + /// is cleared and <m64> is copied to edx:eax. The caller is responsible for | 
| + /// inserting FakeDefs to mark edx and eax as modified. <m64> must be a memory | 
| + /// operand. | 
| + class InstX86Cmpxchg8b final : public InstX86BaseLockable { | 
| + InstX86Cmpxchg8b() = delete; | 
| + InstX86Cmpxchg8b(const InstX86Cmpxchg8b &) = delete; | 
| + InstX86Cmpxchg8b &operator=(const InstX86Cmpxchg8b &) = delete; | 
| + | 
| + public: | 
| + static InstX86Cmpxchg8b *create(Cfg *Func, X86OperandMem *Dest, | 
| + Variable *Edx, Variable *Eax, Variable *Ecx, | 
| + Variable *Ebx, bool Locked) { | 
| + return new (Func->allocate<InstX86Cmpxchg8b>()) | 
| + InstX86Cmpxchg8b(Func, Dest, Edx, Eax, Ecx, Ebx, Locked); | 
| + } | 
| + void emit(const Cfg *Func) const override; | 
| + void emitIAS(const Cfg *Func) const override; | 
| + void dump(const Cfg *Func) const override; | 
| + static bool classof(const Inst *Inst) { | 
| + return InstX86Base::isClassof(Inst, InstX86Base::Cmpxchg8b); | 
| + } | 
| -private: | 
| - explicit InstX86UD2(Cfg *Func); | 
| -}; | 
| + private: | 
| + InstX86Cmpxchg8b(Cfg *Func, X86OperandMem *Dest, Variable *Edx, | 
| + Variable *Eax, Variable *Ecx, Variable *Ebx, bool Locked); | 
| + }; | 
| -/// Test instruction. | 
| -template <class Machine> class InstX86Test final : public InstX86Base<Machine> { | 
| - InstX86Test() = delete; | 
| - InstX86Test(const InstX86Test &) = delete; | 
| - InstX86Test &operator=(const InstX86Test &) = delete; | 
| + /// Cvt instruction - wrapper for cvtsX2sY where X and Y are in {s,d,i} as | 
| + /// appropriate. s=float, d=double, i=int. X and Y are determined from | 
| + /// dest/src types. Sign and zero extension on the integer operand needs to be | 
| + /// done separately. | 
| + class InstX86Cvt final : public InstX86Base { | 
| + InstX86Cvt() = delete; | 
| + InstX86Cvt(const InstX86Cvt &) = delete; | 
| + InstX86Cvt &operator=(const InstX86Cvt &) = delete; | 
| + | 
| + public: | 
| + enum CvtVariant { Si2ss, Tss2si, Float2float, Dq2ps, Tps2dq }; | 
| + static InstX86Cvt *create(Cfg *Func, Variable *Dest, Operand *Source, | 
| + CvtVariant Variant) { | 
| + return new (Func->allocate<InstX86Cvt>()) | 
| + InstX86Cvt(Func, Dest, Source, Variant); | 
| + } | 
| + void emit(const Cfg *Func) const override; | 
| + void emitIAS(const Cfg *Func) const override; | 
| + void dump(const Cfg *Func) const override; | 
| + static bool classof(const Inst *Inst) { | 
| + return InstX86Base::isClassof(Inst, InstX86Base::Cvt); | 
| + } | 
| + bool isTruncating() const { return Variant == Tss2si || Variant == Tps2dq; } | 
| -public: | 
| - static InstX86Test *create(Cfg *Func, Operand *Source1, Operand *Source2) { | 
| - return new (Func->allocate<InstX86Test>()) | 
| - InstX86Test(Func, Source1, Source2); | 
| - } | 
| - void emit(const Cfg *Func) const override; | 
| - void emitIAS(const Cfg *Func) const override; | 
| - void dump(const Cfg *Func) const override; | 
| - static bool classof(const Inst *Inst) { | 
| - return InstX86Base<Machine>::isClassof(Inst, InstX86Base<Machine>::Test); | 
| - } | 
| + private: | 
| + CvtVariant Variant; | 
| + InstX86Cvt(Cfg *Func, Variable *Dest, Operand *Source, CvtVariant Variant); | 
| + }; | 
| -private: | 
| - InstX86Test(Cfg *Func, Operand *Source1, Operand *Source2); | 
| -}; | 
| + /// cmp - Integer compare instruction. | 
| + class InstX86Icmp final : public InstX86Base { | 
| + InstX86Icmp() = delete; | 
| + InstX86Icmp(const InstX86Icmp &) = delete; | 
| + InstX86Icmp &operator=(const InstX86Icmp &) = delete; | 
| -/// Mfence instruction. | 
| -template <class Machine> | 
| -class InstX86Mfence final : public InstX86Base<Machine> { | 
| - InstX86Mfence() = delete; | 
| - InstX86Mfence(const InstX86Mfence &) = delete; | 
| - InstX86Mfence &operator=(const InstX86Mfence &) = delete; | 
| + public: | 
| + static InstX86Icmp *create(Cfg *Func, Operand *Src1, Operand *Src2) { | 
| + return new (Func->allocate<InstX86Icmp>()) InstX86Icmp(Func, Src1, Src2); | 
| + } | 
| + void emit(const Cfg *Func) const override; | 
| + void emitIAS(const Cfg *Func) const override; | 
| + void dump(const Cfg *Func) const override; | 
| + static bool classof(const Inst *Inst) { | 
| + return InstX86Base::isClassof(Inst, InstX86Base::Icmp); | 
| + } | 
| -public: | 
| - static InstX86Mfence *create(Cfg *Func) { | 
| - return new (Func->allocate<InstX86Mfence>()) InstX86Mfence(Func); | 
| - } | 
| - void emit(const Cfg *Func) const override; | 
| - void emitIAS(const Cfg *Func) const override; | 
| - void dump(const Cfg *Func) const override; | 
| - static bool classof(const Inst *Inst) { | 
| - return InstX86Base<Machine>::isClassof(Inst, InstX86Base<Machine>::Mfence); | 
| - } | 
| + private: | 
| + InstX86Icmp(Cfg *Func, Operand *Src1, Operand *Src2); | 
| + }; | 
| -private: | 
| - explicit InstX86Mfence(Cfg *Func); | 
| -}; | 
| + /// ucomiss/ucomisd - floating-point compare instruction. | 
| + class InstX86Ucomiss final : public InstX86Base { | 
| + InstX86Ucomiss() = delete; | 
| + InstX86Ucomiss(const InstX86Ucomiss &) = delete; | 
| + InstX86Ucomiss &operator=(const InstX86Ucomiss &) = delete; | 
| -/// This is essentially a "mov" instruction with an | 
| -/// InstX86Base<Machine>::Traits::X86OperandMem operand instead of Variable as | 
| -/// the destination. It's important for liveness that there is no Dest operand. | 
| -template <class Machine> | 
| -class InstX86Store final : public InstX86Base<Machine> { | 
| - InstX86Store() = delete; | 
| - InstX86Store(const InstX86Store &) = delete; | 
| - InstX86Store &operator=(const InstX86Store &) = delete; | 
| - | 
| -public: | 
| - static InstX86Store * | 
| - create(Cfg *Func, Operand *Value, | 
| - typename InstX86Base<Machine>::Traits::X86Operand *Mem) { | 
| - return new (Func->allocate<InstX86Store>()) InstX86Store(Func, Value, Mem); | 
| - } | 
| - void emit(const Cfg *Func) const override; | 
| - void emitIAS(const Cfg *Func) const override; | 
| - void dump(const Cfg *Func) const override; | 
| - static bool classof(const Inst *Inst) { | 
| - return InstX86Base<Machine>::isClassof(Inst, InstX86Base<Machine>::Store); | 
| - } | 
| + public: | 
| + static InstX86Ucomiss *create(Cfg *Func, Operand *Src1, Operand *Src2) { | 
| + return new (Func->allocate<InstX86Ucomiss>()) | 
| + InstX86Ucomiss(Func, Src1, Src2); | 
| + } | 
| + void emit(const Cfg *Func) const override; | 
| + void emitIAS(const Cfg *Func) const override; | 
| + void dump(const Cfg *Func) const override; | 
| + static bool classof(const Inst *Inst) { | 
| + return InstX86Base::isClassof(Inst, InstX86Base::Ucomiss); | 
| + } | 
| -private: | 
| - InstX86Store(Cfg *Func, Operand *Value, | 
| - typename InstX86Base<Machine>::Traits::X86Operand *Mem); | 
| -}; | 
| + private: | 
| + InstX86Ucomiss(Cfg *Func, Operand *Src1, Operand *Src2); | 
| + }; | 
| -/// This is essentially a vector "mov" instruction with an typename | 
| -/// InstX86Base<Machine>::Traits::X86OperandMem operand instead of Variable as | 
| -/// the destination. It's important for liveness that there is no Dest operand. | 
| -/// The source must be an Xmm register, since Dest is mem. | 
| -template <class Machine> | 
| -class InstX86StoreP final : public InstX86Base<Machine> { | 
| - InstX86StoreP() = delete; | 
| - InstX86StoreP(const InstX86StoreP &) = delete; | 
| - InstX86StoreP &operator=(const InstX86StoreP &) = delete; | 
| - | 
| -public: | 
| - static InstX86StoreP * | 
| - create(Cfg *Func, Variable *Value, | 
| - typename InstX86Base<Machine>::Traits::X86OperandMem *Mem) { | 
| - return new (Func->allocate<InstX86StoreP>()) | 
| - InstX86StoreP(Func, Value, Mem); | 
| - } | 
| - void emit(const Cfg *Func) const override; | 
| - void emitIAS(const Cfg *Func) const override; | 
| - void dump(const Cfg *Func) const override; | 
| - static bool classof(const Inst *Inst) { | 
| - return InstX86Base<Machine>::isClassof(Inst, InstX86Base<Machine>::StoreP); | 
| - } | 
| + /// UD2 instruction. | 
| + class InstX86UD2 final : public InstX86Base { | 
| + InstX86UD2() = delete; | 
| + InstX86UD2(const InstX86UD2 &) = delete; | 
| + InstX86UD2 &operator=(const InstX86UD2 &) = delete; | 
| -private: | 
| - InstX86StoreP(Cfg *Func, Variable *Value, | 
| - typename InstX86Base<Machine>::Traits::X86OperandMem *Mem); | 
| -}; | 
| + public: | 
| + static InstX86UD2 *create(Cfg *Func) { | 
| + return new (Func->allocate<InstX86UD2>()) InstX86UD2(Func); | 
| + } | 
| + void emit(const Cfg *Func) const override; | 
| + void emitIAS(const Cfg *Func) const override; | 
| + void dump(const Cfg *Func) const override; | 
| + static bool classof(const Inst *Inst) { | 
| + return InstX86Base::isClassof(Inst, InstX86Base::UD2); | 
| + } | 
| -template <class Machine> | 
| -class InstX86StoreQ final : public InstX86Base<Machine> { | 
| - InstX86StoreQ() = delete; | 
| - InstX86StoreQ(const InstX86StoreQ &) = delete; | 
| - InstX86StoreQ &operator=(const InstX86StoreQ &) = delete; | 
| - | 
| -public: | 
| - static InstX86StoreQ * | 
| - create(Cfg *Func, Variable *Value, | 
| - typename InstX86Base<Machine>::Traits::X86OperandMem *Mem) { | 
| - return new (Func->allocate<InstX86StoreQ>()) | 
| - InstX86StoreQ(Func, Value, Mem); | 
| - } | 
| - void emit(const Cfg *Func) const override; | 
| - void emitIAS(const Cfg *Func) const override; | 
| - void dump(const Cfg *Func) const override; | 
| - static bool classof(const Inst *Inst) { | 
| - return InstX86Base<Machine>::isClassof(Inst, InstX86Base<Machine>::StoreQ); | 
| - } | 
| + private: | 
| + explicit InstX86UD2(Cfg *Func); | 
| + }; | 
| -private: | 
| - InstX86StoreQ(Cfg *Func, Variable *Value, | 
| - typename InstX86Base<Machine>::Traits::X86OperandMem *Mem); | 
| -}; | 
| + /// Test instruction. | 
| + class InstX86Test final : public InstX86Base { | 
| + InstX86Test() = delete; | 
| + InstX86Test(const InstX86Test &) = delete; | 
| + InstX86Test &operator=(const InstX86Test &) = delete; | 
| -/// Nop instructions of varying length | 
| -template <class Machine> class InstX86Nop final : public InstX86Base<Machine> { | 
| - InstX86Nop() = delete; | 
| - InstX86Nop(const InstX86Nop &) = delete; | 
| - InstX86Nop &operator=(const InstX86Nop &) = delete; | 
| + public: | 
| + static InstX86Test *create(Cfg *Func, Operand *Source1, Operand *Source2) { | 
| + return new (Func->allocate<InstX86Test>()) | 
| + InstX86Test(Func, Source1, Source2); | 
| + } | 
| + void emit(const Cfg *Func) const override; | 
| + void emitIAS(const Cfg *Func) const override; | 
| + void dump(const Cfg *Func) const override; | 
| + static bool classof(const Inst *Inst) { | 
| + return InstX86Base::isClassof(Inst, InstX86Base::Test); | 
| + } | 
| -public: | 
| - // TODO: Replace with enum. | 
| - using NopVariant = unsigned; | 
| + private: | 
| + InstX86Test(Cfg *Func, Operand *Source1, Operand *Source2); | 
| + }; | 
| - static InstX86Nop *create(Cfg *Func, NopVariant Variant) { | 
| - return new (Func->allocate<InstX86Nop>()) InstX86Nop(Func, Variant); | 
| - } | 
| - void emit(const Cfg *Func) const override; | 
| - void emitIAS(const Cfg *Func) const override; | 
| - void dump(const Cfg *Func) const override; | 
| - static bool classof(const Inst *Inst) { | 
| - return InstX86Base<Machine>::isClassof(Inst, InstX86Base<Machine>::Nop); | 
| - } | 
| + /// Mfence instruction. | 
| + class InstX86Mfence final : public InstX86Base { | 
| + InstX86Mfence() = delete; | 
| + InstX86Mfence(const InstX86Mfence &) = delete; | 
| + InstX86Mfence &operator=(const InstX86Mfence &) = delete; | 
| -private: | 
| - InstX86Nop(Cfg *Func, SizeT Length); | 
| + public: | 
| + static InstX86Mfence *create(Cfg *Func) { | 
| + return new (Func->allocate<InstX86Mfence>()) InstX86Mfence(Func); | 
| + } | 
| + void emit(const Cfg *Func) const override; | 
| + void emitIAS(const Cfg *Func) const override; | 
| + void dump(const Cfg *Func) const override; | 
| + static bool classof(const Inst *Inst) { | 
| + return InstX86Base::isClassof(Inst, InstX86Base::Mfence); | 
| + } | 
| - NopVariant Variant; | 
| -}; | 
| + private: | 
| + explicit InstX86Mfence(Cfg *Func); | 
| + }; | 
| -/// Fld - load a value onto the x87 FP stack. | 
| -template <class Machine> class InstX86Fld final : public InstX86Base<Machine> { | 
| - InstX86Fld() = delete; | 
| - InstX86Fld(const InstX86Fld &) = delete; | 
| - InstX86Fld &operator=(const InstX86Fld &) = delete; | 
| + /// This is essentially a "mov" instruction with anX86OperandMem operand | 
| + /// instead of Variable as the destination. It's important for liveness that | 
| + /// there is no Dest operand. | 
| + class InstX86Store final : public InstX86Base { | 
| + InstX86Store() = delete; | 
| + InstX86Store(const InstX86Store &) = delete; | 
| + InstX86Store &operator=(const InstX86Store &) = delete; | 
| + | 
| + public: | 
| + static InstX86Store *create(Cfg *Func, Operand *Value, X86Operand *Mem) { | 
| + return new (Func->allocate<InstX86Store>()) | 
| + InstX86Store(Func, Value, Mem); | 
| + } | 
| + void emit(const Cfg *Func) const override; | 
| + void emitIAS(const Cfg *Func) const override; | 
| + void dump(const Cfg *Func) const override; | 
| + static bool classof(const Inst *Inst) { | 
| + return InstX86Base::isClassof(Inst, InstX86Base::Store); | 
| + } | 
| -public: | 
| - static InstX86Fld *create(Cfg *Func, Operand *Src) { | 
| - return new (Func->allocate<InstX86Fld>()) InstX86Fld(Func, Src); | 
| - } | 
| - void emit(const Cfg *Func) const override; | 
| - void emitIAS(const Cfg *Func) const override; | 
| - void dump(const Cfg *Func) const override; | 
| - static bool classof(const Inst *Inst) { | 
| - return InstX86Base<Machine>::isClassof(Inst, InstX86Base<Machine>::Fld); | 
| - } | 
| + private: | 
| + InstX86Store(Cfg *Func, Operand *Value, X86Operand *Mem); | 
| + }; | 
| -private: | 
| - InstX86Fld(Cfg *Func, Operand *Src); | 
| -}; | 
| + /// This is essentially a vector "mov" instruction with an typename | 
| + /// X86OperandMem operand instead of Variable as the destination. It's | 
| + /// important for liveness that there is no Dest operand. The source must be | 
| + /// an Xmm register, since Dest is mem. | 
| + class InstX86StoreP final : public InstX86Base { | 
| + InstX86StoreP() = delete; | 
| + InstX86StoreP(const InstX86StoreP &) = delete; | 
| + InstX86StoreP &operator=(const InstX86StoreP &) = delete; | 
| + | 
| + public: | 
| + static InstX86StoreP *create(Cfg *Func, Variable *Value, | 
| + X86OperandMem *Mem) { | 
| + return new (Func->allocate<InstX86StoreP>()) | 
| + InstX86StoreP(Func, Value, Mem); | 
| + } | 
| + void emit(const Cfg *Func) const override; | 
| + void emitIAS(const Cfg *Func) const override; | 
| + void dump(const Cfg *Func) const override; | 
| + static bool classof(const Inst *Inst) { | 
| + return InstX86Base::isClassof(Inst, InstX86Base::StoreP); | 
| + } | 
| -/// Fstp - store x87 st(0) into memory and pop st(0). | 
| -template <class Machine> class InstX86Fstp final : public InstX86Base<Machine> { | 
| - InstX86Fstp() = delete; | 
| - InstX86Fstp(const InstX86Fstp &) = delete; | 
| - InstX86Fstp &operator=(const InstX86Fstp &) = delete; | 
| + private: | 
| + InstX86StoreP(Cfg *Func, Variable *Value, X86OperandMem *Mem); | 
| + }; | 
| -public: | 
| - static InstX86Fstp *create(Cfg *Func, Variable *Dest) { | 
| - return new (Func->allocate<InstX86Fstp>()) InstX86Fstp(Func, Dest); | 
| - } | 
| - void emit(const Cfg *Func) const override; | 
| - void emitIAS(const Cfg *Func) const override; | 
| - void dump(const Cfg *Func) const override; | 
| - static bool classof(const Inst *Inst) { | 
| - return InstX86Base<Machine>::isClassof(Inst, InstX86Base<Machine>::Fstp); | 
| - } | 
| + class InstX86StoreQ final : public InstX86Base { | 
| + InstX86StoreQ() = delete; | 
| + InstX86StoreQ(const InstX86StoreQ &) = delete; | 
| + InstX86StoreQ &operator=(const InstX86StoreQ &) = delete; | 
| -private: | 
| - InstX86Fstp(Cfg *Func, Variable *Dest); | 
| -}; | 
| + public: | 
| + static InstX86StoreQ *create(Cfg *Func, Variable *Value, | 
| + X86OperandMem *Mem) { | 
| + return new (Func->allocate<InstX86StoreQ>()) | 
| + InstX86StoreQ(Func, Value, Mem); | 
| + } | 
| + void emit(const Cfg *Func) const override; | 
| + void emitIAS(const Cfg *Func) const override; | 
| + void dump(const Cfg *Func) const override; | 
| + static bool classof(const Inst *Inst) { | 
| + return InstX86Base::isClassof(Inst, InstX86Base::StoreQ); | 
| + } | 
| -template <class Machine> class InstX86Pop final : public InstX86Base<Machine> { | 
| - InstX86Pop() = delete; | 
| - InstX86Pop(const InstX86Pop &) = delete; | 
| - InstX86Pop &operator=(const InstX86Pop &) = delete; | 
| + private: | 
| + InstX86StoreQ(Cfg *Func, Variable *Value, X86OperandMem *Mem); | 
| + }; | 
| -public: | 
| - static InstX86Pop *create(Cfg *Func, Variable *Dest) { | 
| - return new (Func->allocate<InstX86Pop>()) InstX86Pop(Func, Dest); | 
| - } | 
| - void emit(const Cfg *Func) const override; | 
| - void emitIAS(const Cfg *Func) const override; | 
| - void dump(const Cfg *Func) const override; | 
| - static bool classof(const Inst *Inst) { | 
| - return InstX86Base<Machine>::isClassof(Inst, InstX86Base<Machine>::Pop); | 
| - } | 
| + /// Nop instructions of varying length | 
| + class InstX86Nop final : public InstX86Base { | 
| + InstX86Nop() = delete; | 
| + InstX86Nop(const InstX86Nop &) = delete; | 
| + InstX86Nop &operator=(const InstX86Nop &) = delete; | 
| -private: | 
| - InstX86Pop(Cfg *Func, Variable *Dest); | 
| -}; | 
| + public: | 
| + // TODO: Replace with enum. | 
| + using NopVariant = unsigned; | 
| -template <class Machine> class InstX86Push final : public InstX86Base<Machine> { | 
| - InstX86Push() = delete; | 
| - InstX86Push(const InstX86Push &) = delete; | 
| - InstX86Push &operator=(const InstX86Push &) = delete; | 
| + static InstX86Nop *create(Cfg *Func, NopVariant Variant) { | 
| + return new (Func->allocate<InstX86Nop>()) InstX86Nop(Func, Variant); | 
| + } | 
| + void emit(const Cfg *Func) const override; | 
| + void emitIAS(const Cfg *Func) const override; | 
| + void dump(const Cfg *Func) const override; | 
| + static bool classof(const Inst *Inst) { | 
| + return InstX86Base::isClassof(Inst, InstX86Base::Nop); | 
| + } | 
| -public: | 
| - static InstX86Push *create(Cfg *Func, Variable *Source) { | 
| - return new (Func->allocate<InstX86Push>()) InstX86Push(Func, Source); | 
| - } | 
| - void emit(const Cfg *Func) const override; | 
| - void emitIAS(const Cfg *Func) const override; | 
| - void dump(const Cfg *Func) const override; | 
| - static bool classof(const Inst *Inst) { | 
| - return InstX86Base<Machine>::isClassof(Inst, InstX86Base<Machine>::Push); | 
| - } | 
| + private: | 
| + InstX86Nop(Cfg *Func, SizeT Length); | 
| -private: | 
| - InstX86Push(Cfg *Func, Variable *Source); | 
| -}; | 
| + NopVariant Variant; | 
| + }; | 
| -/// Ret instruction. Currently only supports the "ret" version that does not pop | 
| -/// arguments. This instruction takes a Source operand (for non-void returning | 
| -/// functions) for liveness analysis, though a FakeUse before the ret would do | 
| -/// just as well. | 
| -template <class Machine> class InstX86Ret final : public InstX86Base<Machine> { | 
| - InstX86Ret() = delete; | 
| - InstX86Ret(const InstX86Ret &) = delete; | 
| - InstX86Ret &operator=(const InstX86Ret &) = delete; | 
| - | 
| -public: | 
| - static InstX86Ret *create(Cfg *Func, Variable *Source = nullptr) { | 
| - return new (Func->allocate<InstX86Ret>()) InstX86Ret(Func, Source); | 
| - } | 
| - void emit(const Cfg *Func) const override; | 
| - void emitIAS(const Cfg *Func) const override; | 
| - void dump(const Cfg *Func) const override; | 
| - static bool classof(const Inst *Inst) { | 
| - return InstX86Base<Machine>::isClassof(Inst, InstX86Base<Machine>::Ret); | 
| - } | 
| + /// Fld - load a value onto the x87 FP stack. | 
| + class InstX86Fld final : public InstX86Base { | 
| + InstX86Fld() = delete; | 
| + InstX86Fld(const InstX86Fld &) = delete; | 
| + InstX86Fld &operator=(const InstX86Fld &) = delete; | 
| -private: | 
| - InstX86Ret(Cfg *Func, Variable *Source); | 
| -}; | 
| + public: | 
| + static InstX86Fld *create(Cfg *Func, Operand *Src) { | 
| + return new (Func->allocate<InstX86Fld>()) InstX86Fld(Func, Src); | 
| + } | 
| + void emit(const Cfg *Func) const override; | 
| + void emitIAS(const Cfg *Func) const override; | 
| + void dump(const Cfg *Func) const override; | 
| + static bool classof(const Inst *Inst) { | 
| + return InstX86Base::isClassof(Inst, InstX86Base::Fld); | 
| + } | 
| -/// Conditional set-byte instruction. | 
| -template <class Machine> | 
| -class InstX86Setcc final : public InstX86Base<Machine> { | 
| - InstX86Setcc() = delete; | 
| - InstX86Setcc(const InstX86Cmov<Machine> &) = delete; | 
| - InstX86Setcc &operator=(const InstX86Setcc &) = delete; | 
| - | 
| -public: | 
| - static InstX86Setcc * | 
| - create(Cfg *Func, Variable *Dest, | 
| - typename InstX86Base<Machine>::Traits::Cond::BrCond Cond) { | 
| - return new (Func->allocate<InstX86Setcc>()) InstX86Setcc(Func, Dest, Cond); | 
| - } | 
| - void emit(const Cfg *Func) const override; | 
| - void emitIAS(const Cfg *Func) const override; | 
| - void dump(const Cfg *Func) const override; | 
| - static bool classof(const Inst *Inst) { | 
| - return InstX86Base<Machine>::isClassof(Inst, InstX86Base<Machine>::Setcc); | 
| - } | 
| + private: | 
| + InstX86Fld(Cfg *Func, Operand *Src); | 
| + }; | 
| -private: | 
| - InstX86Setcc(Cfg *Func, Variable *Dest, | 
| - typename InstX86Base<Machine>::Traits::Cond::BrCond Cond); | 
| + /// Fstp - store x87 st(0) into memory and pop st(0). | 
| + class InstX86Fstp final : public InstX86Base { | 
| + InstX86Fstp() = delete; | 
| + InstX86Fstp(const InstX86Fstp &) = delete; | 
| + InstX86Fstp &operator=(const InstX86Fstp &) = delete; | 
| - const typename InstX86Base<Machine>::Traits::Cond::BrCond Condition; | 
| -}; | 
| + public: | 
| + static InstX86Fstp *create(Cfg *Func, Variable *Dest) { | 
| + return new (Func->allocate<InstX86Fstp>()) InstX86Fstp(Func, Dest); | 
| + } | 
| + void emit(const Cfg *Func) const override; | 
| + void emitIAS(const Cfg *Func) const override; | 
| + void dump(const Cfg *Func) const override; | 
| + static bool classof(const Inst *Inst) { | 
| + return InstX86Base::isClassof(Inst, InstX86Base::Fstp); | 
| + } | 
| -/// Exchanging Add instruction. Exchanges the first operand (destination | 
| -/// operand) with the second operand (source operand), then loads the sum of the | 
| -/// two values into the destination operand. The destination may be a register | 
| -/// or memory, while the source must be a register. | 
| -/// | 
| -/// Both the dest and source are updated. The caller should then insert a | 
| -/// FakeDef to reflect the second udpate. | 
| -template <class Machine> | 
| -class InstX86Xadd final : public InstX86BaseLockable<Machine> { | 
| - InstX86Xadd() = delete; | 
| - InstX86Xadd(const InstX86Xadd &) = delete; | 
| - InstX86Xadd &operator=(const InstX86Xadd &) = delete; | 
| - | 
| -public: | 
| - static InstX86Xadd *create(Cfg *Func, Operand *Dest, Variable *Source, | 
| - bool Locked) { | 
| - return new (Func->allocate<InstX86Xadd>()) | 
| - InstX86Xadd(Func, Dest, Source, Locked); | 
| - } | 
| - void emit(const Cfg *Func) const override; | 
| - void emitIAS(const Cfg *Func) const override; | 
| - void dump(const Cfg *Func) const override; | 
| - static bool classof(const Inst *Inst) { | 
| - return InstX86Base<Machine>::isClassof(Inst, InstX86Base<Machine>::Xadd); | 
| - } | 
| + private: | 
| + InstX86Fstp(Cfg *Func, Variable *Dest); | 
| + }; | 
| -private: | 
| - InstX86Xadd(Cfg *Func, Operand *Dest, Variable *Source, bool Locked); | 
| -}; | 
| + class InstX86Pop final : public InstX86Base { | 
| + InstX86Pop() = delete; | 
| + InstX86Pop(const InstX86Pop &) = delete; | 
| + InstX86Pop &operator=(const InstX86Pop &) = delete; | 
| -/// Exchange instruction. Exchanges the first operand (destination operand) with | 
| -/// the second operand (source operand). At least one of the operands must be a | 
| -/// register (and the other can be reg or mem). Both the Dest and Source are | 
| -/// updated. If there is a memory operand, then the instruction is automatically | 
| -/// "locked" without the need for a lock prefix. | 
| -template <class Machine> class InstX86Xchg final : public InstX86Base<Machine> { | 
| - InstX86Xchg() = delete; | 
| - InstX86Xchg(const InstX86Xchg &) = delete; | 
| - InstX86Xchg &operator=(const InstX86Xchg &) = delete; | 
| - | 
| -public: | 
| - static InstX86Xchg *create(Cfg *Func, Operand *Dest, Variable *Source) { | 
| - return new (Func->allocate<InstX86Xchg>()) InstX86Xchg(Func, Dest, Source); | 
| - } | 
| - void emit(const Cfg *Func) const override; | 
| - void emitIAS(const Cfg *Func) const override; | 
| - void dump(const Cfg *Func) const override; | 
| - static bool classof(const Inst *Inst) { | 
| - return InstX86Base<Machine>::isClassof(Inst, InstX86Base<Machine>::Xchg); | 
| - } | 
| + public: | 
| + static InstX86Pop *create(Cfg *Func, Variable *Dest) { | 
| + return new (Func->allocate<InstX86Pop>()) InstX86Pop(Func, Dest); | 
| + } | 
| + void emit(const Cfg *Func) const override; | 
| + void emitIAS(const Cfg *Func) const override; | 
| + void dump(const Cfg *Func) const override; | 
| + static bool classof(const Inst *Inst) { | 
| + return InstX86Base::isClassof(Inst, InstX86Base::Pop); | 
| + } | 
| -private: | 
| - InstX86Xchg(Cfg *Func, Operand *Dest, Variable *Source); | 
| -}; | 
| + private: | 
| + InstX86Pop(Cfg *Func, Variable *Dest); | 
| + }; | 
| -/// Start marker for the Intel Architecture Code Analyzer. This is not an | 
| -/// executable instruction and must only be used for analysis. | 
| -template <class Machine> | 
| -class InstX86IacaStart final : public InstX86Base<Machine> { | 
| - InstX86IacaStart() = delete; | 
| - InstX86IacaStart(const InstX86IacaStart &) = delete; | 
| - InstX86IacaStart &operator=(const InstX86IacaStart &) = delete; | 
| - | 
| -public: | 
| - static InstX86IacaStart *create(Cfg *Func) { | 
| - return new (Func->allocate<InstX86IacaStart>()) InstX86IacaStart(Func); | 
| - } | 
| - void emit(const Cfg *Func) const override; | 
| - void emitIAS(const Cfg *Func) const override; | 
| - void dump(const Cfg *Func) const override; | 
| - static bool classof(const Inst *Inst) { | 
| - return InstX86Base<Machine>::isClassof(Inst, | 
| - InstX86Base<Machine>::IacaStart); | 
| - } | 
| + class InstX86Push final : public InstX86Base { | 
| + InstX86Push() = delete; | 
| + InstX86Push(const InstX86Push &) = delete; | 
| + InstX86Push &operator=(const InstX86Push &) = delete; | 
| -private: | 
| - InstX86IacaStart(Cfg *Func); | 
| -}; | 
| + public: | 
| + static InstX86Push *create(Cfg *Func, Variable *Source) { | 
| + return new (Func->allocate<InstX86Push>()) InstX86Push(Func, Source); | 
| + } | 
| + void emit(const Cfg *Func) const override; | 
| + void emitIAS(const Cfg *Func) const override; | 
| + void dump(const Cfg *Func) const override; | 
| + static bool classof(const Inst *Inst) { | 
| + return InstX86Base::isClassof(Inst, InstX86Base::Push); | 
| + } | 
| -/// End marker for the Intel Architecture Code Analyzer. This is not an | 
| -/// executable instruction and must only be used for analysis. | 
| -template <class Machine> | 
| -class InstX86IacaEnd final : public InstX86Base<Machine> { | 
| - InstX86IacaEnd() = delete; | 
| - InstX86IacaEnd(const InstX86IacaEnd &) = delete; | 
| - InstX86IacaEnd &operator=(const InstX86IacaEnd &) = delete; | 
| - | 
| -public: | 
| - static InstX86IacaEnd *create(Cfg *Func) { | 
| - return new (Func->allocate<InstX86IacaEnd>()) InstX86IacaEnd(Func); | 
| - } | 
| - void emit(const Cfg *Func) const override; | 
| - void emitIAS(const Cfg *Func) const override; | 
| - void dump(const Cfg *Func) const override; | 
| - static bool classof(const Inst *Inst) { | 
| - return InstX86Base<Machine>::isClassof(Inst, InstX86Base<Machine>::IacaEnd); | 
| - } | 
| + private: | 
| + InstX86Push(Cfg *Func, Variable *Source); | 
| + }; | 
| -private: | 
| - InstX86IacaEnd(Cfg *Func); | 
| -}; | 
| + /// Ret instruction. Currently only supports the "ret" version that does not | 
| + /// pop arguments. This instruction takes a Source operand (for non-void | 
| + /// returning functions) for liveness analysis, though a FakeUse before the | 
| + /// ret would do just as well. | 
| + class InstX86Ret final : public InstX86Base { | 
| + InstX86Ret() = delete; | 
| + InstX86Ret(const InstX86Ret &) = delete; | 
| + InstX86Ret &operator=(const InstX86Ret &) = delete; | 
| + | 
| + public: | 
| + static InstX86Ret *create(Cfg *Func, Variable *Source = nullptr) { | 
| + return new (Func->allocate<InstX86Ret>()) InstX86Ret(Func, Source); | 
| + } | 
| + void emit(const Cfg *Func) const override; | 
| + void emitIAS(const Cfg *Func) const override; | 
| + void dump(const Cfg *Func) const override; | 
| + static bool classof(const Inst *Inst) { | 
| + return InstX86Base::isClassof(Inst, InstX86Base::Ret); | 
| + } | 
| + | 
| + private: | 
| + InstX86Ret(Cfg *Func, Variable *Source); | 
| + }; | 
| + | 
| + /// Conditional set-byte instruction. | 
| + class InstX86Setcc final : public InstX86Base { | 
| + InstX86Setcc() = delete; | 
| + InstX86Setcc(const InstX86Cmov &) = delete; | 
| + InstX86Setcc &operator=(const InstX86Setcc &) = delete; | 
| + | 
| + public: | 
| + static InstX86Setcc *create(Cfg *Func, Variable *Dest, BrCond Cond) { | 
| + return new (Func->allocate<InstX86Setcc>()) | 
| + InstX86Setcc(Func, Dest, Cond); | 
| + } | 
| + void emit(const Cfg *Func) const override; | 
| + void emitIAS(const Cfg *Func) const override; | 
| + void dump(const Cfg *Func) const override; | 
| + static bool classof(const Inst *Inst) { | 
| + return InstX86Base::isClassof(Inst, InstX86Base::Setcc); | 
| + } | 
| + | 
| + private: | 
| + InstX86Setcc(Cfg *Func, Variable *Dest, BrCond Cond); | 
| + | 
| + const BrCond Condition; | 
| + }; | 
| + | 
| + /// Exchanging Add instruction. Exchanges the first operand (destination | 
| + /// operand) with the second operand (source operand), then loads the sum of | 
| + /// the two values into the destination operand. The destination may be a | 
| + /// register or memory, while the source must be a register. | 
| + /// | 
| + /// Both the dest and source are updated. The caller should then insert a | 
| + /// FakeDef to reflect the second udpate. | 
| + class InstX86Xadd final : public InstX86BaseLockable { | 
| + InstX86Xadd() = delete; | 
| + InstX86Xadd(const InstX86Xadd &) = delete; | 
| + InstX86Xadd &operator=(const InstX86Xadd &) = delete; | 
| + | 
| + public: | 
| + static InstX86Xadd *create(Cfg *Func, Operand *Dest, Variable *Source, | 
| + bool Locked) { | 
| + return new (Func->allocate<InstX86Xadd>()) | 
| + InstX86Xadd(Func, Dest, Source, Locked); | 
| + } | 
| + void emit(const Cfg *Func) const override; | 
| + void emitIAS(const Cfg *Func) const override; | 
| + void dump(const Cfg *Func) const override; | 
| + static bool classof(const Inst *Inst) { | 
| + return InstX86Base::isClassof(Inst, InstX86Base::Xadd); | 
| + } | 
| + | 
| + private: | 
| + InstX86Xadd(Cfg *Func, Operand *Dest, Variable *Source, bool Locked); | 
| + }; | 
| + | 
| + /// Exchange instruction. Exchanges the first operand (destination operand) | 
| + /// with the second operand (source operand). At least one of the operands | 
| + /// must be a register (and the other can be reg or mem). Both the Dest and | 
| + /// Source are updated. If there is a memory operand, then the instruction is | 
| + /// automatically "locked" without the need for a lock prefix. | 
| + class InstX86Xchg final : public InstX86Base { | 
| + InstX86Xchg() = delete; | 
| + InstX86Xchg(const InstX86Xchg &) = delete; | 
| + InstX86Xchg &operator=(const InstX86Xchg &) = delete; | 
| + | 
| + public: | 
| + static InstX86Xchg *create(Cfg *Func, Operand *Dest, Variable *Source) { | 
| + return new (Func->allocate<InstX86Xchg>()) | 
| + InstX86Xchg(Func, Dest, Source); | 
| + } | 
| + void emit(const Cfg *Func) const override; | 
| + void emitIAS(const Cfg *Func) const override; | 
| + void dump(const Cfg *Func) const override; | 
| + static bool classof(const Inst *Inst) { | 
| + return InstX86Base::isClassof(Inst, InstX86Base::Xchg); | 
| + } | 
| + | 
| + private: | 
| + InstX86Xchg(Cfg *Func, Operand *Dest, Variable *Source); | 
| + }; | 
| + | 
| + /// Start marker for the Intel Architecture Code Analyzer. This is not an | 
| + /// executable instruction and must only be used for analysis. | 
| + class InstX86IacaStart final : public InstX86Base { | 
| + InstX86IacaStart() = delete; | 
| + InstX86IacaStart(const InstX86IacaStart &) = delete; | 
| + InstX86IacaStart &operator=(const InstX86IacaStart &) = delete; | 
| + | 
| + public: | 
| + static InstX86IacaStart *create(Cfg *Func) { | 
| + return new (Func->allocate<InstX86IacaStart>()) InstX86IacaStart(Func); | 
| + } | 
| + void emit(const Cfg *Func) const override; | 
| + void emitIAS(const Cfg *Func) const override; | 
| + void dump(const Cfg *Func) const override; | 
| + static bool classof(const Inst *Inst) { | 
| + return InstX86Base::isClassof(Inst, InstX86Base::IacaStart); | 
| + } | 
| + | 
| + private: | 
| + InstX86IacaStart(Cfg *Func); | 
| + }; | 
| + | 
| + /// End marker for the Intel Architecture Code Analyzer. This is not an | 
| + /// executable instruction and must only be used for analysis. | 
| + class InstX86IacaEnd final : public InstX86Base { | 
| + InstX86IacaEnd() = delete; | 
| + InstX86IacaEnd(const InstX86IacaEnd &) = delete; | 
| + InstX86IacaEnd &operator=(const InstX86IacaEnd &) = delete; | 
| + | 
| + public: | 
| + static InstX86IacaEnd *create(Cfg *Func) { | 
| + return new (Func->allocate<InstX86IacaEnd>()) InstX86IacaEnd(Func); | 
| + } | 
| + void emit(const Cfg *Func) const override; | 
| + void emitIAS(const Cfg *Func) const override; | 
| + void dump(const Cfg *Func) const override; | 
| + static bool classof(const Inst *Inst) { | 
| + return InstX86Base::isClassof(Inst, InstX86Base::IacaEnd); | 
| + } | 
| + | 
| + private: | 
| + InstX86IacaEnd(Cfg *Func); | 
| + }; | 
| +}; // struct InstImpl | 
| /// struct Insts is a template that can be used to instantiate all the X86 | 
| /// instructions for a target with a simple | 
| /// | 
| -/// using Insts = ::Ice::X86Internal::Insts<TargeT>; | 
| -template <class Machine> struct Insts { | 
| - using FakeRMW = InstX86FakeRMW<Machine>; | 
| - using Label = InstX86Label<Machine>; | 
| - | 
| - using Call = InstX86Call<Machine>; | 
| - | 
| - using Br = InstX86Br<Machine>; | 
| - using Jmp = InstX86Jmp<Machine>; | 
| - using Bswap = InstX86Bswap<Machine>; | 
| - using Neg = InstX86Neg<Machine>; | 
| - using Bsf = InstX86Bsf<Machine>; | 
| - using Bsr = InstX86Bsr<Machine>; | 
| - using Lea = InstX86Lea<Machine>; | 
| - using Cbwdq = InstX86Cbwdq<Machine>; | 
| - using Movsx = InstX86Movsx<Machine>; | 
| - using Movzx = InstX86Movzx<Machine>; | 
| - using Movd = InstX86Movd<Machine>; | 
| - using Sqrtss = InstX86Sqrtss<Machine>; | 
| - using Mov = InstX86Mov<Machine>; | 
| - using Movp = InstX86Movp<Machine>; | 
| - using Movq = InstX86Movq<Machine>; | 
| - using Add = InstX86Add<Machine>; | 
| - using AddRMW = InstX86AddRMW<Machine>; | 
| - using Addps = InstX86Addps<Machine>; | 
| - using Adc = InstX86Adc<Machine>; | 
| - using AdcRMW = InstX86AdcRMW<Machine>; | 
| - using Addss = InstX86Addss<Machine>; | 
| - using Andnps = InstX86Andnps<Machine>; | 
| - using Andps = InstX86Andps<Machine>; | 
| - using Padd = InstX86Padd<Machine>; | 
| - using Sub = InstX86Sub<Machine>; | 
| - using SubRMW = InstX86SubRMW<Machine>; | 
| - using Subps = InstX86Subps<Machine>; | 
| - using Subss = InstX86Subss<Machine>; | 
| - using Sbb = InstX86Sbb<Machine>; | 
| - using SbbRMW = InstX86SbbRMW<Machine>; | 
| - using Psub = InstX86Psub<Machine>; | 
| - using And = InstX86And<Machine>; | 
| - using AndRMW = InstX86AndRMW<Machine>; | 
| - using Pand = InstX86Pand<Machine>; | 
| - using Pandn = InstX86Pandn<Machine>; | 
| - using Or = InstX86Or<Machine>; | 
| - using Orps = InstX86Orps<Machine>; | 
| - using OrRMW = InstX86OrRMW<Machine>; | 
| - using Por = InstX86Por<Machine>; | 
| - using Xor = InstX86Xor<Machine>; | 
| - using Xorps = InstX86Xorps<Machine>; | 
| - using XorRMW = InstX86XorRMW<Machine>; | 
| - using Pxor = InstX86Pxor<Machine>; | 
| - using Maxss = InstX86Maxss<Machine>; | 
| - using Minss = InstX86Minss<Machine>; | 
| - using Imul = InstX86Imul<Machine>; | 
| - using ImulImm = InstX86ImulImm<Machine>; | 
| - using Mulps = InstX86Mulps<Machine>; | 
| - using Mulss = InstX86Mulss<Machine>; | 
| - using Pmull = InstX86Pmull<Machine>; | 
| - using Pmuludq = InstX86Pmuludq<Machine>; | 
| - using Divps = InstX86Divps<Machine>; | 
| - using Divss = InstX86Divss<Machine>; | 
| - using Rol = InstX86Rol<Machine>; | 
| - using Shl = InstX86Shl<Machine>; | 
| - using Psll = InstX86Psll<Machine>; | 
| - using Psrl = InstX86Psrl<Machine>; | 
| - using Shr = InstX86Shr<Machine>; | 
| - using Sar = InstX86Sar<Machine>; | 
| - using Psra = InstX86Psra<Machine>; | 
| - using Pcmpeq = InstX86Pcmpeq<Machine>; | 
| - using Pcmpgt = InstX86Pcmpgt<Machine>; | 
| - using MovssRegs = InstX86MovssRegs<Machine>; | 
| - using Idiv = InstX86Idiv<Machine>; | 
| - using Div = InstX86Div<Machine>; | 
| - using Insertps = InstX86Insertps<Machine>; | 
| - using Pinsr = InstX86Pinsr<Machine>; | 
| - using Shufps = InstX86Shufps<Machine>; | 
| - using Blendvps = InstX86Blendvps<Machine>; | 
| - using Pblendvb = InstX86Pblendvb<Machine>; | 
| - using Pextr = InstX86Pextr<Machine>; | 
| - using Pshufd = InstX86Pshufd<Machine>; | 
| - using Lockable = InstX86BaseLockable<Machine>; | 
| - using Mul = InstX86Mul<Machine>; | 
| - using Shld = InstX86Shld<Machine>; | 
| - using Shrd = InstX86Shrd<Machine>; | 
| - using Cmov = InstX86Cmov<Machine>; | 
| - using Cmpps = InstX86Cmpps<Machine>; | 
| - using Cmpxchg = InstX86Cmpxchg<Machine>; | 
| - using Cmpxchg8b = InstX86Cmpxchg8b<Machine>; | 
| - using Cvt = InstX86Cvt<Machine>; | 
| - using Icmp = InstX86Icmp<Machine>; | 
| - using Ucomiss = InstX86Ucomiss<Machine>; | 
| - using UD2 = InstX86UD2<Machine>; | 
| - using Test = InstX86Test<Machine>; | 
| - using Mfence = InstX86Mfence<Machine>; | 
| - using Store = InstX86Store<Machine>; | 
| - using StoreP = InstX86StoreP<Machine>; | 
| - using StoreQ = InstX86StoreQ<Machine>; | 
| - using Nop = InstX86Nop<Machine>; | 
| - template <typename T = typename InstX86Base<Machine>::Traits> | 
| - using Fld = typename std::enable_if<T::UsesX87, InstX86Fld<Machine>>::type; | 
| - template <typename T = typename InstX86Base<Machine>::Traits> | 
| - using Fstp = typename std::enable_if<T::UsesX87, InstX86Fstp<Machine>>::type; | 
| - using Pop = InstX86Pop<Machine>; | 
| - using Push = InstX86Push<Machine>; | 
| - using Ret = InstX86Ret<Machine>; | 
| - using Setcc = InstX86Setcc<Machine>; | 
| - using Xadd = InstX86Xadd<Machine>; | 
| - using Xchg = InstX86Xchg<Machine>; | 
| - | 
| - using IacaStart = InstX86IacaStart<Machine>; | 
| - using IacaEnd = InstX86IacaEnd<Machine>; | 
| +/// using Insts = ::Ice::X86NAMESPACE::Insts<TraitsType>; | 
| +template <typename TraitsType> struct Insts { | 
| + using FakeRMW = typename InstImpl<TraitsType>::InstX86FakeRMW; | 
| + using Label = typename InstImpl<TraitsType>::InstX86Label; | 
| + | 
| + using Call = typename InstImpl<TraitsType>::InstX86Call; | 
| + | 
| + using Br = typename InstImpl<TraitsType>::InstX86Br; | 
| + using Jmp = typename InstImpl<TraitsType>::InstX86Jmp; | 
| + using Bswap = typename InstImpl<TraitsType>::InstX86Bswap; | 
| + using Neg = typename InstImpl<TraitsType>::InstX86Neg; | 
| + using Bsf = typename InstImpl<TraitsType>::InstX86Bsf; | 
| + using Bsr = typename InstImpl<TraitsType>::InstX86Bsr; | 
| + using Lea = typename InstImpl<TraitsType>::InstX86Lea; | 
| + using Cbwdq = typename InstImpl<TraitsType>::InstX86Cbwdq; | 
| + using Movsx = typename InstImpl<TraitsType>::InstX86Movsx; | 
| + using Movzx = typename InstImpl<TraitsType>::InstX86Movzx; | 
| + using Movd = typename InstImpl<TraitsType>::InstX86Movd; | 
| + using Sqrtss = typename InstImpl<TraitsType>::InstX86Sqrtss; | 
| + using Mov = typename InstImpl<TraitsType>::InstX86Mov; | 
| + using Movp = typename InstImpl<TraitsType>::InstX86Movp; | 
| + using Movq = typename InstImpl<TraitsType>::InstX86Movq; | 
| + using Add = typename InstImpl<TraitsType>::InstX86Add; | 
| + using AddRMW = typename InstImpl<TraitsType>::InstX86AddRMW; | 
| + using Addps = typename InstImpl<TraitsType>::InstX86Addps; | 
| + using Adc = typename InstImpl<TraitsType>::InstX86Adc; | 
| + using AdcRMW = typename InstImpl<TraitsType>::InstX86AdcRMW; | 
| + using Addss = typename InstImpl<TraitsType>::InstX86Addss; | 
| + using Andnps = typename InstImpl<TraitsType>::InstX86Andnps; | 
| + using Andps = typename InstImpl<TraitsType>::InstX86Andps; | 
| + using Padd = typename InstImpl<TraitsType>::InstX86Padd; | 
| + using Sub = typename InstImpl<TraitsType>::InstX86Sub; | 
| + using SubRMW = typename InstImpl<TraitsType>::InstX86SubRMW; | 
| + using Subps = typename InstImpl<TraitsType>::InstX86Subps; | 
| + using Subss = typename InstImpl<TraitsType>::InstX86Subss; | 
| + using Sbb = typename InstImpl<TraitsType>::InstX86Sbb; | 
| + using SbbRMW = typename InstImpl<TraitsType>::InstX86SbbRMW; | 
| + using Psub = typename InstImpl<TraitsType>::InstX86Psub; | 
| + using And = typename InstImpl<TraitsType>::InstX86And; | 
| + using AndRMW = typename InstImpl<TraitsType>::InstX86AndRMW; | 
| + using Pand = typename InstImpl<TraitsType>::InstX86Pand; | 
| + using Pandn = typename InstImpl<TraitsType>::InstX86Pandn; | 
| + using Or = typename InstImpl<TraitsType>::InstX86Or; | 
| + using Orps = typename InstImpl<TraitsType>::InstX86Orps; | 
| + using OrRMW = typename InstImpl<TraitsType>::InstX86OrRMW; | 
| + using Por = typename InstImpl<TraitsType>::InstX86Por; | 
| + using Xor = typename InstImpl<TraitsType>::InstX86Xor; | 
| + using Xorps = typename InstImpl<TraitsType>::InstX86Xorps; | 
| + using XorRMW = typename InstImpl<TraitsType>::InstX86XorRMW; | 
| + using Pxor = typename InstImpl<TraitsType>::InstX86Pxor; | 
| + using Maxss = typename InstImpl<TraitsType>::InstX86Maxss; | 
| + using Minss = typename InstImpl<TraitsType>::InstX86Minss; | 
| + using Imul = typename InstImpl<TraitsType>::InstX86Imul; | 
| + using ImulImm = typename InstImpl<TraitsType>::InstX86ImulImm; | 
| + using Mulps = typename InstImpl<TraitsType>::InstX86Mulps; | 
| + using Mulss = typename InstImpl<TraitsType>::InstX86Mulss; | 
| + using Pmull = typename InstImpl<TraitsType>::InstX86Pmull; | 
| + using Pmuludq = typename InstImpl<TraitsType>::InstX86Pmuludq; | 
| + using Divps = typename InstImpl<TraitsType>::InstX86Divps; | 
| + using Divss = typename InstImpl<TraitsType>::InstX86Divss; | 
| + using Rol = typename InstImpl<TraitsType>::InstX86Rol; | 
| + using Shl = typename InstImpl<TraitsType>::InstX86Shl; | 
| + using Psll = typename InstImpl<TraitsType>::InstX86Psll; | 
| + using Psrl = typename InstImpl<TraitsType>::InstX86Psrl; | 
| + using Shr = typename InstImpl<TraitsType>::InstX86Shr; | 
| + using Sar = typename InstImpl<TraitsType>::InstX86Sar; | 
| + using Psra = typename InstImpl<TraitsType>::InstX86Psra; | 
| + using Pcmpeq = typename InstImpl<TraitsType>::InstX86Pcmpeq; | 
| + using Pcmpgt = typename InstImpl<TraitsType>::InstX86Pcmpgt; | 
| + using MovssRegs = typename InstImpl<TraitsType>::InstX86MovssRegs; | 
| + using Idiv = typename InstImpl<TraitsType>::InstX86Idiv; | 
| + using Div = typename InstImpl<TraitsType>::InstX86Div; | 
| + using Insertps = typename InstImpl<TraitsType>::InstX86Insertps; | 
| + using Pinsr = typename InstImpl<TraitsType>::InstX86Pinsr; | 
| + using Shufps = typename InstImpl<TraitsType>::InstX86Shufps; | 
| + using Blendvps = typename InstImpl<TraitsType>::InstX86Blendvps; | 
| + using Pblendvb = typename InstImpl<TraitsType>::InstX86Pblendvb; | 
| + using Pextr = typename InstImpl<TraitsType>::InstX86Pextr; | 
| + using Pshufd = typename InstImpl<TraitsType>::InstX86Pshufd; | 
| + using Lockable = typename InstImpl<TraitsType>::InstX86BaseLockable; | 
| + using Mul = typename InstImpl<TraitsType>::InstX86Mul; | 
| + using Shld = typename InstImpl<TraitsType>::InstX86Shld; | 
| + using Shrd = typename InstImpl<TraitsType>::InstX86Shrd; | 
| + using Cmov = typename InstImpl<TraitsType>::InstX86Cmov; | 
| + using Cmpps = typename InstImpl<TraitsType>::InstX86Cmpps; | 
| + using Cmpxchg = typename InstImpl<TraitsType>::InstX86Cmpxchg; | 
| + using Cmpxchg8b = typename InstImpl<TraitsType>::InstX86Cmpxchg8b; | 
| + using Cvt = typename InstImpl<TraitsType>::InstX86Cvt; | 
| + using Icmp = typename InstImpl<TraitsType>::InstX86Icmp; | 
| + using Ucomiss = typename InstImpl<TraitsType>::InstX86Ucomiss; | 
| + using UD2 = typename InstImpl<TraitsType>::InstX86UD2; | 
| + using Test = typename InstImpl<TraitsType>::InstX86Test; | 
| + using Mfence = typename InstImpl<TraitsType>::InstX86Mfence; | 
| + using Store = typename InstImpl<TraitsType>::InstX86Store; | 
| + using StoreP = typename InstImpl<TraitsType>::InstX86StoreP; | 
| + using StoreQ = typename InstImpl<TraitsType>::InstX86StoreQ; | 
| + using Nop = typename InstImpl<TraitsType>::InstX86Nop; | 
| + template <typename T = typename InstImpl<TraitsType>::Traits> | 
| + using Fld = | 
| + typename std::enable_if<T::UsesX87, | 
| + typename InstImpl<TraitsType>::InstX86Fld>::type; | 
| + template <typename T = typename InstImpl<TraitsType>::Traits> | 
| + using Fstp = | 
| + typename std::enable_if<T::UsesX87, | 
| + typename InstImpl<TraitsType>::InstX86Fstp>::type; | 
| + using Pop = typename InstImpl<TraitsType>::InstX86Pop; | 
| + using Push = typename InstImpl<TraitsType>::InstX86Push; | 
| + using Ret = typename InstImpl<TraitsType>::InstX86Ret; | 
| + using Setcc = typename InstImpl<TraitsType>::InstX86Setcc; | 
| + using Xadd = typename InstImpl<TraitsType>::InstX86Xadd; | 
| + using Xchg = typename InstImpl<TraitsType>::InstX86Xchg; | 
| + | 
| + using IacaStart = typename InstImpl<TraitsType>::InstX86IacaStart; | 
| + using IacaEnd = typename InstImpl<TraitsType>::InstX86IacaEnd; | 
| }; | 
| /// X86 Instructions have static data (particularly, opcodes and instruction | 
| /// emitters). Each X86 target needs to define all of these, so this macro is | 
| /// provided so that, if something changes, then all X86 targets will be updated | 
| /// automatically. | 
| -#define X86INSTS_DEFINE_STATIC_DATA(Machine) \ | 
| +#define X86INSTS_DEFINE_STATIC_DATA(X86NAMESPACE, TraitsType) \ | 
| namespace Ice { \ | 
| - namespace X86Internal { \ | 
| + namespace X86NAMESPACE { \ | 
| /* In-place ops */ \ | 
| - template <> const char *InstX86Bswap<Machine>::Base::Opcode = "bswap"; \ | 
| - template <> const char *InstX86Neg<Machine>::Base::Opcode = "neg"; \ | 
| + template <> \ | 
| + template <> \ | 
| + const char *InstImpl<TraitsType>::InstX86Bswap::Base::Opcode = "bswap"; \ | 
| + template <> \ | 
| + template <> \ | 
| + const char *InstImpl<TraitsType>::InstX86Neg::Base::Opcode = "neg"; \ | 
| /* Unary ops */ \ | 
| - template <> const char *InstX86Bsf<Machine>::Base::Opcode = "bsf"; \ | 
| - template <> const char *InstX86Bsr<Machine>::Base::Opcode = "bsr"; \ | 
| - template <> const char *InstX86Lea<Machine>::Base::Opcode = "lea"; \ | 
| - template <> const char *InstX86Movd<Machine>::Base::Opcode = "movd"; \ | 
| - template <> const char *InstX86Movsx<Machine>::Base::Opcode = "movs"; \ | 
| - template <> const char *InstX86Movzx<Machine>::Base::Opcode = "movz"; \ | 
| - template <> const char *InstX86Sqrtss<Machine>::Base::Opcode = "sqrtss"; \ | 
| - template <> const char *InstX86Cbwdq<Machine>::Base::Opcode = "cbw/cwd/cdq"; \ | 
| + template <> \ | 
| + template <> \ | 
| + const char *InstImpl<TraitsType>::InstX86Bsf::Base::Opcode = "bsf"; \ | 
| + template <> \ | 
| + template <> \ | 
| + const char *InstImpl<TraitsType>::InstX86Bsr::Base::Opcode = "bsr"; \ | 
| + template <> \ | 
| + template <> \ | 
| + const char *InstImpl<TraitsType>::InstX86Lea::Base::Opcode = "lea"; \ | 
| + template <> \ | 
| + template <> \ | 
| + const char *InstImpl<TraitsType>::InstX86Movd::Base::Opcode = "movd"; \ | 
| + template <> \ | 
| + template <> \ | 
| + const char *InstImpl<TraitsType>::InstX86Movsx::Base::Opcode = "movs"; \ | 
| + template <> \ | 
| + template <> \ | 
| + const char *InstImpl<TraitsType>::InstX86Movzx::Base::Opcode = "movz"; \ | 
| + template <> \ | 
| + template <> \ | 
| + const char *InstImpl<TraitsType>::InstX86Sqrtss::Base::Opcode = "sqrtss"; \ | 
| + template <> \ | 
| + template <> \ | 
| + const char *InstImpl<TraitsType>::InstX86Cbwdq::Base::Opcode = \ | 
| + "cbw/cwd/cdq"; \ | 
| /* Mov-like ops */ \ | 
| - template <> const char *InstX86Mov<Machine>::Base::Opcode = "mov"; \ | 
| - template <> const char *InstX86Movp<Machine>::Base::Opcode = "movups"; \ | 
| - template <> const char *InstX86Movq<Machine>::Base::Opcode = "movq"; \ | 
| + template <> \ | 
| + template <> \ | 
| + const char *InstImpl<TraitsType>::InstX86Mov::Base::Opcode = "mov"; \ | 
| + template <> \ | 
| + template <> \ | 
| + const char *InstImpl<TraitsType>::InstX86Movp::Base::Opcode = "movups"; \ | 
| + template <> \ | 
| + template <> \ | 
| + const char *InstImpl<TraitsType>::InstX86Movq::Base::Opcode = "movq"; \ | 
| /* Binary ops */ \ | 
| - template <> const char *InstX86Add<Machine>::Base::Opcode = "add"; \ | 
| - template <> const char *InstX86AddRMW<Machine>::Base::Opcode = "add"; \ | 
| - template <> const char *InstX86Addps<Machine>::Base::Opcode = "add"; \ | 
| - template <> const char *InstX86Adc<Machine>::Base::Opcode = "adc"; \ | 
| - template <> const char *InstX86AdcRMW<Machine>::Base::Opcode = "adc"; \ | 
| - template <> const char *InstX86Addss<Machine>::Base::Opcode = "add"; \ | 
| - template <> const char *InstX86Andnps<Machine>::Base::Opcode = "andn"; \ | 
| - template <> const char *InstX86Andps<Machine>::Base::Opcode = "and"; \ | 
| - template <> const char *InstX86Maxss<Machine>::Base::Opcode = "max"; \ | 
| - template <> const char *InstX86Minss<Machine>::Base::Opcode = "min"; \ | 
| - template <> const char *InstX86Padd<Machine>::Base::Opcode = "padd"; \ | 
| - template <> const char *InstX86Sub<Machine>::Base::Opcode = "sub"; \ | 
| - template <> const char *InstX86SubRMW<Machine>::Base::Opcode = "sub"; \ | 
| - template <> const char *InstX86Subps<Machine>::Base::Opcode = "sub"; \ | 
| - template <> const char *InstX86Subss<Machine>::Base::Opcode = "sub"; \ | 
| - template <> const char *InstX86Sbb<Machine>::Base::Opcode = "sbb"; \ | 
| - template <> const char *InstX86SbbRMW<Machine>::Base::Opcode = "sbb"; \ | 
| - template <> const char *InstX86Psub<Machine>::Base::Opcode = "psub"; \ | 
| - template <> const char *InstX86And<Machine>::Base::Opcode = "and"; \ | 
| - template <> const char *InstX86AndRMW<Machine>::Base::Opcode = "and"; \ | 
| - template <> const char *InstX86Pand<Machine>::Base::Opcode = "pand"; \ | 
| - template <> const char *InstX86Pandn<Machine>::Base::Opcode = "pandn"; \ | 
| - template <> const char *InstX86Or<Machine>::Base::Opcode = "or"; \ | 
| - template <> const char *InstX86Orps<Machine>::Base::Opcode = "or"; \ | 
| - template <> const char *InstX86OrRMW<Machine>::Base::Opcode = "or"; \ | 
| - template <> const char *InstX86Por<Machine>::Base::Opcode = "por"; \ | 
| - template <> const char *InstX86Xor<Machine>::Base::Opcode = "xor"; \ | 
| - template <> const char *InstX86Xorps<Machine>::Base::Opcode = "xor"; \ | 
| - template <> const char *InstX86XorRMW<Machine>::Base::Opcode = "xor"; \ | 
| - template <> const char *InstX86Pxor<Machine>::Base::Opcode = "pxor"; \ | 
| - template <> const char *InstX86Imul<Machine>::Base::Opcode = "imul"; \ | 
| - template <> const char *InstX86ImulImm<Machine>::Base::Opcode = "imul"; \ | 
| - template <> const char *InstX86Mulps<Machine>::Base::Opcode = "mul"; \ | 
| - template <> const char *InstX86Mulss<Machine>::Base::Opcode = "mul"; \ | 
| - template <> const char *InstX86Pmull<Machine>::Base::Opcode = "pmull"; \ | 
| - template <> const char *InstX86Pmuludq<Machine>::Base::Opcode = "pmuludq"; \ | 
| - template <> const char *InstX86Div<Machine>::Base::Opcode = "div"; \ | 
| - template <> const char *InstX86Divps<Machine>::Base::Opcode = "div"; \ | 
| - template <> const char *InstX86Divss<Machine>::Base::Opcode = "div"; \ | 
| - template <> const char *InstX86Idiv<Machine>::Base::Opcode = "idiv"; \ | 
| - template <> const char *InstX86Rol<Machine>::Base::Opcode = "rol"; \ | 
| - template <> const char *InstX86Shl<Machine>::Base::Opcode = "shl"; \ | 
| - template <> const char *InstX86Psll<Machine>::Base::Opcode = "psll"; \ | 
| - template <> const char *InstX86Shr<Machine>::Base::Opcode = "shr"; \ | 
| - template <> const char *InstX86Sar<Machine>::Base::Opcode = "sar"; \ | 
| - template <> const char *InstX86Psra<Machine>::Base::Opcode = "psra"; \ | 
| - template <> const char *InstX86Psrl<Machine>::Base::Opcode = "psrl"; \ | 
| - template <> const char *InstX86Pcmpeq<Machine>::Base::Opcode = "pcmpeq"; \ | 
| - template <> const char *InstX86Pcmpgt<Machine>::Base::Opcode = "pcmpgt"; \ | 
| - template <> const char *InstX86MovssRegs<Machine>::Base::Opcode = "movss"; \ | 
| + template <> \ | 
| + template <> \ | 
| + const char *InstImpl<TraitsType>::InstX86Add::Base::Opcode = "add"; \ | 
| + template <> \ | 
| + template <> \ | 
| + const char *InstImpl<TraitsType>::InstX86AddRMW::Base::Opcode = "add"; \ | 
| + template <> \ | 
| + template <> \ | 
| + const char *InstImpl<TraitsType>::InstX86Addps::Base::Opcode = "add"; \ | 
| + template <> \ | 
| + template <> \ | 
| + const char *InstImpl<TraitsType>::InstX86Adc::Base::Opcode = "adc"; \ | 
| + template <> \ | 
| + template <> \ | 
| + const char *InstImpl<TraitsType>::InstX86AdcRMW::Base::Opcode = "adc"; \ | 
| + template <> \ | 
| + template <> \ | 
| + const char *InstImpl<TraitsType>::InstX86Addss::Base::Opcode = "add"; \ | 
| + template <> \ | 
| + template <> \ | 
| + const char *InstImpl<TraitsType>::InstX86Andnps::Base::Opcode = "andn"; \ | 
| + template <> \ | 
| + template <> \ | 
| + const char *InstImpl<TraitsType>::InstX86Andps::Base::Opcode = "and"; \ | 
| + template <> \ | 
| + template <> \ | 
| + const char *InstImpl<TraitsType>::InstX86Maxss::Base::Opcode = "max"; \ | 
| + template <> \ | 
| + template <> \ | 
| + const char *InstImpl<TraitsType>::InstX86Minss::Base::Opcode = "min"; \ | 
| + template <> \ | 
| + template <> \ | 
| + const char *InstImpl<TraitsType>::InstX86Padd::Base::Opcode = "padd"; \ | 
| + template <> \ | 
| + template <> \ | 
| + const char *InstImpl<TraitsType>::InstX86Sub::Base::Opcode = "sub"; \ | 
| + template <> \ | 
| + template <> \ | 
| + const char *InstImpl<TraitsType>::InstX86SubRMW::Base::Opcode = "sub"; \ | 
| + template <> \ | 
| + template <> \ | 
| + const char *InstImpl<TraitsType>::InstX86Subps::Base::Opcode = "sub"; \ | 
| + template <> \ | 
| + template <> \ | 
| + const char *InstImpl<TraitsType>::InstX86Subss::Base::Opcode = "sub"; \ | 
| + template <> \ | 
| + template <> \ | 
| + const char *InstImpl<TraitsType>::InstX86Sbb::Base::Opcode = "sbb"; \ | 
| + template <> \ | 
| + template <> \ | 
| + const char *InstImpl<TraitsType>::InstX86SbbRMW::Base::Opcode = "sbb"; \ | 
| + template <> \ | 
| + template <> \ | 
| + const char *InstImpl<TraitsType>::InstX86Psub::Base::Opcode = "psub"; \ | 
| + template <> \ | 
| + template <> \ | 
| + const char *InstImpl<TraitsType>::InstX86And::Base::Opcode = "and"; \ | 
| + template <> \ | 
| + template <> \ | 
| + const char *InstImpl<TraitsType>::InstX86AndRMW::Base::Opcode = "and"; \ | 
| + template <> \ | 
| + template <> \ | 
| + const char *InstImpl<TraitsType>::InstX86Pand::Base::Opcode = "pand"; \ | 
| + template <> \ | 
| + template <> \ | 
| + const char *InstImpl<TraitsType>::InstX86Pandn::Base::Opcode = "pandn"; \ | 
| + template <> \ | 
| + template <> \ | 
| + const char *InstImpl<TraitsType>::InstX86Or::Base::Opcode = "or"; \ | 
| + template <> \ | 
| + template <> \ | 
| + const char *InstImpl<TraitsType>::InstX86Orps::Base::Opcode = "or"; \ | 
| + template <> \ | 
| + template <> \ | 
| + const char *InstImpl<TraitsType>::InstX86OrRMW::Base::Opcode = "or"; \ | 
| + template <> \ | 
| + template <> \ | 
| + const char *InstImpl<TraitsType>::InstX86Por::Base::Opcode = "por"; \ | 
| + template <> \ | 
| + template <> \ | 
| + const char *InstImpl<TraitsType>::InstX86Xor::Base::Opcode = "xor"; \ | 
| + template <> \ | 
| + template <> \ | 
| + const char *InstImpl<TraitsType>::InstX86Xorps::Base::Opcode = "xor"; \ | 
| + template <> \ | 
| + template <> \ | 
| + const char *InstImpl<TraitsType>::InstX86XorRMW::Base::Opcode = "xor"; \ | 
| + template <> \ | 
| + template <> \ | 
| + const char *InstImpl<TraitsType>::InstX86Pxor::Base::Opcode = "pxor"; \ | 
| + template <> \ | 
| + template <> \ | 
| + const char *InstImpl<TraitsType>::InstX86Imul::Base::Opcode = "imul"; \ | 
| + template <> \ | 
| + template <> \ | 
| + const char *InstImpl<TraitsType>::InstX86ImulImm::Base::Opcode = "imul"; \ | 
| + template <> \ | 
| + template <> \ | 
| + const char *InstImpl<TraitsType>::InstX86Mulps::Base::Opcode = "mul"; \ | 
| + template <> \ | 
| + template <> \ | 
| + const char *InstImpl<TraitsType>::InstX86Mulss::Base::Opcode = "mul"; \ | 
| + template <> \ | 
| + template <> \ | 
| + const char *InstImpl<TraitsType>::InstX86Pmull::Base::Opcode = "pmull"; \ | 
| + template <> \ | 
| + template <> \ | 
| + const char *InstImpl<TraitsType>::InstX86Pmuludq::Base::Opcode = "pmuludq"; \ | 
| + template <> \ | 
| + template <> \ | 
| + const char *InstImpl<TraitsType>::InstX86Div::Base::Opcode = "div"; \ | 
| + template <> \ | 
| + template <> \ | 
| + const char *InstImpl<TraitsType>::InstX86Divps::Base::Opcode = "div"; \ | 
| + template <> \ | 
| + template <> \ | 
| + const char *InstImpl<TraitsType>::InstX86Divss::Base::Opcode = "div"; \ | 
| + template <> \ | 
| + template <> \ | 
| + const char *InstImpl<TraitsType>::InstX86Idiv::Base::Opcode = "idiv"; \ | 
| + template <> \ | 
| + template <> \ | 
| + const char *InstImpl<TraitsType>::InstX86Rol::Base::Opcode = "rol"; \ | 
| + template <> \ | 
| + template <> \ | 
| + const char *InstImpl<TraitsType>::InstX86Shl::Base::Opcode = "shl"; \ | 
| + template <> \ | 
| + template <> \ | 
| + const char *InstImpl<TraitsType>::InstX86Psll::Base::Opcode = "psll"; \ | 
| + template <> \ | 
| + template <> \ | 
| + const char *InstImpl<TraitsType>::InstX86Shr::Base::Opcode = "shr"; \ | 
| + template <> \ | 
| + template <> \ | 
| + const char *InstImpl<TraitsType>::InstX86Sar::Base::Opcode = "sar"; \ | 
| + template <> \ | 
| + template <> \ | 
| + const char *InstImpl<TraitsType>::InstX86Psra::Base::Opcode = "psra"; \ | 
| + template <> \ | 
| + template <> \ | 
| + const char *InstImpl<TraitsType>::InstX86Psrl::Base::Opcode = "psrl"; \ | 
| + template <> \ | 
| + template <> \ | 
| + const char *InstImpl<TraitsType>::InstX86Pcmpeq::Base::Opcode = "pcmpeq"; \ | 
| + template <> \ | 
| + template <> \ | 
| + const char *InstImpl<TraitsType>::InstX86Pcmpgt::Base::Opcode = "pcmpgt"; \ | 
| + template <> \ | 
| + template <> \ | 
| + const char *InstImpl<TraitsType>::InstX86MovssRegs::Base::Opcode = "movss"; \ | 
| /* Ternary ops */ \ | 
| - template <> const char *InstX86Insertps<Machine>::Base::Opcode = "insertps"; \ | 
| - template <> const char *InstX86Shufps<Machine>::Base::Opcode = "shufps"; \ | 
| - template <> const char *InstX86Pinsr<Machine>::Base::Opcode = "pinsr"; \ | 
| - template <> const char *InstX86Blendvps<Machine>::Base::Opcode = "blendvps"; \ | 
| - template <> const char *InstX86Pblendvb<Machine>::Base::Opcode = "pblendvb"; \ | 
| + template <> \ | 
| + template <> \ | 
| + const char *InstImpl<TraitsType>::InstX86Insertps::Base::Opcode = \ | 
| + "insertps"; \ | 
| + template <> \ | 
| + template <> \ | 
| + const char *InstImpl<TraitsType>::InstX86Shufps::Base::Opcode = "shufps"; \ | 
| + template <> \ | 
| + template <> \ | 
| + const char *InstImpl<TraitsType>::InstX86Pinsr::Base::Opcode = "pinsr"; \ | 
| + template <> \ | 
| + template <> \ | 
| + const char *InstImpl<TraitsType>::InstX86Blendvps::Base::Opcode = \ | 
| + "blendvps"; \ | 
| + template <> \ | 
| + template <> \ | 
| + const char *InstImpl<TraitsType>::InstX86Pblendvb::Base::Opcode = \ | 
| + "pblendvb"; \ | 
| /* Three address ops */ \ | 
| - template <> const char *InstX86Pextr<Machine>::Base::Opcode = "pextr"; \ | 
| - template <> const char *InstX86Pshufd<Machine>::Base::Opcode = "pshufd"; \ | 
| + template <> \ | 
| + template <> \ | 
| + const char *InstImpl<TraitsType>::InstX86Pextr::Base::Opcode = "pextr"; \ | 
| + template <> \ | 
| + template <> \ | 
| + const char *InstImpl<TraitsType>::InstX86Pshufd::Base::Opcode = "pshufd"; \ | 
| /* Inplace GPR ops */ \ | 
| template <> \ | 
| - const InstX86Base<Machine>::Traits::Assembler::GPREmitterOneOp \ | 
| - InstX86Bswap<Machine>::Base::Emitter = { \ | 
| - &InstX86Base<Machine>::Traits::Assembler::bswap, \ | 
| + template <> \ | 
| + const InstImpl<TraitsType>::Assembler::GPREmitterOneOp \ | 
| + InstImpl<TraitsType>::InstX86Bswap::Base::Emitter = { \ | 
| + &InstImpl<TraitsType>::Assembler::bswap, \ | 
| nullptr /* only a reg form exists */ \ | 
| }; \ | 
| template <> \ | 
| - const InstX86Base<Machine>::Traits::Assembler::GPREmitterOneOp \ | 
| - InstX86Neg<Machine>::Base::Emitter = { \ | 
| - &InstX86Base<Machine>::Traits::Assembler::neg, \ | 
| - &InstX86Base<Machine>::Traits::Assembler::neg}; \ | 
| + template <> \ | 
| + const InstImpl<TraitsType>::Assembler::GPREmitterOneOp \ | 
| + InstImpl<TraitsType>::InstX86Neg::Base::Emitter = { \ | 
| + &InstImpl<TraitsType>::Assembler::neg, \ | 
| + &InstImpl<TraitsType>::Assembler::neg}; \ | 
| \ | 
| /* Unary GPR ops */ \ | 
| + template <> \ | 
| template <> /* uses specialized emitter. */ \ | 
| - const InstX86Base<Machine>::Traits::Assembler::GPREmitterRegOp \ | 
| - InstX86Cbwdq<Machine>::Base::Emitter = {nullptr, nullptr, nullptr}; \ | 
| + const InstImpl<TraitsType>::Assembler::GPREmitterRegOp \ | 
| + InstImpl<TraitsType>::InstX86Cbwdq::Base::Emitter = {nullptr, nullptr, \ | 
| + nullptr}; \ | 
| + template <> \ | 
| template <> \ | 
| - const InstX86Base<Machine>::Traits::Assembler::GPREmitterRegOp \ | 
| - InstX86Bsf<Machine>::Base::Emitter = { \ | 
| - &InstX86Base<Machine>::Traits::Assembler::bsf, \ | 
| - &InstX86Base<Machine>::Traits::Assembler::bsf, nullptr}; \ | 
| + const InstImpl<TraitsType>::Assembler::GPREmitterRegOp \ | 
| + InstImpl<TraitsType>::InstX86Bsf::Base::Emitter = { \ | 
| + &InstImpl<TraitsType>::Assembler::bsf, \ | 
| + &InstImpl<TraitsType>::Assembler::bsf, nullptr}; \ | 
| template <> \ | 
| - const InstX86Base<Machine>::Traits::Assembler::GPREmitterRegOp \ | 
| - InstX86Bsr<Machine>::Base::Emitter = { \ | 
| - &InstX86Base<Machine>::Traits::Assembler::bsr, \ | 
| - &InstX86Base<Machine>::Traits::Assembler::bsr, nullptr}; \ | 
| template <> \ | 
| - const InstX86Base<Machine>::Traits::Assembler::GPREmitterRegOp \ | 
| - InstX86Lea<Machine>::Base::Emitter = { \ | 
| + const InstImpl<TraitsType>::Assembler::GPREmitterRegOp \ | 
| + InstImpl<TraitsType>::InstX86Bsr::Base::Emitter = { \ | 
| + &InstImpl<TraitsType>::Assembler::bsr, \ | 
| + &InstImpl<TraitsType>::Assembler::bsr, nullptr}; \ | 
| + template <> \ | 
| + template <> \ | 
| + const InstImpl<TraitsType>::Assembler::GPREmitterRegOp \ | 
| + InstImpl<TraitsType>::InstX86Lea::Base::Emitter = { \ | 
| /* reg/reg and reg/imm are illegal */ nullptr, \ | 
| - &InstX86Base<Machine>::Traits::Assembler::lea, nullptr}; \ | 
| + &InstImpl<TraitsType>::Assembler::lea, nullptr}; \ | 
| + template <> \ | 
| template <> \ | 
| - const InstX86Base<Machine>::Traits::Assembler::GPREmitterRegOp \ | 
| - InstX86Movsx<Machine>::Base::Emitter = { \ | 
| - &InstX86Base<Machine>::Traits::Assembler::movsx, \ | 
| - &InstX86Base<Machine>::Traits::Assembler::movsx, nullptr}; \ | 
| + const InstImpl<TraitsType>::Assembler::GPREmitterRegOp \ | 
| + InstImpl<TraitsType>::InstX86Movsx::Base::Emitter = { \ | 
| + &InstImpl<TraitsType>::Assembler::movsx, \ | 
| + &InstImpl<TraitsType>::Assembler::movsx, nullptr}; \ | 
| template <> \ | 
| - const InstX86Base<Machine>::Traits::Assembler::GPREmitterRegOp \ | 
| - InstX86Movzx<Machine>::Base::Emitter = { \ | 
| - &InstX86Base<Machine>::Traits::Assembler::movzx, \ | 
| - &InstX86Base<Machine>::Traits::Assembler::movzx, nullptr}; \ | 
| + template <> \ | 
| + const InstImpl<TraitsType>::Assembler::GPREmitterRegOp \ | 
| + InstImpl<TraitsType>::InstX86Movzx::Base::Emitter = { \ | 
| + &InstImpl<TraitsType>::Assembler::movzx, \ | 
| + &InstImpl<TraitsType>::Assembler::movzx, nullptr}; \ | 
| \ | 
| /* Unary XMM ops */ \ | 
| + template <> \ | 
| template <> /* uses specialized emitter. */ \ | 
| - const InstX86Base<Machine>::Traits::Assembler::XmmEmitterRegOp \ | 
| - InstX86Movd<Machine>::Base::Emitter = {nullptr, nullptr}; \ | 
| + const InstImpl<TraitsType>::Assembler::XmmEmitterRegOp \ | 
| + InstImpl<TraitsType>::InstX86Movd::Base::Emitter = {nullptr, nullptr}; \ | 
| + template <> \ | 
| template <> \ | 
| - const InstX86Base<Machine>::Traits::Assembler::XmmEmitterRegOp \ | 
| - InstX86Sqrtss<Machine>::Base::Emitter = { \ | 
| - &InstX86Base<Machine>::Traits::Assembler::sqrtss, \ | 
| - &InstX86Base<Machine>::Traits::Assembler::sqrtss}; \ | 
| + const InstImpl<TraitsType>::Assembler::XmmEmitterRegOp \ | 
| + InstImpl<TraitsType>::InstX86Sqrtss::Base::Emitter = { \ | 
| + &InstImpl<TraitsType>::Assembler::sqrtss, \ | 
| + &InstImpl<TraitsType>::Assembler::sqrtss}; \ | 
| \ | 
| /* Binary GPR ops */ \ | 
| + template <> \ | 
| template <> /* uses specialized emitter. */ \ | 
| - const InstX86Base<Machine>::Traits::Assembler::GPREmitterRegOp \ | 
| - InstX86Imul<Machine>::Base::Emitter = {nullptr, nullptr, nullptr}; \ | 
| - template <> \ | 
| - const InstX86Base<Machine>::Traits::Assembler::GPREmitterRegOp \ | 
| - InstX86Add<Machine>::Base::Emitter = { \ | 
| - &InstX86Base<Machine>::Traits::Assembler::add, \ | 
| - &InstX86Base<Machine>::Traits::Assembler::add, \ | 
| - &InstX86Base<Machine>::Traits::Assembler::add}; \ | 
| - template <> \ | 
| - const InstX86Base<Machine>::Traits::Assembler::GPREmitterAddrOp \ | 
| - InstX86AddRMW<Machine>::Base::Emitter = { \ | 
| - &InstX86Base<Machine>::Traits::Assembler::add, \ | 
| - &InstX86Base<Machine>::Traits::Assembler::add}; \ | 
| - template <> \ | 
| - const InstX86Base<Machine>::Traits::Assembler::GPREmitterRegOp \ | 
| - InstX86Adc<Machine>::Base::Emitter = { \ | 
| - &InstX86Base<Machine>::Traits::Assembler::adc, \ | 
| - &InstX86Base<Machine>::Traits::Assembler::adc, \ | 
| - &InstX86Base<Machine>::Traits::Assembler::adc}; \ | 
| - template <> \ | 
| - const InstX86Base<Machine>::Traits::Assembler::GPREmitterAddrOp \ | 
| - InstX86AdcRMW<Machine>::Base::Emitter = { \ | 
| - &InstX86Base<Machine>::Traits::Assembler::adc, \ | 
| - &InstX86Base<Machine>::Traits::Assembler::adc}; \ | 
| - template <> \ | 
| - const InstX86Base<Machine>::Traits::Assembler::GPREmitterRegOp \ | 
| - InstX86And<Machine>::Base::Emitter = { \ | 
| - &InstX86Base<Machine>::Traits::Assembler::And, \ | 
| - &InstX86Base<Machine>::Traits::Assembler::And, \ | 
| - &InstX86Base<Machine>::Traits::Assembler::And}; \ | 
| - template <> \ | 
| - const InstX86Base<Machine>::Traits::Assembler::GPREmitterAddrOp \ | 
| - InstX86AndRMW<Machine>::Base::Emitter = { \ | 
| - &InstX86Base<Machine>::Traits::Assembler::And, \ | 
| - &InstX86Base<Machine>::Traits::Assembler::And}; \ | 
| - template <> \ | 
| - const InstX86Base<Machine>::Traits::Assembler::GPREmitterRegOp \ | 
| - InstX86Or<Machine>::Base::Emitter = { \ | 
| - &InstX86Base<Machine>::Traits::Assembler::Or, \ | 
| - &InstX86Base<Machine>::Traits::Assembler::Or, \ | 
| - &InstX86Base<Machine>::Traits::Assembler::Or}; \ | 
| - template <> \ | 
| - const InstX86Base<Machine>::Traits::Assembler::GPREmitterAddrOp \ | 
| - InstX86OrRMW<Machine>::Base::Emitter = { \ | 
| - &InstX86Base<Machine>::Traits::Assembler::Or, \ | 
| - &InstX86Base<Machine>::Traits::Assembler::Or}; \ | 
| - template <> \ | 
| - const InstX86Base<Machine>::Traits::Assembler::GPREmitterRegOp \ | 
| - InstX86Sbb<Machine>::Base::Emitter = { \ | 
| - &InstX86Base<Machine>::Traits::Assembler::sbb, \ | 
| - &InstX86Base<Machine>::Traits::Assembler::sbb, \ | 
| - &InstX86Base<Machine>::Traits::Assembler::sbb}; \ | 
| - template <> \ | 
| - const InstX86Base<Machine>::Traits::Assembler::GPREmitterAddrOp \ | 
| - InstX86SbbRMW<Machine>::Base::Emitter = { \ | 
| - &InstX86Base<Machine>::Traits::Assembler::sbb, \ | 
| - &InstX86Base<Machine>::Traits::Assembler::sbb}; \ | 
| - template <> \ | 
| - const InstX86Base<Machine>::Traits::Assembler::GPREmitterRegOp \ | 
| - InstX86Sub<Machine>::Base::Emitter = { \ | 
| - &InstX86Base<Machine>::Traits::Assembler::sub, \ | 
| - &InstX86Base<Machine>::Traits::Assembler::sub, \ | 
| - &InstX86Base<Machine>::Traits::Assembler::sub}; \ | 
| - template <> \ | 
| - const InstX86Base<Machine>::Traits::Assembler::GPREmitterAddrOp \ | 
| - InstX86SubRMW<Machine>::Base::Emitter = { \ | 
| - &InstX86Base<Machine>::Traits::Assembler::sub, \ | 
| - &InstX86Base<Machine>::Traits::Assembler::sub}; \ | 
| - template <> \ | 
| - const InstX86Base<Machine>::Traits::Assembler::GPREmitterRegOp \ | 
| - InstX86Xor<Machine>::Base::Emitter = { \ | 
| - &InstX86Base<Machine>::Traits::Assembler::Xor, \ | 
| - &InstX86Base<Machine>::Traits::Assembler::Xor, \ | 
| - &InstX86Base<Machine>::Traits::Assembler::Xor}; \ | 
| - template <> \ | 
| - const InstX86Base<Machine>::Traits::Assembler::GPREmitterAddrOp \ | 
| - InstX86XorRMW<Machine>::Base::Emitter = { \ | 
| - &InstX86Base<Machine>::Traits::Assembler::Xor, \ | 
| - &InstX86Base<Machine>::Traits::Assembler::Xor}; \ | 
| + const InstImpl<TraitsType>::Assembler::GPREmitterRegOp \ | 
| + InstImpl<TraitsType>::InstX86Imul::Base::Emitter = {nullptr, nullptr, \ | 
| + nullptr}; \ | 
| + template <> \ | 
| + template <> \ | 
| + const InstImpl<TraitsType>::Assembler::GPREmitterRegOp \ | 
| + InstImpl<TraitsType>::InstX86Add::Base::Emitter = { \ | 
| + &InstImpl<TraitsType>::Assembler::add, \ | 
| + &InstImpl<TraitsType>::Assembler::add, \ | 
| + &InstImpl<TraitsType>::Assembler::add}; \ | 
| + template <> \ | 
| + template <> \ | 
| + const InstImpl<TraitsType>::Assembler::GPREmitterAddrOp \ | 
| + InstImpl<TraitsType>::InstX86AddRMW::Base::Emitter = { \ | 
| + &InstImpl<TraitsType>::Assembler::add, \ | 
| + &InstImpl<TraitsType>::Assembler::add}; \ | 
| + template <> \ | 
| + template <> \ | 
| + const InstImpl<TraitsType>::Assembler::GPREmitterRegOp \ | 
| + InstImpl<TraitsType>::InstX86Adc::Base::Emitter = { \ | 
| + &InstImpl<TraitsType>::Assembler::adc, \ | 
| + &InstImpl<TraitsType>::Assembler::adc, \ | 
| + &InstImpl<TraitsType>::Assembler::adc}; \ | 
| + template <> \ | 
| + template <> \ | 
| + const InstImpl<TraitsType>::Assembler::GPREmitterAddrOp \ | 
| + InstImpl<TraitsType>::InstX86AdcRMW::Base::Emitter = { \ | 
| + &InstImpl<TraitsType>::Assembler::adc, \ | 
| + &InstImpl<TraitsType>::Assembler::adc}; \ | 
| + template <> \ | 
| + template <> \ | 
| + const InstImpl<TraitsType>::Assembler::GPREmitterRegOp \ | 
| + InstImpl<TraitsType>::InstX86And::Base::Emitter = { \ | 
| + &InstImpl<TraitsType>::Assembler::And, \ | 
| + &InstImpl<TraitsType>::Assembler::And, \ | 
| + &InstImpl<TraitsType>::Assembler::And}; \ | 
| + template <> \ | 
| + template <> \ | 
| + const InstImpl<TraitsType>::Assembler::GPREmitterAddrOp \ | 
| + InstImpl<TraitsType>::InstX86AndRMW::Base::Emitter = { \ | 
| + &InstImpl<TraitsType>::Assembler::And, \ | 
| + &InstImpl<TraitsType>::Assembler::And}; \ | 
| + template <> \ | 
| + template <> \ | 
| + const InstImpl<TraitsType>::Assembler::GPREmitterRegOp \ | 
| + InstImpl<TraitsType>::InstX86Or::Base::Emitter = { \ | 
| + &InstImpl<TraitsType>::Assembler::Or, \ | 
| + &InstImpl<TraitsType>::Assembler::Or, \ | 
| + &InstImpl<TraitsType>::Assembler::Or}; \ | 
| + template <> \ | 
| + template <> \ | 
| + const InstImpl<TraitsType>::Assembler::GPREmitterAddrOp \ | 
| + InstImpl<TraitsType>::InstX86OrRMW::Base::Emitter = { \ | 
| + &InstImpl<TraitsType>::Assembler::Or, \ | 
| + &InstImpl<TraitsType>::Assembler::Or}; \ | 
| + template <> \ | 
| + template <> \ | 
| + const InstImpl<TraitsType>::Assembler::GPREmitterRegOp \ | 
| + InstImpl<TraitsType>::InstX86Sbb::Base::Emitter = { \ | 
| + &InstImpl<TraitsType>::Assembler::sbb, \ | 
| + &InstImpl<TraitsType>::Assembler::sbb, \ | 
| + &InstImpl<TraitsType>::Assembler::sbb}; \ | 
| + template <> \ | 
| + template <> \ | 
| + const InstImpl<TraitsType>::Assembler::GPREmitterAddrOp \ | 
| + InstImpl<TraitsType>::InstX86SbbRMW::Base::Emitter = { \ | 
| + &InstImpl<TraitsType>::Assembler::sbb, \ | 
| + &InstImpl<TraitsType>::Assembler::sbb}; \ | 
| + template <> \ | 
| + template <> \ | 
| + const InstImpl<TraitsType>::Assembler::GPREmitterRegOp \ | 
| + InstImpl<TraitsType>::InstX86Sub::Base::Emitter = { \ | 
| + &InstImpl<TraitsType>::Assembler::sub, \ | 
| + &InstImpl<TraitsType>::Assembler::sub, \ | 
| + &InstImpl<TraitsType>::Assembler::sub}; \ | 
| + template <> \ | 
| + template <> \ | 
| + const InstImpl<TraitsType>::Assembler::GPREmitterAddrOp \ | 
| + InstImpl<TraitsType>::InstX86SubRMW::Base::Emitter = { \ | 
| + &InstImpl<TraitsType>::Assembler::sub, \ | 
| + &InstImpl<TraitsType>::Assembler::sub}; \ | 
| + template <> \ | 
| + template <> \ | 
| + const InstImpl<TraitsType>::Assembler::GPREmitterRegOp \ | 
| + InstImpl<TraitsType>::InstX86Xor::Base::Emitter = { \ | 
| + &InstImpl<TraitsType>::Assembler::Xor, \ | 
| + &InstImpl<TraitsType>::Assembler::Xor, \ | 
| + &InstImpl<TraitsType>::Assembler::Xor}; \ | 
| + template <> \ | 
| + template <> \ | 
| + const InstImpl<TraitsType>::Assembler::GPREmitterAddrOp \ | 
| + InstImpl<TraitsType>::InstX86XorRMW::Base::Emitter = { \ | 
| + &InstImpl<TraitsType>::Assembler::Xor, \ | 
| + &InstImpl<TraitsType>::Assembler::Xor}; \ | 
| \ | 
| /* Binary Shift GPR ops */ \ | 
| template <> \ | 
| - const InstX86Base<Machine>::Traits::Assembler::GPREmitterShiftOp \ | 
| - InstX86Rol<Machine>::Base::Emitter = { \ | 
| - &InstX86Base<Machine>::Traits::Assembler::rol, \ | 
| - &InstX86Base<Machine>::Traits::Assembler::rol}; \ | 
| - template <> \ | 
| - const InstX86Base<Machine>::Traits::Assembler::GPREmitterShiftOp \ | 
| - InstX86Sar<Machine>::Base::Emitter = { \ | 
| - &InstX86Base<Machine>::Traits::Assembler::sar, \ | 
| - &InstX86Base<Machine>::Traits::Assembler::sar}; \ | 
| - template <> \ | 
| - const InstX86Base<Machine>::Traits::Assembler::GPREmitterShiftOp \ | 
| - InstX86Shl<Machine>::Base::Emitter = { \ | 
| - &InstX86Base<Machine>::Traits::Assembler::shl, \ | 
| - &InstX86Base<Machine>::Traits::Assembler::shl}; \ | 
| - template <> \ | 
| - const InstX86Base<Machine>::Traits::Assembler::GPREmitterShiftOp \ | 
| - InstX86Shr<Machine>::Base::Emitter = { \ | 
| - &InstX86Base<Machine>::Traits::Assembler::shr, \ | 
| - &InstX86Base<Machine>::Traits::Assembler::shr}; \ | 
| + template <> \ | 
| + const InstImpl<TraitsType>::Assembler::GPREmitterShiftOp \ | 
| + InstImpl<TraitsType>::InstX86Rol::Base::Emitter = { \ | 
| + &InstImpl<TraitsType>::Assembler::rol, \ | 
| + &InstImpl<TraitsType>::Assembler::rol}; \ | 
| + template <> \ | 
| + template <> \ | 
| + const InstImpl<TraitsType>::Assembler::GPREmitterShiftOp \ | 
| + InstImpl<TraitsType>::InstX86Sar::Base::Emitter = { \ | 
| + &InstImpl<TraitsType>::Assembler::sar, \ | 
| + &InstImpl<TraitsType>::Assembler::sar}; \ | 
| + template <> \ | 
| + template <> \ | 
| + const InstImpl<TraitsType>::Assembler::GPREmitterShiftOp \ | 
| + InstImpl<TraitsType>::InstX86Shl::Base::Emitter = { \ | 
| + &InstImpl<TraitsType>::Assembler::shl, \ | 
| + &InstImpl<TraitsType>::Assembler::shl}; \ | 
| + template <> \ | 
| + template <> \ | 
| + const InstImpl<TraitsType>::Assembler::GPREmitterShiftOp \ | 
| + InstImpl<TraitsType>::InstX86Shr::Base::Emitter = { \ | 
| + &InstImpl<TraitsType>::Assembler::shr, \ | 
| + &InstImpl<TraitsType>::Assembler::shr}; \ | 
| \ | 
| /* Binary XMM ops */ \ | 
| + template <> \ | 
| template <> /* uses specialized emitter. */ \ | 
| - const InstX86Base<Machine>::Traits::Assembler::XmmEmitterRegOp \ | 
| - InstX86MovssRegs<Machine>::Base::Emitter = {nullptr, nullptr}; \ | 
| - template <> \ | 
| - const InstX86Base<Machine>::Traits::Assembler::XmmEmitterRegOp \ | 
| - InstX86Addss<Machine>::Base::Emitter = { \ | 
| - &InstX86Base<Machine>::Traits::Assembler::addss, \ | 
| - &InstX86Base<Machine>::Traits::Assembler::addss}; \ | 
| - template <> \ | 
| - const InstX86Base<Machine>::Traits::Assembler::XmmEmitterRegOp \ | 
| - InstX86Addps<Machine>::Base::Emitter = { \ | 
| - &InstX86Base<Machine>::Traits::Assembler::addps, \ | 
| - &InstX86Base<Machine>::Traits::Assembler::addps}; \ | 
| - template <> \ | 
| - const InstX86Base<Machine>::Traits::Assembler::XmmEmitterRegOp \ | 
| - InstX86Divss<Machine>::Base::Emitter = { \ | 
| - &InstX86Base<Machine>::Traits::Assembler::divss, \ | 
| - &InstX86Base<Machine>::Traits::Assembler::divss}; \ | 
| - template <> \ | 
| - const InstX86Base<Machine>::Traits::Assembler::XmmEmitterRegOp \ | 
| - InstX86Divps<Machine>::Base::Emitter = { \ | 
| - &InstX86Base<Machine>::Traits::Assembler::divps, \ | 
| - &InstX86Base<Machine>::Traits::Assembler::divps}; \ | 
| - template <> \ | 
| - const InstX86Base<Machine>::Traits::Assembler::XmmEmitterRegOp \ | 
| - InstX86Mulss<Machine>::Base::Emitter = { \ | 
| - &InstX86Base<Machine>::Traits::Assembler::mulss, \ | 
| - &InstX86Base<Machine>::Traits::Assembler::mulss}; \ | 
| - template <> \ | 
| - const InstX86Base<Machine>::Traits::Assembler::XmmEmitterRegOp \ | 
| - InstX86Mulps<Machine>::Base::Emitter = { \ | 
| - &InstX86Base<Machine>::Traits::Assembler::mulps, \ | 
| - &InstX86Base<Machine>::Traits::Assembler::mulps}; \ | 
| - template <> \ | 
| - const InstX86Base<Machine>::Traits::Assembler::XmmEmitterRegOp \ | 
| - InstX86Padd<Machine>::Base::Emitter = { \ | 
| - &InstX86Base<Machine>::Traits::Assembler::padd, \ | 
| - &InstX86Base<Machine>::Traits::Assembler::padd}; \ | 
| - template <> \ | 
| - const InstX86Base<Machine>::Traits::Assembler::XmmEmitterRegOp \ | 
| - InstX86Pand<Machine>::Base::Emitter = { \ | 
| - &InstX86Base<Machine>::Traits::Assembler::pand, \ | 
| - &InstX86Base<Machine>::Traits::Assembler::pand}; \ | 
| - template <> \ | 
| - const InstX86Base<Machine>::Traits::Assembler::XmmEmitterRegOp \ | 
| - InstX86Pandn<Machine>::Base::Emitter = { \ | 
| - &InstX86Base<Machine>::Traits::Assembler::pandn, \ | 
| - &InstX86Base<Machine>::Traits::Assembler::pandn}; \ | 
| - template <> \ | 
| - const InstX86Base<Machine>::Traits::Assembler::XmmEmitterRegOp \ | 
| - InstX86Pcmpeq<Machine>::Base::Emitter = { \ | 
| - &InstX86Base<Machine>::Traits::Assembler::pcmpeq, \ | 
| - &InstX86Base<Machine>::Traits::Assembler::pcmpeq}; \ | 
| - template <> \ | 
| - const InstX86Base<Machine>::Traits::Assembler::XmmEmitterRegOp \ | 
| - InstX86Pcmpgt<Machine>::Base::Emitter = { \ | 
| - &InstX86Base<Machine>::Traits::Assembler::pcmpgt, \ | 
| - &InstX86Base<Machine>::Traits::Assembler::pcmpgt}; \ | 
| - template <> \ | 
| - const InstX86Base<Machine>::Traits::Assembler::XmmEmitterRegOp \ | 
| - InstX86Pmull<Machine>::Base::Emitter = { \ | 
| - &InstX86Base<Machine>::Traits::Assembler::pmull, \ | 
| - &InstX86Base<Machine>::Traits::Assembler::pmull}; \ | 
| - template <> \ | 
| - const InstX86Base<Machine>::Traits::Assembler::XmmEmitterRegOp \ | 
| - InstX86Pmuludq<Machine>::Base::Emitter = { \ | 
| - &InstX86Base<Machine>::Traits::Assembler::pmuludq, \ | 
| - &InstX86Base<Machine>::Traits::Assembler::pmuludq}; \ | 
| - template <> \ | 
| - const InstX86Base<Machine>::Traits::Assembler::XmmEmitterRegOp \ | 
| - InstX86Por<Machine>::Base::Emitter = { \ | 
| - &InstX86Base<Machine>::Traits::Assembler::por, \ | 
| - &InstX86Base<Machine>::Traits::Assembler::por}; \ | 
| - template <> \ | 
| - const InstX86Base<Machine>::Traits::Assembler::XmmEmitterRegOp \ | 
| - InstX86Psub<Machine>::Base::Emitter = { \ | 
| - &InstX86Base<Machine>::Traits::Assembler::psub, \ | 
| - &InstX86Base<Machine>::Traits::Assembler::psub}; \ | 
| - template <> \ | 
| - const InstX86Base<Machine>::Traits::Assembler::XmmEmitterRegOp \ | 
| - InstX86Pxor<Machine>::Base::Emitter = { \ | 
| - &InstX86Base<Machine>::Traits::Assembler::pxor, \ | 
| - &InstX86Base<Machine>::Traits::Assembler::pxor}; \ | 
| - template <> \ | 
| - const InstX86Base<Machine>::Traits::Assembler::XmmEmitterRegOp \ | 
| - InstX86Subss<Machine>::Base::Emitter = { \ | 
| - &InstX86Base<Machine>::Traits::Assembler::subss, \ | 
| - &InstX86Base<Machine>::Traits::Assembler::subss}; \ | 
| - template <> \ | 
| - const InstX86Base<Machine>::Traits::Assembler::XmmEmitterRegOp \ | 
| - InstX86Subps<Machine>::Base::Emitter = { \ | 
| - &InstX86Base<Machine>::Traits::Assembler::subps, \ | 
| - &InstX86Base<Machine>::Traits::Assembler::subps}; \ | 
| - template <> \ | 
| - const InstX86Base<Machine>::Traits::Assembler::XmmEmitterRegOp \ | 
| - InstX86Andnps<Machine>::Base::Emitter = { \ | 
| - &InstX86Base<Machine>::Traits::Assembler::andnps, \ | 
| - &InstX86Base<Machine>::Traits::Assembler::andnps}; \ | 
| - template <> \ | 
| - const InstX86Base<Machine>::Traits::Assembler::XmmEmitterRegOp \ | 
| - InstX86Andps<Machine>::Base::Emitter = { \ | 
| - &InstX86Base<Machine>::Traits::Assembler::andps, \ | 
| - &InstX86Base<Machine>::Traits::Assembler::andps}; \ | 
| - template <> \ | 
| - const InstX86Base<Machine>::Traits::Assembler::XmmEmitterRegOp \ | 
| - InstX86Maxss<Machine>::Base::Emitter = { \ | 
| - &InstX86Base<Machine>::Traits::Assembler::maxss, \ | 
| - &InstX86Base<Machine>::Traits::Assembler::maxss}; \ | 
| - template <> \ | 
| - const InstX86Base<Machine>::Traits::Assembler::XmmEmitterRegOp \ | 
| - InstX86Minss<Machine>::Base::Emitter = { \ | 
| - &InstX86Base<Machine>::Traits::Assembler::minss, \ | 
| - &InstX86Base<Machine>::Traits::Assembler::minss}; \ | 
| - template <> \ | 
| - const InstX86Base<Machine>::Traits::Assembler::XmmEmitterRegOp \ | 
| - InstX86Orps<Machine>::Base::Emitter = { \ | 
| - &InstX86Base<Machine>::Traits::Assembler::orps, \ | 
| - &InstX86Base<Machine>::Traits::Assembler::orps}; \ | 
| - template <> \ | 
| - const InstX86Base<Machine>::Traits::Assembler::XmmEmitterRegOp \ | 
| - InstX86Xorps<Machine>::Base::Emitter = { \ | 
| - &InstX86Base<Machine>::Traits::Assembler::xorps, \ | 
| - &InstX86Base<Machine>::Traits::Assembler::xorps}; \ | 
| + const InstImpl<TraitsType>::Assembler::XmmEmitterRegOp \ | 
| + InstImpl<TraitsType>::InstX86MovssRegs::Base::Emitter = {nullptr, \ | 
| + nullptr}; \ | 
| + template <> \ | 
| + template <> \ | 
| + const InstImpl<TraitsType>::Assembler::XmmEmitterRegOp \ | 
| + InstImpl<TraitsType>::InstX86Addss::Base::Emitter = { \ | 
| + &InstImpl<TraitsType>::Assembler::addss, \ | 
| + &InstImpl<TraitsType>::Assembler::addss}; \ | 
| + template <> \ | 
| + template <> \ | 
| + const InstImpl<TraitsType>::Assembler::XmmEmitterRegOp \ | 
| + InstImpl<TraitsType>::InstX86Addps::Base::Emitter = { \ | 
| + &InstImpl<TraitsType>::Assembler::addps, \ | 
| + &InstImpl<TraitsType>::Assembler::addps}; \ | 
| + template <> \ | 
| + template <> \ | 
| + const InstImpl<TraitsType>::Assembler::XmmEmitterRegOp \ | 
| + InstImpl<TraitsType>::InstX86Divss::Base::Emitter = { \ | 
| + &InstImpl<TraitsType>::Assembler::divss, \ | 
| + &InstImpl<TraitsType>::Assembler::divss}; \ | 
| + template <> \ | 
| + template <> \ | 
| + const InstImpl<TraitsType>::Assembler::XmmEmitterRegOp \ | 
| + InstImpl<TraitsType>::InstX86Divps::Base::Emitter = { \ | 
| + &InstImpl<TraitsType>::Assembler::divps, \ | 
| + &InstImpl<TraitsType>::Assembler::divps}; \ | 
| + template <> \ | 
| + template <> \ | 
| + const InstImpl<TraitsType>::Assembler::XmmEmitterRegOp \ | 
| + InstImpl<TraitsType>::InstX86Mulss::Base::Emitter = { \ | 
| + &InstImpl<TraitsType>::Assembler::mulss, \ | 
| + &InstImpl<TraitsType>::Assembler::mulss}; \ | 
| + template <> \ | 
| + template <> \ | 
| + const InstImpl<TraitsType>::Assembler::XmmEmitterRegOp \ | 
| + InstImpl<TraitsType>::InstX86Mulps::Base::Emitter = { \ | 
| + &InstImpl<TraitsType>::Assembler::mulps, \ | 
| + &InstImpl<TraitsType>::Assembler::mulps}; \ | 
| + template <> \ | 
| + template <> \ | 
| + const InstImpl<TraitsType>::Assembler::XmmEmitterRegOp \ | 
| + InstImpl<TraitsType>::InstX86Padd::Base::Emitter = { \ | 
| + &InstImpl<TraitsType>::Assembler::padd, \ | 
| + &InstImpl<TraitsType>::Assembler::padd}; \ | 
| + template <> \ | 
| + template <> \ | 
| + const InstImpl<TraitsType>::Assembler::XmmEmitterRegOp \ | 
| + InstImpl<TraitsType>::InstX86Pand::Base::Emitter = { \ | 
| + &InstImpl<TraitsType>::Assembler::pand, \ | 
| + &InstImpl<TraitsType>::Assembler::pand}; \ | 
| + template <> \ | 
| + template <> \ | 
| + const InstImpl<TraitsType>::Assembler::XmmEmitterRegOp \ | 
| + InstImpl<TraitsType>::InstX86Pandn::Base::Emitter = { \ | 
| + &InstImpl<TraitsType>::Assembler::pandn, \ | 
| + &InstImpl<TraitsType>::Assembler::pandn}; \ | 
| + template <> \ | 
| + template <> \ | 
| + const InstImpl<TraitsType>::Assembler::XmmEmitterRegOp \ | 
| + InstImpl<TraitsType>::InstX86Pcmpeq::Base::Emitter = { \ | 
| + &InstImpl<TraitsType>::Assembler::pcmpeq, \ | 
| + &InstImpl<TraitsType>::Assembler::pcmpeq}; \ | 
| + template <> \ | 
| + template <> \ | 
| + const InstImpl<TraitsType>::Assembler::XmmEmitterRegOp \ | 
| + InstImpl<TraitsType>::InstX86Pcmpgt::Base::Emitter = { \ | 
| + &InstImpl<TraitsType>::Assembler::pcmpgt, \ | 
| + &InstImpl<TraitsType>::Assembler::pcmpgt}; \ | 
| + template <> \ | 
| + template <> \ | 
| + const InstImpl<TraitsType>::Assembler::XmmEmitterRegOp \ | 
| + InstImpl<TraitsType>::InstX86Pmull::Base::Emitter = { \ | 
| + &InstImpl<TraitsType>::Assembler::pmull, \ | 
| + &InstImpl<TraitsType>::Assembler::pmull}; \ | 
| + template <> \ | 
| + template <> \ | 
| + const InstImpl<TraitsType>::Assembler::XmmEmitterRegOp \ | 
| + InstImpl<TraitsType>::InstX86Pmuludq::Base::Emitter = { \ | 
| + &InstImpl<TraitsType>::Assembler::pmuludq, \ | 
| + &InstImpl<TraitsType>::Assembler::pmuludq}; \ | 
| + template <> \ | 
| + template <> \ | 
| + const InstImpl<TraitsType>::Assembler::XmmEmitterRegOp \ | 
| + InstImpl<TraitsType>::InstX86Por::Base::Emitter = { \ | 
| + &InstImpl<TraitsType>::Assembler::por, \ | 
| + &InstImpl<TraitsType>::Assembler::por}; \ | 
| + template <> \ | 
| + template <> \ | 
| + const InstImpl<TraitsType>::Assembler::XmmEmitterRegOp \ | 
| + InstImpl<TraitsType>::InstX86Psub::Base::Emitter = { \ | 
| + &InstImpl<TraitsType>::Assembler::psub, \ | 
| + &InstImpl<TraitsType>::Assembler::psub}; \ | 
| + template <> \ | 
| + template <> \ | 
| + const InstImpl<TraitsType>::Assembler::XmmEmitterRegOp \ | 
| + InstImpl<TraitsType>::InstX86Pxor::Base::Emitter = { \ | 
| + &InstImpl<TraitsType>::Assembler::pxor, \ | 
| + &InstImpl<TraitsType>::Assembler::pxor}; \ | 
| + template <> \ | 
| + template <> \ | 
| + const InstImpl<TraitsType>::Assembler::XmmEmitterRegOp \ | 
| + InstImpl<TraitsType>::InstX86Subss::Base::Emitter = { \ | 
| + &InstImpl<TraitsType>::Assembler::subss, \ | 
| + &InstImpl<TraitsType>::Assembler::subss}; \ | 
| + template <> \ | 
| + template <> \ | 
| + const InstImpl<TraitsType>::Assembler::XmmEmitterRegOp \ | 
| + InstImpl<TraitsType>::InstX86Subps::Base::Emitter = { \ | 
| + &InstImpl<TraitsType>::Assembler::subps, \ | 
| + &InstImpl<TraitsType>::Assembler::subps}; \ | 
| + template <> \ | 
| + template <> \ | 
| + const InstImpl<TraitsType>::Assembler::XmmEmitterRegOp \ | 
| + InstImpl<TraitsType>::InstX86Andnps::Base::Emitter = { \ | 
| + &InstImpl<TraitsType>::Assembler::andnps, \ | 
| + &InstImpl<TraitsType>::Assembler::andnps}; \ | 
| + template <> \ | 
| + template <> \ | 
| + const InstImpl<TraitsType>::Assembler::XmmEmitterRegOp \ | 
| + InstImpl<TraitsType>::InstX86Andps::Base::Emitter = { \ | 
| + &InstImpl<TraitsType>::Assembler::andps, \ | 
| + &InstImpl<TraitsType>::Assembler::andps}; \ | 
| + template <> \ | 
| + template <> \ | 
| + const InstImpl<TraitsType>::Assembler::XmmEmitterRegOp \ | 
| + InstImpl<TraitsType>::InstX86Maxss::Base::Emitter = { \ | 
| + &InstImpl<TraitsType>::Assembler::maxss, \ | 
| + &InstImpl<TraitsType>::Assembler::maxss}; \ | 
| + template <> \ | 
| + template <> \ | 
| + const InstImpl<TraitsType>::Assembler::XmmEmitterRegOp \ | 
| + InstImpl<TraitsType>::InstX86Minss::Base::Emitter = { \ | 
| + &InstImpl<TraitsType>::Assembler::minss, \ | 
| + &InstImpl<TraitsType>::Assembler::minss}; \ | 
| + template <> \ | 
| + template <> \ | 
| + const InstImpl<TraitsType>::Assembler::XmmEmitterRegOp \ | 
| + InstImpl<TraitsType>::InstX86Orps::Base::Emitter = { \ | 
| + &InstImpl<TraitsType>::Assembler::orps, \ | 
| + &InstImpl<TraitsType>::Assembler::orps}; \ | 
| + template <> \ | 
| + template <> \ | 
| + const InstImpl<TraitsType>::Assembler::XmmEmitterRegOp \ | 
| + InstImpl<TraitsType>::InstX86Xorps::Base::Emitter = { \ | 
| + &InstImpl<TraitsType>::Assembler::xorps, \ | 
| + &InstImpl<TraitsType>::Assembler::xorps}; \ | 
| \ | 
| /* Binary XMM Shift ops */ \ | 
| template <> \ | 
| - const InstX86Base<Machine>::Traits::Assembler::XmmEmitterShiftOp \ | 
| - InstX86Psll<Machine>::Base::Emitter = { \ | 
| - &InstX86Base<Machine>::Traits::Assembler::psll, \ | 
| - &InstX86Base<Machine>::Traits::Assembler::psll, \ | 
| - &InstX86Base<Machine>::Traits::Assembler::psll}; \ | 
| - template <> \ | 
| - const InstX86Base<Machine>::Traits::Assembler::XmmEmitterShiftOp \ | 
| - InstX86Psra<Machine>::Base::Emitter = { \ | 
| - &InstX86Base<Machine>::Traits::Assembler::psra, \ | 
| - &InstX86Base<Machine>::Traits::Assembler::psra, \ | 
| - &InstX86Base<Machine>::Traits::Assembler::psra}; \ | 
| - template <> \ | 
| - const InstX86Base<Machine>::Traits::Assembler::XmmEmitterShiftOp \ | 
| - InstX86Psrl<Machine>::Base::Emitter = { \ | 
| - &InstX86Base<Machine>::Traits::Assembler::psrl, \ | 
| - &InstX86Base<Machine>::Traits::Assembler::psrl, \ | 
| - &InstX86Base<Machine>::Traits::Assembler::psrl}; \ | 
| + template <> \ | 
| + const InstImpl<TraitsType>::Assembler::XmmEmitterShiftOp \ | 
| + InstImpl<TraitsType>::InstX86Psll::Base::Emitter = { \ | 
| + &InstImpl<TraitsType>::Assembler::psll, \ | 
| + &InstImpl<TraitsType>::Assembler::psll, \ | 
| + &InstImpl<TraitsType>::Assembler::psll}; \ | 
| + template <> \ | 
| + template <> \ | 
| + const InstImpl<TraitsType>::Assembler::XmmEmitterShiftOp \ | 
| + InstImpl<TraitsType>::InstX86Psra::Base::Emitter = { \ | 
| + &InstImpl<TraitsType>::Assembler::psra, \ | 
| + &InstImpl<TraitsType>::Assembler::psra, \ | 
| + &InstImpl<TraitsType>::Assembler::psra}; \ | 
| + template <> \ | 
| + template <> \ | 
| + const InstImpl<TraitsType>::Assembler::XmmEmitterShiftOp \ | 
| + InstImpl<TraitsType>::InstX86Psrl::Base::Emitter = { \ | 
| + &InstImpl<TraitsType>::Assembler::psrl, \ | 
| + &InstImpl<TraitsType>::Assembler::psrl, \ | 
| + &InstImpl<TraitsType>::Assembler::psrl}; \ | 
| } \ | 
| } | 
| -} // end of namespace X86Internal | 
| +} // end of namespace X86NAMESPACE | 
| } // end of namespace Ice | 
| #include "IceInstX86BaseImpl.h" |