diff options
| author | Dimitry Andric <dim@FreeBSD.org> | 2020-01-17 20:45:01 +0000 |
|---|---|---|
| committer | Dimitry Andric <dim@FreeBSD.org> | 2020-01-17 20:45:01 +0000 |
| commit | 706b4fc47bbc608932d3b491ae19a3b9cde9497b (patch) | |
| tree | 4adf86a776049cbf7f69a1929c4babcbbef925eb /llvm/lib/Target/X86/MCTargetDesc | |
| parent | 7cc9cf2bf09f069cb2dd947ead05d0b54301fb71 (diff) | |
Notes
Diffstat (limited to 'llvm/lib/Target/X86/MCTargetDesc')
8 files changed, 1280 insertions, 573 deletions
diff --git a/llvm/lib/Target/X86/MCTargetDesc/X86ATTInstPrinter.cpp b/llvm/lib/Target/X86/MCTargetDesc/X86ATTInstPrinter.cpp index ed2ee55ff2a5..675a9c377b12 100644 --- a/llvm/lib/Target/X86/MCTargetDesc/X86ATTInstPrinter.cpp +++ b/llvm/lib/Target/X86/MCTargetDesc/X86ATTInstPrinter.cpp @@ -38,8 +38,9 @@ void X86ATTInstPrinter::printRegName(raw_ostream &OS, unsigned RegNo) const { OS << markup("<reg:") << '%' << getRegisterName(RegNo) << markup(">"); } -void X86ATTInstPrinter::printInst(const MCInst *MI, raw_ostream &OS, - StringRef Annot, const MCSubtargetInfo &STI) { +void X86ATTInstPrinter::printInst(const MCInst *MI, uint64_t Address, + StringRef Annot, const MCSubtargetInfo &STI, + raw_ostream &OS) { // If verbose assembly is enabled, we can print some informative comments. if (CommentStream) HasCustomInstComment = EmitAnyX86InstComments(MI, *CommentStream, MII); @@ -69,7 +70,7 @@ void X86ATTInstPrinter::printInst(const MCInst *MI, raw_ostream &OS, // Try to print any aliases first. else if (!printAliasInstr(MI, OS) && !printVecCompareInstr(MI, OS)) - printInstruction(MI, OS); + printInstruction(MI, Address, OS); // Next always print the annotation. printAnnotation(OS, Annot); diff --git a/llvm/lib/Target/X86/MCTargetDesc/X86ATTInstPrinter.h b/llvm/lib/Target/X86/MCTargetDesc/X86ATTInstPrinter.h index 747ddd30a2d9..3d5d384dc4a0 100644 --- a/llvm/lib/Target/X86/MCTargetDesc/X86ATTInstPrinter.h +++ b/llvm/lib/Target/X86/MCTargetDesc/X86ATTInstPrinter.h @@ -24,8 +24,8 @@ public: : X86InstPrinterCommon(MAI, MII, MRI), HasCustomInstComment(false) {} void printRegName(raw_ostream &OS, unsigned RegNo) const override; - void printInst(const MCInst *MI, raw_ostream &OS, StringRef Annot, - const MCSubtargetInfo &STI) override; + void printInst(const MCInst *MI, uint64_t Address, StringRef Annot, + const MCSubtargetInfo &STI, raw_ostream &OS) override; bool printVecCompareInstr(const MCInst *MI, raw_ostream &OS); // Autogenerated by tblgen, returns true if we successfully printed an @@ -35,7 +35,7 @@ public: unsigned PrintMethodIdx, raw_ostream &O); // Autogenerated by tblgen. - void printInstruction(const MCInst *MI, raw_ostream &OS); + void printInstruction(const MCInst *MI, uint64_t Address, raw_ostream &OS); static const char *getRegisterName(unsigned RegNo); void printOperand(const MCInst *MI, unsigned OpNo, raw_ostream &OS) override; diff --git a/llvm/lib/Target/X86/MCTargetDesc/X86AsmBackend.cpp b/llvm/lib/Target/X86/MCTargetDesc/X86AsmBackend.cpp index f08fcb575bf0..dffda5217675 100644 --- a/llvm/lib/Target/X86/MCTargetDesc/X86AsmBackend.cpp +++ b/llvm/lib/Target/X86/MCTargetDesc/X86AsmBackend.cpp @@ -12,55 +12,95 @@ #include "llvm/BinaryFormat/ELF.h" #include "llvm/BinaryFormat/MachO.h" #include "llvm/MC/MCAsmBackend.h" +#include "llvm/MC/MCAssembler.h" +#include "llvm/MC/MCContext.h" #include "llvm/MC/MCDwarf.h" #include "llvm/MC/MCELFObjectWriter.h" #include "llvm/MC/MCExpr.h" #include "llvm/MC/MCFixupKindInfo.h" #include "llvm/MC/MCInst.h" +#include "llvm/MC/MCInstrInfo.h" #include "llvm/MC/MCMachObjectWriter.h" +#include "llvm/MC/MCObjectStreamer.h" #include "llvm/MC/MCObjectWriter.h" #include "llvm/MC/MCRegisterInfo.h" #include "llvm/MC/MCSectionMachO.h" #include "llvm/MC/MCSubtargetInfo.h" +#include "llvm/MC/MCValue.h" +#include "llvm/Support/CommandLine.h" #include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/TargetRegistry.h" #include "llvm/Support/raw_ostream.h" + using namespace llvm; -static unsigned getFixupKindSize(unsigned Kind) { - switch (Kind) { - default: - llvm_unreachable("invalid fixup kind!"); - case FK_NONE: - return 0; - case FK_PCRel_1: - case FK_SecRel_1: - case FK_Data_1: - return 1; - case FK_PCRel_2: - case FK_SecRel_2: - case FK_Data_2: - return 2; - case FK_PCRel_4: - case X86::reloc_riprel_4byte: - case X86::reloc_riprel_4byte_relax: - case X86::reloc_riprel_4byte_relax_rex: - case X86::reloc_riprel_4byte_movq_load: - case X86::reloc_signed_4byte: - case X86::reloc_signed_4byte_relax: - case X86::reloc_global_offset_table: - case X86::reloc_branch_4byte_pcrel: - case FK_SecRel_4: - case FK_Data_4: - return 4; - case FK_PCRel_8: - case FK_SecRel_8: - case FK_Data_8: - case X86::reloc_global_offset_table8: - return 8; +namespace { +/// A wrapper for holding a mask of the values from X86::AlignBranchBoundaryKind +class X86AlignBranchKind { +private: + uint8_t AlignBranchKind = 0; + +public: + void operator=(const std::string &Val) { + if (Val.empty()) + return; + SmallVector<StringRef, 6> BranchTypes; + StringRef(Val).split(BranchTypes, '+', -1, false); + for (auto BranchType : BranchTypes) { + if (BranchType == "fused") + addKind(X86::AlignBranchFused); + else if (BranchType == "jcc") + addKind(X86::AlignBranchJcc); + else if (BranchType == "jmp") + addKind(X86::AlignBranchJmp); + else if (BranchType == "call") + addKind(X86::AlignBranchCall); + else if (BranchType == "ret") + addKind(X86::AlignBranchRet); + else if (BranchType == "indirect") + addKind(X86::AlignBranchIndirect); + else { + report_fatal_error( + "'-x86-align-branch 'The branches's type is combination of jcc, " + "fused, jmp, call, ret, indirect.(plus separated)", + false); + } + } } -} -namespace { + operator uint8_t() const { return AlignBranchKind; } + void addKind(X86::AlignBranchBoundaryKind Value) { AlignBranchKind |= Value; } +}; + +X86AlignBranchKind X86AlignBranchKindLoc; + +cl::opt<unsigned> X86AlignBranchBoundary( + "x86-align-branch-boundary", cl::init(0), + cl::desc( + "Control how the assembler should align branches with NOP. If the " + "boundary's size is not 0, it should be a power of 2 and no less " + "than 32. Branches will be aligned to prevent from being across or " + "against the boundary of specified size. The default value 0 does not " + "align branches.")); + +cl::opt<X86AlignBranchKind, true, cl::parser<std::string>> X86AlignBranch( + "x86-align-branch", + cl::desc("Specify types of branches to align (plus separated list of " + "types). The branches's types are combination of jcc, fused, " + "jmp, call, ret, indirect."), + cl::value_desc("jcc indicates conditional jumps, fused indicates fused " + "conditional jumps, jmp indicates unconditional jumps, call " + "indicates direct and indirect calls, ret indicates rets, " + "indirect indicates indirect jumps."), + cl::location(X86AlignBranchKindLoc)); + +cl::opt<bool> X86AlignBranchWithin32BBoundaries( + "x86-branches-within-32B-boundaries", cl::init(false), + cl::desc( + "Align selected instructions to mitigate negative performance impact " + "of Intel's micro code update for errata skx102. May break " + "assumptions about labels corresponding to particular instructions, " + "and should be used with caution.")); class X86ELFObjectWriter : public MCELFObjectTargetWriter { public: @@ -71,9 +111,42 @@ public: class X86AsmBackend : public MCAsmBackend { const MCSubtargetInfo &STI; + std::unique_ptr<const MCInstrInfo> MCII; + X86AlignBranchKind AlignBranchType; + Align AlignBoundary; + + bool isMacroFused(const MCInst &Cmp, const MCInst &Jcc) const; + + bool needAlign(MCObjectStreamer &OS) const; + bool needAlignInst(const MCInst &Inst) const; + MCBoundaryAlignFragment * + getOrCreateBoundaryAlignFragment(MCObjectStreamer &OS) const; + MCInst PrevInst; + public: X86AsmBackend(const Target &T, const MCSubtargetInfo &STI) - : MCAsmBackend(support::little), STI(STI) {} + : MCAsmBackend(support::little), STI(STI), + MCII(T.createMCInstrInfo()) { + if (X86AlignBranchWithin32BBoundaries) { + // At the moment, this defaults to aligning fused branches, unconditional + // jumps, and (unfused) conditional jumps with nops. Both the + // instructions aligned and the alignment method (nop vs prefix) may + // change in the future. + AlignBoundary = assumeAligned(32);; + AlignBranchType.addKind(X86::AlignBranchFused); + AlignBranchType.addKind(X86::AlignBranchJcc); + AlignBranchType.addKind(X86::AlignBranchJmp); + } + // Allow overriding defaults set by master flag + if (X86AlignBranchBoundary.getNumOccurrences()) + AlignBoundary = assumeAligned(X86AlignBranchBoundary); + if (X86AlignBranch.getNumOccurrences()) + AlignBranchType = X86AlignBranchKindLoc; + } + + bool allowAutoPadding() const override; + void alignBranchesBegin(MCObjectStreamer &OS, const MCInst &Inst) override; + void alignBranchesEnd(MCObjectStreamer &OS, const MCInst &Inst) override; unsigned getNumFixupKinds() const override { return X86::NumTargetFixupKinds; @@ -81,49 +154,15 @@ public: Optional<MCFixupKind> getFixupKind(StringRef Name) const override; - const MCFixupKindInfo &getFixupKindInfo(MCFixupKind Kind) const override { - const static MCFixupKindInfo Infos[X86::NumTargetFixupKinds] = { - {"reloc_riprel_4byte", 0, 32, MCFixupKindInfo::FKF_IsPCRel}, - {"reloc_riprel_4byte_movq_load", 0, 32, MCFixupKindInfo::FKF_IsPCRel}, - {"reloc_riprel_4byte_relax", 0, 32, MCFixupKindInfo::FKF_IsPCRel}, - {"reloc_riprel_4byte_relax_rex", 0, 32, MCFixupKindInfo::FKF_IsPCRel}, - {"reloc_signed_4byte", 0, 32, 0}, - {"reloc_signed_4byte_relax", 0, 32, 0}, - {"reloc_global_offset_table", 0, 32, 0}, - {"reloc_global_offset_table8", 0, 64, 0}, - {"reloc_branch_4byte_pcrel", 0, 32, MCFixupKindInfo::FKF_IsPCRel}, - }; - - if (Kind < FirstTargetFixupKind) - return MCAsmBackend::getFixupKindInfo(Kind); - - assert(unsigned(Kind - FirstTargetFixupKind) < getNumFixupKinds() && - "Invalid kind!"); - assert(Infos[Kind - FirstTargetFixupKind].Name && "Empty fixup name!"); - return Infos[Kind - FirstTargetFixupKind]; - } - + const MCFixupKindInfo &getFixupKindInfo(MCFixupKind Kind) const override; + bool shouldForceRelocation(const MCAssembler &Asm, const MCFixup &Fixup, const MCValue &Target) override; void applyFixup(const MCAssembler &Asm, const MCFixup &Fixup, const MCValue &Target, MutableArrayRef<char> Data, uint64_t Value, bool IsResolved, - const MCSubtargetInfo *STI) const override { - unsigned Size = getFixupKindSize(Fixup.getKind()); - - assert(Fixup.getOffset() + Size <= Data.size() && "Invalid fixup offset!"); - - // Check that uppper bits are either all zeros or all ones. - // Specifically ignore overflow/underflow as long as the leakage is - // limited to the lower bits. This is to remain compatible with - // other assemblers. - assert((Size == 0 || isIntN(Size * 8 + 1, Value)) && - "Value does not fit in the Fixup field"); - - for (unsigned i = 0; i != Size; ++i) - Data[Fixup.getOffset() + i] = uint8_t(Value >> (i * 8)); - } + const MCSubtargetInfo *STI) const override; bool mayNeedRelaxation(const MCInst &Inst, const MCSubtargetInfo &STI) const override; @@ -243,6 +282,200 @@ static unsigned getRelaxedOpcode(const MCInst &Inst, bool is16BitMode) { return getRelaxedOpcodeBranch(Inst, is16BitMode); } +static X86::CondCode getCondFromBranch(const MCInst &MI, + const MCInstrInfo &MCII) { + unsigned Opcode = MI.getOpcode(); + switch (Opcode) { + default: + return X86::COND_INVALID; + case X86::JCC_1: { + const MCInstrDesc &Desc = MCII.get(Opcode); + return static_cast<X86::CondCode>( + MI.getOperand(Desc.getNumOperands() - 1).getImm()); + } + } +} + +static X86::SecondMacroFusionInstKind +classifySecondInstInMacroFusion(const MCInst &MI, const MCInstrInfo &MCII) { + X86::CondCode CC = getCondFromBranch(MI, MCII); + return classifySecondCondCodeInMacroFusion(CC); +} + +/// Check if the instruction uses RIP relative addressing. +static bool isRIPRelative(const MCInst &MI, const MCInstrInfo &MCII) { + unsigned Opcode = MI.getOpcode(); + const MCInstrDesc &Desc = MCII.get(Opcode); + uint64_t TSFlags = Desc.TSFlags; + unsigned CurOp = X86II::getOperandBias(Desc); + int MemoryOperand = X86II::getMemoryOperandNo(TSFlags); + if (MemoryOperand < 0) + return false; + unsigned BaseRegNum = MemoryOperand + CurOp + X86::AddrBaseReg; + unsigned BaseReg = MI.getOperand(BaseRegNum).getReg(); + return (BaseReg == X86::RIP); +} + +/// Check if the instruction is valid as the first instruction in macro fusion. +static bool isFirstMacroFusibleInst(const MCInst &Inst, + const MCInstrInfo &MCII) { + // An Intel instruction with RIP relative addressing is not macro fusible. + if (isRIPRelative(Inst, MCII)) + return false; + X86::FirstMacroFusionInstKind FIK = + X86::classifyFirstOpcodeInMacroFusion(Inst.getOpcode()); + return FIK != X86::FirstMacroFusionInstKind::Invalid; +} + +/// Check if the two instructions will be macro-fused on the target cpu. +bool X86AsmBackend::isMacroFused(const MCInst &Cmp, const MCInst &Jcc) const { + const MCInstrDesc &InstDesc = MCII->get(Jcc.getOpcode()); + if (!InstDesc.isConditionalBranch()) + return false; + if (!isFirstMacroFusibleInst(Cmp, *MCII)) + return false; + const X86::FirstMacroFusionInstKind CmpKind = + X86::classifyFirstOpcodeInMacroFusion(Cmp.getOpcode()); + const X86::SecondMacroFusionInstKind BranchKind = + classifySecondInstInMacroFusion(Jcc, *MCII); + return X86::isMacroFused(CmpKind, BranchKind); +} + +/// Check if the instruction has a variant symbol operand. +static bool hasVariantSymbol(const MCInst &MI) { + for (auto &Operand : MI) { + if (!Operand.isExpr()) + continue; + const MCExpr &Expr = *Operand.getExpr(); + if (Expr.getKind() == MCExpr::SymbolRef && + cast<MCSymbolRefExpr>(Expr).getKind() != MCSymbolRefExpr::VK_None) + return true; + } + return false; +} + +bool X86AsmBackend::allowAutoPadding() const { + return (AlignBoundary != Align::None() && + AlignBranchType != X86::AlignBranchNone); +} + +bool X86AsmBackend::needAlign(MCObjectStreamer &OS) const { + if (!OS.getAllowAutoPadding()) + return false; + assert(allowAutoPadding() && "incorrect initialization!"); + + MCAssembler &Assembler = OS.getAssembler(); + MCSection *Sec = OS.getCurrentSectionOnly(); + // To be Done: Currently don't deal with Bundle cases. + if (Assembler.isBundlingEnabled() && Sec->isBundleLocked()) + return false; + + // Branches only need to be aligned in 32-bit or 64-bit mode. + if (!(STI.hasFeature(X86::Mode64Bit) || STI.hasFeature(X86::Mode32Bit))) + return false; + + return true; +} + +/// Check if the instruction operand needs to be aligned. Padding is disabled +/// before intruction which may be rewritten by linker(e.g. TLSCALL). +bool X86AsmBackend::needAlignInst(const MCInst &Inst) const { + // Linker may rewrite the instruction with variant symbol operand. + if (hasVariantSymbol(Inst)) + return false; + + const MCInstrDesc &InstDesc = MCII->get(Inst.getOpcode()); + return (InstDesc.isConditionalBranch() && + (AlignBranchType & X86::AlignBranchJcc)) || + (InstDesc.isUnconditionalBranch() && + (AlignBranchType & X86::AlignBranchJmp)) || + (InstDesc.isCall() && + (AlignBranchType & X86::AlignBranchCall)) || + (InstDesc.isReturn() && + (AlignBranchType & X86::AlignBranchRet)) || + (InstDesc.isIndirectBranch() && + (AlignBranchType & X86::AlignBranchIndirect)); +} + +static bool canReuseBoundaryAlignFragment(const MCBoundaryAlignFragment &F) { + // If a MCBoundaryAlignFragment has not been used to emit NOP,we can reuse it. + return !F.canEmitNops(); +} + +MCBoundaryAlignFragment * +X86AsmBackend::getOrCreateBoundaryAlignFragment(MCObjectStreamer &OS) const { + auto *F = dyn_cast_or_null<MCBoundaryAlignFragment>(OS.getCurrentFragment()); + if (!F || !canReuseBoundaryAlignFragment(*F)) { + F = new MCBoundaryAlignFragment(AlignBoundary); + OS.insert(F); + } + return F; +} + +/// Insert MCBoundaryAlignFragment before instructions to align branches. +void X86AsmBackend::alignBranchesBegin(MCObjectStreamer &OS, + const MCInst &Inst) { + if (!needAlign(OS)) + return; + + MCFragment *CF = OS.getCurrentFragment(); + bool NeedAlignFused = AlignBranchType & X86::AlignBranchFused; + if (NeedAlignFused && isMacroFused(PrevInst, Inst) && CF) { + // Macro fusion actually happens and there is no other fragment inserted + // after the previous instruction. NOP can be emitted in PF to align fused + // jcc. + if (auto *PF = + dyn_cast_or_null<MCBoundaryAlignFragment>(CF->getPrevNode())) { + const_cast<MCBoundaryAlignFragment *>(PF)->setEmitNops(true); + const_cast<MCBoundaryAlignFragment *>(PF)->setFused(true); + } + } else if (needAlignInst(Inst)) { + // Note: When there is at least one fragment, such as MCAlignFragment, + // inserted after the previous instruction, e.g. + // + // \code + // cmp %rax %rcx + // .align 16 + // je .Label0 + // \ endcode + // + // We will treat the JCC as a unfused branch although it may be fused + // with the CMP. + auto *F = getOrCreateBoundaryAlignFragment(OS); + F->setEmitNops(true); + F->setFused(false); + } else if (NeedAlignFused && isFirstMacroFusibleInst(Inst, *MCII)) { + // We don't know if macro fusion happens until the reaching the next + // instruction, so a place holder is put here if necessary. + getOrCreateBoundaryAlignFragment(OS); + } + + PrevInst = Inst; +} + +/// Insert a MCBoundaryAlignFragment to mark the end of the branch to be aligned +/// if necessary. +void X86AsmBackend::alignBranchesEnd(MCObjectStreamer &OS, const MCInst &Inst) { + if (!needAlign(OS)) + return; + // If the branch is emitted into a MCRelaxableFragment, we can determine the + // size of the branch easily in MCAssembler::relaxBoundaryAlign. When the + // branch is fused, the fused branch(macro fusion pair) must be emitted into + // two fragments. Or when the branch is unfused, the branch must be emitted + // into one fragment. The MCRelaxableFragment naturally marks the end of the + // fused or unfused branch. + // Otherwise, we need to insert a MCBoundaryAlignFragment to mark the end of + // the branch. This MCBoundaryAlignFragment may be reused to emit NOP to align + // other branch. + if (needAlignInst(Inst) && !isa<MCRelaxableFragment>(OS.getCurrentFragment())) + OS.insert(new MCBoundaryAlignFragment(AlignBoundary)); + + // Update the maximum alignment on the current section if necessary. + MCSection *Sec = OS.getCurrentSectionOnly(); + if (AlignBoundary.value() > Sec->getAlignment()) + Sec->setAlignment(AlignBoundary); +} + Optional<MCFixupKind> X86AsmBackend::getFixupKind(StringRef Name) const { if (STI.getTargetTriple().isOSBinFormatELF()) { if (STI.getTargetTriple().getArch() == Triple::x86_64) { @@ -256,12 +489,100 @@ Optional<MCFixupKind> X86AsmBackend::getFixupKind(StringRef Name) const { return MCAsmBackend::getFixupKind(Name); } +const MCFixupKindInfo &X86AsmBackend::getFixupKindInfo(MCFixupKind Kind) const { + const static MCFixupKindInfo Infos[X86::NumTargetFixupKinds] = { + {"reloc_riprel_4byte", 0, 32, MCFixupKindInfo::FKF_IsPCRel}, + {"reloc_riprel_4byte_movq_load", 0, 32, MCFixupKindInfo::FKF_IsPCRel}, + {"reloc_riprel_4byte_relax", 0, 32, MCFixupKindInfo::FKF_IsPCRel}, + {"reloc_riprel_4byte_relax_rex", 0, 32, MCFixupKindInfo::FKF_IsPCRel}, + {"reloc_signed_4byte", 0, 32, 0}, + {"reloc_signed_4byte_relax", 0, 32, 0}, + {"reloc_global_offset_table", 0, 32, 0}, + {"reloc_global_offset_table8", 0, 64, 0}, + {"reloc_branch_4byte_pcrel", 0, 32, MCFixupKindInfo::FKF_IsPCRel}, + }; + + if (Kind < FirstTargetFixupKind) + return MCAsmBackend::getFixupKindInfo(Kind); + + assert(unsigned(Kind - FirstTargetFixupKind) < getNumFixupKinds() && + "Invalid kind!"); + assert(Infos[Kind - FirstTargetFixupKind].Name && "Empty fixup name!"); + return Infos[Kind - FirstTargetFixupKind]; +} + bool X86AsmBackend::shouldForceRelocation(const MCAssembler &, const MCFixup &Fixup, const MCValue &) { return Fixup.getKind() == FK_NONE; } +static unsigned getFixupKindSize(unsigned Kind) { + switch (Kind) { + default: + llvm_unreachable("invalid fixup kind!"); + case FK_NONE: + return 0; + case FK_PCRel_1: + case FK_SecRel_1: + case FK_Data_1: + return 1; + case FK_PCRel_2: + case FK_SecRel_2: + case FK_Data_2: + return 2; + case FK_PCRel_4: + case X86::reloc_riprel_4byte: + case X86::reloc_riprel_4byte_relax: + case X86::reloc_riprel_4byte_relax_rex: + case X86::reloc_riprel_4byte_movq_load: + case X86::reloc_signed_4byte: + case X86::reloc_signed_4byte_relax: + case X86::reloc_global_offset_table: + case X86::reloc_branch_4byte_pcrel: + case FK_SecRel_4: + case FK_Data_4: + return 4; + case FK_PCRel_8: + case FK_SecRel_8: + case FK_Data_8: + case X86::reloc_global_offset_table8: + return 8; + } +} + +void X86AsmBackend::applyFixup(const MCAssembler &Asm, const MCFixup &Fixup, + const MCValue &Target, + MutableArrayRef<char> Data, + uint64_t Value, bool IsResolved, + const MCSubtargetInfo *STI) const { + unsigned Size = getFixupKindSize(Fixup.getKind()); + + assert(Fixup.getOffset() + Size <= Data.size() && "Invalid fixup offset!"); + + int64_t SignedValue = static_cast<int64_t>(Value); + if ((Target.isAbsolute() || IsResolved) && + getFixupKindInfo(Fixup.getKind()).Flags & + MCFixupKindInfo::FKF_IsPCRel) { + // check that PC relative fixup fits into the fixup size. + if (Size > 0 && !isIntN(Size * 8, SignedValue)) + Asm.getContext().reportError( + Fixup.getLoc(), "value of " + Twine(SignedValue) + + " is too large for field of " + Twine(Size) + + ((Size == 1) ? " byte." : " bytes.")); + } else { + // Check that uppper bits are either all zeros or all ones. + // Specifically ignore overflow/underflow as long as the leakage is + // limited to the lower bits. This is to remain compatible with + // other assemblers. + assert((Size == 0 || isIntN(Size * 8 + 1, SignedValue)) && + "Value does not fit in the Fixup field"); + } + + for (unsigned i = 0; i != Size; ++i) + Data[Fixup.getOffset() + i] = uint8_t(Value >> (i * 8)); +} + bool X86AsmBackend::mayNeedRelaxation(const MCInst &Inst, const MCSubtargetInfo &STI) const { // Branches can always be relaxed in either mode. diff --git a/llvm/lib/Target/X86/MCTargetDesc/X86BaseInfo.h b/llvm/lib/Target/X86/MCTargetDesc/X86BaseInfo.h index 6bd6c6cac7df..a4f8dd669e1e 100644 --- a/llvm/lib/Target/X86/MCTargetDesc/X86BaseInfo.h +++ b/llvm/lib/Target/X86/MCTargetDesc/X86BaseInfo.h @@ -101,6 +101,261 @@ namespace X86 { COND_INVALID }; + + // The classification for the first instruction in macro fusion. + enum class FirstMacroFusionInstKind { + // TEST + Test, + // CMP + Cmp, + // AND + And, + // ADD, SUB + AddSub, + // INC, DEC + IncDec, + // Not valid as a first macro fusion instruction + Invalid + }; + + enum class SecondMacroFusionInstKind { + // JA, JB and variants. + AB, + // JE, JL, JG and variants. + ELG, + // JS, JP, JO and variants + SPO, + // Not a fusible jump. + Invalid, + }; + + /// \returns the type of the first instruction in macro-fusion. + inline FirstMacroFusionInstKind + classifyFirstOpcodeInMacroFusion(unsigned Opcode) { + switch (Opcode) { + default: + return FirstMacroFusionInstKind::Invalid; + // TEST + case X86::TEST16i16: + case X86::TEST16mr: + case X86::TEST16ri: + case X86::TEST16rr: + case X86::TEST32i32: + case X86::TEST32mr: + case X86::TEST32ri: + case X86::TEST32rr: + case X86::TEST64i32: + case X86::TEST64mr: + case X86::TEST64ri32: + case X86::TEST64rr: + case X86::TEST8i8: + case X86::TEST8mr: + case X86::TEST8ri: + case X86::TEST8rr: + return FirstMacroFusionInstKind::Test; + case X86::AND16i16: + case X86::AND16ri: + case X86::AND16ri8: + case X86::AND16rm: + case X86::AND16rr: + case X86::AND16rr_REV: + case X86::AND32i32: + case X86::AND32ri: + case X86::AND32ri8: + case X86::AND32rm: + case X86::AND32rr: + case X86::AND32rr_REV: + case X86::AND64i32: + case X86::AND64ri32: + case X86::AND64ri8: + case X86::AND64rm: + case X86::AND64rr: + case X86::AND64rr_REV: + case X86::AND8i8: + case X86::AND8ri: + case X86::AND8ri8: + case X86::AND8rm: + case X86::AND8rr: + case X86::AND8rr_REV: + return FirstMacroFusionInstKind::And; + // CMP + case X86::CMP16i16: + case X86::CMP16mr: + case X86::CMP16ri: + case X86::CMP16ri8: + case X86::CMP16rm: + case X86::CMP16rr: + case X86::CMP16rr_REV: + case X86::CMP32i32: + case X86::CMP32mr: + case X86::CMP32ri: + case X86::CMP32ri8: + case X86::CMP32rm: + case X86::CMP32rr: + case X86::CMP32rr_REV: + case X86::CMP64i32: + case X86::CMP64mr: + case X86::CMP64ri32: + case X86::CMP64ri8: + case X86::CMP64rm: + case X86::CMP64rr: + case X86::CMP64rr_REV: + case X86::CMP8i8: + case X86::CMP8mr: + case X86::CMP8ri: + case X86::CMP8ri8: + case X86::CMP8rm: + case X86::CMP8rr: + case X86::CMP8rr_REV: + return FirstMacroFusionInstKind::Cmp; + // ADD + case X86::ADD16i16: + case X86::ADD16ri: + case X86::ADD16ri8: + case X86::ADD16rm: + case X86::ADD16rr: + case X86::ADD16rr_REV: + case X86::ADD32i32: + case X86::ADD32ri: + case X86::ADD32ri8: + case X86::ADD32rm: + case X86::ADD32rr: + case X86::ADD32rr_REV: + case X86::ADD64i32: + case X86::ADD64ri32: + case X86::ADD64ri8: + case X86::ADD64rm: + case X86::ADD64rr: + case X86::ADD64rr_REV: + case X86::ADD8i8: + case X86::ADD8ri: + case X86::ADD8ri8: + case X86::ADD8rm: + case X86::ADD8rr: + case X86::ADD8rr_REV: + // SUB + case X86::SUB16i16: + case X86::SUB16ri: + case X86::SUB16ri8: + case X86::SUB16rm: + case X86::SUB16rr: + case X86::SUB16rr_REV: + case X86::SUB32i32: + case X86::SUB32ri: + case X86::SUB32ri8: + case X86::SUB32rm: + case X86::SUB32rr: + case X86::SUB32rr_REV: + case X86::SUB64i32: + case X86::SUB64ri32: + case X86::SUB64ri8: + case X86::SUB64rm: + case X86::SUB64rr: + case X86::SUB64rr_REV: + case X86::SUB8i8: + case X86::SUB8ri: + case X86::SUB8ri8: + case X86::SUB8rm: + case X86::SUB8rr: + case X86::SUB8rr_REV: + return FirstMacroFusionInstKind::AddSub; + // INC + case X86::INC16r: + case X86::INC16r_alt: + case X86::INC32r: + case X86::INC32r_alt: + case X86::INC64r: + case X86::INC8r: + // DEC + case X86::DEC16r: + case X86::DEC16r_alt: + case X86::DEC32r: + case X86::DEC32r_alt: + case X86::DEC64r: + case X86::DEC8r: + return FirstMacroFusionInstKind::IncDec; + } + } + + /// \returns the type of the second instruction in macro-fusion. + inline SecondMacroFusionInstKind + classifySecondCondCodeInMacroFusion(X86::CondCode CC) { + if (CC == X86::COND_INVALID) + return SecondMacroFusionInstKind::Invalid; + + switch (CC) { + default: + return SecondMacroFusionInstKind::Invalid; + // JE,JZ + case X86::COND_E: + // JNE,JNZ + case X86::COND_NE: + // JL,JNGE + case X86::COND_L: + // JLE,JNG + case X86::COND_LE: + // JG,JNLE + case X86::COND_G: + // JGE,JNL + case X86::COND_GE: + return SecondMacroFusionInstKind::ELG; + // JB,JC + case X86::COND_B: + // JNA,JBE + case X86::COND_BE: + // JA,JNBE + case X86::COND_A: + // JAE,JNC,JNB + case X86::COND_AE: + return SecondMacroFusionInstKind::AB; + // JS + case X86::COND_S: + // JNS + case X86::COND_NS: + // JP,JPE + case X86::COND_P: + // JNP,JPO + case X86::COND_NP: + // JO + case X86::COND_O: + // JNO + case X86::COND_NO: + return SecondMacroFusionInstKind::SPO; + } + } + + /// \param FirstKind kind of the first instruction in macro fusion. + /// \param SecondKind kind of the second instruction in macro fusion. + /// + /// \returns true if the two instruction can be macro fused. + inline bool isMacroFused(FirstMacroFusionInstKind FirstKind, + SecondMacroFusionInstKind SecondKind) { + switch (FirstKind) { + case X86::FirstMacroFusionInstKind::Test: + case X86::FirstMacroFusionInstKind::And: + return true; + case X86::FirstMacroFusionInstKind::Cmp: + case X86::FirstMacroFusionInstKind::AddSub: + return SecondKind == X86::SecondMacroFusionInstKind::AB || + SecondKind == X86::SecondMacroFusionInstKind::ELG; + case X86::FirstMacroFusionInstKind::IncDec: + return SecondKind == X86::SecondMacroFusionInstKind::ELG; + case X86::FirstMacroFusionInstKind::Invalid: + return false; + } + llvm_unreachable("unknown fusion type"); + } + + /// Defines the possible values of the branch boundary alignment mask. + enum AlignBranchBoundaryKind : uint8_t { + AlignBranchNone = 0, + AlignBranchFused = 1U << 0, + AlignBranchJcc = 1U << 1, + AlignBranchJmp = 1U << 2, + AlignBranchCall = 1U << 3, + AlignBranchRet = 1U << 4, + AlignBranchIndirect = 1U << 5 + }; } // end namespace X86; /// X86II - This namespace holds all of the target specific flags that @@ -645,9 +900,8 @@ namespace X86II { NOTRACK = 1ULL << NoTrackShift }; - // getBaseOpcodeFor - This function returns the "base" X86 opcode for the - // specified machine instruction. - // + /// \returns the "base" X86 opcode for the specified machine + /// instruction. inline uint8_t getBaseOpcodeFor(uint64_t TSFlags) { return TSFlags >> X86II::OpcodeShift; } @@ -656,8 +910,8 @@ namespace X86II { return (TSFlags & X86II::ImmMask) != 0; } - /// getSizeOfImm - Decode the "size of immediate" field from the TSFlags field - /// of the specified instruction. + /// Decode the "size of immediate" field from the TSFlags field of the + /// specified instruction. inline unsigned getSizeOfImm(uint64_t TSFlags) { switch (TSFlags & X86II::ImmMask) { default: llvm_unreachable("Unknown immediate size"); @@ -673,9 +927,9 @@ namespace X86II { } } - /// isImmPCRel - Return true if the immediate of the specified instruction's - /// TSFlags indicates that it is pc relative. - inline unsigned isImmPCRel(uint64_t TSFlags) { + /// \returns true if the immediate of the specified instruction's TSFlags + /// indicates that it is pc relative. + inline bool isImmPCRel(uint64_t TSFlags) { switch (TSFlags & X86II::ImmMask) { default: llvm_unreachable("Unknown immediate size"); case X86II::Imm8PCRel: @@ -692,9 +946,9 @@ namespace X86II { } } - /// isImmSigned - Return true if the immediate of the specified instruction's + /// \returns true if the immediate of the specified instruction's /// TSFlags indicates that it is signed. - inline unsigned isImmSigned(uint64_t TSFlags) { + inline bool isImmSigned(uint64_t TSFlags) { switch (TSFlags & X86II::ImmMask) { default: llvm_unreachable("Unknown immediate signedness"); case X86II::Imm32S: @@ -711,8 +965,8 @@ namespace X86II { } } - /// getOperandBias - compute whether all of the def operands are repeated - /// in the uses and therefore should be skipped. + /// Compute whether all of the def operands are repeated in the uses and + /// therefore should be skipped. /// This determines the start of the unique operand list. We need to determine /// if all of the defs have a corresponding tied operand in the uses. /// Unfortunately, the tied operand information is encoded in the uses not @@ -750,8 +1004,8 @@ namespace X86II { } } - /// getMemoryOperandNo - The function returns the MCInst operand # for the - /// first field of the memory operand. If the instruction doesn't have a + /// The function returns the MCInst operand # for the first field of the + /// memory operand. If the instruction doesn't have a /// memory operand, this returns -1. /// /// Note that this ignores tied operands. If there is a tied register which @@ -837,8 +1091,8 @@ namespace X86II { } } - /// isX86_64ExtendedReg - Is the MachineOperand a x86-64 extended (r8 or - /// higher) register? e.g. r8, xmm8, xmm13, etc. + /// \returns true if the MachineOperand is a x86-64 extended (r8 or + /// higher) register, e.g. r8, xmm8, xmm13, etc. inline bool isX86_64ExtendedReg(unsigned RegNo) { if ((RegNo >= X86::XMM8 && RegNo <= X86::XMM31) || (RegNo >= X86::YMM8 && RegNo <= X86::YMM31) || @@ -864,8 +1118,8 @@ namespace X86II { return false; } - /// is32ExtendedReg - Is the MemoryOperand a 32 extended (zmm16 or higher) - /// registers? e.g. zmm21, etc. + /// \returns true if the MemoryOperand is a 32 extended (zmm16 or higher) + /// registers, e.g. zmm21, etc. static inline bool is32ExtendedReg(unsigned RegNo) { return ((RegNo >= X86::XMM16 && RegNo <= X86::XMM31) || (RegNo >= X86::YMM16 && RegNo <= X86::YMM31) || @@ -878,12 +1132,12 @@ namespace X86II { reg == X86::SIL || reg == X86::DIL); } - /// isKMasked - Is this a masked instruction. + /// \returns true if this is a masked instruction. inline bool isKMasked(uint64_t TSFlags) { return (TSFlags & X86II::EVEX_K) != 0; } - /// isKMergedMasked - Is this a merge masked instruction. + /// \returns true if this is a merge masked instruction. inline bool isKMergeMasked(uint64_t TSFlags) { return isKMasked(TSFlags) && (TSFlags & X86II::EVEX_Z) == 0; } diff --git a/llvm/lib/Target/X86/MCTargetDesc/X86IntelInstPrinter.cpp b/llvm/lib/Target/X86/MCTargetDesc/X86IntelInstPrinter.cpp index ea28bef42569..f4bb0fbf62cd 100644 --- a/llvm/lib/Target/X86/MCTargetDesc/X86IntelInstPrinter.cpp +++ b/llvm/lib/Target/X86/MCTargetDesc/X86IntelInstPrinter.cpp @@ -36,9 +36,9 @@ void X86IntelInstPrinter::printRegName(raw_ostream &OS, unsigned RegNo) const { OS << getRegisterName(RegNo); } -void X86IntelInstPrinter::printInst(const MCInst *MI, raw_ostream &OS, - StringRef Annot, - const MCSubtargetInfo &STI) { +void X86IntelInstPrinter::printInst(const MCInst *MI, uint64_t Address, + StringRef Annot, const MCSubtargetInfo &STI, + raw_ostream &OS) { printInstFlags(MI, OS); // In 16-bit mode, print data16 as data32. @@ -47,7 +47,7 @@ void X86IntelInstPrinter::printInst(const MCInst *MI, raw_ostream &OS, OS << "\tdata32"; } else if (!printAliasInstr(MI, OS) && !printVecCompareInstr(MI, OS)) - printInstruction(MI, OS); + printInstruction(MI, Address, OS); // Next always print the annotation. printAnnotation(OS, Annot); diff --git a/llvm/lib/Target/X86/MCTargetDesc/X86IntelInstPrinter.h b/llvm/lib/Target/X86/MCTargetDesc/X86IntelInstPrinter.h index f32f49f7c417..b409b20cbea8 100644 --- a/llvm/lib/Target/X86/MCTargetDesc/X86IntelInstPrinter.h +++ b/llvm/lib/Target/X86/MCTargetDesc/X86IntelInstPrinter.h @@ -25,8 +25,8 @@ public: : X86InstPrinterCommon(MAI, MII, MRI) {} void printRegName(raw_ostream &OS, unsigned RegNo) const override; - void printInst(const MCInst *MI, raw_ostream &OS, StringRef Annot, - const MCSubtargetInfo &STI) override; + void printInst(const MCInst *MI, uint64_t Address, StringRef Annot, + const MCSubtargetInfo &STI, raw_ostream &OS) override; bool printVecCompareInstr(const MCInst *MI, raw_ostream &OS); // Autogenerated by tblgen, returns true if we successfully printed an @@ -36,7 +36,7 @@ public: unsigned PrintMethodIdx, raw_ostream &O); // Autogenerated by tblgen. - void printInstruction(const MCInst *MI, raw_ostream &O); + void printInstruction(const MCInst *MI, uint64_t Address, raw_ostream &O); static const char *getRegisterName(unsigned RegNo); void printOperand(const MCInst *MI, unsigned OpNo, raw_ostream &O) override; diff --git a/llvm/lib/Target/X86/MCTargetDesc/X86MCCodeEmitter.cpp b/llvm/lib/Target/X86/MCTargetDesc/X86MCCodeEmitter.cpp index ac36bf3a12fa..54a293702bd0 100644 --- a/llvm/lib/Target/X86/MCTargetDesc/X86MCCodeEmitter.cpp +++ b/llvm/lib/Target/X86/MCTargetDesc/X86MCCodeEmitter.cpp @@ -42,91 +42,68 @@ class X86MCCodeEmitter : public MCCodeEmitter { public: X86MCCodeEmitter(const MCInstrInfo &mcii, MCContext &ctx) - : MCII(mcii), Ctx(ctx) { - } + : MCII(mcii), Ctx(ctx) {} X86MCCodeEmitter(const X86MCCodeEmitter &) = delete; X86MCCodeEmitter &operator=(const X86MCCodeEmitter &) = delete; ~X86MCCodeEmitter() override = default; - bool is64BitMode(const MCSubtargetInfo &STI) const { - return STI.getFeatureBits()[X86::Mode64Bit]; - } - - bool is32BitMode(const MCSubtargetInfo &STI) const { - return STI.getFeatureBits()[X86::Mode32Bit]; - } - - bool is16BitMode(const MCSubtargetInfo &STI) const { - return STI.getFeatureBits()[X86::Mode16Bit]; - } - - /// Is16BitMemOperand - Return true if the specified instruction has - /// a 16-bit memory operand. Op specifies the operand # of the memoperand. - bool Is16BitMemOperand(const MCInst &MI, unsigned Op, - const MCSubtargetInfo &STI) const { - const MCOperand &BaseReg = MI.getOperand(Op+X86::AddrBaseReg); - const MCOperand &IndexReg = MI.getOperand(Op+X86::AddrIndexReg); - const MCOperand &Disp = MI.getOperand(Op+X86::AddrDisp); + void emitPrefix(const MCInst &MI, raw_ostream &OS, + const MCSubtargetInfo &STI) const override; - if (is16BitMode(STI) && BaseReg.getReg() == 0 && - Disp.isImm() && Disp.getImm() < 0x10000) - return true; - if ((BaseReg.getReg() != 0 && - X86MCRegisterClasses[X86::GR16RegClassID].contains(BaseReg.getReg())) || - (IndexReg.getReg() != 0 && - X86MCRegisterClasses[X86::GR16RegClassID].contains(IndexReg.getReg()))) - return true; - return false; - } + void encodeInstruction(const MCInst &MI, raw_ostream &OS, + SmallVectorImpl<MCFixup> &Fixups, + const MCSubtargetInfo &STI) const override; - unsigned GetX86RegNum(const MCOperand &MO) const { +private: + unsigned getX86RegNum(const MCOperand &MO) const { return Ctx.getRegisterInfo()->getEncodingValue(MO.getReg()) & 0x7; } unsigned getX86RegEncoding(const MCInst &MI, unsigned OpNum) const { return Ctx.getRegisterInfo()->getEncodingValue( - MI.getOperand(OpNum).getReg()); + MI.getOperand(OpNum).getReg()); } - // Does this register require a bit to be set in REX prefix. + /// \param MI a single low-level machine instruction. + /// \param OpNum the operand #. + /// \returns true if the OpNumth operand of MI require a bit to be set in + /// REX prefix. bool isREXExtendedReg(const MCInst &MI, unsigned OpNum) const { return (getX86RegEncoding(MI, OpNum) >> 3) & 1; } - void EmitByte(uint8_t C, unsigned &CurByte, raw_ostream &OS) const { + void emitByte(uint8_t C, unsigned &CurByte, raw_ostream &OS) const { OS << (char)C; ++CurByte; } - void EmitConstant(uint64_t Val, unsigned Size, unsigned &CurByte, + void emitConstant(uint64_t Val, unsigned Size, unsigned &CurByte, raw_ostream &OS) const { // Output the constant in little endian byte order. for (unsigned i = 0; i != Size; ++i) { - EmitByte(Val & 255, CurByte, OS); + emitByte(Val & 255, CurByte, OS); Val >>= 8; } } - void EmitImmediate(const MCOperand &Disp, SMLoc Loc, - unsigned ImmSize, MCFixupKind FixupKind, - unsigned &CurByte, raw_ostream &OS, - SmallVectorImpl<MCFixup> &Fixups, - int ImmOffset = 0) const; + void emitImmediate(const MCOperand &Disp, SMLoc Loc, unsigned ImmSize, + MCFixupKind FixupKind, unsigned &CurByte, raw_ostream &OS, + SmallVectorImpl<MCFixup> &Fixups, int ImmOffset = 0) const; - static uint8_t ModRMByte(unsigned Mod, unsigned RegOpcode, unsigned RM) { + static uint8_t modRMByte(unsigned Mod, unsigned RegOpcode, unsigned RM) { assert(Mod < 4 && RegOpcode < 8 && RM < 8 && "ModRM Fields out of range!"); return RM | (RegOpcode << 3) | (Mod << 6); } - void EmitRegModRMByte(const MCOperand &ModRMReg, unsigned RegOpcodeFld, + void emitRegModRMByte(const MCOperand &ModRMReg, unsigned RegOpcodeFld, unsigned &CurByte, raw_ostream &OS) const { - EmitByte(ModRMByte(3, RegOpcodeFld, GetX86RegNum(ModRMReg)), CurByte, OS); + emitByte(modRMByte(3, RegOpcodeFld, getX86RegNum(ModRMReg)), CurByte, OS); } - void EmitSIBByte(unsigned SS, unsigned Index, unsigned Base, + void emitSIBByte(unsigned SS, unsigned Index, unsigned Base, unsigned &CurByte, raw_ostream &OS) const { - // SIB byte is in the same format as the ModRMByte. - EmitByte(ModRMByte(SS, Index, Base), CurByte, OS); + // SIB byte is in the same format as the modRMByte. + emitByte(modRMByte(SS, Index, Base), CurByte, OS); } void emitMemModRMByte(const MCInst &MI, unsigned Op, unsigned RegOpcodeField, @@ -134,43 +111,39 @@ public: raw_ostream &OS, SmallVectorImpl<MCFixup> &Fixups, const MCSubtargetInfo &STI) const; - void encodeInstruction(const MCInst &MI, raw_ostream &OS, - SmallVectorImpl<MCFixup> &Fixups, - const MCSubtargetInfo &STI) const override; + void emitPrefixImpl(uint64_t TSFlags, unsigned &CurOp, unsigned &CurByte, + bool &Rex, const MCInst &MI, const MCInstrDesc &Desc, + const MCSubtargetInfo &STI, raw_ostream &OS) const; - void EmitVEXOpcodePrefix(uint64_t TSFlags, unsigned &CurByte, int MemOperand, + void emitVEXOpcodePrefix(uint64_t TSFlags, unsigned &CurByte, int MemOperand, const MCInst &MI, const MCInstrDesc &Desc, raw_ostream &OS) const; - void EmitSegmentOverridePrefix(unsigned &CurByte, unsigned SegOperand, + void emitSegmentOverridePrefix(unsigned &CurByte, unsigned SegOperand, const MCInst &MI, raw_ostream &OS) const; bool emitOpcodePrefix(uint64_t TSFlags, unsigned &CurByte, int MemOperand, const MCInst &MI, const MCInstrDesc &Desc, const MCSubtargetInfo &STI, raw_ostream &OS) const; - uint8_t DetermineREXPrefix(const MCInst &MI, uint64_t TSFlags, - int MemOperand, const MCInstrDesc &Desc) const; - - bool isPCRel32Branch(const MCInst &MI) const; + uint8_t determineREXPrefix(const MCInst &MI, uint64_t TSFlags, int MemOperand, + const MCInstrDesc &Desc) const; }; } // end anonymous namespace -/// isDisp8 - Return true if this signed displacement fits in a 8-bit -/// sign-extended field. -static bool isDisp8(int Value) { - return Value == (int8_t)Value; -} +/// \returns true if this signed displacement fits in a 8-bit sign-extended +/// field. +static bool isDisp8(int Value) { return Value == (int8_t)Value; } -/// isCDisp8 - Return true if this signed displacement fits in a 8-bit -/// compressed dispacement field. -static bool isCDisp8(uint64_t TSFlags, int Value, int& CValue) { +/// \returns true if this signed displacement fits in a 8-bit compressed +/// dispacement field. +static bool isCDisp8(uint64_t TSFlags, int Value, int &CValue) { assert(((TSFlags & X86II::EncodingMask) == X86II::EVEX) && "Compressed 8-bit displacement is only valid for EVEX inst."); unsigned CD8_Scale = - (TSFlags & X86II::CD8_Scale_Mask) >> X86II::CD8_Scale_Shift; + (TSFlags & X86II::CD8_Scale_Mask) >> X86II::CD8_Scale_Shift; if (CD8_Scale == 0) { CValue = Value; return isDisp8(Value); @@ -188,26 +161,49 @@ static bool isCDisp8(uint64_t TSFlags, int Value, int& CValue) { return Ret; } -/// getImmFixupKind - Return the appropriate fixup kind to use for an immediate -/// in an instruction with the specified TSFlags. +/// \returns the appropriate fixup kind to use for an immediate in an +/// instruction with the specified TSFlags. static MCFixupKind getImmFixupKind(uint64_t TSFlags) { unsigned Size = X86II::getSizeOfImm(TSFlags); bool isPCRel = X86II::isImmPCRel(TSFlags); if (X86II::isImmSigned(TSFlags)) { switch (Size) { - default: llvm_unreachable("Unsupported signed fixup size!"); - case 4: return MCFixupKind(X86::reloc_signed_4byte); + default: + llvm_unreachable("Unsupported signed fixup size!"); + case 4: + return MCFixupKind(X86::reloc_signed_4byte); } } return MCFixup::getKindForSize(Size, isPCRel); } -/// Is32BitMemOperand - Return true if the specified instruction has -/// a 32-bit memory operand. Op specifies the operand # of the memoperand. -static bool Is32BitMemOperand(const MCInst &MI, unsigned Op) { - const MCOperand &BaseReg = MI.getOperand(Op+X86::AddrBaseReg); - const MCOperand &IndexReg = MI.getOperand(Op+X86::AddrIndexReg); +/// \param Op operand # of the memory operand. +/// +/// \returns true if the specified instruction has a 16-bit memory operand. +static bool is16BitMemOperand(const MCInst &MI, unsigned Op, + const MCSubtargetInfo &STI) { + const MCOperand &BaseReg = MI.getOperand(Op + X86::AddrBaseReg); + const MCOperand &IndexReg = MI.getOperand(Op + X86::AddrIndexReg); + const MCOperand &Disp = MI.getOperand(Op + X86::AddrDisp); + + if (STI.hasFeature(X86::Mode16Bit) && BaseReg.getReg() == 0 && Disp.isImm() && + Disp.getImm() < 0x10000) + return true; + if ((BaseReg.getReg() != 0 && + X86MCRegisterClasses[X86::GR16RegClassID].contains(BaseReg.getReg())) || + (IndexReg.getReg() != 0 && + X86MCRegisterClasses[X86::GR16RegClassID].contains(IndexReg.getReg()))) + return true; + return false; +} + +/// \param Op operand # of the memory operand. +/// +/// \returns true if the specified instruction has a 32-bit memory operand. +static bool is32BitMemOperand(const MCInst &MI, unsigned Op) { + const MCOperand &BaseReg = MI.getOperand(Op + X86::AddrBaseReg); + const MCOperand &IndexReg = MI.getOperand(Op + X86::AddrIndexReg); if ((BaseReg.getReg() != 0 && X86MCRegisterClasses[X86::GR32RegClassID].contains(BaseReg.getReg())) || @@ -223,12 +219,13 @@ static bool Is32BitMemOperand(const MCInst &MI, unsigned Op) { return false; } -/// Is64BitMemOperand - Return true if the specified instruction has -/// a 64-bit memory operand. Op specifies the operand # of the memoperand. +/// \param Op operand # of the memory operand. +/// +/// \returns true if the specified instruction has a 64-bit memory operand. #ifndef NDEBUG -static bool Is64BitMemOperand(const MCInst &MI, unsigned Op) { - const MCOperand &BaseReg = MI.getOperand(Op+X86::AddrBaseReg); - const MCOperand &IndexReg = MI.getOperand(Op+X86::AddrIndexReg); +static bool is64BitMemOperand(const MCInst &MI, unsigned Op) { + const MCOperand &BaseReg = MI.getOperand(Op + X86::AddrBaseReg); + const MCOperand &IndexReg = MI.getOperand(Op + X86::AddrIndexReg); if ((BaseReg.getReg() != 0 && X86MCRegisterClasses[X86::GR64RegClassID].contains(BaseReg.getReg())) || @@ -239,19 +236,15 @@ static bool Is64BitMemOperand(const MCInst &MI, unsigned Op) { } #endif -/// StartsWithGlobalOffsetTable - Check if this expression starts with -/// _GLOBAL_OFFSET_TABLE_ and if it is of the form -/// _GLOBAL_OFFSET_TABLE_-symbol. This is needed to support PIC on ELF -/// i386 as _GLOBAL_OFFSET_TABLE_ is magical. We check only simple case that -/// are know to be used: _GLOBAL_OFFSET_TABLE_ by itself or at the start -/// of a binary expression. -enum GlobalOffsetTableExprKind { - GOT_None, - GOT_Normal, - GOT_SymDiff -}; +enum GlobalOffsetTableExprKind { GOT_None, GOT_Normal, GOT_SymDiff }; + +/// Check if this expression starts with _GLOBAL_OFFSET_TABLE_ and if it is +/// of the form _GLOBAL_OFFSET_TABLE_-symbol. This is needed to support PIC on +/// ELF i386 as _GLOBAL_OFFSET_TABLE_ is magical. We check only simple case that +/// are know to be used: _GLOBAL_OFFSET_TABLE_ by itself or at the start of a +/// binary expression. static GlobalOffsetTableExprKind -StartsWithGlobalOffsetTable(const MCExpr *Expr) { +startsWithGlobalOffsetTable(const MCExpr *Expr) { const MCExpr *RHS = nullptr; if (Expr->getKind() == MCExpr::Binary) { const MCBinaryExpr *BE = static_cast<const MCBinaryExpr *>(Expr); @@ -262,7 +255,7 @@ StartsWithGlobalOffsetTable(const MCExpr *Expr) { if (Expr->getKind() != MCExpr::SymbolRef) return GOT_None; - const MCSymbolRefExpr *Ref = static_cast<const MCSymbolRefExpr*>(Expr); + const MCSymbolRefExpr *Ref = static_cast<const MCSymbolRefExpr *>(Expr); const MCSymbol &S = Ref->getSymbol(); if (S.getName() != "_GLOBAL_OFFSET_TABLE_") return GOT_None; @@ -271,15 +264,15 @@ StartsWithGlobalOffsetTable(const MCExpr *Expr) { return GOT_Normal; } -static bool HasSecRelSymbolRef(const MCExpr *Expr) { +static bool hasSecRelSymbolRef(const MCExpr *Expr) { if (Expr->getKind() == MCExpr::SymbolRef) { - const MCSymbolRefExpr *Ref = static_cast<const MCSymbolRefExpr*>(Expr); + const MCSymbolRefExpr *Ref = static_cast<const MCSymbolRefExpr *>(Expr); return Ref->getKind() == MCSymbolRefExpr::VK_SECREL; } return false; } -bool X86MCCodeEmitter::isPCRel32Branch(const MCInst &MI) const { +static bool isPCRel32Branch(const MCInst &MI, const MCInstrInfo &MCII) { unsigned Opcode = MI.getOpcode(); const MCInstrDesc &Desc = MCII.get(Opcode); if ((Opcode != X86::CALL64pcrel32 && Opcode != X86::JMP_4) || @@ -295,18 +288,18 @@ bool X86MCCodeEmitter::isPCRel32Branch(const MCInst &MI) const { return Ref && Ref->getKind() == MCSymbolRefExpr::VK_None; } -void X86MCCodeEmitter:: -EmitImmediate(const MCOperand &DispOp, SMLoc Loc, unsigned Size, - MCFixupKind FixupKind, unsigned &CurByte, raw_ostream &OS, - SmallVectorImpl<MCFixup> &Fixups, int ImmOffset) const { +void X86MCCodeEmitter::emitImmediate(const MCOperand &DispOp, SMLoc Loc, + unsigned Size, MCFixupKind FixupKind, + unsigned &CurByte, raw_ostream &OS, + SmallVectorImpl<MCFixup> &Fixups, + int ImmOffset) const { const MCExpr *Expr = nullptr; if (DispOp.isImm()) { // If this is a simple integer displacement that doesn't require a // relocation, emit it now. - if (FixupKind != FK_PCRel_1 && - FixupKind != FK_PCRel_2 && + if (FixupKind != FK_PCRel_1 && FixupKind != FK_PCRel_2 && FixupKind != FK_PCRel_4) { - EmitConstant(DispOp.getImm()+ImmOffset, Size, CurByte, OS); + emitConstant(DispOp.getImm() + ImmOffset, Size, CurByte, OS); return; } Expr = MCConstantExpr::create(DispOp.getImm(), Ctx); @@ -315,10 +308,9 @@ EmitImmediate(const MCOperand &DispOp, SMLoc Loc, unsigned Size, } // If we have an immoffset, add it to the expression. - if ((FixupKind == FK_Data_4 || - FixupKind == FK_Data_8 || + if ((FixupKind == FK_Data_4 || FixupKind == FK_Data_8 || FixupKind == MCFixupKind(X86::reloc_signed_4byte))) { - GlobalOffsetTableExprKind Kind = StartsWithGlobalOffsetTable(Expr); + GlobalOffsetTableExprKind Kind = startsWithGlobalOffsetTable(Expr); if (Kind != GOT_None) { assert(ImmOffset == 0); @@ -332,13 +324,13 @@ EmitImmediate(const MCOperand &DispOp, SMLoc Loc, unsigned Size, if (Kind == GOT_Normal) ImmOffset = CurByte; } else if (Expr->getKind() == MCExpr::SymbolRef) { - if (HasSecRelSymbolRef(Expr)) { + if (hasSecRelSymbolRef(Expr)) { FixupKind = MCFixupKind(FK_SecRel_4); } } else if (Expr->getKind() == MCExpr::Binary) { - const MCBinaryExpr *Bin = static_cast<const MCBinaryExpr*>(Expr); - if (HasSecRelSymbolRef(Bin->getLHS()) - || HasSecRelSymbolRef(Bin->getRHS())) { + const MCBinaryExpr *Bin = static_cast<const MCBinaryExpr *>(Expr); + if (hasSecRelSymbolRef(Bin->getLHS()) || + hasSecRelSymbolRef(Bin->getRHS())) { FixupKind = MCFixupKind(FK_SecRel_4); } } @@ -356,7 +348,7 @@ EmitImmediate(const MCOperand &DispOp, SMLoc Loc, unsigned Size, // If this is a pc-relative load off _GLOBAL_OFFSET_TABLE_: // leaq _GLOBAL_OFFSET_TABLE_(%rip), %r15 // this needs to be a GOTPC32 relocation. - if (StartsWithGlobalOffsetTable(Expr) != GOT_None) + if (startsWithGlobalOffsetTable(Expr) != GOT_None) FixupKind = MCFixupKind(X86::reloc_global_offset_table); } if (FixupKind == FK_PCRel_2) @@ -370,7 +362,7 @@ EmitImmediate(const MCOperand &DispOp, SMLoc Loc, unsigned Size, // Emit a symbolic constant as a fixup and 4 zeros. Fixups.push_back(MCFixup::create(CurByte, Expr, FixupKind, Loc)); - EmitConstant(0, Size, CurByte, OS); + emitConstant(0, Size, CurByte, OS); } void X86MCCodeEmitter::emitMemModRMByte(const MCInst &MI, unsigned Op, @@ -379,19 +371,20 @@ void X86MCCodeEmitter::emitMemModRMByte(const MCInst &MI, unsigned Op, unsigned &CurByte, raw_ostream &OS, SmallVectorImpl<MCFixup> &Fixups, const MCSubtargetInfo &STI) const { - const MCOperand &Disp = MI.getOperand(Op+X86::AddrDisp); - const MCOperand &Base = MI.getOperand(Op+X86::AddrBaseReg); - const MCOperand &Scale = MI.getOperand(Op+X86::AddrScaleAmt); - const MCOperand &IndexReg = MI.getOperand(Op+X86::AddrIndexReg); + const MCOperand &Disp = MI.getOperand(Op + X86::AddrDisp); + const MCOperand &Base = MI.getOperand(Op + X86::AddrBaseReg); + const MCOperand &Scale = MI.getOperand(Op + X86::AddrScaleAmt); + const MCOperand &IndexReg = MI.getOperand(Op + X86::AddrIndexReg); unsigned BaseReg = Base.getReg(); bool HasEVEX = (TSFlags & X86II::EncodingMask) == X86II::EVEX; // Handle %rip relative addressing. if (BaseReg == X86::RIP || - BaseReg == X86::EIP) { // [disp32+rIP] in X86-64 mode - assert(is64BitMode(STI) && "Rip-relative addressing requires 64-bit mode"); + BaseReg == X86::EIP) { // [disp32+rIP] in X86-64 mode + assert(STI.hasFeature(X86::Mode64Bit) && + "Rip-relative addressing requires 64-bit mode"); assert(IndexReg.getReg() == 0 && "Invalid rip-relative address"); - EmitByte(ModRMByte(0, RegOpcodeField, 5), CurByte, OS); + emitByte(modRMByte(0, RegOpcodeField, 5), CurByte, OS); unsigned Opcode = MI.getOpcode(); // movq loads are handled with a special relocation form which allows the @@ -432,20 +425,20 @@ void X86MCCodeEmitter::emitMemModRMByte(const MCInst &MI, unsigned Op, ? X86II::getSizeOfImm(TSFlags) : 0; - EmitImmediate(Disp, MI.getLoc(), 4, MCFixupKind(FixupKind), - CurByte, OS, Fixups, -ImmSize); + emitImmediate(Disp, MI.getLoc(), 4, MCFixupKind(FixupKind), CurByte, OS, + Fixups, -ImmSize); return; } - unsigned BaseRegNo = BaseReg ? GetX86RegNum(Base) : -1U; + unsigned BaseRegNo = BaseReg ? getX86RegNum(Base) : -1U; // 16-bit addressing forms of the ModR/M byte have a different encoding for // the R/M field and are far more limited in which registers can be used. - if (Is16BitMemOperand(MI, Op, STI)) { + if (is16BitMemOperand(MI, Op, STI)) { if (BaseReg) { // For 32-bit addressing, the row and column values in Table 2-2 are // basically the same. It's AX/CX/DX/BX/SP/BP/SI/DI in that order, with - // some special cases. And GetX86RegNum reflects that numbering. + // some special cases. And getX86RegNum reflects that numbering. // For 16-bit addressing it's more fun, as shown in the SDM Vol 2A, // Table 2-1 "16-Bit Addressing Forms with the ModR/M byte". We can only // use SI/DI/BP/BX, which have "row" values 4-7 in no particular order, @@ -454,13 +447,13 @@ void X86MCCodeEmitter::emitMemModRMByte(const MCInst &MI, unsigned Op, // // R16Table[] is a lookup from the normal RegNo, to the row values from // Table 2-1 for 16-bit addressing modes. Where zero means disallowed. - static const unsigned R16Table[] = { 0, 0, 0, 7, 0, 6, 4, 5 }; + static const unsigned R16Table[] = {0, 0, 0, 7, 0, 6, 4, 5}; unsigned RMfield = R16Table[BaseRegNo]; assert(RMfield && "invalid 16-bit base register"); if (IndexReg.getReg()) { - unsigned IndexReg16 = R16Table[GetX86RegNum(IndexReg)]; + unsigned IndexReg16 = R16Table[getX86RegNum(IndexReg)]; assert(IndexReg16 && "invalid 16-bit index register"); // We must have one of SI/DI (4,5), and one of BP/BX (6,7). @@ -479,23 +472,23 @@ void X86MCCodeEmitter::emitMemModRMByte(const MCInst &MI, unsigned Op, if (Disp.isImm() && isDisp8(Disp.getImm())) { if (Disp.getImm() == 0 && RMfield != 6) { // There is no displacement; just the register. - EmitByte(ModRMByte(0, RegOpcodeField, RMfield), CurByte, OS); + emitByte(modRMByte(0, RegOpcodeField, RMfield), CurByte, OS); return; } // Use the [REG]+disp8 form, including for [BP] which cannot be encoded. - EmitByte(ModRMByte(1, RegOpcodeField, RMfield), CurByte, OS); - EmitImmediate(Disp, MI.getLoc(), 1, FK_Data_1, CurByte, OS, Fixups); + emitByte(modRMByte(1, RegOpcodeField, RMfield), CurByte, OS); + emitImmediate(Disp, MI.getLoc(), 1, FK_Data_1, CurByte, OS, Fixups); return; } // This is the [REG]+disp16 case. - EmitByte(ModRMByte(2, RegOpcodeField, RMfield), CurByte, OS); + emitByte(modRMByte(2, RegOpcodeField, RMfield), CurByte, OS); } else { // There is no BaseReg; this is the plain [disp16] case. - EmitByte(ModRMByte(0, RegOpcodeField, 6), CurByte, OS); + emitByte(modRMByte(0, RegOpcodeField, 6), CurByte, OS); } // Emit 16-bit displacement for plain disp16 or [REG]+disp16 cases. - EmitImmediate(Disp, MI.getLoc(), 2, FK_Data_2, CurByte, OS, Fixups); + emitImmediate(Disp, MI.getLoc(), 2, FK_Data_2, CurByte, OS, Fixups); return; } @@ -504,7 +497,7 @@ void X86MCCodeEmitter::emitMemModRMByte(const MCInst &MI, unsigned Op, // resolve addresses on-the-fly, otherwise use SIB (Intel Manual 2A, table // 2-7) and absolute references. - if (// The SIB byte must be used if there is an index register. + if ( // The SIB byte must be used if there is an index register. IndexReg.getReg() == 0 && // The SIB byte must be used if the base is ESP/RSP/R12, all of which // encode to an R/M value of 4, which indicates that a SIB byte is @@ -512,11 +505,11 @@ void X86MCCodeEmitter::emitMemModRMByte(const MCInst &MI, unsigned Op, BaseRegNo != N86::ESP && // If there is no base register and we're in 64-bit mode, we need a SIB // byte to emit an addr that is just 'disp32' (the non-RIP relative form). - (!is64BitMode(STI) || BaseReg != 0)) { + (!STI.hasFeature(X86::Mode64Bit) || BaseReg != 0)) { - if (BaseReg == 0) { // [disp32] in X86-32 mode - EmitByte(ModRMByte(0, RegOpcodeField, 5), CurByte, OS); - EmitImmediate(Disp, MI.getLoc(), 4, FK_Data_4, CurByte, OS, Fixups); + if (BaseReg == 0) { // [disp32] in X86-32 mode + emitByte(modRMByte(0, RegOpcodeField, 5), CurByte, OS); + emitImmediate(Disp, MI.getLoc(), 4, FK_Data_4, CurByte, OS, Fixups); return; } @@ -526,7 +519,7 @@ void X86MCCodeEmitter::emitMemModRMByte(const MCInst &MI, unsigned Op, // by emitting a displacement of 0 below. if (BaseRegNo != N86::EBP) { if (Disp.isImm() && Disp.getImm() == 0) { - EmitByte(ModRMByte(0, RegOpcodeField, BaseRegNo), CurByte, OS); + emitByte(modRMByte(0, RegOpcodeField, BaseRegNo), CurByte, OS); return; } @@ -537,7 +530,7 @@ void X86MCCodeEmitter::emitMemModRMByte(const MCInst &MI, unsigned Op, // This is exclusively used by call *a@tlscall(base). The relocation // (R_386_TLSCALL or R_X86_64_TLSCALL) applies to the beginning. Fixups.push_back(MCFixup::create(0, Sym, FK_NONE, MI.getLoc())); - EmitByte(ModRMByte(0, RegOpcodeField, BaseRegNo), CurByte, OS); + emitByte(modRMByte(0, RegOpcodeField, BaseRegNo), CurByte, OS); return; } } @@ -546,70 +539,70 @@ void X86MCCodeEmitter::emitMemModRMByte(const MCInst &MI, unsigned Op, // Otherwise, if the displacement fits in a byte, encode as [REG+disp8]. if (Disp.isImm()) { if (!HasEVEX && isDisp8(Disp.getImm())) { - EmitByte(ModRMByte(1, RegOpcodeField, BaseRegNo), CurByte, OS); - EmitImmediate(Disp, MI.getLoc(), 1, FK_Data_1, CurByte, OS, Fixups); + emitByte(modRMByte(1, RegOpcodeField, BaseRegNo), CurByte, OS); + emitImmediate(Disp, MI.getLoc(), 1, FK_Data_1, CurByte, OS, Fixups); return; } // Try EVEX compressed 8-bit displacement first; if failed, fall back to // 32-bit displacement. int CDisp8 = 0; if (HasEVEX && isCDisp8(TSFlags, Disp.getImm(), CDisp8)) { - EmitByte(ModRMByte(1, RegOpcodeField, BaseRegNo), CurByte, OS); - EmitImmediate(Disp, MI.getLoc(), 1, FK_Data_1, CurByte, OS, Fixups, + emitByte(modRMByte(1, RegOpcodeField, BaseRegNo), CurByte, OS); + emitImmediate(Disp, MI.getLoc(), 1, FK_Data_1, CurByte, OS, Fixups, CDisp8 - Disp.getImm()); return; } } // Otherwise, emit the most general non-SIB encoding: [REG+disp32] - EmitByte(ModRMByte(2, RegOpcodeField, BaseRegNo), CurByte, OS); + emitByte(modRMByte(2, RegOpcodeField, BaseRegNo), CurByte, OS); unsigned Opcode = MI.getOpcode(); unsigned FixupKind = Opcode == X86::MOV32rm ? X86::reloc_signed_4byte_relax : X86::reloc_signed_4byte; - EmitImmediate(Disp, MI.getLoc(), 4, MCFixupKind(FixupKind), CurByte, OS, + emitImmediate(Disp, MI.getLoc(), 4, MCFixupKind(FixupKind), CurByte, OS, Fixups); return; } // We need a SIB byte, so start by outputting the ModR/M byte first - assert(IndexReg.getReg() != X86::ESP && - IndexReg.getReg() != X86::RSP && "Cannot use ESP as index reg!"); + assert(IndexReg.getReg() != X86::ESP && IndexReg.getReg() != X86::RSP && + "Cannot use ESP as index reg!"); bool ForceDisp32 = false; - bool ForceDisp8 = false; + bool ForceDisp8 = false; int CDisp8 = 0; int ImmOffset = 0; if (BaseReg == 0) { // If there is no base register, we emit the special case SIB byte with // MOD=0, BASE=5, to JUST get the index, scale, and displacement. - EmitByte(ModRMByte(0, RegOpcodeField, 4), CurByte, OS); + emitByte(modRMByte(0, RegOpcodeField, 4), CurByte, OS); ForceDisp32 = true; } else if (!Disp.isImm()) { // Emit the normal disp32 encoding. - EmitByte(ModRMByte(2, RegOpcodeField, 4), CurByte, OS); + emitByte(modRMByte(2, RegOpcodeField, 4), CurByte, OS); ForceDisp32 = true; } else if (Disp.getImm() == 0 && // Base reg can't be anything that ends up with '5' as the base // reg, it is the magic [*] nomenclature that indicates no base. BaseRegNo != N86::EBP) { // Emit no displacement ModR/M byte - EmitByte(ModRMByte(0, RegOpcodeField, 4), CurByte, OS); + emitByte(modRMByte(0, RegOpcodeField, 4), CurByte, OS); } else if (!HasEVEX && isDisp8(Disp.getImm())) { // Emit the disp8 encoding. - EmitByte(ModRMByte(1, RegOpcodeField, 4), CurByte, OS); - ForceDisp8 = true; // Make sure to force 8 bit disp if Base=EBP + emitByte(modRMByte(1, RegOpcodeField, 4), CurByte, OS); + ForceDisp8 = true; // Make sure to force 8 bit disp if Base=EBP } else if (HasEVEX && isCDisp8(TSFlags, Disp.getImm(), CDisp8)) { // Emit the disp8 encoding. - EmitByte(ModRMByte(1, RegOpcodeField, 4), CurByte, OS); - ForceDisp8 = true; // Make sure to force 8 bit disp if Base=EBP + emitByte(modRMByte(1, RegOpcodeField, 4), CurByte, OS); + ForceDisp8 = true; // Make sure to force 8 bit disp if Base=EBP ImmOffset = CDisp8 - Disp.getImm(); } else { // Emit the normal disp32 encoding. - EmitByte(ModRMByte(2, RegOpcodeField, 4), CurByte, OS); + emitByte(modRMByte(2, RegOpcodeField, 4), CurByte, OS); } // Calculate what the SS field value should be... - static const unsigned SSTable[] = { ~0U, 0, 1, ~0U, 2, ~0U, ~0U, ~0U, 3 }; + static const unsigned SSTable[] = {~0U, 0, 1, ~0U, 2, ~0U, ~0U, ~0U, 3}; unsigned SS = SSTable[Scale.getImm()]; if (BaseReg == 0) { @@ -617,30 +610,133 @@ void X86MCCodeEmitter::emitMemModRMByte(const MCInst &MI, unsigned Op, // Manual 2A, table 2-7. The displacement has already been output. unsigned IndexRegNo; if (IndexReg.getReg()) - IndexRegNo = GetX86RegNum(IndexReg); + IndexRegNo = getX86RegNum(IndexReg); else // Examples: [ESP+1*<noreg>+4] or [scaled idx]+disp32 (MOD=0,BASE=5) IndexRegNo = 4; - EmitSIBByte(SS, IndexRegNo, 5, CurByte, OS); + emitSIBByte(SS, IndexRegNo, 5, CurByte, OS); } else { unsigned IndexRegNo; if (IndexReg.getReg()) - IndexRegNo = GetX86RegNum(IndexReg); + IndexRegNo = getX86RegNum(IndexReg); else - IndexRegNo = 4; // For example [ESP+1*<noreg>+4] - EmitSIBByte(SS, IndexRegNo, GetX86RegNum(Base), CurByte, OS); + IndexRegNo = 4; // For example [ESP+1*<noreg>+4] + emitSIBByte(SS, IndexRegNo, getX86RegNum(Base), CurByte, OS); } // Do we need to output a displacement? if (ForceDisp8) - EmitImmediate(Disp, MI.getLoc(), 1, FK_Data_1, CurByte, OS, Fixups, ImmOffset); + emitImmediate(Disp, MI.getLoc(), 1, FK_Data_1, CurByte, OS, Fixups, + ImmOffset); else if (ForceDisp32 || Disp.getImm() != 0) - EmitImmediate(Disp, MI.getLoc(), 4, MCFixupKind(X86::reloc_signed_4byte), + emitImmediate(Disp, MI.getLoc(), 4, MCFixupKind(X86::reloc_signed_4byte), CurByte, OS, Fixups); } -/// EmitVEXOpcodePrefix - AVX instructions are encoded using a opcode prefix +void X86MCCodeEmitter::emitPrefixImpl(uint64_t TSFlags, unsigned &CurOp, + unsigned &CurByte, bool &Rex, + const MCInst &MI, const MCInstrDesc &Desc, + const MCSubtargetInfo &STI, + raw_ostream &OS) const { + // Determine where the memory operand starts, if present. + int MemoryOperand = X86II::getMemoryOperandNo(TSFlags); + if (MemoryOperand != -1) + MemoryOperand += CurOp; + + // Emit segment override opcode prefix as needed. + if (MemoryOperand >= 0) + emitSegmentOverridePrefix(CurByte, MemoryOperand + X86::AddrSegmentReg, MI, + OS); + + // Emit the repeat opcode prefix as needed. + unsigned Flags = MI.getFlags(); + if (TSFlags & X86II::REP || Flags & X86::IP_HAS_REPEAT) + emitByte(0xF3, CurByte, OS); + if (Flags & X86::IP_HAS_REPEAT_NE) + emitByte(0xF2, CurByte, OS); + + // Emit the address size opcode prefix as needed. + bool need_address_override; + uint64_t AdSize = TSFlags & X86II::AdSizeMask; + if ((STI.hasFeature(X86::Mode16Bit) && AdSize == X86II::AdSize32) || + (STI.hasFeature(X86::Mode32Bit) && AdSize == X86II::AdSize16) || + (STI.hasFeature(X86::Mode64Bit) && AdSize == X86II::AdSize32)) { + need_address_override = true; + } else if (MemoryOperand < 0) { + need_address_override = false; + } else if (STI.hasFeature(X86::Mode64Bit)) { + assert(!is16BitMemOperand(MI, MemoryOperand, STI)); + need_address_override = is32BitMemOperand(MI, MemoryOperand); + } else if (STI.hasFeature(X86::Mode32Bit)) { + assert(!is64BitMemOperand(MI, MemoryOperand)); + need_address_override = is16BitMemOperand(MI, MemoryOperand, STI); + } else { + assert(STI.hasFeature(X86::Mode16Bit)); + assert(!is64BitMemOperand(MI, MemoryOperand)); + need_address_override = !is16BitMemOperand(MI, MemoryOperand, STI); + } + + if (need_address_override) + emitByte(0x67, CurByte, OS); + + // Encoding type for this instruction. + uint64_t Encoding = TSFlags & X86II::EncodingMask; + if (Encoding == 0) + Rex = emitOpcodePrefix(TSFlags, CurByte, MemoryOperand, MI, Desc, STI, OS); + else + emitVEXOpcodePrefix(TSFlags, CurByte, MemoryOperand, MI, Desc, OS); + + uint64_t Form = TSFlags & X86II::FormMask; + switch (Form) { + default: + break; + case X86II::RawFrmDstSrc: { + unsigned siReg = MI.getOperand(1).getReg(); + assert(((siReg == X86::SI && MI.getOperand(0).getReg() == X86::DI) || + (siReg == X86::ESI && MI.getOperand(0).getReg() == X86::EDI) || + (siReg == X86::RSI && MI.getOperand(0).getReg() == X86::RDI)) && + "SI and DI register sizes do not match"); + // Emit segment override opcode prefix as needed (not for %ds). + if (MI.getOperand(2).getReg() != X86::DS) + emitSegmentOverridePrefix(CurByte, 2, MI, OS); + // Emit AdSize prefix as needed. + if ((!STI.hasFeature(X86::Mode32Bit) && siReg == X86::ESI) || + (STI.hasFeature(X86::Mode32Bit) && siReg == X86::SI)) + emitByte(0x67, CurByte, OS); + CurOp += 3; // Consume operands. + break; + } + case X86II::RawFrmSrc: { + unsigned siReg = MI.getOperand(0).getReg(); + // Emit segment override opcode prefix as needed (not for %ds). + if (MI.getOperand(1).getReg() != X86::DS) + emitSegmentOverridePrefix(CurByte, 1, MI, OS); + // Emit AdSize prefix as needed. + if ((!STI.hasFeature(X86::Mode32Bit) && siReg == X86::ESI) || + (STI.hasFeature(X86::Mode32Bit) && siReg == X86::SI)) + emitByte(0x67, CurByte, OS); + CurOp += 2; // Consume operands. + break; + } + case X86II::RawFrmDst: { + unsigned siReg = MI.getOperand(0).getReg(); + // Emit AdSize prefix as needed. + if ((!STI.hasFeature(X86::Mode32Bit) && siReg == X86::EDI) || + (STI.hasFeature(X86::Mode32Bit) && siReg == X86::DI)) + emitByte(0x67, CurByte, OS); + ++CurOp; // Consume operand. + break; + } + case X86II::RawFrmMemOffs: { + // Emit segment override opcode prefix as needed. + emitSegmentOverridePrefix(CurByte, 1, MI, OS); + break; + } + } +} + +/// emitVEXOpcodePrefix - AVX instructions are encoded using a opcode prefix /// called VEX. -void X86MCCodeEmitter::EmitVEXOpcodePrefix(uint64_t TSFlags, unsigned &CurByte, +void X86MCCodeEmitter::emitVEXOpcodePrefix(uint64_t TSFlags, unsigned &CurByte, int MemOperand, const MCInst &MI, const MCInstrDesc &Desc, raw_ostream &OS) const { @@ -690,13 +786,26 @@ void X86MCCodeEmitter::EmitVEXOpcodePrefix(uint64_t TSFlags, unsigned &CurByte, // 0b01010: XOP map select - 0Ah instructions with imm dword uint8_t VEX_5M; switch (TSFlags & X86II::OpMapMask) { - default: llvm_unreachable("Invalid prefix!"); - case X86II::TB: VEX_5M = 0x1; break; // 0F - case X86II::T8: VEX_5M = 0x2; break; // 0F 38 - case X86II::TA: VEX_5M = 0x3; break; // 0F 3A - case X86II::XOP8: VEX_5M = 0x8; break; - case X86II::XOP9: VEX_5M = 0x9; break; - case X86II::XOPA: VEX_5M = 0xA; break; + default: + llvm_unreachable("Invalid prefix!"); + case X86II::TB: + VEX_5M = 0x1; + break; // 0F + case X86II::T8: + VEX_5M = 0x2; + break; // 0F 38 + case X86II::TA: + VEX_5M = 0x3; + break; // 0F 3A + case X86II::XOP8: + VEX_5M = 0x8; + break; + case X86II::XOP9: + VEX_5M = 0x9; + break; + case X86II::XOPA: + VEX_5M = 0xA; + break; } // VEX_4V (VEX vvvv field): a register specifier @@ -724,9 +833,15 @@ void X86MCCodeEmitter::EmitVEXOpcodePrefix(uint64_t TSFlags, unsigned &CurByte, // uint8_t VEX_PP = 0; switch (TSFlags & X86II::OpPrefixMask) { - case X86II::PD: VEX_PP = 0x1; break; // 66 - case X86II::XS: VEX_PP = 0x2; break; // F3 - case X86II::XD: VEX_PP = 0x3; break; // F2 + case X86II::PD: + VEX_PP = 0x1; + break; // 66 + case X86II::XS: + VEX_PP = 0x2; + break; // F3 + case X86II::XD: + VEX_PP = 0x3; + break; // F2 } // EVEX_U @@ -751,7 +866,8 @@ void X86MCCodeEmitter::EmitVEXOpcodePrefix(uint64_t TSFlags, unsigned &CurByte, unsigned CurOp = X86II::getOperandBias(Desc); switch (TSFlags & X86II::FormMask) { - default: llvm_unreachable("Unexpected form in EmitVEXOpcodePrefix!"); + default: + llvm_unreachable("Unexpected form in emitVEXOpcodePrefix!"); case X86II::RawFrm: break; case X86II::MRMDestMem: { @@ -762,7 +878,8 @@ void X86MCCodeEmitter::EmitVEXOpcodePrefix(uint64_t TSFlags, unsigned &CurByte, // unsigned BaseRegEnc = getX86RegEncoding(MI, MemOperand + X86::AddrBaseReg); VEX_B = ~(BaseRegEnc >> 3) & 1; - unsigned IndexRegEnc = getX86RegEncoding(MI, MemOperand+X86::AddrIndexReg); + unsigned IndexRegEnc = + getX86RegEncoding(MI, MemOperand + X86::AddrIndexReg); VEX_X = ~(IndexRegEnc >> 3) & 1; if (!HasVEX_4V) // Only needed with VSIB which don't use VVVV. EVEX_V2 = ~(IndexRegEnc >> 4) & 1; @@ -807,7 +924,8 @@ void X86MCCodeEmitter::EmitVEXOpcodePrefix(uint64_t TSFlags, unsigned &CurByte, unsigned BaseRegEnc = getX86RegEncoding(MI, MemOperand + X86::AddrBaseReg); VEX_B = ~(BaseRegEnc >> 3) & 1; - unsigned IndexRegEnc = getX86RegEncoding(MI, MemOperand+X86::AddrIndexReg); + unsigned IndexRegEnc = + getX86RegEncoding(MI, MemOperand + X86::AddrIndexReg); VEX_X = ~(IndexRegEnc >> 3) & 1; if (!HasVEX_4V) // Only needed with VSIB which don't use VVVV. EVEX_V2 = ~(IndexRegEnc >> 4) & 1; @@ -822,7 +940,8 @@ void X86MCCodeEmitter::EmitVEXOpcodePrefix(uint64_t TSFlags, unsigned &CurByte, unsigned BaseRegEnc = getX86RegEncoding(MI, MemOperand + X86::AddrBaseReg); VEX_B = ~(BaseRegEnc >> 3) & 1; - unsigned IndexRegEnc = getX86RegEncoding(MI, MemOperand+X86::AddrIndexReg); + unsigned IndexRegEnc = + getX86RegEncoding(MI, MemOperand + X86::AddrIndexReg); VEX_X = ~(IndexRegEnc >> 3) & 1; VEX_4V = ~getX86RegEncoding(MI, CurOp + X86::AddrNumOperands) & 0xf; @@ -838,14 +957,19 @@ void X86MCCodeEmitter::EmitVEXOpcodePrefix(uint64_t TSFlags, unsigned &CurByte, unsigned BaseRegEnc = getX86RegEncoding(MI, MemOperand + X86::AddrBaseReg); VEX_B = ~(BaseRegEnc >> 3) & 1; - unsigned IndexRegEnc = getX86RegEncoding(MI, MemOperand+X86::AddrIndexReg); + unsigned IndexRegEnc = + getX86RegEncoding(MI, MemOperand + X86::AddrIndexReg); VEX_X = ~(IndexRegEnc >> 3) & 1; break; } - case X86II::MRM0m: case X86II::MRM1m: - case X86II::MRM2m: case X86II::MRM3m: - case X86II::MRM4m: case X86II::MRM5m: - case X86II::MRM6m: case X86II::MRM7m: { + case X86II::MRM0m: + case X86II::MRM1m: + case X86II::MRM2m: + case X86II::MRM3m: + case X86II::MRM4m: + case X86II::MRM5m: + case X86II::MRM6m: + case X86II::MRM7m: { // MRM[0-9]m instructions forms: // MemAddr // src1(VEX_4V), MemAddr @@ -860,7 +984,8 @@ void X86MCCodeEmitter::EmitVEXOpcodePrefix(uint64_t TSFlags, unsigned &CurByte, unsigned BaseRegEnc = getX86RegEncoding(MI, MemOperand + X86::AddrBaseReg); VEX_B = ~(BaseRegEnc >> 3) & 1; - unsigned IndexRegEnc = getX86RegEncoding(MI, MemOperand+X86::AddrIndexReg); + unsigned IndexRegEnc = + getX86RegEncoding(MI, MemOperand + X86::AddrIndexReg); VEX_X = ~(IndexRegEnc >> 3) & 1; if (!HasVEX_4V) // Only needed with VSIB which don't use VVVV. EVEX_V2 = ~(IndexRegEnc >> 4) & 1; @@ -894,7 +1019,7 @@ void X86MCCodeEmitter::EmitVEXOpcodePrefix(uint64_t TSFlags, unsigned &CurByte, if (EVEX_b) { if (HasEVEX_RC) { - unsigned RcOperand = NumOps-1; + unsigned RcOperand = NumOps - 1; assert(RcOperand >= CurOp); EVEX_rc = MI.getOperand(RcOperand).getImm(); assert(EVEX_rc <= 3 && "Invalid rounding control!"); @@ -956,10 +1081,14 @@ void X86MCCodeEmitter::EmitVEXOpcodePrefix(uint64_t TSFlags, unsigned &CurByte, EncodeRC = true; break; } - case X86II::MRM0r: case X86II::MRM1r: - case X86II::MRM2r: case X86II::MRM3r: - case X86II::MRM4r: case X86II::MRM5r: - case X86II::MRM6r: case X86II::MRM7r: { + case X86II::MRM0r: + case X86II::MRM1r: + case X86II::MRM2r: + case X86II::MRM3r: + case X86II::MRM4r: + case X86II::MRM5r: + case X86II::MRM6r: + case X86II::MRM7r: { // MRM0r-MRM7r instructions forms: // dst(VEX_4V), src(ModR/M), imm8 if (HasVEX_4V) { @@ -996,17 +1125,17 @@ void X86MCCodeEmitter::EmitVEXOpcodePrefix(uint64_t TSFlags, unsigned &CurByte, uint8_t LastByte = VEX_PP | (VEX_L << 2) | (VEX_4V << 3); // Can we use the 2 byte VEX prefix? - if (!(MI.getFlags() & X86::IP_USE_VEX3) && - Encoding == X86II::VEX && VEX_B && VEX_X && !VEX_W && (VEX_5M == 1)) { - EmitByte(0xC5, CurByte, OS); - EmitByte(LastByte | (VEX_R << 7), CurByte, OS); + if (!(MI.getFlags() & X86::IP_USE_VEX3) && Encoding == X86II::VEX && + VEX_B && VEX_X && !VEX_W && (VEX_5M == 1)) { + emitByte(0xC5, CurByte, OS); + emitByte(LastByte | (VEX_R << 7), CurByte, OS); return; } // 3 byte VEX prefix - EmitByte(Encoding == X86II::XOP ? 0x8F : 0xC4, CurByte, OS); - EmitByte(VEX_R << 7 | VEX_X << 6 | VEX_B << 5 | VEX_5M, CurByte, OS); - EmitByte(LastByte | (VEX_W << 7), CurByte, OS); + emitByte(Encoding == X86II::XOP ? 0x8F : 0xC4, CurByte, OS); + emitByte(VEX_R << 7 | VEX_X << 6 | VEX_B << 5 | VEX_5M, CurByte, OS); + emitByte(LastByte | (VEX_W << 7), CurByte, OS); } else { assert(Encoding == X86II::EVEX && "unknown encoding!"); // EVEX opcode prefix can have 4 bytes @@ -1014,39 +1143,30 @@ void X86MCCodeEmitter::EmitVEXOpcodePrefix(uint64_t TSFlags, unsigned &CurByte, // +-----+ +--------------+ +-------------------+ +------------------------+ // | 62h | | RXBR' | 00mm | | W | vvvv | U | pp | | z | L'L | b | v' | aaa | // +-----+ +--------------+ +-------------------+ +------------------------+ - assert((VEX_5M & 0x3) == VEX_5M - && "More than 2 significant bits in VEX.m-mmmm fields for EVEX!"); + assert((VEX_5M & 0x3) == VEX_5M && + "More than 2 significant bits in VEX.m-mmmm fields for EVEX!"); - EmitByte(0x62, CurByte, OS); - EmitByte((VEX_R << 7) | - (VEX_X << 6) | - (VEX_B << 5) | - (EVEX_R2 << 4) | - VEX_5M, CurByte, OS); - EmitByte((VEX_W << 7) | - (VEX_4V << 3) | - (EVEX_U << 2) | - VEX_PP, CurByte, OS); + emitByte(0x62, CurByte, OS); + emitByte((VEX_R << 7) | (VEX_X << 6) | (VEX_B << 5) | (EVEX_R2 << 4) | + VEX_5M, + CurByte, OS); + emitByte((VEX_W << 7) | (VEX_4V << 3) | (EVEX_U << 2) | VEX_PP, CurByte, + OS); if (EncodeRC) - EmitByte((EVEX_z << 7) | - (EVEX_rc << 5) | - (EVEX_b << 4) | - (EVEX_V2 << 3) | - EVEX_aaa, CurByte, OS); + emitByte((EVEX_z << 7) | (EVEX_rc << 5) | (EVEX_b << 4) | (EVEX_V2 << 3) | + EVEX_aaa, + CurByte, OS); else - EmitByte((EVEX_z << 7) | - (EVEX_L2 << 6) | - (VEX_L << 5) | - (EVEX_b << 4) | - (EVEX_V2 << 3) | - EVEX_aaa, CurByte, OS); + emitByte((EVEX_z << 7) | (EVEX_L2 << 6) | (VEX_L << 5) | (EVEX_b << 4) | + (EVEX_V2 << 3) | EVEX_aaa, + CurByte, OS); } } -/// DetermineREXPrefix - Determine if the MCInst has to be encoded with a X86-64 -/// REX prefix which specifies 1) 64-bit instructions, 2) non-default operand -/// size, and 3) use of X86-64 extended registers. -uint8_t X86MCCodeEmitter::DetermineREXPrefix(const MCInst &MI, uint64_t TSFlags, +/// Determine if the MCInst has to be encoded with a X86-64 REX prefix which +/// specifies 1) 64-bit instructions, 2) non-default operand size, and 3) use +/// of X86-64 extended registers. +uint8_t X86MCCodeEmitter::determineREXPrefix(const MCInst &MI, uint64_t TSFlags, int MemOperand, const MCInstrDesc &Desc) const { uint8_t REX = 0; @@ -1055,7 +1175,8 @@ uint8_t X86MCCodeEmitter::DetermineREXPrefix(const MCInst &MI, uint64_t TSFlags, if (TSFlags & X86II::REX_W) REX |= 1 << 3; // set REX.W - if (MI.getNumOperands() == 0) return REX; + if (MI.getNumOperands() == 0) + return REX; unsigned NumOps = MI.getNumOperands(); unsigned CurOp = X86II::getOperandBias(Desc); @@ -1063,12 +1184,13 @@ uint8_t X86MCCodeEmitter::DetermineREXPrefix(const MCInst &MI, uint64_t TSFlags, // If it accesses SPL, BPL, SIL, or DIL, then it requires a 0x40 REX prefix. for (unsigned i = CurOp; i != NumOps; ++i) { const MCOperand &MO = MI.getOperand(i); - if (!MO.isReg()) continue; + if (!MO.isReg()) + continue; unsigned Reg = MO.getReg(); if (Reg == X86::AH || Reg == X86::BH || Reg == X86::CH || Reg == X86::DH) UsesHighByteReg = true; if (X86II::isX86_64NonExtLowByteReg(Reg)) - // FIXME: The caller of DetermineREXPrefix slaps this prefix onto anything + // FIXME: The caller of determineREXPrefix slaps this prefix onto anything // that returns non-zero. REX |= 0x40; // REX fixed encoding prefix } @@ -1084,9 +1206,9 @@ uint8_t X86MCCodeEmitter::DetermineREXPrefix(const MCInst &MI, uint64_t TSFlags, break; case X86II::MRMSrcMem: case X86II::MRMSrcMemCC: - REX |= isREXExtendedReg(MI, CurOp++) << 2; // REX.R - REX |= isREXExtendedReg(MI, MemOperand+X86::AddrBaseReg) << 0; // REX.B - REX |= isREXExtendedReg(MI, MemOperand+X86::AddrIndexReg) << 1; // REX.X + REX |= isREXExtendedReg(MI, CurOp++) << 2; // REX.R + REX |= isREXExtendedReg(MI, MemOperand + X86::AddrBaseReg) << 0; // REX.B + REX |= isREXExtendedReg(MI, MemOperand + X86::AddrIndexReg) << 1; // REX.X CurOp += X86::AddrNumOperands; break; case X86II::MRMDestReg: @@ -1094,57 +1216,82 @@ uint8_t X86MCCodeEmitter::DetermineREXPrefix(const MCInst &MI, uint64_t TSFlags, REX |= isREXExtendedReg(MI, CurOp++) << 2; // REX.R break; case X86II::MRMDestMem: - REX |= isREXExtendedReg(MI, MemOperand+X86::AddrBaseReg) << 0; // REX.B - REX |= isREXExtendedReg(MI, MemOperand+X86::AddrIndexReg) << 1; // REX.X + REX |= isREXExtendedReg(MI, MemOperand + X86::AddrBaseReg) << 0; // REX.B + REX |= isREXExtendedReg(MI, MemOperand + X86::AddrIndexReg) << 1; // REX.X CurOp += X86::AddrNumOperands; REX |= isREXExtendedReg(MI, CurOp++) << 2; // REX.R break; - case X86II::MRMXmCC: case X86II::MRMXm: - case X86II::MRM0m: case X86II::MRM1m: - case X86II::MRM2m: case X86II::MRM3m: - case X86II::MRM4m: case X86II::MRM5m: - case X86II::MRM6m: case X86II::MRM7m: - REX |= isREXExtendedReg(MI, MemOperand+X86::AddrBaseReg) << 0; // REX.B - REX |= isREXExtendedReg(MI, MemOperand+X86::AddrIndexReg) << 1; // REX.X + case X86II::MRMXmCC: + case X86II::MRMXm: + case X86II::MRM0m: + case X86II::MRM1m: + case X86II::MRM2m: + case X86II::MRM3m: + case X86II::MRM4m: + case X86II::MRM5m: + case X86II::MRM6m: + case X86II::MRM7m: + REX |= isREXExtendedReg(MI, MemOperand + X86::AddrBaseReg) << 0; // REX.B + REX |= isREXExtendedReg(MI, MemOperand + X86::AddrIndexReg) << 1; // REX.X break; - case X86II::MRMXrCC: case X86II::MRMXr: - case X86II::MRM0r: case X86II::MRM1r: - case X86II::MRM2r: case X86II::MRM3r: - case X86II::MRM4r: case X86II::MRM5r: - case X86II::MRM6r: case X86II::MRM7r: + case X86II::MRMXrCC: + case X86II::MRMXr: + case X86II::MRM0r: + case X86II::MRM1r: + case X86II::MRM2r: + case X86II::MRM3r: + case X86II::MRM4r: + case X86II::MRM5r: + case X86II::MRM6r: + case X86II::MRM7r: REX |= isREXExtendedReg(MI, CurOp++) << 0; // REX.B break; } if (REX && UsesHighByteReg) - report_fatal_error("Cannot encode high byte register in REX-prefixed instruction"); + report_fatal_error( + "Cannot encode high byte register in REX-prefixed instruction"); return REX; } -/// EmitSegmentOverridePrefix - Emit segment override opcode prefix as needed -void X86MCCodeEmitter::EmitSegmentOverridePrefix(unsigned &CurByte, +/// Emit segment override opcode prefix as needed. +void X86MCCodeEmitter::emitSegmentOverridePrefix(unsigned &CurByte, unsigned SegOperand, const MCInst &MI, raw_ostream &OS) const { // Check for explicit segment override on memory operand. switch (MI.getOperand(SegOperand).getReg()) { - default: llvm_unreachable("Unknown segment register!"); - case 0: break; - case X86::CS: EmitByte(0x2E, CurByte, OS); break; - case X86::SS: EmitByte(0x36, CurByte, OS); break; - case X86::DS: EmitByte(0x3E, CurByte, OS); break; - case X86::ES: EmitByte(0x26, CurByte, OS); break; - case X86::FS: EmitByte(0x64, CurByte, OS); break; - case X86::GS: EmitByte(0x65, CurByte, OS); break; + default: + llvm_unreachable("Unknown segment register!"); + case 0: + break; + case X86::CS: + emitByte(0x2E, CurByte, OS); + break; + case X86::SS: + emitByte(0x36, CurByte, OS); + break; + case X86::DS: + emitByte(0x3E, CurByte, OS); + break; + case X86::ES: + emitByte(0x26, CurByte, OS); + break; + case X86::FS: + emitByte(0x64, CurByte, OS); + break; + case X86::GS: + emitByte(0x65, CurByte, OS); + break; } } /// Emit all instruction prefixes prior to the opcode. /// -/// MemOperand is the operand # of the start of a memory operand if present. If -/// Not present, it is -1. +/// \param MemOperand the operand # of the start of a memory operand if present. +/// If not present, it is -1. /// -/// Returns true if a REX prefix was used. +/// \returns true if a REX prefix was used. bool X86MCCodeEmitter::emitOpcodePrefix(uint64_t TSFlags, unsigned &CurByte, int MemOperand, const MCInst &MI, const MCInstrDesc &Desc, @@ -1152,35 +1299,35 @@ bool X86MCCodeEmitter::emitOpcodePrefix(uint64_t TSFlags, unsigned &CurByte, raw_ostream &OS) const { bool Ret = false; // Emit the operand size opcode prefix as needed. - if ((TSFlags & X86II::OpSizeMask) == (is16BitMode(STI) ? X86II::OpSize32 - : X86II::OpSize16)) - EmitByte(0x66, CurByte, OS); + if ((TSFlags & X86II::OpSizeMask) == + (STI.hasFeature(X86::Mode16Bit) ? X86II::OpSize32 : X86II::OpSize16)) + emitByte(0x66, CurByte, OS); // Emit the LOCK opcode prefix. if (TSFlags & X86II::LOCK || MI.getFlags() & X86::IP_HAS_LOCK) - EmitByte(0xF0, CurByte, OS); + emitByte(0xF0, CurByte, OS); // Emit the NOTRACK opcode prefix. if (TSFlags & X86II::NOTRACK || MI.getFlags() & X86::IP_HAS_NOTRACK) - EmitByte(0x3E, CurByte, OS); + emitByte(0x3E, CurByte, OS); switch (TSFlags & X86II::OpPrefixMask) { - case X86II::PD: // 66 - EmitByte(0x66, CurByte, OS); + case X86II::PD: // 66 + emitByte(0x66, CurByte, OS); break; - case X86II::XS: // F3 - EmitByte(0xF3, CurByte, OS); + case X86II::XS: // F3 + emitByte(0xF3, CurByte, OS); break; - case X86II::XD: // F2 - EmitByte(0xF2, CurByte, OS); + case X86II::XD: // F2 + emitByte(0xF2, CurByte, OS); break; } // Handle REX prefix. // FIXME: Can this come before F2 etc to simplify emission? - if (is64BitMode(STI)) { - if (uint8_t REX = DetermineREXPrefix(MI, TSFlags, MemOperand, Desc)) { - EmitByte(0x40 | REX, CurByte, OS); + if (STI.hasFeature(X86::Mode64Bit)) { + if (uint8_t REX = determineREXPrefix(MI, TSFlags, MemOperand, Desc)) { + emitByte(0x40 | REX, CurByte, OS); Ret = true; } } else { @@ -1189,33 +1336,50 @@ bool X86MCCodeEmitter::emitOpcodePrefix(uint64_t TSFlags, unsigned &CurByte, // 0x0F escape code must be emitted just before the opcode. switch (TSFlags & X86II::OpMapMask) { - case X86II::TB: // Two-byte opcode map - case X86II::T8: // 0F 38 - case X86II::TA: // 0F 3A - case X86II::ThreeDNow: // 0F 0F, second 0F emitted by caller. - EmitByte(0x0F, CurByte, OS); + case X86II::TB: // Two-byte opcode map + case X86II::T8: // 0F 38 + case X86II::TA: // 0F 3A + case X86II::ThreeDNow: // 0F 0F, second 0F emitted by caller. + emitByte(0x0F, CurByte, OS); break; } switch (TSFlags & X86II::OpMapMask) { - case X86II::T8: // 0F 38 - EmitByte(0x38, CurByte, OS); + case X86II::T8: // 0F 38 + emitByte(0x38, CurByte, OS); break; - case X86II::TA: // 0F 3A - EmitByte(0x3A, CurByte, OS); + case X86II::TA: // 0F 3A + emitByte(0x3A, CurByte, OS); break; } return Ret; } -void X86MCCodeEmitter:: -encodeInstruction(const MCInst &MI, raw_ostream &OS, - SmallVectorImpl<MCFixup> &Fixups, - const MCSubtargetInfo &STI) const { +void X86MCCodeEmitter::emitPrefix(const MCInst &MI, raw_ostream &OS, + const MCSubtargetInfo &STI) const { + unsigned Opcode = MI.getOpcode(); + const MCInstrDesc &Desc = MCII.get(Opcode); + uint64_t TSFlags = Desc.TSFlags; + + // Pseudo instructions don't get encoded. + if ((TSFlags & X86II::FormMask) == X86II::Pseudo) + return; + + unsigned CurOp = X86II::getOperandBias(Desc); + + // Keep track of the current byte being emitted. + unsigned CurByte = 0; + + bool Rex = false; + emitPrefixImpl(TSFlags, CurOp, CurByte, Rex, MI, Desc, STI, OS); +} + +void X86MCCodeEmitter::encodeInstruction(const MCInst &MI, raw_ostream &OS, + SmallVectorImpl<MCFixup> &Fixups, + const MCSubtargetInfo &STI) const { unsigned Opcode = MI.getOpcode(); const MCInstrDesc &Desc = MCII.get(Opcode); uint64_t TSFlags = Desc.TSFlags; - unsigned Flags = MI.getFlags(); // Pseudo instructions don't get encoded. if ((TSFlags & X86II::FormMask) == X86II::Pseudo) @@ -1227,8 +1391,8 @@ encodeInstruction(const MCInst &MI, raw_ostream &OS, // Keep track of the current byte being emitted. unsigned CurByte = 0; - // Encoding type for this instruction. - uint64_t Encoding = TSFlags & X86II::EncodingMask; + bool Rex = false; + emitPrefixImpl(TSFlags, CurOp, CurByte, Rex, MI, Desc, STI, OS); // It uses the VEX.VVVV field? bool HasVEX_4V = TSFlags & X86II::VEX_4V; @@ -1241,104 +1405,25 @@ encodeInstruction(const MCInst &MI, raw_ostream &OS, // Used if a register is encoded in 7:4 of immediate. unsigned I8RegNum = 0; - // Determine where the memory operand starts, if present. - int MemoryOperand = X86II::getMemoryOperandNo(TSFlags); - if (MemoryOperand != -1) MemoryOperand += CurOp; - - // Emit segment override opcode prefix as needed. - if (MemoryOperand >= 0) - EmitSegmentOverridePrefix(CurByte, MemoryOperand+X86::AddrSegmentReg, - MI, OS); - - // Emit the repeat opcode prefix as needed. - if (TSFlags & X86II::REP || Flags & X86::IP_HAS_REPEAT) - EmitByte(0xF3, CurByte, OS); - if (Flags & X86::IP_HAS_REPEAT_NE) - EmitByte(0xF2, CurByte, OS); - - // Emit the address size opcode prefix as needed. - bool need_address_override; - uint64_t AdSize = TSFlags & X86II::AdSizeMask; - if ((is16BitMode(STI) && AdSize == X86II::AdSize32) || - (is32BitMode(STI) && AdSize == X86II::AdSize16) || - (is64BitMode(STI) && AdSize == X86II::AdSize32)) { - need_address_override = true; - } else if (MemoryOperand < 0) { - need_address_override = false; - } else if (is64BitMode(STI)) { - assert(!Is16BitMemOperand(MI, MemoryOperand, STI)); - need_address_override = Is32BitMemOperand(MI, MemoryOperand); - } else if (is32BitMode(STI)) { - assert(!Is64BitMemOperand(MI, MemoryOperand)); - need_address_override = Is16BitMemOperand(MI, MemoryOperand, STI); - } else { - assert(is16BitMode(STI)); - assert(!Is64BitMemOperand(MI, MemoryOperand)); - need_address_override = !Is16BitMemOperand(MI, MemoryOperand, STI); - } - - if (need_address_override) - EmitByte(0x67, CurByte, OS); - - bool Rex = false; - if (Encoding == 0) - Rex = emitOpcodePrefix(TSFlags, CurByte, MemoryOperand, MI, Desc, STI, OS); - else - EmitVEXOpcodePrefix(TSFlags, CurByte, MemoryOperand, MI, Desc, OS); - uint8_t BaseOpcode = X86II::getBaseOpcodeFor(TSFlags); if ((TSFlags & X86II::OpMapMask) == X86II::ThreeDNow) - BaseOpcode = 0x0F; // Weird 3DNow! encoding. + BaseOpcode = 0x0F; // Weird 3DNow! encoding. unsigned OpcodeOffset = 0; uint64_t Form = TSFlags & X86II::FormMask; switch (Form) { - default: errs() << "FORM: " << Form << "\n"; + default: + errs() << "FORM: " << Form << "\n"; llvm_unreachable("Unknown FormMask value in X86MCCodeEmitter!"); case X86II::Pseudo: llvm_unreachable("Pseudo instruction shouldn't be emitted"); - case X86II::RawFrmDstSrc: { - unsigned siReg = MI.getOperand(1).getReg(); - assert(((siReg == X86::SI && MI.getOperand(0).getReg() == X86::DI) || - (siReg == X86::ESI && MI.getOperand(0).getReg() == X86::EDI) || - (siReg == X86::RSI && MI.getOperand(0).getReg() == X86::RDI)) && - "SI and DI register sizes do not match"); - // Emit segment override opcode prefix as needed (not for %ds). - if (MI.getOperand(2).getReg() != X86::DS) - EmitSegmentOverridePrefix(CurByte, 2, MI, OS); - // Emit AdSize prefix as needed. - if ((!is32BitMode(STI) && siReg == X86::ESI) || - (is32BitMode(STI) && siReg == X86::SI)) - EmitByte(0x67, CurByte, OS); - CurOp += 3; // Consume operands. - EmitByte(BaseOpcode, CurByte, OS); - break; - } - case X86II::RawFrmSrc: { - unsigned siReg = MI.getOperand(0).getReg(); - // Emit segment override opcode prefix as needed (not for %ds). - if (MI.getOperand(1).getReg() != X86::DS) - EmitSegmentOverridePrefix(CurByte, 1, MI, OS); - // Emit AdSize prefix as needed. - if ((!is32BitMode(STI) && siReg == X86::ESI) || - (is32BitMode(STI) && siReg == X86::SI)) - EmitByte(0x67, CurByte, OS); - CurOp += 2; // Consume operands. - EmitByte(BaseOpcode, CurByte, OS); + case X86II::RawFrmDstSrc: + case X86II::RawFrmSrc: + case X86II::RawFrmDst: + emitByte(BaseOpcode, CurByte, OS); break; - } - case X86II::RawFrmDst: { - unsigned siReg = MI.getOperand(0).getReg(); - // Emit AdSize prefix as needed. - if ((!is32BitMode(STI) && siReg == X86::EDI) || - (is32BitMode(STI) && siReg == X86::DI)) - EmitByte(0x67, CurByte, OS); - ++CurOp; // Consume operand. - EmitByte(BaseOpcode, CurByte, OS); - break; - } case X86II::AddCCFrm: { // This will be added to the opcode in the fallthrough. OpcodeOffset = MI.getOperand(NumOps - 1).getImm(); @@ -1346,49 +1431,47 @@ encodeInstruction(const MCInst &MI, raw_ostream &OS, --NumOps; // Drop the operand from the end. LLVM_FALLTHROUGH; case X86II::RawFrm: - EmitByte(BaseOpcode + OpcodeOffset, CurByte, OS); + emitByte(BaseOpcode + OpcodeOffset, CurByte, OS); - if (!is64BitMode(STI) || !isPCRel32Branch(MI)) + if (!STI.hasFeature(X86::Mode64Bit) || !isPCRel32Branch(MI, MCII)) break; const MCOperand &Op = MI.getOperand(CurOp++); - EmitImmediate(Op, MI.getLoc(), X86II::getSizeOfImm(TSFlags), + emitImmediate(Op, MI.getLoc(), X86II::getSizeOfImm(TSFlags), MCFixupKind(X86::reloc_branch_4byte_pcrel), CurByte, OS, Fixups); break; } case X86II::RawFrmMemOffs: - // Emit segment override opcode prefix as needed. - EmitSegmentOverridePrefix(CurByte, 1, MI, OS); - EmitByte(BaseOpcode, CurByte, OS); - EmitImmediate(MI.getOperand(CurOp++), MI.getLoc(), + emitByte(BaseOpcode, CurByte, OS); + emitImmediate(MI.getOperand(CurOp++), MI.getLoc(), X86II::getSizeOfImm(TSFlags), getImmFixupKind(TSFlags), CurByte, OS, Fixups); ++CurOp; // skip segment operand break; case X86II::RawFrmImm8: - EmitByte(BaseOpcode, CurByte, OS); - EmitImmediate(MI.getOperand(CurOp++), MI.getLoc(), + emitByte(BaseOpcode, CurByte, OS); + emitImmediate(MI.getOperand(CurOp++), MI.getLoc(), X86II::getSizeOfImm(TSFlags), getImmFixupKind(TSFlags), CurByte, OS, Fixups); - EmitImmediate(MI.getOperand(CurOp++), MI.getLoc(), 1, FK_Data_1, CurByte, + emitImmediate(MI.getOperand(CurOp++), MI.getLoc(), 1, FK_Data_1, CurByte, OS, Fixups); break; case X86II::RawFrmImm16: - EmitByte(BaseOpcode, CurByte, OS); - EmitImmediate(MI.getOperand(CurOp++), MI.getLoc(), + emitByte(BaseOpcode, CurByte, OS); + emitImmediate(MI.getOperand(CurOp++), MI.getLoc(), X86II::getSizeOfImm(TSFlags), getImmFixupKind(TSFlags), CurByte, OS, Fixups); - EmitImmediate(MI.getOperand(CurOp++), MI.getLoc(), 2, FK_Data_2, CurByte, + emitImmediate(MI.getOperand(CurOp++), MI.getLoc(), 2, FK_Data_2, CurByte, OS, Fixups); break; case X86II::AddRegFrm: - EmitByte(BaseOpcode + GetX86RegNum(MI.getOperand(CurOp++)), CurByte, OS); + emitByte(BaseOpcode + getX86RegNum(MI.getOperand(CurOp++)), CurByte, OS); break; case X86II::MRMDestReg: { - EmitByte(BaseOpcode, CurByte, OS); + emitByte(BaseOpcode, CurByte, OS); unsigned SrcRegNum = CurOp + 1; if (HasEVEX_K) // Skip writemask @@ -1397,13 +1480,13 @@ encodeInstruction(const MCInst &MI, raw_ostream &OS, if (HasVEX_4V) // Skip 1st src (which is encoded in VEX_VVVV) ++SrcRegNum; - EmitRegModRMByte(MI.getOperand(CurOp), - GetX86RegNum(MI.getOperand(SrcRegNum)), CurByte, OS); + emitRegModRMByte(MI.getOperand(CurOp), + getX86RegNum(MI.getOperand(SrcRegNum)), CurByte, OS); CurOp = SrcRegNum + 1; break; } case X86II::MRMDestMem: { - EmitByte(BaseOpcode, CurByte, OS); + emitByte(BaseOpcode, CurByte, OS); unsigned SrcRegNum = CurOp + X86::AddrNumOperands; if (HasEVEX_K) // Skip writemask @@ -1412,13 +1495,13 @@ encodeInstruction(const MCInst &MI, raw_ostream &OS, if (HasVEX_4V) // Skip 1st src (which is encoded in VEX_VVVV) ++SrcRegNum; - emitMemModRMByte(MI, CurOp, GetX86RegNum(MI.getOperand(SrcRegNum)), TSFlags, + emitMemModRMByte(MI, CurOp, getX86RegNum(MI.getOperand(SrcRegNum)), TSFlags, Rex, CurByte, OS, Fixups, STI); CurOp = SrcRegNum + 1; break; } case X86II::MRMSrcReg: { - EmitByte(BaseOpcode, CurByte, OS); + emitByte(BaseOpcode, CurByte, OS); unsigned SrcRegNum = CurOp + 1; if (HasEVEX_K) // Skip writemask @@ -1427,8 +1510,8 @@ encodeInstruction(const MCInst &MI, raw_ostream &OS, if (HasVEX_4V) // Skip 1st src (which is encoded in VEX_VVVV) ++SrcRegNum; - EmitRegModRMByte(MI.getOperand(SrcRegNum), - GetX86RegNum(MI.getOperand(CurOp)), CurByte, OS); + emitRegModRMByte(MI.getOperand(SrcRegNum), + getX86RegNum(MI.getOperand(CurOp)), CurByte, OS); CurOp = SrcRegNum + 1; if (HasVEX_I8Reg) I8RegNum = getX86RegEncoding(MI, CurOp++); @@ -1438,17 +1521,17 @@ encodeInstruction(const MCInst &MI, raw_ostream &OS, break; } case X86II::MRMSrcReg4VOp3: { - EmitByte(BaseOpcode, CurByte, OS); + emitByte(BaseOpcode, CurByte, OS); unsigned SrcRegNum = CurOp + 1; - EmitRegModRMByte(MI.getOperand(SrcRegNum), - GetX86RegNum(MI.getOperand(CurOp)), CurByte, OS); + emitRegModRMByte(MI.getOperand(SrcRegNum), + getX86RegNum(MI.getOperand(CurOp)), CurByte, OS); CurOp = SrcRegNum + 1; ++CurOp; // Encoded in VEX.VVVV break; } case X86II::MRMSrcRegOp4: { - EmitByte(BaseOpcode, CurByte, OS); + emitByte(BaseOpcode, CurByte, OS); unsigned SrcRegNum = CurOp + 1; // Skip 1st src (which is encoded in VEX_VVVV) @@ -1458,8 +1541,8 @@ encodeInstruction(const MCInst &MI, raw_ostream &OS, assert(HasVEX_I8Reg && "MRMSrcRegOp4 should imply VEX_I8Reg"); I8RegNum = getX86RegEncoding(MI, SrcRegNum++); - EmitRegModRMByte(MI.getOperand(SrcRegNum), - GetX86RegNum(MI.getOperand(CurOp)), CurByte, OS); + emitRegModRMByte(MI.getOperand(SrcRegNum), + getX86RegNum(MI.getOperand(CurOp)), CurByte, OS); CurOp = SrcRegNum + 1; break; } @@ -1468,24 +1551,24 @@ encodeInstruction(const MCInst &MI, raw_ostream &OS, unsigned SecondOp = CurOp++; unsigned CC = MI.getOperand(CurOp++).getImm(); - EmitByte(BaseOpcode + CC, CurByte, OS); + emitByte(BaseOpcode + CC, CurByte, OS); - EmitRegModRMByte(MI.getOperand(SecondOp), - GetX86RegNum(MI.getOperand(FirstOp)), CurByte, OS); + emitRegModRMByte(MI.getOperand(SecondOp), + getX86RegNum(MI.getOperand(FirstOp)), CurByte, OS); break; } case X86II::MRMSrcMem: { - unsigned FirstMemOp = CurOp+1; + unsigned FirstMemOp = CurOp + 1; if (HasEVEX_K) // Skip writemask ++FirstMemOp; if (HasVEX_4V) - ++FirstMemOp; // Skip the register source (which is encoded in VEX_VVVV). + ++FirstMemOp; // Skip the register source (which is encoded in VEX_VVVV). - EmitByte(BaseOpcode, CurByte, OS); + emitByte(BaseOpcode, CurByte, OS); - emitMemModRMByte(MI, FirstMemOp, GetX86RegNum(MI.getOperand(CurOp)), + emitMemModRMByte(MI, FirstMemOp, getX86RegNum(MI.getOperand(CurOp)), TSFlags, Rex, CurByte, OS, Fixups, STI); CurOp = FirstMemOp + X86::AddrNumOperands; if (HasVEX_I8Reg) @@ -1493,28 +1576,28 @@ encodeInstruction(const MCInst &MI, raw_ostream &OS, break; } case X86II::MRMSrcMem4VOp3: { - unsigned FirstMemOp = CurOp+1; + unsigned FirstMemOp = CurOp + 1; - EmitByte(BaseOpcode, CurByte, OS); + emitByte(BaseOpcode, CurByte, OS); - emitMemModRMByte(MI, FirstMemOp, GetX86RegNum(MI.getOperand(CurOp)), + emitMemModRMByte(MI, FirstMemOp, getX86RegNum(MI.getOperand(CurOp)), TSFlags, Rex, CurByte, OS, Fixups, STI); CurOp = FirstMemOp + X86::AddrNumOperands; ++CurOp; // Encoded in VEX.VVVV. break; } case X86II::MRMSrcMemOp4: { - unsigned FirstMemOp = CurOp+1; + unsigned FirstMemOp = CurOp + 1; - ++FirstMemOp; // Skip the register source (which is encoded in VEX_VVVV). + ++FirstMemOp; // Skip the register source (which is encoded in VEX_VVVV). // Capture second register source (encoded in Imm[7:4]) assert(HasVEX_I8Reg && "MRMSrcRegOp4 should imply VEX_I8Reg"); I8RegNum = getX86RegEncoding(MI, FirstMemOp++); - EmitByte(BaseOpcode, CurByte, OS); + emitByte(BaseOpcode, CurByte, OS); - emitMemModRMByte(MI, FirstMemOp, GetX86RegNum(MI.getOperand(CurOp)), + emitMemModRMByte(MI, FirstMemOp, getX86RegNum(MI.getOperand(CurOp)), TSFlags, Rex, CurByte, OS, Fixups, STI); CurOp = FirstMemOp + X86::AddrNumOperands; break; @@ -1525,9 +1608,9 @@ encodeInstruction(const MCInst &MI, raw_ostream &OS, CurOp = FirstMemOp + X86::AddrNumOperands; unsigned CC = MI.getOperand(CurOp++).getImm(); - EmitByte(BaseOpcode + CC, CurByte, OS); + emitByte(BaseOpcode + CC, CurByte, OS); - emitMemModRMByte(MI, FirstMemOp, GetX86RegNum(MI.getOperand(RegOp)), + emitMemModRMByte(MI, FirstMemOp, getX86RegNum(MI.getOperand(RegOp)), TSFlags, Rex, CurByte, OS, Fixups, STI); break; } @@ -1536,24 +1619,28 @@ encodeInstruction(const MCInst &MI, raw_ostream &OS, unsigned RegOp = CurOp++; unsigned CC = MI.getOperand(CurOp++).getImm(); - EmitByte(BaseOpcode + CC, CurByte, OS); - EmitRegModRMByte(MI.getOperand(RegOp), 0, CurByte, OS); + emitByte(BaseOpcode + CC, CurByte, OS); + emitRegModRMByte(MI.getOperand(RegOp), 0, CurByte, OS); break; } case X86II::MRMXr: - case X86II::MRM0r: case X86II::MRM1r: - case X86II::MRM2r: case X86II::MRM3r: - case X86II::MRM4r: case X86II::MRM5r: - case X86II::MRM6r: case X86II::MRM7r: + case X86II::MRM0r: + case X86II::MRM1r: + case X86II::MRM2r: + case X86II::MRM3r: + case X86II::MRM4r: + case X86II::MRM5r: + case X86II::MRM6r: + case X86II::MRM7r: if (HasVEX_4V) // Skip the register dst (which is encoded in VEX_VVVV). ++CurOp; if (HasEVEX_K) // Skip writemask ++CurOp; - EmitByte(BaseOpcode, CurByte, OS); - EmitRegModRMByte(MI.getOperand(CurOp++), - (Form == X86II::MRMXr) ? 0 : Form-X86II::MRM0r, - CurByte, OS); + emitByte(BaseOpcode, CurByte, OS); + emitRegModRMByte(MI.getOperand(CurOp++), + (Form == X86II::MRMXr) ? 0 : Form - X86II::MRM0r, CurByte, + OS); break; case X86II::MRMXmCC: { @@ -1561,52 +1648,98 @@ encodeInstruction(const MCInst &MI, raw_ostream &OS, CurOp = FirstMemOp + X86::AddrNumOperands; unsigned CC = MI.getOperand(CurOp++).getImm(); - EmitByte(BaseOpcode + CC, CurByte, OS); + emitByte(BaseOpcode + CC, CurByte, OS); emitMemModRMByte(MI, FirstMemOp, 0, TSFlags, Rex, CurByte, OS, Fixups, STI); break; } case X86II::MRMXm: - case X86II::MRM0m: case X86II::MRM1m: - case X86II::MRM2m: case X86II::MRM3m: - case X86II::MRM4m: case X86II::MRM5m: - case X86II::MRM6m: case X86II::MRM7m: + case X86II::MRM0m: + case X86II::MRM1m: + case X86II::MRM2m: + case X86II::MRM3m: + case X86II::MRM4m: + case X86II::MRM5m: + case X86II::MRM6m: + case X86II::MRM7m: if (HasVEX_4V) // Skip the register dst (which is encoded in VEX_VVVV). ++CurOp; if (HasEVEX_K) // Skip writemask ++CurOp; - EmitByte(BaseOpcode, CurByte, OS); + emitByte(BaseOpcode, CurByte, OS); emitMemModRMByte(MI, CurOp, (Form == X86II::MRMXm) ? 0 : Form - X86II::MRM0m, TSFlags, Rex, CurByte, OS, Fixups, STI); CurOp += X86::AddrNumOperands; break; - case X86II::MRM_C0: case X86II::MRM_C1: case X86II::MRM_C2: - case X86II::MRM_C3: case X86II::MRM_C4: case X86II::MRM_C5: - case X86II::MRM_C6: case X86II::MRM_C7: case X86II::MRM_C8: - case X86II::MRM_C9: case X86II::MRM_CA: case X86II::MRM_CB: - case X86II::MRM_CC: case X86II::MRM_CD: case X86II::MRM_CE: - case X86II::MRM_CF: case X86II::MRM_D0: case X86II::MRM_D1: - case X86II::MRM_D2: case X86II::MRM_D3: case X86II::MRM_D4: - case X86II::MRM_D5: case X86II::MRM_D6: case X86II::MRM_D7: - case X86II::MRM_D8: case X86II::MRM_D9: case X86II::MRM_DA: - case X86II::MRM_DB: case X86II::MRM_DC: case X86II::MRM_DD: - case X86II::MRM_DE: case X86II::MRM_DF: case X86II::MRM_E0: - case X86II::MRM_E1: case X86II::MRM_E2: case X86II::MRM_E3: - case X86II::MRM_E4: case X86II::MRM_E5: case X86II::MRM_E6: - case X86II::MRM_E7: case X86II::MRM_E8: case X86II::MRM_E9: - case X86II::MRM_EA: case X86II::MRM_EB: case X86II::MRM_EC: - case X86II::MRM_ED: case X86II::MRM_EE: case X86II::MRM_EF: - case X86II::MRM_F0: case X86II::MRM_F1: case X86II::MRM_F2: - case X86II::MRM_F3: case X86II::MRM_F4: case X86II::MRM_F5: - case X86II::MRM_F6: case X86II::MRM_F7: case X86II::MRM_F8: - case X86II::MRM_F9: case X86II::MRM_FA: case X86II::MRM_FB: - case X86II::MRM_FC: case X86II::MRM_FD: case X86II::MRM_FE: + case X86II::MRM_C0: + case X86II::MRM_C1: + case X86II::MRM_C2: + case X86II::MRM_C3: + case X86II::MRM_C4: + case X86II::MRM_C5: + case X86II::MRM_C6: + case X86II::MRM_C7: + case X86II::MRM_C8: + case X86II::MRM_C9: + case X86II::MRM_CA: + case X86II::MRM_CB: + case X86II::MRM_CC: + case X86II::MRM_CD: + case X86II::MRM_CE: + case X86II::MRM_CF: + case X86II::MRM_D0: + case X86II::MRM_D1: + case X86II::MRM_D2: + case X86II::MRM_D3: + case X86II::MRM_D4: + case X86II::MRM_D5: + case X86II::MRM_D6: + case X86II::MRM_D7: + case X86II::MRM_D8: + case X86II::MRM_D9: + case X86II::MRM_DA: + case X86II::MRM_DB: + case X86II::MRM_DC: + case X86II::MRM_DD: + case X86II::MRM_DE: + case X86II::MRM_DF: + case X86II::MRM_E0: + case X86II::MRM_E1: + case X86II::MRM_E2: + case X86II::MRM_E3: + case X86II::MRM_E4: + case X86II::MRM_E5: + case X86II::MRM_E6: + case X86II::MRM_E7: + case X86II::MRM_E8: + case X86II::MRM_E9: + case X86II::MRM_EA: + case X86II::MRM_EB: + case X86II::MRM_EC: + case X86II::MRM_ED: + case X86II::MRM_EE: + case X86II::MRM_EF: + case X86II::MRM_F0: + case X86II::MRM_F1: + case X86II::MRM_F2: + case X86II::MRM_F3: + case X86II::MRM_F4: + case X86II::MRM_F5: + case X86II::MRM_F6: + case X86II::MRM_F7: + case X86II::MRM_F8: + case X86II::MRM_F9: + case X86II::MRM_FA: + case X86II::MRM_FB: + case X86II::MRM_FC: + case X86II::MRM_FD: + case X86II::MRM_FE: case X86II::MRM_FF: - EmitByte(BaseOpcode, CurByte, OS); - EmitByte(0xC0 + Form - X86II::MRM_C0, CurByte, OS); + emitByte(BaseOpcode, CurByte, OS); + emitByte(0xC0 + Form - X86II::MRM_C0, CurByte, OS); break; } @@ -1620,21 +1753,21 @@ encodeInstruction(const MCInst &MI, raw_ostream &OS, assert(Val < 16 && "Immediate operand value out of range"); I8RegNum |= Val; } - EmitImmediate(MCOperand::createImm(I8RegNum), MI.getLoc(), 1, FK_Data_1, + emitImmediate(MCOperand::createImm(I8RegNum), MI.getLoc(), 1, FK_Data_1, CurByte, OS, Fixups); } else { // If there is a remaining operand, it must be a trailing immediate. Emit it // according to the right size for the instruction. Some instructions // (SSE4a extrq and insertq) have two trailing immediates. while (CurOp != NumOps && NumOps - CurOp <= 2) { - EmitImmediate(MI.getOperand(CurOp++), MI.getLoc(), + emitImmediate(MI.getOperand(CurOp++), MI.getLoc(), X86II::getSizeOfImm(TSFlags), getImmFixupKind(TSFlags), CurByte, OS, Fixups); } } if ((TSFlags & X86II::OpMapMask) == X86II::ThreeDNow) - EmitByte(X86II::getBaseOpcodeFor(TSFlags), CurByte, OS); + emitByte(X86II::getBaseOpcodeFor(TSFlags), CurByte, OS); #ifndef NDEBUG // FIXME: Verify. diff --git a/llvm/lib/Target/X86/MCTargetDesc/X86MCTargetDesc.cpp b/llvm/lib/Target/X86/MCTargetDesc/X86MCTargetDesc.cpp index ced9eacc8b97..049a3a815984 100644 --- a/llvm/lib/Target/X86/MCTargetDesc/X86MCTargetDesc.cpp +++ b/llvm/lib/Target/X86/MCTargetDesc/X86MCTargetDesc.cpp @@ -290,12 +290,9 @@ void X86_MC::initLLVMToSEHAndCVRegMapping(MCRegisterInfo *MRI) { MCSubtargetInfo *X86_MC::createX86MCSubtargetInfo(const Triple &TT, StringRef CPU, StringRef FS) { std::string ArchFS = X86_MC::ParseX86Triple(TT); - if (!FS.empty()) { - if (!ArchFS.empty()) - ArchFS = (Twine(ArchFS) + "," + FS).str(); - else - ArchFS = FS; - } + assert(!ArchFS.empty() && "Failed to parse X86 triple"); + if (!FS.empty()) + ArchFS = (Twine(ArchFS) + "," + FS).str(); std::string CPUName = CPU; if (CPUName.empty()) @@ -323,7 +320,8 @@ static MCRegisterInfo *createX86MCRegisterInfo(const Triple &TT) { } static MCAsmInfo *createX86MCAsmInfo(const MCRegisterInfo &MRI, - const Triple &TheTriple) { + const Triple &TheTriple, + const MCTargetOptions &Options) { bool is64Bit = TheTriple.getArch() == Triple::x86_64; MCAsmInfo *MAI; @@ -554,7 +552,7 @@ static MCInstrAnalysis *createX86MCInstrAnalysis(const MCInstrInfo *Info) { } // Force static initialization. -extern "C" void LLVMInitializeX86TargetMC() { +extern "C" LLVM_EXTERNAL_VISIBILITY void LLVMInitializeX86TargetMC() { for (Target *T : {&getTheX86_32Target(), &getTheX86_64Target()}) { // Register the MC asm info. RegisterMCAsmInfoFn X(*T, createX86MCAsmInfo); |
