1//===-- ARMMCTargetDesc.cpp - ARM Target Descriptions ---------------------===//
2//
3//                     The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9//
10// This file provides ARM specific target descriptions.
11//
12//===----------------------------------------------------------------------===//
13
14#include "ARMBaseInfo.h"
15#include "ARMMCAsmInfo.h"
16#include "ARMMCTargetDesc.h"
17#include "InstPrinter/ARMInstPrinter.h"
18#include "llvm/ADT/Triple.h"
19#include "llvm/MC/MCELFStreamer.h"
20#include "llvm/MC/MCInstrAnalysis.h"
21#include "llvm/MC/MCInstrInfo.h"
22#include "llvm/MC/MCRegisterInfo.h"
23#include "llvm/MC/MCStreamer.h"
24#include "llvm/MC/MCSubtargetInfo.h"
25#include "llvm/Support/ErrorHandling.h"
26#include "llvm/Support/TargetParser.h"
27#include "llvm/Support/TargetRegistry.h"
28
29using namespace llvm;
30
31#define GET_REGINFO_MC_DESC
32#include "ARMGenRegisterInfo.inc"
33
34static bool getMCRDeprecationInfo(MCInst &MI, const MCSubtargetInfo &STI,
35                                  std::string &Info) {
36  if (STI.getFeatureBits()[llvm::ARM::HasV7Ops] &&
37      (MI.getOperand(0).isImm() && MI.getOperand(0).getImm() == 15) &&
38      (MI.getOperand(1).isImm() && MI.getOperand(1).getImm() == 0) &&
39      // Checks for the deprecated CP15ISB encoding:
40      // mcr p15, #0, rX, c7, c5, #4
41      (MI.getOperand(3).isImm() && MI.getOperand(3).getImm() == 7)) {
42    if ((MI.getOperand(5).isImm() && MI.getOperand(5).getImm() == 4)) {
43      if (MI.getOperand(4).isImm() && MI.getOperand(4).getImm() == 5) {
44        Info = "deprecated since v7, use 'isb'";
45        return true;
46      }
47
48      // Checks for the deprecated CP15DSB encoding:
49      // mcr p15, #0, rX, c7, c10, #4
50      if (MI.getOperand(4).isImm() && MI.getOperand(4).getImm() == 10) {
51        Info = "deprecated since v7, use 'dsb'";
52        return true;
53      }
54    }
55    // Checks for the deprecated CP15DMB encoding:
56    // mcr p15, #0, rX, c7, c10, #5
57    if (MI.getOperand(4).isImm() && MI.getOperand(4).getImm() == 10 &&
58        (MI.getOperand(5).isImm() && MI.getOperand(5).getImm() == 5)) {
59      Info = "deprecated since v7, use 'dmb'";
60      return true;
61    }
62  }
63  return false;
64}
65
66static bool getITDeprecationInfo(MCInst &MI, const MCSubtargetInfo &STI,
67                                 std::string &Info) {
68  if (STI.getFeatureBits()[llvm::ARM::HasV8Ops] && MI.getOperand(1).isImm() &&
69      MI.getOperand(1).getImm() != 8) {
70    Info = "applying IT instruction to more than one subsequent instruction is "
71           "deprecated";
72    return true;
73  }
74
75  return false;
76}
77
78static bool getARMStoreDeprecationInfo(MCInst &MI, const MCSubtargetInfo &STI,
79                                       std::string &Info) {
80  assert(!STI.getFeatureBits()[llvm::ARM::ModeThumb] &&
81         "cannot predicate thumb instructions");
82
83  assert(MI.getNumOperands() >= 4 && "expected >= 4 arguments");
84  for (unsigned OI = 4, OE = MI.getNumOperands(); OI < OE; ++OI) {
85    assert(MI.getOperand(OI).isReg() && "expected register");
86    if (MI.getOperand(OI).getReg() == ARM::SP ||
87        MI.getOperand(OI).getReg() == ARM::PC) {
88      Info = "use of SP or PC in the list is deprecated";
89      return true;
90    }
91  }
92  return false;
93}
94
95static bool getARMLoadDeprecationInfo(MCInst &MI, const MCSubtargetInfo &STI,
96                                      std::string &Info) {
97  assert(!STI.getFeatureBits()[llvm::ARM::ModeThumb] &&
98         "cannot predicate thumb instructions");
99
100  assert(MI.getNumOperands() >= 4 && "expected >= 4 arguments");
101  bool ListContainsPC = false, ListContainsLR = false;
102  for (unsigned OI = 4, OE = MI.getNumOperands(); OI < OE; ++OI) {
103    assert(MI.getOperand(OI).isReg() && "expected register");
104    switch (MI.getOperand(OI).getReg()) {
105    default:
106      break;
107    case ARM::LR:
108      ListContainsLR = true;
109      break;
110    case ARM::PC:
111      ListContainsPC = true;
112      break;
113    case ARM::SP:
114      Info = "use of SP in the list is deprecated";
115      return true;
116    }
117  }
118
119  if (ListContainsPC && ListContainsLR) {
120    Info = "use of LR and PC simultaneously in the list is deprecated";
121    return true;
122  }
123
124  return false;
125}
126
127#define GET_INSTRINFO_MC_DESC
128#include "ARMGenInstrInfo.inc"
129
130#define GET_SUBTARGETINFO_MC_DESC
131#include "ARMGenSubtargetInfo.inc"
132
133std::string ARM_MC::ParseARMTriple(const Triple &TT, StringRef CPU) {
134  bool isThumb =
135      TT.getArch() == Triple::thumb || TT.getArch() == Triple::thumbeb;
136
137  std::string ARMArchFeature;
138
139  unsigned ArchID = ARM::parseArch(TT.getArchName());
140  if (ArchID != ARM::AK_INVALID &&  (CPU.empty() || CPU == "generic"))
141    ARMArchFeature = (ARMArchFeature + "+" + ARM::getArchName(ArchID)).str();
142
143  if (isThumb) {
144    if (ARMArchFeature.empty())
145      ARMArchFeature = "+thumb-mode";
146    else
147      ARMArchFeature += ",+thumb-mode";
148  }
149
150  if (TT.isOSNaCl()) {
151    if (ARMArchFeature.empty())
152      ARMArchFeature = "+nacl-trap";
153    else
154      ARMArchFeature += ",+nacl-trap";
155  }
156
157  return ARMArchFeature;
158}
159
160MCSubtargetInfo *ARM_MC::createARMMCSubtargetInfo(const Triple &TT,
161                                                  StringRef CPU, StringRef FS) {
162  std::string ArchFS = ARM_MC::ParseARMTriple(TT, CPU);
163  if (!FS.empty()) {
164    if (!ArchFS.empty())
165      ArchFS = (Twine(ArchFS) + "," + FS).str();
166    else
167      ArchFS = FS;
168  }
169
170  return createARMMCSubtargetInfoImpl(TT, CPU, ArchFS);
171}
172
173static MCInstrInfo *createARMMCInstrInfo() {
174  MCInstrInfo *X = new MCInstrInfo();
175  InitARMMCInstrInfo(X);
176  return X;
177}
178
179static MCRegisterInfo *createARMMCRegisterInfo(const Triple &Triple) {
180  MCRegisterInfo *X = new MCRegisterInfo();
181  InitARMMCRegisterInfo(X, ARM::LR, 0, 0, ARM::PC);
182  return X;
183}
184
185static MCAsmInfo *createARMMCAsmInfo(const MCRegisterInfo &MRI,
186                                     const Triple &TheTriple) {
187  MCAsmInfo *MAI;
188  if (TheTriple.isOSDarwin() || TheTriple.isOSBinFormatMachO())
189    MAI = new ARMMCAsmInfoDarwin(TheTriple);
190  else if (TheTriple.isWindowsMSVCEnvironment())
191    MAI = new ARMCOFFMCAsmInfoMicrosoft();
192  else if (TheTriple.isOSWindows())
193    MAI = new ARMCOFFMCAsmInfoGNU();
194  else
195    MAI = new ARMELFMCAsmInfo(TheTriple);
196
197  unsigned Reg = MRI.getDwarfRegNum(ARM::SP, true);
198  MAI->addInitialFrameState(MCCFIInstruction::createDefCfa(nullptr, Reg, 0));
199
200  return MAI;
201}
202
203static MCStreamer *createELFStreamer(const Triple &T, MCContext &Ctx,
204                                     MCAsmBackend &MAB, raw_pwrite_stream &OS,
205                                     MCCodeEmitter *Emitter, bool RelaxAll) {
206  return createARMELFStreamer(Ctx, MAB, OS, Emitter, false,
207                              T.getArch() == Triple::thumb);
208}
209
210static MCStreamer *createARMMachOStreamer(MCContext &Ctx, MCAsmBackend &MAB,
211                                          raw_pwrite_stream &OS,
212                                          MCCodeEmitter *Emitter, bool RelaxAll,
213                                          bool DWARFMustBeAtTheEnd) {
214  return createMachOStreamer(Ctx, MAB, OS, Emitter, false, DWARFMustBeAtTheEnd);
215}
216
217static MCInstPrinter *createARMMCInstPrinter(const Triple &T,
218                                             unsigned SyntaxVariant,
219                                             const MCAsmInfo &MAI,
220                                             const MCInstrInfo &MII,
221                                             const MCRegisterInfo &MRI) {
222  if (SyntaxVariant == 0)
223    return new ARMInstPrinter(MAI, MII, MRI);
224  return nullptr;
225}
226
227static MCRelocationInfo *createARMMCRelocationInfo(const Triple &TT,
228                                                   MCContext &Ctx) {
229  if (TT.isOSBinFormatMachO())
230    return createARMMachORelocationInfo(Ctx);
231  // Default to the stock relocation info.
232  return llvm::createMCRelocationInfo(TT, Ctx);
233}
234
235namespace {
236
237class ARMMCInstrAnalysis : public MCInstrAnalysis {
238public:
239  ARMMCInstrAnalysis(const MCInstrInfo *Info) : MCInstrAnalysis(Info) {}
240
241  bool isUnconditionalBranch(const MCInst &Inst) const override {
242    // BCCs with the "always" predicate are unconditional branches.
243    if (Inst.getOpcode() == ARM::Bcc && Inst.getOperand(1).getImm()==ARMCC::AL)
244      return true;
245    return MCInstrAnalysis::isUnconditionalBranch(Inst);
246  }
247
248  bool isConditionalBranch(const MCInst &Inst) const override {
249    // BCCs with the "always" predicate are unconditional branches.
250    if (Inst.getOpcode() == ARM::Bcc && Inst.getOperand(1).getImm()==ARMCC::AL)
251      return false;
252    return MCInstrAnalysis::isConditionalBranch(Inst);
253  }
254
255  bool evaluateBranch(const MCInst &Inst, uint64_t Addr,
256                      uint64_t Size, uint64_t &Target) const override {
257    // We only handle PCRel branches for now.
258    if (Info->get(Inst.getOpcode()).OpInfo[0].OperandType!=MCOI::OPERAND_PCREL)
259      return false;
260
261    int64_t Imm = Inst.getOperand(0).getImm();
262    // FIXME: This is not right for thumb.
263    Target = Addr+Imm+8; // In ARM mode the PC is always off by 8 bytes.
264    return true;
265  }
266};
267
268}
269
270static MCInstrAnalysis *createARMMCInstrAnalysis(const MCInstrInfo *Info) {
271  return new ARMMCInstrAnalysis(Info);
272}
273
274// Force static initialization.
275extern "C" void LLVMInitializeARMTargetMC() {
276  for (Target *T : {&TheARMLETarget, &TheARMBETarget, &TheThumbLETarget,
277                    &TheThumbBETarget}) {
278    // Register the MC asm info.
279    RegisterMCAsmInfoFn X(*T, createARMMCAsmInfo);
280
281    // Register the MC instruction info.
282    TargetRegistry::RegisterMCInstrInfo(*T, createARMMCInstrInfo);
283
284    // Register the MC register info.
285    TargetRegistry::RegisterMCRegInfo(*T, createARMMCRegisterInfo);
286
287    // Register the MC subtarget info.
288    TargetRegistry::RegisterMCSubtargetInfo(*T,
289                                            ARM_MC::createARMMCSubtargetInfo);
290
291    // Register the MC instruction analyzer.
292    TargetRegistry::RegisterMCInstrAnalysis(*T, createARMMCInstrAnalysis);
293
294    TargetRegistry::RegisterELFStreamer(*T, createELFStreamer);
295    TargetRegistry::RegisterCOFFStreamer(*T, createARMWinCOFFStreamer);
296    TargetRegistry::RegisterMachOStreamer(*T, createARMMachOStreamer);
297
298    // Register the obj target streamer.
299    TargetRegistry::RegisterObjectTargetStreamer(*T,
300                                                 createARMObjectTargetStreamer);
301
302    // Register the asm streamer.
303    TargetRegistry::RegisterAsmTargetStreamer(*T, createARMTargetAsmStreamer);
304
305    // Register the null TargetStreamer.
306    TargetRegistry::RegisterNullTargetStreamer(*T, createARMNullTargetStreamer);
307
308    // Register the MCInstPrinter.
309    TargetRegistry::RegisterMCInstPrinter(*T, createARMMCInstPrinter);
310
311    // Register the MC relocation info.
312    TargetRegistry::RegisterMCRelocationInfo(*T, createARMMCRelocationInfo);
313  }
314
315  // Register the MC Code Emitter
316  for (Target *T : {&TheARMLETarget, &TheThumbLETarget})
317    TargetRegistry::RegisterMCCodeEmitter(*T, createARMLEMCCodeEmitter);
318  for (Target *T : {&TheARMBETarget, &TheThumbBETarget})
319    TargetRegistry::RegisterMCCodeEmitter(*T, createARMBEMCCodeEmitter);
320
321  // Register the asm backend.
322  TargetRegistry::RegisterMCAsmBackend(TheARMLETarget, createARMLEAsmBackend);
323  TargetRegistry::RegisterMCAsmBackend(TheARMBETarget, createARMBEAsmBackend);
324  TargetRegistry::RegisterMCAsmBackend(TheThumbLETarget,
325                                       createThumbLEAsmBackend);
326  TargetRegistry::RegisterMCAsmBackend(TheThumbBETarget,
327                                       createThumbBEAsmBackend);
328}
329