1 //===-- ARMMCTargetDesc.cpp - ARM 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 ARM specific target descriptions.
11 //===----------------------------------------------------------------------===//
13 #include "ARMMCTargetDesc.h"
14 #include "ARMBaseInfo.h"
15 #include "ARMMCAsmInfo.h"
16 #include "InstPrinter/ARMInstPrinter.h"
17 #include "llvm/ADT/Triple.h"
18 #include "llvm/MC/MCAsmBackend.h"
19 #include "llvm/MC/MCCodeEmitter.h"
20 #include "llvm/MC/MCELFStreamer.h"
21 #include "llvm/MC/MCInstrAnalysis.h"
22 #include "llvm/MC/MCInstrInfo.h"
23 #include "llvm/MC/MCObjectWriter.h"
24 #include "llvm/MC/MCRegisterInfo.h"
25 #include "llvm/MC/MCStreamer.h"
26 #include "llvm/MC/MCSubtargetInfo.h"
27 #include "llvm/Support/ErrorHandling.h"
28 #include "llvm/Support/TargetParser.h"
29 #include "llvm/Support/TargetRegistry.h"
33 #define GET_REGINFO_MC_DESC
34 #include "ARMGenRegisterInfo.inc"
36 static bool getMCRDeprecationInfo(MCInst
&MI
, const MCSubtargetInfo
&STI
,
38 if (STI
.getFeatureBits()[llvm::ARM::HasV7Ops
] &&
39 (MI
.getOperand(0).isImm() && MI
.getOperand(0).getImm() == 15) &&
40 (MI
.getOperand(1).isImm() && MI
.getOperand(1).getImm() == 0) &&
41 // Checks for the deprecated CP15ISB encoding:
42 // mcr p15, #0, rX, c7, c5, #4
43 (MI
.getOperand(3).isImm() && MI
.getOperand(3).getImm() == 7)) {
44 if ((MI
.getOperand(5).isImm() && MI
.getOperand(5).getImm() == 4)) {
45 if (MI
.getOperand(4).isImm() && MI
.getOperand(4).getImm() == 5) {
46 Info
= "deprecated since v7, use 'isb'";
50 // Checks for the deprecated CP15DSB encoding:
51 // mcr p15, #0, rX, c7, c10, #4
52 if (MI
.getOperand(4).isImm() && MI
.getOperand(4).getImm() == 10) {
53 Info
= "deprecated since v7, use 'dsb'";
57 // Checks for the deprecated CP15DMB encoding:
58 // mcr p15, #0, rX, c7, c10, #5
59 if (MI
.getOperand(4).isImm() && MI
.getOperand(4).getImm() == 10 &&
60 (MI
.getOperand(5).isImm() && MI
.getOperand(5).getImm() == 5)) {
61 Info
= "deprecated since v7, use 'dmb'";
68 static bool getITDeprecationInfo(MCInst
&MI
, const MCSubtargetInfo
&STI
,
70 if (STI
.getFeatureBits()[llvm::ARM::HasV8Ops
] && MI
.getOperand(1).isImm() &&
71 MI
.getOperand(1).getImm() != 8) {
72 Info
= "applying IT instruction to more than one subsequent instruction is "
80 static bool getARMStoreDeprecationInfo(MCInst
&MI
, const MCSubtargetInfo
&STI
,
82 assert(!STI
.getFeatureBits()[llvm::ARM::ModeThumb
] &&
83 "cannot predicate thumb instructions");
85 assert(MI
.getNumOperands() >= 4 && "expected >= 4 arguments");
86 for (unsigned OI
= 4, OE
= MI
.getNumOperands(); OI
< OE
; ++OI
) {
87 assert(MI
.getOperand(OI
).isReg() && "expected register");
88 if (MI
.getOperand(OI
).getReg() == ARM::SP
||
89 MI
.getOperand(OI
).getReg() == ARM::PC
) {
90 Info
= "use of SP or PC in the list is deprecated";
97 static bool getARMLoadDeprecationInfo(MCInst
&MI
, const MCSubtargetInfo
&STI
,
99 assert(!STI
.getFeatureBits()[llvm::ARM::ModeThumb
] &&
100 "cannot predicate thumb instructions");
102 assert(MI
.getNumOperands() >= 4 && "expected >= 4 arguments");
103 bool ListContainsPC
= false, ListContainsLR
= false;
104 for (unsigned OI
= 4, OE
= MI
.getNumOperands(); OI
< OE
; ++OI
) {
105 assert(MI
.getOperand(OI
).isReg() && "expected register");
106 switch (MI
.getOperand(OI
).getReg()) {
110 ListContainsLR
= true;
113 ListContainsPC
= true;
116 Info
= "use of SP in the list is deprecated";
121 if (ListContainsPC
&& ListContainsLR
) {
122 Info
= "use of LR and PC simultaneously in the list is deprecated";
129 #define GET_INSTRINFO_MC_DESC
130 #include "ARMGenInstrInfo.inc"
132 #define GET_SUBTARGETINFO_MC_DESC
133 #include "ARMGenSubtargetInfo.inc"
135 std::string
ARM_MC::ParseARMTriple(const Triple
&TT
, StringRef CPU
) {
136 std::string ARMArchFeature
;
138 ARM::ArchKind ArchID
= ARM::parseArch(TT
.getArchName());
139 if (ArchID
!= ARM::ArchKind::INVALID
&& (CPU
.empty() || CPU
== "generic"))
140 ARMArchFeature
= (ARMArchFeature
+ "+" + ARM::getArchName(ArchID
)).str();
143 if (!ARMArchFeature
.empty())
144 ARMArchFeature
+= ",";
145 ARMArchFeature
+= "+thumb-mode,+v4t";
149 if (!ARMArchFeature
.empty())
150 ARMArchFeature
+= ",";
151 ARMArchFeature
+= "+nacl-trap";
154 if (TT
.isOSWindows()) {
155 if (!ARMArchFeature
.empty())
156 ARMArchFeature
+= ",";
157 ARMArchFeature
+= "+noarm";
160 return ARMArchFeature
;
163 MCSubtargetInfo
*ARM_MC::createARMMCSubtargetInfo(const Triple
&TT
,
164 StringRef CPU
, StringRef FS
) {
165 std::string ArchFS
= ARM_MC::ParseARMTriple(TT
, CPU
);
168 ArchFS
= (Twine(ArchFS
) + "," + FS
).str();
173 return createARMMCSubtargetInfoImpl(TT
, CPU
, ArchFS
);
176 static MCInstrInfo
*createARMMCInstrInfo() {
177 MCInstrInfo
*X
= new MCInstrInfo();
178 InitARMMCInstrInfo(X
);
182 static MCRegisterInfo
*createARMMCRegisterInfo(const Triple
&Triple
) {
183 MCRegisterInfo
*X
= new MCRegisterInfo();
184 InitARMMCRegisterInfo(X
, ARM::LR
, 0, 0, ARM::PC
);
188 static MCAsmInfo
*createARMMCAsmInfo(const MCRegisterInfo
&MRI
,
189 const Triple
&TheTriple
) {
191 if (TheTriple
.isOSDarwin() || TheTriple
.isOSBinFormatMachO())
192 MAI
= new ARMMCAsmInfoDarwin(TheTriple
);
193 else if (TheTriple
.isWindowsMSVCEnvironment())
194 MAI
= new ARMCOFFMCAsmInfoMicrosoft();
195 else if (TheTriple
.isOSWindows())
196 MAI
= new ARMCOFFMCAsmInfoGNU();
198 MAI
= new ARMELFMCAsmInfo(TheTriple
);
200 unsigned Reg
= MRI
.getDwarfRegNum(ARM::SP
, true);
201 MAI
->addInitialFrameState(MCCFIInstruction::createDefCfa(nullptr, Reg
, 0));
206 static MCStreamer
*createELFStreamer(const Triple
&T
, MCContext
&Ctx
,
207 std::unique_ptr
<MCAsmBackend
> &&MAB
,
208 std::unique_ptr
<MCObjectWriter
> &&OW
,
209 std::unique_ptr
<MCCodeEmitter
> &&Emitter
,
211 return createARMELFStreamer(
212 Ctx
, std::move(MAB
), std::move(OW
), std::move(Emitter
), false,
213 (T
.getArch() == Triple::thumb
|| T
.getArch() == Triple::thumbeb
));
217 createARMMachOStreamer(MCContext
&Ctx
, std::unique_ptr
<MCAsmBackend
> &&MAB
,
218 std::unique_ptr
<MCObjectWriter
> &&OW
,
219 std::unique_ptr
<MCCodeEmitter
> &&Emitter
, bool RelaxAll
,
220 bool DWARFMustBeAtTheEnd
) {
221 return createMachOStreamer(Ctx
, std::move(MAB
), std::move(OW
),
222 std::move(Emitter
), false, DWARFMustBeAtTheEnd
);
225 static MCInstPrinter
*createARMMCInstPrinter(const Triple
&T
,
226 unsigned SyntaxVariant
,
227 const MCAsmInfo
&MAI
,
228 const MCInstrInfo
&MII
,
229 const MCRegisterInfo
&MRI
) {
230 if (SyntaxVariant
== 0)
231 return new ARMInstPrinter(MAI
, MII
, MRI
);
235 static MCRelocationInfo
*createARMMCRelocationInfo(const Triple
&TT
,
237 if (TT
.isOSBinFormatMachO())
238 return createARMMachORelocationInfo(Ctx
);
239 // Default to the stock relocation info.
240 return llvm::createMCRelocationInfo(TT
, Ctx
);
245 class ARMMCInstrAnalysis
: public MCInstrAnalysis
{
247 ARMMCInstrAnalysis(const MCInstrInfo
*Info
) : MCInstrAnalysis(Info
) {}
249 bool isUnconditionalBranch(const MCInst
&Inst
) const override
{
250 // BCCs with the "always" predicate are unconditional branches.
251 if (Inst
.getOpcode() == ARM::Bcc
&& Inst
.getOperand(1).getImm()==ARMCC::AL
)
253 return MCInstrAnalysis::isUnconditionalBranch(Inst
);
256 bool isConditionalBranch(const MCInst
&Inst
) const override
{
257 // BCCs with the "always" predicate are unconditional branches.
258 if (Inst
.getOpcode() == ARM::Bcc
&& Inst
.getOperand(1).getImm()==ARMCC::AL
)
260 return MCInstrAnalysis::isConditionalBranch(Inst
);
263 bool evaluateBranch(const MCInst
&Inst
, uint64_t Addr
,
264 uint64_t Size
, uint64_t &Target
) const override
{
265 // We only handle PCRel branches for now.
266 if (Info
->get(Inst
.getOpcode()).OpInfo
[0].OperandType
!=MCOI::OPERAND_PCREL
)
269 int64_t Imm
= Inst
.getOperand(0).getImm();
270 Target
= Addr
+Imm
+8; // In ARM mode the PC is always off by 8 bytes.
275 class ThumbMCInstrAnalysis
: public ARMMCInstrAnalysis
{
277 ThumbMCInstrAnalysis(const MCInstrInfo
*Info
) : ARMMCInstrAnalysis(Info
) {}
279 bool evaluateBranch(const MCInst
&Inst
, uint64_t Addr
,
280 uint64_t Size
, uint64_t &Target
) const override
{
281 // We only handle PCRel branches for now.
282 if (Info
->get(Inst
.getOpcode()).OpInfo
[0].OperandType
!=MCOI::OPERAND_PCREL
)
285 int64_t Imm
= Inst
.getOperand(0).getImm();
286 Target
= Addr
+Imm
+4; // In Thumb mode the PC is always off by 4 bytes.
293 static MCInstrAnalysis
*createARMMCInstrAnalysis(const MCInstrInfo
*Info
) {
294 return new ARMMCInstrAnalysis(Info
);
297 static MCInstrAnalysis
*createThumbMCInstrAnalysis(const MCInstrInfo
*Info
) {
298 return new ThumbMCInstrAnalysis(Info
);
301 // Force static initialization.
302 extern "C" void LLVMInitializeARMTargetMC() {
303 for (Target
*T
: {&getTheARMLETarget(), &getTheARMBETarget(),
304 &getTheThumbLETarget(), &getTheThumbBETarget()}) {
305 // Register the MC asm info.
306 RegisterMCAsmInfoFn
X(*T
, createARMMCAsmInfo
);
308 // Register the MC instruction info.
309 TargetRegistry::RegisterMCInstrInfo(*T
, createARMMCInstrInfo
);
311 // Register the MC register info.
312 TargetRegistry::RegisterMCRegInfo(*T
, createARMMCRegisterInfo
);
314 // Register the MC subtarget info.
315 TargetRegistry::RegisterMCSubtargetInfo(*T
,
316 ARM_MC::createARMMCSubtargetInfo
);
318 TargetRegistry::RegisterELFStreamer(*T
, createELFStreamer
);
319 TargetRegistry::RegisterCOFFStreamer(*T
, createARMWinCOFFStreamer
);
320 TargetRegistry::RegisterMachOStreamer(*T
, createARMMachOStreamer
);
322 // Register the obj target streamer.
323 TargetRegistry::RegisterObjectTargetStreamer(*T
,
324 createARMObjectTargetStreamer
);
326 // Register the asm streamer.
327 TargetRegistry::RegisterAsmTargetStreamer(*T
, createARMTargetAsmStreamer
);
329 // Register the null TargetStreamer.
330 TargetRegistry::RegisterNullTargetStreamer(*T
, createARMNullTargetStreamer
);
332 // Register the MCInstPrinter.
333 TargetRegistry::RegisterMCInstPrinter(*T
, createARMMCInstPrinter
);
335 // Register the MC relocation info.
336 TargetRegistry::RegisterMCRelocationInfo(*T
, createARMMCRelocationInfo
);
339 // Register the MC instruction analyzer.
340 for (Target
*T
: {&getTheARMLETarget(), &getTheARMBETarget()})
341 TargetRegistry::RegisterMCInstrAnalysis(*T
, createARMMCInstrAnalysis
);
342 for (Target
*T
: {&getTheThumbLETarget(), &getTheThumbBETarget()})
343 TargetRegistry::RegisterMCInstrAnalysis(*T
, createThumbMCInstrAnalysis
);
345 for (Target
*T
: {&getTheARMLETarget(), &getTheThumbLETarget()}) {
346 TargetRegistry::RegisterMCCodeEmitter(*T
, createARMLEMCCodeEmitter
);
347 TargetRegistry::RegisterMCAsmBackend(*T
, createARMLEAsmBackend
);
349 for (Target
*T
: {&getTheARMBETarget(), &getTheThumbBETarget()}) {
350 TargetRegistry::RegisterMCCodeEmitter(*T
, createARMBEMCCodeEmitter
);
351 TargetRegistry::RegisterMCAsmBackend(*T
, createARMBEAsmBackend
);