1249259Sdim//===-- AArch64MCTargetDesc.cpp - AArch64 Target Descriptions -------------===//
2249259Sdim//
3249259Sdim//                     The LLVM Compiler Infrastructure
4249259Sdim//
5249259Sdim// This file is distributed under the University of Illinois Open Source
6249259Sdim// License. See LICENSE.TXT for details.
7249259Sdim//
8249259Sdim//===----------------------------------------------------------------------===//
9249259Sdim//
10249259Sdim// This file provides AArch64 specific target descriptions.
11249259Sdim//
12249259Sdim//===----------------------------------------------------------------------===//
13249259Sdim
14249259Sdim#include "AArch64MCTargetDesc.h"
15249259Sdim#include "AArch64ELFStreamer.h"
16249259Sdim#include "AArch64MCAsmInfo.h"
17249259Sdim#include "InstPrinter/AArch64InstPrinter.h"
18249259Sdim#include "llvm/ADT/APInt.h"
19249259Sdim#include "llvm/MC/MCCodeGenInfo.h"
20249259Sdim#include "llvm/MC/MCInstrAnalysis.h"
21249259Sdim#include "llvm/MC/MCInstrInfo.h"
22249259Sdim#include "llvm/MC/MCRegisterInfo.h"
23249259Sdim#include "llvm/MC/MCStreamer.h"
24249259Sdim#include "llvm/MC/MCSubtargetInfo.h"
25249259Sdim#include "llvm/Support/TargetRegistry.h"
26249259Sdim#include "llvm/Support/ErrorHandling.h"
27249259Sdim
28249259Sdim#define GET_REGINFO_MC_DESC
29249259Sdim#include "AArch64GenRegisterInfo.inc"
30249259Sdim
31249259Sdim#define GET_INSTRINFO_MC_DESC
32249259Sdim#include "AArch64GenInstrInfo.inc"
33249259Sdim
34249259Sdim#define GET_SUBTARGETINFO_MC_DESC
35249259Sdim#include "AArch64GenSubtargetInfo.inc"
36249259Sdim
37249259Sdimusing namespace llvm;
38249259Sdim
39249259SdimMCSubtargetInfo *AArch64_MC::createAArch64MCSubtargetInfo(StringRef TT,
40249259Sdim                                                          StringRef CPU,
41249259Sdim                                                          StringRef FS) {
42249259Sdim  MCSubtargetInfo *X = new MCSubtargetInfo();
43263508Sdim  InitAArch64MCSubtargetInfo(X, TT, CPU, FS);
44249259Sdim  return X;
45249259Sdim}
46249259Sdim
47249259Sdim
48249259Sdimstatic MCInstrInfo *createAArch64MCInstrInfo() {
49249259Sdim  MCInstrInfo *X = new MCInstrInfo();
50249259Sdim  InitAArch64MCInstrInfo(X);
51249259Sdim  return X;
52249259Sdim}
53249259Sdim
54249259Sdimstatic MCRegisterInfo *createAArch64MCRegisterInfo(StringRef Triple) {
55249259Sdim  MCRegisterInfo *X = new MCRegisterInfo();
56249259Sdim  InitAArch64MCRegisterInfo(X, AArch64::X30);
57249259Sdim  return X;
58249259Sdim}
59249259Sdim
60263508Sdimstatic MCAsmInfo *createAArch64MCAsmInfo(const MCRegisterInfo &MRI,
61263508Sdim                                         StringRef TT) {
62249259Sdim  Triple TheTriple(TT);
63249259Sdim
64249259Sdim  MCAsmInfo *MAI = new AArch64ELFMCAsmInfo();
65263508Sdim  unsigned Reg = MRI.getDwarfRegNum(AArch64::XSP, true);
66263508Sdim  MCCFIInstruction Inst = MCCFIInstruction::createDefCfa(0, Reg, 0);
67263508Sdim  MAI->addInitialFrameState(Inst);
68249259Sdim
69249259Sdim  return MAI;
70249259Sdim}
71249259Sdim
72249259Sdimstatic MCCodeGenInfo *createAArch64MCCodeGenInfo(StringRef TT, Reloc::Model RM,
73249259Sdim                                                 CodeModel::Model CM,
74249259Sdim                                                 CodeGenOpt::Level OL) {
75249259Sdim  MCCodeGenInfo *X = new MCCodeGenInfo();
76249259Sdim  if (RM == Reloc::Default || RM == Reloc::DynamicNoPIC) {
77249259Sdim    // On ELF platforms the default static relocation model has a smart enough
78249259Sdim    // linker to cope with referencing external symbols defined in a shared
79249259Sdim    // library. Hence DynamicNoPIC doesn't need to be promoted to PIC.
80249259Sdim    RM = Reloc::Static;
81249259Sdim  }
82249259Sdim
83249259Sdim  if (CM == CodeModel::Default)
84249259Sdim    CM = CodeModel::Small;
85251662Sdim  else if (CM == CodeModel::JITDefault) {
86251662Sdim    // The default MCJIT memory managers make no guarantees about where they can
87251662Sdim    // find an executable page; JITed code needs to be able to refer to globals
88251662Sdim    // no matter how far away they are.
89251662Sdim    CM = CodeModel::Large;
90251662Sdim  }
91249259Sdim
92249259Sdim  X->InitMCCodeGenInfo(RM, CM, OL);
93249259Sdim  return X;
94249259Sdim}
95249259Sdim
96249259Sdimstatic MCStreamer *createMCStreamer(const Target &T, StringRef TT,
97249259Sdim                                    MCContext &Ctx, MCAsmBackend &MAB,
98249259Sdim                                    raw_ostream &OS,
99249259Sdim                                    MCCodeEmitter *Emitter,
100249259Sdim                                    bool RelaxAll,
101249259Sdim                                    bool NoExecStack) {
102249259Sdim  Triple TheTriple(TT);
103249259Sdim
104249259Sdim  return createAArch64ELFStreamer(Ctx, MAB, OS, Emitter, RelaxAll, NoExecStack);
105249259Sdim}
106249259Sdim
107249259Sdim
108249259Sdimstatic MCInstPrinter *createAArch64MCInstPrinter(const Target &T,
109249259Sdim                                                 unsigned SyntaxVariant,
110249259Sdim                                                 const MCAsmInfo &MAI,
111249259Sdim                                                 const MCInstrInfo &MII,
112249259Sdim                                                 const MCRegisterInfo &MRI,
113249259Sdim                                                 const MCSubtargetInfo &STI) {
114249259Sdim  if (SyntaxVariant == 0)
115249259Sdim    return new AArch64InstPrinter(MAI, MII, MRI, STI);
116249259Sdim  return 0;
117249259Sdim}
118249259Sdim
119249259Sdimnamespace {
120249259Sdim
121249259Sdimclass AArch64MCInstrAnalysis : public MCInstrAnalysis {
122249259Sdimpublic:
123249259Sdim  AArch64MCInstrAnalysis(const MCInstrInfo *Info) : MCInstrAnalysis(Info) {}
124249259Sdim
125249259Sdim  virtual bool isUnconditionalBranch(const MCInst &Inst) const {
126249259Sdim    if (Inst.getOpcode() == AArch64::Bcc
127249259Sdim        && Inst.getOperand(0).getImm() == A64CC::AL)
128249259Sdim      return true;
129249259Sdim    return MCInstrAnalysis::isUnconditionalBranch(Inst);
130249259Sdim  }
131249259Sdim
132249259Sdim  virtual bool isConditionalBranch(const MCInst &Inst) const {
133249259Sdim    if (Inst.getOpcode() == AArch64::Bcc
134249259Sdim        && Inst.getOperand(0).getImm() == A64CC::AL)
135249259Sdim      return false;
136249259Sdim    return MCInstrAnalysis::isConditionalBranch(Inst);
137249259Sdim  }
138249259Sdim
139263508Sdim  bool evaluateBranch(const MCInst &Inst, uint64_t Addr,
140263508Sdim                      uint64_t Size, uint64_t &Target) const {
141249259Sdim    unsigned LblOperand = Inst.getOpcode() == AArch64::Bcc ? 1 : 0;
142249259Sdim    // FIXME: We only handle PCRel branches for now.
143249259Sdim    if (Info->get(Inst.getOpcode()).OpInfo[LblOperand].OperandType
144249259Sdim        != MCOI::OPERAND_PCREL)
145263508Sdim      return false;
146249259Sdim
147249259Sdim    int64_t Imm = Inst.getOperand(LblOperand).getImm();
148263508Sdim    Target = Addr + Imm;
149263508Sdim    return true;
150249259Sdim  }
151249259Sdim};
152249259Sdim
153249259Sdim}
154249259Sdim
155249259Sdimstatic MCInstrAnalysis *createAArch64MCInstrAnalysis(const MCInstrInfo *Info) {
156249259Sdim  return new AArch64MCInstrAnalysis(Info);
157249259Sdim}
158249259Sdim
159249259Sdim
160249259Sdim
161249259Sdimextern "C" void LLVMInitializeAArch64TargetMC() {
162249259Sdim  // Register the MC asm info.
163249259Sdim  RegisterMCAsmInfoFn A(TheAArch64Target, createAArch64MCAsmInfo);
164249259Sdim
165249259Sdim  // Register the MC codegen info.
166249259Sdim  TargetRegistry::RegisterMCCodeGenInfo(TheAArch64Target,
167249259Sdim                                        createAArch64MCCodeGenInfo);
168249259Sdim
169249259Sdim  // Register the MC instruction info.
170249259Sdim  TargetRegistry::RegisterMCInstrInfo(TheAArch64Target,
171249259Sdim                                      createAArch64MCInstrInfo);
172249259Sdim
173249259Sdim  // Register the MC register info.
174249259Sdim  TargetRegistry::RegisterMCRegInfo(TheAArch64Target,
175249259Sdim                                    createAArch64MCRegisterInfo);
176249259Sdim
177249259Sdim  // Register the MC subtarget info.
178249259Sdim  using AArch64_MC::createAArch64MCSubtargetInfo;
179249259Sdim  TargetRegistry::RegisterMCSubtargetInfo(TheAArch64Target,
180249259Sdim                                          createAArch64MCSubtargetInfo);
181249259Sdim
182249259Sdim  // Register the MC instruction analyzer.
183249259Sdim  TargetRegistry::RegisterMCInstrAnalysis(TheAArch64Target,
184249259Sdim                                          createAArch64MCInstrAnalysis);
185249259Sdim
186249259Sdim  // Register the MC Code Emitter
187249259Sdim  TargetRegistry::RegisterMCCodeEmitter(TheAArch64Target,
188249259Sdim                                        createAArch64MCCodeEmitter);
189249259Sdim
190249259Sdim  // Register the asm backend.
191249259Sdim  TargetRegistry::RegisterMCAsmBackend(TheAArch64Target,
192249259Sdim                                       createAArch64AsmBackend);
193249259Sdim
194249259Sdim  // Register the object streamer.
195249259Sdim  TargetRegistry::RegisterMCObjectStreamer(TheAArch64Target,
196249259Sdim                                           createMCStreamer);
197249259Sdim
198249259Sdim  // Register the MCInstPrinter.
199249259Sdim  TargetRegistry::RegisterMCInstPrinter(TheAArch64Target,
200249259Sdim                                        createAArch64MCInstPrinter);
201249259Sdim}
202