Chromium Code Reviews| Index: src/IceInstX86Base.h |
| diff --git a/src/IceInstX86Base.h b/src/IceInstX86Base.h |
| new file mode 100644 |
| index 0000000000000000000000000000000000000000..75e1a5f73ddba4045ad7f5cfc69cfd904c305d04 |
| --- /dev/null |
| +++ b/src/IceInstX86Base.h |
| @@ -0,0 +1,3193 @@ |
| +//===- 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. |
| +// |
| +//===----------------------------------------------------------------------===// |
| +// |
|
jvoung (off chromium)
2015/07/07 00:00:18
Can you add the \file and /// for doxygen to this
John
2015/07/07 15:12:18
Done.
|
| +// This file defines the InstX86Base template class, as well as the generic X86 |
| +// Instruction class hierarchy. Only X86 instructions common across all/most X86 |
| +// targets should be defined here, with target-specific instructions declared in |
| +// the target's traits. |
| +// |
| +//===----------------------------------------------------------------------===// |
| + |
| +#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>; |
|
jvoung (off chromium)
2015/07/07 00:00:17
So just checking on this type aliasing, this can b
John
2015/07/07 15:12:18
Yes, this template <> struct Insts is just a short
|
| + 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 |