Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1094)

Unified Diff: src/IceInstX86Base.h

Issue 1216933015: X8632 Templatization completed. (Closed) Base URL: https://chromium.googlesource.com/native_client/pnacl-subzero.git@master
Patch Set: Addresses comments. Created 5 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
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

Powered by Google App Engine
This is Rietveld 408576698