summaryrefslogtreecommitdiff
path: root/lib/Target/Mips/MipsSubtarget.cpp
blob: 259e68df325c408fe2b30038cc62ef0a1405e292 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
//===-- MipsSubtarget.cpp - Mips Subtarget Information --------------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file implements the Mips specific subclass of TargetSubtargetInfo.
//
//===----------------------------------------------------------------------===//

#define DEBUG_TYPE "mips-subtarget"

#include "MipsMachineFunction.h"
#include "MipsSubtarget.h"
#include "MipsTargetMachine.h"
#include "Mips.h"
#include "MipsRegisterInfo.h"
#include "llvm/IR/Attributes.h"
#include "llvm/IR/Function.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/TargetRegistry.h"
#include "llvm/Support/raw_ostream.h"

#define GET_SUBTARGETINFO_TARGET_DESC
#define GET_SUBTARGETINFO_CTOR
#include "MipsGenSubtargetInfo.inc"


using namespace llvm;

// FIXME: Maybe this should be on by default when Mips16 is specified
//
static cl::opt<bool> Mixed16_32(
  "mips-mixed-16-32",
  cl::init(false),
  cl::desc("Allow for a mixture of Mips16 "
           "and Mips32 code in a single source file"),
  cl::Hidden);

static cl::opt<bool> Mips_Os16(
  "mips-os16",
  cl::init(false),
  cl::desc("Compile all functions that don' use "
           "floating point as Mips 16"),
  cl::Hidden);

static cl::opt<bool>
Mips16HardFloat("mips16-hard-float", cl::NotHidden,
                cl::desc("MIPS: mips16 hard float enable."),
                cl::init(false));

void MipsSubtarget::anchor() { }

MipsSubtarget::MipsSubtarget(const std::string &TT, const std::string &CPU,
                             const std::string &FS, bool little,
                             Reloc::Model _RM, MipsTargetMachine *_TM) :
  MipsGenSubtargetInfo(TT, CPU, FS),
  MipsArchVersion(Mips32), MipsABI(UnknownABI), IsLittle(little),
  IsSingleFloat(false), IsFP64bit(false), IsGP64bit(false), HasVFPU(false),
  IsLinux(true), HasSEInReg(false), HasCondMov(false), HasSwap(false),
  HasBitCount(false), HasFPIdx(false),
  InMips16Mode(false), InMips16HardFloat(Mips16HardFloat),
  InMicroMipsMode(false), HasDSP(false), HasDSPR2(false),
  AllowMixed16_32(Mixed16_32 | Mips_Os16), Os16(Mips_Os16),
  RM(_RM), OverrideMode(NoOverride), TM(_TM)
{
  std::string CPUName = CPU;
  if (CPUName.empty())
    CPUName = "mips32";

  // Parse features string.
  ParseSubtargetFeatures(CPUName, FS);

  PreviousInMips16Mode = InMips16Mode;

  // Initialize scheduling itinerary for the specified CPU.
  InstrItins = getInstrItineraryForCPU(CPUName);

  // Set MipsABI if it hasn't been set yet.
  if (MipsABI == UnknownABI)
    MipsABI = hasMips64() ? N64 : O32;

  // Check if Architecture and ABI are compatible.
  assert(((!hasMips64() && (isABI_O32() || isABI_EABI())) ||
          (hasMips64() && (isABI_N32() || isABI_N64()))) &&
         "Invalid  Arch & ABI pair.");

  // Is the target system Linux ?
  if (TT.find("linux") == std::string::npos)
    IsLinux = false;

  // Set UseSmallSection.
  UseSmallSection = !IsLinux && (RM == Reloc::Static);
}

bool
MipsSubtarget::enablePostRAScheduler(CodeGenOpt::Level OptLevel,
                                    TargetSubtargetInfo::AntiDepBreakMode &Mode,
                                     RegClassVector &CriticalPathRCs) const {
  Mode = TargetSubtargetInfo::ANTIDEP_NONE;
  CriticalPathRCs.clear();
  CriticalPathRCs.push_back(hasMips64() ?
                            &Mips::CPU64RegsRegClass : &Mips::CPURegsRegClass);
  return OptLevel >= CodeGenOpt::Aggressive;
}

//FIXME: This logic for reseting the subtarget along with
// the helper classes can probably be simplified but there are a lot of
// cases so we will defer rewriting this to later.
//
void MipsSubtarget::resetSubtarget(MachineFunction *MF) {
  bool ChangeToMips16 = false, ChangeToNoMips16 = false;
  DEBUG(dbgs() << "resetSubtargetFeatures" << "\n");
  AttributeSet FnAttrs = MF->getFunction()->getAttributes();
  ChangeToMips16 = FnAttrs.hasAttribute(AttributeSet::FunctionIndex,
                                        "mips16");
  ChangeToNoMips16 = FnAttrs.hasAttribute(AttributeSet::FunctionIndex,
                                        "nomips16");
  assert (!(ChangeToMips16 & ChangeToNoMips16) &&
          "mips16 and nomips16 specified on the same function");
  if (ChangeToMips16) {
    if (PreviousInMips16Mode)
      return;
    OverrideMode = Mips16Override;
    PreviousInMips16Mode = true;
    TM->setHelperClassesMips16();
    return;
  } else if (ChangeToNoMips16) {
    if (!PreviousInMips16Mode)
      return;
    OverrideMode = NoMips16Override;
    PreviousInMips16Mode = false;
    TM->setHelperClassesMipsSE();
    return;
  } else {
    if (OverrideMode == NoOverride)
      return;
    OverrideMode = NoOverride;
    DEBUG(dbgs() << "back to default" << "\n");
    if (inMips16Mode() && !PreviousInMips16Mode) {
      TM->setHelperClassesMips16();
      PreviousInMips16Mode = true;
    } else if (!inMips16Mode() && PreviousInMips16Mode) {
      TM->setHelperClassesMipsSE();
      PreviousInMips16Mode = false;
    }
    return;
  }
}