1234353Sdim//===-- ARMMCTargetDesc.cpp - ARM Target Descriptions ---------------------===//
2224133Sdim//
3224133Sdim//                     The LLVM Compiler Infrastructure
4224133Sdim//
5224133Sdim// This file is distributed under the University of Illinois Open Source
6224133Sdim// License. See LICENSE.TXT for details.
7224133Sdim//
8224133Sdim//===----------------------------------------------------------------------===//
9224133Sdim//
10224133Sdim// This file provides ARM specific target descriptions.
11224133Sdim//
12224133Sdim//===----------------------------------------------------------------------===//
13224133Sdim
14249423Sdim#include "ARMBaseInfo.h"
15249423Sdim#include "ARMMCAsmInfo.h"
16224133Sdim#include "ARMMCTargetDesc.h"
17226633Sdim#include "InstPrinter/ARMInstPrinter.h"
18249423Sdim#include "llvm/ADT/Triple.h"
19226633Sdim#include "llvm/MC/MCCodeGenInfo.h"
20261991Sdim#include "llvm/MC/MCELFStreamer.h"
21226633Sdim#include "llvm/MC/MCInstrAnalysis.h"
22224133Sdim#include "llvm/MC/MCInstrInfo.h"
23224133Sdim#include "llvm/MC/MCRegisterInfo.h"
24276479Sdim#include "llvm/MC/MCStreamer.h"
25224133Sdim#include "llvm/MC/MCSubtargetInfo.h"
26226633Sdim#include "llvm/Support/ErrorHandling.h"
27296417Sdim#include "llvm/Support/TargetParser.h"
28226633Sdim#include "llvm/Support/TargetRegistry.h"
29224133Sdim
30261991Sdimusing namespace llvm;
31261991Sdim
32224133Sdim#define GET_REGINFO_MC_DESC
33224133Sdim#include "ARMGenRegisterInfo.inc"
34224133Sdim
35288943Sdimstatic bool getMCRDeprecationInfo(MCInst &MI, const MCSubtargetInfo &STI,
36261991Sdim                                  std::string &Info) {
37288943Sdim  if (STI.getFeatureBits()[llvm::ARM::HasV7Ops] &&
38261991Sdim      (MI.getOperand(0).isImm() && MI.getOperand(0).getImm() == 15) &&
39261991Sdim      (MI.getOperand(1).isImm() && MI.getOperand(1).getImm() == 0) &&
40261991Sdim      // Checks for the deprecated CP15ISB encoding:
41261991Sdim      // mcr p15, #0, rX, c7, c5, #4
42261991Sdim      (MI.getOperand(3).isImm() && MI.getOperand(3).getImm() == 7)) {
43261991Sdim    if ((MI.getOperand(5).isImm() && MI.getOperand(5).getImm() == 4)) {
44261991Sdim      if (MI.getOperand(4).isImm() && MI.getOperand(4).getImm() == 5) {
45261991Sdim        Info = "deprecated since v7, use 'isb'";
46261991Sdim        return true;
47261991Sdim      }
48261991Sdim
49261991Sdim      // Checks for the deprecated CP15DSB encoding:
50261991Sdim      // mcr p15, #0, rX, c7, c10, #4
51261991Sdim      if (MI.getOperand(4).isImm() && MI.getOperand(4).getImm() == 10) {
52261991Sdim        Info = "deprecated since v7, use 'dsb'";
53261991Sdim        return true;
54261991Sdim      }
55261991Sdim    }
56261991Sdim    // Checks for the deprecated CP15DMB encoding:
57261991Sdim    // mcr p15, #0, rX, c7, c10, #5
58261991Sdim    if (MI.getOperand(4).isImm() && MI.getOperand(4).getImm() == 10 &&
59261991Sdim        (MI.getOperand(5).isImm() && MI.getOperand(5).getImm() == 5)) {
60261991Sdim      Info = "deprecated since v7, use 'dmb'";
61261991Sdim      return true;
62261991Sdim    }
63261991Sdim  }
64261991Sdim  return false;
65261991Sdim}
66261991Sdim
67288943Sdimstatic bool getITDeprecationInfo(MCInst &MI, const MCSubtargetInfo &STI,
68280031Sdim                                 std::string &Info) {
69288943Sdim  if (STI.getFeatureBits()[llvm::ARM::HasV8Ops] && MI.getOperand(1).isImm() &&
70280031Sdim      MI.getOperand(1).getImm() != 8) {
71280031Sdim    Info = "applying IT instruction to more than one subsequent instruction is "
72280031Sdim           "deprecated";
73261991Sdim    return true;
74261991Sdim  }
75261991Sdim
76261991Sdim  return false;
77261991Sdim}
78261991Sdim
79288943Sdimstatic bool getARMStoreDeprecationInfo(MCInst &MI, const MCSubtargetInfo &STI,
80280031Sdim                                       std::string &Info) {
81288943Sdim  assert(!STI.getFeatureBits()[llvm::ARM::ModeThumb] &&
82280031Sdim         "cannot predicate thumb instructions");
83280031Sdim
84280031Sdim  assert(MI.getNumOperands() >= 4 && "expected >= 4 arguments");
85280031Sdim  for (unsigned OI = 4, OE = MI.getNumOperands(); OI < OE; ++OI) {
86280031Sdim    assert(MI.getOperand(OI).isReg() && "expected register");
87280031Sdim    if (MI.getOperand(OI).getReg() == ARM::SP ||
88280031Sdim        MI.getOperand(OI).getReg() == ARM::PC) {
89280031Sdim      Info = "use of SP or PC in the list is deprecated";
90280031Sdim      return true;
91280031Sdim    }
92280031Sdim  }
93280031Sdim  return false;
94280031Sdim}
95280031Sdim
96288943Sdimstatic bool getARMLoadDeprecationInfo(MCInst &MI, const MCSubtargetInfo &STI,
97280031Sdim                                      std::string &Info) {
98288943Sdim  assert(!STI.getFeatureBits()[llvm::ARM::ModeThumb] &&
99280031Sdim         "cannot predicate thumb instructions");
100280031Sdim
101280031Sdim  assert(MI.getNumOperands() >= 4 && "expected >= 4 arguments");
102280031Sdim  bool ListContainsPC = false, ListContainsLR = false;
103280031Sdim  for (unsigned OI = 4, OE = MI.getNumOperands(); OI < OE; ++OI) {
104280031Sdim    assert(MI.getOperand(OI).isReg() && "expected register");
105280031Sdim    switch (MI.getOperand(OI).getReg()) {
106280031Sdim    default:
107280031Sdim      break;
108280031Sdim    case ARM::LR:
109280031Sdim      ListContainsLR = true;
110280031Sdim      break;
111280031Sdim    case ARM::PC:
112280031Sdim      ListContainsPC = true;
113280031Sdim      break;
114280031Sdim    case ARM::SP:
115280031Sdim      Info = "use of SP in the list is deprecated";
116280031Sdim      return true;
117280031Sdim    }
118280031Sdim  }
119280031Sdim
120280031Sdim  if (ListContainsPC && ListContainsLR) {
121280031Sdim    Info = "use of LR and PC simultaneously in the list is deprecated";
122280031Sdim    return true;
123280031Sdim  }
124280031Sdim
125280031Sdim  return false;
126280031Sdim}
127280031Sdim
128224133Sdim#define GET_INSTRINFO_MC_DESC
129224133Sdim#include "ARMGenInstrInfo.inc"
130224133Sdim
131224133Sdim#define GET_SUBTARGETINFO_MC_DESC
132224133Sdim#include "ARMGenSubtargetInfo.inc"
133224133Sdim
134288943Sdimstd::string ARM_MC::ParseARMTriple(const Triple &TT, StringRef CPU) {
135288943Sdim  bool isThumb =
136288943Sdim      TT.getArch() == Triple::thumb || TT.getArch() == Triple::thumbeb;
137224133Sdim
138224133Sdim  std::string ARMArchFeature;
139224133Sdim
140296417Sdim  unsigned ArchID = ARM::parseArch(TT.getArchName());
141296417Sdim  if (ArchID != ARM::AK_INVALID &&  (CPU.empty() || CPU == "generic"))
142296417Sdim    ARMArchFeature = (ARMArchFeature + "+" + ARM::getArchName(ArchID)).str();
143296417Sdim
144224133Sdim  if (isThumb) {
145224133Sdim    if (ARMArchFeature.empty())
146224133Sdim      ARMArchFeature = "+thumb-mode";
147224133Sdim    else
148224133Sdim      ARMArchFeature += ",+thumb-mode";
149224133Sdim  }
150224133Sdim
151288943Sdim  if (TT.isOSNaCl()) {
152249423Sdim    if (ARMArchFeature.empty())
153249423Sdim      ARMArchFeature = "+nacl-trap";
154249423Sdim    else
155249423Sdim      ARMArchFeature += ",+nacl-trap";
156249423Sdim  }
157249423Sdim
158224133Sdim  return ARMArchFeature;
159224133Sdim}
160224133Sdim
161288943SdimMCSubtargetInfo *ARM_MC::createARMMCSubtargetInfo(const Triple &TT,
162288943Sdim                                                  StringRef CPU, StringRef FS) {
163239462Sdim  std::string ArchFS = ARM_MC::ParseARMTriple(TT, CPU);
164224133Sdim  if (!FS.empty()) {
165224133Sdim    if (!ArchFS.empty())
166288943Sdim      ArchFS = (Twine(ArchFS) + "," + FS).str();
167224133Sdim    else
168224133Sdim      ArchFS = FS;
169224133Sdim  }
170224133Sdim
171288943Sdim  return createARMMCSubtargetInfoImpl(TT, CPU, ArchFS);
172224133Sdim}
173224133Sdim
174224133Sdimstatic MCInstrInfo *createARMMCInstrInfo() {
175224133Sdim  MCInstrInfo *X = new MCInstrInfo();
176224133Sdim  InitARMMCInstrInfo(X);
177224133Sdim  return X;
178224133Sdim}
179224133Sdim
180288943Sdimstatic MCRegisterInfo *createARMMCRegisterInfo(const Triple &Triple) {
181224133Sdim  MCRegisterInfo *X = new MCRegisterInfo();
182249423Sdim  InitARMMCRegisterInfo(X, ARM::LR, 0, 0, ARM::PC);
183224133Sdim  return X;
184224133Sdim}
185224133Sdim
186288943Sdimstatic MCAsmInfo *createARMMCAsmInfo(const MCRegisterInfo &MRI,
187288943Sdim                                     const Triple &TheTriple) {
188276479Sdim  MCAsmInfo *MAI;
189280031Sdim  if (TheTriple.isOSDarwin() || TheTriple.isOSBinFormatMachO())
190288943Sdim    MAI = new ARMMCAsmInfoDarwin(TheTriple);
191280031Sdim  else if (TheTriple.isWindowsMSVCEnvironment())
192280031Sdim    MAI = new ARMCOFFMCAsmInfoMicrosoft();
193288943Sdim  else if (TheTriple.isOSWindows())
194288943Sdim    MAI = new ARMCOFFMCAsmInfoGNU();
195280031Sdim  else
196288943Sdim    MAI = new ARMELFMCAsmInfo(TheTriple);
197224133Sdim
198276479Sdim  unsigned Reg = MRI.getDwarfRegNum(ARM::SP, true);
199276479Sdim  MAI->addInitialFrameState(MCCFIInstruction::createDefCfa(nullptr, Reg, 0));
200276479Sdim
201276479Sdim  return MAI;
202224133Sdim}
203224133Sdim
204288943Sdimstatic MCCodeGenInfo *createARMMCCodeGenInfo(const Triple &TT, Reloc::Model RM,
205234353Sdim                                             CodeModel::Model CM,
206234353Sdim                                             CodeGenOpt::Level OL) {
207226633Sdim  MCCodeGenInfo *X = new MCCodeGenInfo();
208226633Sdim  if (RM == Reloc::Default) {
209226633Sdim    // Default relocation model on Darwin is PIC, not DynamicNoPIC.
210288943Sdim    RM = TT.isOSDarwin() ? Reloc::PIC_ : Reloc::DynamicNoPIC;
211226633Sdim  }
212288943Sdim  X->initMCCodeGenInfo(RM, CM, OL);
213226633Sdim  return X;
214226633Sdim}
215226633Sdim
216288943Sdimstatic MCStreamer *createELFStreamer(const Triple &T, MCContext &Ctx,
217288943Sdim                                     MCAsmBackend &MAB, raw_pwrite_stream &OS,
218288943Sdim                                     MCCodeEmitter *Emitter, bool RelaxAll) {
219288943Sdim  return createARMELFStreamer(Ctx, MAB, OS, Emitter, false,
220288943Sdim                              T.getArch() == Triple::thumb);
221288943Sdim}
222226633Sdim
223288943Sdimstatic MCStreamer *createARMMachOStreamer(MCContext &Ctx, MCAsmBackend &MAB,
224288943Sdim                                          raw_pwrite_stream &OS,
225288943Sdim                                          MCCodeEmitter *Emitter, bool RelaxAll,
226288943Sdim                                          bool DWARFMustBeAtTheEnd) {
227288943Sdim  return createMachOStreamer(Ctx, MAB, OS, Emitter, false, DWARFMustBeAtTheEnd);
228226633Sdim}
229226633Sdim
230288943Sdimstatic MCInstPrinter *createARMMCInstPrinter(const Triple &T,
231226633Sdim                                             unsigned SyntaxVariant,
232226633Sdim                                             const MCAsmInfo &MAI,
233234353Sdim                                             const MCInstrInfo &MII,
234288943Sdim                                             const MCRegisterInfo &MRI) {
235226633Sdim  if (SyntaxVariant == 0)
236288943Sdim    return new ARMInstPrinter(MAI, MII, MRI);
237276479Sdim  return nullptr;
238226633Sdim}
239226633Sdim
240288943Sdimstatic MCRelocationInfo *createARMMCRelocationInfo(const Triple &TT,
241261991Sdim                                                   MCContext &Ctx) {
242288943Sdim  if (TT.isOSBinFormatMachO())
243261991Sdim    return createARMMachORelocationInfo(Ctx);
244261991Sdim  // Default to the stock relocation info.
245261991Sdim  return llvm::createMCRelocationInfo(TT, Ctx);
246261991Sdim}
247261991Sdim
248226633Sdimnamespace {
249226633Sdim
250226633Sdimclass ARMMCInstrAnalysis : public MCInstrAnalysis {
251226633Sdimpublic:
252226633Sdim  ARMMCInstrAnalysis(const MCInstrInfo *Info) : MCInstrAnalysis(Info) {}
253226633Sdim
254276479Sdim  bool isUnconditionalBranch(const MCInst &Inst) const override {
255226633Sdim    // BCCs with the "always" predicate are unconditional branches.
256226633Sdim    if (Inst.getOpcode() == ARM::Bcc && Inst.getOperand(1).getImm()==ARMCC::AL)
257226633Sdim      return true;
258226633Sdim    return MCInstrAnalysis::isUnconditionalBranch(Inst);
259226633Sdim  }
260226633Sdim
261276479Sdim  bool isConditionalBranch(const MCInst &Inst) const override {
262226633Sdim    // BCCs with the "always" predicate are unconditional branches.
263226633Sdim    if (Inst.getOpcode() == ARM::Bcc && Inst.getOperand(1).getImm()==ARMCC::AL)
264226633Sdim      return false;
265226633Sdim    return MCInstrAnalysis::isConditionalBranch(Inst);
266226633Sdim  }
267226633Sdim
268261991Sdim  bool evaluateBranch(const MCInst &Inst, uint64_t Addr,
269276479Sdim                      uint64_t Size, uint64_t &Target) const override {
270226633Sdim    // We only handle PCRel branches for now.
271226633Sdim    if (Info->get(Inst.getOpcode()).OpInfo[0].OperandType!=MCOI::OPERAND_PCREL)
272261991Sdim      return false;
273226633Sdim
274226633Sdim    int64_t Imm = Inst.getOperand(0).getImm();
275226633Sdim    // FIXME: This is not right for thumb.
276261991Sdim    Target = Addr+Imm+8; // In ARM mode the PC is always off by 8 bytes.
277261991Sdim    return true;
278226633Sdim  }
279226633Sdim};
280226633Sdim
281226633Sdim}
282226633Sdim
283226633Sdimstatic MCInstrAnalysis *createARMMCInstrAnalysis(const MCInstrInfo *Info) {
284226633Sdim  return new ARMMCInstrAnalysis(Info);
285226633Sdim}
286226633Sdim
287226633Sdim// Force static initialization.
288226633Sdimextern "C" void LLVMInitializeARMTargetMC() {
289288943Sdim  for (Target *T : {&TheARMLETarget, &TheARMBETarget, &TheThumbLETarget,
290288943Sdim                    &TheThumbBETarget}) {
291288943Sdim    // Register the MC asm info.
292288943Sdim    RegisterMCAsmInfoFn X(*T, createARMMCAsmInfo);
293226633Sdim
294288943Sdim    // Register the MC codegen info.
295288943Sdim    TargetRegistry::RegisterMCCodeGenInfo(*T, createARMMCCodeGenInfo);
296226633Sdim
297288943Sdim    // Register the MC instruction info.
298288943Sdim    TargetRegistry::RegisterMCInstrInfo(*T, createARMMCInstrInfo);
299226633Sdim
300288943Sdim    // Register the MC register info.
301288943Sdim    TargetRegistry::RegisterMCRegInfo(*T, createARMMCRegisterInfo);
302226633Sdim
303288943Sdim    // Register the MC subtarget info.
304288943Sdim    TargetRegistry::RegisterMCSubtargetInfo(*T,
305288943Sdim                                            ARM_MC::createARMMCSubtargetInfo);
306226633Sdim
307288943Sdim    // Register the MC instruction analyzer.
308288943Sdim    TargetRegistry::RegisterMCInstrAnalysis(*T, createARMMCInstrAnalysis);
309226633Sdim
310288943Sdim    TargetRegistry::RegisterELFStreamer(*T, createELFStreamer);
311288943Sdim    TargetRegistry::RegisterCOFFStreamer(*T, createARMWinCOFFStreamer);
312288943Sdim    TargetRegistry::RegisterMachOStreamer(*T, createARMMachOStreamer);
313288943Sdim
314288943Sdim    // Register the obj target streamer.
315288943Sdim    TargetRegistry::RegisterObjectTargetStreamer(*T,
316288943Sdim                                                 createARMObjectTargetStreamer);
317288943Sdim
318288943Sdim    // Register the asm streamer.
319288943Sdim    TargetRegistry::RegisterAsmTargetStreamer(*T, createARMTargetAsmStreamer);
320288943Sdim
321288943Sdim    // Register the null TargetStreamer.
322288943Sdim    TargetRegistry::RegisterNullTargetStreamer(*T, createARMNullTargetStreamer);
323288943Sdim
324288943Sdim    // Register the MCInstPrinter.
325288943Sdim    TargetRegistry::RegisterMCInstPrinter(*T, createARMMCInstPrinter);
326288943Sdim
327288943Sdim    // Register the MC relocation info.
328288943Sdim    TargetRegistry::RegisterMCRelocationInfo(*T, createARMMCRelocationInfo);
329288943Sdim  }
330288943Sdim
331226633Sdim  // Register the MC Code Emitter
332288943Sdim  for (Target *T : {&TheARMLETarget, &TheThumbLETarget})
333288943Sdim    TargetRegistry::RegisterMCCodeEmitter(*T, createARMLEMCCodeEmitter);
334288943Sdim  for (Target *T : {&TheARMBETarget, &TheThumbBETarget})
335288943Sdim    TargetRegistry::RegisterMCCodeEmitter(*T, createARMBEMCCodeEmitter);
336226633Sdim
337226633Sdim  // Register the asm backend.
338276479Sdim  TargetRegistry::RegisterMCAsmBackend(TheARMLETarget, createARMLEAsmBackend);
339276479Sdim  TargetRegistry::RegisterMCAsmBackend(TheARMBETarget, createARMBEAsmBackend);
340276479Sdim  TargetRegistry::RegisterMCAsmBackend(TheThumbLETarget,
341276479Sdim                                       createThumbLEAsmBackend);
342276479Sdim  TargetRegistry::RegisterMCAsmBackend(TheThumbBETarget,
343276479Sdim                                       createThumbBEAsmBackend);
344224133Sdim}
345