diff options
author | Stephen Hines <srhines@google.com> | 2014-04-23 16:57:46 -0700 |
---|---|---|
committer | Stephen Hines <srhines@google.com> | 2014-04-24 15:53:16 -0700 |
commit | 36b56886974eae4f9c5ebc96befd3e7bfe5de338 (patch) | |
tree | e6cfb69fbbd937f450eeb83bfb83b9da3b01275a /lib/Target/X86/MCTargetDesc | |
parent | 69a8640022b04415ae9fac62f8ab090601d8f889 (diff) | |
download | external_llvm-36b56886974eae4f9c5ebc96befd3e7bfe5de338.zip external_llvm-36b56886974eae4f9c5ebc96befd3e7bfe5de338.tar.gz external_llvm-36b56886974eae4f9c5ebc96befd3e7bfe5de338.tar.bz2 |
Update to LLVM 3.5a.
Change-Id: Ifadecab779f128e62e430c2b4f6ddd84953ed617
Diffstat (limited to 'lib/Target/X86/MCTargetDesc')
-rw-r--r-- | lib/Target/X86/MCTargetDesc/Android.mk | 2 | ||||
-rw-r--r-- | lib/Target/X86/MCTargetDesc/CMakeLists.txt | 5 | ||||
-rw-r--r-- | lib/Target/X86/MCTargetDesc/X86AsmBackend.cpp | 85 | ||||
-rw-r--r-- | lib/Target/X86/MCTargetDesc/X86BaseInfo.h | 278 | ||||
-rw-r--r-- | lib/Target/X86/MCTargetDesc/X86ELFObjectWriter.cpp | 35 | ||||
-rw-r--r-- | lib/Target/X86/MCTargetDesc/X86ELFRelocationInfo.cpp | 4 | ||||
-rw-r--r-- | lib/Target/X86/MCTargetDesc/X86MCAsmInfo.cpp | 31 | ||||
-rw-r--r-- | lib/Target/X86/MCTargetDesc/X86MCAsmInfo.h | 18 | ||||
-rw-r--r-- | lib/Target/X86/MCTargetDesc/X86MCCodeEmitter.cpp | 662 | ||||
-rw-r--r-- | lib/Target/X86/MCTargetDesc/X86MCTargetDesc.cpp | 27 | ||||
-rw-r--r-- | lib/Target/X86/MCTargetDesc/X86MachORelocationInfo.cpp | 12 | ||||
-rw-r--r-- | lib/Target/X86/MCTargetDesc/X86MachObjectWriter.cpp | 9 | ||||
-rw-r--r-- | lib/Target/X86/MCTargetDesc/X86WinCOFFObjectWriter.cpp | 8 |
13 files changed, 685 insertions, 491 deletions
diff --git a/lib/Target/X86/MCTargetDesc/Android.mk b/lib/Target/X86/MCTargetDesc/Android.mk index 65cd8df..ee37c27 100644 --- a/lib/Target/X86/MCTargetDesc/Android.mk +++ b/lib/Target/X86/MCTargetDesc/Android.mk @@ -36,6 +36,7 @@ include $(BUILD_HOST_STATIC_LIBRARY) # For the device only # ===================================================== +ifneq (true,$(DISABLE_LLVM_DEVICE_BUILDS)) include $(CLEAR_VARS) include $(CLEAR_TBLGEN_VARS) @@ -52,3 +53,4 @@ include $(LLVM_DEVICE_BUILD_MK) include $(LLVM_TBLGEN_RULES_MK) include $(LLVM_GEN_INTRINSICS_MK) include $(BUILD_STATIC_LIBRARY) +endif diff --git a/lib/Target/X86/MCTargetDesc/CMakeLists.txt b/lib/Target/X86/MCTargetDesc/CMakeLists.txt index 2eb5f25..3f5a0e2 100644 --- a/lib/Target/X86/MCTargetDesc/CMakeLists.txt +++ b/lib/Target/X86/MCTargetDesc/CMakeLists.txt @@ -9,8 +9,3 @@ add_llvm_library(LLVMX86Desc X86MachORelocationInfo.cpp X86ELFRelocationInfo.cpp ) - -add_dependencies(LLVMX86Desc X86CommonTableGen) - -# Hack: we need to include 'main' target directory to grab private headers -include_directories(${CMAKE_CURRENT_SOURCE_DIR}/.. ${CMAKE_CURRENT_BINARY_DIR}/..) diff --git a/lib/Target/X86/MCTargetDesc/X86AsmBackend.cpp b/lib/Target/X86/MCTargetDesc/X86AsmBackend.cpp index f8e359b..23763f7 100644 --- a/lib/Target/X86/MCTargetDesc/X86AsmBackend.cpp +++ b/lib/Target/X86/MCTargetDesc/X86AsmBackend.cpp @@ -79,11 +79,11 @@ public: CPU != "c3" && CPU != "c3-2"; } - unsigned getNumFixupKinds() const { + unsigned getNumFixupKinds() const override { return X86::NumTargetFixupKinds; } - const MCFixupKindInfo &getFixupKindInfo(MCFixupKind Kind) const { + const MCFixupKindInfo &getFixupKindInfo(MCFixupKind Kind) const override { const static MCFixupKindInfo Infos[X86::NumTargetFixupKinds] = { { "reloc_riprel_4byte", 0, 4 * 8, MCFixupKindInfo::FKF_IsPCRel }, { "reloc_riprel_4byte_movq_load", 0, 4 * 8, MCFixupKindInfo::FKF_IsPCRel}, @@ -100,7 +100,7 @@ public: } void applyFixup(const MCFixup &Fixup, char *Data, unsigned DataSize, - uint64_t Value) const { + uint64_t Value, bool IsPCRel) const override { unsigned Size = 1 << getFixupKindLog2Size(Fixup.getKind()); assert(Fixup.getOffset() + Size <= DataSize && @@ -117,16 +117,15 @@ public: Data[Fixup.getOffset() + i] = uint8_t(Value >> (i * 8)); } - bool mayNeedRelaxation(const MCInst &Inst) const; + bool mayNeedRelaxation(const MCInst &Inst) const override; - bool fixupNeedsRelaxation(const MCFixup &Fixup, - uint64_t Value, + bool fixupNeedsRelaxation(const MCFixup &Fixup, uint64_t Value, const MCRelaxableFragment *DF, - const MCAsmLayout &Layout) const; + const MCAsmLayout &Layout) const override; - void relaxInstruction(const MCInst &Inst, MCInst &Res) const; + void relaxInstruction(const MCInst &Inst, MCInst &Res) const override; - bool writeNopData(uint64_t Count, MCObjectWriter *OW) const; + bool writeNopData(uint64_t Count, MCObjectWriter *OW) const override; }; } // end anonymous namespace @@ -217,9 +216,9 @@ static unsigned getRelaxedOpcodeArith(unsigned Op) { case X86::CMP64mi8: return X86::CMP64mi32; // PUSH - case X86::PUSHi8: return X86::PUSHi32; - case X86::PUSHi16: return X86::PUSHi32; - case X86::PUSH64i8: return X86::PUSH64i32; + case X86::PUSH32i8: return X86::PUSHi32; + case X86::PUSH16i8: return X86::PUSHi16; + case X86::PUSH64i8: return X86::PUSH64i32; case X86::PUSH64i16: return X86::PUSH64i32; } } @@ -314,7 +313,7 @@ bool X86AsmBackend::writeNopData(uint64_t Count, MCObjectWriter *OW) const { {0x66, 0x2e, 0x0f, 0x1f, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00}, }; - // This CPU doesnt support long nops. If needed add more. + // This CPU doesn't support long nops. If needed add more. // FIXME: Can we get this from the subtarget somehow? // FIXME: We could generated something better than plain 0x90. if (!HasNopl) { @@ -347,14 +346,7 @@ class ELFX86AsmBackend : public X86AsmBackend { public: uint8_t OSABI; ELFX86AsmBackend(const Target &T, uint8_t _OSABI, StringRef CPU) - : X86AsmBackend(T, CPU), OSABI(_OSABI) { - HasReliableSymbolDifference = true; - } - - virtual bool doesSectionRequireSymbols(const MCSection &Section) const { - const MCSectionELF &ES = static_cast<const MCSectionELF&>(Section); - return ES.getFlags() & ELF::SHF_MERGE; - } + : X86AsmBackend(T, CPU), OSABI(_OSABI) {} }; class ELFX86_32AsmBackend : public ELFX86AsmBackend { @@ -362,7 +354,7 @@ public: ELFX86_32AsmBackend(const Target &T, uint8_t OSABI, StringRef CPU) : ELFX86AsmBackend(T, OSABI, CPU) {} - MCObjectWriter *createObjectWriter(raw_ostream &OS) const { + MCObjectWriter *createObjectWriter(raw_ostream &OS) const override { return createX86ELFObjectWriter(OS, /*IsELF64*/ false, OSABI, ELF::EM_386); } }; @@ -372,7 +364,7 @@ public: ELFX86_64AsmBackend(const Target &T, uint8_t OSABI, StringRef CPU) : ELFX86AsmBackend(T, OSABI, CPU) {} - MCObjectWriter *createObjectWriter(raw_ostream &OS) const { + MCObjectWriter *createObjectWriter(raw_ostream &OS) const override { return createX86ELFObjectWriter(OS, /*IsELF64*/ true, OSABI, ELF::EM_X86_64); } }; @@ -386,7 +378,7 @@ public: , Is64Bit(is64Bit) { } - MCObjectWriter *createObjectWriter(raw_ostream &OS) const { + MCObjectWriter *createObjectWriter(raw_ostream &OS) const override { return createX86WinCOFFObjectWriter(OS, Is64Bit); } }; @@ -725,15 +717,15 @@ public: StringRef CPU, bool SupportsCU) : DarwinX86AsmBackend(T, MRI, CPU, false), SupportsCU(SupportsCU) {} - MCObjectWriter *createObjectWriter(raw_ostream &OS) const { + MCObjectWriter *createObjectWriter(raw_ostream &OS) const override { return createX86MachObjectWriter(OS, /*Is64Bit=*/false, MachO::CPU_TYPE_I386, MachO::CPU_SUBTYPE_I386_ALL); } /// \brief Generate the compact unwind encoding for the CFI instructions. - virtual uint32_t - generateCompactUnwindEncoding(ArrayRef<MCCFIInstruction> Instrs) const { + uint32_t generateCompactUnwindEncoding( + ArrayRef<MCCFIInstruction> Instrs) const override { return SupportsCU ? generateCompactUnwindEncodingImpl(Instrs) : 0; } }; @@ -747,15 +739,14 @@ public: MachO::CPUSubTypeX86 st) : DarwinX86AsmBackend(T, MRI, CPU, true), SupportsCU(SupportsCU), Subtype(st) { - HasReliableSymbolDifference = true; } - MCObjectWriter *createObjectWriter(raw_ostream &OS) const { + MCObjectWriter *createObjectWriter(raw_ostream &OS) const override { return createX86MachObjectWriter(OS, /*Is64Bit=*/true, MachO::CPU_TYPE_X86_64, Subtype); } - virtual bool doesSectionRequireSymbols(const MCSection &Section) const { + bool doesSectionRequireSymbols(const MCSection &Section) const override { // Temporary labels in the string literals sections require symbols. The // issue is that the x86_64 relocation format does not allow symbol + // offset, and so the linker does not have enough information to resolve the @@ -765,32 +756,32 @@ public: // // See <rdar://problem/4765733>. const MCSectionMachO &SMO = static_cast<const MCSectionMachO&>(Section); - return SMO.getType() == MCSectionMachO::S_CSTRING_LITERALS; + return SMO.getType() == MachO::S_CSTRING_LITERALS; } - virtual bool isSectionAtomizable(const MCSection &Section) const { + bool isSectionAtomizable(const MCSection &Section) const override { const MCSectionMachO &SMO = static_cast<const MCSectionMachO&>(Section); // Fixed sized data sections are uniqued, they cannot be diced into atoms. switch (SMO.getType()) { default: return true; - case MCSectionMachO::S_4BYTE_LITERALS: - case MCSectionMachO::S_8BYTE_LITERALS: - case MCSectionMachO::S_16BYTE_LITERALS: - case MCSectionMachO::S_LITERAL_POINTERS: - case MCSectionMachO::S_NON_LAZY_SYMBOL_POINTERS: - case MCSectionMachO::S_LAZY_SYMBOL_POINTERS: - case MCSectionMachO::S_MOD_INIT_FUNC_POINTERS: - case MCSectionMachO::S_MOD_TERM_FUNC_POINTERS: - case MCSectionMachO::S_INTERPOSING: + case MachO::S_4BYTE_LITERALS: + case MachO::S_8BYTE_LITERALS: + case MachO::S_16BYTE_LITERALS: + case MachO::S_LITERAL_POINTERS: + case MachO::S_NON_LAZY_SYMBOL_POINTERS: + case MachO::S_LAZY_SYMBOL_POINTERS: + case MachO::S_MOD_INIT_FUNC_POINTERS: + case MachO::S_MOD_TERM_FUNC_POINTERS: + case MachO::S_INTERPOSING: return false; } } /// \brief Generate the compact unwind encoding for the CFI instructions. - virtual uint32_t - generateCompactUnwindEncoding(ArrayRef<MCCFIInstruction> Instrs) const { + uint32_t generateCompactUnwindEncoding( + ArrayRef<MCCFIInstruction> Instrs) const override { return SupportsCU ? generateCompactUnwindEncodingImpl(Instrs) : 0; } }; @@ -803,12 +794,12 @@ MCAsmBackend *llvm::createX86_32AsmBackend(const Target &T, StringRef CPU) { Triple TheTriple(TT); - if (TheTriple.isOSDarwin() || TheTriple.getEnvironment() == Triple::MachO) + if (TheTriple.isOSBinFormatMachO()) return new DarwinX86_32AsmBackend(T, MRI, CPU, TheTriple.isMacOSX() && !TheTriple.isMacOSXVersionLT(10, 7)); - if (TheTriple.isOSWindows() && TheTriple.getEnvironment() != Triple::ELF) + if (TheTriple.isOSWindows() && !TheTriple.isOSBinFormatELF()) return new WindowsX86AsmBackend(T, false, CPU); uint8_t OSABI = MCELFObjectTargetWriter::getOSABI(TheTriple.getOS()); @@ -821,7 +812,7 @@ MCAsmBackend *llvm::createX86_64AsmBackend(const Target &T, StringRef CPU) { Triple TheTriple(TT); - if (TheTriple.isOSDarwin() || TheTriple.getEnvironment() == Triple::MachO) { + if (TheTriple.isOSBinFormatMachO()) { MachO::CPUSubTypeX86 CS = StringSwitch<MachO::CPUSubTypeX86>(TheTriple.getArchName()) .Case("x86_64h", MachO::CPU_SUBTYPE_X86_64_H) @@ -831,7 +822,7 @@ MCAsmBackend *llvm::createX86_64AsmBackend(const Target &T, !TheTriple.isMacOSXVersionLT(10, 7), CS); } - if (TheTriple.isOSWindows() && TheTriple.getEnvironment() != Triple::ELF) + if (TheTriple.isOSWindows() && !TheTriple.isOSBinFormatELF()) return new WindowsX86AsmBackend(T, true, CPU); uint8_t OSABI = MCELFObjectTargetWriter::getOSABI(TheTriple.getOS()); diff --git a/lib/Target/X86/MCTargetDesc/X86BaseInfo.h b/lib/Target/X86/MCTargetDesc/X86BaseInfo.h index 1ef9814..38fab15 100644 --- a/lib/Target/X86/MCTargetDesc/X86BaseInfo.h +++ b/lib/Target/X86/MCTargetDesc/X86BaseInfo.h @@ -18,9 +18,9 @@ #define X86BASEINFO_H #include "X86MCTargetDesc.h" +#include "llvm/MC/MCInstrDesc.h" #include "llvm/Support/DataTypes.h" #include "llvm/Support/ErrorHandling.h" -#include "llvm/MC/MCInstrInfo.h" namespace llvm { @@ -255,6 +255,38 @@ namespace X86II { /// MRMSrcMem = 6, + /// RawFrmMemOffs - This form is for instructions that store an absolute + /// memory offset as an immediate with a possible segment override. + RawFrmMemOffs = 7, + + /// RawFrmSrc - This form is for instructions that use the source index + /// register SI/ESI/RSI with a possible segment override. + RawFrmSrc = 8, + + /// RawFrmDst - This form is for instructions that use the destination index + /// register DI/EDI/ESI. + RawFrmDst = 9, + + /// RawFrmSrc - This form is for instructions that use the the source index + /// register SI/ESI/ERI with a possible segment override, and also the + /// destination index register DI/ESI/RDI. + RawFrmDstSrc = 10, + + /// RawFrmImm8 - This is used for the ENTER instruction, which has two + /// immediates, the first of which is a 16-bit immediate (specified by + /// the imm encoding) and the second is a 8-bit fixed value. + RawFrmImm8 = 11, + + /// RawFrmImm16 - This is used for CALL FAR instructions, which have two + /// immediates, the first of which is a 16 or 32-bit immediate (specified by + /// the imm encoding) and the second is a 16-bit fixed value. In the AMD + /// manual, this operand is described as pntr16:32 and pntr16:16 + RawFrmImm16 = 12, + + /// MRMX[rm] - The forms are used to represent instructions that use a + /// Mod/RM byte, and don't use the middle field for anything. + MRMXr = 14, MRMXm = 15, + /// MRM[0-7][rm] - These forms are used to represent instructions that use /// a Mod/RM byte, and use the middle field to hold extended opcode /// information. In the intel manual these are represented as /0, /1, ... @@ -268,94 +300,83 @@ namespace X86II { MRM0m = 24, MRM1m = 25, MRM2m = 26, MRM3m = 27, // Format /0 /1 /2 /3 MRM4m = 28, MRM5m = 29, MRM6m = 30, MRM7m = 31, // Format /4 /5 /6 /7 - // MRMInitReg - This form is used for instructions whose source and - // destinations are the same register. - MRMInitReg = 32, - //// MRM_XX - A mod/rm byte of exactly 0xXX. - MRM_C1 = 33, MRM_C2 = 34, MRM_C3 = 35, MRM_C4 = 36, - MRM_C8 = 37, MRM_C9 = 38, MRM_CA = 39, MRM_CB = 40, - MRM_E8 = 41, MRM_F0 = 42, MRM_F8 = 45, MRM_F9 = 46, - MRM_D0 = 47, MRM_D1 = 48, MRM_D4 = 49, MRM_D5 = 50, - MRM_D6 = 51, MRM_D8 = 52, MRM_D9 = 53, MRM_DA = 54, - MRM_DB = 55, MRM_DC = 56, MRM_DD = 57, MRM_DE = 58, - MRM_DF = 59, - - /// RawFrmImm8 - This is used for the ENTER instruction, which has two - /// immediates, the first of which is a 16-bit immediate (specified by - /// the imm encoding) and the second is a 8-bit fixed value. - RawFrmImm8 = 43, - - /// RawFrmImm16 - This is used for CALL FAR instructions, which have two - /// immediates, the first of which is a 16 or 32-bit immediate (specified by - /// the imm encoding) and the second is a 16-bit fixed value. In the AMD - /// manual, this operand is described as pntr16:32 and pntr16:16 - RawFrmImm16 = 44, - - FormMask = 63, + MRM_C0 = 32, MRM_C1 = 33, MRM_C2 = 34, MRM_C3 = 35, + MRM_C4 = 36, MRM_C8 = 37, MRM_C9 = 38, MRM_CA = 39, + MRM_CB = 40, MRM_D0 = 41, MRM_D1 = 42, MRM_D4 = 43, + MRM_D5 = 44, MRM_D6 = 45, MRM_D8 = 46, MRM_D9 = 47, + MRM_DA = 48, MRM_DB = 49, MRM_DC = 50, MRM_DD = 51, + MRM_DE = 52, MRM_DF = 53, MRM_E0 = 54, MRM_E1 = 55, + MRM_E2 = 56, MRM_E3 = 57, MRM_E4 = 58, MRM_E5 = 59, + MRM_E8 = 60, MRM_E9 = 61, MRM_EA = 62, MRM_EB = 63, + MRM_EC = 64, MRM_ED = 65, MRM_EE = 66, MRM_F0 = 67, + MRM_F1 = 68, MRM_F2 = 69, MRM_F3 = 70, MRM_F4 = 71, + MRM_F5 = 72, MRM_F6 = 73, MRM_F7 = 74, MRM_F8 = 75, + MRM_F9 = 76, MRM_FA = 77, MRM_FB = 78, MRM_FC = 79, + MRM_FD = 80, MRM_FE = 81, MRM_FF = 82, + + FormMask = 127, //===------------------------------------------------------------------===// // Actual flags... - // OpSize - Set if this instruction requires an operand size prefix (0x66), - // which most often indicates that the instruction operates on 16 bit data - // instead of 32 bit data. - OpSize = 1 << 6, + // OpSize - OpSizeFixed implies instruction never needs a 0x66 prefix. + // OpSize16 means this is a 16-bit instruction and needs 0x66 prefix in + // 32-bit mode. OpSize32 means this is a 32-bit instruction needs a 0x66 + // prefix in 16-bit mode. + OpSizeShift = 7, + OpSizeMask = 0x3 << OpSizeShift, + + OpSize16 = 1, + OpSize32 = 2, // AsSize - Set if this instruction requires an operand size prefix (0x67), // which most often indicates that the instruction address 16 bit address // instead of 32 bit address (or 32 bit address in 64 bit mode). - AdSize = 1 << 7, + AdSizeShift = OpSizeShift + 2, + AdSize = 1 << AdSizeShift, //===------------------------------------------------------------------===// - // Op0Mask - There are several prefix bytes that are used to form two byte - // opcodes. These are currently 0x0F, 0xF3, and 0xD8-0xDF. This mask is - // used to obtain the setting of this field. If no bits in this field is - // set, there is no prefix byte for obtaining a multibyte opcode. + // OpPrefix - There are several prefix bytes that are used as opcode + // extensions. These are 0x66, 0xF3, and 0xF2. If this field is 0 there is + // no prefix. // - Op0Shift = 8, - Op0Mask = 0x1F << Op0Shift, - - // TB - TwoByte - Set if this instruction has a two byte opcode, which - // starts with a 0x0F byte before the real opcode. - TB = 1 << Op0Shift, - - // REP - The 0xF3 prefix byte indicating repetition of the following - // instruction. - REP = 2 << Op0Shift, + OpPrefixShift = AdSizeShift + 1, + OpPrefixMask = 0x7 << OpPrefixShift, - // D8-DF - These escape opcodes are used by the floating point unit. These - // values must remain sequential. - D8 = 3 << Op0Shift, D9 = 4 << Op0Shift, - DA = 5 << Op0Shift, DB = 6 << Op0Shift, - DC = 7 << Op0Shift, DD = 8 << Op0Shift, - DE = 9 << Op0Shift, DF = 10 << Op0Shift, + // PS, PD - Prefix code for packed single and double precision vector + // floating point operations performed in the SSE registers. + PS = 1 << OpPrefixShift, PD = 2 << OpPrefixShift, // XS, XD - These prefix codes are for single and double precision scalar // floating point operations performed in the SSE registers. - XD = 11 << Op0Shift, XS = 12 << Op0Shift, + XS = 3 << OpPrefixShift, XD = 4 << OpPrefixShift, - // T8, TA, A6, A7 - Prefix after the 0x0F prefix. - T8 = 13 << Op0Shift, TA = 14 << Op0Shift, - A6 = 15 << Op0Shift, A7 = 16 << Op0Shift, + //===------------------------------------------------------------------===// + // OpMap - This field determines which opcode map this instruction + // belongs to. i.e. one-byte, two-byte, 0x0f 0x38, 0x0f 0x3a, etc. + // + OpMapShift = OpPrefixShift + 3, + OpMapMask = 0x7 << OpMapShift, - // T8XD - Prefix before and after 0x0F. Combination of T8 and XD. - T8XD = 17 << Op0Shift, + // OB - OneByte - Set if this instruction has a one byte opcode. + OB = 0 << OpMapShift, - // T8XS - Prefix before and after 0x0F. Combination of T8 and XS. - T8XS = 18 << Op0Shift, + // TB - TwoByte - Set if this instruction has a two byte opcode, which + // starts with a 0x0F byte before the real opcode. + TB = 1 << OpMapShift, - // TAXD - Prefix before and after 0x0F. Combination of TA and XD. - TAXD = 19 << Op0Shift, + // T8, TA - Prefix after the 0x0F prefix. + T8 = 2 << OpMapShift, TA = 3 << OpMapShift, // XOP8 - Prefix to include use of imm byte. - XOP8 = 20 << Op0Shift, + XOP8 = 4 << OpMapShift, // XOP9 - Prefix to exclude use of imm byte. - XOP9 = 21 << Op0Shift, + XOP9 = 5 << OpMapShift, // XOPA - Prefix to encode 0xA in VEX.MMMM of XOP instructions. - XOPA = 22 << Op0Shift, + XOPA = 6 << OpMapShift, //===------------------------------------------------------------------===// // REX_W - REX prefixes are instruction prefixes used in 64-bit mode. @@ -363,27 +384,28 @@ namespace X86II { // etc. We only cares about REX.W and REX.R bits and only the former is // statically determined. // - REXShift = Op0Shift + 5, + REXShift = OpMapShift + 3, REX_W = 1 << REXShift, //===------------------------------------------------------------------===// // This three-bit field describes the size of an immediate operand. Zero is // unused so that we can tell if we forgot to set a value. ImmShift = REXShift + 1, - ImmMask = 7 << ImmShift, + ImmMask = 15 << ImmShift, Imm8 = 1 << ImmShift, Imm8PCRel = 2 << ImmShift, Imm16 = 3 << ImmShift, Imm16PCRel = 4 << ImmShift, Imm32 = 5 << ImmShift, Imm32PCRel = 6 << ImmShift, - Imm64 = 7 << ImmShift, + Imm32S = 7 << ImmShift, + Imm64 = 8 << ImmShift, //===------------------------------------------------------------------===// // FP Instruction Classification... Zero is non-fp instruction. // FPTypeMask - Mask for all of the FP types... - FPTypeShift = ImmShift + 3, + FPTypeShift = ImmShift + 4, FPTypeMask = 7 << FPTypeShift, // NotFP - The default, set for instructions that do not use FP registers. @@ -419,51 +441,64 @@ namespace X86II { LOCKShift = FPTypeShift + 3, LOCK = 1 << LOCKShift, - // Segment override prefixes. Currently we just need ability to address - // stuff in gs and fs segments. - SegOvrShift = LOCKShift + 1, - SegOvrMask = 3 << SegOvrShift, - FS = 1 << SegOvrShift, - GS = 2 << SegOvrShift, + // REP prefix + REPShift = LOCKShift + 1, + REP = 1 << REPShift, + + // Execution domain for SSE instructions. + // 0 means normal, non-SSE instruction. + SSEDomainShift = REPShift + 1, + + // Encoding + EncodingShift = SSEDomainShift + 2, + EncodingMask = 0x3 << EncodingShift, + + // VEX - encoding using 0xC4/0xC5 + VEX = 1, + + /// XOP - Opcode prefix used by XOP instructions. + XOP = 2, - // Execution domain for SSE instructions in bits 23, 24. - // 0 in bits 23-24 means normal, non-SSE instruction. - SSEDomainShift = SegOvrShift + 2, + // VEX_EVEX - Specifies that this instruction use EVEX form which provides + // syntax support up to 32 512-bit register operands and up to 7 16-bit + // mask operands as well as source operand data swizzling/memory operand + // conversion, eviction hint, and rounding mode. + EVEX = 3, - OpcodeShift = SSEDomainShift + 2, + // Opcode + OpcodeShift = EncodingShift + 2, //===------------------------------------------------------------------===// /// VEX - The opcode prefix used by AVX instructions VEXShift = OpcodeShift + 8, - VEX = 1U << 0, /// VEX_W - Has a opcode specific functionality, but is used in the same /// way as REX_W is for regular SSE instructions. - VEX_W = 1U << 1, + VEX_W = 1U << 0, /// VEX_4V - Used to specify an additional AVX/SSE register. Several 2 /// address instructions in SSE are represented as 3 address ones in AVX /// and the additional register is encoded in VEX_VVVV prefix. - VEX_4V = 1U << 2, + VEX_4V = 1U << 1, /// VEX_4VOp3 - Similar to VEX_4V, but used on instructions that encode /// operand 3 with VEX.vvvv. - VEX_4VOp3 = 1U << 3, + VEX_4VOp3 = 1U << 2, /// VEX_I8IMM - Specifies that the last register used in a AVX instruction, /// must be encoded in the i8 immediate field. This usually happens in /// instructions with 4 operands. - VEX_I8IMM = 1U << 4, + VEX_I8IMM = 1U << 3, /// VEX_L - Stands for a bit in the VEX opcode prefix meaning the current /// instruction uses 256-bit wide registers. This is usually auto detected /// if a VR256 register is used, but some AVX instructions also have this /// field marked when using a f256 memory references. - VEX_L = 1U << 5, + VEX_L = 1U << 4, // VEX_LIG - Specifies that this instruction ignores the L-bit in the VEX // prefix. Usually used for scalar instructions. Needed by disassembler. - VEX_LIG = 1U << 6, + VEX_LIG = 1U << 5, // TODO: we should combine VEX_L and VEX_LIG together to form a 2-bit field // with following encoding: @@ -473,26 +508,20 @@ namespace X86II { // - 11 LIG (but, in insn encoding, leave VEX.L and EVEX.L in zeros. // this will save 1 tsflag bit - // VEX_EVEX - Specifies that this instruction use EVEX form which provides - // syntax support up to 32 512-bit register operands and up to 7 16-bit - // mask operands as well as source operand data swizzling/memory operand - // conversion, eviction hint, and rounding mode. - EVEX = 1U << 7, - // EVEX_K - Set if this instruction requires masking - EVEX_K = 1U << 8, + EVEX_K = 1U << 6, // EVEX_Z - Set if this instruction has EVEX.Z field set. - EVEX_Z = 1U << 9, + EVEX_Z = 1U << 7, // EVEX_L2 - Set if this instruction has EVEX.L' field set. - EVEX_L2 = 1U << 10, + EVEX_L2 = 1U << 8, // EVEX_B - Set if this instruction has EVEX.B field set. - EVEX_B = 1U << 11, + EVEX_B = 1U << 9, // EVEX_CD8E - compressed disp8 form, element-size - EVEX_CD8EShift = VEXShift + 12, + EVEX_CD8EShift = VEXShift + 10, EVEX_CD8EMask = 3, // EVEX_CD8V - compressed disp8 form, vector-width @@ -505,15 +534,14 @@ namespace X86II { /// storing a classifier in the imm8 field. To simplify our implementation, /// we handle this by storeing the classifier in the opcode field and using /// this flag to indicate that the encoder should do the wacky 3DNow! thing. - Has3DNow0F0FOpcode = 1U << 17, + Has3DNow0F0FOpcode = 1U << 15, /// MemOp4 - Used to indicate swapping of operand 3 and 4 to be encoded in /// ModRM or I8IMM. This is used for FMA4 and XOP instructions. - MemOp4 = 1U << 18, - - /// XOP - Opcode prefix used by XOP instructions. - XOP = 1U << 19 + MemOp4 = 1U << 16, + /// Explicitly specified rounding control + EVEX_RC = 1U << 17 }; // getBaseOpcodeFor - This function returns the "base" X86 opcode for the @@ -537,6 +565,7 @@ namespace X86II { case X86II::Imm16: case X86II::Imm16PCRel: return 2; case X86II::Imm32: + case X86II::Imm32S: case X86II::Imm32PCRel: return 4; case X86II::Imm64: return 8; } @@ -554,6 +583,25 @@ namespace X86II { case X86II::Imm8: case X86II::Imm16: case X86II::Imm32: + case X86II::Imm32S: + case X86II::Imm64: + return false; + } + } + + /// isImmSigned - Return true if the immediate of the specified instruction's + /// TSFlags indicates that it is signed. + inline unsigned isImmSigned(uint64_t TSFlags) { + switch (TSFlags & X86II::ImmMask) { + default: llvm_unreachable("Unknown immediate signedness"); + case X86II::Imm32S: + return true; + case X86II::Imm8: + case X86II::Imm8PCRel: + case X86II::Imm16: + case X86II::Imm16PCRel: + case X86II::Imm32: + case X86II::Imm32PCRel: case X86II::Imm64: return false; } @@ -596,9 +644,6 @@ namespace X86II { /// inline int getMemoryOperandNo(uint64_t TSFlags, unsigned Opcode) { switch (TSFlags & X86II::FormMask) { - case X86II::MRMInitReg: - // FIXME: Remove this form. - return -1; default: llvm_unreachable("Unknown FormMask value in getMemoryOperandNo!"); case X86II::Pseudo: case X86II::RawFrm: @@ -607,14 +652,17 @@ namespace X86II { case X86II::MRMSrcReg: case X86II::RawFrmImm8: case X86II::RawFrmImm16: + case X86II::RawFrmMemOffs: + case X86II::RawFrmSrc: + case X86II::RawFrmDst: + case X86II::RawFrmDstSrc: return -1; case X86II::MRMDestMem: return 0; case X86II::MRMSrcMem: { bool HasVEX_4V = (TSFlags >> X86II::VEXShift) & X86II::VEX_4V; bool HasMemOp4 = (TSFlags >> X86II::VEXShift) & X86II::MemOp4; - bool HasEVEX = (TSFlags >> X86II::VEXShift) & X86II::EVEX; - bool HasEVEX_K = HasEVEX && ((TSFlags >> X86II::VEXShift) & X86II::EVEX_K); + bool HasEVEX_K = ((TSFlags >> X86II::VEXShift) & X86II::EVEX_K); unsigned FirstMemOp = 1; if (HasVEX_4V) ++FirstMemOp;// Skip the register source (which is encoded in VEX_VVVV). @@ -627,11 +675,13 @@ namespace X86II { // Opcode == X86::LEA16r || Opcode == X86::LEA32r) return FirstMemOp; } + 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: return -1; + case X86II::MRMXm: case X86II::MRM0m: case X86II::MRM1m: case X86II::MRM2m: case X86II::MRM3m: case X86II::MRM4m: case X86II::MRM5m: @@ -642,15 +692,23 @@ namespace X86II { ++FirstMemOp;// Skip the register dest (which is encoded in VEX_VVVV). return FirstMemOp; } - case X86II::MRM_C1: case X86II::MRM_C2: case X86II::MRM_C3: - case X86II::MRM_C4: case X86II::MRM_C8: case X86II::MRM_C9: - case X86II::MRM_CA: case X86II::MRM_CB: case X86II::MRM_E8: - case X86II::MRM_F0: case X86II::MRM_F8: case X86II::MRM_F9: + case X86II::MRM_C0: case X86II::MRM_C1: case X86II::MRM_C2: + case X86II::MRM_C3: case X86II::MRM_C4: case X86II::MRM_C8: + case X86II::MRM_C9: case X86II::MRM_CA: case X86II::MRM_CB: case X86II::MRM_D0: case X86II::MRM_D1: case X86II::MRM_D4: case X86II::MRM_D5: case X86II::MRM_D6: 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_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_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_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: return -1; } } diff --git a/lib/Target/X86/MCTargetDesc/X86ELFObjectWriter.cpp b/lib/Target/X86/MCTargetDesc/X86ELFObjectWriter.cpp index 3ddd865..c44d88d 100644 --- a/lib/Target/X86/MCTargetDesc/X86ELFObjectWriter.cpp +++ b/lib/Target/X86/MCTargetDesc/X86ELFObjectWriter.cpp @@ -24,9 +24,8 @@ namespace { virtual ~X86ELFObjectWriter(); protected: - virtual unsigned GetRelocType(const MCValue &Target, const MCFixup &Fixup, - bool IsPCRel, bool IsRelocWithSymbol, - int64_t Addend) const; + unsigned GetRelocType(const MCValue &Target, const MCFixup &Fixup, + bool IsPCRel) const override; }; } @@ -41,13 +40,10 @@ X86ELFObjectWriter::~X86ELFObjectWriter() unsigned X86ELFObjectWriter::GetRelocType(const MCValue &Target, const MCFixup &Fixup, - bool IsPCRel, - bool IsRelocWithSymbol, - int64_t Addend) const { + bool IsPCRel) const { // determine the type of the relocation - MCSymbolRefExpr::VariantKind Modifier = Target.isAbsolute() ? - MCSymbolRefExpr::VK_None : Target.getSymA()->getKind(); + MCSymbolRefExpr::VariantKind Modifier = Fixup.getAccessVariant(); unsigned Type; if (getEMachine() == ELF::EM_X86_64) { if (IsPCRel) { @@ -57,6 +53,7 @@ unsigned X86ELFObjectWriter::GetRelocType(const MCValue &Target, case FK_Data_8: Type = ELF::R_X86_64_PC64; break; case FK_Data_4: Type = ELF::R_X86_64_PC32; break; case FK_Data_2: Type = ELF::R_X86_64_PC16; break; + case FK_Data_1: Type = ELF::R_X86_64_PC8; break; case FK_PCRel_8: assert(Modifier == MCSymbolRefExpr::VK_None); @@ -160,6 +157,28 @@ unsigned X86ELFObjectWriter::GetRelocType(const MCValue &Target, Type = ELF::R_386_GOTPC; break; + case FK_PCRel_1: + case FK_Data_1: + switch (Modifier) { + default: + llvm_unreachable("Unimplemented"); + case MCSymbolRefExpr::VK_None: + Type = ELF::R_386_PC8; + break; + } + break; + + case FK_PCRel_2: + case FK_Data_2: + switch (Modifier) { + default: + llvm_unreachable("Unimplemented"); + case MCSymbolRefExpr::VK_None: + Type = ELF::R_386_PC16; + break; + } + break; + case X86::reloc_signed_4byte: case FK_PCRel_4: case FK_Data_4: diff --git a/lib/Target/X86/MCTargetDesc/X86ELFRelocationInfo.cpp b/lib/Target/X86/MCTargetDesc/X86ELFRelocationInfo.cpp index a3eb4fb..4fa519c 100644 --- a/lib/Target/X86/MCTargetDesc/X86ELFRelocationInfo.cpp +++ b/lib/Target/X86/MCTargetDesc/X86ELFRelocationInfo.cpp @@ -11,8 +11,8 @@ #include "llvm/MC/MCContext.h" #include "llvm/MC/MCExpr.h" #include "llvm/MC/MCInst.h" -#include "llvm/MC/MCSymbol.h" #include "llvm/MC/MCRelocationInfo.h" +#include "llvm/MC/MCSymbol.h" #include "llvm/Object/ELFObjectFile.h" #include "llvm/Support/ELF.h" @@ -25,7 +25,7 @@ class X86_64ELFRelocationInfo : public MCRelocationInfo { public: X86_64ELFRelocationInfo(MCContext &Ctx) : MCRelocationInfo(Ctx) {} - const MCExpr *createExprForRelocation(RelocationRef Rel) { + const MCExpr *createExprForRelocation(RelocationRef Rel) override { uint64_t RelType; Rel.getType(RelType); symbol_iterator SymI = Rel.getSymbol(); diff --git a/lib/Target/X86/MCTargetDesc/X86MCAsmInfo.cpp b/lib/Target/X86/MCTargetDesc/X86MCAsmInfo.cpp index 3861e1c..6561804 100644 --- a/lib/Target/X86/MCTargetDesc/X86MCAsmInfo.cpp +++ b/lib/Target/X86/MCTargetDesc/X86MCAsmInfo.cpp @@ -65,6 +65,19 @@ X86MCAsmInfoDarwin::X86MCAsmInfoDarwin(const Triple &T) { // Exceptions handling ExceptionsType = ExceptionHandling::DwarfCFI; + + // old assembler lacks some directives + // FIXME: this should really be a check on the assembler characteristics + // rather than OS version + if (T.isMacOSX() && T.isMacOSXVersionLT(10, 6)) + HasWeakDefCanBeHiddenDirective = false; + + // FIXME: this should not depend on the target OS version, but on the ld64 + // version in use. From at least >= ld64-97.17 (Xcode 3.2.6) the abs-ified + // FDE relocs may be used. + DwarfFDESymbolsUseAbsDiff = T.isMacOSX() && !T.isMacOSXVersionLT(10, 6); + + UseIntegratedAssembler = true; } X86_64MCAsmInfoDarwin::X86_64MCAsmInfoDarwin(const Triple &Triple) @@ -89,8 +102,6 @@ X86ELFMCAsmInfo::X86ELFMCAsmInfo(const Triple &T) { TextAlignFillValue = 0x90; - PrivateGlobalPrefix = ".L"; - // Set up DWARF directives HasLEB128 = true; // Target asm supports leb128 directives (little-endian) @@ -105,6 +116,10 @@ X86ELFMCAsmInfo::X86ELFMCAsmInfo(const Triple &T) { if ((T.getOS() == Triple::OpenBSD || T.getOS() == Triple::Bitrig) && T.getArch() == Triple::x86) Data64bitsDirective = 0; + + // Always enable the integrated assembler by default. + // Clang also enabled it when the OS is Solaris but that is redundant here. + UseIntegratedAssembler = true; } const MCExpr * @@ -127,25 +142,23 @@ getNonexecutableStackSection(MCContext &Ctx) const { void X86MCAsmInfoMicrosoft::anchor() { } X86MCAsmInfoMicrosoft::X86MCAsmInfoMicrosoft(const Triple &Triple) { - if (Triple.getArch() == Triple::x86_64) { - GlobalPrefix = ""; + if (Triple.getArch() == Triple::x86_64) PrivateGlobalPrefix = ".L"; - } AssemblerDialect = AsmWriterFlavor; TextAlignFillValue = 0x90; AllowAtInName = true; + + UseIntegratedAssembler = true; } void X86MCAsmInfoGNUCOFF::anchor() { } X86MCAsmInfoGNUCOFF::X86MCAsmInfoGNUCOFF(const Triple &Triple) { - if (Triple.getArch() == Triple::x86_64) { - GlobalPrefix = ""; + if (Triple.getArch() == Triple::x86_64) PrivateGlobalPrefix = ".L"; - } AssemblerDialect = AsmWriterFlavor; @@ -153,4 +166,6 @@ X86MCAsmInfoGNUCOFF::X86MCAsmInfoGNUCOFF(const Triple &Triple) { // Exceptions handling ExceptionsType = ExceptionHandling::DwarfCFI; + + UseIntegratedAssembler = true; } diff --git a/lib/Target/X86/MCTargetDesc/X86MCAsmInfo.h b/lib/Target/X86/MCTargetDesc/X86MCAsmInfo.h index 80979dd..a7509b0 100644 --- a/lib/Target/X86/MCTargetDesc/X86MCAsmInfo.h +++ b/lib/Target/X86/MCTargetDesc/X86MCAsmInfo.h @@ -23,34 +23,34 @@ namespace llvm { class Triple; class X86MCAsmInfoDarwin : public MCAsmInfoDarwin { - virtual void anchor(); + void anchor() override; public: explicit X86MCAsmInfoDarwin(const Triple &Triple); }; struct X86_64MCAsmInfoDarwin : public X86MCAsmInfoDarwin { explicit X86_64MCAsmInfoDarwin(const Triple &Triple); - virtual const MCExpr * - getExprForPersonalitySymbol(const MCSymbol *Sym, - unsigned Encoding, - MCStreamer &Streamer) const; + const MCExpr * + getExprForPersonalitySymbol(const MCSymbol *Sym, unsigned Encoding, + MCStreamer &Streamer) const override; }; class X86ELFMCAsmInfo : public MCAsmInfoELF { - virtual void anchor(); + void anchor() override; public: explicit X86ELFMCAsmInfo(const Triple &Triple); - virtual const MCSection *getNonexecutableStackSection(MCContext &Ctx) const; + const MCSection * + getNonexecutableStackSection(MCContext &Ctx) const override; }; class X86MCAsmInfoMicrosoft : public MCAsmInfoMicrosoft { - virtual void anchor(); + void anchor() override; public: explicit X86MCAsmInfoMicrosoft(const Triple &Triple); }; class X86MCAsmInfoGNUCOFF : public MCAsmInfoGNUCOFF { - virtual void anchor(); + void anchor() override; public: explicit X86MCAsmInfoGNUCOFF(const Triple &Triple); }; diff --git a/lib/Target/X86/MCTargetDesc/X86MCCodeEmitter.cpp b/lib/Target/X86/MCTargetDesc/X86MCCodeEmitter.cpp index 7952607..e6fb037 100644 --- a/lib/Target/X86/MCTargetDesc/X86MCCodeEmitter.cpp +++ b/lib/Target/X86/MCTargetDesc/X86MCCodeEmitter.cpp @@ -32,24 +32,43 @@ class X86MCCodeEmitter : public MCCodeEmitter { X86MCCodeEmitter(const X86MCCodeEmitter &) LLVM_DELETED_FUNCTION; void operator=(const X86MCCodeEmitter &) LLVM_DELETED_FUNCTION; const MCInstrInfo &MCII; - const MCSubtargetInfo &STI; MCContext &Ctx; public: - X86MCCodeEmitter(const MCInstrInfo &mcii, const MCSubtargetInfo &sti, - MCContext &ctx) - : MCII(mcii), STI(sti), Ctx(ctx) { + X86MCCodeEmitter(const MCInstrInfo &mcii, MCContext &ctx) + : MCII(mcii), Ctx(ctx) { } ~X86MCCodeEmitter() {} - bool is64BitMode() const { - // FIXME: Can tablegen auto-generate this? + bool is64BitMode(const MCSubtargetInfo &STI) const { return (STI.getFeatureBits() & X86::Mode64Bit) != 0; } - bool is32BitMode() const { - // FIXME: Can tablegen auto-generate this? - return (STI.getFeatureBits() & X86::Mode64Bit) == 0; + bool is32BitMode(const MCSubtargetInfo &STI) const { + return (STI.getFeatureBits() & X86::Mode32Bit) != 0; + } + + bool is16BitMode(const MCSubtargetInfo &STI) const { + return (STI.getFeatureBits() & X86::Mode16Bit) != 0; + } + + /// 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); + + 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; } unsigned GetX86RegNum(const MCOperand &MO) const { @@ -126,21 +145,23 @@ public: void EmitMemModRMByte(const MCInst &MI, unsigned Op, unsigned RegOpcodeField, uint64_t TSFlags, unsigned &CurByte, raw_ostream &OS, - SmallVectorImpl<MCFixup> &Fixups) const; + SmallVectorImpl<MCFixup> &Fixups, + const MCSubtargetInfo &STI) const; void EncodeInstruction(const MCInst &MI, raw_ostream &OS, - SmallVectorImpl<MCFixup> &Fixups) const; + SmallVectorImpl<MCFixup> &Fixups, + const MCSubtargetInfo &STI) const override; void EmitVEXOpcodePrefix(uint64_t TSFlags, unsigned &CurByte, int MemOperand, const MCInst &MI, const MCInstrDesc &Desc, raw_ostream &OS) const; - void EmitSegmentOverridePrefix(uint64_t TSFlags, unsigned &CurByte, - int MemOperand, const MCInst &MI, - raw_ostream &OS) const; + void EmitSegmentOverridePrefix(unsigned &CurByte, unsigned SegOperand, + const MCInst &MI, raw_ostream &OS) const; void EmitOpcodePrefix(uint64_t TSFlags, unsigned &CurByte, int MemOperand, const MCInst &MI, const MCInstrDesc &Desc, + const MCSubtargetInfo &STI, raw_ostream &OS) const; }; @@ -151,7 +172,7 @@ MCCodeEmitter *llvm::createX86MCCodeEmitter(const MCInstrInfo &MCII, const MCRegisterInfo &MRI, const MCSubtargetInfo &STI, MCContext &Ctx) { - return new X86MCCodeEmitter(MCII, STI, Ctx); + return new X86MCCodeEmitter(MCII, Ctx); } /// isDisp8 - Return true if this signed displacement fits in a 8-bit @@ -163,7 +184,7 @@ static bool isDisp8(int 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) { - assert(((TSFlags >> X86II::VEXShift) & X86II::EVEX) && + assert((TSFlags & X86II::EncodingMask) >> X86II::EncodingShift == X86II::EVEX && "Compressed 8-bit displacement is only valid for EVEX inst."); unsigned CD8E = (TSFlags >> X86II::EVEX_CD8EShift) & X86II::EVEX_CD8EMask; @@ -198,7 +219,7 @@ static bool isCDisp8(uint64_t TSFlags, int Value, int& CValue) { if (Value & MemObjMask) // Unaligned offset return false; - Value /= MemObjSize; + Value /= (int)MemObjSize; bool Ret = (Value == (signed char)Value); if (Ret) @@ -212,6 +233,12 @@ 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); + } + } return MCFixup::getKindForSize(Size, isPCRel); } @@ -245,20 +272,6 @@ static bool Is64BitMemOperand(const MCInst &MI, unsigned Op) { } #endif -/// Is16BitMemOperand - Return true if the specified instruction has -/// a 16-bit memory operand. Op specifies the operand # of the memoperand. -static bool Is16BitMemOperand(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::GR16RegClassID].contains(BaseReg.getReg())) || - (IndexReg.getReg() != 0 && - X86MCRegisterClasses[X86::GR16RegClassID].contains(IndexReg.getReg()))) - return true; - return false; -} - /// 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 @@ -366,17 +379,20 @@ void X86MCCodeEmitter::EmitMemModRMByte(const MCInst &MI, unsigned Op, unsigned RegOpcodeField, uint64_t TSFlags, unsigned &CurByte, raw_ostream &OS, - SmallVectorImpl<MCFixup> &Fixups) const{ + 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); unsigned BaseReg = Base.getReg(); - bool HasEVEX = (TSFlags >> X86II::VEXShift) & X86II::EVEX; + unsigned char Encoding = (TSFlags & X86II::EncodingMask) >> + X86II::EncodingShift; + bool HasEVEX = (Encoding == X86II::EVEX); // Handle %rip relative addressing. if (BaseReg == X86::RIP) { // [disp32+RIP] in X86-64 mode - assert(is64BitMode() && "Rip-relative addressing requires 64-bit mode"); + assert(is64BitMode(STI) && "Rip-relative addressing requires 64-bit mode"); assert(IndexReg.getReg() == 0 && "Invalid rip-relative address"); EmitByte(ModRMByte(0, RegOpcodeField, 5), CurByte, OS); @@ -402,6 +418,66 @@ void X86MCCodeEmitter::EmitMemModRMByte(const MCInst &MI, unsigned Op, 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 (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. + // 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, + // while values 0-3 indicate the allowed combinations (base+index) of + // those: 0 for BX+SI, 1 for BX+DI, 2 for BP+SI, 3 for BP+DI. + // + // 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 }; + unsigned RMfield = R16Table[BaseRegNo]; + + assert(RMfield && "invalid 16-bit base register"); + + if (IndexReg.getReg()) { + 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). + assert(((IndexReg16 ^ RMfield) & 2) && + "invalid 16-bit base/index register combination"); + assert(Scale.getImm() == 1 && + "invalid scale for 16-bit memory reference"); + + // Allow base/index to appear in either order (although GAS doesn't). + if (IndexReg16 & 2) + RMfield = (RMfield & 1) | ((7 - IndexReg16) << 1); + else + RMfield = (IndexReg16 & 1) | ((7 - RMfield) << 1); + } + + if (Disp.isImm() && isDisp8(Disp.getImm())) { + if (Disp.getImm() == 0 && BaseRegNo != N86::EBP) { + // There is no displacement; just the register. + 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); + return; + } + // This is the [REG]+disp16 case. + 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); + } + + // Emit 16-bit displacement for plain disp16 or [REG]+disp16 cases. + EmitImmediate(Disp, MI.getLoc(), 2, FK_Data_2, CurByte, OS, Fixups); + return; + } + // Determine whether a SIB byte is needed. // If no BaseReg, issue a RIP relative instruction only if the MCE can // resolve addresses on-the-fly, otherwise use SIB (Intel Manual 2A, table @@ -415,7 +491,7 @@ 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() || BaseReg != 0)) { + (!is64BitMode(STI) || BaseReg != 0)) { if (BaseReg == 0) { // [disp32] in X86-32 mode EmitByte(ModRMByte(0, RegOpcodeField, 5), CurByte, OS); @@ -530,11 +606,13 @@ void X86MCCodeEmitter::EmitVEXOpcodePrefix(uint64_t TSFlags, unsigned &CurByte, int MemOperand, const MCInst &MI, const MCInstrDesc &Desc, raw_ostream &OS) const { - bool HasEVEX = (TSFlags >> X86II::VEXShift) & X86II::EVEX; - bool HasEVEX_K = HasEVEX && ((TSFlags >> X86II::VEXShift) & X86II::EVEX_K); + unsigned char Encoding = (TSFlags & X86II::EncodingMask) >> + X86II::EncodingShift; + bool HasEVEX_K = ((TSFlags >> X86II::VEXShift) & X86II::EVEX_K); bool HasVEX_4V = (TSFlags >> X86II::VEXShift) & X86II::VEX_4V; bool HasVEX_4VOp3 = (TSFlags >> X86II::VEXShift) & X86II::VEX_4VOp3; bool HasMemOp4 = (TSFlags >> X86II::VEXShift) & X86II::MemOp4; + bool HasEVEX_RC = (TSFlags >> X86II::VEXShift) & X86II::EVEX_RC; // VEX_R: opcode externsion equivalent to REX.R in // 1's complement (inverted) form @@ -563,9 +641,6 @@ void X86MCCodeEmitter::EmitVEXOpcodePrefix(uint64_t TSFlags, unsigned &CurByte, // opcode extension, or ignored, depending on the opcode byte) unsigned char VEX_W = 0; - // XOP: Use XOP prefix byte 0x8f instead of VEX. - bool XOP = false; - // VEX_5M (VEX m-mmmmm field): // // 0b00000: Reserved for future use @@ -576,7 +651,7 @@ void X86MCCodeEmitter::EmitVEXOpcodePrefix(uint64_t TSFlags, unsigned &CurByte, // 0b01000: XOP map select - 08h instructions with imm byte // 0b01001: XOP map select - 09h instructions with no imm byte // 0b01010: XOP map select - 0Ah instructions with imm dword - unsigned char VEX_5M = 0x1; + unsigned char VEX_5M = 0; // VEX_4V (VEX vvvv field): a register specifier // (in 1's complement form) or 1111 if unused. @@ -610,91 +685,53 @@ void X86MCCodeEmitter::EmitVEXOpcodePrefix(uint64_t TSFlags, unsigned &CurByte, // EVEX_b unsigned char EVEX_b = 0; + // EVEX_rc + unsigned char EVEX_rc = 0; + // EVEX_aaa unsigned char EVEX_aaa = 0; - // Encode the operand size opcode prefix as needed. - if (TSFlags & X86II::OpSize) - VEX_PP = 0x01; + bool EncodeRC = false; if ((TSFlags >> X86II::VEXShift) & X86II::VEX_W) VEX_W = 1; - if ((TSFlags >> X86II::VEXShift) & X86II::XOP) - XOP = true; - if ((TSFlags >> X86II::VEXShift) & X86II::VEX_L) VEX_L = 1; - if (HasEVEX && ((TSFlags >> X86II::VEXShift) & X86II::EVEX_L2)) + if (((TSFlags >> X86II::VEXShift) & X86II::EVEX_L2)) EVEX_L2 = 1; if (HasEVEX_K && ((TSFlags >> X86II::VEXShift) & X86II::EVEX_Z)) EVEX_z = 1; - if (HasEVEX && ((TSFlags >> X86II::VEXShift) & X86II::EVEX_B)) + if (((TSFlags >> X86II::VEXShift) & X86II::EVEX_B)) EVEX_b = 1; - switch (TSFlags & X86II::Op0Mask) { - default: llvm_unreachable("Invalid prefix!"); - case X86II::T8: // 0F 38 - VEX_5M = 0x2; - break; - case X86II::TA: // 0F 3A - VEX_5M = 0x3; - break; - case X86II::T8XS: // F3 0F 38 - VEX_PP = 0x2; - VEX_5M = 0x2; - break; - case X86II::T8XD: // F2 0F 38 - VEX_PP = 0x3; - VEX_5M = 0x2; - break; - case X86II::TAXD: // F2 0F 3A - VEX_PP = 0x3; - VEX_5M = 0x3; - break; - case X86II::XS: // F3 0F - VEX_PP = 0x2; - break; - case X86II::XD: // F2 0F - VEX_PP = 0x3; - break; - case X86II::XOP8: - VEX_5M = 0x8; - break; - case X86II::XOP9: - VEX_5M = 0x9; - break; - case X86II::XOPA: - VEX_5M = 0xA; - break; - case X86II::TB: // VEX_5M/VEX_PP already correct - break; + switch (TSFlags & X86II::OpPrefixMask) { + default: break; // VEX_PP already correct + case X86II::PD: VEX_PP = 0x1; break; // 66 + case X86II::XS: VEX_PP = 0x2; break; // F3 + case X86II::XD: VEX_PP = 0x3; break; // F2 } + 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; + } // Classify VEX_B, VEX_4V, VEX_R, VEX_X unsigned NumOps = Desc.getNumOperands(); - unsigned CurOp = 0; - if (NumOps > 1 && Desc.getOperandConstraint(1, MCOI::TIED_TO) == 0) - ++CurOp; - else if (NumOps > 3 && Desc.getOperandConstraint(2, MCOI::TIED_TO) == 0 && - Desc.getOperandConstraint(3, MCOI::TIED_TO) == 1) - // Special case for AVX-512 GATHER with 2 TIED_TO operands - // Skip the first 2 operands: dst, mask_wb - CurOp += 2; - else if (NumOps > 3 && Desc.getOperandConstraint(2, MCOI::TIED_TO) == 0 && - Desc.getOperandConstraint(NumOps - 1, MCOI::TIED_TO) == 1) - // Special case for GATHER with 2 TIED_TO operands - // Skip the first 2 operands: dst, mask_wb - CurOp += 2; - else if (NumOps > 2 && Desc.getOperandConstraint(NumOps - 2, MCOI::TIED_TO) == 0) - // SCATTER - ++CurOp; + unsigned CurOp = X86II::getOperandBias(Desc); switch (TSFlags & X86II::FormMask) { - case X86II::MRMInitReg: llvm_unreachable("FIXME: Remove this!"); + default: llvm_unreachable("Unexpected form in EmitVEXOpcodePrefix!"); + case X86II::RawFrm: + break; case X86II::MRMDestMem: { // MRMDestMem instructions forms: // MemAddr, src1(ModR/M) @@ -707,7 +744,7 @@ void X86MCCodeEmitter::EmitVEXOpcodePrefix(uint64_t TSFlags, unsigned &CurByte, if (X86II::isX86_64ExtendedReg(MI.getOperand(MemOperand + X86::AddrIndexReg).getReg())) VEX_X = 0x0; - if (HasEVEX && X86II::is32ExtendedReg(MI.getOperand(MemOperand + + if (X86II::is32ExtendedReg(MI.getOperand(MemOperand + X86::AddrIndexReg).getReg())) EVEX_V2 = 0x0; @@ -718,7 +755,7 @@ void X86MCCodeEmitter::EmitVEXOpcodePrefix(uint64_t TSFlags, unsigned &CurByte, if (HasVEX_4V) { VEX_4V = getVEXRegisterEncoding(MI, CurOp); - if (HasEVEX && X86II::is32ExtendedReg(MI.getOperand(CurOp).getReg())) + if (X86II::is32ExtendedReg(MI.getOperand(CurOp).getReg())) EVEX_V2 = 0x0; CurOp++; } @@ -727,7 +764,7 @@ void X86MCCodeEmitter::EmitVEXOpcodePrefix(uint64_t TSFlags, unsigned &CurByte, if (MO.isReg()) { if (X86II::isX86_64ExtendedReg(MO.getReg())) VEX_R = 0x0; - if (HasEVEX && X86II::is32ExtendedReg(MO.getReg())) + if (X86II::is32ExtendedReg(MO.getReg())) EVEX_R2 = 0x0; } break; @@ -744,7 +781,7 @@ void X86MCCodeEmitter::EmitVEXOpcodePrefix(uint64_t TSFlags, unsigned &CurByte, // dst(ModR/M.reg), src1(VEX_4V), src2(VEX_I8IMM), src3(ModR/M), if (X86II::isX86_64ExtendedReg(MI.getOperand(CurOp).getReg())) VEX_R = 0x0; - if (HasEVEX && X86II::is32ExtendedReg(MI.getOperand(CurOp).getReg())) + if (X86II::is32ExtendedReg(MI.getOperand(CurOp).getReg())) EVEX_R2 = 0x0; CurOp++; @@ -753,7 +790,7 @@ void X86MCCodeEmitter::EmitVEXOpcodePrefix(uint64_t TSFlags, unsigned &CurByte, if (HasVEX_4V) { VEX_4V = getVEXRegisterEncoding(MI, CurOp); - if (HasEVEX && X86II::is32ExtendedReg(MI.getOperand(CurOp).getReg())) + if (X86II::is32ExtendedReg(MI.getOperand(CurOp).getReg())) EVEX_V2 = 0x0; CurOp++; } @@ -764,8 +801,8 @@ void X86MCCodeEmitter::EmitVEXOpcodePrefix(uint64_t TSFlags, unsigned &CurByte, if (X86II::isX86_64ExtendedReg( MI.getOperand(MemOperand+X86::AddrIndexReg).getReg())) VEX_X = 0x0; - if (HasEVEX && X86II::is32ExtendedReg(MI.getOperand(MemOperand + - X86::AddrIndexReg).getReg())) + if (X86II::is32ExtendedReg(MI.getOperand(MemOperand + + X86::AddrIndexReg).getReg())) EVEX_V2 = 0x0; if (HasVEX_4VOp3) @@ -785,7 +822,7 @@ void X86MCCodeEmitter::EmitVEXOpcodePrefix(uint64_t TSFlags, unsigned &CurByte, // src1(VEX_4V), MemAddr if (HasVEX_4V) { VEX_4V = getVEXRegisterEncoding(MI, CurOp); - if (HasEVEX && X86II::is32ExtendedReg(MI.getOperand(CurOp).getReg())) + if (X86II::is32ExtendedReg(MI.getOperand(CurOp).getReg())) EVEX_V2 = 0x0; CurOp++; } @@ -812,7 +849,7 @@ void X86MCCodeEmitter::EmitVEXOpcodePrefix(uint64_t TSFlags, unsigned &CurByte, // dst(ModR/M.reg), src1(VEX_4V), src2(VEX_I8IMM), src3(ModR/M), if (X86II::isX86_64ExtendedReg(MI.getOperand(CurOp).getReg())) VEX_R = 0x0; - if (HasEVEX && X86II::is32ExtendedReg(MI.getOperand(CurOp).getReg())) + if (X86II::is32ExtendedReg(MI.getOperand(CurOp).getReg())) EVEX_R2 = 0x0; CurOp++; @@ -821,7 +858,7 @@ void X86MCCodeEmitter::EmitVEXOpcodePrefix(uint64_t TSFlags, unsigned &CurByte, if (HasVEX_4V) { VEX_4V = getVEXRegisterEncoding(MI, CurOp); - if (HasEVEX && X86II::is32ExtendedReg(MI.getOperand(CurOp).getReg())) + if (X86II::is32ExtendedReg(MI.getOperand(CurOp).getReg())) EVEX_V2 = 0x0; CurOp++; } @@ -831,11 +868,19 @@ void X86MCCodeEmitter::EmitVEXOpcodePrefix(uint64_t TSFlags, unsigned &CurByte, if (X86II::isX86_64ExtendedReg(MI.getOperand(CurOp).getReg())) VEX_B = 0x0; - if (HasEVEX && X86II::is32ExtendedReg(MI.getOperand(CurOp).getReg())) + if (X86II::is32ExtendedReg(MI.getOperand(CurOp).getReg())) VEX_X = 0x0; CurOp++; if (HasVEX_4VOp3) - VEX_4V = getVEXRegisterEncoding(MI, CurOp); + VEX_4V = getVEXRegisterEncoding(MI, CurOp++); + if (EVEX_b) { + if (HasEVEX_RC) { + unsigned RcOperand = NumOps-1; + assert(RcOperand >= CurOp); + EVEX_rc = MI.getOperand(RcOperand).getImm() & 0x3; + } + EncodeRC = true; + } break; case X86II::MRMDestReg: // MRMDestReg instructions forms: @@ -844,7 +889,7 @@ void X86MCCodeEmitter::EmitVEXOpcodePrefix(uint64_t TSFlags, unsigned &CurByte, // dst(ModR/M), src1(VEX_4V), src2(ModR/M) if (X86II::isX86_64ExtendedReg(MI.getOperand(CurOp).getReg())) VEX_B = 0x0; - if (HasEVEX && X86II::is32ExtendedReg(MI.getOperand(CurOp).getReg())) + if (X86II::is32ExtendedReg(MI.getOperand(CurOp).getReg())) VEX_X = 0x0; CurOp++; @@ -853,15 +898,17 @@ void X86MCCodeEmitter::EmitVEXOpcodePrefix(uint64_t TSFlags, unsigned &CurByte, if (HasVEX_4V) { VEX_4V = getVEXRegisterEncoding(MI, CurOp); - if (HasEVEX && X86II::is32ExtendedReg(MI.getOperand(CurOp).getReg())) + if (X86II::is32ExtendedReg(MI.getOperand(CurOp).getReg())) EVEX_V2 = 0x0; CurOp++; } if (X86II::isX86_64ExtendedReg(MI.getOperand(CurOp).getReg())) VEX_R = 0x0; - if (HasEVEX && X86II::is32ExtendedReg(MI.getOperand(CurOp).getReg())) + if (X86II::is32ExtendedReg(MI.getOperand(CurOp).getReg())) EVEX_R2 = 0x0; + if (EVEX_b) + EncodeRC = true; break; case X86II::MRM0r: case X86II::MRM1r: case X86II::MRM2r: case X86II::MRM3r: @@ -871,26 +918,21 @@ void X86MCCodeEmitter::EmitVEXOpcodePrefix(uint64_t TSFlags, unsigned &CurByte, // dst(VEX_4V), src(ModR/M), imm8 if (HasVEX_4V) { VEX_4V = getVEXRegisterEncoding(MI, CurOp); - if (HasEVEX && X86II::is32ExtendedReg(MI.getOperand(CurOp).getReg())) + if (X86II::is32ExtendedReg(MI.getOperand(CurOp).getReg())) EVEX_V2 = 0x0; CurOp++; - } + } if (HasEVEX_K) EVEX_aaa = getWriteMaskRegisterEncoding(MI, CurOp++); if (X86II::isX86_64ExtendedReg(MI.getOperand(CurOp).getReg())) VEX_B = 0x0; - if (HasEVEX && X86II::is32ExtendedReg(MI.getOperand(CurOp).getReg())) + if (X86II::is32ExtendedReg(MI.getOperand(CurOp).getReg())) VEX_X = 0x0; break; - default: // RawFrm - break; } - // Emit segment override opcode prefix as needed. - EmitSegmentOverridePrefix(TSFlags, CurByte, MemOperand, MI, OS); - - if (!HasEVEX) { + if (Encoding == X86II::VEX || Encoding == X86II::XOP) { // VEX opcode prefix can have 2 or 3 bytes // // 3 bytes: @@ -902,19 +944,25 @@ void X86MCCodeEmitter::EmitVEXOpcodePrefix(uint64_t TSFlags, unsigned &CurByte, // | C5h | | R | vvvv | L | pp | // +-----+ +-------------------+ // + // XOP uses a similar prefix: + // +-----+ +--------------+ +-------------------+ + // | 8Fh | | RXB | m-mmmm | | W | vvvv | L | pp | + // +-----+ +--------------+ +-------------------+ unsigned char LastByte = VEX_PP | (VEX_L << 2) | (VEX_4V << 3); - if (VEX_B && VEX_X && !VEX_W && !XOP && (VEX_5M == 1)) { // 2 byte VEX prefix + // Can we use the 2 byte VEX prefix? + if (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(XOP ? 0x8F : 0xC4, 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 // // +-----+ +--------------+ +-------------------+ +------------------------+ @@ -935,12 +983,19 @@ void X86MCCodeEmitter::EmitVEXOpcodePrefix(uint64_t TSFlags, unsigned &CurByte, (VEX_4V << 3) | (EVEX_U << 2) | VEX_PP, CurByte, OS); - EmitByte((EVEX_z << 7) | - (EVEX_L2 << 6) | - (VEX_L << 5) | - (EVEX_b << 4) | - (EVEX_V2 << 3) | - EVEX_aaa, CurByte, OS); + if (EncodeRC) + 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); } } @@ -974,7 +1029,6 @@ static unsigned DetermineREXPrefix(const MCInst &MI, uint64_t TSFlags, } switch (TSFlags & X86II::FormMask) { - case X86II::MRMInitReg: llvm_unreachable("FIXME: Remove this!"); case X86II::MRMSrcReg: if (MI.getOperand(0).isReg() && X86II::isX86_64ExtendedReg(MI.getOperand(0).getReg())) @@ -1002,6 +1056,7 @@ static unsigned DetermineREXPrefix(const MCInst &MI, uint64_t TSFlags, } break; } + case X86II::MRMXm: case X86II::MRM0m: case X86II::MRM1m: case X86II::MRM2m: case X86II::MRM3m: case X86II::MRM4m: case X86II::MRM5m: @@ -1039,33 +1094,20 @@ static unsigned DetermineREXPrefix(const MCInst &MI, uint64_t TSFlags, } /// EmitSegmentOverridePrefix - Emit segment override opcode prefix as needed -void X86MCCodeEmitter::EmitSegmentOverridePrefix(uint64_t TSFlags, - unsigned &CurByte, int MemOperand, - const MCInst &MI, - raw_ostream &OS) const { - switch (TSFlags & X86II::SegOvrMask) { - default: llvm_unreachable("Invalid segment!"); - case 0: - // No segment override, check for explicit one on memory operand. - if (MemOperand != -1) { // If the instruction has a memory operand. - switch (MI.getOperand(MemOperand+X86::AddrSegmentReg).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; - } - } - break; - case X86II::FS: - EmitByte(0x64, CurByte, OS); - break; - case X86II::GS: - EmitByte(0x65, CurByte, OS); - break; +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; } } @@ -1076,118 +1118,56 @@ void X86MCCodeEmitter::EmitSegmentOverridePrefix(uint64_t TSFlags, void X86MCCodeEmitter::EmitOpcodePrefix(uint64_t TSFlags, unsigned &CurByte, int MemOperand, const MCInst &MI, const MCInstrDesc &Desc, + const MCSubtargetInfo &STI, raw_ostream &OS) const { - // Emit the lock opcode prefix as needed. - if (TSFlags & X86II::LOCK) - EmitByte(0xF0, CurByte, OS); - - // Emit segment override opcode prefix as needed. - EmitSegmentOverridePrefix(TSFlags, CurByte, MemOperand, MI, OS); - - // Emit the repeat opcode prefix as needed. - if ((TSFlags & X86II::Op0Mask) == X86II::REP) - EmitByte(0xF3, CurByte, OS); - - // Emit the address size opcode prefix as needed. - bool need_address_override; - if (TSFlags & X86II::AdSize) { - need_address_override = true; - } else if (MemOperand == -1) { - need_address_override = false; - } else if (is64BitMode()) { - assert(!Is16BitMemOperand(MI, MemOperand)); - need_address_override = Is32BitMemOperand(MI, MemOperand); - } else if (is32BitMode()) { - assert(!Is64BitMemOperand(MI, MemOperand)); - need_address_override = Is16BitMemOperand(MI, MemOperand); - } else { - need_address_override = false; - } - - if (need_address_override) - EmitByte(0x67, CurByte, OS); - // Emit the operand size opcode prefix as needed. - if (TSFlags & X86II::OpSize) + unsigned char OpSize = (TSFlags & X86II::OpSizeMask) >> X86II::OpSizeShift; + if (OpSize == (is16BitMode(STI) ? X86II::OpSize32 : X86II::OpSize16)) EmitByte(0x66, CurByte, OS); - bool Need0FPrefix = false; - switch (TSFlags & X86II::Op0Mask) { - default: llvm_unreachable("Invalid prefix!"); - case 0: break; // No prefix! - case X86II::REP: break; // already handled. - case X86II::TB: // Two-byte opcode prefix - case X86II::T8: // 0F 38 - case X86II::TA: // 0F 3A - case X86II::A6: // 0F A6 - case X86II::A7: // 0F A7 - Need0FPrefix = true; - break; - case X86II::T8XS: // F3 0F 38 - EmitByte(0xF3, CurByte, OS); - Need0FPrefix = true; - break; - case X86II::T8XD: // F2 0F 38 - EmitByte(0xF2, CurByte, OS); - Need0FPrefix = true; - break; - case X86II::TAXD: // F2 0F 3A - EmitByte(0xF2, CurByte, OS); - Need0FPrefix = true; + switch (TSFlags & X86II::OpPrefixMask) { + case X86II::PD: // 66 + EmitByte(0x66, CurByte, OS); break; - case X86II::XS: // F3 0F + case X86II::XS: // F3 EmitByte(0xF3, CurByte, OS); - Need0FPrefix = true; break; - case X86II::XD: // F2 0F + case X86II::XD: // F2 EmitByte(0xF2, CurByte, OS); - Need0FPrefix = true; break; - case X86II::D8: EmitByte(0xD8, CurByte, OS); break; - case X86II::D9: EmitByte(0xD9, CurByte, OS); break; - case X86II::DA: EmitByte(0xDA, CurByte, OS); break; - case X86II::DB: EmitByte(0xDB, CurByte, OS); break; - case X86II::DC: EmitByte(0xDC, CurByte, OS); break; - case X86II::DD: EmitByte(0xDD, CurByte, OS); break; - case X86II::DE: EmitByte(0xDE, CurByte, OS); break; - case X86II::DF: EmitByte(0xDF, CurByte, OS); break; } // Handle REX prefix. // FIXME: Can this come before F2 etc to simplify emission? - if (is64BitMode()) { + if (is64BitMode(STI)) { if (unsigned REX = DetermineREXPrefix(MI, TSFlags, Desc)) EmitByte(0x40 | REX, CurByte, OS); } // 0x0F escape code must be emitted just before the opcode. - if (Need0FPrefix) + switch (TSFlags & X86II::OpMapMask) { + case X86II::TB: // Two-byte opcode map + case X86II::T8: // 0F 38 + case X86II::TA: // 0F 3A EmitByte(0x0F, CurByte, OS); + break; + } - // FIXME: Pull this up into previous switch if REX can be moved earlier. - switch (TSFlags & X86II::Op0Mask) { - case X86II::T8XS: // F3 0F 38 - case X86II::T8XD: // F2 0F 38 + switch (TSFlags & X86II::OpMapMask) { case X86II::T8: // 0F 38 EmitByte(0x38, CurByte, OS); break; - case X86II::TAXD: // F2 0F 3A case X86II::TA: // 0F 3A EmitByte(0x3A, CurByte, OS); break; - case X86II::A6: // 0F A6 - EmitByte(0xA6, CurByte, OS); - break; - case X86II::A7: // 0F A7 - EmitByte(0xA7, CurByte, OS); - break; } } void X86MCCodeEmitter:: EncodeInstruction(const MCInst &MI, raw_ostream &OS, - SmallVectorImpl<MCFixup> &Fixups) const { + SmallVectorImpl<MCFixup> &Fixups, + const MCSubtargetInfo &STI) const { unsigned Opcode = MI.getOpcode(); const MCInstrDesc &Desc = MCII.get(Opcode); uint64_t TSFlags = Desc.TSFlags; @@ -1202,8 +1182,9 @@ EncodeInstruction(const MCInst &MI, raw_ostream &OS, // Keep track of the current byte being emitted. unsigned CurByte = 0; - // Is this instruction encoded using the AVX VEX prefix? - bool HasVEXPrefix = (TSFlags >> X86II::VEXShift) & X86II::VEX; + // Encoding type for this instruction. + unsigned char Encoding = (TSFlags & X86II::EncodingMask) >> + X86II::EncodingShift; // It uses the VEX.VVVV field? bool HasVEX_4V = (TSFlags >> X86II::VEXShift) & X86II::VEX_4V; @@ -1212,15 +1193,58 @@ EncodeInstruction(const MCInst &MI, raw_ostream &OS, const unsigned MemOp4_I8IMMOperand = 2; // It uses the EVEX.aaa field? - bool HasEVEX = (TSFlags >> X86II::VEXShift) & X86II::EVEX; - bool HasEVEX_K = HasEVEX && ((TSFlags >> X86II::VEXShift) & X86II::EVEX_K); - + bool HasEVEX_K = ((TSFlags >> X86II::VEXShift) & X86II::EVEX_K); + bool HasEVEX_RC = ((TSFlags >> X86II::VEXShift) & X86II::EVEX_RC); + // Determine where the memory operand starts, if present. int MemoryOperand = X86II::getMemoryOperandNo(TSFlags, Opcode); if (MemoryOperand != -1) MemoryOperand += CurOp; - if (!HasVEXPrefix) - EmitOpcodePrefix(TSFlags, CurByte, MemoryOperand, MI, Desc, OS); + // Emit the lock opcode prefix as needed. + if (TSFlags & X86II::LOCK) + EmitByte(0xF0, CurByte, OS); + + // 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) + EmitByte(0xF3, CurByte, OS); + + // Emit the address size opcode prefix as needed. + bool need_address_override; + // The AdSize prefix is only for 32-bit and 64-bit modes. Hm, perhaps we + // should introduce an AdSize16 bit instead of having seven special cases? + if ((!is16BitMode(STI) && TSFlags & X86II::AdSize) || + (is16BitMode(STI) && (MI.getOpcode() == X86::JECXZ_32 || + MI.getOpcode() == X86::MOV8o8a || + MI.getOpcode() == X86::MOV16o16a || + MI.getOpcode() == X86::MOV32o32a || + MI.getOpcode() == X86::MOV8ao8 || + MI.getOpcode() == X86::MOV16ao16 || + MI.getOpcode() == X86::MOV32ao32))) { + 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); + + if (Encoding == 0) + EmitOpcodePrefix(TSFlags, CurByte, MemoryOperand, MI, Desc, STI, OS); else EmitVEXOpcodePrefix(TSFlags, CurByte, MemoryOperand, MI, Desc, OS); @@ -1231,15 +1255,62 @@ EncodeInstruction(const MCInst &MI, raw_ostream &OS, unsigned SrcRegNum = 0; switch (TSFlags & X86II::FormMask) { - case X86II::MRMInitReg: - llvm_unreachable("FIXME: Remove this form when the JIT moves to MCCodeEmitter!"); default: errs() << "FORM: " << (TSFlags & X86II::FormMask) << "\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); + 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::RawFrm: EmitByte(BaseOpcode, CurByte, 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), + CurByte, OS, Fixups); + ++CurOp; // skip segment operand + break; case X86II::RawFrmImm8: EmitByte(BaseOpcode, CurByte, OS); EmitImmediate(MI.getOperand(CurOp++), MI.getLoc(), @@ -1288,7 +1359,7 @@ EncodeInstruction(const MCInst &MI, raw_ostream &OS, EmitMemModRMByte(MI, CurOp, GetX86RegNum(MI.getOperand(SrcRegNum)), - TSFlags, CurByte, OS, Fixups); + TSFlags, CurByte, OS, Fixups, STI); CurOp = SrcRegNum + 1; break; @@ -1312,6 +1383,9 @@ EncodeInstruction(const MCInst &MI, raw_ostream &OS, CurOp = HasMemOp4 ? SrcRegNum : SrcRegNum + 1; if (HasVEX_4VOp3) ++CurOp; + // do not count the rounding control operand + if (HasEVEX_RC) + NumOps--; break; case X86II::MRMSrcMem: { @@ -1333,49 +1407,65 @@ EncodeInstruction(const MCInst &MI, raw_ostream &OS, EmitByte(BaseOpcode, CurByte, OS); EmitMemModRMByte(MI, FirstMemOp, GetX86RegNum(MI.getOperand(CurOp)), - TSFlags, CurByte, OS, Fixups); + TSFlags, CurByte, OS, Fixups, STI); CurOp += AddrOperands + 1; if (HasVEX_4VOp3) ++CurOp; 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::MRM6r: case X86II::MRM7r: { if (HasVEX_4V) // Skip the register dst (which is encoded in VEX_VVVV). ++CurOp; EmitByte(BaseOpcode, CurByte, OS); + uint64_t Form = TSFlags & X86II::FormMask; EmitRegModRMByte(MI.getOperand(CurOp++), - (TSFlags & X86II::FormMask)-X86II::MRM0r, + (Form == X86II::MRMXr) ? 0 : Form-X86II::MRM0r, CurByte, OS); 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::MRM6m: case X86II::MRM7m: { if (HasVEX_4V) // Skip the register dst (which is encoded in VEX_VVVV). ++CurOp; EmitByte(BaseOpcode, CurByte, OS); - EmitMemModRMByte(MI, CurOp, (TSFlags & X86II::FormMask)-X86II::MRM0m, - TSFlags, CurByte, OS, Fixups); + uint64_t Form = TSFlags & X86II::FormMask; + EmitMemModRMByte(MI, CurOp, (Form == X86II::MRMXm) ? 0 : Form-X86II::MRM0m, + TSFlags, CurByte, OS, Fixups, STI); CurOp += X86::AddrNumOperands; break; - case X86II::MRM_C1: case X86II::MRM_C2: case X86II::MRM_C3: - case X86II::MRM_C4: case X86II::MRM_C8: case X86II::MRM_C9: - case X86II::MRM_CA: case X86II::MRM_CB: case X86II::MRM_D0: - case X86II::MRM_D1: case X86II::MRM_D4: case X86II::MRM_D5: - case X86II::MRM_D6: 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_E8: case X86II::MRM_F0: case X86II::MRM_F8: - case X86II::MRM_F9: + } + case X86II::MRM_C0: case X86II::MRM_C1: case X86II::MRM_C2: + case X86II::MRM_C3: case X86II::MRM_C4: case X86II::MRM_C8: + case X86II::MRM_C9: case X86II::MRM_CA: case X86II::MRM_CB: + case X86II::MRM_D0: case X86II::MRM_D1: case X86II::MRM_D4: + case X86II::MRM_D5: case X86II::MRM_D6: 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_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_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); unsigned char MRM; switch (TSFlags & X86II::FormMask) { default: llvm_unreachable("Invalid Form"); + case X86II::MRM_C0: MRM = 0xC0; break; case X86II::MRM_C1: MRM = 0xC1; break; case X86II::MRM_C2: MRM = 0xC2; break; case X86II::MRM_C3: MRM = 0xC3; break; @@ -1397,10 +1487,35 @@ EncodeInstruction(const MCInst &MI, raw_ostream &OS, case X86II::MRM_DD: MRM = 0xDD; break; case X86II::MRM_DE: MRM = 0xDE; break; case X86II::MRM_DF: MRM = 0xDF; break; + case X86II::MRM_E0: MRM = 0xE0; break; + case X86II::MRM_E1: MRM = 0xE1; break; + case X86II::MRM_E2: MRM = 0xE2; break; + case X86II::MRM_E3: MRM = 0xE3; break; + case X86II::MRM_E4: MRM = 0xE4; break; + case X86II::MRM_E5: MRM = 0xE5; break; case X86II::MRM_E8: MRM = 0xE8; break; + case X86II::MRM_E9: MRM = 0xE9; break; + case X86II::MRM_EA: MRM = 0xEA; break; + case X86II::MRM_EB: MRM = 0xEB; break; + case X86II::MRM_EC: MRM = 0xEC; break; + case X86II::MRM_ED: MRM = 0xED; break; + case X86II::MRM_EE: MRM = 0xEE; break; case X86II::MRM_F0: MRM = 0xF0; break; + case X86II::MRM_F1: MRM = 0xF1; break; + case X86II::MRM_F2: MRM = 0xF2; break; + case X86II::MRM_F3: MRM = 0xF3; break; + case X86II::MRM_F4: MRM = 0xF4; break; + case X86II::MRM_F5: MRM = 0xF5; break; + case X86II::MRM_F6: MRM = 0xF6; break; + case X86II::MRM_F7: MRM = 0xF7; break; case X86II::MRM_F8: MRM = 0xF8; break; case X86II::MRM_F9: MRM = 0xF9; break; + case X86II::MRM_FA: MRM = 0xFA; break; + case X86II::MRM_FB: MRM = 0xFB; break; + case X86II::MRM_FC: MRM = 0xFC; break; + case X86II::MRM_FD: MRM = 0xFD; break; + case X86II::MRM_FE: MRM = 0xFE; break; + case X86II::MRM_FF: MRM = 0xFF; break; } EmitByte(MRM, CurByte, OS); break; @@ -1432,17 +1547,8 @@ EncodeInstruction(const MCInst &MI, raw_ostream &OS, EmitImmediate(MCOperand::CreateImm(RegNum), MI.getLoc(), 1, FK_Data_1, CurByte, OS, Fixups); } else { - unsigned FixupKind; - // FIXME: Is there a better way to know that we need a signed relocation? - if (MI.getOpcode() == X86::ADD64ri32 || - MI.getOpcode() == X86::MOV64ri32 || - MI.getOpcode() == X86::MOV64mi32 || - MI.getOpcode() == X86::PUSH64i32) - FixupKind = X86::reloc_signed_4byte; - else - FixupKind = getImmFixupKind(TSFlags); EmitImmediate(MI.getOperand(CurOp++), MI.getLoc(), - X86II::getSizeOfImm(TSFlags), MCFixupKind(FixupKind), + X86II::getSizeOfImm(TSFlags), getImmFixupKind(TSFlags), CurByte, OS, Fixups); } } diff --git a/lib/Target/X86/MCTargetDesc/X86MCTargetDesc.cpp b/lib/Target/X86/MCTargetDesc/X86MCTargetDesc.cpp index 1cbdafd..09fdb9c 100644 --- a/lib/Target/X86/MCTargetDesc/X86MCTargetDesc.cpp +++ b/lib/Target/X86/MCTargetDesc/X86MCTargetDesc.cpp @@ -47,9 +47,12 @@ std::string X86_MC::ParseX86Triple(StringRef TT) { Triple TheTriple(TT); std::string FS; if (TheTriple.getArch() == Triple::x86_64) - FS = "+64bit-mode"; + FS = "+64bit-mode,-32bit-mode,-16bit-mode"; + else if (TheTriple.getEnvironment() != Triple::CODE16) + FS = "-64bit-mode,+32bit-mode,-16bit-mode"; else - FS = "-64bit-mode"; + FS = "-64bit-mode,-32bit-mode,+16bit-mode"; + return FS; } @@ -202,8 +205,7 @@ unsigned X86_MC::getDwarfRegFlavour(StringRef TT, bool isEH) { if (TheTriple.isOSDarwin()) return isEH ? DWARFFlavour::X86_32_DarwinEH : DWARFFlavour::X86_32_Generic; - if (TheTriple.getOS() == Triple::MinGW32 || - TheTriple.getOS() == Triple::Cygwin) + if (TheTriple.isOSCygMing()) // Unsupported by now, just quick fallback return DWARFFlavour::X86_32_Generic; return DWARFFlavour::X86_32_Generic; @@ -268,17 +270,17 @@ static MCAsmInfo *createX86MCAsmInfo(const MCRegisterInfo &MRI, StringRef TT) { bool is64Bit = TheTriple.getArch() == Triple::x86_64; MCAsmInfo *MAI; - if (TheTriple.isOSDarwin() || TheTriple.getEnvironment() == Triple::MachO) { + if (TheTriple.isOSBinFormatMachO()) { if (is64Bit) MAI = new X86_64MCAsmInfoDarwin(TheTriple); else MAI = new X86MCAsmInfoDarwin(TheTriple); - } else if (TheTriple.getEnvironment() == Triple::ELF) { + } else if (TheTriple.isOSBinFormatELF()) { // Force the use of an ELF container. MAI = new X86ELFMCAsmInfo(TheTriple); - } else if (TheTriple.getOS() == Triple::Win32) { + } else if (TheTriple.isWindowsMSVCEnvironment()) { MAI = new X86MCAsmInfoMicrosoft(TheTriple); - } else if (TheTriple.getOS() == Triple::MinGW32 || TheTriple.getOS() == Triple::Cygwin) { + } else if (TheTriple.isOSCygMing()) { MAI = new X86MCAsmInfoGNUCOFF(TheTriple); } else { // The default is ELF. @@ -358,17 +360,18 @@ static MCStreamer *createMCStreamer(const Target &T, StringRef TT, MCContext &Ctx, MCAsmBackend &MAB, raw_ostream &_OS, MCCodeEmitter *_Emitter, + const MCSubtargetInfo &STI, bool RelaxAll, bool NoExecStack) { Triple TheTriple(TT); - if (TheTriple.isOSDarwin() || TheTriple.getEnvironment() == Triple::MachO) + if (TheTriple.isOSBinFormatMachO()) return createMachOStreamer(Ctx, MAB, _OS, _Emitter, RelaxAll); - if (TheTriple.isOSWindows() && TheTriple.getEnvironment() != Triple::ELF) + if (TheTriple.isOSWindows() && !TheTriple.isOSBinFormatELF()) return createWinCOFFStreamer(Ctx, MAB, *_Emitter, _OS, RelaxAll); - return createELFStreamer(Ctx, 0, MAB, _OS, _Emitter, RelaxAll, NoExecStack); + return createELFStreamer(Ctx, MAB, _OS, _Emitter, RelaxAll, NoExecStack); } static MCInstPrinter *createX86MCInstPrinter(const Target &T, @@ -387,7 +390,7 @@ static MCInstPrinter *createX86MCInstPrinter(const Target &T, static MCRelocationInfo *createX86MCRelocationInfo(StringRef TT, MCContext &Ctx) { Triple TheTriple(TT); - if (TheTriple.isEnvironmentMachO() && TheTriple.getArch() == Triple::x86_64) + if (TheTriple.isOSBinFormatMachO() && TheTriple.getArch() == Triple::x86_64) return createX86_64MachORelocationInfo(Ctx); else if (TheTriple.isOSBinFormatELF()) return createX86_64ELFRelocationInfo(Ctx); diff --git a/lib/Target/X86/MCTargetDesc/X86MachORelocationInfo.cpp b/lib/Target/X86/MCTargetDesc/X86MachORelocationInfo.cpp index 209b1d0..f2023e3 100644 --- a/lib/Target/X86/MCTargetDesc/X86MachORelocationInfo.cpp +++ b/lib/Target/X86/MCTargetDesc/X86MachORelocationInfo.cpp @@ -11,8 +11,8 @@ #include "llvm/MC/MCContext.h" #include "llvm/MC/MCExpr.h" #include "llvm/MC/MCInst.h" -#include "llvm/MC/MCSymbol.h" #include "llvm/MC/MCRelocationInfo.h" +#include "llvm/MC/MCSymbol.h" #include "llvm/Object/MachO.h" using namespace llvm; @@ -24,7 +24,7 @@ class X86_64MachORelocationInfo : public MCRelocationInfo { public: X86_64MachORelocationInfo(MCContext &Ctx) : MCRelocationInfo(Ctx) {} - const MCExpr *createExprForRelocation(RelocationRef Rel) { + const MCExpr *createExprForRelocation(RelocationRef Rel) override { const MachOObjectFile *Obj = cast<MachOObjectFile>(Rel.getObjectFile()); uint64_t RelType; Rel.getType(RelType); @@ -72,9 +72,9 @@ public: break; case X86_64_RELOC_SUBTRACTOR: { - RelocationRef RelNext; - Obj->getRelocationNext(Rel.getRawDataRefImpl(), RelNext); - any_relocation_info RENext = Obj->getRelocation(RelNext.getRawDataRefImpl()); + Rel.moveNext(); + any_relocation_info RENext = + Obj->getRelocation(Rel.getRawDataRefImpl()); // X86_64_SUBTRACTOR must be followed by a relocation of type // X86_64_RELOC_UNSIGNED. @@ -86,7 +86,7 @@ public: const MCExpr *LHS = MCSymbolRefExpr::Create(Sym, Ctx); - symbol_iterator RSymI = RelNext.getSymbol(); + symbol_iterator RSymI = Rel.getSymbol(); uint64_t RSymAddr; RSymI->getAddress(RSymAddr); StringRef RSymName; diff --git a/lib/Target/X86/MCTargetDesc/X86MachObjectWriter.cpp b/lib/Target/X86/MCTargetDesc/X86MachObjectWriter.cpp index eb7c0b1..1a35ced 100644 --- a/lib/Target/X86/MCTargetDesc/X86MachObjectWriter.cpp +++ b/lib/Target/X86/MCTargetDesc/X86MachObjectWriter.cpp @@ -63,7 +63,7 @@ public: void RecordRelocation(MachObjectWriter *Writer, const MCAssembler &Asm, const MCAsmLayout &Layout, const MCFragment *Fragment, const MCFixup &Fixup, - MCValue Target, uint64_t &FixedValue) { + MCValue Target, uint64_t &FixedValue) override { if (Writer->is64Bit()) RecordX86_64Relocation(Writer, Asm, Layout, Fragment, Fixup, Target, FixedValue); @@ -230,7 +230,7 @@ void X86MachObjectWriter::RecordX86_64Relocation(MachObjectWriter *Writer, if (Symbol->isInSection()) { const MCSectionMachO &Section = static_cast<const MCSectionMachO&>( Fragment->getParent()->getSection()); - if (Section.hasAttribute(MCSectionMachO::S_ATTR_DEBUG)) + if (Section.hasAttribute(MachO::S_ATTR_DEBUG)) Base = 0; } @@ -362,6 +362,7 @@ bool X86MachObjectWriter::RecordScatteredRelocation(MachObjectWriter *Writer, MCValue Target, unsigned Log2Size, uint64_t &FixedValue) { + uint64_t OriginalFixedValue = FixedValue; uint32_t FixupOffset = Layout.getFragmentOffset(Fragment)+Fixup.getOffset(); unsigned IsPCRel = Writer->isFixupKindPCRel(Asm, Fixup.getKind()); unsigned Type = MachO::GENERIC_RELOC_VANILLA; @@ -431,8 +432,10 @@ bool X86MachObjectWriter::RecordScatteredRelocation(MachObjectWriter *Writer, // symbol, things can go badly. // // Required for 'as' compatibility. - if (FixupOffset > 0xffffff) + if (FixupOffset > 0xffffff) { + FixedValue = OriginalFixedValue; return false; + } } MachO::any_relocation_info MRE; diff --git a/lib/Target/X86/MCTargetDesc/X86WinCOFFObjectWriter.cpp b/lib/Target/X86/MCTargetDesc/X86WinCOFFObjectWriter.cpp index 6da4142..ffc9e8d 100644 --- a/lib/Target/X86/MCTargetDesc/X86WinCOFFObjectWriter.cpp +++ b/lib/Target/X86/MCTargetDesc/X86WinCOFFObjectWriter.cpp @@ -29,9 +29,8 @@ namespace { X86WinCOFFObjectWriter(bool Is64Bit_); virtual ~X86WinCOFFObjectWriter(); - virtual unsigned getRelocType(const MCValue &Target, - const MCFixup &Fixup, - bool IsCrossSection) const LLVM_OVERRIDE; + unsigned getRelocType(const MCValue &Target, const MCFixup &Fixup, + bool IsCrossSection) const override; }; } @@ -65,6 +64,9 @@ unsigned X86WinCOFFObjectWriter::getRelocType(const MCValue &Target, if (Is64Bit) return COFF::IMAGE_REL_AMD64_ADDR64; llvm_unreachable("unsupported relocation type"); + case FK_SecRel_2: + return Is64Bit ? COFF::IMAGE_REL_AMD64_SECTION + : COFF::IMAGE_REL_I386_SECTION; case FK_SecRel_4: return Is64Bit ? COFF::IMAGE_REL_AMD64_SECREL : COFF::IMAGE_REL_I386_SECREL; default: |