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
32using namespace llvm;
33
34#define GET_REGINFO_MC_DESC
35#include "ARMGenRegisterInfo.inc"
36
37static 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  return false;
67}
68
69static bool getITDeprecationInfo(MCInst &MI, const MCSubtargetInfo &STI,
70                                 std::string &Info) {
71  if (STI.getFeatureBits()[llvm::ARM::HasV8Ops] && MI.getOperand(1).isImm() &&
72      MI.getOperand(1).getImm() != 8) {
73    Info = "applying IT instruction to more than one subsequent instruction is "
74           "deprecated";
75    return true;
76  }
77
78  return false;
79}
80
81static bool getARMStoreDeprecationInfo(MCInst &MI, const MCSubtargetInfo &STI,
82                                       std::string &Info) {
83  assert(!STI.getFeatureBits()[llvm::ARM::ModeThumb] &&
84         "cannot predicate thumb instructions");
85
86  assert(MI.getNumOperands() >= 4 && "expected >= 4 arguments");
87  for (unsigned OI = 4, OE = MI.getNumOperands(); OI < OE; ++OI) {
88    assert(MI.getOperand(OI).isReg() && "expected register");
89    if (MI.getOperand(OI).getReg() == ARM::SP ||
90        MI.getOperand(OI).getReg() == ARM::PC) {
91      Info = "use of SP or PC in the list is deprecated";
92      return true;
93    }
94  }
95  return false;
96}
97
98static bool getARMLoadDeprecationInfo(MCInst &MI, const MCSubtargetInfo &STI,
99                                      std::string &Info) {
100  assert(!STI.getFeatureBits()[llvm::ARM::ModeThumb] &&
101         "cannot predicate thumb instructions");
102
103  assert(MI.getNumOperands() >= 4 && "expected >= 4 arguments");
104  bool ListContainsPC = false, ListContainsLR = false;
105  for (unsigned OI = 4, OE = MI.getNumOperands(); OI < OE; ++OI) {
106    assert(MI.getOperand(OI).isReg() && "expected register");
107    switch (MI.getOperand(OI).getReg()) {
108    default:
109      break;
110    case ARM::LR:
111      ListContainsLR = true;
112      break;
113    case ARM::PC:
114      ListContainsPC = true;
115      break;
116    case ARM::SP:
117      Info = "use of SP in the list is deprecated";
118      return true;
119    }
120  }
121
122  if (ListContainsPC && ListContainsLR) {
123    Info = "use of LR and PC simultaneously in the list is deprecated";
124    return true;
125  }
126
127  return false;
128}
129
130#define GET_INSTRINFO_MC_DESC
131#include "ARMGenInstrInfo.inc"
132
133#define GET_SUBTARGETINFO_MC_DESC
134#include "ARMGenSubtargetInfo.inc"
135
136std::string ARM_MC::ParseARMTriple(const Triple &TT, StringRef CPU) {
137  std::string ARMArchFeature;
138
139  ARM::ArchKind ArchID = ARM::parseArch(TT.getArchName());
140  if (ArchID != ARM::ArchKind::INVALID &&  (CPU.empty() || CPU == "generic"))
141    ARMArchFeature = (ARMArchFeature + "+" + ARM::getArchName(ArchID)).str();
142
143  if (TT.isThumb()) {
144    if (!ARMArchFeature.empty())
145      ARMArchFeature += ",";
146    ARMArchFeature += "+thumb-mode,+v4t";
147  }
148
149  if (TT.isOSNaCl()) {
150    if (!ARMArchFeature.empty())
151      ARMArchFeature += ",";
152    ARMArchFeature += "+nacl-trap";
153  }
154
155  if (TT.isOSWindows()) {
156    if (!ARMArchFeature.empty())
157      ARMArchFeature += ",";
158    ARMArchFeature += "+noarm";
159  }
160
161  return ARMArchFeature;
162}
163
164MCSubtargetInfo *ARM_MC::createARMMCSubtargetInfo(const Triple &TT,
165                                                  StringRef CPU, StringRef FS) {
166  std::string ArchFS = ARM_MC::ParseARMTriple(TT, CPU);
167  if (!FS.empty()) {
168    if (!ArchFS.empty())
169      ArchFS = (Twine(ArchFS) + "," + FS).str();
170    else
171      ArchFS = FS;
172  }
173
174  return createARMMCSubtargetInfoImpl(TT, CPU, ArchFS);
175}
176
177static MCInstrInfo *createARMMCInstrInfo() {
178  MCInstrInfo *X = new MCInstrInfo();
179  InitARMMCInstrInfo(X);
180  return X;
181}
182
183static MCRegisterInfo *createARMMCRegisterInfo(const Triple &Triple) {
184  MCRegisterInfo *X = new MCRegisterInfo();
185  InitARMMCRegisterInfo(X, ARM::LR, 0, 0, ARM::PC);
186  return X;
187}
188
189static MCAsmInfo *createARMMCAsmInfo(const MCRegisterInfo &MRI,
190                                     const Triple &TheTriple,
191                                     const MCTargetOptions &Options) {
192  MCAsmInfo *MAI;
193  if (TheTriple.isOSDarwin() || TheTriple.isOSBinFormatMachO())
194    MAI = new ARMMCAsmInfoDarwin(TheTriple);
195  else if (TheTriple.isWindowsMSVCEnvironment())
196    MAI = new ARMCOFFMCAsmInfoMicrosoft();
197  else if (TheTriple.isOSWindows())
198    MAI = new ARMCOFFMCAsmInfoGNU();
199  else
200    MAI = new ARMELFMCAsmInfo(TheTriple);
201
202  unsigned Reg = MRI.getDwarfRegNum(ARM::SP, true);
203  MAI->addInitialFrameState(MCCFIInstruction::createDefCfa(nullptr, Reg, 0));
204
205  return MAI;
206}
207
208static MCStreamer *createELFStreamer(const Triple &T, MCContext &Ctx,
209                                     std::unique_ptr<MCAsmBackend> &&MAB,
210                                     std::unique_ptr<MCObjectWriter> &&OW,
211                                     std::unique_ptr<MCCodeEmitter> &&Emitter,
212                                     bool RelaxAll) {
213  return createARMELFStreamer(
214      Ctx, std::move(MAB), std::move(OW), std::move(Emitter), false,
215      (T.getArch() == Triple::thumb || T.getArch() == Triple::thumbeb),
216      T.isAndroid());
217}
218
219static MCStreamer *
220createARMMachOStreamer(MCContext &Ctx, std::unique_ptr<MCAsmBackend> &&MAB,
221                       std::unique_ptr<MCObjectWriter> &&OW,
222                       std::unique_ptr<MCCodeEmitter> &&Emitter, bool RelaxAll,
223                       bool DWARFMustBeAtTheEnd) {
224  return createMachOStreamer(Ctx, std::move(MAB), std::move(OW),
225                             std::move(Emitter), false, DWARFMustBeAtTheEnd);
226}
227
228static MCInstPrinter *createARMMCInstPrinter(const Triple &T,
229                                             unsigned SyntaxVariant,
230                                             const MCAsmInfo &MAI,
231                                             const MCInstrInfo &MII,
232                                             const MCRegisterInfo &MRI) {
233  if (SyntaxVariant == 0)
234    return new ARMInstPrinter(MAI, MII, MRI);
235  return nullptr;
236}
237
238static MCRelocationInfo *createARMMCRelocationInfo(const Triple &TT,
239                                                   MCContext &Ctx) {
240  if (TT.isOSBinFormatMachO())
241    return createARMMachORelocationInfo(Ctx);
242  // Default to the stock relocation info.
243  return llvm::createMCRelocationInfo(TT, Ctx);
244}
245
246namespace {
247
248class ARMMCInstrAnalysis : public MCInstrAnalysis {
249public:
250  ARMMCInstrAnalysis(const MCInstrInfo *Info) : MCInstrAnalysis(Info) {}
251
252  bool isUnconditionalBranch(const MCInst &Inst) const override {
253    // BCCs with the "always" predicate are unconditional branches.
254    if (Inst.getOpcode() == ARM::Bcc && Inst.getOperand(1).getImm()==ARMCC::AL)
255      return true;
256    return MCInstrAnalysis::isUnconditionalBranch(Inst);
257  }
258
259  bool isConditionalBranch(const MCInst &Inst) const override {
260    // BCCs with the "always" predicate are unconditional branches.
261    if (Inst.getOpcode() == ARM::Bcc && Inst.getOperand(1).getImm()==ARMCC::AL)
262      return false;
263    return MCInstrAnalysis::isConditionalBranch(Inst);
264  }
265
266  bool evaluateBranch(const MCInst &Inst, uint64_t Addr,
267                      uint64_t Size, uint64_t &Target) const override {
268    // We only handle PCRel branches for now.
269    if (Info->get(Inst.getOpcode()).OpInfo[0].OperandType!=MCOI::OPERAND_PCREL)
270      return false;
271
272    int64_t Imm = Inst.getOperand(0).getImm();
273    Target = Addr+Imm+8; // In ARM mode the PC is always off by 8 bytes.
274    return true;
275  }
276};
277
278class ThumbMCInstrAnalysis : public ARMMCInstrAnalysis {
279public:
280  ThumbMCInstrAnalysis(const MCInstrInfo *Info) : ARMMCInstrAnalysis(Info) {}
281
282  bool evaluateBranch(const MCInst &Inst, uint64_t Addr, uint64_t Size,
283                      uint64_t &Target) const override {
284    unsigned OpId;
285    switch (Inst.getOpcode()) {
286    default:
287      OpId = 0;
288      break;
289    case ARM::t2WLS:
290    case ARM::t2LEUpdate:
291      OpId = 2;
292      break;
293    case ARM::t2LE:
294      OpId = 1;
295      break;
296    }
297
298    // We only handle PCRel branches for now.
299    if (Info->get(Inst.getOpcode()).OpInfo[OpId].OperandType !=
300        MCOI::OPERAND_PCREL)
301      return false;
302
303    // In Thumb mode the PC is always off by 4 bytes.
304    Target = Addr + Inst.getOperand(OpId).getImm() + 4;
305    return true;
306  }
307};
308
309}
310
311static MCInstrAnalysis *createARMMCInstrAnalysis(const MCInstrInfo *Info) {
312  return new ARMMCInstrAnalysis(Info);
313}
314
315static MCInstrAnalysis *createThumbMCInstrAnalysis(const MCInstrInfo *Info) {
316  return new ThumbMCInstrAnalysis(Info);
317}
318
319// Force static initialization.
320extern "C" LLVM_EXTERNAL_VISIBILITY void LLVMInitializeARMTargetMC() {
321  for (Target *T : {&getTheARMLETarget(), &getTheARMBETarget(),
322                    &getTheThumbLETarget(), &getTheThumbBETarget()}) {
323    // Register the MC asm info.
324    RegisterMCAsmInfoFn X(*T, createARMMCAsmInfo);
325
326    // Register the MC instruction info.
327    TargetRegistry::RegisterMCInstrInfo(*T, createARMMCInstrInfo);
328
329    // Register the MC register info.
330    TargetRegistry::RegisterMCRegInfo(*T, createARMMCRegisterInfo);
331
332    // Register the MC subtarget info.
333    TargetRegistry::RegisterMCSubtargetInfo(*T,
334                                            ARM_MC::createARMMCSubtargetInfo);
335
336    TargetRegistry::RegisterELFStreamer(*T, createELFStreamer);
337    TargetRegistry::RegisterCOFFStreamer(*T, createARMWinCOFFStreamer);
338    TargetRegistry::RegisterMachOStreamer(*T, createARMMachOStreamer);
339
340    // Register the obj target streamer.
341    TargetRegistry::RegisterObjectTargetStreamer(*T,
342                                                 createARMObjectTargetStreamer);
343
344    // Register the asm streamer.
345    TargetRegistry::RegisterAsmTargetStreamer(*T, createARMTargetAsmStreamer);
346
347    // Register the null TargetStreamer.
348    TargetRegistry::RegisterNullTargetStreamer(*T, createARMNullTargetStreamer);
349
350    // Register the MCInstPrinter.
351    TargetRegistry::RegisterMCInstPrinter(*T, createARMMCInstPrinter);
352
353    // Register the MC relocation info.
354    TargetRegistry::RegisterMCRelocationInfo(*T, createARMMCRelocationInfo);
355  }
356
357  // Register the MC instruction analyzer.
358  for (Target *T : {&getTheARMLETarget(), &getTheARMBETarget()})
359    TargetRegistry::RegisterMCInstrAnalysis(*T, createARMMCInstrAnalysis);
360  for (Target *T : {&getTheThumbLETarget(), &getTheThumbBETarget()})
361    TargetRegistry::RegisterMCInstrAnalysis(*T, createThumbMCInstrAnalysis);
362
363  for (Target *T : {&getTheARMLETarget(), &getTheThumbLETarget()}) {
364    TargetRegistry::RegisterMCCodeEmitter(*T, createARMLEMCCodeEmitter);
365    TargetRegistry::RegisterMCAsmBackend(*T, createARMLEAsmBackend);
366  }
367  for (Target *T : {&getTheARMBETarget(), &getTheThumbBETarget()}) {
368    TargetRegistry::RegisterMCCodeEmitter(*T, createARMBEMCCodeEmitter);
369    TargetRegistry::RegisterMCAsmBackend(*T, createARMBEAsmBackend);
370  }
371}
372