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