1//===-- MipsSubtarget.cpp - Mips Subtarget Information --------------------===//
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 implements the Mips specific subclass of TargetSubtargetInfo.
11//
12//===----------------------------------------------------------------------===//
13
14#include "MipsMachineFunction.h"
15#include "Mips.h"
16#include "MipsRegisterInfo.h"
17#include "MipsSubtarget.h"
18#include "MipsTargetMachine.h"
19#include "llvm/IR/Attributes.h"
20#include "llvm/IR/Function.h"
21#include "llvm/Support/CommandLine.h"
22#include "llvm/Support/Debug.h"
23#include "llvm/Support/TargetRegistry.h"
24#include "llvm/Support/raw_ostream.h"
25
26using namespace llvm;
27
28#define DEBUG_TYPE "mips-subtarget"
29
30#define GET_SUBTARGETINFO_TARGET_DESC
31#define GET_SUBTARGETINFO_CTOR
32#include "MipsGenSubtargetInfo.inc"
33
34// FIXME: Maybe this should be on by default when Mips16 is specified
35//
36static cl::opt<bool>
37    Mixed16_32("mips-mixed-16-32", cl::init(false),
38               cl::desc("Allow for a mixture of Mips16 "
39                        "and Mips32 code in a single output file"),
40               cl::Hidden);
41
42static cl::opt<bool> Mips_Os16("mips-os16", cl::init(false),
43                               cl::desc("Compile all functions that don't use "
44                                        "floating point as Mips 16"),
45                               cl::Hidden);
46
47static cl::opt<bool> Mips16HardFloat("mips16-hard-float", cl::NotHidden,
48                                     cl::desc("Enable mips16 hard float."),
49                                     cl::init(false));
50
51static cl::opt<bool>
52    Mips16ConstantIslands("mips16-constant-islands", cl::NotHidden,
53                          cl::desc("Enable mips16 constant islands."),
54                          cl::init(true));
55
56static cl::opt<bool>
57    GPOpt("mgpopt", cl::Hidden,
58          cl::desc("Enable gp-relative addressing of mips small data items"));
59
60void MipsSubtarget::anchor() { }
61
62MipsSubtarget::MipsSubtarget(const Triple &TT, const std::string &CPU,
63                             const std::string &FS, bool little,
64                             const MipsTargetMachine &TM)
65    : MipsGenSubtargetInfo(TT, CPU, FS), MipsArchVersion(MipsDefault),
66      IsLittle(little), IsSoftFloat(false), IsSingleFloat(false), IsFPXX(false),
67      NoABICalls(false), IsFP64bit(false), UseOddSPReg(true),
68      IsNaN2008bit(false), IsGP64bit(false), HasVFPU(false), HasCnMips(false),
69      HasMips3_32(false), HasMips3_32r2(false), HasMips4_32(false),
70      HasMips4_32r2(false), HasMips5_32r2(false), InMips16Mode(false),
71      InMips16HardFloat(Mips16HardFloat), InMicroMipsMode(false), HasDSP(false),
72      HasDSPR2(false), HasDSPR3(false), AllowMixed16_32(Mixed16_32 | Mips_Os16),
73      Os16(Mips_Os16), HasMSA(false), UseTCCInDIV(false), HasEVA(false), TM(TM),
74      TargetTriple(TT), TSInfo(),
75      InstrInfo(
76          MipsInstrInfo::create(initializeSubtargetDependencies(CPU, FS, TM))),
77      FrameLowering(MipsFrameLowering::create(*this)),
78      TLInfo(MipsTargetLowering::create(TM, *this)) {
79
80  PreviousInMips16Mode = InMips16Mode;
81
82  if (MipsArchVersion == MipsDefault)
83    MipsArchVersion = Mips32;
84
85  // Don't even attempt to generate code for MIPS-I and MIPS-V. They have not
86  // been tested and currently exist for the integrated assembler only.
87  if (MipsArchVersion == Mips1)
88    report_fatal_error("Code generation for MIPS-I is not implemented", false);
89  if (MipsArchVersion == Mips5)
90    report_fatal_error("Code generation for MIPS-V is not implemented", false);
91
92  // Check if Architecture and ABI are compatible.
93  assert(((!isGP64bit() && isABI_O32()) ||
94          (isGP64bit() && (isABI_N32() || isABI_N64()))) &&
95         "Invalid  Arch & ABI pair.");
96
97  if (hasMSA() && !isFP64bit())
98    report_fatal_error("MSA requires a 64-bit FPU register file (FR=1 mode). "
99                       "See -mattr=+fp64.",
100                       false);
101
102  if (!isABI_O32() && !useOddSPReg())
103    report_fatal_error("-mattr=+nooddspreg requires the O32 ABI.", false);
104
105  if (IsFPXX && (isABI_N32() || isABI_N64()))
106    report_fatal_error("FPXX is not permitted for the N32/N64 ABI's.", false);
107
108  if (hasMips32r6()) {
109    StringRef ISA = hasMips64r6() ? "MIPS64r6" : "MIPS32r6";
110
111    assert(isFP64bit());
112    assert(isNaN2008());
113    if (hasDSP())
114      report_fatal_error(ISA + " is not compatible with the DSP ASE", false);
115  }
116
117  if (NoABICalls && TM.isPositionIndependent())
118    report_fatal_error("position-independent code requires '-mabicalls'");
119
120  // Set UseSmallSection.
121  UseSmallSection = GPOpt;
122  if (!NoABICalls && GPOpt) {
123    errs() << "warning: cannot use small-data accesses for '-mabicalls'"
124           << "\n";
125    UseSmallSection = false;
126  }
127}
128
129bool MipsSubtarget::isPositionIndependent() const {
130  return TM.isPositionIndependent();
131}
132
133/// This overrides the PostRAScheduler bit in the SchedModel for any CPU.
134bool MipsSubtarget::enablePostRAScheduler() const { return true; }
135
136void MipsSubtarget::getCriticalPathRCs(RegClassVector &CriticalPathRCs) const {
137  CriticalPathRCs.clear();
138  CriticalPathRCs.push_back(isGP64bit() ?
139                            &Mips::GPR64RegClass : &Mips::GPR32RegClass);
140}
141
142CodeGenOpt::Level MipsSubtarget::getOptLevelToEnablePostRAScheduler() const {
143  return CodeGenOpt::Aggressive;
144}
145
146MipsSubtarget &
147MipsSubtarget::initializeSubtargetDependencies(StringRef CPU, StringRef FS,
148                                               const TargetMachine &TM) {
149  std::string CPUName = MIPS_MC::selectMipsCPU(TM.getTargetTriple(), CPU);
150
151  // Parse features string.
152  ParseSubtargetFeatures(CPUName, FS);
153  // Initialize scheduling itinerary for the specified CPU.
154  InstrItins = getInstrItineraryForCPU(CPUName);
155
156  if (InMips16Mode && !IsSoftFloat)
157    InMips16HardFloat = true;
158
159  return *this;
160}
161
162bool MipsSubtarget::useConstantIslands() {
163  DEBUG(dbgs() << "use constant islands " << Mips16ConstantIslands << "\n");
164  return Mips16ConstantIslands;
165}
166
167Reloc::Model MipsSubtarget::getRelocationModel() const {
168  return TM.getRelocationModel();
169}
170
171bool MipsSubtarget::isABI_N64() const { return getABI().IsN64(); }
172bool MipsSubtarget::isABI_N32() const { return getABI().IsN32(); }
173bool MipsSubtarget::isABI_O32() const { return getABI().IsO32(); }
174const MipsABIInfo &MipsSubtarget::getABI() const { return TM.getABI(); }
175