X-Git-Url: http://plrg.eecs.uci.edu/git/?a=blobdiff_plain;f=lib%2FTarget%2FHexagon%2FMCTargetDesc%2FHexagonMCCodeEmitter.cpp;h=9fc4e2aeaba6ab243496fafcdf7f2ab7ca12fcd5;hb=44bf343ec1420b3505aab17c7953d5f68263dee1;hp=a5a09ba1d6308cb7f090730d0038e12223abf4a9;hpb=d40ce7ac2bf5adedfc95b1c33fe2b170af737f36;p=oota-llvm.git diff --git a/lib/Target/Hexagon/MCTargetDesc/HexagonMCCodeEmitter.cpp b/lib/Target/Hexagon/MCTargetDesc/HexagonMCCodeEmitter.cpp index a5a09ba1d63..9fc4e2aeaba 100644 --- a/lib/Target/Hexagon/MCTargetDesc/HexagonMCCodeEmitter.cpp +++ b/lib/Target/Hexagon/MCTargetDesc/HexagonMCCodeEmitter.cpp @@ -9,6 +9,7 @@ #include "Hexagon.h" #include "MCTargetDesc/HexagonBaseInfo.h" +#include "MCTargetDesc/HexagonFixupKinds.h" #include "MCTargetDesc/HexagonMCCodeEmitter.h" #include "MCTargetDesc/HexagonMCInstrInfo.h" #include "MCTargetDesc/HexagonMCTargetDesc.h" @@ -21,6 +22,7 @@ #include "llvm/MC/MCRegisterInfo.h" #include "llvm/MC/MCSubtargetInfo.h" #include "llvm/Support/Debug.h" +#include "llvm/Support/EndianStream.h" #include "llvm/Support/raw_ostream.h" #define DEBUG_TYPE "mccodeemitter" @@ -30,40 +32,678 @@ using namespace Hexagon; STATISTIC(MCNumEmitted, "Number of MC instructions emitted"); -namespace { -/// \brief 10.6 Instruction Packets -/// Possible values for instruction packet parse field. -enum class ParseField { duplex = 0x0, last0 = 0x1, last1 = 0x2, end = 0x3 }; -/// \brief Returns the packet bits based on instruction position. -uint32_t getPacketBits(MCInst const &HMI) { - unsigned const ParseFieldOffset = 14; - ParseField Field = HexagonMCInstrInfo::isPacketEnd(HMI) ? ParseField::end : ParseField::last0; - return static_cast (Field) << ParseFieldOffset; -} -void emitLittleEndian(uint64_t Binary, raw_ostream &OS) { - OS << static_cast((Binary >> 0x00) & 0xff); - OS << static_cast((Binary >> 0x08) & 0xff); - OS << static_cast((Binary >> 0x10) & 0xff); - OS << static_cast((Binary >> 0x18) & 0xff); -} -} - HexagonMCCodeEmitter::HexagonMCCodeEmitter(MCInstrInfo const &aMII, - MCSubtargetInfo const &aMST, MCContext &aMCT) - : MST(aMST), MCT(aMCT), MCII (aMII) {} + : MCT(aMCT), MCII(aMII), Addend(new unsigned(0)), + Extended(new bool(false)), CurrentBundle(new MCInst const *) {} + +uint32_t HexagonMCCodeEmitter::parseBits(size_t Instruction, size_t Last, + MCInst const &MCB, + MCInst const &MCI) const { + bool Duplex = HexagonMCInstrInfo::isDuplex(MCII, MCI); + if (Instruction == 0) { + if (HexagonMCInstrInfo::isInnerLoop(MCB)) { + assert(!Duplex); + assert(Instruction != Last); + return HexagonII::INST_PARSE_LOOP_END; + } + } + if (Instruction == 1) { + if (HexagonMCInstrInfo::isOuterLoop(MCB)) { + assert(!Duplex); + assert(Instruction != Last); + return HexagonII::INST_PARSE_LOOP_END; + } + } + if (Duplex) { + assert(Instruction == Last); + return HexagonII::INST_PARSE_DUPLEX; + } + if(Instruction == Last) + return HexagonII::INST_PARSE_PACKET_END; + return HexagonII::INST_PARSE_NOT_END; +} -void HexagonMCCodeEmitter::EncodeInstruction(MCInst const &MI, raw_ostream &OS, +void HexagonMCCodeEmitter::encodeInstruction(MCInst const &MI, raw_ostream &OS, SmallVectorImpl &Fixups, MCSubtargetInfo const &STI) const { - uint64_t Binary = getBinaryCodeForInstr(MI, Fixups, STI) | getPacketBits(MI); - assert(HexagonMCInstrInfo::getDesc(MCII, MI).getSize() == 4 && - "All instructions should be 32bit"); - (void)&MCII; - emitLittleEndian(Binary, OS); + MCInst &HMB = const_cast(MI); + + assert(HexagonMCInstrInfo::isBundle(HMB)); + DEBUG(dbgs() << "Encoding bundle\n";); + *Addend = 0; + *Extended = false; + *CurrentBundle = &MI; + size_t Instruction = 0; + size_t Last = HexagonMCInstrInfo::bundleSize(HMB) - 1; + for (auto &I : HexagonMCInstrInfo::bundleInstructions(HMB)) { + MCInst &HMI = const_cast(*I.getInst()); + EncodeSingleInstruction(HMI, OS, Fixups, STI, + parseBits(Instruction, Last, HMB, HMI), + Instruction); + *Extended = HexagonMCInstrInfo::isImmext(HMI); + *Addend += HEXAGON_INSTR_SIZE; + ++Instruction; + } + return; +} + +/// EncodeSingleInstruction - Emit a single +void HexagonMCCodeEmitter::EncodeSingleInstruction( + const MCInst &MI, raw_ostream &OS, SmallVectorImpl &Fixups, + const MCSubtargetInfo &STI, uint32_t Parse, size_t Index) const { + MCInst HMB = MI; + assert(!HexagonMCInstrInfo::isBundle(HMB)); + uint64_t Binary; + + // Pseudo instructions don't get encoded and shouldn't be here + // in the first place! + assert(!HexagonMCInstrInfo::getDesc(MCII, HMB).isPseudo() && + "pseudo-instruction found"); + DEBUG(dbgs() << "Encoding insn" + " `" << HexagonMCInstrInfo::getName(MCII, HMB) << "'" + "\n"); + + if (HexagonMCInstrInfo::isNewValue(MCII, HMB)) { + // Calculate the new value distance to the associated producer + MCOperand &MCO = + HMB.getOperand(HexagonMCInstrInfo::getNewValueOp(MCII, HMB)); + unsigned SOffset = 0; + unsigned Register = MCO.getReg(); + unsigned Register1; + auto Instructions = HexagonMCInstrInfo::bundleInstructions(**CurrentBundle); + auto i = Instructions.begin() + Index - 1; + for (;; --i) { + assert(i != Instructions.begin() - 1 && "Couldn't find producer"); + MCInst const &Inst = *i->getInst(); + if (HexagonMCInstrInfo::isImmext(Inst)) + continue; + ++SOffset; + Register1 = + HexagonMCInstrInfo::hasNewValue(MCII, Inst) + ? HexagonMCInstrInfo::getNewValueOperand(MCII, Inst).getReg() + : static_cast(Hexagon::NoRegister); + if (Register != Register1) + // This isn't the register we're looking for + continue; + if (!HexagonMCInstrInfo::isPredicated(MCII, Inst)) + // Producer is unpredicated + break; + assert(HexagonMCInstrInfo::isPredicated(MCII, HMB) && + "Unpredicated consumer depending on predicated producer"); + if (HexagonMCInstrInfo::isPredicatedTrue(MCII, Inst) == + HexagonMCInstrInfo::isPredicatedTrue(MCII, HMB)) + // Producer predicate sense matched ours + break; + } + // Hexagon PRM 10.11 Construct Nt from distance + unsigned Offset = SOffset; + Offset <<= 1; + MCO.setReg(Offset + Hexagon::R0); + } + + Binary = getBinaryCodeForInstr(HMB, Fixups, STI); + // Check for unimplemented instructions. Immediate extenders + // are encoded as zero, so they need to be accounted for. + if ((!Binary) && + ((HMB.getOpcode() != DuplexIClass0) && (HMB.getOpcode() != A4_ext) && + (HMB.getOpcode() != A4_ext_b) && (HMB.getOpcode() != A4_ext_c) && + (HMB.getOpcode() != A4_ext_g))) { + // Use a A2_nop for unimplemented instructions. + DEBUG(dbgs() << "Unimplemented inst: " + " `" << HexagonMCInstrInfo::getName(MCII, HMB) << "'" + "\n"); + llvm_unreachable("Unimplemented Instruction"); + } + Binary |= Parse; + + // if we need to emit a duplexed instruction + if (HMB.getOpcode() >= Hexagon::DuplexIClass0 && + HMB.getOpcode() <= Hexagon::DuplexIClassF) { + assert(Parse == HexagonII::INST_PARSE_DUPLEX && + "Emitting duplex without duplex parse bits"); + unsigned dupIClass; + switch (HMB.getOpcode()) { + case Hexagon::DuplexIClass0: + dupIClass = 0; + break; + case Hexagon::DuplexIClass1: + dupIClass = 1; + break; + case Hexagon::DuplexIClass2: + dupIClass = 2; + break; + case Hexagon::DuplexIClass3: + dupIClass = 3; + break; + case Hexagon::DuplexIClass4: + dupIClass = 4; + break; + case Hexagon::DuplexIClass5: + dupIClass = 5; + break; + case Hexagon::DuplexIClass6: + dupIClass = 6; + break; + case Hexagon::DuplexIClass7: + dupIClass = 7; + break; + case Hexagon::DuplexIClass8: + dupIClass = 8; + break; + case Hexagon::DuplexIClass9: + dupIClass = 9; + break; + case Hexagon::DuplexIClassA: + dupIClass = 10; + break; + case Hexagon::DuplexIClassB: + dupIClass = 11; + break; + case Hexagon::DuplexIClassC: + dupIClass = 12; + break; + case Hexagon::DuplexIClassD: + dupIClass = 13; + break; + case Hexagon::DuplexIClassE: + dupIClass = 14; + break; + case Hexagon::DuplexIClassF: + dupIClass = 15; + break; + default: + llvm_unreachable("Unimplemented DuplexIClass"); + break; + } + // 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 = HMB.getOperand(0).getInst(); + const MCInst *subInst1 = HMB.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(OS).write(Binary); ++MCNumEmitted; } +static Hexagon::Fixups getFixupNoBits(MCInstrInfo const &MCII, const MCInst &MI, + const MCOperand &MO, + const MCSymbolRefExpr::VariantKind kind) { + const MCInstrDesc &MCID = HexagonMCInstrInfo::getDesc(MCII, MI); + unsigned insnType = llvm::HexagonMCInstrInfo::getType(MCII, MI); + + if (insnType == HexagonII::TypePREFIX) { + switch (kind) { + case llvm::MCSymbolRefExpr::VK_GOTOFF: + return Hexagon::fixup_Hexagon_GOTREL_32_6_X; + case llvm::MCSymbolRefExpr::VK_GOT: + return Hexagon::fixup_Hexagon_GOT_32_6_X; + case llvm::MCSymbolRefExpr::VK_TPREL: + return Hexagon::fixup_Hexagon_TPREL_32_6_X; + case llvm::MCSymbolRefExpr::VK_DTPREL: + return Hexagon::fixup_Hexagon_DTPREL_32_6_X; + case llvm::MCSymbolRefExpr::VK_Hexagon_GD_GOT: + return Hexagon::fixup_Hexagon_GD_GOT_32_6_X; + case llvm::MCSymbolRefExpr::VK_Hexagon_LD_GOT: + return Hexagon::fixup_Hexagon_LD_GOT_32_6_X; + case llvm::MCSymbolRefExpr::VK_Hexagon_IE: + return Hexagon::fixup_Hexagon_IE_32_6_X; + case llvm::MCSymbolRefExpr::VK_Hexagon_IE_GOT: + return Hexagon::fixup_Hexagon_IE_GOT_32_6_X; + default: + if (MCID.isBranch()) + return Hexagon::fixup_Hexagon_B32_PCREL_X; + else + return Hexagon::fixup_Hexagon_32_6_X; + } + } else if (MCID.isBranch()) + return (Hexagon::fixup_Hexagon_B13_PCREL); + + switch (MCID.getOpcode()) { + case Hexagon::HI: + case Hexagon::A2_tfrih: + switch (kind) { + case llvm::MCSymbolRefExpr::VK_GOT: + return Hexagon::fixup_Hexagon_GOT_HI16; + case llvm::MCSymbolRefExpr::VK_GOTOFF: + return Hexagon::fixup_Hexagon_GOTREL_HI16; + case llvm::MCSymbolRefExpr::VK_Hexagon_GD_GOT: + return Hexagon::fixup_Hexagon_GD_GOT_HI16; + case llvm::MCSymbolRefExpr::VK_Hexagon_LD_GOT: + return Hexagon::fixup_Hexagon_LD_GOT_HI16; + case llvm::MCSymbolRefExpr::VK_Hexagon_IE: + return Hexagon::fixup_Hexagon_IE_HI16; + case llvm::MCSymbolRefExpr::VK_Hexagon_IE_GOT: + return Hexagon::fixup_Hexagon_IE_GOT_HI16; + case llvm::MCSymbolRefExpr::VK_TPREL: + return Hexagon::fixup_Hexagon_TPREL_HI16; + case llvm::MCSymbolRefExpr::VK_DTPREL: + return Hexagon::fixup_Hexagon_DTPREL_HI16; + default: + return Hexagon::fixup_Hexagon_HI16; + } + + case Hexagon::LO: + case Hexagon::A2_tfril: + switch (kind) { + case llvm::MCSymbolRefExpr::VK_GOT: + return Hexagon::fixup_Hexagon_GOT_LO16; + case llvm::MCSymbolRefExpr::VK_GOTOFF: + return Hexagon::fixup_Hexagon_GOTREL_LO16; + case llvm::MCSymbolRefExpr::VK_Hexagon_GD_GOT: + return Hexagon::fixup_Hexagon_GD_GOT_LO16; + case llvm::MCSymbolRefExpr::VK_Hexagon_LD_GOT: + return Hexagon::fixup_Hexagon_LD_GOT_LO16; + case llvm::MCSymbolRefExpr::VK_Hexagon_IE: + return Hexagon::fixup_Hexagon_IE_LO16; + case llvm::MCSymbolRefExpr::VK_Hexagon_IE_GOT: + return Hexagon::fixup_Hexagon_IE_GOT_LO16; + case llvm::MCSymbolRefExpr::VK_TPREL: + return Hexagon::fixup_Hexagon_TPREL_LO16; + case llvm::MCSymbolRefExpr::VK_DTPREL: + return Hexagon::fixup_Hexagon_DTPREL_LO16; + default: + return Hexagon::fixup_Hexagon_LO16; + } + + // The only relocs left should be GP relative: + default: + if (MCID.mayStore() || MCID.mayLoad()) { + for (const uint16_t *ImpUses = MCID.getImplicitUses(); *ImpUses; + ++ImpUses) { + if (*ImpUses == Hexagon::GP) { + switch (HexagonMCInstrInfo::getAccessSize(MCII, MI)) { + case HexagonII::MemAccessSize::ByteAccess: + return fixup_Hexagon_GPREL16_0; + case HexagonII::MemAccessSize::HalfWordAccess: + return fixup_Hexagon_GPREL16_1; + case HexagonII::MemAccessSize::WordAccess: + return fixup_Hexagon_GPREL16_2; + case HexagonII::MemAccessSize::DoubleWordAccess: + return fixup_Hexagon_GPREL16_3; + default: + llvm_unreachable("unhandled fixup"); + } + } + } + } else + llvm_unreachable("unhandled fixup"); + } + + return LastTargetFixupKind; +} + +namespace llvm { +extern const MCInstrDesc HexagonInsts[]; +} + +namespace { + 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_6_PCREL_X: + return true; + default: + return false; + } + } +} + +unsigned HexagonMCCodeEmitter::getExprOpValue(const MCInst &MI, + const MCOperand &MO, + const MCExpr *ME, + SmallVectorImpl &Fixups, + const MCSubtargetInfo &STI) const + +{ + int64_t Res; + + if (ME->evaluateAsAbsolute(Res)) + return Res; + + MCExpr::ExprKind MK = ME->getKind(); + if (MK == MCExpr::Constant) { + return cast(ME)->getValue(); + } + if (MK == MCExpr::Binary) { + unsigned Res; + Res = getExprOpValue(MI, MO, cast(ME)->getLHS(), Fixups, STI); + Res += + getExprOpValue(MI, MO, cast(ME)->getRHS(), Fixups, STI); + return 0; + } + + assert(MK == MCExpr::SymbolRef); + + Hexagon::Fixups FixupKind = + Hexagon::Fixups(Hexagon::fixup_Hexagon_TPREL_LO16); + const MCSymbolRefExpr *MCSRE = static_cast(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: + DEBUG(dbgs() << "unrecognized bit count of " << bits << '\n'); + break; + + case 32: + switch (kind) { + case llvm::MCSymbolRefExpr::VK_Hexagon_PCREL: + FixupKind = Hexagon::fixup_Hexagon_32_PCREL; + break; + case llvm::MCSymbolRefExpr::VK_GOT: + FixupKind = *Extended ? Hexagon::fixup_Hexagon_GOT_32_6_X + : Hexagon::fixup_Hexagon_GOT_32; + break; + case llvm::MCSymbolRefExpr::VK_GOTOFF: + FixupKind = *Extended ? Hexagon::fixup_Hexagon_GOTREL_32_6_X + : Hexagon::fixup_Hexagon_GOTREL_32; + break; + case llvm::MCSymbolRefExpr::VK_Hexagon_GD_GOT: + FixupKind = *Extended ? Hexagon::fixup_Hexagon_GD_GOT_32_6_X + : Hexagon::fixup_Hexagon_GD_GOT_32; + break; + case llvm::MCSymbolRefExpr::VK_Hexagon_LD_GOT: + FixupKind = *Extended ? Hexagon::fixup_Hexagon_LD_GOT_32_6_X + : Hexagon::fixup_Hexagon_LD_GOT_32; + break; + case llvm::MCSymbolRefExpr::VK_Hexagon_IE: + FixupKind = *Extended ? Hexagon::fixup_Hexagon_IE_32_6_X + : Hexagon::fixup_Hexagon_IE_32; + break; + case llvm::MCSymbolRefExpr::VK_Hexagon_IE_GOT: + FixupKind = *Extended ? Hexagon::fixup_Hexagon_IE_GOT_32_6_X + : Hexagon::fixup_Hexagon_IE_GOT_32; + break; + case llvm::MCSymbolRefExpr::VK_TPREL: + FixupKind = *Extended ? Hexagon::fixup_Hexagon_TPREL_32_6_X + : Hexagon::fixup_Hexagon_TPREL_32; + break; + case llvm::MCSymbolRefExpr::VK_DTPREL: + FixupKind = *Extended ? Hexagon::fixup_Hexagon_DTPREL_32_6_X + : Hexagon::fixup_Hexagon_DTPREL_32; + break; + default: + FixupKind = + *Extended ? Hexagon::fixup_Hexagon_32_6_X : Hexagon::fixup_Hexagon_32; + break; + } + break; + + case 22: + switch (kind) { + case llvm::MCSymbolRefExpr::VK_Hexagon_GD_PLT: + FixupKind = Hexagon::fixup_Hexagon_GD_PLT_B22_PCREL; + break; + case llvm::MCSymbolRefExpr::VK_Hexagon_LD_PLT: + FixupKind = Hexagon::fixup_Hexagon_LD_PLT_B22_PCREL; + break; + default: + if (MCID.isBranch() || MCID.isCall()) { + FixupKind = *Extended ? Hexagon::fixup_Hexagon_B22_PCREL_X + : Hexagon::fixup_Hexagon_B22_PCREL; + } else { + errs() << "unrecognized relocation, bits: " << bits << "\n"; + errs() << "name = " << HexagonMCInstrInfo::getName(MCII, MI) << "\n"; + } + break; + } + break; + + case 16: + if (*Extended) { + switch (kind) { + default: + FixupKind = Hexagon::fixup_Hexagon_16_X; + break; + case llvm::MCSymbolRefExpr::VK_GOT: + FixupKind = Hexagon::fixup_Hexagon_GOT_16_X; + break; + case llvm::MCSymbolRefExpr::VK_GOTOFF: + FixupKind = Hexagon::fixup_Hexagon_GOTREL_16_X; + break; + case llvm::MCSymbolRefExpr::VK_Hexagon_GD_GOT: + FixupKind = Hexagon::fixup_Hexagon_GD_GOT_16_X; + break; + case llvm::MCSymbolRefExpr::VK_Hexagon_LD_GOT: + FixupKind = Hexagon::fixup_Hexagon_LD_GOT_16_X; + break; + case llvm::MCSymbolRefExpr::VK_Hexagon_IE: + FixupKind = Hexagon::fixup_Hexagon_IE_16_X; + break; + case llvm::MCSymbolRefExpr::VK_Hexagon_IE_GOT: + FixupKind = Hexagon::fixup_Hexagon_IE_GOT_16_X; + break; + case llvm::MCSymbolRefExpr::VK_TPREL: + FixupKind = Hexagon::fixup_Hexagon_TPREL_16_X; + break; + case llvm::MCSymbolRefExpr::VK_DTPREL: + FixupKind = Hexagon::fixup_Hexagon_DTPREL_16_X; + break; + } + } else + switch (kind) { + default: + errs() << "unrecognized relocation, bits " << bits << "\n"; + errs() << "name = " << HexagonMCInstrInfo::getName(MCII, MI) << "\n"; + break; + case llvm::MCSymbolRefExpr::VK_GOTOFF: + if ((MCID.getOpcode() == Hexagon::HI) || + (MCID.getOpcode() == Hexagon::LO_H)) + FixupKind = Hexagon::fixup_Hexagon_GOTREL_HI16; + else + FixupKind = Hexagon::fixup_Hexagon_GOTREL_LO16; + break; + case llvm::MCSymbolRefExpr::VK_Hexagon_GPREL: + FixupKind = Hexagon::fixup_Hexagon_GPREL16_0; + break; + case llvm::MCSymbolRefExpr::VK_Hexagon_LO16: + FixupKind = Hexagon::fixup_Hexagon_LO16; + break; + case llvm::MCSymbolRefExpr::VK_Hexagon_HI16: + FixupKind = Hexagon::fixup_Hexagon_HI16; + break; + case llvm::MCSymbolRefExpr::VK_Hexagon_GD_GOT: + FixupKind = Hexagon::fixup_Hexagon_GD_GOT_16; + break; + case llvm::MCSymbolRefExpr::VK_Hexagon_LD_GOT: + FixupKind = Hexagon::fixup_Hexagon_LD_GOT_16; + break; + case llvm::MCSymbolRefExpr::VK_Hexagon_IE_GOT: + FixupKind = Hexagon::fixup_Hexagon_IE_GOT_16; + break; + case llvm::MCSymbolRefExpr::VK_TPREL: + FixupKind = Hexagon::fixup_Hexagon_TPREL_16; + break; + case llvm::MCSymbolRefExpr::VK_DTPREL: + FixupKind = Hexagon::fixup_Hexagon_DTPREL_16; + break; + } + break; + + case 15: + if (MCID.isBranch() || MCID.isCall()) + FixupKind = *Extended ? Hexagon::fixup_Hexagon_B15_PCREL_X + : Hexagon::fixup_Hexagon_B15_PCREL; + break; + + case 13: + if (MCID.isBranch()) + FixupKind = Hexagon::fixup_Hexagon_B13_PCREL; + else { + errs() << "unrecognized relocation, bits " << bits << "\n"; + errs() << "name = " << HexagonMCInstrInfo::getName(MCII, MI) << "\n"; + } + break; + + case 12: + if (*Extended) + switch (kind) { + default: + FixupKind = Hexagon::fixup_Hexagon_12_X; + break; + // There isn't a GOT_12_X, both 11_X and 16_X resolve to 6/26 + case llvm::MCSymbolRefExpr::VK_GOT: + FixupKind = Hexagon::fixup_Hexagon_GOT_16_X; + break; + case llvm::MCSymbolRefExpr::VK_GOTOFF: + FixupKind = Hexagon::fixup_Hexagon_GOTREL_16_X; + break; + } + else { + errs() << "unrecognized relocation, bits " << bits << "\n"; + errs() << "name = " << HexagonMCInstrInfo::getName(MCII, MI) << "\n"; + } + break; + + case 11: + if (*Extended) + switch (kind) { + default: + FixupKind = Hexagon::fixup_Hexagon_11_X; + break; + case llvm::MCSymbolRefExpr::VK_GOT: + FixupKind = Hexagon::fixup_Hexagon_GOT_11_X; + break; + case llvm::MCSymbolRefExpr::VK_GOTOFF: + FixupKind = Hexagon::fixup_Hexagon_GOTREL_11_X; + break; + case llvm::MCSymbolRefExpr::VK_Hexagon_GD_GOT: + FixupKind = Hexagon::fixup_Hexagon_GD_GOT_11_X; + break; + case llvm::MCSymbolRefExpr::VK_Hexagon_LD_GOT: + FixupKind = Hexagon::fixup_Hexagon_LD_GOT_11_X; + break; + case llvm::MCSymbolRefExpr::VK_Hexagon_IE_GOT: + FixupKind = Hexagon::fixup_Hexagon_IE_GOT_11_X; + break; + case llvm::MCSymbolRefExpr::VK_TPREL: + FixupKind = Hexagon::fixup_Hexagon_TPREL_11_X; + break; + case llvm::MCSymbolRefExpr::VK_DTPREL: + FixupKind = Hexagon::fixup_Hexagon_DTPREL_11_X; + break; + } + else { + errs() << "unrecognized relocation, bits " << bits << "\n"; + errs() << "name = " << HexagonMCInstrInfo::getName(MCII, MI) << "\n"; + } + break; + + case 10: + if (*Extended) + FixupKind = Hexagon::fixup_Hexagon_10_X; + break; + + case 9: + if (MCID.isBranch() || + (llvm::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 { + errs() << "unrecognized relocation, bits " << bits << "\n"; + errs() << "name = " << HexagonMCInstrInfo::getName(MCII, MI) << "\n"; + } + break; + + case 8: + if (*Extended) + FixupKind = Hexagon::fixup_Hexagon_8_X; + else { + errs() << "unrecognized relocation, bits " << bits << "\n"; + errs() << "name = " << HexagonMCInstrInfo::getName(MCII, MI) << "\n"; + } + break; + + case 7: + if (MCID.isBranch() || + (llvm::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 { + errs() << "unrecognized relocation, bits " << bits << "\n"; + errs() << "name = " << HexagonMCInstrInfo::getName(MCII, MI) << "\n"; + } + break; + + case 6: + if (*Extended) { + switch (kind) { + default: + FixupKind = Hexagon::fixup_Hexagon_6_X; + break; + case llvm::MCSymbolRefExpr::VK_Hexagon_PCREL: + FixupKind = Hexagon::fixup_Hexagon_6_PCREL_X; + break; + // This is part of an extender, GOT_11 is a + // Word32_U6 unsigned/truncated reloc. + case llvm::MCSymbolRefExpr::VK_GOT: + FixupKind = Hexagon::fixup_Hexagon_GOT_11_X; + break; + case llvm::MCSymbolRefExpr::VK_GOTOFF: + FixupKind = Hexagon::fixup_Hexagon_GOTREL_11_X; + break; + } + } else { + errs() << "unrecognized relocation, bits " << bits << "\n"; + errs() << "name = " << HexagonMCInstrInfo::getName(MCII, MI) << "\n"; + } + 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 &Fixups, @@ -72,18 +712,16 @@ HexagonMCCodeEmitter::getMachineOpValue(MCInst const &MI, MCOperand const &MO, return MCT.getRegisterInfo()->getEncodingValue(MO.getReg()); if (MO.isImm()) return static_cast(MO.getImm()); - llvm_unreachable("Only Immediates and Registers implemented right now"); -} -MCSubtargetInfo const &HexagonMCCodeEmitter::getSubtargetInfo() const { - return MST; + // MO must be an ME. + assert(MO.isExpr()); + return getExprOpValue(MI, MO, MO.getExpr(), Fixups, STI); } MCCodeEmitter *llvm::createHexagonMCCodeEmitter(MCInstrInfo const &MII, MCRegisterInfo const &MRI, - MCSubtargetInfo const &MST, MCContext &MCT) { - return new HexagonMCCodeEmitter(MII, MST, MCT); + return new HexagonMCCodeEmitter(MII, MCT); } #include "HexagonGenMCCodeEmitter.inc"