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 bool ARM_MC::isPredicated(const MCInst &MI, const MCInstrInfo *MCII) {
184   const MCInstrDesc &Desc = MCII->get(MI.getOpcode());
185   int PredOpIdx = Desc.findFirstPredOperandIdx();
186   return PredOpIdx != -1 && MI.getOperand(PredOpIdx).getImm() != ARMCC::AL;
187 }
188 
189 MCSubtargetInfo *ARM_MC::createARMMCSubtargetInfo(const Triple &TT,
190                                                   StringRef CPU, StringRef FS) {
191   std::string ArchFS = ARM_MC::ParseARMTriple(TT, CPU);
192   if (!FS.empty()) {
193     if (!ArchFS.empty())
194       ArchFS = (Twine(ArchFS) + "," + FS).str();
195     else
196       ArchFS = std::string(FS);
197   }
198 
199   return createARMMCSubtargetInfoImpl(TT, CPU, /*TuneCPU*/ CPU, ArchFS);
200 }
201 
202 static MCInstrInfo *createARMMCInstrInfo() {
203   MCInstrInfo *X = new MCInstrInfo();
204   InitARMMCInstrInfo(X);
205   return X;
206 }
207 
208 static MCRegisterInfo *createARMMCRegisterInfo(const Triple &Triple) {
209   MCRegisterInfo *X = new MCRegisterInfo();
210   InitARMMCRegisterInfo(X, ARM::LR, 0, 0, ARM::PC);
211   return X;
212 }
213 
214 static MCAsmInfo *createARMMCAsmInfo(const MCRegisterInfo &MRI,
215                                      const Triple &TheTriple,
216                                      const MCTargetOptions &Options) {
217   MCAsmInfo *MAI;
218   if (TheTriple.isOSDarwin() || TheTriple.isOSBinFormatMachO())
219     MAI = new ARMMCAsmInfoDarwin(TheTriple);
220   else if (TheTriple.isWindowsMSVCEnvironment())
221     MAI = new ARMCOFFMCAsmInfoMicrosoft();
222   else if (TheTriple.isOSWindows())
223     MAI = new ARMCOFFMCAsmInfoGNU();
224   else
225     MAI = new ARMELFMCAsmInfo(TheTriple);
226 
227   unsigned Reg = MRI.getDwarfRegNum(ARM::SP, true);
228   MAI->addInitialFrameState(MCCFIInstruction::cfiDefCfa(nullptr, Reg, 0));
229 
230   return MAI;
231 }
232 
233 static MCStreamer *createELFStreamer(const Triple &T, MCContext &Ctx,
234                                      std::unique_ptr<MCAsmBackend> &&MAB,
235                                      std::unique_ptr<MCObjectWriter> &&OW,
236                                      std::unique_ptr<MCCodeEmitter> &&Emitter,
237                                      bool RelaxAll) {
238   return createARMELFStreamer(
239       Ctx, std::move(MAB), std::move(OW), std::move(Emitter), false,
240       (T.getArch() == Triple::thumb || T.getArch() == Triple::thumbeb),
241       T.isAndroid());
242 }
243 
244 static MCStreamer *
245 createARMMachOStreamer(MCContext &Ctx, std::unique_ptr<MCAsmBackend> &&MAB,
246                        std::unique_ptr<MCObjectWriter> &&OW,
247                        std::unique_ptr<MCCodeEmitter> &&Emitter, bool RelaxAll,
248                        bool DWARFMustBeAtTheEnd) {
249   return createMachOStreamer(Ctx, std::move(MAB), std::move(OW),
250                              std::move(Emitter), false, DWARFMustBeAtTheEnd);
251 }
252 
253 static MCInstPrinter *createARMMCInstPrinter(const Triple &T,
254                                              unsigned SyntaxVariant,
255                                              const MCAsmInfo &MAI,
256                                              const MCInstrInfo &MII,
257                                              const MCRegisterInfo &MRI) {
258   if (SyntaxVariant == 0)
259     return new ARMInstPrinter(MAI, MII, MRI);
260   return nullptr;
261 }
262 
263 static MCRelocationInfo *createARMMCRelocationInfo(const Triple &TT,
264                                                    MCContext &Ctx) {
265   if (TT.isOSBinFormatMachO())
266     return createARMMachORelocationInfo(Ctx);
267   // Default to the stock relocation info.
268   return llvm::createMCRelocationInfo(TT, Ctx);
269 }
270 
271 namespace {
272 
273 class ARMMCInstrAnalysis : public MCInstrAnalysis {
274 public:
275   ARMMCInstrAnalysis(const MCInstrInfo *Info) : MCInstrAnalysis(Info) {}
276 
277   bool isUnconditionalBranch(const MCInst &Inst) const override {
278     // BCCs with the "always" predicate are unconditional branches.
279     if (Inst.getOpcode() == ARM::Bcc && Inst.getOperand(1).getImm()==ARMCC::AL)
280       return true;
281     return MCInstrAnalysis::isUnconditionalBranch(Inst);
282   }
283 
284   bool isConditionalBranch(const MCInst &Inst) const override {
285     // BCCs with the "always" predicate are unconditional branches.
286     if (Inst.getOpcode() == ARM::Bcc && Inst.getOperand(1).getImm()==ARMCC::AL)
287       return false;
288     return MCInstrAnalysis::isConditionalBranch(Inst);
289   }
290 
291   bool evaluateBranch(const MCInst &Inst, uint64_t Addr,
292                       uint64_t Size, uint64_t &Target) const override {
293     // We only handle PCRel branches for now.
294     if (Inst.getNumOperands() == 0 ||
295         Info->get(Inst.getOpcode()).OpInfo[0].OperandType !=
296             MCOI::OPERAND_PCREL)
297       return false;
298 
299     int64_t Imm = Inst.getOperand(0).getImm();
300     Target = Addr+Imm+8; // In ARM mode the PC is always off by 8 bytes.
301     return true;
302   }
303 };
304 
305 class ThumbMCInstrAnalysis : public ARMMCInstrAnalysis {
306 public:
307   ThumbMCInstrAnalysis(const MCInstrInfo *Info) : ARMMCInstrAnalysis(Info) {}
308 
309   bool evaluateBranch(const MCInst &Inst, uint64_t Addr, uint64_t Size,
310                       uint64_t &Target) const override {
311     unsigned OpId;
312     switch (Inst.getOpcode()) {
313     default:
314       OpId = 0;
315       if (Inst.getNumOperands() == 0)
316         return false;
317       break;
318     case ARM::MVE_WLSTP_8:
319     case ARM::MVE_WLSTP_16:
320     case ARM::MVE_WLSTP_32:
321     case ARM::MVE_WLSTP_64:
322     case ARM::t2WLS:
323     case ARM::MVE_LETP:
324     case ARM::t2LEUpdate:
325       OpId = 2;
326       break;
327     case ARM::t2LE:
328       OpId = 1;
329       break;
330     }
331 
332     // We only handle PCRel branches for now.
333     if (Info->get(Inst.getOpcode()).OpInfo[OpId].OperandType !=
334         MCOI::OPERAND_PCREL)
335       return false;
336 
337     // In Thumb mode the PC is always off by 4 bytes.
338     Target = Addr + Inst.getOperand(OpId).getImm() + 4;
339     return true;
340   }
341 };
342 
343 }
344 
345 static MCInstrAnalysis *createARMMCInstrAnalysis(const MCInstrInfo *Info) {
346   return new ARMMCInstrAnalysis(Info);
347 }
348 
349 static MCInstrAnalysis *createThumbMCInstrAnalysis(const MCInstrInfo *Info) {
350   return new ThumbMCInstrAnalysis(Info);
351 }
352 
353 bool ARM::isCDECoproc(size_t Coproc, const MCSubtargetInfo &STI) {
354   // Unfortunately we don't have ARMTargetInfo in the disassembler, so we have
355   // to rely on feature bits.
356   if (Coproc >= 8)
357     return false;
358   return STI.getFeatureBits()[ARM::FeatureCoprocCDE0 + Coproc];
359 }
360 
361 // Force static initialization.
362 extern "C" LLVM_EXTERNAL_VISIBILITY void LLVMInitializeARMTargetMC() {
363   for (Target *T : {&getTheARMLETarget(), &getTheARMBETarget(),
364                     &getTheThumbLETarget(), &getTheThumbBETarget()}) {
365     // Register the MC asm info.
366     RegisterMCAsmInfoFn X(*T, createARMMCAsmInfo);
367 
368     // Register the MC instruction info.
369     TargetRegistry::RegisterMCInstrInfo(*T, createARMMCInstrInfo);
370 
371     // Register the MC register info.
372     TargetRegistry::RegisterMCRegInfo(*T, createARMMCRegisterInfo);
373 
374     // Register the MC subtarget info.
375     TargetRegistry::RegisterMCSubtargetInfo(*T,
376                                             ARM_MC::createARMMCSubtargetInfo);
377 
378     TargetRegistry::RegisterELFStreamer(*T, createELFStreamer);
379     TargetRegistry::RegisterCOFFStreamer(*T, createARMWinCOFFStreamer);
380     TargetRegistry::RegisterMachOStreamer(*T, createARMMachOStreamer);
381 
382     // Register the obj target streamer.
383     TargetRegistry::RegisterObjectTargetStreamer(*T,
384                                                  createARMObjectTargetStreamer);
385 
386     // Register the asm streamer.
387     TargetRegistry::RegisterAsmTargetStreamer(*T, createARMTargetAsmStreamer);
388 
389     // Register the null TargetStreamer.
390     TargetRegistry::RegisterNullTargetStreamer(*T, createARMNullTargetStreamer);
391 
392     // Register the MCInstPrinter.
393     TargetRegistry::RegisterMCInstPrinter(*T, createARMMCInstPrinter);
394 
395     // Register the MC relocation info.
396     TargetRegistry::RegisterMCRelocationInfo(*T, createARMMCRelocationInfo);
397   }
398 
399   // Register the MC instruction analyzer.
400   for (Target *T : {&getTheARMLETarget(), &getTheARMBETarget()})
401     TargetRegistry::RegisterMCInstrAnalysis(*T, createARMMCInstrAnalysis);
402   for (Target *T : {&getTheThumbLETarget(), &getTheThumbBETarget()})
403     TargetRegistry::RegisterMCInstrAnalysis(*T, createThumbMCInstrAnalysis);
404 
405   for (Target *T : {&getTheARMLETarget(), &getTheThumbLETarget()}) {
406     TargetRegistry::RegisterMCCodeEmitter(*T, createARMLEMCCodeEmitter);
407     TargetRegistry::RegisterMCAsmBackend(*T, createARMLEAsmBackend);
408   }
409   for (Target *T : {&getTheARMBETarget(), &getTheThumbBETarget()}) {
410     TargetRegistry::RegisterMCCodeEmitter(*T, createARMBEMCCodeEmitter);
411     TargetRegistry::RegisterMCAsmBackend(*T, createARMBEAsmBackend);
412   }
413 }
414