1//===-- MipsMCTargetDesc.cpp - Mips 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 Mips specific target descriptions.
10//
11//===----------------------------------------------------------------------===//
12
13#include "MipsMCTargetDesc.h"
14#include "MipsAsmBackend.h"
15#include "MipsBaseInfo.h"
16#include "MipsELFStreamer.h"
17#include "MipsInstPrinter.h"
18#include "MipsMCAsmInfo.h"
19#include "MipsMCNaCl.h"
20#include "MipsTargetStreamer.h"
21#include "TargetInfo/MipsTargetInfo.h"
22#include "llvm/ADT/Triple.h"
23#include "llvm/MC/MCCodeEmitter.h"
24#include "llvm/MC/MCELFStreamer.h"
25#include "llvm/MC/MCInstrAnalysis.h"
26#include "llvm/MC/MCInstrInfo.h"
27#include "llvm/MC/MCObjectWriter.h"
28#include "llvm/MC/MCRegisterInfo.h"
29#include "llvm/MC/MCSubtargetInfo.h"
30#include "llvm/MC/MCSymbol.h"
31#include "llvm/MC/MachineLocation.h"
32#include "llvm/Support/ErrorHandling.h"
33#include "llvm/Support/FormattedStream.h"
34#include "llvm/Support/TargetRegistry.h"
35
36using namespace llvm;
37
38#define GET_INSTRINFO_MC_DESC
39#include "MipsGenInstrInfo.inc"
40
41#define GET_SUBTARGETINFO_MC_DESC
42#include "MipsGenSubtargetInfo.inc"
43
44#define GET_REGINFO_MC_DESC
45#include "MipsGenRegisterInfo.inc"
46
47/// Select the Mips CPU for the given triple and cpu name.
48StringRef MIPS_MC::selectMipsCPU(const Triple &TT, StringRef CPU) {
49  if (CPU.empty() || CPU == "generic") {
50    if (TT.getSubArch() == llvm::Triple::MipsSubArch_r6) {
51      if (TT.isMIPS32())
52        CPU = "mips32r6";
53      else
54        CPU = "mips64r6";
55    } else {
56      if (TT.isMIPS32())
57        CPU = "mips32";
58      else
59        CPU = "mips64";
60    }
61  }
62  return CPU;
63}
64
65static MCInstrInfo *createMipsMCInstrInfo() {
66  MCInstrInfo *X = new MCInstrInfo();
67  InitMipsMCInstrInfo(X);
68  return X;
69}
70
71static MCRegisterInfo *createMipsMCRegisterInfo(const Triple &TT) {
72  MCRegisterInfo *X = new MCRegisterInfo();
73  InitMipsMCRegisterInfo(X, Mips::RA);
74  return X;
75}
76
77static MCSubtargetInfo *createMipsMCSubtargetInfo(const Triple &TT,
78                                                  StringRef CPU, StringRef FS) {
79  CPU = MIPS_MC::selectMipsCPU(TT, CPU);
80  return createMipsMCSubtargetInfoImpl(TT, CPU, FS);
81}
82
83static MCAsmInfo *createMipsMCAsmInfo(const MCRegisterInfo &MRI,
84                                      const Triple &TT,
85                                      const MCTargetOptions &Options) {
86  MCAsmInfo *MAI = new MipsMCAsmInfo(TT, Options);
87
88  unsigned SP = MRI.getDwarfRegNum(Mips::SP, true);
89  MCCFIInstruction Inst = MCCFIInstruction::createDefCfaRegister(nullptr, SP);
90  MAI->addInitialFrameState(Inst);
91
92  return MAI;
93}
94
95static MCInstPrinter *createMipsMCInstPrinter(const Triple &T,
96                                              unsigned SyntaxVariant,
97                                              const MCAsmInfo &MAI,
98                                              const MCInstrInfo &MII,
99                                              const MCRegisterInfo &MRI) {
100  return new MipsInstPrinter(MAI, MII, MRI);
101}
102
103static MCStreamer *createMCStreamer(const Triple &T, MCContext &Context,
104                                    std::unique_ptr<MCAsmBackend> &&MAB,
105                                    std::unique_ptr<MCObjectWriter> &&OW,
106                                    std::unique_ptr<MCCodeEmitter> &&Emitter,
107                                    bool RelaxAll) {
108  MCStreamer *S;
109  if (!T.isOSNaCl())
110    S = createMipsELFStreamer(Context, std::move(MAB), std::move(OW),
111                              std::move(Emitter), RelaxAll);
112  else
113    S = createMipsNaClELFStreamer(Context, std::move(MAB), std::move(OW),
114                                  std::move(Emitter), RelaxAll);
115  return S;
116}
117
118static MCTargetStreamer *createMipsAsmTargetStreamer(MCStreamer &S,
119                                                     formatted_raw_ostream &OS,
120                                                     MCInstPrinter *InstPrint,
121                                                     bool isVerboseAsm) {
122  return new MipsTargetAsmStreamer(S, OS);
123}
124
125static MCTargetStreamer *createMipsNullTargetStreamer(MCStreamer &S) {
126  return new MipsTargetStreamer(S);
127}
128
129static MCTargetStreamer *
130createMipsObjectTargetStreamer(MCStreamer &S, const MCSubtargetInfo &STI) {
131  return new MipsTargetELFStreamer(S, STI);
132}
133
134namespace {
135
136class MipsMCInstrAnalysis : public MCInstrAnalysis {
137public:
138  MipsMCInstrAnalysis(const MCInstrInfo *Info) : MCInstrAnalysis(Info) {}
139
140  bool evaluateBranch(const MCInst &Inst, uint64_t Addr, uint64_t Size,
141                      uint64_t &Target) const override {
142    unsigned NumOps = Inst.getNumOperands();
143    if (NumOps == 0)
144      return false;
145    switch (Info->get(Inst.getOpcode()).OpInfo[NumOps - 1].OperandType) {
146    case MCOI::OPERAND_UNKNOWN:
147    case MCOI::OPERAND_IMMEDIATE: {
148      // j, jal, jalx, jals
149      // Absolute branch within the current 256 MB-aligned region
150      uint64_t Region = Addr & ~uint64_t(0xfffffff);
151      Target = Region + Inst.getOperand(NumOps - 1).getImm();
152      return true;
153    }
154    case MCOI::OPERAND_PCREL:
155      // b, beq ...
156      Target = Addr + Inst.getOperand(NumOps - 1).getImm();
157      return true;
158    default:
159      return false;
160    }
161  }
162};
163}
164
165static MCInstrAnalysis *createMipsMCInstrAnalysis(const MCInstrInfo *Info) {
166  return new MipsMCInstrAnalysis(Info);
167}
168
169extern "C" LLVM_EXTERNAL_VISIBILITY void LLVMInitializeMipsTargetMC() {
170  for (Target *T : {&getTheMipsTarget(), &getTheMipselTarget(),
171                    &getTheMips64Target(), &getTheMips64elTarget()}) {
172    // Register the MC asm info.
173    RegisterMCAsmInfoFn X(*T, createMipsMCAsmInfo);
174
175    // Register the MC instruction info.
176    TargetRegistry::RegisterMCInstrInfo(*T, createMipsMCInstrInfo);
177
178    // Register the MC register info.
179    TargetRegistry::RegisterMCRegInfo(*T, createMipsMCRegisterInfo);
180
181    // Register the elf streamer.
182    TargetRegistry::RegisterELFStreamer(*T, createMCStreamer);
183
184    // Register the asm target streamer.
185    TargetRegistry::RegisterAsmTargetStreamer(*T, createMipsAsmTargetStreamer);
186
187    TargetRegistry::RegisterNullTargetStreamer(*T,
188                                               createMipsNullTargetStreamer);
189
190    // Register the MC subtarget info.
191    TargetRegistry::RegisterMCSubtargetInfo(*T, createMipsMCSubtargetInfo);
192
193    // Register the MC instruction analyzer.
194    TargetRegistry::RegisterMCInstrAnalysis(*T, createMipsMCInstrAnalysis);
195
196    // Register the MCInstPrinter.
197    TargetRegistry::RegisterMCInstPrinter(*T, createMipsMCInstPrinter);
198
199    TargetRegistry::RegisterObjectTargetStreamer(
200        *T, createMipsObjectTargetStreamer);
201
202    // Register the asm backend.
203    TargetRegistry::RegisterMCAsmBackend(*T, createMipsAsmBackend);
204  }
205
206  // Register the MC Code Emitter
207  for (Target *T : {&getTheMipsTarget(), &getTheMips64Target()})
208    TargetRegistry::RegisterMCCodeEmitter(*T, createMipsMCCodeEmitterEB);
209
210  for (Target *T : {&getTheMipselTarget(), &getTheMips64elTarget()})
211    TargetRegistry::RegisterMCCodeEmitter(*T, createMipsMCCodeEmitterEL);
212}
213