#include "Hexagon.h"
#include "MCTargetDesc/HexagonBaseInfo.h"
+#include "MCTargetDesc/HexagonFixupKinds.h"
#include "MCTargetDesc/HexagonMCCodeEmitter.h"
#include "MCTargetDesc/HexagonMCInstrInfo.h"
#include "MCTargetDesc/HexagonMCTargetDesc.h"
#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"
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 <uint32_t> (Field) << ParseFieldOffset;
-}
-void emitLittleEndian(uint64_t Binary, raw_ostream &OS) {
- OS << static_cast<uint8_t>((Binary >> 0x00) & 0xff);
- OS << static_cast<uint8_t>((Binary >> 0x08) & 0xff);
- OS << static_cast<uint8_t>((Binary >> 0x10) & 0xff);
- OS << static_cast<uint8_t>((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<MCFixup> &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");
- emitLittleEndian(Binary, OS);
+ MCInst &HMB = const_cast<MCInst &>(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<MCInst &>(*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<MCFixup> &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<unsigned>(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<support::little>(OS).write<uint32_t>(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;
+}
+
+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,
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"