| //===- HexagonMCCodeEmitter.cpp - Hexagon Target Descriptions -------------===// |
| // |
| // The LLVM Compiler Infrastructure |
| // |
| // This file is distributed under the University of Illinois Open Source |
| // License. See LICENSE.TXT for details. |
| // |
| //===----------------------------------------------------------------------===// |
| |
| #include "MCTargetDesc/HexagonMCCodeEmitter.h" |
| #include "Hexagon.h" |
| #include "MCTargetDesc/HexagonBaseInfo.h" |
| #include "MCTargetDesc/HexagonFixupKinds.h" |
| #include "MCTargetDesc/HexagonMCExpr.h" |
| #include "MCTargetDesc/HexagonMCInstrInfo.h" |
| #include "MCTargetDesc/HexagonMCTargetDesc.h" |
| #include "llvm/ADT/Statistic.h" |
| #include "llvm/MC/MCContext.h" |
| #include "llvm/MC/MCExpr.h" |
| #include "llvm/MC/MCFixup.h" |
| #include "llvm/MC/MCInst.h" |
| #include "llvm/MC/MCInstrDesc.h" |
| #include "llvm/MC/MCInstrInfo.h" |
| #include "llvm/MC/MCRegisterInfo.h" |
| #include "llvm/MC/MCSubtargetInfo.h" |
| #include "llvm/Support/Casting.h" |
| #include "llvm/Support/Compiler.h" |
| #include "llvm/Support/Debug.h" |
| #include "llvm/Support/Endian.h" |
| #include "llvm/Support/EndianStream.h" |
| #include "llvm/Support/ErrorHandling.h" |
| #include "llvm/Support/raw_ostream.h" |
| #include <cassert> |
| #include <cstddef> |
| #include <cstdint> |
| #include <string> |
| |
| #define DEBUG_TYPE "mccodeemitter" |
| |
| using namespace llvm; |
| using namespace Hexagon; |
| |
| STATISTIC(MCNumEmitted, "Number of MC instructions emitted"); |
| |
| HexagonMCCodeEmitter::HexagonMCCodeEmitter(MCInstrInfo const &aMII, |
| MCContext &aMCT) |
| : MCT(aMCT), MCII(aMII), Addend(new unsigned(0)), |
| Extended(new bool(false)), CurrentBundle(new MCInst const *), |
| CurrentIndex(new size_t(0)) {} |
| |
| uint32_t HexagonMCCodeEmitter::parseBits(size_t Last, |
| MCInst const &MCB, |
| MCInst const &MCI) const { |
| bool Duplex = HexagonMCInstrInfo::isDuplex(MCII, MCI); |
| if (*CurrentIndex == 0) { |
| if (HexagonMCInstrInfo::isInnerLoop(MCB)) { |
| assert(!Duplex); |
| assert(*CurrentIndex != Last); |
| return HexagonII::INST_PARSE_LOOP_END; |
| } |
| } |
| if (*CurrentIndex == 1) { |
| if (HexagonMCInstrInfo::isOuterLoop(MCB)) { |
| assert(!Duplex); |
| assert(*CurrentIndex != Last); |
| return HexagonII::INST_PARSE_LOOP_END; |
| } |
| } |
| if (Duplex) { |
| assert(*CurrentIndex == Last); |
| return HexagonII::INST_PARSE_DUPLEX; |
| } |
| if(*CurrentIndex == Last) |
| return HexagonII::INST_PARSE_PACKET_END; |
| return HexagonII::INST_PARSE_NOT_END; |
| } |
| |
| /// EncodeInstruction - Emit the bundle |
| void HexagonMCCodeEmitter::encodeInstruction(const MCInst &MI, raw_ostream &OS, |
| SmallVectorImpl<MCFixup> &Fixups, |
| const MCSubtargetInfo &STI) const { |
| MCInst &HMB = const_cast<MCInst &>(MI); |
| |
| assert(HexagonMCInstrInfo::isBundle(HMB)); |
| DEBUG(dbgs() << "Encoding bundle\n";); |
| *Addend = 0; |
| *Extended = false; |
| *CurrentBundle = &MI; |
| *CurrentIndex = 0; |
| size_t Last = HexagonMCInstrInfo::bundleSize(HMB) - 1; |
| for (auto &I : HexagonMCInstrInfo::bundleInstructions(HMB)) { |
| MCInst &HMI = const_cast<MCInst &>(*I.getInst()); |
| verifyInstructionPredicates(HMI, |
| computeAvailableFeatures(STI.getFeatureBits())); |
| |
| EncodeSingleInstruction(HMI, OS, Fixups, STI, |
| parseBits(Last, HMB, HMI)); |
| *Extended = HexagonMCInstrInfo::isImmext(HMI); |
| *Addend += HEXAGON_INSTR_SIZE; |
| ++*CurrentIndex; |
| } |
| } |
| |
| static bool RegisterMatches(unsigned Consumer, unsigned Producer, |
| unsigned Producer2) { |
| if (Consumer == Producer) |
| return true; |
| if (Consumer == Producer2) |
| return true; |
| // Calculate if we're a single vector consumer referencing a double producer |
| if (Producer >= Hexagon::W0 && Producer <= Hexagon::W15) |
| if (Consumer >= Hexagon::V0 && Consumer <= Hexagon::V31) |
| return ((Consumer - Hexagon::V0) >> 1) == (Producer - Hexagon::W0); |
| return false; |
| } |
| |
| /// EncodeSingleInstruction - Emit a single |
| void HexagonMCCodeEmitter::EncodeSingleInstruction( |
| const MCInst &MI, raw_ostream &OS, SmallVectorImpl<MCFixup> &Fixups, |
| const MCSubtargetInfo &STI, uint32_t Parse) const { |
| assert(!HexagonMCInstrInfo::isBundle(MI)); |
| uint64_t Binary; |
| |
| // Pseudo instructions don't get encoded and shouldn't be here |
| // in the first place! |
| assert(!HexagonMCInstrInfo::getDesc(MCII, MI).isPseudo() && |
| "pseudo-instruction found"); |
| DEBUG(dbgs() << "Encoding insn" |
| " `" << HexagonMCInstrInfo::getName(MCII, MI) << "'" |
| "\n"); |
| |
| Binary = getBinaryCodeForInstr(MI, Fixups, STI); |
| // Check for unimplemented instructions. Immediate extenders |
| // are encoded as zero, so they need to be accounted for. |
| if (!Binary && |
| MI.getOpcode() != DuplexIClass0 && |
| MI.getOpcode() != A4_ext) { |
| DEBUG(dbgs() << "Unimplemented inst: " |
| " `" << HexagonMCInstrInfo::getName(MCII, MI) << "'" |
| "\n"); |
| llvm_unreachable("Unimplemented Instruction"); |
| } |
| Binary |= Parse; |
| |
| // if we need to emit a duplexed instruction |
| if (MI.getOpcode() >= Hexagon::DuplexIClass0 && |
| MI.getOpcode() <= Hexagon::DuplexIClassF) { |
| assert(Parse == HexagonII::INST_PARSE_DUPLEX && |
| "Emitting duplex without duplex parse bits"); |
| unsigned dupIClass = MI.getOpcode() - Hexagon::DuplexIClass0; |
| // 29 is the bit position. |
| // 0b1110 =0xE bits are masked off and down shifted by 1 bit. |
| // Last bit is moved to bit position 13 |
| Binary = ((dupIClass & 0xE) << (29 - 1)) | ((dupIClass & 0x1) << 13); |
| |
| const MCInst *subInst0 = MI.getOperand(0).getInst(); |
| const MCInst *subInst1 = MI.getOperand(1).getInst(); |
| |
| // get subinstruction slot 0 |
| unsigned subInstSlot0Bits = getBinaryCodeForInstr(*subInst0, Fixups, STI); |
| // get subinstruction slot 1 |
| unsigned subInstSlot1Bits = getBinaryCodeForInstr(*subInst1, Fixups, STI); |
| |
| Binary |= subInstSlot0Bits | (subInstSlot1Bits << 16); |
| } |
| support::endian::Writer<support::little>(OS).write<uint32_t>(Binary); |
| ++MCNumEmitted; |
| } |
| |
| LLVM_ATTRIBUTE_NORETURN |
| static void raise_relocation_error(unsigned bits, unsigned kind) { |
| std::string Text; |
| { |
| raw_string_ostream Stream(Text); |
| Stream << "Unrecognized relocation combination bits: " << bits |
| << " kind: " << kind; |
| } |
| report_fatal_error(Text); |
| } |
| |
| /// getFixupNoBits - Some insns are not extended and thus have no |
| /// bits. These cases require a more brute force method for determining |
| /// the correct relocation. |
| Hexagon::Fixups HexagonMCCodeEmitter::getFixupNoBits( |
| MCInstrInfo const &MCII, const MCInst &MI, const MCOperand &MO, |
| const MCSymbolRefExpr::VariantKind kind) const { |
| const MCInstrDesc &MCID = HexagonMCInstrInfo::getDesc(MCII, MI); |
| unsigned insnType = HexagonMCInstrInfo::getType(MCII, MI); |
| |
| if (insnType == HexagonII::TypeEXTENDER) { |
| switch (kind) { |
| case MCSymbolRefExpr::VK_GOTREL: |
| return Hexagon::fixup_Hexagon_GOTREL_32_6_X; |
| case MCSymbolRefExpr::VK_GOT: |
| return Hexagon::fixup_Hexagon_GOT_32_6_X; |
| case MCSymbolRefExpr::VK_TPREL: |
| return Hexagon::fixup_Hexagon_TPREL_32_6_X; |
| case MCSymbolRefExpr::VK_DTPREL: |
| return Hexagon::fixup_Hexagon_DTPREL_32_6_X; |
| case MCSymbolRefExpr::VK_Hexagon_GD_GOT: |
| return Hexagon::fixup_Hexagon_GD_GOT_32_6_X; |
| case MCSymbolRefExpr::VK_Hexagon_LD_GOT: |
| return Hexagon::fixup_Hexagon_LD_GOT_32_6_X; |
| case MCSymbolRefExpr::VK_Hexagon_IE: |
| return Hexagon::fixup_Hexagon_IE_32_6_X; |
| case MCSymbolRefExpr::VK_Hexagon_IE_GOT: |
| return Hexagon::fixup_Hexagon_IE_GOT_32_6_X; |
| case MCSymbolRefExpr::VK_Hexagon_PCREL: |
| return Hexagon::fixup_Hexagon_B32_PCREL_X; |
| case MCSymbolRefExpr::VK_Hexagon_GD_PLT: |
| return Hexagon::fixup_Hexagon_GD_PLT_B32_PCREL_X; |
| case MCSymbolRefExpr::VK_Hexagon_LD_PLT: |
| return Hexagon::fixup_Hexagon_LD_PLT_B32_PCREL_X; |
| |
| case MCSymbolRefExpr::VK_None: { |
| auto Insts = HexagonMCInstrInfo::bundleInstructions(**CurrentBundle); |
| for (auto I = Insts.begin(), N = Insts.end(); I != N; ++I) { |
| if (I->getInst() == &MI) { |
| const MCInst &NextI = *(I+1)->getInst(); |
| const MCInstrDesc &D = HexagonMCInstrInfo::getDesc(MCII, NextI); |
| if (D.isBranch() || D.isCall() || |
| HexagonMCInstrInfo::getType(MCII, NextI) == HexagonII::TypeCR) |
| return Hexagon::fixup_Hexagon_B32_PCREL_X; |
| return Hexagon::fixup_Hexagon_32_6_X; |
| } |
| } |
| raise_relocation_error(0, kind); |
| } |
| default: |
| raise_relocation_error(0, kind); |
| } |
| } else if (MCID.isBranch()) |
| return Hexagon::fixup_Hexagon_B13_PCREL; |
| |
| switch (MCID.getOpcode()) { |
| case Hexagon::HI: |
| case Hexagon::A2_tfrih: |
| switch (kind) { |
| case MCSymbolRefExpr::VK_GOT: |
| return Hexagon::fixup_Hexagon_GOT_HI16; |
| case MCSymbolRefExpr::VK_GOTREL: |
| return Hexagon::fixup_Hexagon_GOTREL_HI16; |
| case MCSymbolRefExpr::VK_Hexagon_GD_GOT: |
| return Hexagon::fixup_Hexagon_GD_GOT_HI16; |
| case MCSymbolRefExpr::VK_Hexagon_LD_GOT: |
| return Hexagon::fixup_Hexagon_LD_GOT_HI16; |
| case MCSymbolRefExpr::VK_Hexagon_IE: |
| return Hexagon::fixup_Hexagon_IE_HI16; |
| case MCSymbolRefExpr::VK_Hexagon_IE_GOT: |
| return Hexagon::fixup_Hexagon_IE_GOT_HI16; |
| case MCSymbolRefExpr::VK_TPREL: |
| return Hexagon::fixup_Hexagon_TPREL_HI16; |
| case MCSymbolRefExpr::VK_DTPREL: |
| return Hexagon::fixup_Hexagon_DTPREL_HI16; |
| case MCSymbolRefExpr::VK_None: |
| return Hexagon::fixup_Hexagon_HI16; |
| default: |
| raise_relocation_error(0, kind); |
| } |
| |
| case Hexagon::LO: |
| case Hexagon::A2_tfril: |
| switch (kind) { |
| case MCSymbolRefExpr::VK_GOT: |
| return Hexagon::fixup_Hexagon_GOT_LO16; |
| case MCSymbolRefExpr::VK_GOTREL: |
| return Hexagon::fixup_Hexagon_GOTREL_LO16; |
| case MCSymbolRefExpr::VK_Hexagon_GD_GOT: |
| return Hexagon::fixup_Hexagon_GD_GOT_LO16; |
| case MCSymbolRefExpr::VK_Hexagon_LD_GOT: |
| return Hexagon::fixup_Hexagon_LD_GOT_LO16; |
| case MCSymbolRefExpr::VK_Hexagon_IE: |
| return Hexagon::fixup_Hexagon_IE_LO16; |
| case MCSymbolRefExpr::VK_Hexagon_IE_GOT: |
| return Hexagon::fixup_Hexagon_IE_GOT_LO16; |
| case MCSymbolRefExpr::VK_TPREL: |
| return Hexagon::fixup_Hexagon_TPREL_LO16; |
| case MCSymbolRefExpr::VK_DTPREL: |
| return Hexagon::fixup_Hexagon_DTPREL_LO16; |
| case MCSymbolRefExpr::VK_None: |
| return Hexagon::fixup_Hexagon_LO16; |
| default: |
| raise_relocation_error(0, kind); |
| } |
| |
| // The only relocs left should be GP relative: |
| default: |
| if (MCID.mayStore() || MCID.mayLoad()) { |
| for (const MCPhysReg *ImpUses = MCID.getImplicitUses(); *ImpUses; |
| ++ImpUses) { |
| if (*ImpUses != Hexagon::GP) |
| continue; |
| switch (HexagonMCInstrInfo::getMemAccessSize(MCII, MI)) { |
| case 1: |
| return fixup_Hexagon_GPREL16_0; |
| case 2: |
| return fixup_Hexagon_GPREL16_1; |
| case 4: |
| return fixup_Hexagon_GPREL16_2; |
| case 8: |
| return fixup_Hexagon_GPREL16_3; |
| default: |
| raise_relocation_error(0, kind); |
| } |
| } |
| } |
| raise_relocation_error(0, kind); |
| } |
| llvm_unreachable("Relocation exit not taken"); |
| } |
| |
| namespace llvm { |
| |
| extern const MCInstrDesc HexagonInsts[]; |
| |
| } // end namespace llvm |
| |
| static bool isPCRel (unsigned Kind) { |
| switch(Kind){ |
| case fixup_Hexagon_B22_PCREL: |
| case fixup_Hexagon_B15_PCREL: |
| case fixup_Hexagon_B7_PCREL: |
| case fixup_Hexagon_B13_PCREL: |
| case fixup_Hexagon_B9_PCREL: |
| case fixup_Hexagon_B32_PCREL_X: |
| case fixup_Hexagon_B22_PCREL_X: |
| case fixup_Hexagon_B15_PCREL_X: |
| case fixup_Hexagon_B13_PCREL_X: |
| case fixup_Hexagon_B9_PCREL_X: |
| case fixup_Hexagon_B7_PCREL_X: |
| case fixup_Hexagon_32_PCREL: |
| case fixup_Hexagon_PLT_B22_PCREL: |
| case fixup_Hexagon_GD_PLT_B22_PCREL: |
| case fixup_Hexagon_LD_PLT_B22_PCREL: |
| case fixup_Hexagon_GD_PLT_B22_PCREL_X: |
| case fixup_Hexagon_LD_PLT_B22_PCREL_X: |
| case fixup_Hexagon_6_PCREL_X: |
| return true; |
| default: |
| return false; |
| } |
| } |
| |
| unsigned HexagonMCCodeEmitter::getExprOpValue(const MCInst &MI, |
| const MCOperand &MO, |
| const MCExpr *ME, |
| SmallVectorImpl<MCFixup> &Fixups, |
| const MCSubtargetInfo &STI) const |
| { |
| if (isa<HexagonMCExpr>(ME)) |
| ME = &HexagonMCInstrInfo::getExpr(*ME); |
| int64_t Value; |
| if (ME->evaluateAsAbsolute(Value)) |
| return Value; |
| assert(ME->getKind() == MCExpr::SymbolRef || |
| ME->getKind() == MCExpr::Binary); |
| if (ME->getKind() == MCExpr::Binary) { |
| MCBinaryExpr const *Binary = cast<MCBinaryExpr>(ME); |
| getExprOpValue(MI, MO, Binary->getLHS(), Fixups, STI); |
| getExprOpValue(MI, MO, Binary->getRHS(), Fixups, STI); |
| return 0; |
| } |
| Hexagon::Fixups FixupKind = |
| Hexagon::Fixups(Hexagon::fixup_Hexagon_TPREL_LO16); |
| const MCSymbolRefExpr *MCSRE = static_cast<const MCSymbolRefExpr *>(ME); |
| const MCInstrDesc &MCID = HexagonMCInstrInfo::getDesc(MCII, MI); |
| unsigned bits = HexagonMCInstrInfo::getExtentBits(MCII, MI) - |
| HexagonMCInstrInfo::getExtentAlignment(MCII, MI); |
| const MCSymbolRefExpr::VariantKind kind = MCSRE->getKind(); |
| |
| DEBUG(dbgs() << "----------------------------------------\n"); |
| DEBUG(dbgs() << "Opcode Name: " << HexagonMCInstrInfo::getName(MCII, MI) |
| << "\n"); |
| DEBUG(dbgs() << "Opcode: " << MCID.getOpcode() << "\n"); |
| DEBUG(dbgs() << "Relocation bits: " << bits << "\n"); |
| DEBUG(dbgs() << "Addend: " << *Addend << "\n"); |
| DEBUG(dbgs() << "----------------------------------------\n"); |
| |
| switch (bits) { |
| default: |
| raise_relocation_error(bits, kind); |
| case 32: |
| switch (kind) { |
| case MCSymbolRefExpr::VK_DTPREL: |
| FixupKind = *Extended ? Hexagon::fixup_Hexagon_DTPREL_32_6_X |
| : Hexagon::fixup_Hexagon_DTPREL_32; |
| break; |
| case MCSymbolRefExpr::VK_GOT: |
| FixupKind = *Extended ? Hexagon::fixup_Hexagon_GOT_32_6_X |
| : Hexagon::fixup_Hexagon_GOT_32; |
| break; |
| case MCSymbolRefExpr::VK_GOTREL: |
| FixupKind = *Extended ? Hexagon::fixup_Hexagon_GOTREL_32_6_X |
| : Hexagon::fixup_Hexagon_GOTREL_32; |
| break; |
| case MCSymbolRefExpr::VK_Hexagon_GD_GOT: |
| FixupKind = *Extended ? Hexagon::fixup_Hexagon_GD_GOT_32_6_X |
| : Hexagon::fixup_Hexagon_GD_GOT_32; |
| break; |
| case MCSymbolRefExpr::VK_Hexagon_IE: |
| FixupKind = *Extended ? Hexagon::fixup_Hexagon_IE_32_6_X |
| : Hexagon::fixup_Hexagon_IE_32; |
| break; |
| case MCSymbolRefExpr::VK_Hexagon_IE_GOT: |
| FixupKind = *Extended ? Hexagon::fixup_Hexagon_IE_GOT_32_6_X |
| : Hexagon::fixup_Hexagon_IE_GOT_32; |
| break; |
| case MCSymbolRefExpr::VK_Hexagon_LD_GOT: |
| FixupKind = *Extended ? Hexagon::fixup_Hexagon_LD_GOT_32_6_X |
| : Hexagon::fixup_Hexagon_LD_GOT_32; |
| break; |
| case MCSymbolRefExpr::VK_Hexagon_PCREL: |
| FixupKind = Hexagon::fixup_Hexagon_32_PCREL; |
| break; |
| case MCSymbolRefExpr::VK_None: |
| FixupKind = |
| *Extended ? Hexagon::fixup_Hexagon_32_6_X : Hexagon::fixup_Hexagon_32; |
| break; |
| case MCSymbolRefExpr::VK_TPREL: |
| FixupKind = *Extended ? Hexagon::fixup_Hexagon_TPREL_32_6_X |
| : Hexagon::fixup_Hexagon_TPREL_32; |
| break; |
| default: |
| raise_relocation_error(bits, kind); |
| } |
| break; |
| |
| case 22: |
| switch (kind) { |
| case MCSymbolRefExpr::VK_Hexagon_GD_PLT: |
| FixupKind = *Extended ? Hexagon::fixup_Hexagon_GD_PLT_B22_PCREL_X |
| : Hexagon::fixup_Hexagon_GD_PLT_B22_PCREL; |
| break; |
| case MCSymbolRefExpr::VK_Hexagon_LD_PLT: |
| FixupKind = *Extended ? Hexagon::fixup_Hexagon_LD_PLT_B22_PCREL_X |
| : Hexagon::fixup_Hexagon_LD_PLT_B22_PCREL; |
| break; |
| case MCSymbolRefExpr::VK_None: |
| FixupKind = *Extended ? Hexagon::fixup_Hexagon_B22_PCREL_X |
| : Hexagon::fixup_Hexagon_B22_PCREL; |
| break; |
| case MCSymbolRefExpr::VK_PLT: |
| FixupKind = Hexagon::fixup_Hexagon_PLT_B22_PCREL; |
| break; |
| default: |
| raise_relocation_error(bits, kind); |
| } |
| break; |
| |
| case 16: |
| if (*Extended) { |
| switch (kind) { |
| case MCSymbolRefExpr::VK_DTPREL: |
| FixupKind = Hexagon::fixup_Hexagon_DTPREL_16_X; |
| break; |
| case MCSymbolRefExpr::VK_GOT: |
| FixupKind = Hexagon::fixup_Hexagon_GOT_16_X; |
| break; |
| case MCSymbolRefExpr::VK_GOTREL: |
| FixupKind = Hexagon::fixup_Hexagon_GOTREL_16_X; |
| break; |
| case MCSymbolRefExpr::VK_Hexagon_GD_GOT: |
| FixupKind = Hexagon::fixup_Hexagon_GD_GOT_16_X; |
| break; |
| case MCSymbolRefExpr::VK_Hexagon_IE: |
| FixupKind = Hexagon::fixup_Hexagon_IE_16_X; |
| break; |
| case MCSymbolRefExpr::VK_Hexagon_IE_GOT: |
| FixupKind = Hexagon::fixup_Hexagon_IE_GOT_16_X; |
| break; |
| case MCSymbolRefExpr::VK_Hexagon_LD_GOT: |
| FixupKind = Hexagon::fixup_Hexagon_LD_GOT_16_X; |
| break; |
| case MCSymbolRefExpr::VK_None: |
| FixupKind = Hexagon::fixup_Hexagon_16_X; |
| break; |
| case MCSymbolRefExpr::VK_TPREL: |
| FixupKind = Hexagon::fixup_Hexagon_TPREL_16_X; |
| break; |
| default: |
| raise_relocation_error(bits, kind); |
| } |
| } else |
| switch (kind) { |
| case MCSymbolRefExpr::VK_None: |
| if (HexagonMCInstrInfo::s27_2_reloc(*MO.getExpr())) |
| FixupKind = Hexagon::fixup_Hexagon_27_REG; |
| else |
| if (MCID.mayStore() || MCID.mayLoad()) { |
| for (const MCPhysReg *ImpUses = MCID.getImplicitUses(); *ImpUses; |
| ++ImpUses) { |
| if (*ImpUses != Hexagon::GP) |
| continue; |
| switch (HexagonMCInstrInfo::getMemAccessSize(MCII, MI)) { |
| case 1: |
| FixupKind = fixup_Hexagon_GPREL16_0; |
| break; |
| case 2: |
| FixupKind = fixup_Hexagon_GPREL16_1; |
| break; |
| case 4: |
| FixupKind = fixup_Hexagon_GPREL16_2; |
| break; |
| case 8: |
| FixupKind = fixup_Hexagon_GPREL16_3; |
| break; |
| default: |
| raise_relocation_error(bits, kind); |
| } |
| } |
| } else |
| raise_relocation_error(bits, kind); |
| break; |
| case MCSymbolRefExpr::VK_DTPREL: |
| FixupKind = Hexagon::fixup_Hexagon_DTPREL_16; |
| break; |
| case MCSymbolRefExpr::VK_GOTREL: |
| if (MCID.getOpcode() == Hexagon::HI) |
| FixupKind = Hexagon::fixup_Hexagon_GOTREL_HI16; |
| else |
| FixupKind = Hexagon::fixup_Hexagon_GOTREL_LO16; |
| break; |
| case MCSymbolRefExpr::VK_Hexagon_GD_GOT: |
| FixupKind = Hexagon::fixup_Hexagon_GD_GOT_16; |
| break; |
| case MCSymbolRefExpr::VK_Hexagon_GPREL: |
| FixupKind = Hexagon::fixup_Hexagon_GPREL16_0; |
| break; |
| case MCSymbolRefExpr::VK_Hexagon_HI16: |
| FixupKind = Hexagon::fixup_Hexagon_HI16; |
| break; |
| case MCSymbolRefExpr::VK_Hexagon_IE_GOT: |
| FixupKind = Hexagon::fixup_Hexagon_IE_GOT_16; |
| break; |
| case MCSymbolRefExpr::VK_Hexagon_LD_GOT: |
| FixupKind = Hexagon::fixup_Hexagon_LD_GOT_16; |
| break; |
| case MCSymbolRefExpr::VK_Hexagon_LO16: |
| FixupKind = Hexagon::fixup_Hexagon_LO16; |
| break; |
| case MCSymbolRefExpr::VK_TPREL: |
| FixupKind = Hexagon::fixup_Hexagon_TPREL_16; |
| break; |
| default: |
| raise_relocation_error(bits, kind); |
| } |
| break; |
| |
| case 15: |
| switch (kind) { |
| case MCSymbolRefExpr::VK_None: |
| FixupKind = *Extended ? Hexagon::fixup_Hexagon_B15_PCREL_X |
| : Hexagon::fixup_Hexagon_B15_PCREL; |
| break; |
| default: |
| raise_relocation_error(bits, kind); |
| } |
| break; |
| |
| case 13: |
| switch (kind) { |
| case MCSymbolRefExpr::VK_None: |
| FixupKind = Hexagon::fixup_Hexagon_B13_PCREL; |
| break; |
| default: |
| raise_relocation_error(bits, kind); |
| } |
| break; |
| |
| case 12: |
| if (*Extended) |
| switch (kind) { |
| // There isn't a GOT_12_X, both 11_X and 16_X resolve to 6/26 |
| case MCSymbolRefExpr::VK_GOT: |
| FixupKind = Hexagon::fixup_Hexagon_GOT_16_X; |
| break; |
| case MCSymbolRefExpr::VK_GOTREL: |
| FixupKind = Hexagon::fixup_Hexagon_GOTREL_16_X; |
| break; |
| case MCSymbolRefExpr::VK_None: |
| FixupKind = Hexagon::fixup_Hexagon_12_X; |
| break; |
| default: |
| raise_relocation_error(bits, kind); |
| } |
| else |
| raise_relocation_error(bits, kind); |
| break; |
| |
| case 11: |
| if (*Extended) |
| switch (kind) { |
| case MCSymbolRefExpr::VK_DTPREL: |
| FixupKind = Hexagon::fixup_Hexagon_DTPREL_11_X; |
| break; |
| case MCSymbolRefExpr::VK_GOT: |
| FixupKind = Hexagon::fixup_Hexagon_GOT_11_X; |
| break; |
| case MCSymbolRefExpr::VK_GOTREL: |
| FixupKind = Hexagon::fixup_Hexagon_GOTREL_11_X; |
| break; |
| case MCSymbolRefExpr::VK_Hexagon_GD_GOT: |
| FixupKind = Hexagon::fixup_Hexagon_GD_GOT_11_X; |
| break; |
| case MCSymbolRefExpr::VK_Hexagon_IE_GOT: |
| FixupKind = Hexagon::fixup_Hexagon_IE_GOT_11_X; |
| break; |
| case MCSymbolRefExpr::VK_Hexagon_LD_GOT: |
| FixupKind = Hexagon::fixup_Hexagon_LD_GOT_11_X; |
| break; |
| case MCSymbolRefExpr::VK_Hexagon_GD_PLT: |
| FixupKind = Hexagon::fixup_Hexagon_GD_PLT_B22_PCREL_X; |
| break; |
| case MCSymbolRefExpr::VK_Hexagon_LD_PLT: |
| FixupKind = Hexagon::fixup_Hexagon_LD_PLT_B22_PCREL_X; |
| break; |
| case MCSymbolRefExpr::VK_None: |
| FixupKind = Hexagon::fixup_Hexagon_11_X; |
| break; |
| case MCSymbolRefExpr::VK_TPREL: |
| FixupKind = Hexagon::fixup_Hexagon_TPREL_11_X; |
| break; |
| default: |
| raise_relocation_error(bits, kind); |
| } |
| else { |
| switch (kind) { |
| case MCSymbolRefExpr::VK_TPREL: |
| FixupKind = Hexagon::fixup_Hexagon_TPREL_11_X; |
| break; |
| default: |
| raise_relocation_error(bits, kind); |
| } |
| } |
| break; |
| |
| case 10: |
| if (*Extended) { |
| switch (kind) { |
| case MCSymbolRefExpr::VK_None: |
| FixupKind = Hexagon::fixup_Hexagon_10_X; |
| break; |
| default: |
| raise_relocation_error(bits, kind); |
| } |
| } else |
| raise_relocation_error(bits, kind); |
| break; |
| |
| case 9: |
| if (MCID.isBranch() || |
| (HexagonMCInstrInfo::getType(MCII, MI) == HexagonII::TypeCR)) |
| FixupKind = *Extended ? Hexagon::fixup_Hexagon_B9_PCREL_X |
| : Hexagon::fixup_Hexagon_B9_PCREL; |
| else if (*Extended) |
| FixupKind = Hexagon::fixup_Hexagon_9_X; |
| else |
| raise_relocation_error(bits, kind); |
| break; |
| |
| case 8: |
| if (*Extended) |
| FixupKind = Hexagon::fixup_Hexagon_8_X; |
| else |
| raise_relocation_error(bits, kind); |
| break; |
| |
| case 7: |
| if (MCID.isBranch() || |
| (HexagonMCInstrInfo::getType(MCII, MI) == HexagonII::TypeCR)) |
| FixupKind = *Extended ? Hexagon::fixup_Hexagon_B7_PCREL_X |
| : Hexagon::fixup_Hexagon_B7_PCREL; |
| else if (*Extended) |
| FixupKind = Hexagon::fixup_Hexagon_7_X; |
| else |
| raise_relocation_error(bits, kind); |
| break; |
| |
| case 6: |
| if (*Extended) { |
| switch (kind) { |
| case MCSymbolRefExpr::VK_DTPREL: |
| FixupKind = Hexagon::fixup_Hexagon_DTPREL_16_X; |
| break; |
| // This is part of an extender, GOT_11 is a |
| // Word32_U6 unsigned/truncated reloc. |
| case MCSymbolRefExpr::VK_GOT: |
| FixupKind = Hexagon::fixup_Hexagon_GOT_11_X; |
| break; |
| case MCSymbolRefExpr::VK_GOTREL: |
| FixupKind = Hexagon::fixup_Hexagon_GOTREL_11_X; |
| break; |
| case MCSymbolRefExpr::VK_Hexagon_PCREL: |
| FixupKind = Hexagon::fixup_Hexagon_6_PCREL_X; |
| break; |
| case MCSymbolRefExpr::VK_TPREL: |
| FixupKind = Hexagon::fixup_Hexagon_TPREL_16_X; |
| break; |
| case MCSymbolRefExpr::VK_None: |
| FixupKind = Hexagon::fixup_Hexagon_6_X; |
| break; |
| default: |
| raise_relocation_error(bits, kind); |
| } |
| } else |
| raise_relocation_error(bits, kind); |
| break; |
| |
| case 0: |
| FixupKind = getFixupNoBits(MCII, MI, MO, kind); |
| break; |
| } |
| |
| MCExpr const *FixupExpression = |
| (*Addend > 0 && isPCRel(FixupKind)) |
| ? MCBinaryExpr::createAdd(MO.getExpr(), |
| MCConstantExpr::create(*Addend, MCT), MCT) |
| : MO.getExpr(); |
| |
| MCFixup fixup = MCFixup::create(*Addend, FixupExpression, |
| MCFixupKind(FixupKind), MI.getLoc()); |
| Fixups.push_back(fixup); |
| // All of the information is in the fixup. |
| return 0; |
| } |
| |
| unsigned |
| HexagonMCCodeEmitter::getMachineOpValue(MCInst const &MI, MCOperand const &MO, |
| SmallVectorImpl<MCFixup> &Fixups, |
| MCSubtargetInfo const &STI) const { |
| #ifndef NDEBUG |
| size_t OperandNumber = ~0U; |
| for (unsigned i = 0, n = MI.getNumOperands(); i < n; ++i) |
| if (&MI.getOperand(i) == &MO) { |
| OperandNumber = i; |
| break; |
| } |
| assert((OperandNumber != ~0U) && "Operand not found"); |
| #endif |
| |
| if (HexagonMCInstrInfo::isNewValue(MCII, MI) && |
| &MO == &MI.getOperand(HexagonMCInstrInfo::getNewValueOp(MCII, MI))) { |
| // Calculate the new value distance to the associated producer |
| MCOperand const &MCO = |
| MI.getOperand(HexagonMCInstrInfo::getNewValueOp(MCII, MI)); |
| unsigned SOffset = 0; |
| unsigned VOffset = 0; |
| unsigned Register = MCO.getReg(); |
| unsigned Register1; |
| unsigned Register2; |
| auto Instructions = HexagonMCInstrInfo::bundleInstructions(**CurrentBundle); |
| auto i = Instructions.begin() + *CurrentIndex - 1; |
| for (;; --i) { |
| assert(i != Instructions.begin() - 1 && "Couldn't find producer"); |
| MCInst const &Inst = *i->getInst(); |
| if (HexagonMCInstrInfo::isImmext(Inst)) |
| continue; |
| ++SOffset; |
| if (HexagonMCInstrInfo::isVector(MCII, Inst)) |
| // Vector instructions don't count scalars |
| ++VOffset; |
| Register1 = |
| HexagonMCInstrInfo::hasNewValue(MCII, Inst) |
| ? HexagonMCInstrInfo::getNewValueOperand(MCII, Inst).getReg() |
| : static_cast<unsigned>(Hexagon::NoRegister); |
| Register2 = |
| HexagonMCInstrInfo::hasNewValue2(MCII, Inst) |
| ? HexagonMCInstrInfo::getNewValueOperand2(MCII, Inst).getReg() |
| : static_cast<unsigned>(Hexagon::NoRegister); |
| if (!RegisterMatches(Register, Register1, Register2)) |
| // This isn't the register we're looking for |
| continue; |
| if (!HexagonMCInstrInfo::isPredicated(MCII, Inst)) |
| // Producer is unpredicated |
| break; |
| assert(HexagonMCInstrInfo::isPredicated(MCII, MI) && |
| "Unpredicated consumer depending on predicated producer"); |
| if (HexagonMCInstrInfo::isPredicatedTrue(MCII, Inst) == |
| HexagonMCInstrInfo::isPredicatedTrue(MCII, MI)) |
| // Producer predicate sense matched ours |
| break; |
| } |
| // Hexagon PRM 10.11 Construct Nt from distance |
| unsigned Offset = |
| HexagonMCInstrInfo::isVector(MCII, MI) ? VOffset : SOffset; |
| Offset <<= 1; |
| Offset |= |
| HexagonMCInstrInfo::SubregisterBit(Register, Register1, Register2); |
| return Offset; |
| } |
| assert(!MO.isImm()); |
| if (MO.isReg()) { |
| unsigned Reg = MO.getReg(); |
| if (HexagonMCInstrInfo::isSubInstruction(MI) || |
| HexagonMCInstrInfo::getType(MCII, MI) == HexagonII::TypeCJ) |
| return HexagonMCInstrInfo::getDuplexRegisterNumbering(Reg); |
| return MCT.getRegisterInfo()->getEncodingValue(Reg); |
| } |
| |
| return getExprOpValue(MI, MO, MO.getExpr(), Fixups, STI); |
| } |
| |
| MCCodeEmitter *llvm::createHexagonMCCodeEmitter(MCInstrInfo const &MII, |
| MCRegisterInfo const &MRI, |
| MCContext &MCT) { |
| return new HexagonMCCodeEmitter(MII, MCT); |
| } |
| |
| #define ENABLE_INSTR_PREDICATE_VERIFIER |
| #include "HexagonGenMCCodeEmitter.inc" |