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