diff options
Diffstat (limited to 'contrib/llvm/lib/Target/Hexagon/MCTargetDesc/HexagonMCCodeEmitter.cpp')
-rw-r--r-- | contrib/llvm/lib/Target/Hexagon/MCTargetDesc/HexagonMCCodeEmitter.cpp | 467 |
1 files changed, 451 insertions, 16 deletions
diff --git a/contrib/llvm/lib/Target/Hexagon/MCTargetDesc/HexagonMCCodeEmitter.cpp b/contrib/llvm/lib/Target/Hexagon/MCTargetDesc/HexagonMCCodeEmitter.cpp index 487872a..ae3953a 100644 --- a/contrib/llvm/lib/Target/Hexagon/MCTargetDesc/HexagonMCCodeEmitter.cpp +++ b/contrib/llvm/lib/Target/Hexagon/MCTargetDesc/HexagonMCCodeEmitter.cpp @@ -9,8 +9,9 @@ #include "Hexagon.h" #include "MCTargetDesc/HexagonBaseInfo.h" +#include "MCTargetDesc/HexagonFixupKinds.h" #include "MCTargetDesc/HexagonMCCodeEmitter.h" -#include "MCTargetDesc/HexagonMCInst.h" +#include "MCTargetDesc/HexagonMCInstrInfo.h" #include "MCTargetDesc/HexagonMCTargetDesc.h" #include "llvm/ADT/Statistic.h" #include "llvm/MC/MCCodeEmitter.h" @@ -35,10 +36,11 @@ namespace { /// 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(HexagonMCInst const &HMI) { +uint32_t getPacketBits(MCInst const &HMI) { unsigned const ParseFieldOffset = 14; - ParseField Field = HMI.isPacketEnd() ? ParseField::end : ParseField::last0; - return static_cast <uint32_t> (Field) << ParseFieldOffset; + ParseField Field = HexagonMCInstrInfo::isPacketEnd(HMI) ? ParseField::end + : ParseField::last0; + return static_cast<uint32_t>(Field) << ParseFieldOffset; } void emitLittleEndian(uint64_t Binary, raw_ostream &OS) { OS << static_cast<uint8_t>((Binary >> 0x00) & 0xff); @@ -49,20 +51,455 @@ void emitLittleEndian(uint64_t Binary, raw_ostream &OS) { } HexagonMCCodeEmitter::HexagonMCCodeEmitter(MCInstrInfo const &aMII, - MCSubtargetInfo const &aMST, MCContext &aMCT) - : MST(aMST), MCT(aMCT) {} + : MCT(aMCT), MCII(aMII), Addend(new unsigned(0)), + Extended(new bool(false)) {} -void HexagonMCCodeEmitter::EncodeInstruction(MCInst const &MI, raw_ostream &OS, +void HexagonMCCodeEmitter::encodeInstruction(MCInst const &MI, raw_ostream &OS, SmallVectorImpl<MCFixup> &Fixups, MCSubtargetInfo const &STI) const { - HexagonMCInst const &HMB = static_cast<HexagonMCInst const &>(MI); - uint64_t Binary = getBinaryCodeForInstr(HMB, Fixups, STI) | getPacketBits(HMB); - assert(HMB.getDesc().getSize() == 4 && "All instructions should be 32bit"); + 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); ++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; +} + +unsigned HexagonMCCodeEmitter::getExprOpValue(const MCInst &MI, + const MCOperand &MO, + const MCExpr *ME, + SmallVectorImpl<MCFixup> &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<MCConstantExpr>(ME)->getValue(); + } + if (MK == MCExpr::Binary) { + unsigned Res; + Res = getExprOpValue(MI, MO, cast<MCBinaryExpr>(ME)->getLHS(), Fixups, STI); + Res += + getExprOpValue(MI, MO, cast<MCBinaryExpr>(ME)->getRHS(), Fixups, STI); + return Res; + } + + assert(MK == MCExpr::SymbolRef); + + 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: + 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; + } + + MCFixup fixup = + MCFixup::create(*Addend, MO.getExpr(), MCFixupKind(FixupKind)); + 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, @@ -71,18 +508,16 @@ HexagonMCCodeEmitter::getMachineOpValue(MCInst const &MI, MCOperand const &MO, return MCT.getRegisterInfo()->getEncodingValue(MO.getReg()); if (MO.isImm()) return static_cast<unsigned>(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" |