853 lines · cpp
1//===-- HexagonMCTargetDesc.cpp - Hexagon Target Descriptions -------------===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8//9// This file provides Hexagon specific target descriptions.10//11//===----------------------------------------------------------------------===//12 13#include "MCTargetDesc/HexagonMCTargetDesc.h"14#include "HexagonDepArch.h"15#include "HexagonTargetStreamer.h"16#include "MCTargetDesc/HexagonInstPrinter.h"17#include "MCTargetDesc/HexagonMCAsmInfo.h"18#include "MCTargetDesc/HexagonMCELFStreamer.h"19#include "MCTargetDesc/HexagonMCInstrInfo.h"20#include "TargetInfo/HexagonTargetInfo.h"21#include "llvm/ADT/StringExtras.h"22#include "llvm/ADT/StringRef.h"23#include "llvm/BinaryFormat/ELF.h"24#include "llvm/MC/MCAsmBackend.h"25#include "llvm/MC/MCAssembler.h"26#include "llvm/MC/MCCodeEmitter.h"27#include "llvm/MC/MCContext.h"28#include "llvm/MC/MCDwarf.h"29#include "llvm/MC/MCELFObjectWriter.h"30#include "llvm/MC/MCELFStreamer.h"31#include "llvm/MC/MCInstrAnalysis.h"32#include "llvm/MC/MCInstrInfo.h"33#include "llvm/MC/MCRegisterInfo.h"34#include "llvm/MC/MCStreamer.h"35#include "llvm/MC/MCSubtargetInfo.h"36#include "llvm/MC/TargetRegistry.h"37#include "llvm/Support/Compiler.h"38#include "llvm/Support/ErrorHandling.h"39#include "llvm/Support/HexagonAttributes.h"40#include "llvm/Support/raw_ostream.h"41#include <cassert>42#include <cstdint>43#include <mutex>44#include <new>45#include <string>46#include <unordered_map>47 48using namespace llvm;49 50#define GET_INSTRINFO_MC_DESC51#define ENABLE_INSTR_PREDICATE_VERIFIER52#include "HexagonGenInstrInfo.inc"53 54#define GET_SUBTARGETINFO_MC_DESC55#include "HexagonGenSubtargetInfo.inc"56 57#define GET_REGINFO_MC_DESC58#include "HexagonGenRegisterInfo.inc"59 60cl::opt<bool> llvm::HexagonDisableCompound61 ("mno-compound",62 cl::desc("Disable looking for compound instructions for Hexagon"));63 64cl::opt<bool> llvm::HexagonDisableDuplex65 ("mno-pairing",66 cl::desc("Disable looking for duplex instructions for Hexagon"));67 68namespace { // These flags are to be deprecated69cl::opt<bool> MV5("mv5", cl::Hidden, cl::desc("Build for Hexagon V5"),70 cl::init(false));71cl::opt<bool> MV55("mv55", cl::Hidden, cl::desc("Build for Hexagon V55"),72 cl::init(false));73cl::opt<bool> MV60("mv60", cl::Hidden, cl::desc("Build for Hexagon V60"),74 cl::init(false));75cl::opt<bool> MV62("mv62", cl::Hidden, cl::desc("Build for Hexagon V62"),76 cl::init(false));77cl::opt<bool> MV65("mv65", cl::Hidden, cl::desc("Build for Hexagon V65"),78 cl::init(false));79cl::opt<bool> MV66("mv66", cl::Hidden, cl::desc("Build for Hexagon V66"),80 cl::init(false));81cl::opt<bool> MV67("mv67", cl::Hidden, cl::desc("Build for Hexagon V67"),82 cl::init(false));83cl::opt<bool> MV67T("mv67t", cl::Hidden, cl::desc("Build for Hexagon V67T"),84 cl::init(false));85cl::opt<bool> MV68("mv68", cl::Hidden, cl::desc("Build for Hexagon V68"),86 cl::init(false));87cl::opt<bool> MV69("mv69", cl::Hidden, cl::desc("Build for Hexagon V69"),88 cl::init(false));89cl::opt<bool> MV71("mv71", cl::Hidden, cl::desc("Build for Hexagon V71"),90 cl::init(false));91cl::opt<bool> MV71T("mv71t", cl::Hidden, cl::desc("Build for Hexagon V71T"),92 cl::init(false));93cl::opt<bool> MV73("mv73", cl::Hidden, cl::desc("Build for Hexagon V73"),94 cl::init(false));95cl::opt<bool> MV75("mv75", cl::Hidden, cl::desc("Build for Hexagon V75"),96 cl::init(false));97cl::opt<bool> MV79("mv79", cl::Hidden, cl::desc("Build for Hexagon V79"),98 cl::init(false));99cl::opt<bool> MV81("mv81", cl::Hidden, cl::desc("Build for Hexagon V81"),100 cl::init(false));101} // namespace102 103static cl::opt<Hexagon::ArchEnum> EnableHVX(104 "mhvx", cl::desc("Enable Hexagon Vector eXtensions"),105 cl::values(clEnumValN(Hexagon::ArchEnum::V60, "v60", "Build for HVX v60"),106 clEnumValN(Hexagon::ArchEnum::V62, "v62", "Build for HVX v62"),107 clEnumValN(Hexagon::ArchEnum::V65, "v65", "Build for HVX v65"),108 clEnumValN(Hexagon::ArchEnum::V66, "v66", "Build for HVX v66"),109 clEnumValN(Hexagon::ArchEnum::V67, "v67", "Build for HVX v67"),110 clEnumValN(Hexagon::ArchEnum::V68, "v68", "Build for HVX v68"),111 clEnumValN(Hexagon::ArchEnum::V69, "v69", "Build for HVX v69"),112 clEnumValN(Hexagon::ArchEnum::V71, "v71", "Build for HVX v71"),113 clEnumValN(Hexagon::ArchEnum::V73, "v73", "Build for HVX v73"),114 clEnumValN(Hexagon::ArchEnum::V75, "v75", "Build for HVX v75"),115 clEnumValN(Hexagon::ArchEnum::V79, "v79", "Build for HVX v79"),116 clEnumValN(Hexagon::ArchEnum::V81, "v81", "Build for HVX v81"),117 // Sentinel for no value specified.118 clEnumValN(Hexagon::ArchEnum::Generic, "", "")),119 // Sentinel for flag not present.120 cl::init(Hexagon::ArchEnum::NoArch), cl::ValueOptional);121 122static cl::opt<bool>123 DisableHVX("mno-hvx", cl::Hidden,124 cl::desc("Disable Hexagon Vector eXtensions"));125 126static cl::opt<bool>127 EnableHvxIeeeFp("mhvx-ieee-fp", cl::Hidden,128 cl::desc("Enable HVX IEEE floating point extensions"));129static cl::opt<bool> EnableHexagonCabac130 ("mcabac", cl::desc("tbd"), cl::init(false));131 132static constexpr StringRef DefaultArch = "hexagonv68";133 134static StringRef HexagonGetArchVariant() {135 if (MV5)136 return "hexagonv5";137 if (MV55)138 return "hexagonv55";139 if (MV60)140 return "hexagonv60";141 if (MV62)142 return "hexagonv62";143 if (MV65)144 return "hexagonv65";145 if (MV66)146 return "hexagonv66";147 if (MV67)148 return "hexagonv67";149 if (MV67T)150 return "hexagonv67t";151 if (MV68)152 return "hexagonv68";153 if (MV69)154 return "hexagonv69";155 if (MV71)156 return "hexagonv71";157 if (MV71T)158 return "hexagonv71t";159 if (MV73)160 return "hexagonv73";161 if (MV75)162 return "hexagonv75";163 if (MV79)164 return "hexagonv79";165 if (MV81)166 return "hexagonv81";167 168 return "";169}170 171StringRef Hexagon_MC::selectHexagonCPU(StringRef CPU) {172 StringRef ArchV = HexagonGetArchVariant();173 if (!ArchV.empty() && !CPU.empty()) {174 // Tiny cores have a "t" suffix that is discarded when creating a secondary175 // non-tiny subtarget. See: addArchSubtarget176 std::pair<StringRef, StringRef> ArchP = ArchV.split('t');177 std::pair<StringRef, StringRef> CPUP = CPU.split('t');178 if (ArchP.first != CPUP.first)179 report_fatal_error("conflicting architectures specified.");180 return CPU;181 }182 if (ArchV.empty()) {183 if (CPU.empty())184 CPU = DefaultArch;185 return CPU;186 }187 return ArchV;188}189 190unsigned llvm::HexagonGetLastSlot() { return HexagonItinerariesV5FU::SLOT3; }191 192unsigned llvm::HexagonConvertUnits(unsigned ItinUnits, unsigned *Lanes) {193 enum {194 CVI_NONE = 0,195 CVI_XLANE = 1 << 0,196 CVI_SHIFT = 1 << 1,197 CVI_MPY0 = 1 << 2,198 CVI_MPY1 = 1 << 3,199 CVI_ZW = 1 << 4200 };201 202 if (ItinUnits == HexagonItinerariesV62FU::CVI_ALL ||203 ItinUnits == HexagonItinerariesV62FU::CVI_ALL_NOMEM)204 return (*Lanes = 4, CVI_XLANE);205 else if (ItinUnits & HexagonItinerariesV62FU::CVI_MPY01 &&206 ItinUnits & HexagonItinerariesV62FU::CVI_XLSHF)207 return (*Lanes = 2, CVI_XLANE | CVI_MPY0);208 else if (ItinUnits & HexagonItinerariesV62FU::CVI_MPY01)209 return (*Lanes = 2, CVI_MPY0);210 else if (ItinUnits & HexagonItinerariesV62FU::CVI_XLSHF)211 return (*Lanes = 2, CVI_XLANE);212 else if (ItinUnits & HexagonItinerariesV62FU::CVI_XLANE &&213 ItinUnits & HexagonItinerariesV62FU::CVI_SHIFT &&214 ItinUnits & HexagonItinerariesV62FU::CVI_MPY0 &&215 ItinUnits & HexagonItinerariesV62FU::CVI_MPY1)216 return (*Lanes = 1, CVI_XLANE | CVI_SHIFT | CVI_MPY0 | CVI_MPY1);217 else if (ItinUnits & HexagonItinerariesV62FU::CVI_XLANE &&218 ItinUnits & HexagonItinerariesV62FU::CVI_SHIFT)219 return (*Lanes = 1, CVI_XLANE | CVI_SHIFT);220 else if (ItinUnits & HexagonItinerariesV62FU::CVI_MPY0 &&221 ItinUnits & HexagonItinerariesV62FU::CVI_MPY1)222 return (*Lanes = 1, CVI_MPY0 | CVI_MPY1);223 else if (ItinUnits == HexagonItinerariesV62FU::CVI_ZW)224 return (*Lanes = 1, CVI_ZW);225 else if (ItinUnits == HexagonItinerariesV62FU::CVI_XLANE)226 return (*Lanes = 1, CVI_XLANE);227 else if (ItinUnits == HexagonItinerariesV62FU::CVI_SHIFT)228 return (*Lanes = 1, CVI_SHIFT);229 230 return (*Lanes = 0, CVI_NONE);231}232 233 234namespace llvm {235namespace HexagonFUnits {236bool isSlot0Only(unsigned units) {237 return HexagonItinerariesV62FU::SLOT0 == units;238}239} // namespace HexagonFUnits240} // namespace llvm241 242namespace {243 244class HexagonTargetAsmStreamer : public HexagonTargetStreamer {245 formatted_raw_ostream &OS;246 247public:248 HexagonTargetAsmStreamer(MCStreamer &S, formatted_raw_ostream &OS,249 MCInstPrinter &IP)250 : HexagonTargetStreamer(S), OS(OS) {}251 252 void prettyPrintAsm(MCInstPrinter &InstPrinter, uint64_t Address,253 const MCInst &Inst, const MCSubtargetInfo &STI,254 raw_ostream &OS) override {255 assert(HexagonMCInstrInfo::isBundle(Inst));256 assert(HexagonMCInstrInfo::bundleSize(Inst) <= HEXAGON_PACKET_SIZE);257 std::string Buffer;258 {259 raw_string_ostream TempStream(Buffer);260 for (auto &I : HexagonMCInstrInfo::bundleInstructions(Inst)) {261 InstPrinter.printInst(I.getInst(), Address, "", STI, TempStream);262 TempStream << "\n";263 }264 }265 266 std::string LoopString = "";267 bool IsLoop0 = HexagonMCInstrInfo::isInnerLoop(Inst);268 bool IsLoop1 = HexagonMCInstrInfo::isOuterLoop(Inst);269 if (IsLoop0) {270 LoopString += (IsLoop1 ? " :endloop01" : " :endloop0");271 } else if (IsLoop1) {272 LoopString += " :endloop1";273 }274 275 StringRef Contents(Buffer);276 auto PacketBundle = Contents.rsplit('\n');277 auto HeadTail = PacketBundle.first.split('\n');278 StringRef Separator = "\n";279 StringRef Indent = "\t";280 OS << "\t{\n";281 while (!HeadTail.first.empty()) {282 StringRef InstTxt;283 auto Duplex = HeadTail.first.split('\v');284 if (!Duplex.second.empty()) {285 OS << Indent << Duplex.first << Separator;286 InstTxt = Duplex.second;287 } else if (!HeadTail.first.trim().starts_with("immext")) {288 InstTxt = Duplex.first;289 }290 if (!InstTxt.empty())291 OS << Indent << InstTxt << Separator;292 HeadTail = HeadTail.second.split('\n');293 }294 295 if (HexagonMCInstrInfo::isMemReorderDisabled(Inst))296 OS << "\n\t} :mem_noshuf" << LoopString;297 else298 OS << "\t}" << LoopString;299 }300 301 void finish() override { finishAttributeSection(); }302 303 void finishAttributeSection() override {}304 305 void emitAttribute(unsigned Attribute, unsigned Value) override {306 OS << "\t.attribute\t" << Attribute << ", " << Twine(Value);307 if (getStreamer().isVerboseAsm()) {308 StringRef Name = ELFAttrs::attrTypeAsString(309 Attribute, HexagonAttrs::getHexagonAttributeTags());310 if (!Name.empty())311 OS << "\t// " << Name;312 }313 OS << "\n";314 }315};316 317class HexagonTargetELFStreamer : public HexagonTargetStreamer {318public:319 MCELFStreamer &getStreamer() {320 return static_cast<MCELFStreamer &>(Streamer);321 }322 HexagonTargetELFStreamer(MCStreamer &S, MCSubtargetInfo const &STI)323 : HexagonTargetStreamer(S) {324 getStreamer().getWriter().setELFHeaderEFlags(Hexagon_MC::GetELFFlags(STI));325 }326 327 void emitCommonSymbolSorted(MCSymbol *Symbol, uint64_t Size,328 unsigned ByteAlignment,329 unsigned AccessSize) override {330 HexagonMCELFStreamer &HexagonELFStreamer =331 static_cast<HexagonMCELFStreamer &>(getStreamer());332 HexagonELFStreamer.HexagonMCEmitCommonSymbol(333 Symbol, Size, Align(ByteAlignment), AccessSize);334 }335 336 void emitLocalCommonSymbolSorted(MCSymbol *Symbol, uint64_t Size,337 unsigned ByteAlignment,338 unsigned AccessSize) override {339 HexagonMCELFStreamer &HexagonELFStreamer =340 static_cast<HexagonMCELFStreamer &>(getStreamer());341 HexagonELFStreamer.HexagonMCEmitLocalCommonSymbol(342 Symbol, Size, Align(ByteAlignment), AccessSize);343 }344 345 void finish() override { finishAttributeSection(); }346 347 void reset() override { AttributeSection = nullptr; }348 349private:350 MCSection *AttributeSection = nullptr;351 352 void finishAttributeSection() override {353 MCELFStreamer &S = getStreamer();354 if (S.Contents.empty())355 return;356 357 S.emitAttributesSection("hexagon", ".hexagon.attributes",358 ELF::SHT_HEXAGON_ATTRIBUTES, AttributeSection);359 }360 361 void emitAttribute(uint32_t Attribute, uint32_t Value) override {362 getStreamer().setAttributeItem(Attribute, Value,363 /*OverwriteExisting=*/true);364 }365};366 367} // end anonymous namespace368 369llvm::MCInstrInfo *llvm::createHexagonMCInstrInfo() {370 MCInstrInfo *X = new MCInstrInfo();371 InitHexagonMCInstrInfo(X);372 return X;373}374 375static MCRegisterInfo *createHexagonMCRegisterInfo(const Triple &TT) {376 MCRegisterInfo *X = new MCRegisterInfo();377 InitHexagonMCRegisterInfo(X, Hexagon::R31, /*DwarfFlavour=*/0,378 /*EHFlavour=*/0, /*PC=*/Hexagon::PC);379 return X;380}381 382static MCAsmInfo *createHexagonMCAsmInfo(const MCRegisterInfo &MRI,383 const Triple &TT,384 const MCTargetOptions &Options) {385 MCAsmInfo *MAI = new HexagonMCAsmInfo(TT);386 387 // VirtualFP = (R30 + #0).388 MCCFIInstruction Inst = MCCFIInstruction::cfiDefCfa(389 nullptr, MRI.getDwarfRegNum(Hexagon::R30, true), 0);390 MAI->addInitialFrameState(Inst);391 392 return MAI;393}394 395static MCInstPrinter *createHexagonMCInstPrinter(const Triple &T,396 unsigned SyntaxVariant,397 const MCAsmInfo &MAI,398 const MCInstrInfo &MII,399 const MCRegisterInfo &MRI)400{401 if (SyntaxVariant == 0)402 return new HexagonInstPrinter(MAI, MII, MRI);403 else404 return nullptr;405}406 407static MCTargetStreamer *createMCAsmTargetStreamer(MCStreamer &S,408 formatted_raw_ostream &OS,409 MCInstPrinter *IP) {410 return new HexagonTargetAsmStreamer(S, OS, *IP);411}412 413static MCStreamer *createMCStreamer(Triple const &T, MCContext &Context,414 std::unique_ptr<MCAsmBackend> &&MAB,415 std::unique_ptr<MCObjectWriter> &&OW,416 std::unique_ptr<MCCodeEmitter> &&Emitter) {417 return createHexagonELFStreamer(T, Context, std::move(MAB), std::move(OW),418 std::move(Emitter));419}420 421static MCTargetStreamer *422createHexagonObjectTargetStreamer(MCStreamer &S, const MCSubtargetInfo &STI) {423 return new HexagonTargetELFStreamer(S, STI);424}425 426static MCTargetStreamer *createHexagonNullTargetStreamer(MCStreamer &S) {427 return new HexagonTargetStreamer(S);428}429 430[[maybe_unused]] static void clearFeature(MCSubtargetInfo *STI, uint64_t F) {431 if (STI->hasFeature(F))432 STI->ToggleFeature(F);433}434 435[[maybe_unused]] static bool checkFeature(MCSubtargetInfo *STI, uint64_t F) {436 return STI->hasFeature(F);437}438 439namespace {440std::string selectHexagonFS(StringRef CPU, StringRef FS) {441 SmallVector<StringRef, 3> Result;442 if (!FS.empty())443 Result.push_back(FS);444 445 switch (EnableHVX) {446 case Hexagon::ArchEnum::V5:447 case Hexagon::ArchEnum::V55:448 break;449 case Hexagon::ArchEnum::V60:450 Result.push_back("+hvxv60");451 break;452 case Hexagon::ArchEnum::V62:453 Result.push_back("+hvxv62");454 break;455 case Hexagon::ArchEnum::V65:456 Result.push_back("+hvxv65");457 break;458 case Hexagon::ArchEnum::V66:459 Result.push_back("+hvxv66");460 break;461 case Hexagon::ArchEnum::V67:462 Result.push_back("+hvxv67");463 break;464 case Hexagon::ArchEnum::V68:465 Result.push_back("+hvxv68");466 break;467 case Hexagon::ArchEnum::V69:468 Result.push_back("+hvxv69");469 break;470 case Hexagon::ArchEnum::V71:471 Result.push_back("+hvxv71");472 break;473 case Hexagon::ArchEnum::V73:474 Result.push_back("+hvxv73");475 break;476 case Hexagon::ArchEnum::V75:477 Result.push_back("+hvxv75");478 break;479 case Hexagon::ArchEnum::V79:480 Result.push_back("+hvxv79");481 break;482 case Hexagon::ArchEnum::V81:483 Result.push_back("+hvxv81");484 break;485 486 case Hexagon::ArchEnum::Generic: {487 Result.push_back(StringSwitch<StringRef>(CPU)488 .Case("hexagonv60", "+hvxv60")489 .Case("hexagonv62", "+hvxv62")490 .Case("hexagonv65", "+hvxv65")491 .Case("hexagonv66", "+hvxv66")492 .Case("hexagonv67", "+hvxv67")493 .Case("hexagonv67t", "+hvxv67")494 .Case("hexagonv68", "+hvxv68")495 .Case("hexagonv69", "+hvxv69")496 .Case("hexagonv71", "+hvxv71")497 .Case("hexagonv71t", "+hvxv71")498 .Case("hexagonv73", "+hvxv73")499 .Case("hexagonv75", "+hvxv75")500 .Case("hexagonv79", "+hvxv79")501 .Case("hexagonv81", "+hvxv81"));502 break;503 }504 case Hexagon::ArchEnum::NoArch:505 // Sentinel if -mhvx isn't specified506 break;507 }508 if (EnableHvxIeeeFp)509 Result.push_back("+hvx-ieee-fp");510 if (EnableHexagonCabac)511 Result.push_back("+cabac");512 513 return join(Result.begin(), Result.end(), ",");514}515}516 517static bool isCPUValid(StringRef CPU) {518 return Hexagon::getCpu(CPU).has_value();519}520 521namespace {522std::pair<std::string, std::string> selectCPUAndFS(StringRef CPU,523 StringRef FS) {524 std::pair<std::string, std::string> Result;525 Result.first = std::string(Hexagon_MC::selectHexagonCPU(CPU));526 Result.second = selectHexagonFS(Result.first, FS);527 return Result;528}529std::mutex ArchSubtargetMutex;530std::unordered_map<std::string, std::unique_ptr<MCSubtargetInfo const>>531 ArchSubtarget;532} // namespace533 534MCSubtargetInfo const *535Hexagon_MC::getArchSubtarget(MCSubtargetInfo const *STI) {536 std::lock_guard<std::mutex> Lock(ArchSubtargetMutex);537 auto Existing = ArchSubtarget.find(std::string(STI->getCPU()));538 if (Existing == ArchSubtarget.end())539 return nullptr;540 return Existing->second.get();541}542 543FeatureBitset Hexagon_MC::completeHVXFeatures(const FeatureBitset &S) {544 using namespace Hexagon;545 // Make sure that +hvx-length turns hvx on, and that "hvx" alone546 // turns on hvxvNN, corresponding to the existing ArchVNN.547 FeatureBitset FB = S;548 unsigned CpuArch = ArchV5;549 for (unsigned F :550 {ArchV81, ArchV79, ArchV75, ArchV73, ArchV71, ArchV69, ArchV68, ArchV67,551 ArchV66, ArchV65, ArchV62, ArchV60, ArchV55, ArchV5}) {552 if (!FB.test(F))553 continue;554 CpuArch = F;555 break;556 }557 bool UseHvx = false;558 for (unsigned F : {ExtensionHVX, ExtensionHVX64B, ExtensionHVX128B}) {559 if (!FB.test(F))560 continue;561 UseHvx = true;562 break;563 }564 bool HasHvxVer = false;565 for (unsigned F :566 {ExtensionHVXV60, ExtensionHVXV62, ExtensionHVXV65, ExtensionHVXV66,567 ExtensionHVXV67, ExtensionHVXV68, ExtensionHVXV69, ExtensionHVXV71,568 ExtensionHVXV73, ExtensionHVXV75, ExtensionHVXV79, ExtensionHVXV81}) {569 if (!FB.test(F))570 continue;571 HasHvxVer = true;572 UseHvx = true;573 break;574 }575 576 if (!UseHvx || HasHvxVer)577 return FB;578 579 // HasHvxVer is false, and UseHvx is true.580 switch (CpuArch) {581 case ArchV81:582 FB.set(ExtensionHVXV81);583 [[fallthrough]];584 case ArchV79:585 FB.set(ExtensionHVXV79);586 [[fallthrough]];587 case ArchV75:588 FB.set(ExtensionHVXV75);589 [[fallthrough]];590 case ArchV73:591 FB.set(ExtensionHVXV73);592 [[fallthrough]];593 case ArchV71:594 FB.set(ExtensionHVXV71);595 [[fallthrough]];596 case ArchV69:597 FB.set(ExtensionHVXV69);598 [[fallthrough]];599 case ArchV68:600 FB.set(ExtensionHVXV68);601 [[fallthrough]];602 case ArchV67:603 FB.set(ExtensionHVXV67);604 [[fallthrough]];605 case ArchV66:606 FB.set(ExtensionHVXV66);607 [[fallthrough]];608 case ArchV65:609 FB.set(ExtensionHVXV65);610 [[fallthrough]];611 case ArchV62:612 FB.set(ExtensionHVXV62);613 [[fallthrough]];614 case ArchV60:615 FB.set(ExtensionHVXV60);616 break;617 }618 return FB;619}620 621MCSubtargetInfo *Hexagon_MC::createHexagonMCSubtargetInfo(const Triple &TT,622 StringRef CPU,623 StringRef FS) {624 std::pair<std::string, std::string> Features = selectCPUAndFS(CPU, FS);625 StringRef CPUName = Features.first;626 StringRef ArchFS = Features.second;627 628 MCSubtargetInfo *X = createHexagonMCSubtargetInfoImpl(629 TT, CPUName, /*TuneCPU*/ CPUName, ArchFS);630 if (X != nullptr && (CPUName == "hexagonv67t" || CPUName == "hexagon71t"))631 addArchSubtarget(X, ArchFS);632 633 if (CPU == "help")634 exit(0);635 636 if (!isCPUValid(CPUName.str())) {637 errs() << "error: invalid CPU \"" << CPUName.str().c_str()638 << "\" specified\n";639 return nullptr;640 }641 642 // Add qfloat subtarget feature by default to v68 and above643 // unless explicitly disabled644 if (checkFeature(X, Hexagon::ExtensionHVXV68) &&645 !ArchFS.contains("-hvx-qfloat")) {646 llvm::FeatureBitset Features = X->getFeatureBits();647 X->setFeatureBits(Features.set(Hexagon::ExtensionHVXQFloat));648 }649 650 if (HexagonDisableDuplex) {651 llvm::FeatureBitset Features = X->getFeatureBits();652 X->setFeatureBits(Features.reset(Hexagon::FeatureDuplex));653 }654 655 X->setFeatureBits(completeHVXFeatures(X->getFeatureBits()));656 657 // The Z-buffer instructions are grandfathered in for current658 // architectures but omitted for new ones. Future instruction659 // sets may introduce new/conflicting z-buffer instructions.660 const bool ZRegOnDefault =661 (CPUName == "hexagonv67") || (CPUName == "hexagonv66");662 if (ZRegOnDefault) {663 llvm::FeatureBitset Features = X->getFeatureBits();664 X->setFeatureBits(Features.set(Hexagon::ExtensionZReg));665 }666 667 return X;668}669 670void Hexagon_MC::addArchSubtarget(MCSubtargetInfo const *STI, StringRef FS) {671 assert(STI != nullptr);672 if (STI->getCPU().contains("t")) {673 auto ArchSTI = createHexagonMCSubtargetInfo(STI->getTargetTriple(),674 STI->getCPU().drop_back(), FS);675 std::lock_guard<std::mutex> Lock(ArchSubtargetMutex);676 ArchSubtarget[std::string(STI->getCPU())] =677 std::unique_ptr<MCSubtargetInfo const>(ArchSTI);678 }679}680 681std::optional<unsigned>682Hexagon_MC::getHVXVersion(const FeatureBitset &Features) {683 for (auto Arch : {Hexagon::ExtensionHVXV81, Hexagon::ExtensionHVXV79,684 Hexagon::ExtensionHVXV75, Hexagon::ExtensionHVXV73,685 Hexagon::ExtensionHVXV71, Hexagon::ExtensionHVXV69,686 Hexagon::ExtensionHVXV68, Hexagon::ExtensionHVXV67,687 Hexagon::ExtensionHVXV66, Hexagon::ExtensionHVXV65,688 Hexagon::ExtensionHVXV62, Hexagon::ExtensionHVXV60})689 if (Features.test(Arch))690 return Arch;691 return {};692}693 694unsigned Hexagon_MC::getArchVersion(const FeatureBitset &Features) {695 for (auto Arch :696 {Hexagon::ArchV81, Hexagon::ArchV79, Hexagon::ArchV75, Hexagon::ArchV73,697 Hexagon::ArchV71, Hexagon::ArchV69, Hexagon::ArchV68, Hexagon::ArchV67,698 Hexagon::ArchV66, Hexagon::ArchV65, Hexagon::ArchV62, Hexagon::ArchV60,699 Hexagon::ArchV55, Hexagon::ArchV5})700 if (Features.test(Arch))701 return Arch;702 llvm_unreachable("Expected arch v5-v81");703 return 0;704}705 706unsigned Hexagon_MC::GetELFFlags(const MCSubtargetInfo &STI) {707 return StringSwitch<unsigned>(STI.getCPU())708 .Case("generic", llvm::ELF::EF_HEXAGON_MACH_V5)709 .Case("hexagonv5", llvm::ELF::EF_HEXAGON_MACH_V5)710 .Case("hexagonv55", llvm::ELF::EF_HEXAGON_MACH_V55)711 .Case("hexagonv60", llvm::ELF::EF_HEXAGON_MACH_V60)712 .Case("hexagonv62", llvm::ELF::EF_HEXAGON_MACH_V62)713 .Case("hexagonv65", llvm::ELF::EF_HEXAGON_MACH_V65)714 .Case("hexagonv66", llvm::ELF::EF_HEXAGON_MACH_V66)715 .Case("hexagonv67", llvm::ELF::EF_HEXAGON_MACH_V67)716 .Case("hexagonv67t", llvm::ELF::EF_HEXAGON_MACH_V67T)717 .Case("hexagonv68", llvm::ELF::EF_HEXAGON_MACH_V68)718 .Case("hexagonv69", llvm::ELF::EF_HEXAGON_MACH_V69)719 .Case("hexagonv71", llvm::ELF::EF_HEXAGON_MACH_V71)720 .Case("hexagonv71t", llvm::ELF::EF_HEXAGON_MACH_V71T)721 .Case("hexagonv73", llvm::ELF::EF_HEXAGON_MACH_V73)722 .Case("hexagonv75", llvm::ELF::EF_HEXAGON_MACH_V75)723 .Case("hexagonv79", llvm::ELF::EF_HEXAGON_MACH_V79)724 .Case("hexagonv81", llvm::ELF::EF_HEXAGON_MACH_V81);725}726 727llvm::ArrayRef<MCPhysReg> Hexagon_MC::GetVectRegRev() {728 return ArrayRef(VectRegRev);729}730 731namespace {732class HexagonMCInstrAnalysis : public MCInstrAnalysis {733public:734 HexagonMCInstrAnalysis(MCInstrInfo const *Info) : MCInstrAnalysis(Info) {}735 736 bool isUnconditionalBranch(MCInst const &Inst) const override {737 //assert(!HexagonMCInstrInfo::isBundle(Inst));738 return MCInstrAnalysis::isUnconditionalBranch(Inst);739 }740 741 bool isConditionalBranch(MCInst const &Inst) const override {742 //assert(!HexagonMCInstrInfo::isBundle(Inst));743 return MCInstrAnalysis::isConditionalBranch(Inst);744 }745 746 bool evaluateBranch(MCInst const &Inst, uint64_t Addr,747 uint64_t Size, uint64_t &Target) const override {748 if (!(isCall(Inst) || isUnconditionalBranch(Inst) ||749 isConditionalBranch(Inst)))750 return false;751 752 //assert(!HexagonMCInstrInfo::isBundle(Inst));753 if (!HexagonMCInstrInfo::isExtendable(*Info, Inst))754 return false;755 auto const &Extended(HexagonMCInstrInfo::getExtendableOperand(*Info, Inst));756 assert(Extended.isExpr());757 int64_t Value;758 if (!Extended.getExpr()->evaluateAsAbsolute(Value))759 return false;760 Target = Value;761 return true;762 }763 764 uint32_t getValueFromMask(uint32_t Instruction, uint32_t Mask) const {765 uint32_t Result = 0;766 uint32_t Offset = 0;767 while (Mask) {768 if (Instruction & (Mask & -Mask))769 Result |= (1 << Offset);770 Mask &= (Mask - 1);771 ++Offset;772 }773 return Result;774 }775 776 std::vector<std::pair<uint64_t, uint64_t>>777 findPltEntries(uint64_t PltSectionVA, ArrayRef<uint8_t> PltContents,778 const MCSubtargetInfo &STI) const override {779 // Do a lightweight parsing of PLT entries.780 std::vector<std::pair<uint64_t, uint64_t>> Result;781 for (uint64_t Byte = 0x0, End = PltContents.size(); Byte < End; Byte += 4) {782 // Recognize immext(##gotpltn)783 uint32_t ImmExt = support::endian::read32le(PltContents.data() + Byte);784 if ((ImmExt & 0x00004000) != 0x00004000)785 continue;786 uint32_t LoadGotPlt =787 support::endian::read32le(PltContents.data() + Byte + 4);788 if ((LoadGotPlt & 0x6a49c00c) != 0x6a49c00c)789 continue;790 uint32_t Address = (getValueFromMask(ImmExt, 0xfff3fff) << 6) +791 getValueFromMask(LoadGotPlt, 0x1f80) + PltSectionVA +792 Byte;793 Result.emplace_back(PltSectionVA + Byte, Address);794 }795 return Result;796 }797};798} // namespace799 800static MCInstrAnalysis *createHexagonMCInstrAnalysis(const MCInstrInfo *Info) {801 return new HexagonMCInstrAnalysis(Info);802}803 804// Force static initialization.805extern "C" LLVM_ABI LLVM_EXTERNAL_VISIBILITY void806LLVMInitializeHexagonTargetMC() {807 // Register the MC asm info.808 RegisterMCAsmInfoFn X(getTheHexagonTarget(), createHexagonMCAsmInfo);809 810 // Register the MC instruction info.811 TargetRegistry::RegisterMCInstrInfo(getTheHexagonTarget(),812 createHexagonMCInstrInfo);813 814 // Register the MC register info.815 TargetRegistry::RegisterMCRegInfo(getTheHexagonTarget(),816 createHexagonMCRegisterInfo);817 818 // Register the MC subtarget info.819 TargetRegistry::RegisterMCSubtargetInfo(820 getTheHexagonTarget(), Hexagon_MC::createHexagonMCSubtargetInfo);821 822 // Register the MC Code Emitter823 TargetRegistry::RegisterMCCodeEmitter(getTheHexagonTarget(),824 createHexagonMCCodeEmitter);825 826 // Register the asm backend827 TargetRegistry::RegisterMCAsmBackend(getTheHexagonTarget(),828 createHexagonAsmBackend);829 830 // Register the MC instruction analyzer.831 TargetRegistry::RegisterMCInstrAnalysis(getTheHexagonTarget(),832 createHexagonMCInstrAnalysis);833 834 // Register the obj streamer835 TargetRegistry::RegisterELFStreamer(getTheHexagonTarget(), createMCStreamer);836 837 // Register the obj target streamer838 TargetRegistry::RegisterObjectTargetStreamer(839 getTheHexagonTarget(), createHexagonObjectTargetStreamer);840 841 // Register the asm streamer842 TargetRegistry::RegisterAsmTargetStreamer(getTheHexagonTarget(),843 createMCAsmTargetStreamer);844 845 // Register the null streamer846 TargetRegistry::RegisterNullTargetStreamer(getTheHexagonTarget(),847 createHexagonNullTargetStreamer);848 849 // Register the MC Inst Printer850 TargetRegistry::RegisterMCInstPrinter(getTheHexagonTarget(),851 createHexagonMCInstPrinter);852}853