diff options
author | Dimitry Andric <dim@FreeBSD.org> | 2020-07-26 19:36:28 +0000 |
---|---|---|
committer | Dimitry Andric <dim@FreeBSD.org> | 2020-07-26 19:36:28 +0000 |
commit | cfca06d7963fa0909f90483b42a6d7d194d01e08 (patch) | |
tree | 209fb2a2d68f8f277793fc8df46c753d31bc853b /llvm/lib/Target/X86/MCTargetDesc/X86MCCodeEmitter.cpp | |
parent | 706b4fc47bbc608932d3b491ae19a3b9cde9497b (diff) |
Notes
Diffstat (limited to 'llvm/lib/Target/X86/MCTargetDesc/X86MCCodeEmitter.cpp')
-rw-r--r-- | llvm/lib/Target/X86/MCTargetDesc/X86MCCodeEmitter.cpp | 696 |
1 files changed, 367 insertions, 329 deletions
diff --git a/llvm/lib/Target/X86/MCTargetDesc/X86MCCodeEmitter.cpp b/llvm/lib/Target/X86/MCTargetDesc/X86MCCodeEmitter.cpp index 54a293702bd0f..7dea0760a8310 100644 --- a/llvm/lib/Target/X86/MCTargetDesc/X86MCCodeEmitter.cpp +++ b/llvm/lib/Target/X86/MCTargetDesc/X86MCCodeEmitter.cpp @@ -55,83 +55,64 @@ public: const MCSubtargetInfo &STI) const override; private: - unsigned getX86RegNum(const MCOperand &MO) const { - return Ctx.getRegisterInfo()->getEncodingValue(MO.getReg()) & 0x7; - } + unsigned getX86RegNum(const MCOperand &MO) const; - unsigned getX86RegEncoding(const MCInst &MI, unsigned OpNum) const { - return Ctx.getRegisterInfo()->getEncodingValue( - MI.getOperand(OpNum).getReg()); - } + unsigned getX86RegEncoding(const MCInst &MI, unsigned OpNum) const; /// \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 { - OS << (char)C; - ++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); - Val >>= 8; - } - } + bool isREXExtendedReg(const MCInst &MI, unsigned OpNum) const; void emitImmediate(const MCOperand &Disp, SMLoc Loc, unsigned ImmSize, - MCFixupKind FixupKind, unsigned &CurByte, raw_ostream &OS, + MCFixupKind FixupKind, uint64_t StartByte, raw_ostream &OS, SmallVectorImpl<MCFixup> &Fixups, int ImmOffset = 0) const; - 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, - unsigned &CurByte, raw_ostream &OS) const { - emitByte(modRMByte(3, RegOpcodeFld, getX86RegNum(ModRMReg)), CurByte, OS); - } + raw_ostream &OS) const; 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); - } + raw_ostream &OS) const; void emitMemModRMByte(const MCInst &MI, unsigned Op, unsigned RegOpcodeField, - uint64_t TSFlags, bool Rex, unsigned &CurByte, + uint64_t TSFlags, bool HasREX, uint64_t StartByte, raw_ostream &OS, SmallVectorImpl<MCFixup> &Fixups, - const MCSubtargetInfo &STI) const; + const MCSubtargetInfo &STI, + bool ForceSIB = false) const; - void emitPrefixImpl(uint64_t TSFlags, unsigned &CurOp, unsigned &CurByte, - bool &Rex, const MCInst &MI, const MCInstrDesc &Desc, - const MCSubtargetInfo &STI, raw_ostream &OS) const; + bool emitPrefixImpl(unsigned &CurOp, const MCInst &MI, + const MCSubtargetInfo &STI, raw_ostream &OS) const; - void emitVEXOpcodePrefix(uint64_t TSFlags, unsigned &CurByte, int MemOperand, - const MCInst &MI, const MCInstrDesc &Desc, + void emitVEXOpcodePrefix(int MemOperand, const MCInst &MI, raw_ostream &OS) const; - void emitSegmentOverridePrefix(unsigned &CurByte, unsigned SegOperand, - const MCInst &MI, raw_ostream &OS) const; + void emitSegmentOverridePrefix(unsigned SegOperand, const MCInst &MI, + raw_ostream &OS) const; - bool emitOpcodePrefix(uint64_t TSFlags, unsigned &CurByte, int MemOperand, - const MCInst &MI, const MCInstrDesc &Desc, + bool emitOpcodePrefix(int MemOperand, const MCInst &MI, const MCSubtargetInfo &STI, raw_ostream &OS) const; - uint8_t determineREXPrefix(const MCInst &MI, uint64_t TSFlags, int MemOperand, - const MCInstrDesc &Desc) const; + bool emitREXPrefix(int MemOperand, const MCInst &MI, raw_ostream &OS) const; }; } // end anonymous namespace +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); +} + +static void emitByte(uint8_t C, raw_ostream &OS) { OS << static_cast<char>(C); } + +static void emitConstant(uint64_t Val, unsigned Size, raw_ostream &OS) { + // Output the constant in little endian byte order. + for (unsigned i = 0; i != Size; ++i) { + emitByte(Val & 255, OS); + Val >>= 8; + } +} + /// \returns true if this signed displacement fits in a 8-bit sign-extended /// field. static bool isDisp8(int Value) { return Value == (int8_t)Value; } @@ -275,7 +256,8 @@ static bool hasSecRelSymbolRef(const MCExpr *Expr) { 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) || + if ((Opcode != X86::CALL64pcrel32 && Opcode != X86::JMP_4 && + Opcode != X86::JCC_4) || getImmFixupKind(Desc.TSFlags) != FK_PCRel_4) return false; @@ -288,9 +270,27 @@ static bool isPCRel32Branch(const MCInst &MI, const MCInstrInfo &MCII) { return Ref && Ref->getKind() == MCSymbolRefExpr::VK_None; } +unsigned X86MCCodeEmitter::getX86RegNum(const MCOperand &MO) const { + return Ctx.getRegisterInfo()->getEncodingValue(MO.getReg()) & 0x7; +} + +unsigned X86MCCodeEmitter::getX86RegEncoding(const MCInst &MI, + unsigned OpNum) const { + return Ctx.getRegisterInfo()->getEncodingValue(MI.getOperand(OpNum).getReg()); +} + +/// \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 X86MCCodeEmitter::isREXExtendedReg(const MCInst &MI, + unsigned OpNum) const { + return (getX86RegEncoding(MI, OpNum) >> 3) & 1; +} + void X86MCCodeEmitter::emitImmediate(const MCOperand &DispOp, SMLoc Loc, unsigned Size, MCFixupKind FixupKind, - unsigned &CurByte, raw_ostream &OS, + uint64_t StartByte, raw_ostream &OS, SmallVectorImpl<MCFixup> &Fixups, int ImmOffset) const { const MCExpr *Expr = nullptr; @@ -299,7 +299,7 @@ void X86MCCodeEmitter::emitImmediate(const MCOperand &DispOp, SMLoc Loc, // relocation, emit it now. 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, OS); return; } Expr = MCConstantExpr::create(DispOp.getImm(), Ctx); @@ -322,7 +322,7 @@ void X86MCCodeEmitter::emitImmediate(const MCOperand &DispOp, SMLoc Loc, } if (Kind == GOT_Normal) - ImmOffset = CurByte; + ImmOffset = static_cast<int>(OS.tell() - StartByte); } else if (Expr->getKind() == MCExpr::SymbolRef) { if (hasSecRelSymbolRef(Expr)) { FixupKind = MCFixupKind(FK_SecRel_4); @@ -361,16 +361,30 @@ void X86MCCodeEmitter::emitImmediate(const MCOperand &DispOp, SMLoc Loc, Ctx); // Emit a symbolic constant as a fixup and 4 zeros. - Fixups.push_back(MCFixup::create(CurByte, Expr, FixupKind, Loc)); - emitConstant(0, Size, CurByte, OS); + Fixups.push_back(MCFixup::create(static_cast<uint32_t>(OS.tell() - StartByte), + Expr, FixupKind, Loc)); + emitConstant(0, Size, OS); +} + +void X86MCCodeEmitter::emitRegModRMByte(const MCOperand &ModRMReg, + unsigned RegOpcodeFld, + raw_ostream &OS) const { + emitByte(modRMByte(3, RegOpcodeFld, getX86RegNum(ModRMReg)), OS); +} + +void X86MCCodeEmitter::emitSIBByte(unsigned SS, unsigned Index, unsigned Base, + raw_ostream &OS) const { + // SIB byte is in the same format as the modRMByte. + emitByte(modRMByte(SS, Index, Base), OS); } void X86MCCodeEmitter::emitMemModRMByte(const MCInst &MI, unsigned Op, unsigned RegOpcodeField, - uint64_t TSFlags, bool Rex, - unsigned &CurByte, raw_ostream &OS, + uint64_t TSFlags, bool HasREX, + uint64_t StartByte, raw_ostream &OS, SmallVectorImpl<MCFixup> &Fixups, - const MCSubtargetInfo &STI) const { + const MCSubtargetInfo &STI, + bool ForceSIB) 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); @@ -383,8 +397,9 @@ void X86MCCodeEmitter::emitMemModRMByte(const MCInst &MI, unsigned Op, 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); + assert(IndexReg.getReg() == 0 && !ForceSIB && + "Invalid rip-relative address"); + emitByte(modRMByte(0, RegOpcodeField, 5), OS); unsigned Opcode = MI.getOpcode(); // movq loads are handled with a special relocation form which allows the @@ -395,7 +410,7 @@ void X86MCCodeEmitter::emitMemModRMByte(const MCInst &MI, unsigned Op, default: return X86::reloc_riprel_4byte; case X86::MOV64rm: - assert(Rex); + assert(HasREX); return X86::reloc_riprel_4byte_movq_load; case X86::CALL64m: case X86::JMP64m: @@ -409,8 +424,8 @@ void X86MCCodeEmitter::emitMemModRMByte(const MCInst &MI, unsigned Op, case X86::SBB64rm: case X86::SUB64rm: case X86::XOR64rm: - return Rex ? X86::reloc_riprel_4byte_relax_rex - : X86::reloc_riprel_4byte_relax; + return HasREX ? X86::reloc_riprel_4byte_relax_rex + : X86::reloc_riprel_4byte_relax; } }(); @@ -425,7 +440,7 @@ void X86MCCodeEmitter::emitMemModRMByte(const MCInst &MI, unsigned Op, ? X86II::getSizeOfImm(TSFlags) : 0; - emitImmediate(Disp, MI.getLoc(), 4, MCFixupKind(FixupKind), CurByte, OS, + emitImmediate(Disp, MI.getLoc(), 4, MCFixupKind(FixupKind), StartByte, OS, Fixups, -ImmSize); return; } @@ -472,23 +487,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), 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), OS); + emitImmediate(Disp, MI.getLoc(), 1, FK_Data_1, StartByte, OS, Fixups); return; } // This is the [REG]+disp16 case. - emitByte(modRMByte(2, RegOpcodeField, RMfield), CurByte, OS); + emitByte(modRMByte(2, RegOpcodeField, RMfield), OS); } else { // There is no BaseReg; this is the plain [disp16] case. - emitByte(modRMByte(0, RegOpcodeField, 6), CurByte, OS); + emitByte(modRMByte(0, RegOpcodeField, 6), 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, StartByte, OS, Fixups); return; } @@ -498,7 +513,7 @@ void X86MCCodeEmitter::emitMemModRMByte(const MCInst &MI, unsigned Op, // 2-7) and absolute references. if ( // The SIB byte must be used if there is an index register. - IndexReg.getReg() == 0 && + !ForceSIB && 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 // present. @@ -508,8 +523,8 @@ void X86MCCodeEmitter::emitMemModRMByte(const MCInst &MI, unsigned Op, (!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); + emitByte(modRMByte(0, RegOpcodeField, 5), OS); + emitImmediate(Disp, MI.getLoc(), 4, FK_Data_4, StartByte, OS, Fixups); return; } @@ -519,7 +534,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), OS); return; } @@ -530,7 +545,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), OS); return; } } @@ -539,27 +554,27 @@ 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), OS); + emitImmediate(Disp, MI.getLoc(), 1, FK_Data_1, StartByte, 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), OS); + emitImmediate(Disp, MI.getLoc(), 1, FK_Data_1, StartByte, 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), 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), StartByte, OS, Fixups); return; } @@ -575,30 +590,30 @@ void X86MCCodeEmitter::emitMemModRMByte(const MCInst &MI, unsigned Op, 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), OS); ForceDisp32 = true; } else if (!Disp.isImm()) { // Emit the normal disp32 encoding. - emitByte(modRMByte(2, RegOpcodeField, 4), CurByte, OS); + emitByte(modRMByte(2, RegOpcodeField, 4), 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), OS); } else if (!HasEVEX && isDisp8(Disp.getImm())) { // Emit the disp8 encoding. - emitByte(modRMByte(1, RegOpcodeField, 4), CurByte, OS); + emitByte(modRMByte(1, RegOpcodeField, 4), 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); + emitByte(modRMByte(1, RegOpcodeField, 4), 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), OS); } // Calculate what the SS field value should be... @@ -613,77 +628,78 @@ void X86MCCodeEmitter::emitMemModRMByte(const MCInst &MI, unsigned Op, 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, OS); } else { unsigned IndexRegNo; if (IndexReg.getReg()) IndexRegNo = getX86RegNum(IndexReg); else IndexRegNo = 4; // For example [ESP+1*<noreg>+4] - emitSIBByte(SS, IndexRegNo, getX86RegNum(Base), CurByte, OS); + emitSIBByte(SS, IndexRegNo, getX86RegNum(Base), OS); } // Do we need to output a displacement? if (ForceDisp8) - emitImmediate(Disp, MI.getLoc(), 1, FK_Data_1, CurByte, OS, Fixups, + emitImmediate(Disp, MI.getLoc(), 1, FK_Data_1, StartByte, OS, Fixups, ImmOffset); else if (ForceDisp32 || Disp.getImm() != 0) emitImmediate(Disp, MI.getLoc(), 4, MCFixupKind(X86::reloc_signed_4byte), - CurByte, OS, Fixups); + StartByte, OS, Fixups); } -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 { +/// Emit all instruction prefixes. +/// +/// \returns true if REX prefix is used, otherwise returns false. +bool X86MCCodeEmitter::emitPrefixImpl(unsigned &CurOp, const MCInst &MI, + const MCSubtargetInfo &STI, + raw_ostream &OS) const { + uint64_t TSFlags = MCII.get(MI.getOpcode()).TSFlags; // 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); + if (MemoryOperand != -1) { + MemoryOperand += CurOp; + emitSegmentOverridePrefix(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); + emitByte(0xF3, OS); if (Flags & X86::IP_HAS_REPEAT_NE) - emitByte(0xF2, CurByte, OS); + emitByte(0xF2, OS); // Emit the address size opcode prefix as needed. - bool need_address_override; + bool NeedAddressOverride; 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; + NeedAddressOverride = true; } else if (MemoryOperand < 0) { - need_address_override = false; + NeedAddressOverride = false; } else if (STI.hasFeature(X86::Mode64Bit)) { assert(!is16BitMemOperand(MI, MemoryOperand, STI)); - need_address_override = is32BitMemOperand(MI, MemoryOperand); + NeedAddressOverride = is32BitMemOperand(MI, MemoryOperand); } else if (STI.hasFeature(X86::Mode32Bit)) { assert(!is64BitMemOperand(MI, MemoryOperand)); - need_address_override = is16BitMemOperand(MI, MemoryOperand, STI); + NeedAddressOverride = is16BitMemOperand(MI, MemoryOperand, STI); } else { assert(STI.hasFeature(X86::Mode16Bit)); assert(!is64BitMemOperand(MI, MemoryOperand)); - need_address_override = !is16BitMemOperand(MI, MemoryOperand, STI); + NeedAddressOverride = !is16BitMemOperand(MI, MemoryOperand, STI); } - if (need_address_override) - emitByte(0x67, CurByte, OS); + if (NeedAddressOverride) + emitByte(0x67, OS); // Encoding type for this instruction. uint64_t Encoding = TSFlags & X86II::EncodingMask; - if (Encoding == 0) - Rex = emitOpcodePrefix(TSFlags, CurByte, MemoryOperand, MI, Desc, STI, OS); + bool HasREX = false; + if (Encoding) + emitVEXOpcodePrefix(MemoryOperand, MI, OS); else - emitVEXOpcodePrefix(TSFlags, CurByte, MemoryOperand, MI, Desc, OS); + HasREX = emitOpcodePrefix(MemoryOperand, MI, STI, OS); uint64_t Form = TSFlags & X86II::FormMask; switch (Form) { @@ -697,11 +713,11 @@ void X86MCCodeEmitter::emitPrefixImpl(uint64_t TSFlags, unsigned &CurOp, "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); + emitSegmentOverridePrefix(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); + emitByte(0x67, OS); CurOp += 3; // Consume operands. break; } @@ -709,11 +725,11 @@ void X86MCCodeEmitter::emitPrefixImpl(uint64_t TSFlags, unsigned &CurOp, 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); + emitSegmentOverridePrefix(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); + emitByte(0x67, OS); CurOp += 2; // Consume operands. break; } @@ -722,24 +738,26 @@ void X86MCCodeEmitter::emitPrefixImpl(uint64_t TSFlags, unsigned &CurOp, // Emit AdSize prefix as needed. if ((!STI.hasFeature(X86::Mode32Bit) && siReg == X86::EDI) || (STI.hasFeature(X86::Mode32Bit) && siReg == X86::DI)) - emitByte(0x67, CurByte, OS); + emitByte(0x67, OS); ++CurOp; // Consume operand. break; } case X86II::RawFrmMemOffs: { // Emit segment override opcode prefix as needed. - emitSegmentOverridePrefix(CurByte, 1, MI, OS); + emitSegmentOverridePrefix(1, MI, OS); break; } } + + return HasREX; } -/// emitVEXOpcodePrefix - AVX instructions are encoded using a opcode prefix -/// called VEX. -void X86MCCodeEmitter::emitVEXOpcodePrefix(uint64_t TSFlags, unsigned &CurByte, - int MemOperand, const MCInst &MI, - const MCInstrDesc &Desc, +/// AVX instructions are encoded using a opcode prefix called VEX. +void X86MCCodeEmitter::emitVEXOpcodePrefix(int MemOperand, const MCInst &MI, raw_ostream &OS) const { + const MCInstrDesc &Desc = MCII.get(MI.getOpcode()); + uint64_t TSFlags = Desc.TSFlags; + assert(!(TSFlags & X86II::LOCK) && "Can't have LOCK VEX."); uint64_t Encoding = TSFlags & X86II::EncodingMask; @@ -868,8 +886,11 @@ void X86MCCodeEmitter::emitVEXOpcodePrefix(uint64_t TSFlags, unsigned &CurByte, switch (TSFlags & X86II::FormMask) { default: llvm_unreachable("Unexpected form in emitVEXOpcodePrefix!"); + case X86II::MRM_C0: case X86II::RawFrm: + case X86II::PrefixByte: break; + case X86II::MRMDestMemFSIB: case X86II::MRMDestMem: { // MRMDestMem instructions forms: // MemAddr, src1(ModR/M) @@ -900,6 +921,7 @@ void X86MCCodeEmitter::emitVEXOpcodePrefix(uint64_t TSFlags, unsigned &CurByte, EVEX_R2 = ~(RegEnc >> 4) & 1; break; } + case X86II::MRMSrcMemFSIB: case X86II::MRMSrcMem: { // MRMSrcMem instructions forms: // src1(ModR/M), MemAddr @@ -1081,6 +1103,15 @@ void X86MCCodeEmitter::emitVEXOpcodePrefix(uint64_t TSFlags, unsigned &CurByte, EncodeRC = true; break; } + case X86II::MRMr0: { + // MRMr0 instructions forms: + // 11:rrr:000 + // dst(ModR/M) + unsigned RegEnc = getX86RegEncoding(MI, CurOp++); + VEX_R = ~(RegEnc >> 3) & 1; + EVEX_R2 = ~(RegEnc >> 4) & 1; + break; + } case X86II::MRM0r: case X86II::MRM1r: case X86II::MRM2r: @@ -1127,15 +1158,15 @@ void X86MCCodeEmitter::emitVEXOpcodePrefix(uint64_t TSFlags, unsigned &CurByte, // 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); + emitByte(0xC5, OS); + emitByte(LastByte | (VEX_R << 7), 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, OS); + emitByte(VEX_R << 7 | VEX_X << 6 | VEX_B << 5 | VEX_5M, OS); + emitByte(LastByte | (VEX_W << 7), OS); } else { assert(Encoding == X86II::EVEX && "unknown encoding!"); // EVEX opcode prefix can have 4 bytes @@ -1146,144 +1177,137 @@ void X86MCCodeEmitter::emitVEXOpcodePrefix(uint64_t TSFlags, unsigned &CurByte, assert((VEX_5M & 0x3) == VEX_5M && "More than 2 significant bits in VEX.m-mmmm fields for EVEX!"); - emitByte(0x62, CurByte, OS); + emitByte(0x62, 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((VEX_W << 7) | (VEX_4V << 3) | (EVEX_U << 2) | VEX_PP, OS); if (EncodeRC) emitByte((EVEX_z << 7) | (EVEX_rc << 5) | (EVEX_b << 4) | (EVEX_V2 << 3) | EVEX_aaa, - CurByte, OS); + OS); else emitByte((EVEX_z << 7) | (EVEX_L2 << 6) | (VEX_L << 5) | (EVEX_b << 4) | (EVEX_V2 << 3) | EVEX_aaa, - CurByte, OS); + OS); } } -/// 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; - bool UsesHighByteReg = false; - - if (TSFlags & X86II::REX_W) - REX |= 1 << 3; // set REX.W +/// Emit REX prefix which specifies +/// 1) 64-bit instructions, +/// 2) non-default operand size, and +/// 3) use of X86-64 extended registers. +/// +/// \returns true if REX prefix is used, otherwise returns false. +bool X86MCCodeEmitter::emitREXPrefix(int MemOperand, const MCInst &MI, + raw_ostream &OS) const { + uint8_t REX = [&, MemOperand]() { + uint8_t REX = 0; + bool UsesHighByteReg = false; + + const MCInstrDesc &Desc = MCII.get(MI.getOpcode()); + uint64_t TSFlags = Desc.TSFlags; + + if (TSFlags & X86II::REX_W) + REX |= 1 << 3; // set REX.W + + if (MI.getNumOperands() == 0) + return REX; + + unsigned NumOps = MI.getNumOperands(); + unsigned CurOp = X86II::getOperandBias(Desc); + + // 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; + 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 that returns non-zero. + REX |= 0x40; // REX fixed encoding prefix + } - if (MI.getNumOperands() == 0) + switch (TSFlags & X86II::FormMask) { + case X86II::AddRegFrm: + REX |= isREXExtendedReg(MI, CurOp++) << 0; // REX.B + break; + case X86II::MRMSrcReg: + case X86II::MRMSrcRegCC: + REX |= isREXExtendedReg(MI, CurOp++) << 2; // REX.R + REX |= isREXExtendedReg(MI, CurOp++) << 0; // REX.B + 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 + CurOp += X86::AddrNumOperands; + break; + case X86II::MRMDestReg: + REX |= isREXExtendedReg(MI, CurOp++) << 0; // REX.B + 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 + 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 + 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: + REX |= isREXExtendedReg(MI, CurOp++) << 0; // REX.B + break; + case X86II::MRMr0: + REX |= isREXExtendedReg(MI, CurOp++) << 2; // REX.R + break; + case X86II::MRMDestMemFSIB: + llvm_unreachable("FSIB format never need REX prefix!"); + } + if (REX && UsesHighByteReg) + report_fatal_error( + "Cannot encode high byte register in REX-prefixed instruction"); return REX; + }(); - unsigned NumOps = MI.getNumOperands(); - unsigned CurOp = X86II::getOperandBias(Desc); - - // 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; - 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 - // that returns non-zero. - REX |= 0x40; // REX fixed encoding prefix - } - - switch (TSFlags & X86II::FormMask) { - case X86II::AddRegFrm: - REX |= isREXExtendedReg(MI, CurOp++) << 0; // REX.B - break; - case X86II::MRMSrcReg: - case X86II::MRMSrcRegCC: - REX |= isREXExtendedReg(MI, CurOp++) << 2; // REX.R - REX |= isREXExtendedReg(MI, CurOp++) << 0; // REX.B - 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 - CurOp += X86::AddrNumOperands; - break; - case X86II::MRMDestReg: - REX |= isREXExtendedReg(MI, CurOp++) << 0; // REX.B - 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 - 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 - 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: - REX |= isREXExtendedReg(MI, CurOp++) << 0; // REX.B - break; - } - if (REX && UsesHighByteReg) - report_fatal_error( - "Cannot encode high byte register in REX-prefixed instruction"); + if (!REX) + return false; - return REX; + emitByte(0x40 | REX, OS); + return true; } /// Emit segment override opcode prefix as needed. -void X86MCCodeEmitter::emitSegmentOverridePrefix(unsigned &CurByte, - unsigned SegOperand, +void X86MCCodeEmitter::emitSegmentOverridePrefix(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; - } + if (unsigned Reg = MI.getOperand(SegOperand).getReg()) + emitByte(X86::getSegmentOverridePrefixForReg(Reg), OS); } /// Emit all instruction prefixes prior to the opcode. @@ -1291,48 +1315,44 @@ void X86MCCodeEmitter::emitSegmentOverridePrefix(unsigned &CurByte, /// \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. -bool X86MCCodeEmitter::emitOpcodePrefix(uint64_t TSFlags, unsigned &CurByte, - int MemOperand, const MCInst &MI, - const MCInstrDesc &Desc, +/// \returns true if REX prefix is used, otherwise returns false. +bool X86MCCodeEmitter::emitOpcodePrefix(int MemOperand, const MCInst &MI, const MCSubtargetInfo &STI, raw_ostream &OS) const { - bool Ret = false; + const MCInstrDesc &Desc = MCII.get(MI.getOpcode()); + uint64_t TSFlags = Desc.TSFlags; + // Emit the operand size opcode prefix as needed. if ((TSFlags & X86II::OpSizeMask) == (STI.hasFeature(X86::Mode16Bit) ? X86II::OpSize32 : X86II::OpSize16)) - emitByte(0x66, CurByte, OS); + emitByte(0x66, OS); // Emit the LOCK opcode prefix. if (TSFlags & X86II::LOCK || MI.getFlags() & X86::IP_HAS_LOCK) - emitByte(0xF0, CurByte, OS); + emitByte(0xF0, OS); // Emit the NOTRACK opcode prefix. if (TSFlags & X86II::NOTRACK || MI.getFlags() & X86::IP_HAS_NOTRACK) - emitByte(0x3E, CurByte, OS); + emitByte(0x3E, OS); switch (TSFlags & X86II::OpPrefixMask) { case X86II::PD: // 66 - emitByte(0x66, CurByte, OS); + emitByte(0x66, OS); break; case X86II::XS: // F3 - emitByte(0xF3, CurByte, OS); + emitByte(0xF3, OS); break; case X86II::XD: // F2 - emitByte(0xF2, CurByte, OS); + emitByte(0xF2, OS); break; } // Handle REX prefix. - // FIXME: Can this come before F2 etc to simplify emission? - if (STI.hasFeature(X86::Mode64Bit)) { - if (uint8_t REX = determineREXPrefix(MI, TSFlags, MemOperand, Desc)) { - emitByte(0x40 | REX, CurByte, OS); - Ret = true; - } - } else { - assert(!(TSFlags & X86II::REX_W) && "REX.W requires 64bit mode."); - } + assert((STI.hasFeature(X86::Mode64Bit) || !(TSFlags & X86II::REX_W)) && + "REX.W requires 64bit mode."); + bool HasREX = STI.hasFeature(X86::Mode64Bit) + ? emitREXPrefix(MemOperand, MI, OS) + : false; // 0x0F escape code must be emitted just before the opcode. switch (TSFlags & X86II::OpMapMask) { @@ -1340,19 +1360,20 @@ bool X86MCCodeEmitter::emitOpcodePrefix(uint64_t TSFlags, unsigned &CurByte, case X86II::T8: // 0F 38 case X86II::TA: // 0F 3A case X86II::ThreeDNow: // 0F 0F, second 0F emitted by caller. - emitByte(0x0F, CurByte, OS); + emitByte(0x0F, OS); break; } switch (TSFlags & X86II::OpMapMask) { case X86II::T8: // 0F 38 - emitByte(0x38, CurByte, OS); + emitByte(0x38, OS); break; case X86II::TA: // 0F 3A - emitByte(0x3A, CurByte, OS); + emitByte(0x3A, OS); break; } - return Ret; + + return HasREX; } void X86MCCodeEmitter::emitPrefix(const MCInst &MI, raw_ostream &OS, @@ -1362,16 +1383,12 @@ void X86MCCodeEmitter::emitPrefix(const MCInst &MI, raw_ostream &OS, uint64_t TSFlags = Desc.TSFlags; // Pseudo instructions don't get encoded. - if ((TSFlags & X86II::FormMask) == X86II::Pseudo) + if (X86II::isPseudo(TSFlags)) 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); + emitPrefixImpl(CurOp, MI, STI, OS); } void X86MCCodeEmitter::encodeInstruction(const MCInst &MI, raw_ostream &OS, @@ -1382,17 +1399,15 @@ void X86MCCodeEmitter::encodeInstruction(const MCInst &MI, raw_ostream &OS, uint64_t TSFlags = Desc.TSFlags; // Pseudo instructions don't get encoded. - if ((TSFlags & X86II::FormMask) == X86II::Pseudo) + if (X86II::isPseudo(TSFlags)) return; unsigned NumOps = Desc.getNumOperands(); unsigned CurOp = X86II::getOperandBias(Desc); - // Keep track of the current byte being emitted. - unsigned CurByte = 0; + uint64_t StartByte = OS.tell(); - bool Rex = false; - emitPrefixImpl(TSFlags, CurOp, CurByte, Rex, MI, Desc, STI, OS); + bool HasREX = emitPrefixImpl(CurOp, MI, STI, OS); // It uses the VEX.VVVV field? bool HasVEX_4V = TSFlags & X86II::VEX_4V; @@ -1422,7 +1437,8 @@ void X86MCCodeEmitter::encodeInstruction(const MCInst &MI, raw_ostream &OS, case X86II::RawFrmDstSrc: case X86II::RawFrmSrc: case X86II::RawFrmDst: - emitByte(BaseOpcode, CurByte, OS); + case X86II::PrefixByte: + emitByte(BaseOpcode, OS); break; case X86II::AddCCFrm: { // This will be added to the opcode in the fallthrough. @@ -1431,47 +1447,47 @@ void X86MCCodeEmitter::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, OS); if (!STI.hasFeature(X86::Mode64Bit) || !isPCRel32Branch(MI, MCII)) break; const MCOperand &Op = MI.getOperand(CurOp++); emitImmediate(Op, MI.getLoc(), X86II::getSizeOfImm(TSFlags), - MCFixupKind(X86::reloc_branch_4byte_pcrel), CurByte, OS, + MCFixupKind(X86::reloc_branch_4byte_pcrel), StartByte, OS, Fixups); break; } case X86II::RawFrmMemOffs: - emitByte(BaseOpcode, CurByte, OS); + emitByte(BaseOpcode, OS); emitImmediate(MI.getOperand(CurOp++), MI.getLoc(), X86II::getSizeOfImm(TSFlags), getImmFixupKind(TSFlags), - CurByte, OS, Fixups); + StartByte, OS, Fixups); ++CurOp; // skip segment operand break; case X86II::RawFrmImm8: - emitByte(BaseOpcode, CurByte, OS); + emitByte(BaseOpcode, 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, + StartByte, OS, Fixups); + emitImmediate(MI.getOperand(CurOp++), MI.getLoc(), 1, FK_Data_1, StartByte, OS, Fixups); break; case X86II::RawFrmImm16: - emitByte(BaseOpcode, CurByte, OS); + emitByte(BaseOpcode, 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, + StartByte, OS, Fixups); + emitImmediate(MI.getOperand(CurOp++), MI.getLoc(), 2, FK_Data_2, StartByte, OS, Fixups); break; case X86II::AddRegFrm: - emitByte(BaseOpcode + getX86RegNum(MI.getOperand(CurOp++)), CurByte, OS); + emitByte(BaseOpcode + getX86RegNum(MI.getOperand(CurOp++)), OS); break; case X86II::MRMDestReg: { - emitByte(BaseOpcode, CurByte, OS); + emitByte(BaseOpcode, OS); unsigned SrcRegNum = CurOp + 1; if (HasEVEX_K) // Skip writemask @@ -1481,12 +1497,13 @@ void X86MCCodeEmitter::encodeInstruction(const MCInst &MI, raw_ostream &OS, ++SrcRegNum; emitRegModRMByte(MI.getOperand(CurOp), - getX86RegNum(MI.getOperand(SrcRegNum)), CurByte, OS); + getX86RegNum(MI.getOperand(SrcRegNum)), OS); CurOp = SrcRegNum + 1; break; } + case X86II::MRMDestMemFSIB: case X86II::MRMDestMem: { - emitByte(BaseOpcode, CurByte, OS); + emitByte(BaseOpcode, OS); unsigned SrcRegNum = CurOp + X86::AddrNumOperands; if (HasEVEX_K) // Skip writemask @@ -1495,13 +1512,14 @@ void X86MCCodeEmitter::encodeInstruction(const MCInst &MI, raw_ostream &OS, if (HasVEX_4V) // Skip 1st src (which is encoded in VEX_VVVV) ++SrcRegNum; + bool ForceSIB = (Form == X86II::MRMDestMemFSIB); emitMemModRMByte(MI, CurOp, getX86RegNum(MI.getOperand(SrcRegNum)), TSFlags, - Rex, CurByte, OS, Fixups, STI); + HasREX, StartByte, OS, Fixups, STI, ForceSIB); CurOp = SrcRegNum + 1; break; } case X86II::MRMSrcReg: { - emitByte(BaseOpcode, CurByte, OS); + emitByte(BaseOpcode, OS); unsigned SrcRegNum = CurOp + 1; if (HasEVEX_K) // Skip writemask @@ -1511,7 +1529,7 @@ void X86MCCodeEmitter::encodeInstruction(const MCInst &MI, raw_ostream &OS, ++SrcRegNum; emitRegModRMByte(MI.getOperand(SrcRegNum), - getX86RegNum(MI.getOperand(CurOp)), CurByte, OS); + getX86RegNum(MI.getOperand(CurOp)), OS); CurOp = SrcRegNum + 1; if (HasVEX_I8Reg) I8RegNum = getX86RegEncoding(MI, CurOp++); @@ -1521,17 +1539,17 @@ void X86MCCodeEmitter::encodeInstruction(const MCInst &MI, raw_ostream &OS, break; } case X86II::MRMSrcReg4VOp3: { - emitByte(BaseOpcode, CurByte, OS); + emitByte(BaseOpcode, OS); unsigned SrcRegNum = CurOp + 1; emitRegModRMByte(MI.getOperand(SrcRegNum), - getX86RegNum(MI.getOperand(CurOp)), CurByte, OS); + getX86RegNum(MI.getOperand(CurOp)), OS); CurOp = SrcRegNum + 1; ++CurOp; // Encoded in VEX.VVVV break; } case X86II::MRMSrcRegOp4: { - emitByte(BaseOpcode, CurByte, OS); + emitByte(BaseOpcode, OS); unsigned SrcRegNum = CurOp + 1; // Skip 1st src (which is encoded in VEX_VVVV) @@ -1542,7 +1560,7 @@ void X86MCCodeEmitter::encodeInstruction(const MCInst &MI, raw_ostream &OS, I8RegNum = getX86RegEncoding(MI, SrcRegNum++); emitRegModRMByte(MI.getOperand(SrcRegNum), - getX86RegNum(MI.getOperand(CurOp)), CurByte, OS); + getX86RegNum(MI.getOperand(CurOp)), OS); CurOp = SrcRegNum + 1; break; } @@ -1551,12 +1569,13 @@ void X86MCCodeEmitter::encodeInstruction(const MCInst &MI, raw_ostream &OS, unsigned SecondOp = CurOp++; unsigned CC = MI.getOperand(CurOp++).getImm(); - emitByte(BaseOpcode + CC, CurByte, OS); + emitByte(BaseOpcode + CC, OS); emitRegModRMByte(MI.getOperand(SecondOp), - getX86RegNum(MI.getOperand(FirstOp)), CurByte, OS); + getX86RegNum(MI.getOperand(FirstOp)), OS); break; } + case X86II::MRMSrcMemFSIB: case X86II::MRMSrcMem: { unsigned FirstMemOp = CurOp + 1; @@ -1566,10 +1585,11 @@ void X86MCCodeEmitter::encodeInstruction(const MCInst &MI, raw_ostream &OS, if (HasVEX_4V) ++FirstMemOp; // Skip the register source (which is encoded in VEX_VVVV). - emitByte(BaseOpcode, CurByte, OS); + emitByte(BaseOpcode, OS); + bool ForceSIB = (Form == X86II::MRMSrcMemFSIB); emitMemModRMByte(MI, FirstMemOp, getX86RegNum(MI.getOperand(CurOp)), - TSFlags, Rex, CurByte, OS, Fixups, STI); + TSFlags, HasREX, StartByte, OS, Fixups, STI, ForceSIB); CurOp = FirstMemOp + X86::AddrNumOperands; if (HasVEX_I8Reg) I8RegNum = getX86RegEncoding(MI, CurOp++); @@ -1578,10 +1598,10 @@ void X86MCCodeEmitter::encodeInstruction(const MCInst &MI, raw_ostream &OS, case X86II::MRMSrcMem4VOp3: { unsigned FirstMemOp = CurOp + 1; - emitByte(BaseOpcode, CurByte, OS); + emitByte(BaseOpcode, OS); emitMemModRMByte(MI, FirstMemOp, getX86RegNum(MI.getOperand(CurOp)), - TSFlags, Rex, CurByte, OS, Fixups, STI); + TSFlags, HasREX, StartByte, OS, Fixups, STI); CurOp = FirstMemOp + X86::AddrNumOperands; ++CurOp; // Encoded in VEX.VVVV. break; @@ -1595,10 +1615,10 @@ void X86MCCodeEmitter::encodeInstruction(const MCInst &MI, raw_ostream &OS, assert(HasVEX_I8Reg && "MRMSrcRegOp4 should imply VEX_I8Reg"); I8RegNum = getX86RegEncoding(MI, FirstMemOp++); - emitByte(BaseOpcode, CurByte, OS); + emitByte(BaseOpcode, OS); emitMemModRMByte(MI, FirstMemOp, getX86RegNum(MI.getOperand(CurOp)), - TSFlags, Rex, CurByte, OS, Fixups, STI); + TSFlags, HasREX, StartByte, OS, Fixups, STI); CurOp = FirstMemOp + X86::AddrNumOperands; break; } @@ -1608,10 +1628,10 @@ void X86MCCodeEmitter::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, OS); emitMemModRMByte(MI, FirstMemOp, getX86RegNum(MI.getOperand(RegOp)), - TSFlags, Rex, CurByte, OS, Fixups, STI); + TSFlags, HasREX, StartByte, OS, Fixups, STI); break; } @@ -1619,8 +1639,8 @@ void X86MCCodeEmitter::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, OS); + emitRegModRMByte(MI.getOperand(RegOp), 0, OS); break; } @@ -1637,10 +1657,13 @@ void X86MCCodeEmitter::encodeInstruction(const MCInst &MI, raw_ostream &OS, ++CurOp; if (HasEVEX_K) // Skip writemask ++CurOp; - emitByte(BaseOpcode, CurByte, OS); + emitByte(BaseOpcode, OS); emitRegModRMByte(MI.getOperand(CurOp++), - (Form == X86II::MRMXr) ? 0 : Form - X86II::MRM0r, CurByte, - OS); + (Form == X86II::MRMXr) ? 0 : Form - X86II::MRM0r, OS); + break; + case X86II::MRMr0: + emitByte(BaseOpcode, OS); + emitByte(modRMByte(3, getX86RegNum(MI.getOperand(CurOp++)),0), OS); break; case X86II::MRMXmCC: { @@ -1648,9 +1671,10 @@ void X86MCCodeEmitter::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, OS); - emitMemModRMByte(MI, FirstMemOp, 0, TSFlags, Rex, CurByte, OS, Fixups, STI); + emitMemModRMByte(MI, FirstMemOp, 0, TSFlags, HasREX, StartByte, OS, Fixups, + STI); break; } @@ -1667,13 +1691,25 @@ void X86MCCodeEmitter::encodeInstruction(const MCInst &MI, raw_ostream &OS, ++CurOp; if (HasEVEX_K) // Skip writemask ++CurOp; - emitByte(BaseOpcode, CurByte, OS); + emitByte(BaseOpcode, OS); emitMemModRMByte(MI, CurOp, (Form == X86II::MRMXm) ? 0 : Form - X86II::MRM0m, TSFlags, - Rex, CurByte, OS, Fixups, STI); + HasREX, StartByte, OS, Fixups, STI); CurOp += X86::AddrNumOperands; break; + case X86II::MRM0X: + case X86II::MRM1X: + case X86II::MRM2X: + case X86II::MRM3X: + case X86II::MRM4X: + case X86II::MRM5X: + case X86II::MRM6X: + case X86II::MRM7X: + emitByte(BaseOpcode, OS); + emitByte(0xC0 + ((Form - X86II::MRM0X) << 3), OS); + break; + case X86II::MRM_C0: case X86II::MRM_C1: case X86II::MRM_C2: @@ -1738,8 +1774,8 @@ void X86MCCodeEmitter::encodeInstruction(const MCInst &MI, raw_ostream &OS, 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, OS); + emitByte(0xC0 + Form - X86II::MRM_C0, OS); break; } @@ -1754,7 +1790,7 @@ void X86MCCodeEmitter::encodeInstruction(const MCInst &MI, raw_ostream &OS, I8RegNum |= Val; } emitImmediate(MCOperand::createImm(I8RegNum), MI.getLoc(), 1, FK_Data_1, - CurByte, OS, Fixups); + StartByte, 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 @@ -1762,13 +1798,15 @@ void X86MCCodeEmitter::encodeInstruction(const MCInst &MI, raw_ostream &OS, while (CurOp != NumOps && NumOps - CurOp <= 2) { emitImmediate(MI.getOperand(CurOp++), MI.getLoc(), X86II::getSizeOfImm(TSFlags), getImmFixupKind(TSFlags), - CurByte, OS, Fixups); + StartByte, OS, Fixups); } } if ((TSFlags & X86II::OpMapMask) == X86II::ThreeDNow) - emitByte(X86II::getBaseOpcodeFor(TSFlags), CurByte, OS); + emitByte(X86II::getBaseOpcodeFor(TSFlags), OS); + assert(OS.tell() - StartByte <= 15 && + "The size of instruction must be no longer than 15."); #ifndef NDEBUG // FIXME: Verify. if (/*!Desc.isVariadic() &&*/ CurOp != NumOps) { |