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