1 //===-- HexagonMCTargetDesc.cpp - Hexagon Target Descriptions -------------===//
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
7 //===----------------------------------------------------------------------===//
9 // This file provides Hexagon specific target descriptions.
11 //===----------------------------------------------------------------------===//
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/MCCodeEmitter.h"
26 #include "llvm/MC/MCContext.h"
27 #include "llvm/MC/MCDwarf.h"
28 #include "llvm/MC/MCELFStreamer.h"
29 #include "llvm/MC/MCInstrAnalysis.h"
30 #include "llvm/MC/MCInstrInfo.h"
31 #include "llvm/MC/MCObjectWriter.h"
32 #include "llvm/MC/MCRegisterInfo.h"
33 #include "llvm/MC/MCStreamer.h"
34 #include "llvm/MC/MCSubtargetInfo.h"
35 #include "llvm/Support/ErrorHandling.h"
36 #include "llvm/Support/TargetRegistry.h"
37 #include "llvm/Support/raw_ostream.h"
45 #define GET_INSTRINFO_MC_DESC
46 #include "HexagonGenInstrInfo.inc"
48 #define GET_SUBTARGETINFO_MC_DESC
49 #include "HexagonGenSubtargetInfo.inc"
51 #define GET_REGINFO_MC_DESC
52 #include "HexagonGenRegisterInfo.inc"
54 cl::opt
<bool> llvm::HexagonDisableCompound
56 cl::desc("Disable looking for compound instructions for Hexagon"));
58 cl::opt
<bool> llvm::HexagonDisableDuplex
60 cl::desc("Disable looking for duplex instructions for Hexagon"));
62 namespace { // These flags are to be deprecated
63 cl::opt
<bool> MV5("mv5", cl::Hidden
, cl::desc("Build for Hexagon V5"),
65 cl::opt
<bool> MV55("mv55", cl::Hidden
, cl::desc("Build for Hexagon V55"),
67 cl::opt
<bool> MV60("mv60", cl::Hidden
, cl::desc("Build for Hexagon V60"),
69 cl::opt
<bool> MV62("mv62", cl::Hidden
, cl::desc("Build for Hexagon V62"),
71 cl::opt
<bool> MV65("mv65", cl::Hidden
, cl::desc("Build for Hexagon V65"),
73 cl::opt
<bool> MV66("mv66", cl::Hidden
, cl::desc("Build for Hexagon V66"),
76 cl::opt
<Hexagon::ArchEnum
>
78 cl::desc("Enable Hexagon Vector eXtensions"),
80 clEnumValN(Hexagon::ArchEnum::V60
, "v60", "Build for HVX v60"),
81 clEnumValN(Hexagon::ArchEnum::V62
, "v62", "Build for HVX v62"),
82 clEnumValN(Hexagon::ArchEnum::V65
, "v65", "Build for HVX v65"),
83 clEnumValN(Hexagon::ArchEnum::V66
, "v66", "Build for HVX v66"),
84 // Sentinel for no value specified.
85 clEnumValN(Hexagon::ArchEnum::Generic
, "", "")),
86 // Sentinel for flag not present.
87 cl::init(Hexagon::ArchEnum::NoArch
), cl::ValueOptional
);
91 DisableHVX("mno-hvx", cl::Hidden
,
92 cl::desc("Disable Hexagon Vector eXtensions"));
95 static StringRef DefaultArch
= "hexagonv60";
97 static StringRef
HexagonGetArchVariant() {
113 StringRef
Hexagon_MC::selectHexagonCPU(StringRef CPU
) {
114 StringRef ArchV
= HexagonGetArchVariant();
115 if (!ArchV
.empty() && !CPU
.empty()) {
117 report_fatal_error("conflicting architectures specified.");
128 unsigned llvm::HexagonGetLastSlot() { return HexagonItinerariesV5FU::SLOT3
; }
132 class HexagonTargetAsmStreamer
: public HexagonTargetStreamer
{
134 HexagonTargetAsmStreamer(MCStreamer
&S
,
135 formatted_raw_ostream
&OS
,
138 : HexagonTargetStreamer(S
) {}
140 void prettyPrintAsm(MCInstPrinter
&InstPrinter
, raw_ostream
&OS
,
141 const MCInst
&Inst
, const MCSubtargetInfo
&STI
) override
{
142 assert(HexagonMCInstrInfo::isBundle(Inst
));
143 assert(HexagonMCInstrInfo::bundleSize(Inst
) <= HEXAGON_PACKET_SIZE
);
146 raw_string_ostream
TempStream(Buffer
);
147 InstPrinter
.printInst(&Inst
, TempStream
, "", STI
);
149 StringRef
Contents(Buffer
);
150 auto PacketBundle
= Contents
.rsplit('\n');
151 auto HeadTail
= PacketBundle
.first
.split('\n');
152 StringRef Separator
= "\n";
153 StringRef Indent
= "\t";
155 while (!HeadTail
.first
.empty()) {
157 auto Duplex
= HeadTail
.first
.split('\v');
158 if (!Duplex
.second
.empty()) {
159 OS
<< Indent
<< Duplex
.first
<< Separator
;
160 InstTxt
= Duplex
.second
;
161 } else if (!HeadTail
.first
.trim().startswith("immext")) {
162 InstTxt
= Duplex
.first
;
164 if (!InstTxt
.empty())
165 OS
<< Indent
<< InstTxt
<< Separator
;
166 HeadTail
= HeadTail
.second
.split('\n');
169 if (HexagonMCInstrInfo::isMemReorderDisabled(Inst
))
170 OS
<< "\n\t} :mem_noshuf" << PacketBundle
.second
;
172 OS
<< "\t}" << PacketBundle
.second
;
176 class HexagonTargetELFStreamer
: public HexagonTargetStreamer
{
178 MCELFStreamer
&getStreamer() {
179 return static_cast<MCELFStreamer
&>(Streamer
);
181 HexagonTargetELFStreamer(MCStreamer
&S
, MCSubtargetInfo
const &STI
)
182 : HexagonTargetStreamer(S
) {
183 MCAssembler
&MCA
= getStreamer().getAssembler();
184 MCA
.setELFHeaderEFlags(Hexagon_MC::GetELFFlags(STI
));
188 void EmitCommonSymbolSorted(MCSymbol
*Symbol
, uint64_t Size
,
189 unsigned ByteAlignment
,
190 unsigned AccessSize
) override
{
191 HexagonMCELFStreamer
&HexagonELFStreamer
=
192 static_cast<HexagonMCELFStreamer
&>(getStreamer());
193 HexagonELFStreamer
.HexagonMCEmitCommonSymbol(Symbol
, Size
, ByteAlignment
,
197 void EmitLocalCommonSymbolSorted(MCSymbol
*Symbol
, uint64_t Size
,
198 unsigned ByteAlignment
,
199 unsigned AccessSize
) override
{
200 HexagonMCELFStreamer
&HexagonELFStreamer
=
201 static_cast<HexagonMCELFStreamer
&>(getStreamer());
202 HexagonELFStreamer
.HexagonMCEmitLocalCommonSymbol(
203 Symbol
, Size
, ByteAlignment
, AccessSize
);
207 } // end anonymous namespace
209 llvm::MCInstrInfo
*llvm::createHexagonMCInstrInfo() {
210 MCInstrInfo
*X
= new MCInstrInfo();
211 InitHexagonMCInstrInfo(X
);
215 static MCRegisterInfo
*createHexagonMCRegisterInfo(const Triple
&TT
) {
216 MCRegisterInfo
*X
= new MCRegisterInfo();
217 InitHexagonMCRegisterInfo(X
, Hexagon::R31
);
221 static MCAsmInfo
*createHexagonMCAsmInfo(const MCRegisterInfo
&MRI
,
223 MCAsmInfo
*MAI
= new HexagonMCAsmInfo(TT
);
225 // VirtualFP = (R30 + #0).
226 MCCFIInstruction Inst
=
227 MCCFIInstruction::createDefCfa(nullptr,
228 MRI
.getDwarfRegNum(Hexagon::R30
, true), 0);
229 MAI
->addInitialFrameState(Inst
);
234 static MCInstPrinter
*createHexagonMCInstPrinter(const Triple
&T
,
235 unsigned SyntaxVariant
,
236 const MCAsmInfo
&MAI
,
237 const MCInstrInfo
&MII
,
238 const MCRegisterInfo
&MRI
)
240 if (SyntaxVariant
== 0)
241 return new HexagonInstPrinter(MAI
, MII
, MRI
);
246 static MCTargetStreamer
*
247 createMCAsmTargetStreamer(MCStreamer
&S
, formatted_raw_ostream
&OS
,
248 MCInstPrinter
*IP
, bool IsVerboseAsm
) {
249 return new HexagonTargetAsmStreamer(S
, OS
, IsVerboseAsm
, *IP
);
252 static MCStreamer
*createMCStreamer(Triple
const &T
, MCContext
&Context
,
253 std::unique_ptr
<MCAsmBackend
> &&MAB
,
254 std::unique_ptr
<MCObjectWriter
> &&OW
,
255 std::unique_ptr
<MCCodeEmitter
> &&Emitter
,
257 return createHexagonELFStreamer(T
, Context
, std::move(MAB
), std::move(OW
),
261 static MCTargetStreamer
*
262 createHexagonObjectTargetStreamer(MCStreamer
&S
, const MCSubtargetInfo
&STI
) {
263 return new HexagonTargetELFStreamer(S
, STI
);
266 static void LLVM_ATTRIBUTE_UNUSED
clearFeature(MCSubtargetInfo
* STI
, uint64_t F
) {
267 if (STI
->getFeatureBits()[F
])
268 STI
->ToggleFeature(F
);
271 static bool LLVM_ATTRIBUTE_UNUSED
checkFeature(MCSubtargetInfo
* STI
, uint64_t F
) {
272 return STI
->getFeatureBits()[F
];
276 std::string
selectHexagonFS(StringRef CPU
, StringRef FS
) {
277 SmallVector
<StringRef
, 3> Result
;
279 Result
.push_back(FS
);
282 case Hexagon::ArchEnum::V5
:
283 case Hexagon::ArchEnum::V55
:
285 case Hexagon::ArchEnum::V60
:
286 Result
.push_back("+hvxv60");
288 case Hexagon::ArchEnum::V62
:
289 Result
.push_back("+hvxv62");
291 case Hexagon::ArchEnum::V65
:
292 Result
.push_back("+hvxv65");
294 case Hexagon::ArchEnum::V66
:
295 Result
.push_back("+hvxv66");
297 case Hexagon::ArchEnum::Generic
:{
298 Result
.push_back(StringSwitch
<StringRef
>(CPU
)
299 .Case("hexagonv60", "+hvxv60")
300 .Case("hexagonv62", "+hvxv62")
301 .Case("hexagonv65", "+hvxv65")
302 .Case("hexagonv66", "+hvxv66"));
305 case Hexagon::ArchEnum::NoArch
:
306 // Sentinal if -mhvx isn't specified
309 return join(Result
.begin(), Result
.end(), ",");
313 static bool isCPUValid(std::string CPU
)
315 std::vector
<std::string
> table
{
316 "generic", "hexagonv5", "hexagonv55", "hexagonv60",
317 "hexagonv62", "hexagonv65", "hexagonv66",
320 return std::find(table
.begin(), table
.end(), CPU
) != table
.end();
324 std::pair
<std::string
, std::string
> selectCPUAndFS(StringRef CPU
,
326 std::pair
<std::string
, std::string
> Result
;
327 Result
.first
= Hexagon_MC::selectHexagonCPU(CPU
);
328 Result
.second
= selectHexagonFS(Result
.first
, FS
);
333 FeatureBitset
Hexagon_MC::completeHVXFeatures(const FeatureBitset
&S
) {
334 using namespace Hexagon
;
335 // Make sure that +hvx-length turns hvx on, and that "hvx" alone
336 // turns on hvxvNN, corresponding to the existing ArchVNN.
337 FeatureBitset FB
= S
;
338 unsigned CpuArch
= ArchV5
;
339 for (unsigned F
: {ArchV66
, ArchV65
, ArchV62
, ArchV60
, ArchV55
, ArchV5
}) {
346 for (unsigned F
: {ExtensionHVX
, ExtensionHVX64B
, ExtensionHVX128B
}) {
352 bool HasHvxVer
= false;
353 for (unsigned F
: {ExtensionHVXV60
, ExtensionHVXV62
, ExtensionHVXV65
,
362 if (!UseHvx
|| HasHvxVer
)
365 // HasHvxVer is false, and UseHvx is true.
368 FB
.set(ExtensionHVXV66
);
371 FB
.set(ExtensionHVXV65
);
374 FB
.set(ExtensionHVXV62
);
377 FB
.set(ExtensionHVXV60
);
383 MCSubtargetInfo
*Hexagon_MC::createHexagonMCSubtargetInfo(const Triple
&TT
,
386 std::pair
<std::string
, std::string
> Features
= selectCPUAndFS(CPU
, FS
);
387 StringRef CPUName
= Features
.first
;
388 StringRef ArchFS
= Features
.second
;
390 if (!isCPUValid(CPUName
.str())) {
391 errs() << "error: invalid CPU \"" << CPUName
.str().c_str()
396 MCSubtargetInfo
*X
= createHexagonMCSubtargetInfoImpl(TT
, CPUName
, ArchFS
);
397 if (HexagonDisableDuplex
) {
398 llvm::FeatureBitset Features
= X
->getFeatureBits();
399 X
->setFeatureBits(Features
.reset(Hexagon::FeatureDuplex
));
402 X
->setFeatureBits(completeHVXFeatures(X
->getFeatureBits()));
406 unsigned Hexagon_MC::GetELFFlags(const MCSubtargetInfo
&STI
) {
407 static std::map
<StringRef
,unsigned> ElfFlags
= {
408 {"hexagonv5", ELF::EF_HEXAGON_MACH_V5
},
409 {"hexagonv55", ELF::EF_HEXAGON_MACH_V55
},
410 {"hexagonv60", ELF::EF_HEXAGON_MACH_V60
},
411 {"hexagonv62", ELF::EF_HEXAGON_MACH_V62
},
412 {"hexagonv65", ELF::EF_HEXAGON_MACH_V65
},
413 {"hexagonv66", ELF::EF_HEXAGON_MACH_V66
},
416 auto F
= ElfFlags
.find(STI
.getCPU());
417 assert(F
!= ElfFlags
.end() && "Unrecognized Architecture");
422 class HexagonMCInstrAnalysis
: public MCInstrAnalysis
{
424 HexagonMCInstrAnalysis(MCInstrInfo
const *Info
) : MCInstrAnalysis(Info
) {}
426 bool isUnconditionalBranch(MCInst
const &Inst
) const override
{
427 //assert(!HexagonMCInstrInfo::isBundle(Inst));
428 return MCInstrAnalysis::isUnconditionalBranch(Inst
);
431 bool isConditionalBranch(MCInst
const &Inst
) const override
{
432 //assert(!HexagonMCInstrInfo::isBundle(Inst));
433 return MCInstrAnalysis::isConditionalBranch(Inst
);
436 bool evaluateBranch(MCInst
const &Inst
, uint64_t Addr
,
437 uint64_t Size
, uint64_t &Target
) const override
{
438 //assert(!HexagonMCInstrInfo::isBundle(Inst));
439 if(!HexagonMCInstrInfo::isExtendable(*Info
, Inst
))
441 auto const &Extended(HexagonMCInstrInfo::getExtendableOperand(*Info
, Inst
));
442 assert(Extended
.isExpr());
444 if(!Extended
.getExpr()->evaluateAsAbsolute(Value
))
452 static MCInstrAnalysis
*createHexagonMCInstrAnalysis(const MCInstrInfo
*Info
) {
453 return new HexagonMCInstrAnalysis(Info
);
456 // Force static initialization.
457 extern "C" void LLVMInitializeHexagonTargetMC() {
458 // Register the MC asm info.
459 RegisterMCAsmInfoFn
X(getTheHexagonTarget(), createHexagonMCAsmInfo
);
461 // Register the MC instruction info.
462 TargetRegistry::RegisterMCInstrInfo(getTheHexagonTarget(),
463 createHexagonMCInstrInfo
);
465 // Register the MC register info.
466 TargetRegistry::RegisterMCRegInfo(getTheHexagonTarget(),
467 createHexagonMCRegisterInfo
);
469 // Register the MC subtarget info.
470 TargetRegistry::RegisterMCSubtargetInfo(getTheHexagonTarget(),
471 Hexagon_MC::createHexagonMCSubtargetInfo
);
473 // Register the MC Code Emitter
474 TargetRegistry::RegisterMCCodeEmitter(getTheHexagonTarget(),
475 createHexagonMCCodeEmitter
);
477 // Register the asm backend
478 TargetRegistry::RegisterMCAsmBackend(getTheHexagonTarget(),
479 createHexagonAsmBackend
);
482 // Register the MC instruction analyzer.
483 TargetRegistry::RegisterMCInstrAnalysis(getTheHexagonTarget(),
484 createHexagonMCInstrAnalysis
);
486 // Register the obj streamer
487 TargetRegistry::RegisterELFStreamer(getTheHexagonTarget(),
490 // Register the obj target streamer
491 TargetRegistry::RegisterObjectTargetStreamer(getTheHexagonTarget(),
492 createHexagonObjectTargetStreamer
);
494 // Register the asm streamer
495 TargetRegistry::RegisterAsmTargetStreamer(getTheHexagonTarget(),
496 createMCAsmTargetStreamer
);
498 // Register the MC Inst Printer
499 TargetRegistry::RegisterMCInstPrinter(getTheHexagonTarget(),
500 createHexagonMCInstPrinter
);