diff --git a/include/llvm/MC/MCCodeEmitter.h b/include/llvm/MC/MCCodeEmitter.h index 04b4367ada7..2794acc0753 100644 --- a/include/llvm/MC/MCCodeEmitter.h +++ b/include/llvm/MC/MCCodeEmitter.h @@ -30,6 +30,12 @@ public: /// Lifetime management virtual void reset() {} + /// Emit the prefixes of given instruction on the output stream. + /// + /// \param Inst a single low-level machine instruction. + /// \param OS output stream. + virtual void emitPrefix(const MCInst &Inst, raw_ostream &OS, + const MCSubtargetInfo &STI) const {} /// EncodeInstruction - Encode the given \p Inst to bytes on the output /// stream \p OS. virtual void encodeInstruction(const MCInst &Inst, raw_ostream &OS, diff --git a/lib/Target/X86/MCTargetDesc/X86MCCodeEmitter.cpp b/lib/Target/X86/MCTargetDesc/X86MCCodeEmitter.cpp index c8c4046ee39..54a293702bd 100644 --- a/lib/Target/X86/MCTargetDesc/X86MCCodeEmitter.cpp +++ b/lib/Target/X86/MCTargetDesc/X86MCCodeEmitter.cpp @@ -47,6 +47,9 @@ public: X86MCCodeEmitter &operator=(const X86MCCodeEmitter &) = delete; ~X86MCCodeEmitter() override = default; + void emitPrefix(const MCInst &MI, raw_ostream &OS, + const MCSubtargetInfo &STI) const override; + void encodeInstruction(const MCInst &MI, raw_ostream &OS, SmallVectorImpl &Fixups, const MCSubtargetInfo &STI) const override; @@ -108,6 +111,10 @@ private: raw_ostream &OS, SmallVectorImpl &Fixups, const MCSubtargetInfo &STI) 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; + void emitVEXOpcodePrefix(uint64_t TSFlags, unsigned &CurByte, int MemOperand, const MCInst &MI, const MCInstrDesc &Desc, raw_ostream &OS) const; @@ -625,6 +632,108 @@ void X86MCCodeEmitter::emitMemModRMByte(const MCInst &MI, unsigned Op, CurByte, 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 { + // 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, @@ -1246,13 +1355,31 @@ bool X86MCCodeEmitter::emitOpcodePrefix(uint64_t TSFlags, unsigned &CurByte, return Ret; } +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 &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) @@ -1264,8 +1391,8 @@ void X86MCCodeEmitter::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; @@ -1278,52 +1405,6 @@ void X86MCCodeEmitter::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 ((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); - - 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) @@ -1338,46 +1419,11 @@ void X86MCCodeEmitter::encodeInstruction(const MCInst &MI, raw_ostream &OS, 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 ((!STI.hasFeature(X86::Mode32Bit) && siReg == X86::ESI) || - (STI.hasFeature(X86::Mode32Bit) && siReg == X86::SI)) - emitByte(0x67, CurByte, OS); - CurOp += 3; // Consume operands. + case X86II::RawFrmDstSrc: + case X86II::RawFrmSrc: + case X86II::RawFrmDst: 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 ((!STI.hasFeature(X86::Mode32Bit) && siReg == X86::ESI) || - (STI.hasFeature(X86::Mode32Bit) && siReg == X86::SI)) - emitByte(0x67, CurByte, OS); - CurOp += 2; // Consume operands. - emitByte(BaseOpcode, CurByte, OS); - 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. - emitByte(BaseOpcode, CurByte, OS); - break; - } case X86II::AddCCFrm: { // This will be added to the opcode in the fallthrough. OpcodeOffset = MI.getOperand(NumOps - 1).getImm(); @@ -1397,8 +1443,6 @@ void X86MCCodeEmitter::encodeInstruction(const MCInst &MI, raw_ostream &OS, 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(), X86II::getSizeOfImm(TSFlags), getImmFixupKind(TSFlags),