You've already forked linux-packaging-mono
							
							
		
			
	
	
		
			811 lines
		
	
	
		
			28 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
		
		
			
		
	
	
			811 lines
		
	
	
		
			28 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
|   | //===- 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"
 |