1 //===-- ARMMCTargetDesc.cpp - ARM 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 ARM specific target descriptions.
10 //
11 //===----------------------------------------------------------------------===//
12 
13 #include "ARMMCTargetDesc.h"
14 #include "ARMBaseInfo.h"
15 #include "ARMInstPrinter.h"
16 #include "ARMMCAsmInfo.h"
17 #include "TargetInfo/ARMTargetInfo.h"
18 #include "llvm/ADT/Triple.h"
19 #include "llvm/MC/MCAsmBackend.h"
20 #include "llvm/MC/MCCodeEmitter.h"
21 #include "llvm/MC/MCELFStreamer.h"
22 #include "llvm/MC/MCInstrAnalysis.h"
23 #include "llvm/MC/MCInstrInfo.h"
24 #include "llvm/MC/MCObjectWriter.h"
25 #include "llvm/MC/MCRegisterInfo.h"
26 #include "llvm/MC/MCStreamer.h"
27 #include "llvm/MC/MCSubtargetInfo.h"
28 #include "llvm/Support/ErrorHandling.h"
29 #include "llvm/Support/TargetParser.h"
30 #include "llvm/Support/TargetRegistry.h"
31 
32 using namespace llvm;
33 
34 #define GET_REGINFO_MC_DESC
35 #include "ARMGenRegisterInfo.inc"
36 
37 static bool getMCRDeprecationInfo(MCInst &MI, const MCSubtargetInfo &STI,
38                                   std::string &Info) {
39   if (STI.getFeatureBits()[llvm::ARM::HasV7Ops] &&
40       (MI.getOperand(0).isImm() && MI.getOperand(0).getImm() == 15) &&
41       (MI.getOperand(1).isImm() && MI.getOperand(1).getImm() == 0) &&
42       // Checks for the deprecated CP15ISB encoding:
43       // mcr p15, #0, rX, c7, c5, #4
44       (MI.getOperand(3).isImm() && MI.getOperand(3).getImm() == 7)) {
45     if ((MI.getOperand(5).isImm() && MI.getOperand(5).getImm() == 4)) {
46       if (MI.getOperand(4).isImm() && MI.getOperand(4).getImm() == 5) {
47         Info = "deprecated since v7, use 'isb'";
48         return true;
49       }
50 
51       // Checks for the deprecated CP15DSB encoding:
52       // mcr p15, #0, rX, c7, c10, #4
53       if (MI.getOperand(4).isImm() && MI.getOperand(4).getImm() == 10) {
54         Info = "deprecated since v7, use 'dsb'";
55         return true;
56       }
57     }
58     // Checks for the deprecated CP15DMB encoding:
59     // mcr p15, #0, rX, c7, c10, #5
60     if (MI.getOperand(4).isImm() && MI.getOperand(4).getImm() == 10 &&
61         (MI.getOperand(5).isImm() && MI.getOperand(5).getImm() == 5)) {
62       Info = "deprecated since v7, use 'dmb'";
63       return true;
64     }
65   }
66   if (STI.getFeatureBits()[llvm::ARM::HasV7Ops] &&
67       ((MI.getOperand(0).isImm() && MI.getOperand(0).getImm() == 10) ||
68        (MI.getOperand(0).isImm() && MI.getOperand(0).getImm() == 11))) {
69     Info = "since v7, cp10 and cp11 are reserved for advanced SIMD or floating "
70            "point instructions";
71     return true;
72   }
73   return false;
74 }
75 
76 static bool getMRCDeprecationInfo(MCInst &MI, const MCSubtargetInfo &STI,
77                                   std::string &Info) {
78   if (STI.getFeatureBits()[llvm::ARM::HasV7Ops] &&
79       ((MI.getOperand(0).isImm() && MI.getOperand(0).getImm() == 10) ||
80        (MI.getOperand(0).isImm() && MI.getOperand(0).getImm() == 11))) {
81     Info = "since v7, cp10 and cp11 are reserved for advanced SIMD or floating "
82            "point instructions";
83     return true;
84   }
85   return false;
86 }
87 
88 static bool getITDeprecationInfo(MCInst &MI, const MCSubtargetInfo &STI,
89                                  std::string &Info) {
90   if (STI.getFeatureBits()[llvm::ARM::HasV8Ops] && MI.getOperand(1).isImm() &&
91       MI.getOperand(1).getImm() != 8) {
92     Info = "applying IT instruction to more than one subsequent instruction is "
93            "deprecated";
94     return true;
95   }
96 
97   return false;
98 }
99 
100 static bool getARMStoreDeprecationInfo(MCInst &MI, const MCSubtargetInfo &STI,
101                                        std::string &Info) {
102   assert(!STI.getFeatureBits()[llvm::ARM::ModeThumb] &&
103          "cannot predicate thumb instructions");
104 
105   assert(MI.getNumOperands() >= 4 && "expected >= 4 arguments");
106   for (unsigned OI = 4, OE = MI.getNumOperands(); OI < OE; ++OI) {
107     assert(MI.getOperand(OI).isReg() && "expected register");
108     if (MI.getOperand(OI).getReg() == ARM::SP ||
109         MI.getOperand(OI).getReg() == ARM::PC) {
110       Info = "use of SP or PC in the list is deprecated";
111       return true;
112     }
113   }
114   return false;
115 }
116 
117 static bool getARMLoadDeprecationInfo(MCInst &MI, const MCSubtargetInfo &STI,
118                                       std::string &Info) {
119   assert(!STI.getFeatureBits()[llvm::ARM::ModeThumb] &&
120          "cannot predicate thumb instructions");
121 
122   assert(MI.getNumOperands() >= 4 && "expected >= 4 arguments");
123   bool ListContainsPC = false, ListContainsLR = false;
124   for (unsigned OI = 4, OE = MI.getNumOperands(); OI < OE; ++OI) {
125     assert(MI.getOperand(OI).isReg() && "expected register");
126     switch (MI.getOperand(OI).getReg()) {
127     default:
128       break;
129     case ARM::LR:
130       ListContainsLR = true;
131       break;
132     case ARM::PC:
133       ListContainsPC = true;
134       break;
135     case ARM::SP:
136       Info = "use of SP in the list is deprecated";
137       return true;
138     }
139   }
140 
141   if (ListContainsPC && ListContainsLR) {
142     Info = "use of LR and PC simultaneously in the list is deprecated";
143     return true;
144   }
145 
146   return false;
147 }
148 
149 #define GET_INSTRINFO_MC_DESC
150 #include "ARMGenInstrInfo.inc"
151 
152 #define GET_SUBTARGETINFO_MC_DESC
153 #include "ARMGenSubtargetInfo.inc"
154 
155 std::string ARM_MC::ParseARMTriple(const Triple &TT, StringRef CPU) {
156   std::string ARMArchFeature;
157 
158   ARM::ArchKind ArchID = ARM::parseArch(TT.getArchName());
159   if (ArchID != ARM::ArchKind::INVALID &&  (CPU.empty() || CPU == "generic"))
160     ARMArchFeature = (ARMArchFeature + "+" + ARM::getArchName(ArchID)).str();
161 
162   if (TT.isThumb()) {
163     if (!ARMArchFeature.empty())
164       ARMArchFeature += ",";
165     ARMArchFeature += "+thumb-mode,+v4t";
166   }
167 
168   if (TT.isOSNaCl()) {
169     if (!ARMArchFeature.empty())
170       ARMArchFeature += ",";
171     ARMArchFeature += "+nacl-trap";
172   }
173 
174   if (TT.isOSWindows()) {
175     if (!ARMArchFeature.empty())
176       ARMArchFeature += ",";
177     ARMArchFeature += "+noarm";
178   }
179 
180   return ARMArchFeature;
181 }
182 
183 MCSubtargetInfo *ARM_MC::createARMMCSubtargetInfo(const Triple &TT,
184                                                   StringRef CPU, StringRef FS) {
185   std::string ArchFS = ARM_MC::ParseARMTriple(TT, CPU);
186   if (!FS.empty()) {
187     if (!ArchFS.empty())
188       ArchFS = (Twine(ArchFS) + "," + FS).str();
189     else
190       ArchFS = std::string(FS);
191   }
192 
193   return createARMMCSubtargetInfoImpl(TT, CPU, ArchFS);
194 }
195 
196 static MCInstrInfo *createARMMCInstrInfo() {
197   MCInstrInfo *X = new MCInstrInfo();
198   InitARMMCInstrInfo(X);
199   return X;
200 }
201 
202 static MCRegisterInfo *createARMMCRegisterInfo(const Triple &Triple) {
203   MCRegisterInfo *X = new MCRegisterInfo();
204   InitARMMCRegisterInfo(X, ARM::LR, 0, 0, ARM::PC);
205   return X;
206 }
207 
208 static MCAsmInfo *createARMMCAsmInfo(const MCRegisterInfo &MRI,
209                                      const Triple &TheTriple,
210                                      const MCTargetOptions &Options) {
211   MCAsmInfo *MAI;
212   if (TheTriple.isOSDarwin() || TheTriple.isOSBinFormatMachO())
213     MAI = new ARMMCAsmInfoDarwin(TheTriple);
214   else if (TheTriple.isWindowsMSVCEnvironment())
215     MAI = new ARMCOFFMCAsmInfoMicrosoft();
216   else if (TheTriple.isOSWindows())
217     MAI = new ARMCOFFMCAsmInfoGNU();
218   else
219     MAI = new ARMELFMCAsmInfo(TheTriple);
220 
221   unsigned Reg = MRI.getDwarfRegNum(ARM::SP, true);
222   MAI->addInitialFrameState(MCCFIInstruction::cfiDefCfa(nullptr, Reg, 0));
223 
224   return MAI;
225 }
226 
227 static MCStreamer *createELFStreamer(const Triple &T, MCContext &Ctx,
228                                      std::unique_ptr<MCAsmBackend> &&MAB,
229                                      std::unique_ptr<MCObjectWriter> &&OW,
230                                      std::unique_ptr<MCCodeEmitter> &&Emitter,
231                                      bool RelaxAll) {
232   return createARMELFStreamer(
233       Ctx, std::move(MAB), std::move(OW), std::move(Emitter), false,
234       (T.getArch() == Triple::thumb || T.getArch() == Triple::thumbeb),
235       T.isAndroid());
236 }
237 
238 static MCStreamer *
239 createARMMachOStreamer(MCContext &Ctx, std::unique_ptr<MCAsmBackend> &&MAB,
240                        std::unique_ptr<MCObjectWriter> &&OW,
241                        std::unique_ptr<MCCodeEmitter> &&Emitter, bool RelaxAll,
242                        bool DWARFMustBeAtTheEnd) {
243   return createMachOStreamer(Ctx, std::move(MAB), std::move(OW),
244                              std::move(Emitter), false, DWARFMustBeAtTheEnd);
245 }
246 
247 static MCInstPrinter *createARMMCInstPrinter(const Triple &T,
248                                              unsigned SyntaxVariant,
249                                              const MCAsmInfo &MAI,
250                                              const MCInstrInfo &MII,
251                                              const MCRegisterInfo &MRI) {
252   if (SyntaxVariant == 0)
253     return new ARMInstPrinter(MAI, MII, MRI);
254   return nullptr;
255 }
256 
257 static MCRelocationInfo *createARMMCRelocationInfo(const Triple &TT,
258                                                    MCContext &Ctx) {
259   if (TT.isOSBinFormatMachO())
260     return createARMMachORelocationInfo(Ctx);
261   // Default to the stock relocation info.
262   return llvm::createMCRelocationInfo(TT, Ctx);
263 }
264 
265 namespace {
266 
267 class ARMMCInstrAnalysis : public MCInstrAnalysis {
268 public:
269   ARMMCInstrAnalysis(const MCInstrInfo *Info) : MCInstrAnalysis(Info) {}
270 
271   bool isUnconditionalBranch(const MCInst &Inst) const override {
272     // BCCs with the "always" predicate are unconditional branches.
273     if (Inst.getOpcode() == ARM::Bcc && Inst.getOperand(1).getImm()==ARMCC::AL)
274       return true;
275     return MCInstrAnalysis::isUnconditionalBranch(Inst);
276   }
277 
278   bool isConditionalBranch(const MCInst &Inst) const override {
279     // BCCs with the "always" predicate are unconditional branches.
280     if (Inst.getOpcode() == ARM::Bcc && Inst.getOperand(1).getImm()==ARMCC::AL)
281       return false;
282     return MCInstrAnalysis::isConditionalBranch(Inst);
283   }
284 
285   bool evaluateBranch(const MCInst &Inst, uint64_t Addr,
286                       uint64_t Size, uint64_t &Target) const override {
287     // We only handle PCRel branches for now.
288     if (Inst.getNumOperands() == 0 ||
289         Info->get(Inst.getOpcode()).OpInfo[0].OperandType !=
290             MCOI::OPERAND_PCREL)
291       return false;
292 
293     int64_t Imm = Inst.getOperand(0).getImm();
294     Target = Addr+Imm+8; // In ARM mode the PC is always off by 8 bytes.
295     return true;
296   }
297 };
298 
299 class ThumbMCInstrAnalysis : public ARMMCInstrAnalysis {
300 public:
301   ThumbMCInstrAnalysis(const MCInstrInfo *Info) : ARMMCInstrAnalysis(Info) {}
302 
303   bool evaluateBranch(const MCInst &Inst, uint64_t Addr, uint64_t Size,
304                       uint64_t &Target) const override {
305     unsigned OpId;
306     switch (Inst.getOpcode()) {
307     default:
308       OpId = 0;
309       if (Inst.getNumOperands() == 0)
310         return false;
311       break;
312     case ARM::MVE_WLSTP_8:
313     case ARM::MVE_WLSTP_16:
314     case ARM::MVE_WLSTP_32:
315     case ARM::MVE_WLSTP_64:
316     case ARM::t2WLS:
317     case ARM::MVE_LETP:
318     case ARM::t2LEUpdate:
319       OpId = 2;
320       break;
321     case ARM::t2LE:
322       OpId = 1;
323       break;
324     }
325 
326     // We only handle PCRel branches for now.
327     if (Info->get(Inst.getOpcode()).OpInfo[OpId].OperandType !=
328         MCOI::OPERAND_PCREL)
329       return false;
330 
331     // In Thumb mode the PC is always off by 4 bytes.
332     Target = Addr + Inst.getOperand(OpId).getImm() + 4;
333     return true;
334   }
335 };
336 
337 }
338 
339 static MCInstrAnalysis *createARMMCInstrAnalysis(const MCInstrInfo *Info) {
340   return new ARMMCInstrAnalysis(Info);
341 }
342 
343 static MCInstrAnalysis *createThumbMCInstrAnalysis(const MCInstrInfo *Info) {
344   return new ThumbMCInstrAnalysis(Info);
345 }
346 
347 bool ARM::isCDECoproc(size_t Coproc, const MCSubtargetInfo &STI) {
348   // Unfortunately we don't have ARMTargetInfo in the disassembler, so we have
349   // to rely on feature bits.
350   if (Coproc >= 8)
351     return false;
352   return STI.getFeatureBits()[ARM::FeatureCoprocCDE0 + Coproc];
353 }
354 
355 // Force static initialization.
356 extern "C" LLVM_EXTERNAL_VISIBILITY void LLVMInitializeARMTargetMC() {
357   for (Target *T : {&getTheARMLETarget(), &getTheARMBETarget(),
358                     &getTheThumbLETarget(), &getTheThumbBETarget()}) {
359     // Register the MC asm info.
360     RegisterMCAsmInfoFn X(*T, createARMMCAsmInfo);
361 
362     // Register the MC instruction info.
363     TargetRegistry::RegisterMCInstrInfo(*T, createARMMCInstrInfo);
364 
365     // Register the MC register info.
366     TargetRegistry::RegisterMCRegInfo(*T, createARMMCRegisterInfo);
367 
368     // Register the MC subtarget info.
369     TargetRegistry::RegisterMCSubtargetInfo(*T,
370                                             ARM_MC::createARMMCSubtargetInfo);
371 
372     TargetRegistry::RegisterELFStreamer(*T, createELFStreamer);
373     TargetRegistry::RegisterCOFFStreamer(*T, createARMWinCOFFStreamer);
374     TargetRegistry::RegisterMachOStreamer(*T, createARMMachOStreamer);
375 
376     // Register the obj target streamer.
377     TargetRegistry::RegisterObjectTargetStreamer(*T,
378                                                  createARMObjectTargetStreamer);
379 
380     // Register the asm streamer.
381     TargetRegistry::RegisterAsmTargetStreamer(*T, createARMTargetAsmStreamer);
382 
383     // Register the null TargetStreamer.
384     TargetRegistry::RegisterNullTargetStreamer(*T, createARMNullTargetStreamer);
385 
386     // Register the MCInstPrinter.
387     TargetRegistry::RegisterMCInstPrinter(*T, createARMMCInstPrinter);
388 
389     // Register the MC relocation info.
390     TargetRegistry::RegisterMCRelocationInfo(*T, createARMMCRelocationInfo);
391   }
392 
393   // Register the MC instruction analyzer.
394   for (Target *T : {&getTheARMLETarget(), &getTheARMBETarget()})
395     TargetRegistry::RegisterMCInstrAnalysis(*T, createARMMCInstrAnalysis);
396   for (Target *T : {&getTheThumbLETarget(), &getTheThumbBETarget()})
397     TargetRegistry::RegisterMCInstrAnalysis(*T, createThumbMCInstrAnalysis);
398 
399   for (Target *T : {&getTheARMLETarget(), &getTheThumbLETarget()}) {
400     TargetRegistry::RegisterMCCodeEmitter(*T, createARMLEMCCodeEmitter);
401     TargetRegistry::RegisterMCAsmBackend(*T, createARMLEAsmBackend);
402   }
403   for (Target *T : {&getTheARMBETarget(), &getTheThumbBETarget()}) {
404     TargetRegistry::RegisterMCCodeEmitter(*T, createARMBEMCCodeEmitter);
405     TargetRegistry::RegisterMCAsmBackend(*T, createARMBEAsmBackend);
406   }
407 }
408