Index: src/IceInstX8632.cpp |
diff --git a/src/IceInstX8632.cpp b/src/IceInstX8632.cpp |
index fd33c55c534644009c491e6d55e79d612c558f0b..c6d6abf46b2a439395e3078e74a247c880687533 100644 |
--- a/src/IceInstX8632.cpp |
+++ b/src/IceInstX8632.cpp |
@@ -8,2912 +8,103 @@ |
//===----------------------------------------------------------------------===// |
/// |
/// \file |
-/// This file implements the InstX8632 and OperandX8632 classes, |
-/// primarily the constructors and the dump()/emit() methods. |
+/// This file defines X8632 specific data related to X8632 Instructions and |
+/// Instruction traits. These are declared in the IceTargetLoweringX8632Traits.h |
+/// header file. |
/// |
-//===----------------------------------------------------------------------===// |
- |
-#include "IceInstX8632.h" |
- |
-#include "IceAssemblerX8632.h" |
-#include "IceCfg.h" |
-#include "IceCfgNode.h" |
-#include "IceConditionCodesX8632.h" |
-#include "IceInst.h" |
-#include "IceRegistersX8632.h" |
-#include "IceTargetLoweringX8632.h" |
-#include "IceOperand.h" |
- |
-namespace Ice { |
- |
-namespace { |
- |
-const struct InstX8632BrAttributes_ { |
- X8632::Traits::Cond::BrCond Opposite; |
- const char *DisplayString; |
- const char *EmitString; |
-} InstX8632BrAttributes[] = { |
-#define X(tag, encode, opp, dump, emit) \ |
- { X8632::Traits::Cond::opp, dump, emit } \ |
- , |
- ICEINSTX8632BR_TABLE |
-#undef X |
-}; |
- |
-const struct InstX8632CmppsAttributes_ { |
- const char *EmitString; |
-} InstX8632CmppsAttributes[] = { |
-#define X(tag, emit) \ |
- { emit } \ |
- , |
- ICEINSTX8632CMPPS_TABLE |
-#undef X |
-}; |
- |
-const struct TypeX8632Attributes_ { |
- const char *CvtString; // i (integer), s (single FP), d (double FP) |
- const char *SdSsString; // ss, sd, or <blank> |
- const char *PackString; // b, w, d, or <blank> |
- const char *WidthString; // b, w, l, q, or <blank> |
- const char *FldString; // s, l, or <blank> |
-} TypeX8632Attributes[] = { |
-#define X(tag, elementty, cvt, sdss, pack, width, fld) \ |
- { cvt, sdss, pack, width, fld } \ |
- , |
- ICETYPEX8632_TABLE |
-#undef X |
-}; |
- |
-const char *InstX8632SegmentRegNames[] = { |
-#define X(val, name, prefix) name, |
- SEG_REGX8632_TABLE |
-#undef X |
-}; |
- |
-uint8_t InstX8632SegmentPrefixes[] = { |
-#define X(val, name, prefix) prefix, |
- SEG_REGX8632_TABLE |
-#undef X |
-}; |
- |
-} // end of anonymous namespace |
- |
-const char *InstX8632::getWidthString(Type Ty) { |
- return TypeX8632Attributes[Ty].WidthString; |
-} |
- |
-const char *InstX8632::getFldString(Type Ty) { |
- return TypeX8632Attributes[Ty].FldString; |
-} |
- |
-X8632::Traits::Cond::BrCond |
-InstX8632::getOppositeCondition(X8632::Traits::Cond::BrCond Cond) { |
- return InstX8632BrAttributes[Cond].Opposite; |
-} |
- |
-OperandX8632Mem::OperandX8632Mem(Cfg *Func, Type Ty, Variable *Base, |
- Constant *Offset, Variable *Index, |
- uint16_t Shift, SegmentRegisters SegmentReg) |
- : OperandX8632(kMem, Ty), Base(Base), Offset(Offset), Index(Index), |
- Shift(Shift), SegmentReg(SegmentReg), Randomized(false) { |
- assert(Shift <= 3); |
- Vars = nullptr; |
- NumVars = 0; |
- if (Base) |
- ++NumVars; |
- if (Index) |
- ++NumVars; |
- if (NumVars) { |
- Vars = Func->allocateArrayOf<Variable *>(NumVars); |
- SizeT I = 0; |
- if (Base) |
- Vars[I++] = Base; |
- if (Index) |
- Vars[I++] = Index; |
- assert(I == NumVars); |
- } |
-} |
- |
-InstX8632FakeRMW::InstX8632FakeRMW(Cfg *Func, Operand *Data, Operand *Addr, |
- InstArithmetic::OpKind Op, Variable *Beacon) |
- : InstX8632(Func, InstX8632::FakeRMW, 3, nullptr), Op(Op) { |
- addSource(Data); |
- addSource(Addr); |
- addSource(Beacon); |
-} |
- |
-InstX8632AdjustStack::InstX8632AdjustStack(Cfg *Func, SizeT Amount, |
- Variable *Esp) |
- : InstX8632(Func, InstX8632::Adjuststack, 1, Esp), Amount(Amount) { |
- addSource(Esp); |
-} |
- |
-InstX8632Mul::InstX8632Mul(Cfg *Func, Variable *Dest, Variable *Source1, |
- Operand *Source2) |
- : InstX8632(Func, InstX8632::Mul, 2, Dest) { |
- addSource(Source1); |
- addSource(Source2); |
-} |
- |
-InstX8632Shld::InstX8632Shld(Cfg *Func, Variable *Dest, Variable *Source1, |
- Variable *Source2) |
- : InstX8632(Func, InstX8632::Shld, 3, Dest) { |
- addSource(Dest); |
- addSource(Source1); |
- addSource(Source2); |
-} |
- |
-InstX8632Shrd::InstX8632Shrd(Cfg *Func, Variable *Dest, Variable *Source1, |
- Variable *Source2) |
- : InstX8632(Func, InstX8632::Shrd, 3, Dest) { |
- addSource(Dest); |
- addSource(Source1); |
- addSource(Source2); |
-} |
- |
-InstX8632Label::InstX8632Label(Cfg *Func, TargetX8632 *Target) |
- : InstX8632(Func, InstX8632::Label, 0, nullptr), |
- Number(Target->makeNextLabelNumber()) {} |
- |
-IceString InstX8632Label::getName(const Cfg *Func) const { |
- return ".L" + Func->getFunctionName() + "$local$__" + std::to_string(Number); |
-} |
- |
-InstX8632Br::InstX8632Br(Cfg *Func, const CfgNode *TargetTrue, |
- const CfgNode *TargetFalse, |
- const InstX8632Label *Label, |
- X8632::Traits::Cond::BrCond Condition) |
- : InstX8632(Func, InstX8632::Br, 0, nullptr), Condition(Condition), |
- TargetTrue(TargetTrue), TargetFalse(TargetFalse), Label(Label) {} |
- |
-bool InstX8632Br::optimizeBranch(const CfgNode *NextNode) { |
- // If there is no next block, then there can be no fallthrough to |
- // optimize. |
- if (NextNode == nullptr) |
- return false; |
- // Intra-block conditional branches can't be optimized. |
- if (Label) |
- return false; |
- // If there is no fallthrough node, such as a non-default case label |
- // for a switch instruction, then there is no opportunity to |
- // optimize. |
- if (getTargetFalse() == nullptr) |
- return false; |
- |
- // Unconditional branch to the next node can be removed. |
- if (Condition == X8632::Traits::Cond::Br_None && |
- getTargetFalse() == NextNode) { |
- assert(getTargetTrue() == nullptr); |
- setDeleted(); |
- return true; |
- } |
- // If the fallthrough is to the next node, set fallthrough to nullptr |
- // to indicate. |
- if (getTargetFalse() == NextNode) { |
- TargetFalse = nullptr; |
- return true; |
- } |
- // If TargetTrue is the next node, and TargetFalse is not nullptr |
- // (which was already tested above), then invert the branch |
- // condition, swap the targets, and set new fallthrough to nullptr. |
- if (getTargetTrue() == NextNode) { |
- assert(Condition != X8632::Traits::Cond::Br_None); |
- Condition = getOppositeCondition(Condition); |
- TargetTrue = getTargetFalse(); |
- TargetFalse = nullptr; |
- return true; |
- } |
- return false; |
-} |
- |
-bool InstX8632Br::repointEdge(CfgNode *OldNode, CfgNode *NewNode) { |
- if (TargetFalse == OldNode) { |
- TargetFalse = NewNode; |
- return true; |
- } else if (TargetTrue == OldNode) { |
- TargetTrue = NewNode; |
- return true; |
- } |
- return false; |
-} |
- |
-InstX8632Jmp::InstX8632Jmp(Cfg *Func, Operand *Target) |
- : InstX8632(Func, InstX8632::Jmp, 1, nullptr) { |
- addSource(Target); |
-} |
- |
-InstX8632Call::InstX8632Call(Cfg *Func, Variable *Dest, Operand *CallTarget) |
- : InstX8632(Func, InstX8632::Call, 1, Dest) { |
- HasSideEffects = true; |
- addSource(CallTarget); |
-} |
- |
-InstX8632Cmov::InstX8632Cmov(Cfg *Func, Variable *Dest, Operand *Source, |
- X8632::Traits::Cond::BrCond Condition) |
- : InstX8632(Func, InstX8632::Cmov, 2, Dest), Condition(Condition) { |
- // The final result is either the original Dest, or Source, so mark |
- // both as sources. |
- addSource(Dest); |
- addSource(Source); |
-} |
- |
-InstX8632Cmpps::InstX8632Cmpps(Cfg *Func, Variable *Dest, Operand *Source, |
- X8632::Traits::Cond::CmppsCond Condition) |
- : InstX8632(Func, InstX8632::Cmpps, 2, Dest), Condition(Condition) { |
- addSource(Dest); |
- addSource(Source); |
-} |
- |
-InstX8632Cmpxchg::InstX8632Cmpxchg(Cfg *Func, Operand *DestOrAddr, |
- Variable *Eax, Variable *Desired, |
- bool Locked) |
- : InstX8632Lockable(Func, InstX8632::Cmpxchg, 3, |
- llvm::dyn_cast<Variable>(DestOrAddr), Locked) { |
- assert(Eax->getRegNum() == RegX8632::Reg_eax); |
- addSource(DestOrAddr); |
- addSource(Eax); |
- addSource(Desired); |
-} |
- |
-InstX8632Cmpxchg8b::InstX8632Cmpxchg8b(Cfg *Func, OperandX8632Mem *Addr, |
- Variable *Edx, Variable *Eax, |
- Variable *Ecx, Variable *Ebx, |
- bool Locked) |
- : InstX8632Lockable(Func, InstX8632::Cmpxchg, 5, nullptr, Locked) { |
- assert(Edx->getRegNum() == RegX8632::Reg_edx); |
- assert(Eax->getRegNum() == RegX8632::Reg_eax); |
- assert(Ecx->getRegNum() == RegX8632::Reg_ecx); |
- assert(Ebx->getRegNum() == RegX8632::Reg_ebx); |
- addSource(Addr); |
- addSource(Edx); |
- addSource(Eax); |
- addSource(Ecx); |
- addSource(Ebx); |
-} |
- |
-InstX8632Cvt::InstX8632Cvt(Cfg *Func, Variable *Dest, Operand *Source, |
- CvtVariant Variant) |
- : InstX8632(Func, InstX8632::Cvt, 1, Dest), Variant(Variant) { |
- addSource(Source); |
-} |
- |
-InstX8632Icmp::InstX8632Icmp(Cfg *Func, Operand *Src0, Operand *Src1) |
- : InstX8632(Func, InstX8632::Icmp, 2, nullptr) { |
- addSource(Src0); |
- addSource(Src1); |
-} |
- |
-InstX8632Ucomiss::InstX8632Ucomiss(Cfg *Func, Operand *Src0, Operand *Src1) |
- : InstX8632(Func, InstX8632::Ucomiss, 2, nullptr) { |
- addSource(Src0); |
- addSource(Src1); |
-} |
- |
-InstX8632UD2::InstX8632UD2(Cfg *Func) |
- : InstX8632(Func, InstX8632::UD2, 0, nullptr) {} |
- |
-InstX8632Test::InstX8632Test(Cfg *Func, Operand *Src1, Operand *Src2) |
- : InstX8632(Func, InstX8632::Test, 2, nullptr) { |
- addSource(Src1); |
- addSource(Src2); |
-} |
- |
-InstX8632Mfence::InstX8632Mfence(Cfg *Func) |
- : InstX8632(Func, InstX8632::Mfence, 0, nullptr) { |
- HasSideEffects = true; |
-} |
- |
-InstX8632Store::InstX8632Store(Cfg *Func, Operand *Value, OperandX8632 *Mem) |
- : InstX8632(Func, InstX8632::Store, 2, nullptr) { |
- addSource(Value); |
- addSource(Mem); |
-} |
- |
-InstX8632StoreP::InstX8632StoreP(Cfg *Func, Variable *Value, |
- OperandX8632Mem *Mem) |
- : InstX8632(Func, InstX8632::StoreP, 2, nullptr) { |
- addSource(Value); |
- addSource(Mem); |
-} |
- |
-InstX8632StoreQ::InstX8632StoreQ(Cfg *Func, Variable *Value, |
- OperandX8632Mem *Mem) |
- : InstX8632(Func, InstX8632::StoreQ, 2, nullptr) { |
- addSource(Value); |
- addSource(Mem); |
-} |
- |
-InstX8632Nop::InstX8632Nop(Cfg *Func, InstX8632Nop::NopVariant Variant) |
- : InstX8632(Func, InstX8632::Nop, 0, nullptr), Variant(Variant) {} |
- |
-InstX8632Fld::InstX8632Fld(Cfg *Func, Operand *Src) |
- : InstX8632(Func, InstX8632::Fld, 1, nullptr) { |
- addSource(Src); |
-} |
- |
-InstX8632Fstp::InstX8632Fstp(Cfg *Func, Variable *Dest) |
- : InstX8632(Func, InstX8632::Fstp, 0, Dest) {} |
- |
-InstX8632Pop::InstX8632Pop(Cfg *Func, Variable *Dest) |
- : InstX8632(Func, InstX8632::Pop, 0, Dest) { |
- // A pop instruction affects the stack pointer and so it should not |
- // be allowed to be automatically dead-code eliminated. (The |
- // corresponding push instruction doesn't need this treatment |
- // because it has no dest variable and therefore won't be dead-code |
- // eliminated.) This is needed for late-stage liveness analysis |
- // (e.g. asm-verbose mode). |
- HasSideEffects = true; |
-} |
- |
-InstX8632Push::InstX8632Push(Cfg *Func, Variable *Source) |
- : InstX8632(Func, InstX8632::Push, 1, nullptr) { |
- addSource(Source); |
-} |
- |
-InstX8632Ret::InstX8632Ret(Cfg *Func, Variable *Source) |
- : InstX8632(Func, InstX8632::Ret, Source ? 1 : 0, nullptr) { |
- if (Source) |
- addSource(Source); |
-} |
- |
-InstX8632Setcc::InstX8632Setcc(Cfg *Func, Variable *Dest, |
- X8632::Traits::Cond::BrCond Cond) |
- : InstX8632(Func, InstX8632::Setcc, 0, Dest), Condition(Cond) {} |
- |
-InstX8632Xadd::InstX8632Xadd(Cfg *Func, Operand *Dest, Variable *Source, |
- bool Locked) |
- : InstX8632Lockable(Func, InstX8632::Xadd, 2, |
- llvm::dyn_cast<Variable>(Dest), Locked) { |
- addSource(Dest); |
- addSource(Source); |
-} |
- |
-InstX8632Xchg::InstX8632Xchg(Cfg *Func, Operand *Dest, Variable *Source) |
- : InstX8632(Func, InstX8632::Xchg, 2, llvm::dyn_cast<Variable>(Dest)) { |
- addSource(Dest); |
- addSource(Source); |
-} |
- |
-// ======================== Dump routines ======================== // |
- |
-void InstX8632::dump(const Cfg *Func) const { |
- if (!BuildDefs::dump()) |
- return; |
- Ostream &Str = Func->getContext()->getStrDump(); |
- Str << "[X8632] "; |
- Inst::dump(Func); |
-} |
- |
-void InstX8632FakeRMW::dump(const Cfg *Func) const { |
- if (!BuildDefs::dump()) |
- return; |
- Ostream &Str = Func->getContext()->getStrDump(); |
- Type Ty = getData()->getType(); |
- Str << "rmw " << InstArithmetic::getOpName(getOp()) << " " << Ty << " *"; |
- getAddr()->dump(Func); |
- Str << ", "; |
- getData()->dump(Func); |
- Str << ", beacon="; |
- getBeacon()->dump(Func); |
-} |
- |
-void InstX8632Label::emit(const Cfg *Func) const { |
- if (!BuildDefs::dump()) |
- return; |
- Ostream &Str = Func->getContext()->getStrEmit(); |
- Str << getName(Func) << ":"; |
-} |
- |
-void InstX8632Label::emitIAS(const Cfg *Func) const { |
- X8632::AssemblerX8632 *Asm = Func->getAssembler<X8632::AssemblerX8632>(); |
- Asm->BindLocalLabel(Number); |
-} |
- |
-void InstX8632Label::dump(const Cfg *Func) const { |
- if (!BuildDefs::dump()) |
- return; |
- Ostream &Str = Func->getContext()->getStrDump(); |
- Str << getName(Func) << ":"; |
-} |
- |
-void InstX8632Br::emit(const Cfg *Func) const { |
- if (!BuildDefs::dump()) |
- return; |
- Ostream &Str = Func->getContext()->getStrEmit(); |
- Str << "\t"; |
- |
- if (Condition == X8632::Traits::Cond::Br_None) { |
- Str << "jmp"; |
- } else { |
- Str << InstX8632BrAttributes[Condition].EmitString; |
- } |
- |
- if (Label) { |
- Str << "\t" << Label->getName(Func); |
- } else { |
- if (Condition == X8632::Traits::Cond::Br_None) { |
- Str << "\t" << getTargetFalse()->getAsmName(); |
- } else { |
- Str << "\t" << getTargetTrue()->getAsmName(); |
- if (getTargetFalse()) { |
- Str << "\n\tjmp\t" << getTargetFalse()->getAsmName(); |
- } |
- } |
- } |
-} |
- |
-void InstX8632Br::emitIAS(const Cfg *Func) const { |
- X8632::AssemblerX8632 *Asm = Func->getAssembler<X8632::AssemblerX8632>(); |
- if (Label) { |
- X8632::Label *L = Asm->GetOrCreateLocalLabel(Label->getNumber()); |
- // In all these cases, local Labels should only be used for Near. |
- const bool Near = true; |
- if (Condition == X8632::Traits::Cond::Br_None) { |
- Asm->jmp(L, Near); |
- } else { |
- Asm->j(Condition, L, Near); |
- } |
- } else { |
- // Pessimistically assume it's far. This only affects Labels that |
- // are not Bound. |
- const bool Near = false; |
- if (Condition == X8632::Traits::Cond::Br_None) { |
- X8632::Label *L = |
- Asm->GetOrCreateCfgNodeLabel(getTargetFalse()->getIndex()); |
- assert(!getTargetTrue()); |
- Asm->jmp(L, Near); |
- } else { |
- X8632::Label *L = |
- Asm->GetOrCreateCfgNodeLabel(getTargetTrue()->getIndex()); |
- Asm->j(Condition, L, Near); |
- if (getTargetFalse()) { |
- X8632::Label *L2 = |
- Asm->GetOrCreateCfgNodeLabel(getTargetFalse()->getIndex()); |
- Asm->jmp(L2, Near); |
- } |
- } |
- } |
-} |
- |
-void InstX8632Br::dump(const Cfg *Func) const { |
- if (!BuildDefs::dump()) |
- return; |
- Ostream &Str = Func->getContext()->getStrDump(); |
- Str << "br "; |
- |
- if (Condition == X8632::Traits::Cond::Br_None) { |
- Str << "label %" |
- << (Label ? Label->getName(Func) : getTargetFalse()->getName()); |
- return; |
- } |
- |
- Str << InstX8632BrAttributes[Condition].DisplayString; |
- if (Label) { |
- Str << ", label %" << Label->getName(Func); |
- } else { |
- Str << ", label %" << getTargetTrue()->getName(); |
- if (getTargetFalse()) { |
- Str << ", label %" << getTargetFalse()->getName(); |
- } |
- } |
-} |
- |
-void InstX8632Jmp::emit(const Cfg *Func) const { |
- if (!BuildDefs::dump()) |
- return; |
- Ostream &Str = Func->getContext()->getStrEmit(); |
- assert(getSrcSize() == 1); |
- Str << "\tjmp\t*"; |
- getJmpTarget()->emit(Func); |
-} |
- |
-void InstX8632Jmp::emitIAS(const Cfg *Func) const { |
- // Note: Adapted (mostly copied) from InstX8632Call::emitIAS(). |
- X8632::AssemblerX8632 *Asm = Func->getAssembler<X8632::AssemblerX8632>(); |
- Operand *Target = getJmpTarget(); |
- if (const auto Var = llvm::dyn_cast<Variable>(Target)) { |
- if (Var->hasReg()) { |
- Asm->jmp(RegX8632::getEncodedGPR(Var->getRegNum())); |
- } else { |
- // The jmp instruction with a memory operand should be possible |
- // to encode, but it isn't a valid sandboxed instruction, and |
- // there shouldn't be a register allocation issue to jump |
- // through a scratch register, so we don't really need to bother |
- // implementing it. |
- llvm::report_fatal_error("Assembler can't jmp to memory operand"); |
- } |
- } else if (const auto Mem = llvm::dyn_cast<OperandX8632Mem>(Target)) { |
- (void)Mem; |
- assert(Mem->getSegmentRegister() == OperandX8632Mem::DefaultSegment); |
- llvm::report_fatal_error("Assembler can't jmp to memory operand"); |
- } else if (const auto CR = llvm::dyn_cast<ConstantRelocatable>(Target)) { |
- assert(CR->getOffset() == 0 && "We only support jumping to a function"); |
- Asm->jmp(CR); |
- } else if (const auto Imm = llvm::dyn_cast<ConstantInteger32>(Target)) { |
- // NaCl trampoline calls refer to an address within the sandbox directly. |
- // This is usually only needed for non-IRT builds and otherwise not |
- // very portable or stable. Usually this is only done for "calls" |
- // and not jumps. |
- // TODO(jvoung): Support this when there is a lowering that |
- // actually triggers this case. |
- (void)Imm; |
- llvm::report_fatal_error("Unexpected jmp to absolute address"); |
- } else { |
- llvm::report_fatal_error("Unexpected operand type"); |
- } |
-} |
- |
-void InstX8632Jmp::dump(const Cfg *Func) const { |
- if (!BuildDefs::dump()) |
- return; |
- Ostream &Str = Func->getContext()->getStrDump(); |
- Str << "jmp "; |
- getJmpTarget()->dump(Func); |
-} |
- |
-void InstX8632Call::emit(const Cfg *Func) const { |
- if (!BuildDefs::dump()) |
- return; |
- Ostream &Str = Func->getContext()->getStrEmit(); |
- assert(getSrcSize() == 1); |
- Str << "\tcall\t"; |
- if (const auto CI = llvm::dyn_cast<ConstantInteger32>(getCallTarget())) { |
- // Emit without a leading '$'. |
- Str << CI->getValue(); |
- } else if (const auto CallTarget = |
- llvm::dyn_cast<ConstantRelocatable>(getCallTarget())) { |
- CallTarget->emitWithoutPrefix(Func->getTarget()); |
- } else { |
- Str << "*"; |
- getCallTarget()->emit(Func); |
- } |
- Func->getTarget()->resetStackAdjustment(); |
-} |
- |
-void InstX8632Call::emitIAS(const Cfg *Func) const { |
- X8632::AssemblerX8632 *Asm = Func->getAssembler<X8632::AssemblerX8632>(); |
- Operand *Target = getCallTarget(); |
- if (const auto Var = llvm::dyn_cast<Variable>(Target)) { |
- if (Var->hasReg()) { |
- Asm->call(RegX8632::getEncodedGPR(Var->getRegNum())); |
- } else { |
- Asm->call(static_cast<TargetX8632 *>(Func->getTarget()) |
- ->stackVarToAsmOperand(Var)); |
- } |
- } else if (const auto Mem = llvm::dyn_cast<OperandX8632Mem>(Target)) { |
- assert(Mem->getSegmentRegister() == OperandX8632Mem::DefaultSegment); |
- Asm->call(Mem->toAsmAddress(Asm)); |
- } else if (const auto CR = llvm::dyn_cast<ConstantRelocatable>(Target)) { |
- assert(CR->getOffset() == 0 && "We only support calling a function"); |
- Asm->call(CR); |
- } else if (const auto Imm = llvm::dyn_cast<ConstantInteger32>(Target)) { |
- Asm->call(X8632::Immediate(Imm->getValue())); |
- } else { |
- llvm_unreachable("Unexpected operand type"); |
- } |
- Func->getTarget()->resetStackAdjustment(); |
-} |
- |
-void InstX8632Call::dump(const Cfg *Func) const { |
- if (!BuildDefs::dump()) |
- return; |
- Ostream &Str = Func->getContext()->getStrDump(); |
- if (getDest()) { |
- dumpDest(Func); |
- Str << " = "; |
- } |
- Str << "call "; |
- getCallTarget()->dump(Func); |
-} |
- |
-// The ShiftHack parameter is used to emit "cl" instead of "ecx" for |
-// shift instructions, in order to be syntactically valid. The |
-// Opcode parameter needs to be char* and not IceString because of |
-// template issues. |
-void InstX8632::emitTwoAddress(const char *Opcode, const Inst *Inst, |
- const Cfg *Func, bool ShiftHack) { |
- if (!BuildDefs::dump()) |
- return; |
- Ostream &Str = Func->getContext()->getStrEmit(); |
- assert(Inst->getSrcSize() == 2); |
- Operand *Dest = Inst->getDest(); |
- if (Dest == nullptr) |
- Dest = Inst->getSrc(0); |
- assert(Dest == Inst->getSrc(0)); |
- Operand *Src1 = Inst->getSrc(1); |
- Str << "\t" << Opcode << InstX8632::getWidthString(Dest->getType()) << "\t"; |
- const auto ShiftReg = llvm::dyn_cast<Variable>(Src1); |
- if (ShiftHack && ShiftReg && ShiftReg->getRegNum() == RegX8632::Reg_ecx) |
- Str << "%cl"; |
- else |
- Src1->emit(Func); |
- Str << ", "; |
- Dest->emit(Func); |
-} |
- |
-void emitIASOpTyGPR(const Cfg *Func, Type Ty, const Operand *Op, |
- const X8632::AssemblerX8632::GPREmitterOneOp &Emitter) { |
- X8632::AssemblerX8632 *Asm = Func->getAssembler<X8632::AssemblerX8632>(); |
- if (const auto Var = llvm::dyn_cast<Variable>(Op)) { |
- if (Var->hasReg()) { |
- // We cheat a little and use GPRRegister even for byte operations. |
- RegX8632::GPRRegister VarReg = |
- RegX8632::getEncodedByteRegOrGPR(Ty, Var->getRegNum()); |
- (Asm->*(Emitter.Reg))(Ty, VarReg); |
- } else { |
- X8632::Traits::Address StackAddr( |
- static_cast<TargetX8632 *>(Func->getTarget()) |
- ->stackVarToAsmOperand(Var)); |
- (Asm->*(Emitter.Addr))(Ty, StackAddr); |
- } |
- } else if (const auto Mem = llvm::dyn_cast<OperandX8632Mem>(Op)) { |
- Mem->emitSegmentOverride(Asm); |
- (Asm->*(Emitter.Addr))(Ty, Mem->toAsmAddress(Asm)); |
- } else { |
- llvm_unreachable("Unexpected operand type"); |
- } |
-} |
- |
-template <bool VarCanBeByte, bool SrcCanBeByte> |
-void emitIASRegOpTyGPR(const Cfg *Func, Type Ty, const Variable *Var, |
- const Operand *Src, |
- const X8632::AssemblerX8632::GPREmitterRegOp &Emitter) { |
- X8632::AssemblerX8632 *Asm = Func->getAssembler<X8632::AssemblerX8632>(); |
- assert(Var->hasReg()); |
- // We cheat a little and use GPRRegister even for byte operations. |
- RegX8632::GPRRegister VarReg = |
- VarCanBeByte ? RegX8632::getEncodedByteRegOrGPR(Ty, Var->getRegNum()) |
- : RegX8632::getEncodedGPR(Var->getRegNum()); |
- if (const auto SrcVar = llvm::dyn_cast<Variable>(Src)) { |
- if (SrcVar->hasReg()) { |
- RegX8632::GPRRegister SrcReg = |
- SrcCanBeByte |
- ? RegX8632::getEncodedByteRegOrGPR(Ty, SrcVar->getRegNum()) |
- : RegX8632::getEncodedGPR(SrcVar->getRegNum()); |
- (Asm->*(Emitter.GPRGPR))(Ty, VarReg, SrcReg); |
- } else { |
- X8632::Traits::Address SrcStackAddr = |
- static_cast<TargetX8632 *>(Func->getTarget()) |
- ->stackVarToAsmOperand(SrcVar); |
- (Asm->*(Emitter.GPRAddr))(Ty, VarReg, SrcStackAddr); |
- } |
- } else if (const auto Mem = llvm::dyn_cast<OperandX8632Mem>(Src)) { |
- Mem->emitSegmentOverride(Asm); |
- (Asm->*(Emitter.GPRAddr))(Ty, VarReg, Mem->toAsmAddress(Asm)); |
- } else if (const auto Imm = llvm::dyn_cast<ConstantInteger32>(Src)) { |
- (Asm->*(Emitter.GPRImm))(Ty, VarReg, X8632::Immediate(Imm->getValue())); |
- } else if (const auto Reloc = llvm::dyn_cast<ConstantRelocatable>(Src)) { |
- AssemblerFixup *Fixup = Asm->createFixup(llvm::ELF::R_386_32, Reloc); |
- (Asm->*(Emitter.GPRImm))(Ty, VarReg, |
- X8632::Immediate(Reloc->getOffset(), Fixup)); |
- } else if (const auto Split = llvm::dyn_cast<VariableSplit>(Src)) { |
- (Asm->*(Emitter.GPRAddr))(Ty, VarReg, Split->toAsmAddress(Func)); |
- } else { |
- llvm_unreachable("Unexpected operand type"); |
- } |
-} |
- |
-void emitIASAddrOpTyGPR( |
- const Cfg *Func, Type Ty, const X8632::Traits::Address &Addr, |
- const Operand *Src, |
- const X8632::AssemblerX8632::GPREmitterAddrOp &Emitter) { |
- X8632::AssemblerX8632 *Asm = Func->getAssembler<X8632::AssemblerX8632>(); |
- // Src can only be Reg or Immediate. |
- if (const auto SrcVar = llvm::dyn_cast<Variable>(Src)) { |
- assert(SrcVar->hasReg()); |
- RegX8632::GPRRegister SrcReg = |
- RegX8632::getEncodedByteRegOrGPR(Ty, SrcVar->getRegNum()); |
- (Asm->*(Emitter.AddrGPR))(Ty, Addr, SrcReg); |
- } else if (const auto Imm = llvm::dyn_cast<ConstantInteger32>(Src)) { |
- (Asm->*(Emitter.AddrImm))(Ty, Addr, X8632::Immediate(Imm->getValue())); |
- } else if (const auto Reloc = llvm::dyn_cast<ConstantRelocatable>(Src)) { |
- AssemblerFixup *Fixup = Asm->createFixup(llvm::ELF::R_386_32, Reloc); |
- (Asm->*(Emitter.AddrImm))(Ty, Addr, |
- X8632::Immediate(Reloc->getOffset(), Fixup)); |
- } else { |
- llvm_unreachable("Unexpected operand type"); |
- } |
-} |
- |
-void emitIASAsAddrOpTyGPR( |
- const Cfg *Func, Type Ty, const Operand *Op0, const Operand *Op1, |
- const X8632::AssemblerX8632::GPREmitterAddrOp &Emitter) { |
- if (const auto Op0Var = llvm::dyn_cast<Variable>(Op0)) { |
- assert(!Op0Var->hasReg()); |
- X8632::Traits::Address StackAddr( |
- static_cast<TargetX8632 *>(Func->getTarget()) |
- ->stackVarToAsmOperand(Op0Var)); |
- emitIASAddrOpTyGPR(Func, Ty, StackAddr, Op1, Emitter); |
- } else if (const auto Op0Mem = llvm::dyn_cast<OperandX8632Mem>(Op0)) { |
- X8632::AssemblerX8632 *Asm = Func->getAssembler<X8632::AssemblerX8632>(); |
- Op0Mem->emitSegmentOverride(Asm); |
- emitIASAddrOpTyGPR(Func, Ty, Op0Mem->toAsmAddress(Asm), Op1, Emitter); |
- } else if (const auto Split = llvm::dyn_cast<VariableSplit>(Op0)) { |
- emitIASAddrOpTyGPR(Func, Ty, Split->toAsmAddress(Func), Op1, Emitter); |
- } else { |
- llvm_unreachable("Unexpected operand type"); |
- } |
-} |
- |
-void InstX8632::emitIASGPRShift( |
- const Cfg *Func, Type Ty, const Variable *Var, const Operand *Src, |
- const X8632::AssemblerX8632::GPREmitterShiftOp &Emitter) { |
- X8632::AssemblerX8632 *Asm = Func->getAssembler<X8632::AssemblerX8632>(); |
- // Technically, the Dest Var can be mem as well, but we only use Reg. |
- // We can extend this to check Dest if we decide to use that form. |
- assert(Var->hasReg()); |
- // We cheat a little and use GPRRegister even for byte operations. |
- RegX8632::GPRRegister VarReg = |
- RegX8632::getEncodedByteRegOrGPR(Ty, Var->getRegNum()); |
- // Src must be reg == ECX or an Imm8. |
- // This is asserted by the assembler. |
- if (const auto SrcVar = llvm::dyn_cast<Variable>(Src)) { |
- assert(SrcVar->hasReg()); |
- RegX8632::GPRRegister SrcReg = |
- RegX8632::getEncodedByteRegOrGPR(Ty, SrcVar->getRegNum()); |
- (Asm->*(Emitter.GPRGPR))(Ty, VarReg, SrcReg); |
- } else if (const auto Imm = llvm::dyn_cast<ConstantInteger32>(Src)) { |
- (Asm->*(Emitter.GPRImm))(Ty, VarReg, X8632::Immediate(Imm->getValue())); |
- } else { |
- llvm_unreachable("Unexpected operand type"); |
- } |
-} |
- |
-void emitIASGPRShiftDouble( |
- const Cfg *Func, const Variable *Dest, const Operand *Src1Op, |
- const Operand *Src2Op, |
- const X8632::AssemblerX8632::GPREmitterShiftD &Emitter) { |
- X8632::AssemblerX8632 *Asm = Func->getAssembler<X8632::AssemblerX8632>(); |
- // Dest can be reg or mem, but we only use the reg variant. |
- assert(Dest->hasReg()); |
- RegX8632::GPRRegister DestReg = RegX8632::getEncodedGPR(Dest->getRegNum()); |
- // SrcVar1 must be reg. |
- const auto SrcVar1 = llvm::cast<Variable>(Src1Op); |
- assert(SrcVar1->hasReg()); |
- RegX8632::GPRRegister SrcReg = RegX8632::getEncodedGPR(SrcVar1->getRegNum()); |
- Type Ty = SrcVar1->getType(); |
- // Src2 can be the implicit CL register or an immediate. |
- if (const auto Imm = llvm::dyn_cast<ConstantInteger32>(Src2Op)) { |
- (Asm->*(Emitter.GPRGPRImm))(Ty, DestReg, SrcReg, |
- X8632::Immediate(Imm->getValue())); |
- } else { |
- assert(llvm::cast<Variable>(Src2Op)->getRegNum() == RegX8632::Reg_ecx); |
- (Asm->*(Emitter.GPRGPR))(Ty, DestReg, SrcReg); |
- } |
-} |
- |
-void emitIASXmmShift(const Cfg *Func, Type Ty, const Variable *Var, |
- const Operand *Src, |
- const X8632::AssemblerX8632::XmmEmitterShiftOp &Emitter) { |
- X8632::AssemblerX8632 *Asm = Func->getAssembler<X8632::AssemblerX8632>(); |
- assert(Var->hasReg()); |
- RegX8632::XmmRegister VarReg = RegX8632::getEncodedXmm(Var->getRegNum()); |
- if (const auto SrcVar = llvm::dyn_cast<Variable>(Src)) { |
- if (SrcVar->hasReg()) { |
- RegX8632::XmmRegister SrcReg = |
- RegX8632::getEncodedXmm(SrcVar->getRegNum()); |
- (Asm->*(Emitter.XmmXmm))(Ty, VarReg, SrcReg); |
- } else { |
- X8632::Traits::Address SrcStackAddr = |
- static_cast<TargetX8632 *>(Func->getTarget()) |
- ->stackVarToAsmOperand(SrcVar); |
- (Asm->*(Emitter.XmmAddr))(Ty, VarReg, SrcStackAddr); |
- } |
- } else if (const auto Mem = llvm::dyn_cast<OperandX8632Mem>(Src)) { |
- assert(Mem->getSegmentRegister() == OperandX8632Mem::DefaultSegment); |
- (Asm->*(Emitter.XmmAddr))(Ty, VarReg, Mem->toAsmAddress(Asm)); |
- } else if (const auto Imm = llvm::dyn_cast<ConstantInteger32>(Src)) { |
- (Asm->*(Emitter.XmmImm))(Ty, VarReg, X8632::Immediate(Imm->getValue())); |
- } else { |
- llvm_unreachable("Unexpected operand type"); |
- } |
-} |
- |
-void emitIASRegOpTyXMM(const Cfg *Func, Type Ty, const Variable *Var, |
- const Operand *Src, |
- const X8632::AssemblerX8632::XmmEmitterRegOp &Emitter) { |
- X8632::AssemblerX8632 *Asm = Func->getAssembler<X8632::AssemblerX8632>(); |
- assert(Var->hasReg()); |
- RegX8632::XmmRegister VarReg = RegX8632::getEncodedXmm(Var->getRegNum()); |
- if (const auto SrcVar = llvm::dyn_cast<Variable>(Src)) { |
- if (SrcVar->hasReg()) { |
- RegX8632::XmmRegister SrcReg = |
- RegX8632::getEncodedXmm(SrcVar->getRegNum()); |
- (Asm->*(Emitter.XmmXmm))(Ty, VarReg, SrcReg); |
- } else { |
- X8632::Traits::Address SrcStackAddr = |
- static_cast<TargetX8632 *>(Func->getTarget()) |
- ->stackVarToAsmOperand(SrcVar); |
- (Asm->*(Emitter.XmmAddr))(Ty, VarReg, SrcStackAddr); |
- } |
- } else if (const auto Mem = llvm::dyn_cast<OperandX8632Mem>(Src)) { |
- assert(Mem->getSegmentRegister() == OperandX8632Mem::DefaultSegment); |
- (Asm->*(Emitter.XmmAddr))(Ty, VarReg, Mem->toAsmAddress(Asm)); |
- } else if (const auto Imm = llvm::dyn_cast<Constant>(Src)) { |
- (Asm->*(Emitter.XmmAddr))(Ty, VarReg, |
- X8632::Traits::Address::ofConstPool(Asm, Imm)); |
- } else { |
- llvm_unreachable("Unexpected operand type"); |
- } |
-} |
- |
-template <typename DReg_t, typename SReg_t, DReg_t (*destEnc)(int32_t), |
- SReg_t (*srcEnc)(int32_t)> |
-void emitIASCastRegOp( |
- const Cfg *Func, Type DispatchTy, const Variable *Dest, const Operand *Src, |
- const X8632::AssemblerX8632::CastEmitterRegOp<DReg_t, SReg_t> Emitter) { |
- X8632::AssemblerX8632 *Asm = Func->getAssembler<X8632::AssemblerX8632>(); |
- assert(Dest->hasReg()); |
- DReg_t DestReg = destEnc(Dest->getRegNum()); |
- if (const auto SrcVar = llvm::dyn_cast<Variable>(Src)) { |
- if (SrcVar->hasReg()) { |
- SReg_t SrcReg = srcEnc(SrcVar->getRegNum()); |
- (Asm->*(Emitter.RegReg))(DispatchTy, DestReg, SrcReg); |
- } else { |
- X8632::Traits::Address SrcStackAddr = |
- static_cast<TargetX8632 *>(Func->getTarget()) |
- ->stackVarToAsmOperand(SrcVar); |
- (Asm->*(Emitter.RegAddr))(DispatchTy, DestReg, SrcStackAddr); |
- } |
- } else if (const auto Mem = llvm::dyn_cast<OperandX8632Mem>(Src)) { |
- Mem->emitSegmentOverride(Asm); |
- (Asm->*(Emitter.RegAddr))(DispatchTy, DestReg, Mem->toAsmAddress(Asm)); |
- } else { |
- llvm_unreachable("Unexpected operand type"); |
- } |
-} |
- |
-template <typename DReg_t, typename SReg_t, DReg_t (*destEnc)(int32_t), |
- SReg_t (*srcEnc)(int32_t)> |
-void emitIASThreeOpImmOps( |
- const Cfg *Func, Type DispatchTy, const Variable *Dest, const Operand *Src0, |
- const Operand *Src1, |
- const X8632::AssemblerX8632::ThreeOpImmEmitter<DReg_t, SReg_t> Emitter) { |
- X8632::AssemblerX8632 *Asm = Func->getAssembler<X8632::AssemblerX8632>(); |
- // This only handles Dest being a register, and Src1 being an immediate. |
- assert(Dest->hasReg()); |
- DReg_t DestReg = destEnc(Dest->getRegNum()); |
- X8632::Immediate Imm(llvm::cast<ConstantInteger32>(Src1)->getValue()); |
- if (const auto SrcVar = llvm::dyn_cast<Variable>(Src0)) { |
- if (SrcVar->hasReg()) { |
- SReg_t SrcReg = srcEnc(SrcVar->getRegNum()); |
- (Asm->*(Emitter.RegRegImm))(DispatchTy, DestReg, SrcReg, Imm); |
- } else { |
- X8632::Traits::Address SrcStackAddr = |
- static_cast<TargetX8632 *>(Func->getTarget()) |
- ->stackVarToAsmOperand(SrcVar); |
- (Asm->*(Emitter.RegAddrImm))(DispatchTy, DestReg, SrcStackAddr, Imm); |
- } |
- } else if (const auto Mem = llvm::dyn_cast<OperandX8632Mem>(Src0)) { |
- Mem->emitSegmentOverride(Asm); |
- (Asm->*(Emitter.RegAddrImm))(DispatchTy, DestReg, Mem->toAsmAddress(Asm), |
- Imm); |
- } else { |
- llvm_unreachable("Unexpected operand type"); |
- } |
-} |
- |
-void emitIASMovlikeXMM(const Cfg *Func, const Variable *Dest, |
- const Operand *Src, |
- const X8632::AssemblerX8632::XmmEmitterMovOps Emitter) { |
- X8632::AssemblerX8632 *Asm = Func->getAssembler<X8632::AssemblerX8632>(); |
- if (Dest->hasReg()) { |
- RegX8632::XmmRegister DestReg = RegX8632::getEncodedXmm(Dest->getRegNum()); |
- if (const auto SrcVar = llvm::dyn_cast<Variable>(Src)) { |
- if (SrcVar->hasReg()) { |
- (Asm->*(Emitter.XmmXmm))(DestReg, |
- RegX8632::getEncodedXmm(SrcVar->getRegNum())); |
- } else { |
- X8632::Traits::Address StackAddr( |
- static_cast<TargetX8632 *>(Func->getTarget()) |
- ->stackVarToAsmOperand(SrcVar)); |
- (Asm->*(Emitter.XmmAddr))(DestReg, StackAddr); |
- } |
- } else if (const auto SrcMem = llvm::dyn_cast<OperandX8632Mem>(Src)) { |
- assert(SrcMem->getSegmentRegister() == OperandX8632Mem::DefaultSegment); |
- (Asm->*(Emitter.XmmAddr))(DestReg, SrcMem->toAsmAddress(Asm)); |
- } else { |
- llvm_unreachable("Unexpected operand type"); |
- } |
- } else { |
- X8632::Traits::Address StackAddr( |
- static_cast<TargetX8632 *>(Func->getTarget()) |
- ->stackVarToAsmOperand(Dest)); |
- // Src must be a register in this case. |
- const auto SrcVar = llvm::cast<Variable>(Src); |
- assert(SrcVar->hasReg()); |
- (Asm->*(Emitter.AddrXmm))(StackAddr, |
- RegX8632::getEncodedXmm(SrcVar->getRegNum())); |
- } |
-} |
- |
-// In-place ops |
-template <> const char *InstX8632Bswap::Opcode = "bswap"; |
-template <> const char *InstX8632Neg::Opcode = "neg"; |
-// Unary ops |
-template <> const char *InstX8632Bsf::Opcode = "bsf"; |
-template <> const char *InstX8632Bsr::Opcode = "bsr"; |
-template <> const char *InstX8632Lea::Opcode = "lea"; |
-template <> const char *InstX8632Movd::Opcode = "movd"; |
-template <> const char *InstX8632Movsx::Opcode = "movs"; |
-template <> const char *InstX8632Movzx::Opcode = "movz"; |
-template <> const char *InstX8632Sqrtss::Opcode = "sqrtss"; |
-template <> const char *InstX8632Cbwdq::Opcode = "cbw/cwd/cdq"; |
-// Mov-like ops |
-template <> const char *InstX8632Mov::Opcode = "mov"; |
-template <> const char *InstX8632Movp::Opcode = "movups"; |
-template <> const char *InstX8632Movq::Opcode = "movq"; |
-// Binary ops |
-template <> const char *InstX8632Add::Opcode = "add"; |
-template <> const char *InstX8632AddRMW::Opcode = "add"; |
-template <> const char *InstX8632Addps::Opcode = "addps"; |
-template <> const char *InstX8632Adc::Opcode = "adc"; |
-template <> const char *InstX8632AdcRMW::Opcode = "adc"; |
-template <> const char *InstX8632Addss::Opcode = "addss"; |
-template <> const char *InstX8632Padd::Opcode = "padd"; |
-template <> const char *InstX8632Sub::Opcode = "sub"; |
-template <> const char *InstX8632SubRMW::Opcode = "sub"; |
-template <> const char *InstX8632Subps::Opcode = "subps"; |
-template <> const char *InstX8632Subss::Opcode = "subss"; |
-template <> const char *InstX8632Sbb::Opcode = "sbb"; |
-template <> const char *InstX8632SbbRMW::Opcode = "sbb"; |
-template <> const char *InstX8632Psub::Opcode = "psub"; |
-template <> const char *InstX8632And::Opcode = "and"; |
-template <> const char *InstX8632AndRMW::Opcode = "and"; |
-template <> const char *InstX8632Pand::Opcode = "pand"; |
-template <> const char *InstX8632Pandn::Opcode = "pandn"; |
-template <> const char *InstX8632Or::Opcode = "or"; |
-template <> const char *InstX8632OrRMW::Opcode = "or"; |
-template <> const char *InstX8632Por::Opcode = "por"; |
-template <> const char *InstX8632Xor::Opcode = "xor"; |
-template <> const char *InstX8632XorRMW::Opcode = "xor"; |
-template <> const char *InstX8632Pxor::Opcode = "pxor"; |
-template <> const char *InstX8632Imul::Opcode = "imul"; |
-template <> const char *InstX8632Mulps::Opcode = "mulps"; |
-template <> const char *InstX8632Mulss::Opcode = "mulss"; |
-template <> const char *InstX8632Pmull::Opcode = "pmull"; |
-template <> const char *InstX8632Pmuludq::Opcode = "pmuludq"; |
-template <> const char *InstX8632Div::Opcode = "div"; |
-template <> const char *InstX8632Divps::Opcode = "divps"; |
-template <> const char *InstX8632Idiv::Opcode = "idiv"; |
-template <> const char *InstX8632Divss::Opcode = "divss"; |
-template <> const char *InstX8632Rol::Opcode = "rol"; |
-template <> const char *InstX8632Shl::Opcode = "shl"; |
-template <> const char *InstX8632Psll::Opcode = "psll"; |
-template <> const char *InstX8632Shr::Opcode = "shr"; |
-template <> const char *InstX8632Sar::Opcode = "sar"; |
-template <> const char *InstX8632Psra::Opcode = "psra"; |
-template <> const char *InstX8632Psrl::Opcode = "psrl"; |
-template <> const char *InstX8632Pcmpeq::Opcode = "pcmpeq"; |
-template <> const char *InstX8632Pcmpgt::Opcode = "pcmpgt"; |
-template <> const char *InstX8632MovssRegs::Opcode = "movss"; |
-// Ternary ops |
-template <> const char *InstX8632Insertps::Opcode = "insertps"; |
-template <> const char *InstX8632Shufps::Opcode = "shufps"; |
-template <> const char *InstX8632Pinsr::Opcode = "pinsr"; |
-template <> const char *InstX8632Blendvps::Opcode = "blendvps"; |
-template <> const char *InstX8632Pblendvb::Opcode = "pblendvb"; |
-// Three address ops |
-template <> const char *InstX8632Pextr::Opcode = "pextr"; |
-template <> const char *InstX8632Pshufd::Opcode = "pshufd"; |
- |
-// Inplace GPR ops |
-template <> |
-const X8632::AssemblerX8632::GPREmitterOneOp InstX8632Bswap::Emitter = { |
- &X8632::AssemblerX8632::bswap, nullptr /* only a reg form exists */ |
-}; |
-template <> |
-const X8632::AssemblerX8632::GPREmitterOneOp InstX8632Neg::Emitter = { |
- &X8632::AssemblerX8632::neg, &X8632::AssemblerX8632::neg}; |
- |
-// Unary GPR ops |
-template <> |
-const X8632::AssemblerX8632::GPREmitterRegOp InstX8632Bsf::Emitter = { |
- &X8632::AssemblerX8632::bsf, &X8632::AssemblerX8632::bsf, nullptr}; |
-template <> |
-const X8632::AssemblerX8632::GPREmitterRegOp InstX8632Bsr::Emitter = { |
- &X8632::AssemblerX8632::bsr, &X8632::AssemblerX8632::bsr, nullptr}; |
-template <> |
-const X8632::AssemblerX8632::GPREmitterRegOp InstX8632Lea::Emitter = { |
- /* reg/reg and reg/imm are illegal */ nullptr, &X8632::AssemblerX8632::lea, |
- nullptr}; |
-template <> |
-const X8632::AssemblerX8632::GPREmitterRegOp InstX8632Movsx::Emitter = { |
- &X8632::AssemblerX8632::movsx, &X8632::AssemblerX8632::movsx, nullptr}; |
-template <> |
-const X8632::AssemblerX8632::GPREmitterRegOp InstX8632Movzx::Emitter = { |
- &X8632::AssemblerX8632::movzx, &X8632::AssemblerX8632::movzx, nullptr}; |
- |
-// Unary XMM ops |
-template <> |
-const X8632::AssemblerX8632::XmmEmitterRegOp InstX8632Sqrtss::Emitter = { |
- &X8632::AssemblerX8632::sqrtss, &X8632::AssemblerX8632::sqrtss}; |
- |
-// Binary GPR ops |
-template <> |
-const X8632::AssemblerX8632::GPREmitterRegOp InstX8632Add::Emitter = { |
- &X8632::AssemblerX8632::add, &X8632::AssemblerX8632::add, |
- &X8632::AssemblerX8632::add}; |
-template <> |
-const X8632::AssemblerX8632::GPREmitterAddrOp InstX8632AddRMW::Emitter = { |
- &X8632::AssemblerX8632::add, &X8632::AssemblerX8632::add}; |
-template <> |
-const X8632::AssemblerX8632::GPREmitterRegOp InstX8632Adc::Emitter = { |
- &X8632::AssemblerX8632::adc, &X8632::AssemblerX8632::adc, |
- &X8632::AssemblerX8632::adc}; |
-template <> |
-const X8632::AssemblerX8632::GPREmitterAddrOp InstX8632AdcRMW::Emitter = { |
- &X8632::AssemblerX8632::adc, &X8632::AssemblerX8632::adc}; |
-template <> |
-const X8632::AssemblerX8632::GPREmitterRegOp InstX8632And::Emitter = { |
- &X8632::AssemblerX8632::And, &X8632::AssemblerX8632::And, |
- &X8632::AssemblerX8632::And}; |
-template <> |
-const X8632::AssemblerX8632::GPREmitterAddrOp InstX8632AndRMW::Emitter = { |
- &X8632::AssemblerX8632::And, &X8632::AssemblerX8632::And}; |
-template <> |
-const X8632::AssemblerX8632::GPREmitterRegOp InstX8632Or::Emitter = { |
- &X8632::AssemblerX8632::Or, &X8632::AssemblerX8632::Or, |
- &X8632::AssemblerX8632::Or}; |
-template <> |
-const X8632::AssemblerX8632::GPREmitterAddrOp InstX8632OrRMW::Emitter = { |
- &X8632::AssemblerX8632::Or, &X8632::AssemblerX8632::Or}; |
-template <> |
-const X8632::AssemblerX8632::GPREmitterRegOp InstX8632Sbb::Emitter = { |
- &X8632::AssemblerX8632::sbb, &X8632::AssemblerX8632::sbb, |
- &X8632::AssemblerX8632::sbb}; |
-template <> |
-const X8632::AssemblerX8632::GPREmitterAddrOp InstX8632SbbRMW::Emitter = { |
- &X8632::AssemblerX8632::sbb, &X8632::AssemblerX8632::sbb}; |
-template <> |
-const X8632::AssemblerX8632::GPREmitterRegOp InstX8632Sub::Emitter = { |
- &X8632::AssemblerX8632::sub, &X8632::AssemblerX8632::sub, |
- &X8632::AssemblerX8632::sub}; |
-template <> |
-const X8632::AssemblerX8632::GPREmitterAddrOp InstX8632SubRMW::Emitter = { |
- &X8632::AssemblerX8632::sub, &X8632::AssemblerX8632::sub}; |
-template <> |
-const X8632::AssemblerX8632::GPREmitterRegOp InstX8632Xor::Emitter = { |
- &X8632::AssemblerX8632::Xor, &X8632::AssemblerX8632::Xor, |
- &X8632::AssemblerX8632::Xor}; |
-template <> |
-const X8632::AssemblerX8632::GPREmitterAddrOp InstX8632XorRMW::Emitter = { |
- &X8632::AssemblerX8632::Xor, &X8632::AssemblerX8632::Xor}; |
- |
-// Binary Shift GPR ops |
-template <> |
-const X8632::AssemblerX8632::GPREmitterShiftOp InstX8632Rol::Emitter = { |
- &X8632::AssemblerX8632::rol, &X8632::AssemblerX8632::rol}; |
-template <> |
-const X8632::AssemblerX8632::GPREmitterShiftOp InstX8632Sar::Emitter = { |
- &X8632::AssemblerX8632::sar, &X8632::AssemblerX8632::sar}; |
-template <> |
-const X8632::AssemblerX8632::GPREmitterShiftOp InstX8632Shl::Emitter = { |
- &X8632::AssemblerX8632::shl, &X8632::AssemblerX8632::shl}; |
-template <> |
-const X8632::AssemblerX8632::GPREmitterShiftOp InstX8632Shr::Emitter = { |
- &X8632::AssemblerX8632::shr, &X8632::AssemblerX8632::shr}; |
- |
-// Binary XMM ops |
-template <> |
-const X8632::AssemblerX8632::XmmEmitterRegOp InstX8632Addss::Emitter = { |
- &X8632::AssemblerX8632::addss, &X8632::AssemblerX8632::addss}; |
-template <> |
-const X8632::AssemblerX8632::XmmEmitterRegOp InstX8632Addps::Emitter = { |
- &X8632::AssemblerX8632::addps, &X8632::AssemblerX8632::addps}; |
-template <> |
-const X8632::AssemblerX8632::XmmEmitterRegOp InstX8632Divss::Emitter = { |
- &X8632::AssemblerX8632::divss, &X8632::AssemblerX8632::divss}; |
-template <> |
-const X8632::AssemblerX8632::XmmEmitterRegOp InstX8632Divps::Emitter = { |
- &X8632::AssemblerX8632::divps, &X8632::AssemblerX8632::divps}; |
-template <> |
-const X8632::AssemblerX8632::XmmEmitterRegOp InstX8632Mulss::Emitter = { |
- &X8632::AssemblerX8632::mulss, &X8632::AssemblerX8632::mulss}; |
-template <> |
-const X8632::AssemblerX8632::XmmEmitterRegOp InstX8632Mulps::Emitter = { |
- &X8632::AssemblerX8632::mulps, &X8632::AssemblerX8632::mulps}; |
-template <> |
-const X8632::AssemblerX8632::XmmEmitterRegOp InstX8632Padd::Emitter = { |
- &X8632::AssemblerX8632::padd, &X8632::AssemblerX8632::padd}; |
-template <> |
-const X8632::AssemblerX8632::XmmEmitterRegOp InstX8632Pand::Emitter = { |
- &X8632::AssemblerX8632::pand, &X8632::AssemblerX8632::pand}; |
-template <> |
-const X8632::AssemblerX8632::XmmEmitterRegOp InstX8632Pandn::Emitter = { |
- &X8632::AssemblerX8632::pandn, &X8632::AssemblerX8632::pandn}; |
-template <> |
-const X8632::AssemblerX8632::XmmEmitterRegOp InstX8632Pcmpeq::Emitter = { |
- &X8632::AssemblerX8632::pcmpeq, &X8632::AssemblerX8632::pcmpeq}; |
-template <> |
-const X8632::AssemblerX8632::XmmEmitterRegOp InstX8632Pcmpgt::Emitter = { |
- &X8632::AssemblerX8632::pcmpgt, &X8632::AssemblerX8632::pcmpgt}; |
-template <> |
-const X8632::AssemblerX8632::XmmEmitterRegOp InstX8632Pmull::Emitter = { |
- &X8632::AssemblerX8632::pmull, &X8632::AssemblerX8632::pmull}; |
-template <> |
-const X8632::AssemblerX8632::XmmEmitterRegOp InstX8632Pmuludq::Emitter = { |
- &X8632::AssemblerX8632::pmuludq, &X8632::AssemblerX8632::pmuludq}; |
-template <> |
-const X8632::AssemblerX8632::XmmEmitterRegOp InstX8632Por::Emitter = { |
- &X8632::AssemblerX8632::por, &X8632::AssemblerX8632::por}; |
-template <> |
-const X8632::AssemblerX8632::XmmEmitterRegOp InstX8632Psub::Emitter = { |
- &X8632::AssemblerX8632::psub, &X8632::AssemblerX8632::psub}; |
-template <> |
-const X8632::AssemblerX8632::XmmEmitterRegOp InstX8632Pxor::Emitter = { |
- &X8632::AssemblerX8632::pxor, &X8632::AssemblerX8632::pxor}; |
-template <> |
-const X8632::AssemblerX8632::XmmEmitterRegOp InstX8632Subss::Emitter = { |
- &X8632::AssemblerX8632::subss, &X8632::AssemblerX8632::subss}; |
-template <> |
-const X8632::AssemblerX8632::XmmEmitterRegOp InstX8632Subps::Emitter = { |
- &X8632::AssemblerX8632::subps, &X8632::AssemblerX8632::subps}; |
- |
-// Binary XMM Shift ops |
-template <> |
-const X8632::AssemblerX8632::XmmEmitterShiftOp InstX8632Psll::Emitter = { |
- &X8632::AssemblerX8632::psll, &X8632::AssemblerX8632::psll, |
- &X8632::AssemblerX8632::psll}; |
-template <> |
-const X8632::AssemblerX8632::XmmEmitterShiftOp InstX8632Psra::Emitter = { |
- &X8632::AssemblerX8632::psra, &X8632::AssemblerX8632::psra, |
- &X8632::AssemblerX8632::psra}; |
-template <> |
-const X8632::AssemblerX8632::XmmEmitterShiftOp InstX8632Psrl::Emitter = { |
- &X8632::AssemblerX8632::psrl, &X8632::AssemblerX8632::psrl, |
- &X8632::AssemblerX8632::psrl}; |
- |
-template <> void InstX8632Sqrtss::emit(const Cfg *Func) const { |
- if (!BuildDefs::dump()) |
- return; |
- Ostream &Str = Func->getContext()->getStrEmit(); |
- assert(getSrcSize() == 1); |
- Type Ty = getSrc(0)->getType(); |
- assert(isScalarFloatingType(Ty)); |
- Str << "\tsqrt" << TypeX8632Attributes[Ty].SdSsString << "\t"; |
- getSrc(0)->emit(Func); |
- Str << ", "; |
- getDest()->emit(Func); |
-} |
- |
-template <> void InstX8632Addss::emit(const Cfg *Func) const { |
- if (!BuildDefs::dump()) |
- return; |
- char buf[30]; |
- snprintf(buf, llvm::array_lengthof(buf), "add%s", |
- TypeX8632Attributes[getDest()->getType()].SdSsString); |
- emitTwoAddress(buf, this, Func); |
-} |
- |
-template <> void InstX8632Padd::emit(const Cfg *Func) const { |
- if (!BuildDefs::dump()) |
- return; |
- char buf[30]; |
- snprintf(buf, llvm::array_lengthof(buf), "padd%s", |
- TypeX8632Attributes[getDest()->getType()].PackString); |
- emitTwoAddress(buf, this, Func); |
-} |
- |
-template <> void InstX8632Pmull::emit(const Cfg *Func) const { |
- if (!BuildDefs::dump()) |
- return; |
- char buf[30]; |
- bool TypesAreValid = getDest()->getType() == IceType_v4i32 || |
- getDest()->getType() == IceType_v8i16; |
- bool InstructionSetIsValid = |
- getDest()->getType() == IceType_v8i16 || |
- static_cast<TargetX8632 *>(Func->getTarget())->getInstructionSet() >= |
- X8632::Traits::SSE4_1; |
- (void)TypesAreValid; |
- (void)InstructionSetIsValid; |
- assert(TypesAreValid); |
- assert(InstructionSetIsValid); |
- snprintf(buf, llvm::array_lengthof(buf), "pmull%s", |
- TypeX8632Attributes[getDest()->getType()].PackString); |
- emitTwoAddress(buf, this, Func); |
-} |
- |
-template <> void InstX8632Pmull::emitIAS(const Cfg *Func) const { |
- Type Ty = getDest()->getType(); |
- bool TypesAreValid = Ty == IceType_v4i32 || Ty == IceType_v8i16; |
- bool InstructionSetIsValid = |
- Ty == IceType_v8i16 || |
- static_cast<TargetX8632 *>(Func->getTarget())->getInstructionSet() >= |
- X8632::Traits::SSE4_1; |
- (void)TypesAreValid; |
- (void)InstructionSetIsValid; |
- assert(TypesAreValid); |
- assert(InstructionSetIsValid); |
- assert(getSrcSize() == 2); |
- Type ElementTy = typeElementType(Ty); |
- emitIASRegOpTyXMM(Func, ElementTy, getDest(), getSrc(1), Emitter); |
-} |
- |
-template <> void InstX8632Subss::emit(const Cfg *Func) const { |
- if (!BuildDefs::dump()) |
- return; |
- char buf[30]; |
- snprintf(buf, llvm::array_lengthof(buf), "sub%s", |
- TypeX8632Attributes[getDest()->getType()].SdSsString); |
- emitTwoAddress(buf, this, Func); |
-} |
- |
-template <> void InstX8632Psub::emit(const Cfg *Func) const { |
- if (!BuildDefs::dump()) |
- return; |
- char buf[30]; |
- snprintf(buf, llvm::array_lengthof(buf), "psub%s", |
- TypeX8632Attributes[getDest()->getType()].PackString); |
- emitTwoAddress(buf, this, Func); |
-} |
- |
-template <> void InstX8632Mulss::emit(const Cfg *Func) const { |
- if (!BuildDefs::dump()) |
- return; |
- char buf[30]; |
- snprintf(buf, llvm::array_lengthof(buf), "mul%s", |
- TypeX8632Attributes[getDest()->getType()].SdSsString); |
- emitTwoAddress(buf, this, Func); |
-} |
- |
-template <> void InstX8632Pmuludq::emit(const Cfg *Func) const { |
- if (!BuildDefs::dump()) |
- return; |
- assert(getSrc(0)->getType() == IceType_v4i32 && |
- getSrc(1)->getType() == IceType_v4i32); |
- emitTwoAddress(Opcode, this, Func); |
-} |
- |
-template <> void InstX8632Divss::emit(const Cfg *Func) const { |
- if (!BuildDefs::dump()) |
- return; |
- char buf[30]; |
- snprintf(buf, llvm::array_lengthof(buf), "div%s", |
- TypeX8632Attributes[getDest()->getType()].SdSsString); |
- emitTwoAddress(buf, this, Func); |
-} |
- |
-template <> void InstX8632Div::emit(const Cfg *Func) const { |
- if (!BuildDefs::dump()) |
- return; |
- Ostream &Str = Func->getContext()->getStrEmit(); |
- assert(getSrcSize() == 3); |
- Operand *Src1 = getSrc(1); |
- Str << "\t" << Opcode << getWidthString(Src1->getType()) << "\t"; |
- Src1->emit(Func); |
-} |
- |
-template <> void InstX8632Div::emitIAS(const Cfg *Func) const { |
- assert(getSrcSize() == 3); |
- const Operand *Src = getSrc(1); |
- Type Ty = Src->getType(); |
- const static X8632::AssemblerX8632::GPREmitterOneOp Emitter = { |
- &X8632::AssemblerX8632::div, &X8632::AssemblerX8632::div}; |
- emitIASOpTyGPR(Func, Ty, Src, Emitter); |
-} |
- |
-template <> void InstX8632Idiv::emit(const Cfg *Func) const { |
- if (!BuildDefs::dump()) |
- return; |
- Ostream &Str = Func->getContext()->getStrEmit(); |
- assert(getSrcSize() == 3); |
- Operand *Src1 = getSrc(1); |
- Str << "\t" << Opcode << getWidthString(Src1->getType()) << "\t"; |
- Src1->emit(Func); |
-} |
- |
-template <> void InstX8632Idiv::emitIAS(const Cfg *Func) const { |
- assert(getSrcSize() == 3); |
- const Operand *Src = getSrc(1); |
- Type Ty = Src->getType(); |
- const static X8632::AssemblerX8632::GPREmitterOneOp Emitter = { |
- &X8632::AssemblerX8632::idiv, &X8632::AssemblerX8632::idiv}; |
- emitIASOpTyGPR(Func, Ty, Src, Emitter); |
-} |
- |
-namespace { |
- |
-// pblendvb and blendvps take xmm0 as a final implicit argument. |
-void emitVariableBlendInst(const char *Opcode, const Inst *Inst, |
- const Cfg *Func) { |
- if (!BuildDefs::dump()) |
- return; |
- Ostream &Str = Func->getContext()->getStrEmit(); |
- assert(Inst->getSrcSize() == 3); |
- assert(llvm::cast<Variable>(Inst->getSrc(2))->getRegNum() == |
- RegX8632::Reg_xmm0); |
- Str << "\t" << Opcode << "\t"; |
- Inst->getSrc(1)->emit(Func); |
- Str << ", "; |
- Inst->getDest()->emit(Func); |
-} |
- |
-void emitIASVariableBlendInst( |
- const Inst *Inst, const Cfg *Func, |
- const X8632::AssemblerX8632::XmmEmitterRegOp &Emitter) { |
- assert(Inst->getSrcSize() == 3); |
- assert(llvm::cast<Variable>(Inst->getSrc(2))->getRegNum() == |
- RegX8632::Reg_xmm0); |
- const Variable *Dest = Inst->getDest(); |
- const Operand *Src = Inst->getSrc(1); |
- emitIASRegOpTyXMM(Func, Dest->getType(), Dest, Src, Emitter); |
-} |
- |
-} // end anonymous namespace |
- |
-template <> void InstX8632Blendvps::emit(const Cfg *Func) const { |
- if (!BuildDefs::dump()) |
- return; |
- assert(static_cast<TargetX8632 *>(Func->getTarget())->getInstructionSet() >= |
- X8632::Traits::SSE4_1); |
- emitVariableBlendInst(Opcode, this, Func); |
-} |
- |
-template <> void InstX8632Blendvps::emitIAS(const Cfg *Func) const { |
- assert(static_cast<TargetX8632 *>(Func->getTarget())->getInstructionSet() >= |
- X8632::Traits::SSE4_1); |
- static const X8632::AssemblerX8632::XmmEmitterRegOp Emitter = { |
- &X8632::AssemblerX8632::blendvps, &X8632::AssemblerX8632::blendvps}; |
- emitIASVariableBlendInst(this, Func, Emitter); |
-} |
- |
-template <> void InstX8632Pblendvb::emit(const Cfg *Func) const { |
- if (!BuildDefs::dump()) |
- return; |
- assert(static_cast<TargetX8632 *>(Func->getTarget())->getInstructionSet() >= |
- X8632::Traits::SSE4_1); |
- emitVariableBlendInst(Opcode, this, Func); |
-} |
- |
-template <> void InstX8632Pblendvb::emitIAS(const Cfg *Func) const { |
- assert(static_cast<TargetX8632 *>(Func->getTarget())->getInstructionSet() >= |
- X8632::Traits::SSE4_1); |
- static const X8632::AssemblerX8632::XmmEmitterRegOp Emitter = { |
- &X8632::AssemblerX8632::pblendvb, &X8632::AssemblerX8632::pblendvb}; |
- emitIASVariableBlendInst(this, Func, Emitter); |
-} |
- |
-template <> void InstX8632Imul::emit(const Cfg *Func) const { |
- if (!BuildDefs::dump()) |
- return; |
- Ostream &Str = Func->getContext()->getStrEmit(); |
- assert(getSrcSize() == 2); |
- Variable *Dest = getDest(); |
- if (isByteSizedArithType(Dest->getType())) { |
- // The 8-bit version of imul only allows the form "imul r/m8". |
- const auto Src0Var = llvm::dyn_cast<Variable>(getSrc(0)); |
- (void)Src0Var; |
- assert(Src0Var && Src0Var->getRegNum() == RegX8632::Reg_eax); |
- Str << "\timulb\t"; |
- getSrc(1)->emit(Func); |
- } else if (llvm::isa<Constant>(getSrc(1))) { |
- Str << "\timul" << getWidthString(Dest->getType()) << "\t"; |
- getSrc(1)->emit(Func); |
- Str << ", "; |
- getSrc(0)->emit(Func); |
- Str << ", "; |
- Dest->emit(Func); |
- } else { |
- emitTwoAddress("imul", this, Func); |
- } |
-} |
- |
-template <> void InstX8632Imul::emitIAS(const Cfg *Func) const { |
- assert(getSrcSize() == 2); |
- const Variable *Var = getDest(); |
- Type Ty = Var->getType(); |
- const Operand *Src = getSrc(1); |
- if (isByteSizedArithType(Ty)) { |
- // The 8-bit version of imul only allows the form "imul r/m8". |
- const auto Src0Var = llvm::dyn_cast<Variable>(getSrc(0)); |
- (void)Src0Var; |
- assert(Src0Var && Src0Var->getRegNum() == RegX8632::Reg_eax); |
- const X8632::AssemblerX8632::GPREmitterOneOp Emitter = { |
- &X8632::AssemblerX8632::imul, &X8632::AssemblerX8632::imul}; |
- emitIASOpTyGPR(Func, Ty, getSrc(1), Emitter); |
- } else { |
- // We only use imul as a two-address instruction even though |
- // there is a 3 operand version when one of the operands is a constant. |
- assert(Var == getSrc(0)); |
- const X8632::AssemblerX8632::GPREmitterRegOp Emitter = { |
- &X8632::AssemblerX8632::imul, &X8632::AssemblerX8632::imul, |
- &X8632::AssemblerX8632::imul}; |
- emitIASRegOpTyGPR(Func, Ty, Var, Src, Emitter); |
- } |
-} |
- |
-template <> void InstX8632Insertps::emitIAS(const Cfg *Func) const { |
- assert(getSrcSize() == 3); |
- assert(static_cast<TargetX8632 *>(Func->getTarget())->getInstructionSet() >= |
- X8632::Traits::SSE4_1); |
- const Variable *Dest = getDest(); |
- assert(Dest == getSrc(0)); |
- Type Ty = Dest->getType(); |
- static const X8632::AssemblerX8632::ThreeOpImmEmitter< |
- RegX8632::XmmRegister, RegX8632::XmmRegister> Emitter = { |
- &X8632::AssemblerX8632::insertps, &X8632::AssemblerX8632::insertps}; |
- emitIASThreeOpImmOps<RegX8632::XmmRegister, RegX8632::XmmRegister, |
- RegX8632::getEncodedXmm, RegX8632::getEncodedXmm>( |
- Func, Ty, Dest, getSrc(1), getSrc(2), Emitter); |
-} |
- |
-template <> void InstX8632Cbwdq::emit(const Cfg *Func) const { |
- if (!BuildDefs::dump()) |
- return; |
- Ostream &Str = Func->getContext()->getStrEmit(); |
- assert(getSrcSize() == 1); |
- Operand *Src0 = getSrc(0); |
- assert(llvm::isa<Variable>(Src0)); |
- assert(llvm::cast<Variable>(Src0)->getRegNum() == RegX8632::Reg_eax); |
- switch (Src0->getType()) { |
- default: |
- llvm_unreachable("unexpected source type!"); |
- break; |
- case IceType_i8: |
- assert(getDest()->getRegNum() == RegX8632::Reg_eax); |
- Str << "\tcbtw"; |
- break; |
- case IceType_i16: |
- assert(getDest()->getRegNum() == RegX8632::Reg_edx); |
- Str << "\tcwtd"; |
- break; |
- case IceType_i32: |
- assert(getDest()->getRegNum() == RegX8632::Reg_edx); |
- Str << "\tcltd"; |
- break; |
- } |
-} |
- |
-template <> void InstX8632Cbwdq::emitIAS(const Cfg *Func) const { |
- X8632::AssemblerX8632 *Asm = Func->getAssembler<X8632::AssemblerX8632>(); |
- assert(getSrcSize() == 1); |
- Operand *Src0 = getSrc(0); |
- assert(llvm::isa<Variable>(Src0)); |
- assert(llvm::cast<Variable>(Src0)->getRegNum() == RegX8632::Reg_eax); |
- switch (Src0->getType()) { |
- default: |
- llvm_unreachable("unexpected source type!"); |
- break; |
- case IceType_i8: |
- assert(getDest()->getRegNum() == RegX8632::Reg_eax); |
- Asm->cbw(); |
- break; |
- case IceType_i16: |
- assert(getDest()->getRegNum() == RegX8632::Reg_edx); |
- Asm->cwd(); |
- break; |
- case IceType_i32: |
- assert(getDest()->getRegNum() == RegX8632::Reg_edx); |
- Asm->cdq(); |
- break; |
- } |
-} |
- |
-void InstX8632Mul::emit(const Cfg *Func) const { |
- if (!BuildDefs::dump()) |
- return; |
- Ostream &Str = Func->getContext()->getStrEmit(); |
- assert(getSrcSize() == 2); |
- assert(llvm::isa<Variable>(getSrc(0))); |
- assert(llvm::cast<Variable>(getSrc(0))->getRegNum() == RegX8632::Reg_eax); |
- assert(getDest()->getRegNum() == RegX8632::Reg_eax); // TODO: allow edx? |
- Str << "\tmul" << getWidthString(getDest()->getType()) << "\t"; |
- getSrc(1)->emit(Func); |
-} |
- |
-void InstX8632Mul::emitIAS(const Cfg *Func) const { |
- assert(getSrcSize() == 2); |
- assert(llvm::isa<Variable>(getSrc(0))); |
- assert(llvm::cast<Variable>(getSrc(0))->getRegNum() == RegX8632::Reg_eax); |
- assert(getDest()->getRegNum() == RegX8632::Reg_eax); // TODO: allow edx? |
- const Operand *Src = getSrc(1); |
- Type Ty = Src->getType(); |
- const static X8632::AssemblerX8632::GPREmitterOneOp Emitter = { |
- &X8632::AssemblerX8632::mul, &X8632::AssemblerX8632::mul}; |
- emitIASOpTyGPR(Func, Ty, Src, Emitter); |
-} |
- |
-void InstX8632Mul::dump(const Cfg *Func) const { |
- if (!BuildDefs::dump()) |
- return; |
- Ostream &Str = Func->getContext()->getStrDump(); |
- dumpDest(Func); |
- Str << " = mul." << getDest()->getType() << " "; |
- dumpSources(Func); |
-} |
- |
-void InstX8632Shld::emit(const Cfg *Func) const { |
- if (!BuildDefs::dump()) |
- return; |
- Ostream &Str = Func->getContext()->getStrEmit(); |
- Variable *Dest = getDest(); |
- assert(getSrcSize() == 3); |
- assert(Dest == getSrc(0)); |
- Str << "\tshld" << getWidthString(Dest->getType()) << "\t"; |
- if (const auto ShiftReg = llvm::dyn_cast<Variable>(getSrc(2))) { |
- (void)ShiftReg; |
- assert(ShiftReg->getRegNum() == RegX8632::Reg_ecx); |
- Str << "%cl"; |
- } else { |
- getSrc(2)->emit(Func); |
- } |
- Str << ", "; |
- getSrc(1)->emit(Func); |
- Str << ", "; |
- Dest->emit(Func); |
-} |
- |
-void InstX8632Shld::emitIAS(const Cfg *Func) const { |
- assert(getSrcSize() == 3); |
- assert(getDest() == getSrc(0)); |
- const Variable *Dest = getDest(); |
- const Operand *Src1 = getSrc(1); |
- const Operand *Src2 = getSrc(2); |
- static const X8632::AssemblerX8632::GPREmitterShiftD Emitter = { |
- &X8632::AssemblerX8632::shld, &X8632::AssemblerX8632::shld}; |
- emitIASGPRShiftDouble(Func, Dest, Src1, Src2, Emitter); |
-} |
- |
-void InstX8632Shld::dump(const Cfg *Func) const { |
- if (!BuildDefs::dump()) |
- return; |
- Ostream &Str = Func->getContext()->getStrDump(); |
- dumpDest(Func); |
- Str << " = shld." << getDest()->getType() << " "; |
- dumpSources(Func); |
-} |
- |
-void InstX8632Shrd::emit(const Cfg *Func) const { |
- if (!BuildDefs::dump()) |
- return; |
- Ostream &Str = Func->getContext()->getStrEmit(); |
- Variable *Dest = getDest(); |
- assert(getSrcSize() == 3); |
- assert(Dest == getSrc(0)); |
- Str << "\tshrd" << getWidthString(Dest->getType()) << "\t"; |
- if (const auto ShiftReg = llvm::dyn_cast<Variable>(getSrc(2))) { |
- (void)ShiftReg; |
- assert(ShiftReg->getRegNum() == RegX8632::Reg_ecx); |
- Str << "%cl"; |
- } else { |
- getSrc(2)->emit(Func); |
- } |
- Str << ", "; |
- getSrc(1)->emit(Func); |
- Str << ", "; |
- Dest->emit(Func); |
-} |
- |
-void InstX8632Shrd::emitIAS(const Cfg *Func) const { |
- assert(getSrcSize() == 3); |
- assert(getDest() == getSrc(0)); |
- const Variable *Dest = getDest(); |
- const Operand *Src1 = getSrc(1); |
- const Operand *Src2 = getSrc(2); |
- static const X8632::AssemblerX8632::GPREmitterShiftD Emitter = { |
- &X8632::AssemblerX8632::shrd, &X8632::AssemblerX8632::shrd}; |
- emitIASGPRShiftDouble(Func, Dest, Src1, Src2, Emitter); |
-} |
- |
-void InstX8632Shrd::dump(const Cfg *Func) const { |
- if (!BuildDefs::dump()) |
- return; |
- Ostream &Str = Func->getContext()->getStrDump(); |
- dumpDest(Func); |
- Str << " = shrd." << getDest()->getType() << " "; |
- dumpSources(Func); |
-} |
- |
-void InstX8632Cmov::emit(const Cfg *Func) const { |
- if (!BuildDefs::dump()) |
- return; |
- Ostream &Str = Func->getContext()->getStrEmit(); |
- Variable *Dest = getDest(); |
- Str << "\t"; |
- assert(Condition != X8632::Traits::Cond::Br_None); |
- assert(getDest()->hasReg()); |
- Str << "cmov" << InstX8632BrAttributes[Condition].DisplayString |
- << getWidthString(Dest->getType()) << "\t"; |
- getSrc(1)->emit(Func); |
- Str << ", "; |
- Dest->emit(Func); |
-} |
- |
-void InstX8632Cmov::emitIAS(const Cfg *Func) const { |
- assert(Condition != X8632::Traits::Cond::Br_None); |
- assert(getDest()->hasReg()); |
- assert(getSrcSize() == 2); |
- Operand *Src = getSrc(1); |
- Type SrcTy = Src->getType(); |
- assert(SrcTy == IceType_i16 || SrcTy == IceType_i32); |
- X8632::AssemblerX8632 *Asm = Func->getAssembler<X8632::AssemblerX8632>(); |
- if (const auto *SrcVar = llvm::dyn_cast<Variable>(Src)) { |
- if (SrcVar->hasReg()) { |
- Asm->cmov(SrcTy, Condition, |
- RegX8632::getEncodedGPR(getDest()->getRegNum()), |
- RegX8632::getEncodedGPR(SrcVar->getRegNum())); |
- } else { |
- Asm->cmov(SrcTy, Condition, |
- RegX8632::getEncodedGPR(getDest()->getRegNum()), |
- static_cast<TargetX8632 *>(Func->getTarget()) |
- ->stackVarToAsmOperand(SrcVar)); |
- } |
- } else if (const auto Mem = llvm::dyn_cast<OperandX8632Mem>(Src)) { |
- assert(Mem->getSegmentRegister() == OperandX8632Mem::DefaultSegment); |
- Asm->cmov(SrcTy, Condition, RegX8632::getEncodedGPR(getDest()->getRegNum()), |
- Mem->toAsmAddress(Asm)); |
- } else { |
- llvm_unreachable("Unexpected operand type"); |
- } |
-} |
- |
-void InstX8632Cmov::dump(const Cfg *Func) const { |
- if (!BuildDefs::dump()) |
- return; |
- Ostream &Str = Func->getContext()->getStrDump(); |
- Str << "cmov" << InstX8632BrAttributes[Condition].DisplayString << "."; |
- Str << getDest()->getType() << " "; |
- dumpDest(Func); |
- Str << ", "; |
- dumpSources(Func); |
-} |
- |
-void InstX8632Cmpps::emit(const Cfg *Func) const { |
- if (!BuildDefs::dump()) |
- return; |
- Ostream &Str = Func->getContext()->getStrEmit(); |
- assert(getSrcSize() == 2); |
- assert(Condition < X8632::Traits::Cond::Cmpps_Invalid); |
- Str << "\t"; |
- Str << "cmp" << InstX8632CmppsAttributes[Condition].EmitString << "ps" |
- << "\t"; |
- getSrc(1)->emit(Func); |
- Str << ", "; |
- getDest()->emit(Func); |
-} |
- |
-void InstX8632Cmpps::emitIAS(const Cfg *Func) const { |
- X8632::AssemblerX8632 *Asm = Func->getAssembler<X8632::AssemblerX8632>(); |
- assert(getSrcSize() == 2); |
- assert(Condition < X8632::Traits::Cond::Cmpps_Invalid); |
- // Assuming there isn't any load folding for cmpps, and vector constants |
- // are not allowed in PNaCl. |
- assert(llvm::isa<Variable>(getSrc(1))); |
- const auto SrcVar = llvm::cast<Variable>(getSrc(1)); |
- if (SrcVar->hasReg()) { |
- Asm->cmpps(RegX8632::getEncodedXmm(getDest()->getRegNum()), |
- RegX8632::getEncodedXmm(SrcVar->getRegNum()), Condition); |
- } else { |
- X8632::Traits::Address SrcStackAddr = |
- static_cast<TargetX8632 *>(Func->getTarget()) |
- ->stackVarToAsmOperand(SrcVar); |
- Asm->cmpps(RegX8632::getEncodedXmm(getDest()->getRegNum()), SrcStackAddr, |
- Condition); |
- } |
-} |
- |
-void InstX8632Cmpps::dump(const Cfg *Func) const { |
- if (!BuildDefs::dump()) |
- return; |
- Ostream &Str = Func->getContext()->getStrDump(); |
- assert(Condition < X8632::Traits::Cond::Cmpps_Invalid); |
- dumpDest(Func); |
- Str << " = cmp" << InstX8632CmppsAttributes[Condition].EmitString << "ps" |
- << "\t"; |
- dumpSources(Func); |
-} |
- |
-void InstX8632Cmpxchg::emit(const Cfg *Func) const { |
- if (!BuildDefs::dump()) |
- return; |
- Ostream &Str = Func->getContext()->getStrEmit(); |
- assert(getSrcSize() == 3); |
- if (Locked) { |
- Str << "\tlock"; |
- } |
- Str << "\tcmpxchg" << getWidthString(getSrc(0)->getType()) << "\t"; |
- getSrc(2)->emit(Func); |
- Str << ", "; |
- getSrc(0)->emit(Func); |
-} |
- |
-void InstX8632Cmpxchg::emitIAS(const Cfg *Func) const { |
- assert(getSrcSize() == 3); |
- X8632::AssemblerX8632 *Asm = Func->getAssembler<X8632::AssemblerX8632>(); |
- Type Ty = getSrc(0)->getType(); |
- const auto Mem = llvm::cast<OperandX8632Mem>(getSrc(0)); |
- assert(Mem->getSegmentRegister() == OperandX8632Mem::DefaultSegment); |
- const X8632::Traits::Address Addr = Mem->toAsmAddress(Asm); |
- const auto VarReg = llvm::cast<Variable>(getSrc(2)); |
- assert(VarReg->hasReg()); |
- const RegX8632::GPRRegister Reg = |
- RegX8632::getEncodedGPR(VarReg->getRegNum()); |
- Asm->cmpxchg(Ty, Addr, Reg, Locked); |
-} |
- |
-void InstX8632Cmpxchg::dump(const Cfg *Func) const { |
- if (!BuildDefs::dump()) |
- return; |
- Ostream &Str = Func->getContext()->getStrDump(); |
- if (Locked) { |
- Str << "lock "; |
- } |
- Str << "cmpxchg." << getSrc(0)->getType() << " "; |
- dumpSources(Func); |
-} |
- |
-void InstX8632Cmpxchg8b::emit(const Cfg *Func) const { |
- if (!BuildDefs::dump()) |
- return; |
- Ostream &Str = Func->getContext()->getStrEmit(); |
- assert(getSrcSize() == 5); |
- if (Locked) { |
- Str << "\tlock"; |
- } |
- Str << "\tcmpxchg8b\t"; |
- getSrc(0)->emit(Func); |
-} |
- |
-void InstX8632Cmpxchg8b::emitIAS(const Cfg *Func) const { |
- assert(getSrcSize() == 5); |
- X8632::AssemblerX8632 *Asm = Func->getAssembler<X8632::AssemblerX8632>(); |
- const auto Mem = llvm::cast<OperandX8632Mem>(getSrc(0)); |
- assert(Mem->getSegmentRegister() == OperandX8632Mem::DefaultSegment); |
- const X8632::Traits::Address Addr = Mem->toAsmAddress(Asm); |
- Asm->cmpxchg8b(Addr, Locked); |
-} |
- |
-void InstX8632Cmpxchg8b::dump(const Cfg *Func) const { |
- if (!BuildDefs::dump()) |
- return; |
- Ostream &Str = Func->getContext()->getStrDump(); |
- if (Locked) { |
- Str << "lock "; |
- } |
- Str << "cmpxchg8b "; |
- dumpSources(Func); |
-} |
- |
-void InstX8632Cvt::emit(const Cfg *Func) const { |
- if (!BuildDefs::dump()) |
- return; |
- Ostream &Str = Func->getContext()->getStrEmit(); |
- assert(getSrcSize() == 1); |
- Str << "\tcvt"; |
- if (isTruncating()) |
- Str << "t"; |
- Str << TypeX8632Attributes[getSrc(0)->getType()].CvtString << "2" |
- << TypeX8632Attributes[getDest()->getType()].CvtString << "\t"; |
- getSrc(0)->emit(Func); |
- Str << ", "; |
- getDest()->emit(Func); |
-} |
- |
-void InstX8632Cvt::emitIAS(const Cfg *Func) const { |
- assert(getSrcSize() == 1); |
- const Variable *Dest = getDest(); |
- const Operand *Src = getSrc(0); |
- Type DestTy = Dest->getType(); |
- Type SrcTy = Src->getType(); |
- switch (Variant) { |
- case Si2ss: { |
- assert(isScalarIntegerType(SrcTy)); |
- assert(typeWidthInBytes(SrcTy) <= 4); |
- assert(isScalarFloatingType(DestTy)); |
- static const X8632::AssemblerX8632::CastEmitterRegOp< |
- RegX8632::XmmRegister, RegX8632::GPRRegister> Emitter = { |
- &X8632::AssemblerX8632::cvtsi2ss, &X8632::AssemblerX8632::cvtsi2ss}; |
- emitIASCastRegOp<RegX8632::XmmRegister, RegX8632::GPRRegister, |
- RegX8632::getEncodedXmm, RegX8632::getEncodedGPR>( |
- Func, DestTy, Dest, Src, Emitter); |
- return; |
- } |
- case Tss2si: { |
- assert(isScalarFloatingType(SrcTy)); |
- assert(isScalarIntegerType(DestTy)); |
- assert(typeWidthInBytes(DestTy) <= 4); |
- static const X8632::AssemblerX8632::CastEmitterRegOp< |
- RegX8632::GPRRegister, RegX8632::XmmRegister> Emitter = { |
- &X8632::AssemblerX8632::cvttss2si, &X8632::AssemblerX8632::cvttss2si}; |
- emitIASCastRegOp<RegX8632::GPRRegister, RegX8632::XmmRegister, |
- RegX8632::getEncodedGPR, RegX8632::getEncodedXmm>( |
- Func, SrcTy, Dest, Src, Emitter); |
- return; |
- } |
- case Float2float: { |
- assert(isScalarFloatingType(SrcTy)); |
- assert(isScalarFloatingType(DestTy)); |
- assert(DestTy != SrcTy); |
- static const X8632::AssemblerX8632::XmmEmitterRegOp Emitter = { |
- &X8632::AssemblerX8632::cvtfloat2float, |
- &X8632::AssemblerX8632::cvtfloat2float}; |
- emitIASRegOpTyXMM(Func, SrcTy, Dest, Src, Emitter); |
- return; |
- } |
- case Dq2ps: { |
- assert(isVectorIntegerType(SrcTy)); |
- assert(isVectorFloatingType(DestTy)); |
- static const X8632::AssemblerX8632::XmmEmitterRegOp Emitter = { |
- &X8632::AssemblerX8632::cvtdq2ps, &X8632::AssemblerX8632::cvtdq2ps}; |
- emitIASRegOpTyXMM(Func, DestTy, Dest, Src, Emitter); |
- return; |
- } |
- case Tps2dq: { |
- assert(isVectorFloatingType(SrcTy)); |
- assert(isVectorIntegerType(DestTy)); |
- static const X8632::AssemblerX8632::XmmEmitterRegOp Emitter = { |
- &X8632::AssemblerX8632::cvttps2dq, &X8632::AssemblerX8632::cvttps2dq}; |
- emitIASRegOpTyXMM(Func, DestTy, Dest, Src, Emitter); |
- return; |
- } |
- } |
-} |
- |
-void InstX8632Cvt::dump(const Cfg *Func) const { |
- if (!BuildDefs::dump()) |
- return; |
- Ostream &Str = Func->getContext()->getStrDump(); |
- dumpDest(Func); |
- Str << " = cvt"; |
- if (isTruncating()) |
- Str << "t"; |
- Str << TypeX8632Attributes[getSrc(0)->getType()].CvtString << "2" |
- << TypeX8632Attributes[getDest()->getType()].CvtString << " "; |
- dumpSources(Func); |
-} |
- |
-void InstX8632Icmp::emit(const Cfg *Func) const { |
- if (!BuildDefs::dump()) |
- return; |
- Ostream &Str = Func->getContext()->getStrEmit(); |
- assert(getSrcSize() == 2); |
- Str << "\tcmp" << getWidthString(getSrc(0)->getType()) << "\t"; |
- getSrc(1)->emit(Func); |
- Str << ", "; |
- getSrc(0)->emit(Func); |
-} |
- |
-void InstX8632Icmp::emitIAS(const Cfg *Func) const { |
- assert(getSrcSize() == 2); |
- const Operand *Src0 = getSrc(0); |
- const Operand *Src1 = getSrc(1); |
- Type Ty = Src0->getType(); |
- static const X8632::AssemblerX8632::GPREmitterRegOp RegEmitter = { |
- &X8632::AssemblerX8632::cmp, &X8632::AssemblerX8632::cmp, |
- &X8632::AssemblerX8632::cmp}; |
- static const X8632::AssemblerX8632::GPREmitterAddrOp AddrEmitter = { |
- &X8632::AssemblerX8632::cmp, &X8632::AssemblerX8632::cmp}; |
- if (const auto SrcVar0 = llvm::dyn_cast<Variable>(Src0)) { |
- if (SrcVar0->hasReg()) { |
- emitIASRegOpTyGPR(Func, Ty, SrcVar0, Src1, RegEmitter); |
- return; |
- } |
- } |
- emitIASAsAddrOpTyGPR(Func, Ty, Src0, Src1, AddrEmitter); |
-} |
- |
-void InstX8632Icmp::dump(const Cfg *Func) const { |
- if (!BuildDefs::dump()) |
- return; |
- Ostream &Str = Func->getContext()->getStrDump(); |
- Str << "cmp." << getSrc(0)->getType() << " "; |
- dumpSources(Func); |
-} |
- |
-void InstX8632Ucomiss::emit(const Cfg *Func) const { |
- if (!BuildDefs::dump()) |
- return; |
- Ostream &Str = Func->getContext()->getStrEmit(); |
- assert(getSrcSize() == 2); |
- Str << "\tucomi" << TypeX8632Attributes[getSrc(0)->getType()].SdSsString |
- << "\t"; |
- getSrc(1)->emit(Func); |
- Str << ", "; |
- getSrc(0)->emit(Func); |
-} |
- |
-void InstX8632Ucomiss::emitIAS(const Cfg *Func) const { |
- assert(getSrcSize() == 2); |
- // Currently src0 is always a variable by convention, to avoid having |
- // two memory operands. |
- assert(llvm::isa<Variable>(getSrc(0))); |
- const auto Src0Var = llvm::cast<Variable>(getSrc(0)); |
- Type Ty = Src0Var->getType(); |
- const static X8632::AssemblerX8632::XmmEmitterRegOp Emitter = { |
- &X8632::AssemblerX8632::ucomiss, &X8632::AssemblerX8632::ucomiss}; |
- emitIASRegOpTyXMM(Func, Ty, Src0Var, getSrc(1), Emitter); |
-} |
- |
-void InstX8632Ucomiss::dump(const Cfg *Func) const { |
- if (!BuildDefs::dump()) |
- return; |
- Ostream &Str = Func->getContext()->getStrDump(); |
- Str << "ucomiss." << getSrc(0)->getType() << " "; |
- dumpSources(Func); |
-} |
- |
-void InstX8632UD2::emit(const Cfg *Func) const { |
- if (!BuildDefs::dump()) |
- return; |
- Ostream &Str = Func->getContext()->getStrEmit(); |
- assert(getSrcSize() == 0); |
- Str << "\tud2"; |
-} |
- |
-void InstX8632UD2::emitIAS(const Cfg *Func) const { |
- X8632::AssemblerX8632 *Asm = Func->getAssembler<X8632::AssemblerX8632>(); |
- Asm->ud2(); |
-} |
- |
-void InstX8632UD2::dump(const Cfg *Func) const { |
- if (!BuildDefs::dump()) |
- return; |
- Ostream &Str = Func->getContext()->getStrDump(); |
- Str << "ud2"; |
-} |
- |
-void InstX8632Test::emit(const Cfg *Func) const { |
- if (!BuildDefs::dump()) |
- return; |
- Ostream &Str = Func->getContext()->getStrEmit(); |
- assert(getSrcSize() == 2); |
- Str << "\ttest" << getWidthString(getSrc(0)->getType()) << "\t"; |
- getSrc(1)->emit(Func); |
- Str << ", "; |
- getSrc(0)->emit(Func); |
-} |
- |
-void InstX8632Test::emitIAS(const Cfg *Func) const { |
- assert(getSrcSize() == 2); |
- const Operand *Src0 = getSrc(0); |
- const Operand *Src1 = getSrc(1); |
- Type Ty = Src0->getType(); |
- // The Reg/Addr form of test is not encodeable. |
- static const X8632::AssemblerX8632::GPREmitterRegOp RegEmitter = { |
- &X8632::AssemblerX8632::test, nullptr, &X8632::AssemblerX8632::test}; |
- static const X8632::AssemblerX8632::GPREmitterAddrOp AddrEmitter = { |
- &X8632::AssemblerX8632::test, &X8632::AssemblerX8632::test}; |
- if (const auto SrcVar0 = llvm::dyn_cast<Variable>(Src0)) { |
- if (SrcVar0->hasReg()) { |
- emitIASRegOpTyGPR(Func, Ty, SrcVar0, Src1, RegEmitter); |
- return; |
- } |
- } |
- llvm_unreachable("Nothing actually generates this so it's untested"); |
- emitIASAsAddrOpTyGPR(Func, Ty, Src0, Src1, AddrEmitter); |
-} |
- |
-void InstX8632Test::dump(const Cfg *Func) const { |
- if (!BuildDefs::dump()) |
- return; |
- Ostream &Str = Func->getContext()->getStrDump(); |
- Str << "test." << getSrc(0)->getType() << " "; |
- dumpSources(Func); |
-} |
- |
-void InstX8632Mfence::emit(const Cfg *Func) const { |
- if (!BuildDefs::dump()) |
- return; |
- Ostream &Str = Func->getContext()->getStrEmit(); |
- assert(getSrcSize() == 0); |
- Str << "\tmfence"; |
-} |
- |
-void InstX8632Mfence::emitIAS(const Cfg *Func) const { |
- X8632::AssemblerX8632 *Asm = Func->getAssembler<X8632::AssemblerX8632>(); |
- Asm->mfence(); |
-} |
- |
-void InstX8632Mfence::dump(const Cfg *Func) const { |
- if (!BuildDefs::dump()) |
- return; |
- Ostream &Str = Func->getContext()->getStrDump(); |
- Str << "mfence"; |
-} |
- |
-void InstX8632Store::emit(const Cfg *Func) const { |
- if (!BuildDefs::dump()) |
- return; |
- Ostream &Str = Func->getContext()->getStrEmit(); |
- assert(getSrcSize() == 2); |
- Type Ty = getSrc(0)->getType(); |
- Str << "\tmov" << getWidthString(Ty) << TypeX8632Attributes[Ty].SdSsString |
- << "\t"; |
- getSrc(0)->emit(Func); |
- Str << ", "; |
- getSrc(1)->emit(Func); |
-} |
- |
-void InstX8632Store::emitIAS(const Cfg *Func) const { |
- assert(getSrcSize() == 2); |
- const Operand *Dest = getSrc(1); |
- const Operand *Src = getSrc(0); |
- Type DestTy = Dest->getType(); |
- if (isScalarFloatingType(DestTy)) { |
- // Src must be a register, since Dest is a Mem operand of some kind. |
- const auto SrcVar = llvm::cast<Variable>(Src); |
- assert(SrcVar->hasReg()); |
- RegX8632::XmmRegister SrcReg = RegX8632::getEncodedXmm(SrcVar->getRegNum()); |
- X8632::AssemblerX8632 *Asm = Func->getAssembler<X8632::AssemblerX8632>(); |
- if (const auto DestVar = llvm::dyn_cast<Variable>(Dest)) { |
- assert(!DestVar->hasReg()); |
- X8632::Traits::Address StackAddr( |
- static_cast<TargetX8632 *>(Func->getTarget()) |
- ->stackVarToAsmOperand(DestVar)); |
- Asm->movss(DestTy, StackAddr, SrcReg); |
- } else { |
- const auto DestMem = llvm::cast<OperandX8632Mem>(Dest); |
- assert(DestMem->getSegmentRegister() == OperandX8632Mem::DefaultSegment); |
- Asm->movss(DestTy, DestMem->toAsmAddress(Asm), SrcReg); |
- } |
- return; |
- } else { |
- assert(isScalarIntegerType(DestTy)); |
- static const X8632::AssemblerX8632::GPREmitterAddrOp GPRAddrEmitter = { |
- &X8632::AssemblerX8632::mov, &X8632::AssemblerX8632::mov}; |
- emitIASAsAddrOpTyGPR(Func, DestTy, Dest, Src, GPRAddrEmitter); |
- } |
-} |
- |
-void InstX8632Store::dump(const Cfg *Func) const { |
- if (!BuildDefs::dump()) |
- return; |
- Ostream &Str = Func->getContext()->getStrDump(); |
- Str << "mov." << getSrc(0)->getType() << " "; |
- getSrc(1)->dump(Func); |
- Str << ", "; |
- getSrc(0)->dump(Func); |
-} |
- |
-void InstX8632StoreP::emit(const Cfg *Func) const { |
- if (!BuildDefs::dump()) |
- return; |
- Ostream &Str = Func->getContext()->getStrEmit(); |
- assert(getSrcSize() == 2); |
- Str << "\tmovups\t"; |
- getSrc(0)->emit(Func); |
- Str << ", "; |
- getSrc(1)->emit(Func); |
-} |
- |
-void InstX8632StoreP::emitIAS(const Cfg *Func) const { |
- X8632::AssemblerX8632 *Asm = Func->getAssembler<X8632::AssemblerX8632>(); |
- assert(getSrcSize() == 2); |
- const auto SrcVar = llvm::cast<Variable>(getSrc(0)); |
- const auto DestMem = llvm::cast<OperandX8632Mem>(getSrc(1)); |
- assert(DestMem->getSegmentRegister() == OperandX8632Mem::DefaultSegment); |
- assert(SrcVar->hasReg()); |
- Asm->movups(DestMem->toAsmAddress(Asm), |
- RegX8632::getEncodedXmm(SrcVar->getRegNum())); |
-} |
- |
-void InstX8632StoreP::dump(const Cfg *Func) const { |
- if (!BuildDefs::dump()) |
- return; |
- Ostream &Str = Func->getContext()->getStrDump(); |
- Str << "storep." << getSrc(0)->getType() << " "; |
- getSrc(1)->dump(Func); |
- Str << ", "; |
- getSrc(0)->dump(Func); |
-} |
- |
-void InstX8632StoreQ::emit(const Cfg *Func) const { |
- if (!BuildDefs::dump()) |
- return; |
- Ostream &Str = Func->getContext()->getStrEmit(); |
- assert(getSrcSize() == 2); |
- assert(getSrc(1)->getType() == IceType_i64 || |
- getSrc(1)->getType() == IceType_f64); |
- Str << "\tmovq\t"; |
- getSrc(0)->emit(Func); |
- Str << ", "; |
- getSrc(1)->emit(Func); |
-} |
- |
-void InstX8632StoreQ::emitIAS(const Cfg *Func) const { |
- X8632::AssemblerX8632 *Asm = Func->getAssembler<X8632::AssemblerX8632>(); |
- assert(getSrcSize() == 2); |
- const auto SrcVar = llvm::cast<Variable>(getSrc(0)); |
- const auto DestMem = llvm::cast<OperandX8632Mem>(getSrc(1)); |
- assert(DestMem->getSegmentRegister() == OperandX8632Mem::DefaultSegment); |
- assert(SrcVar->hasReg()); |
- Asm->movq(DestMem->toAsmAddress(Asm), |
- RegX8632::getEncodedXmm(SrcVar->getRegNum())); |
-} |
- |
-void InstX8632StoreQ::dump(const Cfg *Func) const { |
- if (!BuildDefs::dump()) |
- return; |
- Ostream &Str = Func->getContext()->getStrDump(); |
- Str << "storeq." << getSrc(0)->getType() << " "; |
- getSrc(1)->dump(Func); |
- Str << ", "; |
- getSrc(0)->dump(Func); |
-} |
- |
-template <> void InstX8632Lea::emit(const Cfg *Func) const { |
- if (!BuildDefs::dump()) |
- return; |
- Ostream &Str = Func->getContext()->getStrEmit(); |
- assert(getSrcSize() == 1); |
- assert(getDest()->hasReg()); |
- Str << "\tleal\t"; |
- Operand *Src0 = getSrc(0); |
- if (const auto Src0Var = llvm::dyn_cast<Variable>(Src0)) { |
- Type Ty = Src0Var->getType(); |
- // lea on x86-32 doesn't accept mem128 operands, so cast VSrc0 to an |
- // acceptable type. |
- Src0Var->asType(isVectorType(Ty) ? IceType_i32 : Ty)->emit(Func); |
- } else { |
- Src0->emit(Func); |
- } |
- Str << ", "; |
- getDest()->emit(Func); |
-} |
- |
-template <> void InstX8632Mov::emit(const Cfg *Func) const { |
- if (!BuildDefs::dump()) |
- return; |
- Ostream &Str = Func->getContext()->getStrEmit(); |
- assert(getSrcSize() == 1); |
- Operand *Src = getSrc(0); |
- Type SrcTy = Src->getType(); |
- Type DestTy = getDest()->getType(); |
- Str << "\tmov" << (!isScalarFloatingType(DestTy) |
- ? getWidthString(SrcTy) |
- : TypeX8632Attributes[DestTy].SdSsString) << "\t"; |
- // For an integer truncation operation, src is wider than dest. |
- // Ideally, we use a mov instruction whose data width matches the |
- // narrower dest. This is a problem if e.g. src is a register like |
- // esi or si where there is no 8-bit version of the register. To be |
- // safe, we instead widen the dest to match src. This works even |
- // for stack-allocated dest variables because typeWidthOnStack() |
- // pads to a 4-byte boundary even if only a lower portion is used. |
- // TODO: This assert disallows usages such as copying a floating point |
- // value between a vector and a scalar (which movss is used for). |
- // Clean this up. |
- assert(Func->getTarget()->typeWidthInBytesOnStack(DestTy) == |
- Func->getTarget()->typeWidthInBytesOnStack(SrcTy)); |
- Src->emit(Func); |
- Str << ", "; |
- getDest()->asType(SrcTy)->emit(Func); |
-} |
- |
-template <> void InstX8632Mov::emitIAS(const Cfg *Func) const { |
- assert(getSrcSize() == 1); |
- const Variable *Dest = getDest(); |
- const Operand *Src = getSrc(0); |
- Type DestTy = Dest->getType(); |
- Type SrcTy = Src->getType(); |
- // Mov can be used for GPRs or XMM registers. Also, the type does not |
- // necessarily match (Mov can be used for bitcasts). However, when |
- // the type does not match, one of the operands must be a register. |
- // Thus, the strategy is to find out if Src or Dest are a register, |
- // then use that register's type to decide on which emitter set to use. |
- // The emitter set will include reg-reg movs, but that case should |
- // be unused when the types don't match. |
- static const X8632::AssemblerX8632::XmmEmitterRegOp XmmRegEmitter = { |
- &X8632::AssemblerX8632::movss, &X8632::AssemblerX8632::movss}; |
- static const X8632::AssemblerX8632::GPREmitterRegOp GPRRegEmitter = { |
- &X8632::AssemblerX8632::mov, &X8632::AssemblerX8632::mov, |
- &X8632::AssemblerX8632::mov}; |
- static const X8632::AssemblerX8632::GPREmitterAddrOp GPRAddrEmitter = { |
- &X8632::AssemblerX8632::mov, &X8632::AssemblerX8632::mov}; |
- // For an integer truncation operation, src is wider than dest. |
- // Ideally, we use a mov instruction whose data width matches the |
- // narrower dest. This is a problem if e.g. src is a register like |
- // esi or si where there is no 8-bit version of the register. To be |
- // safe, we instead widen the dest to match src. This works even |
- // for stack-allocated dest variables because typeWidthOnStack() |
- // pads to a 4-byte boundary even if only a lower portion is used. |
- // TODO: This assert disallows usages such as copying a floating point |
- // value between a vector and a scalar (which movss is used for). |
- // Clean this up. |
- assert(Func->getTarget()->typeWidthInBytesOnStack(getDest()->getType()) == |
- Func->getTarget()->typeWidthInBytesOnStack(Src->getType())); |
- if (Dest->hasReg()) { |
- if (isScalarFloatingType(DestTy)) { |
- emitIASRegOpTyXMM(Func, DestTy, Dest, Src, XmmRegEmitter); |
- return; |
- } else { |
- assert(isScalarIntegerType(DestTy)); |
- // Widen DestTy for truncation (see above note). We should only do this |
- // when both Src and Dest are integer types. |
- if (isScalarIntegerType(SrcTy)) { |
- DestTy = SrcTy; |
- } |
- emitIASRegOpTyGPR(Func, DestTy, Dest, Src, GPRRegEmitter); |
- return; |
- } |
- } else { |
- // Dest must be Stack and Src *could* be a register. Use Src's type |
- // to decide on the emitters. |
- X8632::Traits::Address StackAddr( |
- static_cast<TargetX8632 *>(Func->getTarget()) |
- ->stackVarToAsmOperand(Dest)); |
- if (isScalarFloatingType(SrcTy)) { |
- // Src must be a register. |
- const auto SrcVar = llvm::cast<Variable>(Src); |
- assert(SrcVar->hasReg()); |
- X8632::AssemblerX8632 *Asm = Func->getAssembler<X8632::AssemblerX8632>(); |
- Asm->movss(SrcTy, StackAddr, |
- RegX8632::getEncodedXmm(SrcVar->getRegNum())); |
- return; |
- } else { |
- // Src can be a register or immediate. |
- assert(isScalarIntegerType(SrcTy)); |
- emitIASAddrOpTyGPR(Func, SrcTy, StackAddr, Src, GPRAddrEmitter); |
- return; |
- } |
- return; |
- } |
-} |
- |
-template <> void InstX8632Movd::emitIAS(const Cfg *Func) const { |
- X8632::AssemblerX8632 *Asm = Func->getAssembler<X8632::AssemblerX8632>(); |
- assert(getSrcSize() == 1); |
- const Variable *Dest = getDest(); |
- const auto SrcVar = llvm::cast<Variable>(getSrc(0)); |
- // For insert/extract element (one of Src/Dest is an Xmm vector and |
- // the other is an int type). |
- if (SrcVar->getType() == IceType_i32) { |
- assert(isVectorType(Dest->getType())); |
- assert(Dest->hasReg()); |
- RegX8632::XmmRegister DestReg = RegX8632::getEncodedXmm(Dest->getRegNum()); |
- if (SrcVar->hasReg()) { |
- Asm->movd(DestReg, RegX8632::getEncodedGPR(SrcVar->getRegNum())); |
- } else { |
- X8632::Traits::Address StackAddr( |
- static_cast<TargetX8632 *>(Func->getTarget()) |
- ->stackVarToAsmOperand(SrcVar)); |
- Asm->movd(DestReg, StackAddr); |
- } |
- } else { |
- assert(isVectorType(SrcVar->getType())); |
- assert(SrcVar->hasReg()); |
- assert(Dest->getType() == IceType_i32); |
- RegX8632::XmmRegister SrcReg = RegX8632::getEncodedXmm(SrcVar->getRegNum()); |
- if (Dest->hasReg()) { |
- Asm->movd(RegX8632::getEncodedGPR(Dest->getRegNum()), SrcReg); |
- } else { |
- X8632::Traits::Address StackAddr( |
- static_cast<TargetX8632 *>(Func->getTarget()) |
- ->stackVarToAsmOperand(Dest)); |
- Asm->movd(StackAddr, SrcReg); |
- } |
- } |
-} |
- |
-template <> void InstX8632Movp::emit(const Cfg *Func) const { |
- if (!BuildDefs::dump()) |
- return; |
- // TODO(wala,stichnot): movups works with all vector operands, but |
- // there exist other instructions (movaps, movdqa, movdqu) that may |
- // perform better, depending on the data type and alignment of the |
- // operands. |
- Ostream &Str = Func->getContext()->getStrEmit(); |
- assert(getSrcSize() == 1); |
- Str << "\tmovups\t"; |
- getSrc(0)->emit(Func); |
- Str << ", "; |
- getDest()->emit(Func); |
-} |
- |
-template <> void InstX8632Movp::emitIAS(const Cfg *Func) const { |
- assert(getSrcSize() == 1); |
- assert(isVectorType(getDest()->getType())); |
- const Variable *Dest = getDest(); |
- const Operand *Src = getSrc(0); |
- const static X8632::AssemblerX8632::XmmEmitterMovOps Emitter = { |
- &X8632::AssemblerX8632::movups, &X8632::AssemblerX8632::movups, |
- &X8632::AssemblerX8632::movups}; |
- emitIASMovlikeXMM(Func, Dest, Src, Emitter); |
-} |
- |
-template <> void InstX8632Movq::emit(const Cfg *Func) const { |
- if (!BuildDefs::dump()) |
- return; |
- Ostream &Str = Func->getContext()->getStrEmit(); |
- assert(getSrcSize() == 1); |
- assert(getDest()->getType() == IceType_i64 || |
- getDest()->getType() == IceType_f64); |
- Str << "\tmovq\t"; |
- getSrc(0)->emit(Func); |
- Str << ", "; |
- getDest()->emit(Func); |
-} |
- |
-template <> void InstX8632Movq::emitIAS(const Cfg *Func) const { |
- assert(getSrcSize() == 1); |
- assert(getDest()->getType() == IceType_i64 || |
- getDest()->getType() == IceType_f64); |
- const Variable *Dest = getDest(); |
- const Operand *Src = getSrc(0); |
- const static X8632::AssemblerX8632::XmmEmitterMovOps Emitter = { |
- &X8632::AssemblerX8632::movq, &X8632::AssemblerX8632::movq, |
- &X8632::AssemblerX8632::movq}; |
- emitIASMovlikeXMM(Func, Dest, Src, Emitter); |
-} |
- |
-template <> void InstX8632MovssRegs::emitIAS(const Cfg *Func) const { |
- // This is Binop variant is only intended to be used for reg-reg moves |
- // where part of the Dest register is untouched. |
- assert(getSrcSize() == 2); |
- const Variable *Dest = getDest(); |
- assert(Dest == getSrc(0)); |
- const auto SrcVar = llvm::cast<Variable>(getSrc(1)); |
- assert(Dest->hasReg() && SrcVar->hasReg()); |
- X8632::AssemblerX8632 *Asm = Func->getAssembler<X8632::AssemblerX8632>(); |
- Asm->movss(IceType_f32, RegX8632::getEncodedXmm(Dest->getRegNum()), |
- RegX8632::getEncodedXmm(SrcVar->getRegNum())); |
-} |
- |
-template <> void InstX8632Movsx::emitIAS(const Cfg *Func) const { |
- assert(getSrcSize() == 1); |
- const Variable *Dest = getDest(); |
- const Operand *Src = getSrc(0); |
- // Dest must be a > 8-bit register, but Src can be 8-bit. In practice |
- // we just use the full register for Dest to avoid having an |
- // OperandSizeOverride prefix. It also allows us to only dispatch on SrcTy. |
- Type SrcTy = Src->getType(); |
- assert(typeWidthInBytes(Dest->getType()) > 1); |
- assert(typeWidthInBytes(Dest->getType()) > typeWidthInBytes(SrcTy)); |
- emitIASRegOpTyGPR<false, true>(Func, SrcTy, Dest, Src, Emitter); |
-} |
- |
-template <> void InstX8632Movzx::emitIAS(const Cfg *Func) const { |
- assert(getSrcSize() == 1); |
- const Variable *Dest = getDest(); |
- const Operand *Src = getSrc(0); |
- Type SrcTy = Src->getType(); |
- assert(typeWidthInBytes(Dest->getType()) > 1); |
- assert(typeWidthInBytes(Dest->getType()) > typeWidthInBytes(SrcTy)); |
- emitIASRegOpTyGPR<false, true>(Func, SrcTy, Dest, Src, Emitter); |
-} |
- |
-void InstX8632Nop::emit(const Cfg *Func) const { |
- if (!BuildDefs::dump()) |
- return; |
- Ostream &Str = Func->getContext()->getStrEmit(); |
- // TODO: Emit the right code for each variant. |
- Str << "\tnop\t# variant = " << Variant; |
-} |
- |
-void InstX8632Nop::emitIAS(const Cfg *Func) const { |
- X8632::AssemblerX8632 *Asm = Func->getAssembler<X8632::AssemblerX8632>(); |
- // TODO: Emit the right code for the variant. |
- Asm->nop(); |
-} |
- |
-void InstX8632Nop::dump(const Cfg *Func) const { |
- if (!BuildDefs::dump()) |
- return; |
- Ostream &Str = Func->getContext()->getStrDump(); |
- Str << "nop (variant = " << Variant << ")"; |
-} |
- |
-void InstX8632Fld::emit(const Cfg *Func) const { |
- if (!BuildDefs::dump()) |
- return; |
- Ostream &Str = Func->getContext()->getStrEmit(); |
- assert(getSrcSize() == 1); |
- Type Ty = getSrc(0)->getType(); |
- SizeT Width = typeWidthInBytes(Ty); |
- const auto Var = llvm::dyn_cast<Variable>(getSrc(0)); |
- if (Var && Var->hasReg()) { |
- // This is a physical xmm register, so we need to spill it to a |
- // temporary stack slot. |
- Str << "\tsubl\t$" << Width << ", %esp" |
- << "\n"; |
- Str << "\tmov" << TypeX8632Attributes[Ty].SdSsString << "\t"; |
- Var->emit(Func); |
- Str << ", (%esp)\n"; |
- Str << "\tfld" << getFldString(Ty) << "\t" |
- << "(%esp)\n"; |
- Str << "\taddl\t$" << Width << ", %esp"; |
- return; |
- } |
- Str << "\tfld" << getFldString(Ty) << "\t"; |
- getSrc(0)->emit(Func); |
-} |
- |
-void InstX8632Fld::emitIAS(const Cfg *Func) const { |
- X8632::AssemblerX8632 *Asm = Func->getAssembler<X8632::AssemblerX8632>(); |
- assert(getSrcSize() == 1); |
- const Operand *Src = getSrc(0); |
- Type Ty = Src->getType(); |
- if (const auto Var = llvm::dyn_cast<Variable>(Src)) { |
- if (Var->hasReg()) { |
- // This is a physical xmm register, so we need to spill it to a |
- // temporary stack slot. |
- X8632::Immediate Width(typeWidthInBytes(Ty)); |
- Asm->sub(IceType_i32, RegX8632::Encoded_Reg_esp, Width); |
- X8632::Traits::Address StackSlot = |
- X8632::Traits::Address(RegX8632::Encoded_Reg_esp, 0); |
- Asm->movss(Ty, StackSlot, RegX8632::getEncodedXmm(Var->getRegNum())); |
- Asm->fld(Ty, StackSlot); |
- Asm->add(IceType_i32, RegX8632::Encoded_Reg_esp, Width); |
- } else { |
- X8632::Traits::Address StackAddr( |
- static_cast<TargetX8632 *>(Func->getTarget()) |
- ->stackVarToAsmOperand(Var)); |
- Asm->fld(Ty, StackAddr); |
- } |
- } else if (const auto Mem = llvm::dyn_cast<OperandX8632Mem>(Src)) { |
- assert(Mem->getSegmentRegister() == OperandX8632Mem::DefaultSegment); |
- Asm->fld(Ty, Mem->toAsmAddress(Asm)); |
- } else if (const auto Imm = llvm::dyn_cast<Constant>(Src)) { |
- Asm->fld(Ty, X8632::Traits::Address::ofConstPool(Asm, Imm)); |
- } else { |
- llvm_unreachable("Unexpected operand type"); |
- } |
-} |
- |
-void InstX8632Fld::dump(const Cfg *Func) const { |
- if (!BuildDefs::dump()) |
- return; |
- Ostream &Str = Func->getContext()->getStrDump(); |
- Str << "fld." << getSrc(0)->getType() << " "; |
- dumpSources(Func); |
-} |
- |
-void InstX8632Fstp::emit(const Cfg *Func) const { |
- if (!BuildDefs::dump()) |
- return; |
- Ostream &Str = Func->getContext()->getStrEmit(); |
- assert(getSrcSize() == 0); |
- // TODO(jvoung,stichnot): Utilize this by setting Dest to nullptr to |
- // "partially" delete the fstp if the Dest is unused. |
- // Even if Dest is unused, the fstp should be kept for the SideEffects |
- // of popping the stack. |
- if (!getDest()) { |
- Str << "\tfstp\tst(0)"; |
- return; |
- } |
- Type Ty = getDest()->getType(); |
- size_t Width = typeWidthInBytes(Ty); |
- if (!getDest()->hasReg()) { |
- Str << "\tfstp" << getFldString(Ty) << "\t"; |
- getDest()->emit(Func); |
- return; |
- } |
- // Dest is a physical (xmm) register, so st(0) needs to go through |
- // memory. Hack this by creating a temporary stack slot, spilling |
- // st(0) there, loading it into the xmm register, and deallocating |
- // the stack slot. |
- Str << "\tsubl\t$" << Width << ", %esp\n"; |
- Str << "\tfstp" << getFldString(Ty) << "\t" |
- << "(%esp)\n"; |
- Str << "\tmov" << TypeX8632Attributes[Ty].SdSsString << "\t" |
- << "(%esp), "; |
- getDest()->emit(Func); |
- Str << "\n"; |
- Str << "\taddl\t$" << Width << ", %esp"; |
-} |
- |
-void InstX8632Fstp::emitIAS(const Cfg *Func) const { |
- X8632::AssemblerX8632 *Asm = Func->getAssembler<X8632::AssemblerX8632>(); |
- assert(getSrcSize() == 0); |
- const Variable *Dest = getDest(); |
- // TODO(jvoung,stichnot): Utilize this by setting Dest to nullptr to |
- // "partially" delete the fstp if the Dest is unused. |
- // Even if Dest is unused, the fstp should be kept for the SideEffects |
- // of popping the stack. |
- if (!Dest) { |
- Asm->fstp(RegX8632::getEncodedSTReg(0)); |
- return; |
- } |
- Type Ty = Dest->getType(); |
- if (!Dest->hasReg()) { |
- X8632::Traits::Address StackAddr( |
- static_cast<TargetX8632 *>(Func->getTarget()) |
- ->stackVarToAsmOperand(Dest)); |
- Asm->fstp(Ty, StackAddr); |
- } else { |
- // Dest is a physical (xmm) register, so st(0) needs to go through |
- // memory. Hack this by creating a temporary stack slot, spilling |
- // st(0) there, loading it into the xmm register, and deallocating |
- // the stack slot. |
- X8632::Immediate Width(typeWidthInBytes(Ty)); |
- Asm->sub(IceType_i32, RegX8632::Encoded_Reg_esp, Width); |
- X8632::Traits::Address StackSlot = |
- X8632::Traits::Address(RegX8632::Encoded_Reg_esp, 0); |
- Asm->fstp(Ty, StackSlot); |
- Asm->movss(Ty, RegX8632::getEncodedXmm(Dest->getRegNum()), StackSlot); |
- Asm->add(IceType_i32, RegX8632::Encoded_Reg_esp, Width); |
- } |
-} |
- |
-void InstX8632Fstp::dump(const Cfg *Func) const { |
- if (!BuildDefs::dump()) |
- return; |
- Ostream &Str = Func->getContext()->getStrDump(); |
- dumpDest(Func); |
- Str << " = fstp." << getDest()->getType() << ", st(0)"; |
-} |
- |
-template <> void InstX8632Pcmpeq::emit(const Cfg *Func) const { |
- if (!BuildDefs::dump()) |
- return; |
- char buf[30]; |
- snprintf(buf, llvm::array_lengthof(buf), "pcmpeq%s", |
- TypeX8632Attributes[getDest()->getType()].PackString); |
- emitTwoAddress(buf, this, Func); |
-} |
- |
-template <> void InstX8632Pcmpgt::emit(const Cfg *Func) const { |
- if (!BuildDefs::dump()) |
- return; |
- char buf[30]; |
- snprintf(buf, llvm::array_lengthof(buf), "pcmpgt%s", |
- TypeX8632Attributes[getDest()->getType()].PackString); |
- emitTwoAddress(buf, this, Func); |
-} |
- |
-template <> void InstX8632Pextr::emit(const Cfg *Func) const { |
- if (!BuildDefs::dump()) |
- return; |
- Ostream &Str = Func->getContext()->getStrEmit(); |
- assert(getSrcSize() == 2); |
- // pextrb and pextrd are SSE4.1 instructions. |
- assert(getSrc(0)->getType() == IceType_v8i16 || |
- getSrc(0)->getType() == IceType_v8i1 || |
- static_cast<TargetX8632 *>(Func->getTarget())->getInstructionSet() >= |
- X8632::Traits::SSE4_1); |
- Str << "\t" << Opcode << TypeX8632Attributes[getSrc(0)->getType()].PackString |
- << "\t"; |
- getSrc(1)->emit(Func); |
- Str << ", "; |
- getSrc(0)->emit(Func); |
- Str << ", "; |
- Variable *Dest = getDest(); |
- // pextrw must take a register dest. There is an SSE4.1 version that takes |
- // a memory dest, but we aren't using it. For uniformity, just restrict |
- // them all to have a register dest for now. |
- assert(Dest->hasReg()); |
- Dest->asType(IceType_i32)->emit(Func); |
-} |
- |
-template <> void InstX8632Pextr::emitIAS(const Cfg *Func) const { |
- assert(getSrcSize() == 2); |
- // pextrb and pextrd are SSE4.1 instructions. |
- const Variable *Dest = getDest(); |
- Type DispatchTy = Dest->getType(); |
- assert(DispatchTy == IceType_i16 || |
- static_cast<TargetX8632 *>(Func->getTarget())->getInstructionSet() >= |
- X8632::Traits::SSE4_1); |
- // pextrw must take a register dest. There is an SSE4.1 version that takes |
- // a memory dest, but we aren't using it. For uniformity, just restrict |
- // them all to have a register dest for now. |
- assert(Dest->hasReg()); |
- // pextrw's Src(0) must be a register (both SSE4.1 and SSE2). |
- assert(llvm::cast<Variable>(getSrc(0))->hasReg()); |
- static const X8632::AssemblerX8632::ThreeOpImmEmitter< |
- RegX8632::GPRRegister, RegX8632::XmmRegister> Emitter = { |
- &X8632::AssemblerX8632::pextr, nullptr}; |
- emitIASThreeOpImmOps<RegX8632::GPRRegister, RegX8632::XmmRegister, |
- RegX8632::getEncodedGPR, RegX8632::getEncodedXmm>( |
- Func, DispatchTy, Dest, getSrc(0), getSrc(1), Emitter); |
-} |
- |
-template <> void InstX8632Pinsr::emit(const Cfg *Func) const { |
- if (!BuildDefs::dump()) |
- return; |
- Ostream &Str = Func->getContext()->getStrEmit(); |
- assert(getSrcSize() == 3); |
- // pinsrb and pinsrd are SSE4.1 instructions. |
- assert(getDest()->getType() == IceType_v8i16 || |
- getDest()->getType() == IceType_v8i1 || |
- static_cast<TargetX8632 *>(Func->getTarget())->getInstructionSet() >= |
- X8632::Traits::SSE4_1); |
- Str << "\t" << Opcode << TypeX8632Attributes[getDest()->getType()].PackString |
- << "\t"; |
- getSrc(2)->emit(Func); |
- Str << ", "; |
- Operand *Src1 = getSrc(1); |
- if (const auto Src1Var = llvm::dyn_cast<Variable>(Src1)) { |
- // If src1 is a register, it should always be r32. |
- if (Src1Var->hasReg()) { |
- Src1Var->asType(IceType_i32)->emit(Func); |
- } else { |
- Src1Var->emit(Func); |
- } |
- } else { |
- Src1->emit(Func); |
- } |
- Str << ", "; |
- getDest()->emit(Func); |
-} |
- |
-template <> void InstX8632Pinsr::emitIAS(const Cfg *Func) const { |
- assert(getSrcSize() == 3); |
- assert(getDest() == getSrc(0)); |
- // pinsrb and pinsrd are SSE4.1 instructions. |
- const Operand *Src0 = getSrc(1); |
- Type DispatchTy = Src0->getType(); |
- assert(DispatchTy == IceType_i16 || |
- static_cast<TargetX8632 *>(Func->getTarget())->getInstructionSet() >= |
- X8632::Traits::SSE4_1); |
- // If src1 is a register, it should always be r32 (this should fall out |
- // from the encodings for ByteRegs overlapping the encodings for r32), |
- // but we have to trust the regalloc to not choose "ah", where it |
- // doesn't overlap. |
- static const X8632::AssemblerX8632::ThreeOpImmEmitter< |
- RegX8632::XmmRegister, RegX8632::GPRRegister> Emitter = { |
- &X8632::AssemblerX8632::pinsr, &X8632::AssemblerX8632::pinsr}; |
- emitIASThreeOpImmOps<RegX8632::XmmRegister, RegX8632::GPRRegister, |
- RegX8632::getEncodedXmm, RegX8632::getEncodedGPR>( |
- Func, DispatchTy, getDest(), Src0, getSrc(2), Emitter); |
-} |
- |
-template <> void InstX8632Pshufd::emitIAS(const Cfg *Func) const { |
- assert(getSrcSize() == 2); |
- const Variable *Dest = getDest(); |
- Type Ty = Dest->getType(); |
- static const X8632::AssemblerX8632::ThreeOpImmEmitter< |
- RegX8632::XmmRegister, RegX8632::XmmRegister> Emitter = { |
- &X8632::AssemblerX8632::pshufd, &X8632::AssemblerX8632::pshufd}; |
- emitIASThreeOpImmOps<RegX8632::XmmRegister, RegX8632::XmmRegister, |
- RegX8632::getEncodedXmm, RegX8632::getEncodedXmm>( |
- Func, Ty, Dest, getSrc(0), getSrc(1), Emitter); |
-} |
- |
-template <> void InstX8632Shufps::emitIAS(const Cfg *Func) const { |
- assert(getSrcSize() == 3); |
- const Variable *Dest = getDest(); |
- assert(Dest == getSrc(0)); |
- Type Ty = Dest->getType(); |
- static const X8632::AssemblerX8632::ThreeOpImmEmitter< |
- RegX8632::XmmRegister, RegX8632::XmmRegister> Emitter = { |
- &X8632::AssemblerX8632::shufps, &X8632::AssemblerX8632::shufps}; |
- emitIASThreeOpImmOps<RegX8632::XmmRegister, RegX8632::XmmRegister, |
- RegX8632::getEncodedXmm, RegX8632::getEncodedXmm>( |
- Func, Ty, Dest, getSrc(1), getSrc(2), Emitter); |
-} |
- |
-void InstX8632Pop::emit(const Cfg *Func) const { |
- if (!BuildDefs::dump()) |
- return; |
- Ostream &Str = Func->getContext()->getStrEmit(); |
- assert(getSrcSize() == 0); |
- Str << "\tpop\t"; |
- getDest()->emit(Func); |
-} |
- |
-void InstX8632Pop::emitIAS(const Cfg *Func) const { |
- assert(getSrcSize() == 0); |
- X8632::AssemblerX8632 *Asm = Func->getAssembler<X8632::AssemblerX8632>(); |
- if (getDest()->hasReg()) { |
- Asm->popl(RegX8632::getEncodedGPR(getDest()->getRegNum())); |
- } else { |
- Asm->popl(static_cast<TargetX8632 *>(Func->getTarget()) |
- ->stackVarToAsmOperand(getDest())); |
- } |
-} |
- |
-void InstX8632Pop::dump(const Cfg *Func) const { |
- if (!BuildDefs::dump()) |
- return; |
- Ostream &Str = Func->getContext()->getStrDump(); |
- dumpDest(Func); |
- Str << " = pop." << getDest()->getType() << " "; |
-} |
- |
-void InstX8632AdjustStack::emit(const Cfg *Func) const { |
- if (!BuildDefs::dump()) |
- return; |
- Ostream &Str = Func->getContext()->getStrEmit(); |
- Str << "\tsubl\t$" << Amount << ", %esp"; |
- Func->getTarget()->updateStackAdjustment(Amount); |
-} |
- |
-void InstX8632AdjustStack::emitIAS(const Cfg *Func) const { |
- X8632::AssemblerX8632 *Asm = Func->getAssembler<X8632::AssemblerX8632>(); |
- Asm->sub(IceType_i32, RegX8632::Encoded_Reg_esp, X8632::Immediate(Amount)); |
- Func->getTarget()->updateStackAdjustment(Amount); |
-} |
- |
-void InstX8632AdjustStack::dump(const Cfg *Func) const { |
- if (!BuildDefs::dump()) |
- return; |
- Ostream &Str = Func->getContext()->getStrDump(); |
- Str << "esp = sub.i32 esp, " << Amount; |
-} |
- |
-void InstX8632Push::emit(const Cfg *Func) const { |
- if (!BuildDefs::dump()) |
- return; |
- Ostream &Str = Func->getContext()->getStrEmit(); |
- assert(getSrcSize() == 1); |
- // Push is currently only used for saving GPRs. |
- const auto Var = llvm::cast<Variable>(getSrc(0)); |
- assert(Var->hasReg()); |
- Str << "\tpush\t"; |
- Var->emit(Func); |
-} |
- |
-void InstX8632Push::emitIAS(const Cfg *Func) const { |
- assert(getSrcSize() == 1); |
- // Push is currently only used for saving GPRs. |
- const auto Var = llvm::cast<Variable>(getSrc(0)); |
- assert(Var->hasReg()); |
- X8632::AssemblerX8632 *Asm = Func->getAssembler<X8632::AssemblerX8632>(); |
- Asm->pushl(RegX8632::getEncodedGPR(Var->getRegNum())); |
-} |
- |
-void InstX8632Push::dump(const Cfg *Func) const { |
- if (!BuildDefs::dump()) |
- return; |
- Ostream &Str = Func->getContext()->getStrDump(); |
- Str << "push." << getSrc(0)->getType() << " "; |
- dumpSources(Func); |
-} |
- |
-template <> void InstX8632Psll::emit(const Cfg *Func) const { |
- if (!BuildDefs::dump()) |
- return; |
- assert(getDest()->getType() == IceType_v8i16 || |
- getDest()->getType() == IceType_v8i1 || |
- getDest()->getType() == IceType_v4i32 || |
- getDest()->getType() == IceType_v4i1); |
- char buf[30]; |
- snprintf(buf, llvm::array_lengthof(buf), "psll%s", |
- TypeX8632Attributes[getDest()->getType()].PackString); |
- emitTwoAddress(buf, this, Func); |
-} |
- |
-template <> void InstX8632Psra::emit(const Cfg *Func) const { |
- if (!BuildDefs::dump()) |
- return; |
- assert(getDest()->getType() == IceType_v8i16 || |
- getDest()->getType() == IceType_v8i1 || |
- getDest()->getType() == IceType_v4i32 || |
- getDest()->getType() == IceType_v4i1); |
- char buf[30]; |
- snprintf(buf, llvm::array_lengthof(buf), "psra%s", |
- TypeX8632Attributes[getDest()->getType()].PackString); |
- emitTwoAddress(buf, this, Func); |
-} |
+/// This file also defines X8632 operand specific methods (dump and emit.) |
+/// |
+//===----------------------------------------------------------------------===// |
+#include "IceInstX8632.h" |
-template <> void InstX8632Psrl::emit(const Cfg *Func) const { |
- if (!BuildDefs::dump()) |
- return; |
- char buf[30]; |
- snprintf(buf, llvm::array_lengthof(buf), "psrl%s", |
- TypeX8632Attributes[getDest()->getType()].PackString); |
- emitTwoAddress(buf, this, Func); |
-} |
+#include "IceAssemblerX8632.h" |
+#include "IceCfg.h" |
+#include "IceCfgNode.h" |
+#include "IceConditionCodesX8632.h" |
+#include "IceInst.h" |
+#include "IceRegistersX8632.h" |
+#include "IceTargetLoweringX8632.h" |
+#include "IceOperand.h" |
-void InstX8632Ret::emit(const Cfg *Func) const { |
- if (!BuildDefs::dump()) |
- return; |
- Ostream &Str = Func->getContext()->getStrEmit(); |
- Str << "\tret"; |
-} |
+namespace Ice { |
-void InstX8632Ret::emitIAS(const Cfg *Func) const { |
- X8632::AssemblerX8632 *Asm = Func->getAssembler<X8632::AssemblerX8632>(); |
- Asm->ret(); |
-} |
+namespace X86Internal { |
-void InstX8632Ret::dump(const Cfg *Func) const { |
- if (!BuildDefs::dump()) |
- return; |
- Ostream &Str = Func->getContext()->getStrDump(); |
- Type Ty = (getSrcSize() == 0 ? IceType_void : getSrc(0)->getType()); |
- Str << "ret." << Ty << " "; |
- dumpSources(Func); |
-} |
+const MachineTraits<TargetX8632>::InstBrAttributesType |
+ MachineTraits<TargetX8632>::InstBrAttributes[] = { |
+#define X(tag, encode, opp, dump, emit) \ |
+ { X8632::Traits::Cond::opp, dump, emit } \ |
+ , |
+ ICEINSTX8632BR_TABLE |
+#undef X |
+}; |
-void InstX8632Setcc::emit(const Cfg *Func) const { |
- if (!BuildDefs::dump()) |
- return; |
- Ostream &Str = Func->getContext()->getStrEmit(); |
- Str << "\tset" << InstX8632BrAttributes[Condition].DisplayString << "\t"; |
- Dest->emit(Func); |
-} |
+const MachineTraits<TargetX8632>::InstCmppsAttributesType |
+ MachineTraits<TargetX8632>::InstCmppsAttributes[] = { |
+#define X(tag, emit) \ |
+ { emit } \ |
+ , |
+ ICEINSTX8632CMPPS_TABLE |
+#undef X |
+}; |
-void InstX8632Setcc::emitIAS(const Cfg *Func) const { |
- assert(Condition != X8632::Traits::Cond::Br_None); |
- assert(getDest()->getType() == IceType_i1); |
- assert(getSrcSize() == 0); |
- X8632::AssemblerX8632 *Asm = Func->getAssembler<X8632::AssemblerX8632>(); |
- if (getDest()->hasReg()) |
- Asm->setcc(Condition, RegX8632::getEncodedByteReg(getDest()->getRegNum())); |
- else |
- Asm->setcc(Condition, static_cast<TargetX8632 *>(Func->getTarget()) |
- ->stackVarToAsmOperand(getDest())); |
- return; |
-} |
+const MachineTraits<TargetX8632>::TypeAttributesType |
+ MachineTraits<TargetX8632>::TypeAttributes[] = { |
+#define X(tag, elementty, cvt, sdss, pack, width, fld) \ |
+ { cvt, sdss, pack, width, fld } \ |
+ , |
+ ICETYPEX8632_TABLE |
+#undef X |
+}; |
-void InstX8632Setcc::dump(const Cfg *Func) const { |
- if (!BuildDefs::dump()) |
- return; |
- Ostream &Str = Func->getContext()->getStrDump(); |
- Str << "setcc." << InstX8632BrAttributes[Condition].DisplayString << " "; |
- dumpDest(Func); |
-} |
+const char *MachineTraits<TargetX8632>::InstSegmentRegNames[] = { |
+#define X(val, name, prefix) name, |
+ SEG_REGX8632_TABLE |
+#undef X |
+}; |
-void InstX8632Xadd::emit(const Cfg *Func) const { |
- if (!BuildDefs::dump()) |
- return; |
- Ostream &Str = Func->getContext()->getStrEmit(); |
- if (Locked) { |
- Str << "\tlock"; |
- } |
- Str << "\txadd" << getWidthString(getSrc(0)->getType()) << "\t"; |
- getSrc(1)->emit(Func); |
- Str << ", "; |
- getSrc(0)->emit(Func); |
-} |
+uint8_t MachineTraits<TargetX8632>::InstSegmentPrefixes[] = { |
+#define X(val, name, prefix) prefix, |
+ SEG_REGX8632_TABLE |
+#undef X |
+}; |
-void InstX8632Xadd::emitIAS(const Cfg *Func) const { |
- assert(getSrcSize() == 2); |
- X8632::AssemblerX8632 *Asm = Func->getAssembler<X8632::AssemblerX8632>(); |
- Type Ty = getSrc(0)->getType(); |
- const auto Mem = llvm::cast<OperandX8632Mem>(getSrc(0)); |
- assert(Mem->getSegmentRegister() == OperandX8632Mem::DefaultSegment); |
- const X8632::Traits::Address Addr = Mem->toAsmAddress(Asm); |
- const auto VarReg = llvm::cast<Variable>(getSrc(1)); |
- assert(VarReg->hasReg()); |
- const RegX8632::GPRRegister Reg = |
- RegX8632::getEncodedGPR(VarReg->getRegNum()); |
- Asm->xadd(Ty, Addr, Reg, Locked); |
+void MachineTraits<TargetX8632>::X86Operand::dump(const Cfg *, |
+ Ostream &Str) const { |
+ if (BuildDefs::dump()) |
+ Str << "<OperandX8632>"; |
} |
-void InstX8632Xadd::dump(const Cfg *Func) const { |
- if (!BuildDefs::dump()) |
- return; |
- Ostream &Str = Func->getContext()->getStrDump(); |
- if (Locked) { |
- Str << "lock "; |
+MachineTraits<TargetX8632>::X86OperandMem::X86OperandMem( |
+ Cfg *Func, Type Ty, Variable *Base, Constant *Offset, Variable *Index, |
+ uint16_t Shift, SegmentRegisters SegmentReg) |
+ : X86Operand(kMem, Ty), Base(Base), Offset(Offset), Index(Index), |
+ Shift(Shift), SegmentReg(SegmentReg), Randomized(false) { |
+ assert(Shift <= 3); |
+ Vars = nullptr; |
+ NumVars = 0; |
+ if (Base) |
+ ++NumVars; |
+ if (Index) |
+ ++NumVars; |
+ if (NumVars) { |
+ Vars = Func->allocateArrayOf<Variable *>(NumVars); |
+ SizeT I = 0; |
+ if (Base) |
+ Vars[I++] = Base; |
+ if (Index) |
+ Vars[I++] = Index; |
+ assert(I == NumVars); |
} |
- Type Ty = getSrc(0)->getType(); |
- Str << "xadd." << Ty << " "; |
- dumpSources(Func); |
-} |
- |
-void InstX8632Xchg::emit(const Cfg *Func) const { |
- if (!BuildDefs::dump()) |
- return; |
- Ostream &Str = Func->getContext()->getStrEmit(); |
- Str << "\txchg" << getWidthString(getSrc(0)->getType()) << "\t"; |
- getSrc(1)->emit(Func); |
- Str << ", "; |
- getSrc(0)->emit(Func); |
-} |
- |
-void InstX8632Xchg::emitIAS(const Cfg *Func) const { |
- assert(getSrcSize() == 2); |
- X8632::AssemblerX8632 *Asm = Func->getAssembler<X8632::AssemblerX8632>(); |
- Type Ty = getSrc(0)->getType(); |
- const auto Mem = llvm::cast<OperandX8632Mem>(getSrc(0)); |
- assert(Mem->getSegmentRegister() == OperandX8632Mem::DefaultSegment); |
- const X8632::Traits::Address Addr = Mem->toAsmAddress(Asm); |
- const auto VarReg = llvm::cast<Variable>(getSrc(1)); |
- assert(VarReg->hasReg()); |
- const RegX8632::GPRRegister Reg = |
- RegX8632::getEncodedGPR(VarReg->getRegNum()); |
- Asm->xchg(Ty, Addr, Reg); |
-} |
- |
-void InstX8632Xchg::dump(const Cfg *Func) const { |
- if (!BuildDefs::dump()) |
- return; |
- Ostream &Str = Func->getContext()->getStrDump(); |
- Type Ty = getSrc(0)->getType(); |
- Str << "xchg." << Ty << " "; |
- dumpSources(Func); |
} |
-void OperandX8632Mem::emit(const Cfg *Func) const { |
+void MachineTraits<TargetX8632>::X86OperandMem::emit(const Cfg *Func) const { |
if (!BuildDefs::dump()) |
return; |
Ostream &Str = Func->getContext()->getStrEmit(); |
if (SegmentReg != DefaultSegment) { |
assert(SegmentReg >= 0 && SegmentReg < SegReg_NUM); |
- Str << "%" << InstX8632SegmentRegNames[SegmentReg] << ":"; |
+ Str << "%" << X8632::Traits::InstSegmentRegNames[SegmentReg] << ":"; |
} |
// Emit as Offset(Base,Index,1<<Shift). |
// Offset is emitted without the leading '$'. |
@@ -2943,12 +134,13 @@ void OperandX8632Mem::emit(const Cfg *Func) const { |
} |
} |
-void OperandX8632Mem::dump(const Cfg *Func, Ostream &Str) const { |
+void MachineTraits<TargetX8632>::X86OperandMem::dump(const Cfg *Func, |
+ Ostream &Str) const { |
if (!BuildDefs::dump()) |
return; |
if (SegmentReg != DefaultSegment) { |
assert(SegmentReg >= 0 && SegmentReg < SegReg_NUM); |
- Str << InstX8632SegmentRegNames[SegmentReg] << ":"; |
+ Str << X8632::Traits::InstSegmentRegNames[SegmentReg] << ":"; |
} |
bool Dumped = false; |
Str << "["; |
@@ -2994,14 +186,17 @@ void OperandX8632Mem::dump(const Cfg *Func, Ostream &Str) const { |
Str << "]"; |
} |
-void OperandX8632Mem::emitSegmentOverride(X8632::AssemblerX8632 *Asm) const { |
+void MachineTraits<TargetX8632>::X86OperandMem::emitSegmentOverride( |
+ MachineTraits<TargetX8632>::Assembler *Asm) const { |
if (SegmentReg != DefaultSegment) { |
assert(SegmentReg >= 0 && SegmentReg < SegReg_NUM); |
- Asm->emitSegmentOverride(InstX8632SegmentPrefixes[SegmentReg]); |
+ Asm->emitSegmentOverride(X8632::Traits::InstSegmentPrefixes[SegmentReg]); |
} |
} |
-X8632::Traits::Address OperandX8632Mem::toAsmAddress(Assembler *Asm) const { |
+MachineTraits<TargetX8632>::Address |
+MachineTraits<TargetX8632>::X86OperandMem::toAsmAddress( |
+ MachineTraits<TargetX8632>::Assembler *Asm) const { |
int32_t Disp = 0; |
AssemblerFixup *Fixup = nullptr; |
// Determine the offset (is it relocatable?) |
@@ -3037,22 +232,23 @@ X8632::Traits::Address OperandX8632Mem::toAsmAddress(Assembler *Asm) const { |
} |
} |
-X8632::Traits::Address VariableSplit::toAsmAddress(const Cfg *Func) const { |
+MachineTraits<TargetX8632>::Address |
+MachineTraits<TargetX8632>::VariableSplit::toAsmAddress(const Cfg *Func) const { |
assert(!Var->hasReg()); |
- const TargetLowering *Target = Func->getTarget(); |
+ const ::Ice::TargetLowering *Target = Func->getTarget(); |
int32_t Offset = |
Var->getStackOffset() + Target->getStackAdjustment() + getOffset(); |
return X8632::Traits::Address( |
RegX8632::getEncodedGPR(Target->getFrameOrStackReg()), Offset); |
} |
-void VariableSplit::emit(const Cfg *Func) const { |
+void MachineTraits<TargetX8632>::VariableSplit::emit(const Cfg *Func) const { |
if (!BuildDefs::dump()) |
return; |
Ostream &Str = Func->getContext()->getStrEmit(); |
assert(!Var->hasReg()); |
// The following is copied/adapted from TargetX8632::emitVariable(). |
- const TargetLowering *Target = Func->getTarget(); |
+ const ::Ice::TargetLowering *Target = Func->getTarget(); |
const Type Ty = IceType_i32; |
int32_t Offset = |
Var->getStackOffset() + Target->getStackAdjustment() + getOffset(); |
@@ -3061,7 +257,8 @@ void VariableSplit::emit(const Cfg *Func) const { |
Str << "(%" << Target->getRegName(Target->getFrameOrStackReg(), Ty) << ")"; |
} |
-void VariableSplit::dump(const Cfg *Func, Ostream &Str) const { |
+void MachineTraits<TargetX8632>::VariableSplit::dump(const Cfg *Func, |
+ Ostream &Str) const { |
if (!BuildDefs::dump()) |
return; |
switch (Part) { |
@@ -3080,4 +277,7 @@ void VariableSplit::dump(const Cfg *Func, Ostream &Str) const { |
Str << ")"; |
} |
+} // namespace X86Internal |
} // end of namespace Ice |
+ |
+X86INSTS_DEFINE_STATIC_DATA(TargetX8632); |