Index: src/IceInstX86Base.h |
diff --git a/src/IceInstX86Base.h b/src/IceInstX86Base.h |
new file mode 100644 |
index 0000000000000000000000000000000000000000..8abdf2591f4e826d9e00026913f119d768221edb |
--- /dev/null |
+++ b/src/IceInstX86Base.h |
@@ -0,0 +1,3191 @@ |
+//===- subzero/src/IceInstX86Base.h - Generic x86 instructions -*- C++ -*--===// |
+// |
+// The Subzero Code Generator |
+// |
+// This file is distributed under the University of Illinois Open Source |
+// License. See LICENSE.TXT for details. |
+// |
+//===----------------------------------------------------------------------===// |
+// |
+// This file defines the InstX86Base and OperandX86Base template classes that |
jvoung (off chromium)
2015/07/06 18:58:45
Is there a OperandX86Base template class? I see so
John
2015/07/06 22:30:09
There's an X86Operand class defined in the X8632 T
|
+// are shared accross all x86 targets. |
jvoung (off chromium)
2015/07/06 18:58:45
accross -> across
John
2015/07/06 22:30:09
Done.
|
+// |
+//===----------------------------------------------------------------------===// |
+ |
+#ifndef SUBZERO_SRC_ICEINSTX86BASE_H |
+#define SUBZERO_SRC_ICEINSTX86BASE_H |
+ |
+#include "IceDefs.h" |
+#include "IceInst.h" |
+#include "IceOperand.h" |
+ |
+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>; |
+ |
+ enum InstKindX86 { |
+ k__Start = Inst::Target, |
+ Adc, |
+ AdcRMW, |
+ Add, |
+ AddRMW, |
+ Addps, |
+ Addss, |
+ Adjuststack, |
+ And, |
+ AndRMW, |
+ Blendvps, |
+ Br, |
+ Bsf, |
+ Bsr, |
+ Bswap, |
+ Call, |
+ Cbwdq, |
+ Cmov, |
+ Cmpps, |
+ Cmpxchg, |
+ Cmpxchg8b, |
+ Cvt, |
+ Div, |
+ Divps, |
+ Divss, |
+ FakeRMW, |
+ Fld, |
+ Fstp, |
+ Icmp, |
+ Idiv, |
+ Imul, |
+ Insertps, |
+ Jmp, |
+ Label, |
+ Lea, |
+ Load, |
+ Mfence, |
+ Mov, |
+ Movd, |
+ Movp, |
+ Movq, |
+ MovssRegs, |
+ Movsx, |
+ Movzx, |
+ Mul, |
+ Mulps, |
+ Mulss, |
+ Neg, |
+ Nop, |
+ Or, |
+ 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, |
+ XorRMW |
+ }; |
+ |
+ 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. |
+ // See the definition of emitTwoAddress() for a description of |
+ // ShiftHack. |
+ static void emitTwoAddress(const char *Opcode, const Inst *Inst, |
+ const Cfg *Func, bool ShiftHack = false); |
+ |
+ static void |
+ emitIASGPRShift(const Cfg *Func, Type Ty, const Variable *Var, |
+ const Operand *Src, |
+ const typename Traits::Assembler::GPREmitterShiftOp &Emitter); |
+ |
+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()) |
+ 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<typename InstX86Base<Machine>::Traits::X86OperandMem>(Opnd) && |
+ isVectorType(Opnd->getType())) { |
+ llvm::report_fatal_error("Possible misaligned vector memory operation"); |
+ } |
+ } |
+}; |
+ |
+// InstX86BaseFakeRMW represents a non-atomic read-modify-write operation on a |
+// memory location. An InstX86BaseFakeRMW 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 InstX86BaseFakeRMW : public InstX86Base<Machine> { |
+ InstX86BaseFakeRMW() = delete; |
+ InstX86BaseFakeRMW(const InstX86BaseFakeRMW &) = delete; |
+ InstX86BaseFakeRMW &operator=(const InstX86BaseFakeRMW &) = delete; |
+ |
+public: |
+ static InstX86BaseFakeRMW *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<InstX86BaseFakeRMW>()) |
+ InstX86BaseFakeRMW(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; |
+ InstX86BaseFakeRMW(Cfg *Func, Operand *Data, Operand *Addr, |
+ InstArithmetic::OpKind Op, Variable *Beacon); |
+}; |
+ |
+// InstX86BaseLabel 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 InstX86BaseLabel : public InstX86Base<Machine> { |
+ InstX86BaseLabel() = delete; |
+ InstX86BaseLabel(const InstX86BaseLabel &) = delete; |
+ InstX86BaseLabel &operator=(const InstX86BaseLabel &) = delete; |
+ |
+public: |
+ static InstX86BaseLabel * |
+ create(Cfg *Func, |
+ typename InstX86Base<Machine>::Traits::TargetLowering *Target) { |
+ return new (Func->allocate<InstX86BaseLabel>()) |
+ InstX86BaseLabel(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: |
+ InstX86BaseLabel( |
+ Cfg *Func, typename InstX86Base<Machine>::Traits::TargetLowering *Target); |
+ |
+ SizeT Number; // used for unique label generation. |
+}; |
+ |
+// Conditional and unconditional branch instruction. |
+template <class Machine> class InstX86BaseBr : public InstX86Base<Machine> { |
+ InstX86BaseBr() = delete; |
+ InstX86BaseBr(const InstX86BaseBr &) = delete; |
+ InstX86BaseBr &operator=(const InstX86BaseBr &) = delete; |
+ |
+public: |
+ // Create a conditional branch to a node. |
+ static InstX86BaseBr * |
+ create(Cfg *Func, CfgNode *TargetTrue, CfgNode *TargetFalse, |
+ typename InstX86Base<Machine>::Traits::Cond::BrCond Condition) { |
+ assert(Condition != InstX86Base<Machine>::Traits::Cond::Br_None); |
+ const InstX86BaseLabel<Machine> *NoLabel = nullptr; |
+ return new (Func->allocate<InstX86BaseBr>()) |
+ InstX86BaseBr(Func, TargetTrue, TargetFalse, NoLabel, Condition); |
+ } |
+ // Create an unconditional branch to a node. |
+ static InstX86BaseBr *create(Cfg *Func, CfgNode *Target) { |
+ const CfgNode *NoCondTarget = nullptr; |
+ const InstX86BaseLabel<Machine> *NoLabel = nullptr; |
+ return new (Func->allocate<InstX86BaseBr>()) |
+ InstX86BaseBr(Func, NoCondTarget, Target, NoLabel, |
+ InstX86Base<Machine>::Traits::Cond::Br_None); |
+ } |
+ // 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 InstX86BaseBr * |
+ create(Cfg *Func, CfgNode *Target, |
+ typename InstX86Base<Machine>::Traits::Cond::BrCond Condition) { |
+ assert(Condition != InstX86Base<Machine>::Traits::Cond::Br_None); |
+ const CfgNode *NoUncondTarget = nullptr; |
+ const InstX86BaseLabel<Machine> *NoLabel = nullptr; |
+ return new (Func->allocate<InstX86BaseBr>()) |
+ InstX86BaseBr(Func, Target, NoUncondTarget, NoLabel, Condition); |
+ } |
+ // Create a conditional intra-block branch (or unconditional, if |
+ // Condition==Br_None) to a label in the current block. |
+ static InstX86BaseBr * |
+ create(Cfg *Func, InstX86BaseLabel<Machine> *Label, |
+ typename InstX86Base<Machine>::Traits::Cond::BrCond Condition) { |
+ const CfgNode *NoCondTarget = nullptr; |
+ const CfgNode *NoUncondTarget = nullptr; |
+ return new (Func->allocate<InstX86BaseBr>()) |
+ InstX86BaseBr(Func, NoCondTarget, NoUncondTarget, Label, Condition); |
+ } |
+ const CfgNode *getTargetTrue() const { return TargetTrue; } |
+ const CfgNode *getTargetFalse() const { return TargetFalse; } |
+ 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 repointEdge(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); |
+ } |
+ |
+private: |
+ InstX86BaseBr(Cfg *Func, const CfgNode *TargetTrue, |
+ const CfgNode *TargetFalse, |
+ const InstX86BaseLabel<Machine> *Label, |
+ typename InstX86Base<Machine>::Traits::Cond::BrCond Condition); |
+ |
+ typename InstX86Base<Machine>::Traits::Cond::BrCond Condition; |
+ const CfgNode *TargetTrue; |
+ const CfgNode *TargetFalse; |
+ const InstX86BaseLabel<Machine> *Label; // Intra-block branch target |
+}; |
+ |
+// 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 InstX86BaseJmp : public InstX86Base<Machine> { |
+ InstX86BaseJmp() = delete; |
+ InstX86BaseJmp(const InstX86BaseJmp &) = delete; |
+ InstX86BaseJmp &operator=(const InstX86BaseJmp &) = delete; |
+ |
+public: |
+ static InstX86BaseJmp *create(Cfg *Func, Operand *Target) { |
+ return new (Func->allocate<InstX86BaseJmp>()) InstX86BaseJmp(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: |
+ InstX86BaseJmp(Cfg *Func, Operand *Target); |
+}; |
+ |
+// AdjustStack instruction - subtracts esp by the given amount and |
+// updates the stack offset during code emission. |
+template <class Machine> |
+class InstX86BaseAdjustStack : public InstX86Base<Machine> { |
+ InstX86BaseAdjustStack() = delete; |
+ InstX86BaseAdjustStack(const InstX86BaseAdjustStack &) = delete; |
+ InstX86BaseAdjustStack &operator=(const InstX86BaseAdjustStack &) = delete; |
+ |
+public: |
+ static InstX86BaseAdjustStack *create(Cfg *Func, SizeT Amount, |
+ Variable *Esp) { |
+ return new (Func->allocate<InstX86BaseAdjustStack>()) |
+ InstX86BaseAdjustStack(Func, Amount, Esp); |
+ } |
+ 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>::Adjuststack); |
+ } |
+ |
+private: |
+ InstX86BaseAdjustStack(Cfg *Func, SizeT Amount, Variable *Esp); |
+ SizeT Amount; |
+}; |
+ |
+// Call instruction. Arguments should have already been pushed. |
+template <class Machine> class InstX86BaseCall : public InstX86Base<Machine> { |
+ InstX86BaseCall() = delete; |
+ InstX86BaseCall(const InstX86BaseCall &) = delete; |
+ InstX86BaseCall &operator=(const InstX86BaseCall &) = delete; |
+ |
+public: |
+ static InstX86BaseCall *create(Cfg *Func, Variable *Dest, |
+ Operand *CallTarget) { |
+ return new (Func->allocate<InstX86BaseCall>()) |
+ InstX86BaseCall(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: |
+ InstX86BaseCall(Cfg *Func, Variable *Dest, Operand *CallTarget); |
+}; |
+ |
+// 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); |
+ } |
+ |
+protected: |
+ InstX86BaseInplaceopGPR(Cfg *Func, Operand *SrcDest) |
+ : InstX86Base<Machine>(Func, K, 1, llvm::dyn_cast<Variable>(SrcDest)) { |
+ this->addSource(SrcDest); |
+ } |
+ |
+private: |
+ static const char *Opcode; |
+ static const typename InstX86Base<Machine>::Traits::Assembler::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); |
+ } |
+ |
+protected: |
+ InstX86BaseUnaryopGPR(Cfg *Func, Variable *Dest, Operand *Src) |
+ : InstX86Base<Machine>(Func, K, 1, Dest) { |
+ this->addSource(Src); |
+ } |
+ |
+ static const char *Opcode; |
+ static const typename InstX86Base<Machine>::Traits::Assembler::GPREmitterRegOp |
+ 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); |
+ } |
+ |
+protected: |
+ InstX86BaseUnaryopXmm(Cfg *Func, Variable *Dest, Operand *Src) |
+ : InstX86Base<Machine>(Func, K, 1, Dest) { |
+ this->addSource(Src); |
+ } |
+ |
+ static const char *Opcode; |
+ static const typename InstX86Base<Machine>::Traits::Assembler::XmmEmitterRegOp |
+ Emitter; |
+}; |
+ |
+template <class Machine, typename InstX86Base<Machine>::InstKindX86 K> |
+class InstX86BaseBinopGPRShift : public InstX86Base<Machine> { |
+ InstX86BaseBinopGPRShift() = delete; |
+ InstX86BaseBinopGPRShift(const InstX86BaseBinopGPRShift &) = delete; |
+ InstX86BaseBinopGPRShift & |
+ operator=(const InstX86BaseBinopGPRShift &) = delete; |
+ |
+public: |
+ using Base = InstX86BaseBinopGPRShift<Machine, K>; |
+ |
+ void emit(const Cfg *Func) const override { |
+ if (!BuildDefs::dump()) |
+ return; |
+ const bool ShiftHack = true; |
+ this->emitTwoAddress(Opcode, this, Func, ShiftHack); |
+ } |
+ 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); |
+ } |
+ |
+protected: |
+ InstX86BaseBinopGPRShift(Cfg *Func, Variable *Dest, Operand *Source) |
+ : InstX86Base<Machine>(Func, K, 2, Dest) { |
+ this->addSource(Dest); |
+ this->addSource(Source); |
+ } |
+ |
+ static const char *Opcode; |
+ static const typename InstX86Base< |
+ Machine>::Traits::Assembler::GPREmitterShiftOp 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; |
+ |
+public: |
+ using Base = InstX86BaseBinopGPR<Machine, K>; |
+ |
+ void emit(const Cfg *Func) const override { |
+ if (!BuildDefs::dump()) |
+ return; |
+ const bool ShiftHack = false; |
+ this->emitTwoAddress(Opcode, this, Func, ShiftHack); |
+ } |
+ 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); |
+ } |
+ |
+protected: |
+ InstX86BaseBinopGPR(Cfg *Func, Variable *Dest, Operand *Source) |
+ : InstX86Base<Machine>(Func, K, 2, Dest) { |
+ this->addSource(Dest); |
+ this->addSource(Source); |
+ } |
+ |
+ static const char *Opcode; |
+ static const typename InstX86Base<Machine>::Traits::Assembler::GPREmitterRegOp |
+ Emitter; |
+}; |
+ |
+template <class Machine, typename InstX86Base<Machine>::InstKindX86 K> |
+class InstX86BaseBinopRMW : public InstX86Base<Machine> { |
+ InstX86BaseBinopRMW() = delete; |
+ InstX86BaseBinopRMW(const InstX86BaseBinopRMW &) = delete; |
+ InstX86BaseBinopRMW &operator=(const InstX86BaseBinopRMW &) = delete; |
+ |
+public: |
+ using Base = InstX86BaseBinopRMW<Machine, K>; |
+ |
+ void emit(const Cfg *Func) const override { |
+ if (!BuildDefs::dump()) |
+ return; |
+ const bool ShiftHack = false; |
+ this->emitTwoAddress(Opcode, this, Func, ShiftHack); |
+ } |
+ 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); |
+ } |
+ |
+protected: |
+ InstX86BaseBinopRMW( |
+ Cfg *Func, typename InstX86Base<Machine>::Traits::X86OperandMem *DestSrc0, |
+ Operand *Src1) |
+ : InstX86Base<Machine>(Func, K, 2, nullptr) { |
+ this->addSource(DestSrc0); |
+ this->addSource(Src1); |
+ } |
+ |
+ static const char *Opcode; |
+ static const typename InstX86Base< |
+ Machine>::Traits::Assembler::GPREmitterAddrOp Emitter; |
+}; |
+ |
+template <class Machine, typename InstX86Base<Machine>::InstKindX86 K, |
+ bool NeedsElementType> |
+class InstX86BaseBinopXmm : public InstX86Base<Machine> { |
+ InstX86BaseBinopXmm() = delete; |
+ InstX86BaseBinopXmm(const InstX86BaseBinopXmm &) = delete; |
+ InstX86BaseBinopXmm &operator=(const InstX86BaseBinopXmm &) = delete; |
+ |
+public: |
+ using Base = InstX86BaseBinopXmm<Machine, K, NeedsElementType>; |
+ |
+ void emit(const Cfg *Func) const override { |
+ if (!BuildDefs::dump()) |
+ return; |
+ this->validateVectorAddrMode(); |
+ const bool ShiftHack = false; |
+ this->emitTwoAddress(Opcode, this, Func, ShiftHack); |
+ } |
+ 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); |
+ } |
+ |
+protected: |
+ InstX86BaseBinopXmm(Cfg *Func, Variable *Dest, Operand *Source) |
+ : InstX86Base<Machine>(Func, K, 2, Dest) { |
+ this->addSource(Dest); |
+ this->addSource(Source); |
+ } |
+ |
+ static const char *Opcode; |
+ static const typename InstX86Base<Machine>::Traits::Assembler::XmmEmitterRegOp |
+ 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(); |
+ const bool ShiftHack = false; |
+ this->emitTwoAddress(Opcode, this, Func, ShiftHack); |
+ } |
+ 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); |
+ } |
+ |
+protected: |
+ InstX86BaseBinopXmmShift(Cfg *Func, Variable *Dest, Operand *Source) |
+ : InstX86Base<Machine>(Func, K, 2, Dest) { |
+ this->addSource(Dest); |
+ this->addSource(Source); |
+ } |
+ |
+ static const char *Opcode; |
+ static const typename InstX86Base< |
+ Machine>::Traits::Assembler::XmmEmitterShiftOp Emitter; |
+}; |
+ |
+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: |
+ 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; |
+}; |
+ |
+// 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: |
+ 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; |
+}; |
+ |
+// 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 { |
+ return checkForRedundantAssign(this->getDest(), this->getSrc(0)); |
+ } |
+ bool isSimpleAssign() const override { return true; } |
+ 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); |
+ } |
+ |
+ static const char *Opcode; |
+}; |
+ |
+template <class Machine> |
+class InstX86BaseBswap |
+ : public InstX86BaseInplaceopGPR<Machine, InstX86Base<Machine>::Bswap> { |
+public: |
+ static InstX86BaseBswap *create(Cfg *Func, Operand *SrcDest) { |
+ return new (Func->allocate<InstX86BaseBswap>()) |
+ InstX86BaseBswap(Func, SrcDest); |
+ } |
+ |
+private: |
+ InstX86BaseBswap(Cfg *Func, Operand *SrcDest) |
+ : InstX86BaseInplaceopGPR<Machine, InstX86Base<Machine>::Bswap>(Func, |
+ SrcDest) { |
+ } |
+}; |
+ |
+template <class Machine> |
+class InstX86BaseNeg |
+ : public InstX86BaseInplaceopGPR<Machine, InstX86Base<Machine>::Neg> { |
+public: |
+ static InstX86BaseNeg *create(Cfg *Func, Operand *SrcDest) { |
+ return new (Func->allocate<InstX86BaseNeg>()) InstX86BaseNeg(Func, SrcDest); |
+ } |
+ |
+private: |
+ InstX86BaseNeg(Cfg *Func, Operand *SrcDest) |
+ : InstX86BaseInplaceopGPR<Machine, InstX86Base<Machine>::Neg>(Func, |
+ SrcDest) {} |
+}; |
+ |
+template <class Machine> |
+class InstX86BaseBsf |
+ : public InstX86BaseUnaryopGPR<Machine, InstX86Base<Machine>::Bsf> { |
+public: |
+ static InstX86BaseBsf *create(Cfg *Func, Variable *Dest, Operand *Src) { |
+ return new (Func->allocate<InstX86BaseBsf>()) |
+ InstX86BaseBsf(Func, Dest, Src); |
+ } |
+ |
+private: |
+ InstX86BaseBsf(Cfg *Func, Variable *Dest, Operand *Src) |
+ : InstX86BaseUnaryopGPR<Machine, InstX86Base<Machine>::Bsf>(Func, Dest, |
+ Src) {} |
+}; |
+ |
+template <class Machine> |
+class InstX86BaseBsr |
+ : public InstX86BaseUnaryopGPR<Machine, InstX86Base<Machine>::Bsr> { |
+public: |
+ static InstX86BaseBsr *create(Cfg *Func, Variable *Dest, Operand *Src) { |
+ return new (Func->allocate<InstX86BaseBsr>()) |
+ InstX86BaseBsr(Func, Dest, Src); |
+ } |
+ |
+private: |
+ InstX86BaseBsr(Cfg *Func, Variable *Dest, Operand *Src) |
+ : InstX86BaseUnaryopGPR<Machine, InstX86Base<Machine>::Bsr>(Func, Dest, |
+ Src) {} |
+}; |
+ |
+template <class Machine> |
+class InstX86BaseLea |
+ : public InstX86BaseUnaryopGPR<Machine, InstX86Base<Machine>::Lea> { |
+public: |
+ static InstX86BaseLea *create(Cfg *Func, Variable *Dest, Operand *Src) { |
+ return new (Func->allocate<InstX86BaseLea>()) |
+ InstX86BaseLea(Func, Dest, Src); |
+ } |
+ |
+ void emit(const Cfg *Func) const override; |
+ |
+private: |
+ InstX86BaseLea(Cfg *Func, Variable *Dest, Operand *Src) |
+ : InstX86BaseUnaryopGPR<Machine, InstX86Base<Machine>::Lea>(Func, Dest, |
+ Src) {} |
+}; |
+ |
+// Cbwdq instruction - wrapper for cbw, cwd, and cdq |
+template <class Machine> |
+class InstX86BaseCbwdq |
+ : public InstX86BaseUnaryopGPR<Machine, InstX86Base<Machine>::Cbwdq> { |
+public: |
+ static InstX86BaseCbwdq *create(Cfg *Func, Variable *Dest, Operand *Src) { |
+ return new (Func->allocate<InstX86BaseCbwdq>()) |
+ InstX86BaseCbwdq(Func, Dest, Src); |
+ } |
+ |
+ void emit(const Cfg *Func) const override; |
+ void emitIAS(const Cfg *Func) const override; |
+ |
+private: |
+ InstX86BaseCbwdq(Cfg *Func, Variable *Dest, Operand *Src) |
+ : InstX86BaseUnaryopGPR<Machine, InstX86Base<Machine>::Cbwdq>(Func, Dest, |
+ Src) {} |
+}; |
+ |
+template <class Machine> |
+class InstX86BaseMovsx |
+ : public InstX86BaseUnaryopGPR<Machine, InstX86Base<Machine>::Movsx> { |
+public: |
+ static InstX86BaseMovsx *create(Cfg *Func, Variable *Dest, Operand *Src) { |
+ return new (Func->allocate<InstX86BaseMovsx>()) |
+ InstX86BaseMovsx(Func, Dest, Src); |
+ } |
+ |
+ void emitIAS(const Cfg *Func) const override; |
+ |
+private: |
+ InstX86BaseMovsx(Cfg *Func, Variable *Dest, Operand *Src) |
+ : InstX86BaseUnaryopGPR<Machine, InstX86Base<Machine>::Movsx>(Func, Dest, |
+ Src) {} |
+}; |
+ |
+template <class Machine> |
+class InstX86BaseMovzx |
+ : public InstX86BaseUnaryopGPR<Machine, InstX86Base<Machine>::Movzx> { |
+public: |
+ static InstX86BaseMovzx *create(Cfg *Func, Variable *Dest, Operand *Src) { |
+ return new (Func->allocate<InstX86BaseMovzx>()) |
+ InstX86BaseMovzx(Func, Dest, Src); |
+ } |
+ |
+ void emitIAS(const Cfg *Func) const override; |
+ |
+private: |
+ InstX86BaseMovzx(Cfg *Func, Variable *Dest, Operand *Src) |
+ : InstX86BaseUnaryopGPR<Machine, InstX86Base<Machine>::Movzx>(Func, Dest, |
+ Src) {} |
+}; |
+ |
+template <class Machine> |
+class InstX86BaseMovd |
+ : public InstX86BaseUnaryopXmm<Machine, InstX86Base<Machine>::Movd> { |
+public: |
+ static InstX86BaseMovd *create(Cfg *Func, Variable *Dest, Operand *Src) { |
+ return new (Func->allocate<InstX86BaseMovd>()) |
+ InstX86BaseMovd(Func, Dest, Src); |
+ } |
+ |
+ void emitIAS(const Cfg *Func) const override; |
+ |
+private: |
+ InstX86BaseMovd(Cfg *Func, Variable *Dest, Operand *Src) |
+ : InstX86BaseUnaryopXmm<Machine, InstX86Base<Machine>::Movd>(Func, Dest, |
+ Src) {} |
+}; |
+ |
+template <class Machine> |
+class InstX86BaseSqrtss |
+ : public InstX86BaseUnaryopXmm<Machine, InstX86Base<Machine>::Sqrtss> { |
+public: |
+ static InstX86BaseSqrtss *create(Cfg *Func, Variable *Dest, Operand *Src) { |
+ return new (Func->allocate<InstX86BaseSqrtss>()) |
+ InstX86BaseSqrtss(Func, Dest, Src); |
+ } |
+ |
+ virtual void emit(const Cfg *Func) const override; |
+ |
+private: |
+ InstX86BaseSqrtss(Cfg *Func, Variable *Dest, Operand *Src) |
+ : InstX86BaseUnaryopXmm<Machine, InstX86Base<Machine>::Sqrtss>(Func, Dest, |
+ Src) {} |
+}; |
+ |
+// Move/assignment instruction - wrapper for mov/movss/movsd. |
+template <class Machine> |
+class InstX86BaseMov |
+ : public InstX86BaseMovlike<Machine, InstX86Base<Machine>::Mov> { |
+public: |
+ static InstX86BaseMov *create(Cfg *Func, Variable *Dest, Operand *Source) { |
+ return new (Func->allocate<InstX86BaseMov>()) |
+ InstX86BaseMov(Func, Dest, Source); |
+ } |
+ |
+ void emit(const Cfg *Func) const override; |
+ void emitIAS(const Cfg *Func) const override; |
+ |
+private: |
+ InstX86BaseMov(Cfg *Func, Variable *Dest, Operand *Source) |
+ : InstX86BaseMovlike<Machine, InstX86Base<Machine>::Mov>(Func, Dest, |
+ Source) {} |
+}; |
+ |
+// Move packed - copy 128 bit values between XMM registers, or mem128 |
+// and XMM registers. |
+template <class Machine> |
+class InstX86BaseMovp |
+ : public InstX86BaseMovlike<Machine, InstX86Base<Machine>::Movp> { |
+public: |
+ static InstX86BaseMovp *create(Cfg *Func, Variable *Dest, Operand *Source) { |
+ return new (Func->allocate<InstX86BaseMovp>()) |
+ InstX86BaseMovp(Func, Dest, Source); |
+ } |
+ |
+ void emit(const Cfg *Func) const override; |
+ void emitIAS(const Cfg *Func) const override; |
+ |
+private: |
+ InstX86BaseMovp(Cfg *Func, Variable *Dest, Operand *Source) |
+ : InstX86BaseMovlike<Machine, InstX86Base<Machine>::Movp>(Func, Dest, |
+ Source) {} |
+}; |
+ |
+// Movq - copy between XMM registers, or mem64 and XMM registers. |
+template <class Machine> |
+class InstX86BaseMovq |
+ : public InstX86BaseMovlike<Machine, InstX86Base<Machine>::Movq> { |
+public: |
+ static InstX86BaseMovq *create(Cfg *Func, Variable *Dest, Operand *Source) { |
+ return new (Func->allocate<InstX86BaseMovq>()) |
+ InstX86BaseMovq(Func, Dest, Source); |
+ } |
+ |
+ void emit(const Cfg *Func) const override; |
+ void emitIAS(const Cfg *Func) const override; |
+ |
+private: |
+ InstX86BaseMovq(Cfg *Func, Variable *Dest, Operand *Source) |
+ : InstX86BaseMovlike<Machine, InstX86Base<Machine>::Movq>(Func, Dest, |
+ Source) {} |
+}; |
+ |
+template <class Machine> |
+class InstX86BaseAdd |
+ : public InstX86BaseBinopGPR<Machine, InstX86Base<Machine>::Add> { |
+public: |
+ static InstX86BaseAdd *create(Cfg *Func, Variable *Dest, Operand *Source) { |
+ return new (Func->allocate<InstX86BaseAdd>()) |
+ InstX86BaseAdd(Func, Dest, Source); |
+ } |
+ |
+private: |
+ InstX86BaseAdd(Cfg *Func, Variable *Dest, Operand *Source) |
+ : InstX86BaseBinopGPR<Machine, InstX86Base<Machine>::Add>(Func, Dest, |
+ Source) {} |
+}; |
+ |
+template <class Machine> |
+class InstX86BaseAddRMW |
+ : public InstX86BaseBinopRMW<Machine, InstX86Base<Machine>::AddRMW> { |
+public: |
+ static InstX86BaseAddRMW * |
+ create(Cfg *Func, |
+ typename InstX86Base<Machine>::Traits::X86OperandMem *DestSrc0, |
+ Operand *Src1) { |
+ return new (Func->allocate<InstX86BaseAddRMW>()) |
+ InstX86BaseAddRMW(Func, DestSrc0, Src1); |
+ } |
+ |
+private: |
+ InstX86BaseAddRMW( |
+ Cfg *Func, typename InstX86Base<Machine>::Traits::X86OperandMem *DestSrc0, |
+ Operand *Src1) |
+ : InstX86BaseBinopRMW<Machine, InstX86Base<Machine>::AddRMW>( |
+ Func, DestSrc0, Src1) {} |
+}; |
+ |
+template <class Machine> |
+class InstX86BaseAddps |
+ : public InstX86BaseBinopXmm<Machine, InstX86Base<Machine>::Addps, true> { |
+public: |
+ static InstX86BaseAddps *create(Cfg *Func, Variable *Dest, Operand *Source) { |
+ return new (Func->allocate<InstX86BaseAddps>()) |
+ InstX86BaseAddps(Func, Dest, Source); |
+ } |
+ |
+private: |
+ InstX86BaseAddps(Cfg *Func, Variable *Dest, Operand *Source) |
+ : InstX86BaseBinopXmm<Machine, InstX86Base<Machine>::Addps, true>( |
+ Func, Dest, Source) {} |
+}; |
+ |
+template <class Machine> |
+class InstX86BaseAdc |
+ : public InstX86BaseBinopGPR<Machine, InstX86Base<Machine>::Adc> { |
+public: |
+ static InstX86BaseAdc *create(Cfg *Func, Variable *Dest, Operand *Source) { |
+ return new (Func->allocate<InstX86BaseAdc>()) |
+ InstX86BaseAdc(Func, Dest, Source); |
+ } |
+ |
+private: |
+ InstX86BaseAdc(Cfg *Func, Variable *Dest, Operand *Source) |
+ : InstX86BaseBinopGPR<Machine, InstX86Base<Machine>::Adc>(Func, Dest, |
+ Source) {} |
+}; |
+ |
+template <class Machine> |
+class InstX86BaseAdcRMW |
+ : public InstX86BaseBinopRMW<Machine, InstX86Base<Machine>::AdcRMW> { |
+public: |
+ static InstX86BaseAdcRMW * |
+ create(Cfg *Func, |
+ typename InstX86Base<Machine>::Traits::X86OperandMem *DestSrc0, |
+ Operand *Src1) { |
+ return new (Func->allocate<InstX86BaseAdcRMW>()) |
+ InstX86BaseAdcRMW(Func, DestSrc0, Src1); |
+ } |
+ |
+private: |
+ InstX86BaseAdcRMW( |
+ Cfg *Func, typename InstX86Base<Machine>::Traits::X86OperandMem *DestSrc0, |
+ Operand *Src1) |
+ : InstX86BaseBinopRMW<Machine, InstX86Base<Machine>::AdcRMW>( |
+ Func, DestSrc0, Src1) {} |
+}; |
+ |
+template <class Machine> |
+class InstX86BaseAddss |
+ : public InstX86BaseBinopXmm<Machine, InstX86Base<Machine>::Addss, false> { |
+public: |
+ static InstX86BaseAddss *create(Cfg *Func, Variable *Dest, Operand *Source) { |
+ return new (Func->allocate<InstX86BaseAddss>()) |
+ InstX86BaseAddss(Func, Dest, Source); |
+ } |
+ |
+ void emit(const Cfg *Func) const override; |
+ |
+private: |
+ InstX86BaseAddss(Cfg *Func, Variable *Dest, Operand *Source) |
+ : InstX86BaseBinopXmm<Machine, InstX86Base<Machine>::Addss, false>( |
+ Func, Dest, Source) {} |
+}; |
+ |
+template <class Machine> |
+class InstX86BasePadd |
+ : public InstX86BaseBinopXmm<Machine, InstX86Base<Machine>::Padd, true> { |
+public: |
+ static InstX86BasePadd *create(Cfg *Func, Variable *Dest, Operand *Source) { |
+ return new (Func->allocate<InstX86BasePadd>()) |
+ InstX86BasePadd(Func, Dest, Source); |
+ } |
+ |
+ void emit(const Cfg *Func) const override; |
+ |
+private: |
+ InstX86BasePadd(Cfg *Func, Variable *Dest, Operand *Source) |
+ : InstX86BaseBinopXmm<Machine, InstX86Base<Machine>::Padd, true>( |
+ Func, Dest, Source) {} |
+}; |
+ |
+template <class Machine> |
+class InstX86BaseSub |
+ : public InstX86BaseBinopGPR<Machine, InstX86Base<Machine>::Sub> { |
+public: |
+ static InstX86BaseSub *create(Cfg *Func, Variable *Dest, Operand *Source) { |
+ return new (Func->allocate<InstX86BaseSub>()) |
+ InstX86BaseSub(Func, Dest, Source); |
+ } |
+ |
+private: |
+ InstX86BaseSub(Cfg *Func, Variable *Dest, Operand *Source) |
+ : InstX86BaseBinopGPR<Machine, InstX86Base<Machine>::Sub>(Func, Dest, |
+ Source) {} |
+}; |
+ |
+template <class Machine> |
+class InstX86BaseSubRMW |
+ : public InstX86BaseBinopRMW<Machine, InstX86Base<Machine>::SubRMW> { |
+public: |
+ static InstX86BaseSubRMW * |
+ create(Cfg *Func, |
+ typename InstX86Base<Machine>::Traits::X86OperandMem *DestSrc0, |
+ Operand *Src1) { |
+ return new (Func->allocate<InstX86BaseSubRMW>()) |
+ InstX86BaseSubRMW(Func, DestSrc0, Src1); |
+ } |
+ |
+private: |
+ InstX86BaseSubRMW( |
+ Cfg *Func, typename InstX86Base<Machine>::Traits::X86OperandMem *DestSrc0, |
+ Operand *Src1) |
+ : InstX86BaseBinopRMW<Machine, InstX86Base<Machine>::SubRMW>( |
+ Func, DestSrc0, Src1) {} |
+}; |
+ |
+template <class Machine> |
+class InstX86BaseSubps |
+ : public InstX86BaseBinopXmm<Machine, InstX86Base<Machine>::Subps, true> { |
+public: |
+ static InstX86BaseSubps *create(Cfg *Func, Variable *Dest, Operand *Source) { |
+ return new (Func->allocate<InstX86BaseSubps>()) |
+ InstX86BaseSubps(Func, Dest, Source); |
+ } |
+ |
+private: |
+ InstX86BaseSubps(Cfg *Func, Variable *Dest, Operand *Source) |
+ : InstX86BaseBinopXmm<Machine, InstX86Base<Machine>::Subps, true>( |
+ Func, Dest, Source) {} |
+}; |
+ |
+template <class Machine> |
+class InstX86BaseSubss |
+ : public InstX86BaseBinopXmm<Machine, InstX86Base<Machine>::Subss, false> { |
+public: |
+ static InstX86BaseSubss *create(Cfg *Func, Variable *Dest, Operand *Source) { |
+ return new (Func->allocate<InstX86BaseSubss>()) |
+ InstX86BaseSubss(Func, Dest, Source); |
+ } |
+ |
+ void emit(const Cfg *Func) const override; |
+ |
+private: |
+ InstX86BaseSubss(Cfg *Func, Variable *Dest, Operand *Source) |
+ : InstX86BaseBinopXmm<Machine, InstX86Base<Machine>::Subss, false>( |
+ Func, Dest, Source) {} |
+}; |
+ |
+template <class Machine> |
+class InstX86BaseSbb |
+ : public InstX86BaseBinopGPR<Machine, InstX86Base<Machine>::Sbb> { |
+public: |
+ static InstX86BaseSbb *create(Cfg *Func, Variable *Dest, Operand *Source) { |
+ return new (Func->allocate<InstX86BaseSbb>()) |
+ InstX86BaseSbb(Func, Dest, Source); |
+ } |
+ |
+private: |
+ InstX86BaseSbb(Cfg *Func, Variable *Dest, Operand *Source) |
+ : InstX86BaseBinopGPR<Machine, InstX86Base<Machine>::Sbb>(Func, Dest, |
+ Source) {} |
+}; |
+ |
+template <class Machine> |
+class InstX86BaseSbbRMW |
+ : public InstX86BaseBinopRMW<Machine, InstX86Base<Machine>::SbbRMW> { |
+public: |
+ static InstX86BaseSbbRMW * |
+ create(Cfg *Func, |
+ typename InstX86Base<Machine>::Traits::X86OperandMem *DestSrc0, |
+ Operand *Src1) { |
+ return new (Func->allocate<InstX86BaseSbbRMW>()) |
+ InstX86BaseSbbRMW(Func, DestSrc0, Src1); |
+ } |
+ |
+private: |
+ InstX86BaseSbbRMW( |
+ Cfg *Func, typename InstX86Base<Machine>::Traits::X86OperandMem *DestSrc0, |
+ Operand *Src1) |
+ : InstX86BaseBinopRMW<Machine, InstX86Base<Machine>::SbbRMW>( |
+ Func, DestSrc0, Src1) {} |
+}; |
+ |
+template <class Machine> |
+class InstX86BasePsub |
+ : public InstX86BaseBinopXmm<Machine, InstX86Base<Machine>::Psub, true> { |
+public: |
+ static InstX86BasePsub *create(Cfg *Func, Variable *Dest, Operand *Source) { |
+ return new (Func->allocate<InstX86BasePsub>()) |
+ InstX86BasePsub(Func, Dest, Source); |
+ } |
+ |
+ void emit(const Cfg *Func) const override; |
+ |
+private: |
+ InstX86BasePsub(Cfg *Func, Variable *Dest, Operand *Source) |
+ : InstX86BaseBinopXmm<Machine, InstX86Base<Machine>::Psub, true>( |
+ Func, Dest, Source) {} |
+}; |
+ |
+template <class Machine> |
+class InstX86BaseAnd |
+ : public InstX86BaseBinopGPR<Machine, InstX86Base<Machine>::And> { |
+public: |
+ static InstX86BaseAnd *create(Cfg *Func, Variable *Dest, Operand *Source) { |
+ return new (Func->allocate<InstX86BaseAnd>()) |
+ InstX86BaseAnd(Func, Dest, Source); |
+ } |
+ |
+private: |
+ InstX86BaseAnd(Cfg *Func, Variable *Dest, Operand *Source) |
+ : InstX86BaseBinopGPR<Machine, InstX86Base<Machine>::And>(Func, Dest, |
+ Source) {} |
+}; |
+ |
+template <class Machine> |
+class InstX86BaseAndRMW |
+ : public InstX86BaseBinopRMW<Machine, InstX86Base<Machine>::AndRMW> { |
+public: |
+ static InstX86BaseAndRMW * |
+ create(Cfg *Func, |
+ typename InstX86Base<Machine>::Traits::X86OperandMem *DestSrc0, |
+ Operand *Src1) { |
+ return new (Func->allocate<InstX86BaseAndRMW>()) |
+ InstX86BaseAndRMW(Func, DestSrc0, Src1); |
+ } |
+ |
+private: |
+ InstX86BaseAndRMW( |
+ Cfg *Func, typename InstX86Base<Machine>::Traits::X86OperandMem *DestSrc0, |
+ Operand *Src1) |
+ : InstX86BaseBinopRMW<Machine, InstX86Base<Machine>::AndRMW>( |
+ Func, DestSrc0, Src1) {} |
+}; |
+ |
+template <class Machine> |
+class InstX86BasePand |
+ : public InstX86BaseBinopXmm<Machine, InstX86Base<Machine>::Pand, false> { |
+public: |
+ static InstX86BasePand *create(Cfg *Func, Variable *Dest, Operand *Source) { |
+ return new (Func->allocate<InstX86BasePand>()) |
+ InstX86BasePand(Func, Dest, Source); |
+ } |
+ |
+private: |
+ InstX86BasePand(Cfg *Func, Variable *Dest, Operand *Source) |
+ : InstX86BaseBinopXmm<Machine, InstX86Base<Machine>::Pand, false>( |
+ Func, Dest, Source) {} |
+}; |
+ |
+template <class Machine> |
+class InstX86BasePandn |
+ : public InstX86BaseBinopXmm<Machine, InstX86Base<Machine>::Pandn, false> { |
+public: |
+ static InstX86BasePandn *create(Cfg *Func, Variable *Dest, Operand *Source) { |
+ return new (Func->allocate<InstX86BasePandn>()) |
+ InstX86BasePandn(Func, Dest, Source); |
+ } |
+ |
+private: |
+ InstX86BasePandn(Cfg *Func, Variable *Dest, Operand *Source) |
+ : InstX86BaseBinopXmm<Machine, InstX86Base<Machine>::Pandn, false>( |
+ Func, Dest, Source) {} |
+}; |
+ |
+template <class Machine> |
+class InstX86BaseOr |
+ : public InstX86BaseBinopGPR<Machine, InstX86Base<Machine>::Or> { |
+public: |
+ static InstX86BaseOr *create(Cfg *Func, Variable *Dest, Operand *Source) { |
+ return new (Func->allocate<InstX86BaseOr>()) |
+ InstX86BaseOr(Func, Dest, Source); |
+ } |
+ |
+private: |
+ InstX86BaseOr(Cfg *Func, Variable *Dest, Operand *Source) |
+ : InstX86BaseBinopGPR<Machine, InstX86Base<Machine>::Or>(Func, Dest, |
+ Source) {} |
+}; |
+ |
+template <class Machine> |
+class InstX86BaseOrRMW |
+ : public InstX86BaseBinopRMW<Machine, InstX86Base<Machine>::OrRMW> { |
+public: |
+ static InstX86BaseOrRMW * |
+ create(Cfg *Func, |
+ typename InstX86Base<Machine>::Traits::X86OperandMem *DestSrc0, |
+ Operand *Src1) { |
+ return new (Func->allocate<InstX86BaseOrRMW>()) |
+ InstX86BaseOrRMW(Func, DestSrc0, Src1); |
+ } |
+ |
+private: |
+ InstX86BaseOrRMW( |
+ Cfg *Func, typename InstX86Base<Machine>::Traits::X86OperandMem *DestSrc0, |
+ Operand *Src1) |
+ : InstX86BaseBinopRMW<Machine, InstX86Base<Machine>::OrRMW>( |
+ Func, DestSrc0, Src1) {} |
+}; |
+ |
+template <class Machine> |
+class InstX86BasePor |
+ : public InstX86BaseBinopXmm<Machine, InstX86Base<Machine>::Por, false> { |
+public: |
+ static InstX86BasePor *create(Cfg *Func, Variable *Dest, Operand *Source) { |
+ return new (Func->allocate<InstX86BasePor>()) |
+ InstX86BasePor(Func, Dest, Source); |
+ } |
+ |
+private: |
+ InstX86BasePor(Cfg *Func, Variable *Dest, Operand *Source) |
+ : InstX86BaseBinopXmm<Machine, InstX86Base<Machine>::Por, false>( |
+ Func, Dest, Source) {} |
+}; |
+ |
+template <class Machine> |
+class InstX86BaseXor |
+ : public InstX86BaseBinopGPR<Machine, InstX86Base<Machine>::Xor> { |
+public: |
+ static InstX86BaseXor *create(Cfg *Func, Variable *Dest, Operand *Source) { |
+ return new (Func->allocate<InstX86BaseXor>()) |
+ InstX86BaseXor(Func, Dest, Source); |
+ } |
+ |
+private: |
+ InstX86BaseXor(Cfg *Func, Variable *Dest, Operand *Source) |
+ : InstX86BaseBinopGPR<Machine, InstX86Base<Machine>::Xor>(Func, Dest, |
+ Source) {} |
+}; |
+ |
+template <class Machine> |
+class InstX86BaseXorRMW |
+ : public InstX86BaseBinopRMW<Machine, InstX86Base<Machine>::XorRMW> { |
+public: |
+ static InstX86BaseXorRMW * |
+ create(Cfg *Func, |
+ typename InstX86Base<Machine>::Traits::X86OperandMem *DestSrc0, |
+ Operand *Src1) { |
+ return new (Func->allocate<InstX86BaseXorRMW>()) |
+ InstX86BaseXorRMW(Func, DestSrc0, Src1); |
+ } |
+ |
+private: |
+ InstX86BaseXorRMW( |
+ Cfg *Func, typename InstX86Base<Machine>::Traits::X86OperandMem *DestSrc0, |
+ Operand *Src1) |
+ : InstX86BaseBinopRMW<Machine, InstX86Base<Machine>::XorRMW>( |
+ Func, DestSrc0, Src1) {} |
+}; |
+ |
+template <class Machine> |
+class InstX86BasePxor |
+ : public InstX86BaseBinopXmm<Machine, InstX86Base<Machine>::Pxor, false> { |
+public: |
+ static InstX86BasePxor *create(Cfg *Func, Variable *Dest, Operand *Source) { |
+ return new (Func->allocate<InstX86BasePxor>()) |
+ InstX86BasePxor(Func, Dest, Source); |
+ } |
+ |
+private: |
+ InstX86BasePxor(Cfg *Func, Variable *Dest, Operand *Source) |
+ : InstX86BaseBinopXmm<Machine, InstX86Base<Machine>::Pxor, false>( |
+ Func, Dest, Source) {} |
+}; |
+ |
+template <class Machine> |
+class InstX86BaseImul |
+ : public InstX86BaseBinopGPR<Machine, InstX86Base<Machine>::Imul> { |
+public: |
+ static InstX86BaseImul *create(Cfg *Func, Variable *Dest, Operand *Source) { |
+ return new (Func->allocate<InstX86BaseImul>()) |
+ InstX86BaseImul(Func, Dest, Source); |
+ } |
+ |
+ void emit(const Cfg *Func) const override; |
+ void emitIAS(const Cfg *Func) const override; |
+ |
+private: |
+ InstX86BaseImul(Cfg *Func, Variable *Dest, Operand *Source) |
+ : InstX86BaseBinopGPR<Machine, InstX86Base<Machine>::Imul>(Func, Dest, |
+ Source) {} |
+}; |
+ |
+template <class Machine> |
+class InstX86BaseMulps |
+ : public InstX86BaseBinopXmm<Machine, InstX86Base<Machine>::Mulps, true> { |
+public: |
+ static InstX86BaseMulps *create(Cfg *Func, Variable *Dest, Operand *Source) { |
+ return new (Func->allocate<InstX86BaseMulps>()) |
+ InstX86BaseMulps(Func, Dest, Source); |
+ } |
+ |
+private: |
+ InstX86BaseMulps(Cfg *Func, Variable *Dest, Operand *Source) |
+ : InstX86BaseBinopXmm<Machine, InstX86Base<Machine>::Mulps, true>( |
+ Func, Dest, Source) {} |
+}; |
+ |
+template <class Machine> |
+class InstX86BaseMulss |
+ : public InstX86BaseBinopXmm<Machine, InstX86Base<Machine>::Mulss, false> { |
+public: |
+ static InstX86BaseMulss *create(Cfg *Func, Variable *Dest, Operand *Source) { |
+ return new (Func->allocate<InstX86BaseMulss>()) |
+ InstX86BaseMulss(Func, Dest, Source); |
+ } |
+ |
+ void emit(const Cfg *Func) const override; |
+ |
+private: |
+ InstX86BaseMulss(Cfg *Func, Variable *Dest, Operand *Source) |
+ : InstX86BaseBinopXmm<Machine, InstX86Base<Machine>::Mulss, false>( |
+ Func, Dest, Source) {} |
+}; |
+ |
+template <class Machine> |
+class InstX86BasePmull |
+ : public InstX86BaseBinopXmm<Machine, InstX86Base<Machine>::Pmull, true> { |
+public: |
+ static InstX86BasePmull *create(Cfg *Func, Variable *Dest, Operand *Source) { |
+ return new (Func->allocate<InstX86BasePmull>()) |
+ InstX86BasePmull(Func, Dest, Source); |
+ } |
+ |
+ void emit(const Cfg *Func) const override; |
+ void emitIAS(const Cfg *Func) const override; |
+ |
+private: |
+ InstX86BasePmull(Cfg *Func, Variable *Dest, Operand *Source) |
+ : InstX86BaseBinopXmm<Machine, InstX86Base<Machine>::Pmull, true>( |
+ Func, Dest, Source) {} |
+}; |
+ |
+template <class Machine> |
+class InstX86BasePmuludq |
+ : public InstX86BaseBinopXmm<Machine, InstX86Base<Machine>::Pmuludq, |
+ false> { |
+public: |
+ static InstX86BasePmuludq *create(Cfg *Func, Variable *Dest, |
+ Operand *Source) { |
+ return new (Func->allocate<InstX86BasePmuludq>()) |
+ InstX86BasePmuludq(Func, Dest, Source); |
+ } |
+ |
+ void emit(const Cfg *Func) const override; |
+ |
+private: |
+ InstX86BasePmuludq(Cfg *Func, Variable *Dest, Operand *Source) |
+ : InstX86BaseBinopXmm<Machine, InstX86Base<Machine>::Pmuludq, false>( |
+ Func, Dest, Source) {} |
+}; |
+ |
+template <class Machine> |
+class InstX86BaseDivps |
+ : public InstX86BaseBinopXmm<Machine, InstX86Base<Machine>::Divps, true> { |
+public: |
+ static InstX86BaseDivps *create(Cfg *Func, Variable *Dest, Operand *Source) { |
+ return new (Func->allocate<InstX86BaseDivps>()) |
+ InstX86BaseDivps(Func, Dest, Source); |
+ } |
+ |
+private: |
+ InstX86BaseDivps(Cfg *Func, Variable *Dest, Operand *Source) |
+ : InstX86BaseBinopXmm<Machine, InstX86Base<Machine>::Divps, true>( |
+ Func, Dest, Source) {} |
+}; |
+ |
+template <class Machine> |
+class InstX86BaseDivss |
+ : public InstX86BaseBinopXmm<Machine, InstX86Base<Machine>::Divss, false> { |
+public: |
+ static InstX86BaseDivss *create(Cfg *Func, Variable *Dest, Operand *Source) { |
+ return new (Func->allocate<InstX86BaseDivss>()) |
+ InstX86BaseDivss(Func, Dest, Source); |
+ } |
+ |
+ void emit(const Cfg *Func) const override; |
+ |
+private: |
+ InstX86BaseDivss(Cfg *Func, Variable *Dest, Operand *Source) |
+ : InstX86BaseBinopXmm<Machine, InstX86Base<Machine>::Divss, false>( |
+ Func, Dest, Source) {} |
+}; |
+ |
+template <class Machine> |
+class InstX86BaseRol |
+ : public InstX86BaseBinopGPRShift<Machine, InstX86Base<Machine>::Rol> { |
+public: |
+ static InstX86BaseRol *create(Cfg *Func, Variable *Dest, Operand *Source) { |
+ return new (Func->allocate<InstX86BaseRol>()) |
+ InstX86BaseRol(Func, Dest, Source); |
+ } |
+ |
+private: |
+ InstX86BaseRol(Cfg *Func, Variable *Dest, Operand *Source) |
+ : InstX86BaseBinopGPRShift<Machine, InstX86Base<Machine>::Rol>(Func, Dest, |
+ Source) {} |
+}; |
+ |
+template <class Machine> |
+class InstX86BaseShl |
+ : public InstX86BaseBinopGPRShift<Machine, InstX86Base<Machine>::Shl> { |
+public: |
+ static InstX86BaseShl *create(Cfg *Func, Variable *Dest, Operand *Source) { |
+ return new (Func->allocate<InstX86BaseShl>()) |
+ InstX86BaseShl(Func, Dest, Source); |
+ } |
+ |
+private: |
+ InstX86BaseShl(Cfg *Func, Variable *Dest, Operand *Source) |
+ : InstX86BaseBinopGPRShift<Machine, InstX86Base<Machine>::Shl>(Func, Dest, |
+ Source) {} |
+}; |
+ |
+template <class Machine> |
+class InstX86BasePsll |
+ : public InstX86BaseBinopXmmShift<Machine, InstX86Base<Machine>::Psll> { |
+public: |
+ static InstX86BasePsll *create(Cfg *Func, Variable *Dest, Operand *Source) { |
+ return new (Func->allocate<InstX86BasePsll>()) |
+ InstX86BasePsll(Func, Dest, Source); |
+ } |
+ |
+ void emit(const Cfg *Func) const override; |
+ |
+private: |
+ InstX86BasePsll(Cfg *Func, Variable *Dest, Operand *Source) |
+ : InstX86BaseBinopXmmShift<Machine, InstX86Base<Machine>::Psll>( |
+ Func, Dest, Source) {} |
+}; |
+ |
+template <class Machine> |
+class InstX86BasePsrl |
+ : public InstX86BaseBinopXmmShift<Machine, InstX86Base<Machine>::Psrl, |
+ true> { |
+public: |
+ static InstX86BasePsrl *create(Cfg *Func, Variable *Dest, Operand *Source) { |
+ return new (Func->allocate<InstX86BasePsrl>()) |
+ InstX86BasePsrl(Func, Dest, Source); |
+ } |
+ |
+ void emit(const Cfg *Func) const override; |
+ |
+private: |
+ InstX86BasePsrl(Cfg *Func, Variable *Dest, Operand *Source) |
+ : InstX86BaseBinopXmmShift<Machine, InstX86Base<Machine>::Psrl, true>( |
+ Func, Dest, Source) {} |
+}; |
+ |
+template <class Machine> |
+class InstX86BaseShr |
+ : public InstX86BaseBinopGPRShift<Machine, InstX86Base<Machine>::Shr> { |
+public: |
+ static InstX86BaseShr *create(Cfg *Func, Variable *Dest, Operand *Source) { |
+ return new (Func->allocate<InstX86BaseShr>()) |
+ InstX86BaseShr(Func, Dest, Source); |
+ } |
+ |
+private: |
+ InstX86BaseShr(Cfg *Func, Variable *Dest, Operand *Source) |
+ : InstX86BaseBinopGPRShift<Machine, InstX86Base<Machine>::Shr>(Func, Dest, |
+ Source) {} |
+}; |
+ |
+template <class Machine> |
+class InstX86BaseSar |
+ : public InstX86BaseBinopGPRShift<Machine, InstX86Base<Machine>::Sar> { |
+public: |
+ static InstX86BaseSar *create(Cfg *Func, Variable *Dest, Operand *Source) { |
+ return new (Func->allocate<InstX86BaseSar>()) |
+ InstX86BaseSar(Func, Dest, Source); |
+ } |
+ |
+private: |
+ InstX86BaseSar(Cfg *Func, Variable *Dest, Operand *Source) |
+ : InstX86BaseBinopGPRShift<Machine, InstX86Base<Machine>::Sar>(Func, Dest, |
+ Source) {} |
+}; |
+ |
+template <class Machine> |
+class InstX86BasePsra |
+ : public InstX86BaseBinopXmmShift<Machine, InstX86Base<Machine>::Psra> { |
+public: |
+ static InstX86BasePsra *create(Cfg *Func, Variable *Dest, Operand *Source) { |
+ return new (Func->allocate<InstX86BasePsra>()) |
+ InstX86BasePsra(Func, Dest, Source); |
+ } |
+ |
+ void emit(const Cfg *Func) const override; |
+ |
+private: |
+ InstX86BasePsra(Cfg *Func, Variable *Dest, Operand *Source) |
+ : InstX86BaseBinopXmmShift<Machine, InstX86Base<Machine>::Psra>( |
+ Func, Dest, Source) {} |
+}; |
+ |
+template <class Machine> |
+class InstX86BasePcmpeq |
+ : public InstX86BaseBinopXmm<Machine, InstX86Base<Machine>::Pcmpeq, true> { |
+public: |
+ static InstX86BasePcmpeq *create(Cfg *Func, Variable *Dest, Operand *Source) { |
+ return new (Func->allocate<InstX86BasePcmpeq>()) |
+ InstX86BasePcmpeq(Func, Dest, Source); |
+ } |
+ |
+ void emit(const Cfg *Func) const override; |
+ |
+private: |
+ InstX86BasePcmpeq(Cfg *Func, Variable *Dest, Operand *Source) |
+ : InstX86BaseBinopXmm<Machine, InstX86Base<Machine>::Pcmpeq, true>( |
+ Func, Dest, Source) {} |
+}; |
+ |
+template <class Machine> |
+class InstX86BasePcmpgt |
+ : public InstX86BaseBinopXmm<Machine, InstX86Base<Machine>::Pcmpgt, true> { |
+public: |
+ static InstX86BasePcmpgt *create(Cfg *Func, Variable *Dest, Operand *Source) { |
+ return new (Func->allocate<InstX86BasePcmpgt>()) |
+ InstX86BasePcmpgt(Func, Dest, Source); |
+ } |
+ |
+ void emit(const Cfg *Func) const override; |
+ |
+private: |
+ InstX86BasePcmpgt(Cfg *Func, Variable *Dest, Operand *Source) |
+ : InstX86BaseBinopXmm<Machine, InstX86Base<Machine>::Pcmpgt, true>( |
+ 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). |
+// InstX86BaseMovss 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 InstX86BaseMovssRegs |
+ : public InstX86BaseBinopXmm<Machine, InstX86Base<Machine>::MovssRegs, |
+ false> { |
+public: |
+ static InstX86BaseMovssRegs *create(Cfg *Func, Variable *Dest, |
+ Operand *Source) { |
+ return new (Func->allocate<InstX86BaseMovssRegs>()) |
+ InstX86BaseMovssRegs(Func, Dest, Source); |
+ } |
+ |
+ void emitIAS(const Cfg *Func) const override; |
+ |
+private: |
+ InstX86BaseMovssRegs(Cfg *Func, Variable *Dest, Operand *Source) |
+ : InstX86BaseBinopXmm<Machine, InstX86Base<Machine>::MovssRegs, false>( |
+ Func, Dest, Source) {} |
+}; |
+ |
+template <class Machine> |
+class InstX86BaseIdiv |
+ : public InstX86BaseTernop<Machine, InstX86Base<Machine>::Idiv> { |
+public: |
+ static InstX86BaseIdiv *create(Cfg *Func, Variable *Dest, Operand *Source1, |
+ Operand *Source2) { |
+ return new (Func->allocate<InstX86BaseIdiv>()) |
+ InstX86BaseIdiv(Func, Dest, Source1, Source2); |
+ } |
+ |
+ void emit(const Cfg *Func) const override; |
+ void emitIAS(const Cfg *Func) const override; |
+ |
+private: |
+ InstX86BaseIdiv(Cfg *Func, Variable *Dest, Operand *Source1, Operand *Source2) |
+ : InstX86BaseTernop<Machine, InstX86Base<Machine>::Idiv>( |
+ Func, Dest, Source1, Source2) {} |
+}; |
+ |
+template <class Machine> |
+class InstX86BaseDiv |
+ : public InstX86BaseTernop<Machine, InstX86Base<Machine>::Div> { |
+public: |
+ static InstX86BaseDiv *create(Cfg *Func, Variable *Dest, Operand *Source1, |
+ Operand *Source2) { |
+ return new (Func->allocate<InstX86BaseDiv>()) |
+ InstX86BaseDiv(Func, Dest, Source1, Source2); |
+ } |
+ |
+ void emit(const Cfg *Func) const override; |
+ void emitIAS(const Cfg *Func) const override; |
+ |
+private: |
+ InstX86BaseDiv(Cfg *Func, Variable *Dest, Operand *Source1, Operand *Source2) |
+ : InstX86BaseTernop<Machine, InstX86Base<Machine>::Div>( |
+ Func, Dest, Source1, Source2) {} |
+}; |
+ |
+template <class Machine> |
+class InstX86BaseInsertps |
+ : public InstX86BaseTernop<Machine, InstX86Base<Machine>::Insertps> { |
+public: |
+ static InstX86BaseInsertps *create(Cfg *Func, Variable *Dest, |
+ Operand *Source1, Operand *Source2) { |
+ return new (Func->allocate<InstX86BaseInsertps>()) |
+ InstX86BaseInsertps(Func, Dest, Source1, Source2); |
+ } |
+ |
+ void emitIAS(const Cfg *Func) const override; |
+ |
+private: |
+ InstX86BaseInsertps(Cfg *Func, Variable *Dest, Operand *Source1, |
+ Operand *Source2) |
+ : InstX86BaseTernop<Machine, InstX86Base<Machine>::Insertps>( |
+ Func, Dest, Source1, Source2) {} |
+}; |
+ |
+template <class Machine> |
+class InstX86BasePinsr |
+ : public InstX86BaseTernop<Machine, InstX86Base<Machine>::Pinsr> { |
+public: |
+ static InstX86BasePinsr *create(Cfg *Func, Variable *Dest, Operand *Source1, |
+ Operand *Source2) { |
+ return new (Func->allocate<InstX86BasePinsr>()) |
+ InstX86BasePinsr(Func, Dest, Source1, Source2); |
+ } |
+ |
+ void emit(const Cfg *Func) const override; |
+ void emitIAS(const Cfg *Func) const override; |
+ |
+private: |
+ InstX86BasePinsr(Cfg *Func, Variable *Dest, Operand *Source1, |
+ Operand *Source2) |
+ : InstX86BaseTernop<Machine, InstX86Base<Machine>::Pinsr>( |
+ Func, Dest, Source1, Source2) {} |
+}; |
+ |
+template <class Machine> |
+class InstX86BaseShufps |
+ : public InstX86BaseTernop<Machine, InstX86Base<Machine>::Shufps> { |
+public: |
+ static InstX86BaseShufps *create(Cfg *Func, Variable *Dest, Operand *Source1, |
+ Operand *Source2) { |
+ return new (Func->allocate<InstX86BaseShufps>()) |
+ InstX86BaseShufps(Func, Dest, Source1, Source2); |
+ } |
+ |
+ void emitIAS(const Cfg *Func) const override; |
+ |
+private: |
+ InstX86BaseShufps(Cfg *Func, Variable *Dest, Operand *Source1, |
+ Operand *Source2) |
+ : InstX86BaseTernop<Machine, InstX86Base<Machine>::Shufps>( |
+ Func, Dest, Source1, Source2) {} |
+}; |
+ |
+template <class Machine> |
+class InstX86BaseBlendvps |
+ : public InstX86BaseTernop<Machine, InstX86Base<Machine>::Blendvps> { |
+public: |
+ static InstX86BaseBlendvps *create(Cfg *Func, Variable *Dest, |
+ Operand *Source1, Operand *Source2) { |
+ return new (Func->allocate<InstX86BaseBlendvps>()) |
+ InstX86BaseBlendvps(Func, Dest, Source1, Source2); |
+ } |
+ |
+ void emit(const Cfg *Func) const override; |
+ void emitIAS(const Cfg *Fund) const override; |
+ |
+private: |
+ InstX86BaseBlendvps(Cfg *Func, Variable *Dest, Operand *Source1, |
+ Operand *Source2) |
+ : InstX86BaseTernop<Machine, InstX86Base<Machine>::Blendvps>( |
+ Func, Dest, Source1, Source2) {} |
+}; |
+ |
+template <class Machine> |
+class InstX86BasePblendvb |
+ : public InstX86BaseTernop<Machine, InstX86Base<Machine>::Pblendvb> { |
+public: |
+ static InstX86BasePblendvb *create(Cfg *Func, Variable *Dest, |
+ Operand *Source1, Operand *Source2) { |
+ return new (Func->allocate<InstX86BasePblendvb>()) |
+ InstX86BasePblendvb(Func, Dest, Source1, Source2); |
+ } |
+ |
+ void emit(const Cfg *Func) const override; |
+ void emitIAS(const Cfg *Func) const override; |
+ |
+private: |
+ InstX86BasePblendvb(Cfg *Func, Variable *Dest, Operand *Source1, |
+ Operand *Source2) |
+ : InstX86BaseTernop<Machine, InstX86Base<Machine>::Pblendvb>( |
+ Func, Dest, Source1, Source2) {} |
+}; |
+ |
+template <class Machine> |
+class InstX86BasePextr |
+ : public InstX86BaseThreeAddressop<Machine, InstX86Base<Machine>::Pextr> { |
+public: |
+ static InstX86BasePextr *create(Cfg *Func, Variable *Dest, Operand *Source0, |
+ Operand *Source1) { |
+ return new (Func->allocate<InstX86BasePextr>()) |
+ InstX86BasePextr(Func, Dest, Source0, Source1); |
+ } |
+ |
+ void emit(const Cfg *Func) const override; |
+ void emitIAS(const Cfg *Func) const override; |
+ |
+private: |
+ InstX86BasePextr(Cfg *Func, Variable *Dest, Operand *Source0, |
+ Operand *Source1) |
+ : InstX86BaseThreeAddressop<Machine, InstX86Base<Machine>::Pextr>( |
+ Func, Dest, Source0, Source1) {} |
+}; |
+ |
+template <class Machine> |
+class InstX86BasePshufd |
+ : public InstX86BaseThreeAddressop<Machine, InstX86Base<Machine>::Pshufd> { |
+public: |
+ static InstX86BasePshufd *create(Cfg *Func, Variable *Dest, Operand *Source0, |
+ Operand *Source1) { |
+ return new (Func->allocate<InstX86BasePshufd>()) |
+ InstX86BasePshufd(Func, Dest, Source0, Source1); |
+ } |
+ |
+ void emitIAS(const Cfg *Func) const override; |
+ |
+private: |
+ InstX86BasePshufd(Cfg *Func, Variable *Dest, Operand *Source0, |
+ Operand *Source1) |
+ : InstX86BaseThreeAddressop<Machine, InstX86Base<Machine>::Pshufd>( |
+ Func, Dest, Source0, Source1) {} |
+}; |
+ |
+// 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; |
+ } |
+}; |
+ |
+// Mul instruction - unsigned multiply. |
+template <class Machine> class InstX86BaseMul : public InstX86Base<Machine> { |
+ InstX86BaseMul() = delete; |
+ InstX86BaseMul(const InstX86BaseMul &) = delete; |
+ InstX86BaseMul &operator=(const InstX86BaseMul &) = delete; |
+ |
+public: |
+ static InstX86BaseMul *create(Cfg *Func, Variable *Dest, Variable *Source1, |
+ Operand *Source2) { |
+ return new (Func->allocate<InstX86BaseMul>()) |
+ InstX86BaseMul(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); |
+ } |
+ |
+private: |
+ InstX86BaseMul(Cfg *Func, Variable *Dest, Variable *Source1, |
+ Operand *Source2); |
+}; |
+ |
+// Shld instruction - shift across a pair of operands. |
+template <class Machine> class InstX86BaseShld : public InstX86Base<Machine> { |
+ InstX86BaseShld() = delete; |
+ InstX86BaseShld(const InstX86BaseShld &) = delete; |
+ InstX86BaseShld &operator=(const InstX86BaseShld &) = delete; |
+ |
+public: |
+ static InstX86BaseShld *create(Cfg *Func, Variable *Dest, Variable *Source1, |
+ Variable *Source2) { |
+ return new (Func->allocate<InstX86BaseShld>()) |
+ InstX86BaseShld(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: |
+ InstX86BaseShld(Cfg *Func, Variable *Dest, Variable *Source1, |
+ Variable *Source2); |
+}; |
+ |
+// Shrd instruction - shift across a pair of operands. |
+template <class Machine> class InstX86BaseShrd : public InstX86Base<Machine> { |
+ InstX86BaseShrd() = delete; |
+ InstX86BaseShrd(const InstX86BaseShrd &) = delete; |
+ InstX86BaseShrd &operator=(const InstX86BaseShrd &) = delete; |
+ |
+public: |
+ static InstX86BaseShrd *create(Cfg *Func, Variable *Dest, Variable *Source1, |
+ Variable *Source2) { |
+ return new (Func->allocate<InstX86BaseShrd>()) |
+ InstX86BaseShrd(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); |
+ } |
+ |
+private: |
+ InstX86BaseShrd(Cfg *Func, Variable *Dest, Variable *Source1, |
+ Variable *Source2); |
+}; |
+ |
+// Conditional move instruction. |
+template <class Machine> class InstX86BaseCmov : public InstX86Base<Machine> { |
+ InstX86BaseCmov() = delete; |
+ InstX86BaseCmov(const InstX86BaseCmov &) = delete; |
+ InstX86BaseCmov &operator=(const InstX86BaseCmov &) = delete; |
+ |
+public: |
+ static InstX86BaseCmov * |
+ create(Cfg *Func, Variable *Dest, Operand *Source, |
+ typename InstX86Base<Machine>::Traits::Cond::BrCond Cond) { |
+ return new (Func->allocate<InstX86BaseCmov>()) |
+ InstX86BaseCmov(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); |
+ } |
+ |
+private: |
+ InstX86BaseCmov(Cfg *Func, Variable *Dest, Operand *Source, |
+ typename InstX86Base<Machine>::Traits::Cond::BrCond Cond); |
+ |
+ typename InstX86Base<Machine>::Traits::Cond::BrCond Condition; |
+}; |
+ |
+// Cmpps instruction - compare packed singled-precision floating point |
+// values |
+template <class Machine> class InstX86BaseCmpps : public InstX86Base<Machine> { |
+ InstX86BaseCmpps() = delete; |
+ InstX86BaseCmpps(const InstX86BaseCmpps &) = delete; |
+ InstX86BaseCmpps &operator=(const InstX86BaseCmpps &) = delete; |
+ |
+public: |
+ static InstX86BaseCmpps * |
+ create(Cfg *Func, Variable *Dest, Operand *Source, |
+ typename InstX86Base<Machine>::Traits::Cond::CmppsCond Condition) { |
+ return new (Func->allocate<InstX86BaseCmpps>()) |
+ InstX86BaseCmpps(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: |
+ InstX86BaseCmpps(Cfg *Func, Variable *Dest, Operand *Source, |
+ typename InstX86Base<Machine>::Traits::Cond::CmppsCond Cond); |
+ |
+ typename InstX86Base<Machine>::Traits::Cond::CmppsCond Condition; |
+}; |
+ |
+// 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 responsiblity to mark eax with a FakeDef. |
+template <class Machine> |
+class InstX86BaseCmpxchg : public InstX86BaseLockable<Machine> { |
+ InstX86BaseCmpxchg() = delete; |
+ InstX86BaseCmpxchg(const InstX86BaseCmpxchg &) = delete; |
+ InstX86BaseCmpxchg &operator=(const InstX86BaseCmpxchg &) = delete; |
+ |
+public: |
+ static InstX86BaseCmpxchg *create(Cfg *Func, Operand *DestOrAddr, |
+ Variable *Eax, Variable *Desired, |
+ bool Locked) { |
+ return new (Func->allocate<InstX86BaseCmpxchg>()) |
+ InstX86BaseCmpxchg(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: |
+ InstX86BaseCmpxchg(Cfg *Func, Operand *DestOrAddr, Variable *Eax, |
+ Variable *Desired, bool Locked); |
+}; |
+ |
+// 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 InstX86BaseCmpxchg8b : public InstX86BaseLockable<Machine> { |
+ InstX86BaseCmpxchg8b() = delete; |
+ InstX86BaseCmpxchg8b(const InstX86BaseCmpxchg8b &) = delete; |
+ InstX86BaseCmpxchg8b &operator=(const InstX86BaseCmpxchg8b &) = delete; |
+ |
+public: |
+ static InstX86BaseCmpxchg8b * |
+ create(Cfg *Func, typename InstX86Base<Machine>::Traits::X86OperandMem *Dest, |
+ Variable *Edx, Variable *Eax, Variable *Ecx, Variable *Ebx, |
+ bool Locked) { |
+ return new (Func->allocate<InstX86BaseCmpxchg8b>()) |
+ InstX86BaseCmpxchg8b(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); |
+ } |
+ |
+private: |
+ InstX86BaseCmpxchg8b( |
+ Cfg *Func, typename InstX86Base<Machine>::Traits::X86OperandMem *Dest, |
+ Variable *Edx, Variable *Eax, Variable *Ecx, Variable *Ebx, bool Locked); |
+}; |
+ |
+// 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 InstX86BaseCvt : public InstX86Base<Machine> { |
+ InstX86BaseCvt() = delete; |
+ InstX86BaseCvt(const InstX86BaseCvt &) = delete; |
+ InstX86BaseCvt &operator=(const InstX86BaseCvt &) = delete; |
+ |
+public: |
+ enum CvtVariant { Si2ss, Tss2si, Float2float, Dq2ps, Tps2dq }; |
+ static InstX86BaseCvt *create(Cfg *Func, Variable *Dest, Operand *Source, |
+ CvtVariant Variant) { |
+ return new (Func->allocate<InstX86BaseCvt>()) |
+ InstX86BaseCvt(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; } |
+ |
+private: |
+ CvtVariant Variant; |
+ InstX86BaseCvt(Cfg *Func, Variable *Dest, Operand *Source, |
+ CvtVariant Variant); |
+}; |
+ |
+// cmp - Integer compare instruction. |
+template <class Machine> class InstX86BaseIcmp : public InstX86Base<Machine> { |
+ InstX86BaseIcmp() = delete; |
+ InstX86BaseIcmp(const InstX86BaseIcmp &) = delete; |
+ InstX86BaseIcmp &operator=(const InstX86BaseIcmp &) = delete; |
+ |
+public: |
+ static InstX86BaseIcmp *create(Cfg *Func, Operand *Src1, Operand *Src2) { |
+ return new (Func->allocate<InstX86BaseIcmp>()) |
+ InstX86BaseIcmp(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); |
+ } |
+ |
+private: |
+ InstX86BaseIcmp(Cfg *Func, Operand *Src1, Operand *Src2); |
+}; |
+ |
+// ucomiss/ucomisd - floating-point compare instruction. |
+template <class Machine> |
+class InstX86BaseUcomiss : public InstX86Base<Machine> { |
+ InstX86BaseUcomiss() = delete; |
+ InstX86BaseUcomiss(const InstX86BaseUcomiss &) = delete; |
+ InstX86BaseUcomiss &operator=(const InstX86BaseUcomiss &) = delete; |
+ |
+public: |
+ static InstX86BaseUcomiss *create(Cfg *Func, Operand *Src1, Operand *Src2) { |
+ return new (Func->allocate<InstX86BaseUcomiss>()) |
+ InstX86BaseUcomiss(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); |
+ } |
+ |
+private: |
+ InstX86BaseUcomiss(Cfg *Func, Operand *Src1, Operand *Src2); |
+}; |
+ |
+// UD2 instruction. |
+template <class Machine> class InstX86BaseUD2 : public InstX86Base<Machine> { |
+ InstX86BaseUD2() = delete; |
+ InstX86BaseUD2(const InstX86BaseUD2 &) = delete; |
+ InstX86BaseUD2 &operator=(const InstX86BaseUD2 &) = delete; |
+ |
+public: |
+ static InstX86BaseUD2 *create(Cfg *Func) { |
+ return new (Func->allocate<InstX86BaseUD2>()) InstX86BaseUD2(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); |
+ } |
+ |
+private: |
+ explicit InstX86BaseUD2(Cfg *Func); |
+}; |
+ |
+// Test instruction. |
+template <class Machine> class InstX86BaseTest : public InstX86Base<Machine> { |
+ InstX86BaseTest() = delete; |
+ InstX86BaseTest(const InstX86BaseTest &) = delete; |
+ InstX86BaseTest &operator=(const InstX86BaseTest &) = delete; |
+ |
+public: |
+ static InstX86BaseTest *create(Cfg *Func, Operand *Source1, |
+ Operand *Source2) { |
+ return new (Func->allocate<InstX86BaseTest>()) |
+ InstX86BaseTest(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: |
+ InstX86BaseTest(Cfg *Func, Operand *Source1, Operand *Source2); |
+}; |
+ |
+// Mfence instruction. |
+template <class Machine> class InstX86BaseMfence : public InstX86Base<Machine> { |
+ InstX86BaseMfence() = delete; |
+ InstX86BaseMfence(const InstX86BaseMfence &) = delete; |
+ InstX86BaseMfence &operator=(const InstX86BaseMfence &) = delete; |
+ |
+public: |
+ static InstX86BaseMfence *create(Cfg *Func) { |
+ return new (Func->allocate<InstX86BaseMfence>()) InstX86BaseMfence(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: |
+ explicit InstX86BaseMfence(Cfg *Func); |
+}; |
+ |
+// This is essentially a "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. |
+template <class Machine> class InstX86BaseStore : public InstX86Base<Machine> { |
+ InstX86BaseStore() = delete; |
+ InstX86BaseStore(const InstX86BaseStore &) = delete; |
+ InstX86BaseStore &operator=(const InstX86BaseStore &) = delete; |
+ |
+public: |
+ static InstX86BaseStore * |
+ create(Cfg *Func, Operand *Value, |
+ typename InstX86Base<Machine>::Traits::X86Operand *Mem) { |
+ return new (Func->allocate<InstX86BaseStore>()) |
+ InstX86BaseStore(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); |
+ } |
+ |
+private: |
+ InstX86BaseStore(Cfg *Func, Operand *Value, |
+ typename InstX86Base<Machine>::Traits::X86Operand *Mem); |
+}; |
+ |
+// 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 InstX86BaseStoreP : public InstX86Base<Machine> { |
+ InstX86BaseStoreP() = delete; |
+ InstX86BaseStoreP(const InstX86BaseStoreP &) = delete; |
+ InstX86BaseStoreP &operator=(const InstX86BaseStoreP &) = delete; |
+ |
+public: |
+ static InstX86BaseStoreP * |
+ create(Cfg *Func, Variable *Value, |
+ typename InstX86Base<Machine>::Traits::X86OperandMem *Mem) { |
+ return new (Func->allocate<InstX86BaseStoreP>()) |
+ InstX86BaseStoreP(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); |
+ } |
+ |
+private: |
+ InstX86BaseStoreP(Cfg *Func, Variable *Value, |
+ typename InstX86Base<Machine>::Traits::X86OperandMem *Mem); |
+}; |
+ |
+template <class Machine> class InstX86BaseStoreQ : public InstX86Base<Machine> { |
+ InstX86BaseStoreQ() = delete; |
+ InstX86BaseStoreQ(const InstX86BaseStoreQ &) = delete; |
+ InstX86BaseStoreQ &operator=(const InstX86BaseStoreQ &) = delete; |
+ |
+public: |
+ static InstX86BaseStoreQ * |
+ create(Cfg *Func, Variable *Value, |
+ typename InstX86Base<Machine>::Traits::X86OperandMem *Mem) { |
+ return new (Func->allocate<InstX86BaseStoreQ>()) |
+ InstX86BaseStoreQ(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: |
+ InstX86BaseStoreQ(Cfg *Func, Variable *Value, |
+ typename InstX86Base<Machine>::Traits::X86OperandMem *Mem); |
+}; |
+ |
+// Nop instructions of varying length |
+template <class Machine> class InstX86BaseNop : public InstX86Base<Machine> { |
+ InstX86BaseNop() = delete; |
+ InstX86BaseNop(const InstX86BaseNop &) = delete; |
+ InstX86BaseNop &operator=(const InstX86BaseNop &) = delete; |
+ |
+public: |
+ // TODO: Replace with enum. |
+ typedef unsigned NopVariant; |
+ |
+ static InstX86BaseNop *create(Cfg *Func, NopVariant Variant) { |
+ return new (Func->allocate<InstX86BaseNop>()) InstX86BaseNop(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); |
+ } |
+ |
+private: |
+ InstX86BaseNop(Cfg *Func, SizeT Length); |
+ |
+ NopVariant Variant; |
+}; |
+ |
+// Fld - load a value onto the x87 FP stack. |
+template <class Machine> class InstX86BaseFld : public InstX86Base<Machine> { |
+ InstX86BaseFld() = delete; |
+ InstX86BaseFld(const InstX86BaseFld &) = delete; |
+ InstX86BaseFld &operator=(const InstX86BaseFld &) = delete; |
+ |
+public: |
+ static InstX86BaseFld *create(Cfg *Func, Operand *Src) { |
+ return new (Func->allocate<InstX86BaseFld>()) InstX86BaseFld(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: |
+ InstX86BaseFld(Cfg *Func, Operand *Src); |
+}; |
+ |
+// Fstp - store x87 st(0) into memory and pop st(0). |
+template <class Machine> class InstX86BaseFstp : public InstX86Base<Machine> { |
+ InstX86BaseFstp() = delete; |
+ InstX86BaseFstp(const InstX86BaseFstp &) = delete; |
+ InstX86BaseFstp &operator=(const InstX86BaseFstp &) = delete; |
+ |
+public: |
+ static InstX86BaseFstp *create(Cfg *Func, Variable *Dest) { |
+ return new (Func->allocate<InstX86BaseFstp>()) InstX86BaseFstp(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); |
+ } |
+ |
+private: |
+ InstX86BaseFstp(Cfg *Func, Variable *Dest); |
+}; |
+ |
+template <class Machine> class InstX86BasePop : public InstX86Base<Machine> { |
+ InstX86BasePop() = delete; |
+ InstX86BasePop(const InstX86BasePop &) = delete; |
+ InstX86BasePop &operator=(const InstX86BasePop &) = delete; |
+ |
+public: |
+ static InstX86BasePop *create(Cfg *Func, Variable *Dest) { |
+ return new (Func->allocate<InstX86BasePop>()) InstX86BasePop(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); |
+ } |
+ |
+private: |
+ InstX86BasePop(Cfg *Func, Variable *Dest); |
+}; |
+ |
+template <class Machine> class InstX86BasePush : public InstX86Base<Machine> { |
+ InstX86BasePush() = delete; |
+ InstX86BasePush(const InstX86BasePush &) = delete; |
+ InstX86BasePush &operator=(const InstX86BasePush &) = delete; |
+ |
+public: |
+ static InstX86BasePush *create(Cfg *Func, Variable *Source) { |
+ return new (Func->allocate<InstX86BasePush>()) |
+ InstX86BasePush(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: |
+ InstX86BasePush(Cfg *Func, Variable *Source); |
+}; |
+ |
+// 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 InstX86BaseRet : public InstX86Base<Machine> { |
+ InstX86BaseRet() = delete; |
+ InstX86BaseRet(const InstX86BaseRet &) = delete; |
+ InstX86BaseRet &operator=(const InstX86BaseRet &) = delete; |
+ |
+public: |
+ static InstX86BaseRet *create(Cfg *Func, Variable *Source = nullptr) { |
+ return new (Func->allocate<InstX86BaseRet>()) InstX86BaseRet(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); |
+ } |
+ |
+private: |
+ InstX86BaseRet(Cfg *Func, Variable *Source); |
+}; |
+ |
+// Conditional set-byte instruction. |
+template <class Machine> class InstX86BaseSetcc : public InstX86Base<Machine> { |
+ InstX86BaseSetcc() = delete; |
+ InstX86BaseSetcc(const InstX86BaseCmov<Machine> &) = delete; |
+ InstX86BaseSetcc &operator=(const InstX86BaseSetcc &) = delete; |
+ |
+public: |
+ static InstX86BaseSetcc * |
+ create(Cfg *Func, Variable *Dest, |
+ typename InstX86Base<Machine>::Traits::Cond::BrCond Cond) { |
+ return new (Func->allocate<InstX86BaseSetcc>()) |
+ InstX86BaseSetcc(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: |
+ InstX86BaseSetcc(Cfg *Func, Variable *Dest, |
+ typename InstX86Base<Machine>::Traits::Cond::BrCond Cond); |
+ |
+ const typename InstX86Base<Machine>::Traits::Cond::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. |
+template <class Machine> |
+class InstX86BaseXadd : public InstX86BaseLockable<Machine> { |
+ InstX86BaseXadd() = delete; |
+ InstX86BaseXadd(const InstX86BaseXadd &) = delete; |
+ InstX86BaseXadd &operator=(const InstX86BaseXadd &) = delete; |
+ |
+public: |
+ static InstX86BaseXadd *create(Cfg *Func, Operand *Dest, Variable *Source, |
+ bool Locked) { |
+ return new (Func->allocate<InstX86BaseXadd>()) |
+ InstX86BaseXadd(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: |
+ InstX86BaseXadd(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. |
+template <class Machine> class InstX86BaseXchg : public InstX86Base<Machine> { |
+ InstX86BaseXchg() = delete; |
+ InstX86BaseXchg(const InstX86BaseXchg &) = delete; |
+ InstX86BaseXchg &operator=(const InstX86BaseXchg &) = delete; |
+ |
+public: |
+ static InstX86BaseXchg *create(Cfg *Func, Operand *Dest, Variable *Source) { |
+ return new (Func->allocate<InstX86BaseXchg>()) |
+ InstX86BaseXchg(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); |
+ } |
+ |
+private: |
+ InstX86BaseXchg(Cfg *Func, Operand *Dest, Variable *Source); |
+}; |
+ |
+template <class Machine> struct Insts { |
+ using FakeRMW = InstX86BaseFakeRMW<Machine>; |
+ using Label = InstX86BaseLabel<Machine>; |
+ |
+ using AdjustStack = InstX86BaseAdjustStack<Machine>; |
+ using Call = InstX86BaseCall<Machine>; |
+ |
+ using Br = InstX86BaseBr<Machine>; |
+ using Jmp = InstX86BaseJmp<Machine>; |
+ using Bswap = InstX86BaseBswap<Machine>; |
+ using Neg = InstX86BaseNeg<Machine>; |
+ using Bsf = InstX86BaseBsf<Machine>; |
+ using Bsr = InstX86BaseBsr<Machine>; |
+ using Lea = InstX86BaseLea<Machine>; |
+ using Cbwdq = InstX86BaseCbwdq<Machine>; |
+ using Movsx = InstX86BaseMovsx<Machine>; |
+ using Movzx = InstX86BaseMovzx<Machine>; |
+ using Movd = InstX86BaseMovd<Machine>; |
+ using Sqrtss = InstX86BaseSqrtss<Machine>; |
+ using Mov = InstX86BaseMov<Machine>; |
+ using Movp = InstX86BaseMovp<Machine>; |
+ using Movq = InstX86BaseMovq<Machine>; |
+ using Add = InstX86BaseAdd<Machine>; |
+ using AddRMW = InstX86BaseAddRMW<Machine>; |
+ using Addps = InstX86BaseAddps<Machine>; |
+ using Adc = InstX86BaseAdc<Machine>; |
+ using AdcRMW = InstX86BaseAdcRMW<Machine>; |
+ using Addss = InstX86BaseAddss<Machine>; |
+ using Padd = InstX86BasePadd<Machine>; |
+ using Sub = InstX86BaseSub<Machine>; |
+ using SubRMW = InstX86BaseSubRMW<Machine>; |
+ using Subps = InstX86BaseSubps<Machine>; |
+ using Subss = InstX86BaseSubss<Machine>; |
+ using Sbb = InstX86BaseSbb<Machine>; |
+ using SbbRMW = InstX86BaseSbbRMW<Machine>; |
+ using Psub = InstX86BasePsub<Machine>; |
+ using And = InstX86BaseAnd<Machine>; |
+ using AndRMW = InstX86BaseAndRMW<Machine>; |
+ using Pand = InstX86BasePand<Machine>; |
+ using Pandn = InstX86BasePandn<Machine>; |
+ using Or = InstX86BaseOr<Machine>; |
+ using OrRMW = InstX86BaseOrRMW<Machine>; |
+ using Por = InstX86BasePor<Machine>; |
+ using Xor = InstX86BaseXor<Machine>; |
+ using XorRMW = InstX86BaseXorRMW<Machine>; |
+ using Pxor = InstX86BasePxor<Machine>; |
+ using Imul = InstX86BaseImul<Machine>; |
+ using Mulps = InstX86BaseMulps<Machine>; |
+ using Mulss = InstX86BaseMulss<Machine>; |
+ using Pmull = InstX86BasePmull<Machine>; |
+ using Pmuludq = InstX86BasePmuludq<Machine>; |
+ using Divps = InstX86BaseDivps<Machine>; |
+ using Divss = InstX86BaseDivss<Machine>; |
+ using Rol = InstX86BaseRol<Machine>; |
+ using Shl = InstX86BaseShl<Machine>; |
+ using Psll = InstX86BasePsll<Machine>; |
+ using Psrl = InstX86BasePsrl<Machine>; |
+ using Shr = InstX86BaseShr<Machine>; |
+ using Sar = InstX86BaseSar<Machine>; |
+ using Psra = InstX86BasePsra<Machine>; |
+ using Pcmpeq = InstX86BasePcmpeq<Machine>; |
+ using Pcmpgt = InstX86BasePcmpgt<Machine>; |
+ using MovssRegs = InstX86BaseMovssRegs<Machine>; |
+ using Idiv = InstX86BaseIdiv<Machine>; |
+ using Div = InstX86BaseDiv<Machine>; |
+ using Insertps = InstX86BaseInsertps<Machine>; |
+ using Pinsr = InstX86BasePinsr<Machine>; |
+ using Shufps = InstX86BaseShufps<Machine>; |
+ using Blendvps = InstX86BaseBlendvps<Machine>; |
+ using Pblendvb = InstX86BasePblendvb<Machine>; |
+ using Pextr = InstX86BasePextr<Machine>; |
+ using Pshufd = InstX86BasePshufd<Machine>; |
+ using Lockable = InstX86BaseLockable<Machine>; |
+ using Mul = InstX86BaseMul<Machine>; |
+ using Shld = InstX86BaseShld<Machine>; |
+ using Shrd = InstX86BaseShrd<Machine>; |
+ using Cmov = InstX86BaseCmov<Machine>; |
+ using Cmpps = InstX86BaseCmpps<Machine>; |
+ using Cmpxchg = InstX86BaseCmpxchg<Machine>; |
+ using Cmpxchg8b = InstX86BaseCmpxchg8b<Machine>; |
+ using Cvt = InstX86BaseCvt<Machine>; |
+ using Icmp = InstX86BaseIcmp<Machine>; |
+ using Ucomiss = InstX86BaseUcomiss<Machine>; |
+ using UD2 = InstX86BaseUD2<Machine>; |
+ using Test = InstX86BaseTest<Machine>; |
+ using Mfence = InstX86BaseMfence<Machine>; |
+ using Store = InstX86BaseStore<Machine>; |
+ using StoreP = InstX86BaseStoreP<Machine>; |
+ using StoreQ = InstX86BaseStoreQ<Machine>; |
+ using Nop = InstX86BaseNop<Machine>; |
+ using Fld = InstX86BaseFld<Machine>; |
+ using Fstp = InstX86BaseFstp<Machine>; |
+ using Pop = InstX86BasePop<Machine>; |
+ using Push = InstX86BasePush<Machine>; |
+ using Ret = InstX86BaseRet<Machine>; |
+ using Setcc = InstX86BaseSetcc<Machine>; |
+ using Xadd = InstX86BaseXadd<Machine>; |
+ using Xchg = InstX86BaseXchg<Machine>; |
+}; |
+ |
+#define X86INSTS_DEFINE_STATIC_DATA(Machine) \ |
+ namespace Ice { \ |
+ namespace X86Internal { \ |
+ /* In-place ops */ \ |
+ template <> const char *InstX86BaseBswap<Machine>::Base::Opcode = "bswap"; \ |
+ template <> const char *InstX86BaseNeg<Machine>::Base::Opcode = "neg"; \ |
+ /* Unary ops */ \ |
+ template <> const char *InstX86BaseBsf<Machine>::Base::Opcode = "bsf"; \ |
+ template <> const char *InstX86BaseBsr<Machine>::Base::Opcode = "bsr"; \ |
+ template <> const char *InstX86BaseLea<Machine>::Base::Opcode = "lea"; \ |
+ template <> const char *InstX86BaseMovd<Machine>::Base::Opcode = "movd"; \ |
+ template <> const char *InstX86BaseMovsx<Machine>::Base::Opcode = "movs"; \ |
+ template <> const char *InstX86BaseMovzx<Machine>::Base::Opcode = "movz"; \ |
+ template <> const char *InstX86BaseSqrtss<Machine>::Base::Opcode = "sqrtss"; \ |
+ template <> \ |
+ const char *InstX86BaseCbwdq<Machine>::Base::Opcode = "cbw/cwd/cdq"; \ |
+ /* Mov-like ops */ \ |
+ template <> const char *InstX86BaseMov<Machine>::Base::Opcode = "mov"; \ |
+ template <> const char *InstX86BaseMovp<Machine>::Base::Opcode = "movups"; \ |
+ template <> const char *InstX86BaseMovq<Machine>::Base::Opcode = "movq"; \ |
+ /* Binary ops */ \ |
+ template <> const char *InstX86BaseAdd<Machine>::Base::Opcode = "add"; \ |
+ template <> const char *InstX86BaseAddRMW<Machine>::Base::Opcode = "add"; \ |
+ template <> const char *InstX86BaseAddps<Machine>::Base::Opcode = "addps"; \ |
+ template <> const char *InstX86BaseAdc<Machine>::Base::Opcode = "adc"; \ |
+ template <> const char *InstX86BaseAdcRMW<Machine>::Base::Opcode = "adc"; \ |
+ template <> const char *InstX86BaseAddss<Machine>::Base::Opcode = "addss"; \ |
+ template <> const char *InstX86BasePadd<Machine>::Base::Opcode = "padd"; \ |
+ template <> const char *InstX86BaseSub<Machine>::Base::Opcode = "sub"; \ |
+ template <> const char *InstX86BaseSubRMW<Machine>::Base::Opcode = "sub"; \ |
+ template <> const char *InstX86BaseSubps<Machine>::Base::Opcode = "subps"; \ |
+ template <> const char *InstX86BaseSubss<Machine>::Base::Opcode = "subss"; \ |
+ template <> const char *InstX86BaseSbb<Machine>::Base::Opcode = "sbb"; \ |
+ template <> const char *InstX86BaseSbbRMW<Machine>::Base::Opcode = "sbb"; \ |
+ template <> const char *InstX86BasePsub<Machine>::Base::Opcode = "psub"; \ |
+ template <> const char *InstX86BaseAnd<Machine>::Base::Opcode = "and"; \ |
+ template <> const char *InstX86BaseAndRMW<Machine>::Base::Opcode = "and"; \ |
+ template <> const char *InstX86BasePand<Machine>::Base::Opcode = "pand"; \ |
+ template <> const char *InstX86BasePandn<Machine>::Base::Opcode = "pandn"; \ |
+ template <> const char *InstX86BaseOr<Machine>::Base::Opcode = "or"; \ |
+ template <> const char *InstX86BaseOrRMW<Machine>::Base::Opcode = "or"; \ |
+ template <> const char *InstX86BasePor<Machine>::Base::Opcode = "por"; \ |
+ template <> const char *InstX86BaseXor<Machine>::Base::Opcode = "xor"; \ |
+ template <> const char *InstX86BaseXorRMW<Machine>::Base::Opcode = "xor"; \ |
+ template <> const char *InstX86BasePxor<Machine>::Base::Opcode = "pxor"; \ |
+ template <> const char *InstX86BaseImul<Machine>::Base::Opcode = "imul"; \ |
+ template <> const char *InstX86BaseMulps<Machine>::Base::Opcode = "mulps"; \ |
+ template <> const char *InstX86BaseMulss<Machine>::Base::Opcode = "mulss"; \ |
+ template <> const char *InstX86BasePmull<Machine>::Base::Opcode = "pmull"; \ |
+ template <> \ |
+ const char *InstX86BasePmuludq<Machine>::Base::Opcode = "pmuludq"; \ |
+ template <> const char *InstX86BaseDiv<Machine>::Base::Opcode = "div"; \ |
+ template <> const char *InstX86BaseDivps<Machine>::Base::Opcode = "divps"; \ |
+ template <> const char *InstX86BaseIdiv<Machine>::Base::Opcode = "idiv"; \ |
+ template <> const char *InstX86BaseDivss<Machine>::Base::Opcode = "divss"; \ |
+ template <> const char *InstX86BaseRol<Machine>::Base::Opcode = "rol"; \ |
+ template <> const char *InstX86BaseShl<Machine>::Base::Opcode = "shl"; \ |
+ template <> const char *InstX86BasePsll<Machine>::Base::Opcode = "psll"; \ |
+ template <> const char *InstX86BaseShr<Machine>::Base::Opcode = "shr"; \ |
+ template <> const char *InstX86BaseSar<Machine>::Base::Opcode = "sar"; \ |
+ template <> const char *InstX86BasePsra<Machine>::Base::Opcode = "psra"; \ |
+ template <> const char *InstX86BasePsrl<Machine>::Base::Opcode = "psrl"; \ |
+ template <> const char *InstX86BasePcmpeq<Machine>::Base::Opcode = "pcmpeq"; \ |
+ template <> const char *InstX86BasePcmpgt<Machine>::Base::Opcode = "pcmpgt"; \ |
+ template <> \ |
+ const char *InstX86BaseMovssRegs<Machine>::Base::Opcode = "movss"; \ |
+ /* Ternary ops */ \ |
+ template <> \ |
+ const char *InstX86BaseInsertps<Machine>::Base::Opcode = "insertps"; \ |
+ template <> const char *InstX86BaseShufps<Machine>::Base::Opcode = "shufps"; \ |
+ template <> const char *InstX86BasePinsr<Machine>::Base::Opcode = "pinsr"; \ |
+ template <> \ |
+ const char *InstX86BaseBlendvps<Machine>::Base::Opcode = "blendvps"; \ |
+ template <> \ |
+ const char *InstX86BasePblendvb<Machine>::Base::Opcode = "pblendvb"; \ |
+ /* Three address ops */ \ |
+ template <> const char *InstX86BasePextr<Machine>::Base::Opcode = "pextr"; \ |
+ template <> const char *InstX86BasePshufd<Machine>::Base::Opcode = "pshufd"; \ |
+ /* Inplace GPR ops */ \ |
+ template <> \ |
+ const InstX86Base<Machine>::Traits::Assembler::GPREmitterOneOp \ |
+ InstX86BaseBswap<Machine>::Base::Emitter = { \ |
+ &InstX86Base<Machine>::Traits::Assembler::bswap, \ |
+ nullptr /* only a reg form exists */ \ |
+ }; \ |
+ template <> \ |
+ const InstX86Base<Machine>::Traits::Assembler::GPREmitterOneOp \ |
+ InstX86BaseNeg<Machine>::Base::Emitter = { \ |
+ &InstX86Base<Machine>::Traits::Assembler::neg, \ |
+ &InstX86Base<Machine>::Traits::Assembler::neg}; \ |
+ \ |
+ /* Unary GPR ops */ \ |
+ template <> /* uses specialized emitter. */ \ |
+ const InstX86Base<Machine>::Traits::Assembler::GPREmitterRegOp \ |
+ InstX86BaseCbwdq<Machine>::Base::Emitter = {nullptr, nullptr, nullptr}; \ |
+ template <> \ |
+ const InstX86Base<Machine>::Traits::Assembler::GPREmitterRegOp \ |
+ InstX86BaseBsf<Machine>::Base::Emitter = { \ |
+ &InstX86Base<Machine>::Traits::Assembler::bsf, \ |
+ &InstX86Base<Machine>::Traits::Assembler::bsf, nullptr}; \ |
+ template <> \ |
+ const InstX86Base<Machine>::Traits::Assembler::GPREmitterRegOp \ |
+ InstX86BaseBsr<Machine>::Base::Emitter = { \ |
+ &InstX86Base<Machine>::Traits::Assembler::bsr, \ |
+ &InstX86Base<Machine>::Traits::Assembler::bsr, nullptr}; \ |
+ template <> \ |
+ const InstX86Base<Machine>::Traits::Assembler::GPREmitterRegOp \ |
+ InstX86BaseLea<Machine>::Base::Emitter = { \ |
+ /* reg/reg and reg/imm are illegal */ nullptr, \ |
+ &InstX86Base<Machine>::Traits::Assembler::lea, nullptr}; \ |
+ template <> \ |
+ const InstX86Base<Machine>::Traits::Assembler::GPREmitterRegOp \ |
+ InstX86BaseMovsx<Machine>::Base::Emitter = { \ |
+ &InstX86Base<Machine>::Traits::Assembler::movsx, \ |
+ &InstX86Base<Machine>::Traits::Assembler::movsx, nullptr}; \ |
+ template <> \ |
+ const InstX86Base<Machine>::Traits::Assembler::GPREmitterRegOp \ |
+ InstX86BaseMovzx<Machine>::Base::Emitter = { \ |
+ &InstX86Base<Machine>::Traits::Assembler::movzx, \ |
+ &InstX86Base<Machine>::Traits::Assembler::movzx, nullptr}; \ |
+ \ |
+ /* Unary XMM ops */ \ |
+ template <> /* uses specialized emitter. */ \ |
+ const InstX86Base<Machine>::Traits::Assembler::XmmEmitterRegOp \ |
+ InstX86BaseMovd<Machine>::Base::Emitter = {nullptr, nullptr}; \ |
+ template <> \ |
+ const InstX86Base<Machine>::Traits::Assembler::XmmEmitterRegOp \ |
+ InstX86BaseSqrtss<Machine>::Base::Emitter = { \ |
+ &InstX86Base<Machine>::Traits::Assembler::sqrtss, \ |
+ &InstX86Base<Machine>::Traits::Assembler::sqrtss}; \ |
+ \ |
+ /* Binary GPR ops */ \ |
+ template <> /* uses specialized emitter. */ \ |
+ const InstX86Base<Machine>::Traits::Assembler::GPREmitterRegOp \ |
+ InstX86BaseImul<Machine>::Base::Emitter = {nullptr, nullptr, nullptr}; \ |
+ template <> \ |
+ const InstX86Base<Machine>::Traits::Assembler::GPREmitterRegOp \ |
+ InstX86BaseAdd<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 \ |
+ InstX86BaseAddRMW<Machine>::Base::Emitter = { \ |
+ &InstX86Base<Machine>::Traits::Assembler::add, \ |
+ &InstX86Base<Machine>::Traits::Assembler::add}; \ |
+ template <> \ |
+ const InstX86Base<Machine>::Traits::Assembler::GPREmitterRegOp \ |
+ InstX86BaseAdc<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 \ |
+ InstX86BaseAdcRMW<Machine>::Base::Emitter = { \ |
+ &InstX86Base<Machine>::Traits::Assembler::adc, \ |
+ &InstX86Base<Machine>::Traits::Assembler::adc}; \ |
+ template <> \ |
+ const InstX86Base<Machine>::Traits::Assembler::GPREmitterRegOp \ |
+ InstX86BaseAnd<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 \ |
+ InstX86BaseAndRMW<Machine>::Base::Emitter = { \ |
+ &InstX86Base<Machine>::Traits::Assembler::And, \ |
+ &InstX86Base<Machine>::Traits::Assembler::And}; \ |
+ template <> \ |
+ const InstX86Base<Machine>::Traits::Assembler::GPREmitterRegOp \ |
+ InstX86BaseOr<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 \ |
+ InstX86BaseOrRMW<Machine>::Base::Emitter = { \ |
+ &InstX86Base<Machine>::Traits::Assembler::Or, \ |
+ &InstX86Base<Machine>::Traits::Assembler::Or}; \ |
+ template <> \ |
+ const InstX86Base<Machine>::Traits::Assembler::GPREmitterRegOp \ |
+ InstX86BaseSbb<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 \ |
+ InstX86BaseSbbRMW<Machine>::Base::Emitter = { \ |
+ &InstX86Base<Machine>::Traits::Assembler::sbb, \ |
+ &InstX86Base<Machine>::Traits::Assembler::sbb}; \ |
+ template <> \ |
+ const InstX86Base<Machine>::Traits::Assembler::GPREmitterRegOp \ |
+ InstX86BaseSub<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 \ |
+ InstX86BaseSubRMW<Machine>::Base::Emitter = { \ |
+ &InstX86Base<Machine>::Traits::Assembler::sub, \ |
+ &InstX86Base<Machine>::Traits::Assembler::sub}; \ |
+ template <> \ |
+ const InstX86Base<Machine>::Traits::Assembler::GPREmitterRegOp \ |
+ InstX86BaseXor<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 \ |
+ InstX86BaseXorRMW<Machine>::Base::Emitter = { \ |
+ &InstX86Base<Machine>::Traits::Assembler::Xor, \ |
+ &InstX86Base<Machine>::Traits::Assembler::Xor}; \ |
+ \ |
+ /* Binary Shift GPR ops */ \ |
+ template <> \ |
+ const InstX86Base<Machine>::Traits::Assembler::GPREmitterShiftOp \ |
+ InstX86BaseRol<Machine>::Base::Emitter = { \ |
+ &InstX86Base<Machine>::Traits::Assembler::rol, \ |
+ &InstX86Base<Machine>::Traits::Assembler::rol}; \ |
+ template <> \ |
+ const InstX86Base<Machine>::Traits::Assembler::GPREmitterShiftOp \ |
+ InstX86BaseSar<Machine>::Base::Emitter = { \ |
+ &InstX86Base<Machine>::Traits::Assembler::sar, \ |
+ &InstX86Base<Machine>::Traits::Assembler::sar}; \ |
+ template <> \ |
+ const InstX86Base<Machine>::Traits::Assembler::GPREmitterShiftOp \ |
+ InstX86BaseShl<Machine>::Base::Emitter = { \ |
+ &InstX86Base<Machine>::Traits::Assembler::shl, \ |
+ &InstX86Base<Machine>::Traits::Assembler::shl}; \ |
+ template <> \ |
+ const InstX86Base<Machine>::Traits::Assembler::GPREmitterShiftOp \ |
+ InstX86BaseShr<Machine>::Base::Emitter = { \ |
+ &InstX86Base<Machine>::Traits::Assembler::shr, \ |
+ &InstX86Base<Machine>::Traits::Assembler::shr}; \ |
+ \ |
+ /* Binary XMM ops */ \ |
+ template <> /* uses specialized emitter. */ \ |
+ const InstX86Base<Machine>::Traits::Assembler::XmmEmitterRegOp \ |
+ InstX86BaseMovssRegs<Machine>::Base::Emitter = {nullptr, nullptr}; \ |
+ template <> \ |
+ const InstX86Base<Machine>::Traits::Assembler::XmmEmitterRegOp \ |
+ InstX86BaseAddss<Machine>::Base::Emitter = { \ |
+ &InstX86Base<Machine>::Traits::Assembler::addss, \ |
+ &InstX86Base<Machine>::Traits::Assembler::addss}; \ |
+ template <> \ |
+ const InstX86Base<Machine>::Traits::Assembler::XmmEmitterRegOp \ |
+ InstX86BaseAddps<Machine>::Base::Emitter = { \ |
+ &InstX86Base<Machine>::Traits::Assembler::addps, \ |
+ &InstX86Base<Machine>::Traits::Assembler::addps}; \ |
+ template <> \ |
+ const InstX86Base<Machine>::Traits::Assembler::XmmEmitterRegOp \ |
+ InstX86BaseDivss<Machine>::Base::Emitter = { \ |
+ &InstX86Base<Machine>::Traits::Assembler::divss, \ |
+ &InstX86Base<Machine>::Traits::Assembler::divss}; \ |
+ template <> \ |
+ const InstX86Base<Machine>::Traits::Assembler::XmmEmitterRegOp \ |
+ InstX86BaseDivps<Machine>::Base::Emitter = { \ |
+ &InstX86Base<Machine>::Traits::Assembler::divps, \ |
+ &InstX86Base<Machine>::Traits::Assembler::divps}; \ |
+ template <> \ |
+ const InstX86Base<Machine>::Traits::Assembler::XmmEmitterRegOp \ |
+ InstX86BaseMulss<Machine>::Base::Emitter = { \ |
+ &InstX86Base<Machine>::Traits::Assembler::mulss, \ |
+ &InstX86Base<Machine>::Traits::Assembler::mulss}; \ |
+ template <> \ |
+ const InstX86Base<Machine>::Traits::Assembler::XmmEmitterRegOp \ |
+ InstX86BaseMulps<Machine>::Base::Emitter = { \ |
+ &InstX86Base<Machine>::Traits::Assembler::mulps, \ |
+ &InstX86Base<Machine>::Traits::Assembler::mulps}; \ |
+ template <> \ |
+ const InstX86Base<Machine>::Traits::Assembler::XmmEmitterRegOp \ |
+ InstX86BasePadd<Machine>::Base::Emitter = { \ |
+ &InstX86Base<Machine>::Traits::Assembler::padd, \ |
+ &InstX86Base<Machine>::Traits::Assembler::padd}; \ |
+ template <> \ |
+ const InstX86Base<Machine>::Traits::Assembler::XmmEmitterRegOp \ |
+ InstX86BasePand<Machine>::Base::Emitter = { \ |
+ &InstX86Base<Machine>::Traits::Assembler::pand, \ |
+ &InstX86Base<Machine>::Traits::Assembler::pand}; \ |
+ template <> \ |
+ const InstX86Base<Machine>::Traits::Assembler::XmmEmitterRegOp \ |
+ InstX86BasePandn<Machine>::Base::Emitter = { \ |
+ &InstX86Base<Machine>::Traits::Assembler::pandn, \ |
+ &InstX86Base<Machine>::Traits::Assembler::pandn}; \ |
+ template <> \ |
+ const InstX86Base<Machine>::Traits::Assembler::XmmEmitterRegOp \ |
+ InstX86BasePcmpeq<Machine>::Base::Emitter = { \ |
+ &InstX86Base<Machine>::Traits::Assembler::pcmpeq, \ |
+ &InstX86Base<Machine>::Traits::Assembler::pcmpeq}; \ |
+ template <> \ |
+ const InstX86Base<Machine>::Traits::Assembler::XmmEmitterRegOp \ |
+ InstX86BasePcmpgt<Machine>::Base::Emitter = { \ |
+ &InstX86Base<Machine>::Traits::Assembler::pcmpgt, \ |
+ &InstX86Base<Machine>::Traits::Assembler::pcmpgt}; \ |
+ template <> \ |
+ const InstX86Base<Machine>::Traits::Assembler::XmmEmitterRegOp \ |
+ InstX86BasePmull<Machine>::Base::Emitter = { \ |
+ &InstX86Base<Machine>::Traits::Assembler::pmull, \ |
+ &InstX86Base<Machine>::Traits::Assembler::pmull}; \ |
+ template <> \ |
+ const InstX86Base<Machine>::Traits::Assembler::XmmEmitterRegOp \ |
+ InstX86BasePmuludq<Machine>::Base::Emitter = { \ |
+ &InstX86Base<Machine>::Traits::Assembler::pmuludq, \ |
+ &InstX86Base<Machine>::Traits::Assembler::pmuludq}; \ |
+ template <> \ |
+ const InstX86Base<Machine>::Traits::Assembler::XmmEmitterRegOp \ |
+ InstX86BasePor<Machine>::Base::Emitter = { \ |
+ &InstX86Base<Machine>::Traits::Assembler::por, \ |
+ &InstX86Base<Machine>::Traits::Assembler::por}; \ |
+ template <> \ |
+ const InstX86Base<Machine>::Traits::Assembler::XmmEmitterRegOp \ |
+ InstX86BasePsub<Machine>::Base::Emitter = { \ |
+ &InstX86Base<Machine>::Traits::Assembler::psub, \ |
+ &InstX86Base<Machine>::Traits::Assembler::psub}; \ |
+ template <> \ |
+ const InstX86Base<Machine>::Traits::Assembler::XmmEmitterRegOp \ |
+ InstX86BasePxor<Machine>::Base::Emitter = { \ |
+ &InstX86Base<Machine>::Traits::Assembler::pxor, \ |
+ &InstX86Base<Machine>::Traits::Assembler::pxor}; \ |
+ template <> \ |
+ const InstX86Base<Machine>::Traits::Assembler::XmmEmitterRegOp \ |
+ InstX86BaseSubss<Machine>::Base::Emitter = { \ |
+ &InstX86Base<Machine>::Traits::Assembler::subss, \ |
+ &InstX86Base<Machine>::Traits::Assembler::subss}; \ |
+ template <> \ |
+ const InstX86Base<Machine>::Traits::Assembler::XmmEmitterRegOp \ |
+ InstX86BaseSubps<Machine>::Base::Emitter = { \ |
+ &InstX86Base<Machine>::Traits::Assembler::subps, \ |
+ &InstX86Base<Machine>::Traits::Assembler::subps}; \ |
+ \ |
+ /* Binary XMM Shift ops */ \ |
+ template <> \ |
+ const InstX86Base<Machine>::Traits::Assembler::XmmEmitterShiftOp \ |
+ InstX86BasePsll<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 \ |
+ InstX86BasePsra<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 \ |
+ InstX86BasePsrl<Machine>::Base::Emitter = { \ |
+ &InstX86Base<Machine>::Traits::Assembler::psrl, \ |
+ &InstX86Base<Machine>::Traits::Assembler::psrl, \ |
+ &InstX86Base<Machine>::Traits::Assembler::psrl}; \ |
+ } \ |
+ } |
+ |
+} // end of namespace X86Internal |
+} // end of namespace Ice |
+ |
+#include "IceInstX86BaseImpl.h" |
+ |
+#endif // SUBZERO_SRC_ICEINSTX86BASE_H |