1
0
mirror of https://github.com/RPCS3/llvm-mirror.git synced 2025-02-01 05:01:59 +01:00
llvm-mirror/lib/Target/Hexagon/MCTargetDesc/HexagonMCCodeEmitter.cpp
Krzysztof Parzyszek 805df76dbe [Hexagon] Make getMemAccessSize return size in bytes
It used to return the actual field value from the instruction descriptor.
There is no reason for that, that value is not interesting in any way and
the specifics of its encoding in the descriptor should not be exposed.

llvm-svn: 313257
2017-09-14 12:06:40 +00:00

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"