1d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers/*
2d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers * Copyright (C) 2014 The Android Open Source Project
3d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers *
4d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers * Licensed under the Apache License, Version 2.0 (the "License");
5d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers * you may not use this file except in compliance with the License.
6d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers * You may obtain a copy of the License at
7d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers *
8d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers *      http://www.apache.org/licenses/LICENSE-2.0
9d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers *
10d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers * Unless required by applicable law or agreed to in writing, software
11d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers * distributed under the License is distributed on an "AS IS" BASIS,
12d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers * See the License for the specific language governing permissions and
14d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers * limitations under the License.
15d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers */
16d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers
17d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers#include "instruction_set_features_mips.h"
18d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers
19d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers#include <fstream>
20d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers#include <sstream>
21d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers
22d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers#include "base/stringprintf.h"
23d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers#include "utils.h"  // For Trim.
24d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers
25d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogersnamespace art {
26d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers
273d12eadf67e263ebc7e533f8daa65029feb41313Douglas Leung// An enum for the Mips revision.
283d12eadf67e263ebc7e533f8daa65029feb41313Douglas Leungenum class MipsLevel {
293d12eadf67e263ebc7e533f8daa65029feb41313Douglas Leung  kBase,
303d12eadf67e263ebc7e533f8daa65029feb41313Douglas Leung  kR2,
313d12eadf67e263ebc7e533f8daa65029feb41313Douglas Leung  kR5,
323d12eadf67e263ebc7e533f8daa65029feb41313Douglas Leung  kR6
333d12eadf67e263ebc7e533f8daa65029feb41313Douglas Leung};
343d12eadf67e263ebc7e533f8daa65029feb41313Douglas Leung
353d12eadf67e263ebc7e533f8daa65029feb41313Douglas Leung#if defined(_MIPS_ARCH_MIPS32R6)
363d12eadf67e263ebc7e533f8daa65029feb41313Douglas Leungstatic constexpr MipsLevel kRuntimeMipsLevel = MipsLevel::kR6;
373d12eadf67e263ebc7e533f8daa65029feb41313Douglas Leung#elif defined(_MIPS_ARCH_MIPS32R5)
383d12eadf67e263ebc7e533f8daa65029feb41313Douglas Leungstatic constexpr MipsLevel kRuntimeMipsLevel = MipsLevel::kR5;
393d12eadf67e263ebc7e533f8daa65029feb41313Douglas Leung#elif defined(_MIPS_ARCH_MIPS32R2)
403d12eadf67e263ebc7e533f8daa65029feb41313Douglas Leungstatic constexpr MipsLevel kRuntimeMipsLevel = MipsLevel::kR2;
413d12eadf67e263ebc7e533f8daa65029feb41313Douglas Leung#else
423d12eadf67e263ebc7e533f8daa65029feb41313Douglas Leungstatic constexpr MipsLevel kRuntimeMipsLevel = MipsLevel::kBase;
433d12eadf67e263ebc7e533f8daa65029feb41313Douglas Leung#endif
443d12eadf67e263ebc7e533f8daa65029feb41313Douglas Leung
453d12eadf67e263ebc7e533f8daa65029feb41313Douglas Leungstatic void GetFlagsFromCppDefined(bool* mips_isa_gte2, bool* r6, bool* fpu_32bit) {
463d12eadf67e263ebc7e533f8daa65029feb41313Douglas Leung  // Override defaults based on compiler flags.
473d12eadf67e263ebc7e533f8daa65029feb41313Douglas Leung  if (kRuntimeMipsLevel >= MipsLevel::kR2) {
483d12eadf67e263ebc7e533f8daa65029feb41313Douglas Leung    *mips_isa_gte2 = true;
493d12eadf67e263ebc7e533f8daa65029feb41313Douglas Leung  } else {
503d12eadf67e263ebc7e533f8daa65029feb41313Douglas Leung    *mips_isa_gte2 = false;
513d12eadf67e263ebc7e533f8daa65029feb41313Douglas Leung  }
523d12eadf67e263ebc7e533f8daa65029feb41313Douglas Leung
533d12eadf67e263ebc7e533f8daa65029feb41313Douglas Leung  if (kRuntimeMipsLevel >= MipsLevel::kR5) {
543d12eadf67e263ebc7e533f8daa65029feb41313Douglas Leung    *fpu_32bit = false;
553d12eadf67e263ebc7e533f8daa65029feb41313Douglas Leung  } else {
563d12eadf67e263ebc7e533f8daa65029feb41313Douglas Leung    *fpu_32bit = true;
573d12eadf67e263ebc7e533f8daa65029feb41313Douglas Leung  }
583d12eadf67e263ebc7e533f8daa65029feb41313Douglas Leung
593d12eadf67e263ebc7e533f8daa65029feb41313Douglas Leung  if (kRuntimeMipsLevel >= MipsLevel::kR6) {
603d12eadf67e263ebc7e533f8daa65029feb41313Douglas Leung    *r6 = true;
613d12eadf67e263ebc7e533f8daa65029feb41313Douglas Leung  } else {
623d12eadf67e263ebc7e533f8daa65029feb41313Douglas Leung    *r6 = false;
633d12eadf67e263ebc7e533f8daa65029feb41313Douglas Leung  }
643d12eadf67e263ebc7e533f8daa65029feb41313Douglas Leung}
653d12eadf67e263ebc7e533f8daa65029feb41313Douglas Leung
66d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogersconst MipsInstructionSetFeatures* MipsInstructionSetFeatures::FromVariant(
67c5a3ea7522b59c18daa4325d69703a6f7f743378Andreas Gampe    const std::string& variant, std::string* error_msg ATTRIBUTE_UNUSED) {
68c5a3ea7522b59c18daa4325d69703a6f7f743378Andreas Gampe
69d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers  bool smp = true;  // Conservative default.
703d12eadf67e263ebc7e533f8daa65029feb41313Douglas Leung
713d12eadf67e263ebc7e533f8daa65029feb41313Douglas Leung  // Override defaults based on compiler flags.
723d12eadf67e263ebc7e533f8daa65029feb41313Douglas Leung  // This is needed when running ART test where the variant is not defined.
733d12eadf67e263ebc7e533f8daa65029feb41313Douglas Leung  bool fpu_32bit;
743d12eadf67e263ebc7e533f8daa65029feb41313Douglas Leung  bool mips_isa_gte2;
753d12eadf67e263ebc7e533f8daa65029feb41313Douglas Leung  bool r6;
763d12eadf67e263ebc7e533f8daa65029feb41313Douglas Leung  GetFlagsFromCppDefined(&mips_isa_gte2, &r6, &fpu_32bit);
77c5a3ea7522b59c18daa4325d69703a6f7f743378Andreas Gampe
78c5a3ea7522b59c18daa4325d69703a6f7f743378Andreas Gampe  // Override defaults based on variant string.
79c5a3ea7522b59c18daa4325d69703a6f7f743378Andreas Gampe  // Only care if it is R1, R2 or R6 and we assume all CPUs will have a FP unit.
80c5a3ea7522b59c18daa4325d69703a6f7f743378Andreas Gampe  constexpr const char* kMips32Prefix = "mips32r";
81c5a3ea7522b59c18daa4325d69703a6f7f743378Andreas Gampe  const size_t kPrefixLength = strlen(kMips32Prefix);
82c5a3ea7522b59c18daa4325d69703a6f7f743378Andreas Gampe  if (variant.compare(0, kPrefixLength, kMips32Prefix, kPrefixLength) == 0 &&
83c5a3ea7522b59c18daa4325d69703a6f7f743378Andreas Gampe      variant.size() > kPrefixLength) {
84c5a3ea7522b59c18daa4325d69703a6f7f743378Andreas Gampe    if (variant[kPrefixLength] >= '6') {
85c5a3ea7522b59c18daa4325d69703a6f7f743378Andreas Gampe      fpu_32bit = false;
86c5a3ea7522b59c18daa4325d69703a6f7f743378Andreas Gampe      r6 = true;
87c5a3ea7522b59c18daa4325d69703a6f7f743378Andreas Gampe    }
88c5a3ea7522b59c18daa4325d69703a6f7f743378Andreas Gampe    if (variant[kPrefixLength] >= '2') {
89c5a3ea7522b59c18daa4325d69703a6f7f743378Andreas Gampe      mips_isa_gte2 = true;
90c5a3ea7522b59c18daa4325d69703a6f7f743378Andreas Gampe    }
91c5a3ea7522b59c18daa4325d69703a6f7f743378Andreas Gampe  } else if (variant == "default") {
92c5a3ea7522b59c18daa4325d69703a6f7f743378Andreas Gampe    // Default variant is: smp = true, has fpu, is gte2, is not r6. This is the traditional
93c5a3ea7522b59c18daa4325d69703a6f7f743378Andreas Gampe    // setting.
94c5a3ea7522b59c18daa4325d69703a6f7f743378Andreas Gampe    mips_isa_gte2 = true;
95c5a3ea7522b59c18daa4325d69703a6f7f743378Andreas Gampe  } else {
96c5a3ea7522b59c18daa4325d69703a6f7f743378Andreas Gampe    LOG(WARNING) << "Unexpected CPU variant for Mips32 using defaults: " << variant;
97c5a3ea7522b59c18daa4325d69703a6f7f743378Andreas Gampe  }
98c5a3ea7522b59c18daa4325d69703a6f7f743378Andreas Gampe
99c5a3ea7522b59c18daa4325d69703a6f7f743378Andreas Gampe  return new MipsInstructionSetFeatures(smp, fpu_32bit, mips_isa_gte2, r6);
100d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers}
101d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers
102d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogersconst MipsInstructionSetFeatures* MipsInstructionSetFeatures::FromBitmap(uint32_t bitmap) {
103d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers  bool smp = (bitmap & kSmpBitfield) != 0;
104d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers  bool fpu_32bit = (bitmap & kFpu32Bitfield) != 0;
105d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers  bool mips_isa_gte2 = (bitmap & kIsaRevGte2Bitfield) != 0;
106c5a3ea7522b59c18daa4325d69703a6f7f743378Andreas Gampe  bool r6 = (bitmap & kR6) != 0;
107c5a3ea7522b59c18daa4325d69703a6f7f743378Andreas Gampe  return new MipsInstructionSetFeatures(smp, fpu_32bit, mips_isa_gte2, r6);
108d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers}
109d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers
110d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogersconst MipsInstructionSetFeatures* MipsInstructionSetFeatures::FromCppDefines() {
111c5a3ea7522b59c18daa4325d69703a6f7f743378Andreas Gampe  // Assume conservative defaults.
112d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers  const bool smp = true;
113d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers
1143d12eadf67e263ebc7e533f8daa65029feb41313Douglas Leung  bool fpu_32bit;
1153d12eadf67e263ebc7e533f8daa65029feb41313Douglas Leung  bool mips_isa_gte2;
1163d12eadf67e263ebc7e533f8daa65029feb41313Douglas Leung  bool r6;
1173d12eadf67e263ebc7e533f8daa65029feb41313Douglas Leung  GetFlagsFromCppDefined(&mips_isa_gte2, &r6, &fpu_32bit);
118d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers
119c5a3ea7522b59c18daa4325d69703a6f7f743378Andreas Gampe  return new MipsInstructionSetFeatures(smp, fpu_32bit, mips_isa_gte2, r6);
120d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers}
121d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers
122d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogersconst MipsInstructionSetFeatures* MipsInstructionSetFeatures::FromCpuInfo() {
123d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers  // Look in /proc/cpuinfo for features we need.  Only use this when we can guarantee that
124d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers  // the kernel puts the appropriate feature flags in here.  Sometimes it doesn't.
125c5a3ea7522b59c18daa4325d69703a6f7f743378Andreas Gampe  // Assume conservative defaults.
126d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers  bool smp = false;
127d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers
1283d12eadf67e263ebc7e533f8daa65029feb41313Douglas Leung  bool fpu_32bit;
1293d12eadf67e263ebc7e533f8daa65029feb41313Douglas Leung  bool mips_isa_gte2;
1303d12eadf67e263ebc7e533f8daa65029feb41313Douglas Leung  bool r6;
1313d12eadf67e263ebc7e533f8daa65029feb41313Douglas Leung  GetFlagsFromCppDefined(&mips_isa_gte2, &r6, &fpu_32bit);
132d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers
133d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers  std::ifstream in("/proc/cpuinfo");
134d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers  if (!in.fail()) {
135d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers    while (!in.eof()) {
136d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers      std::string line;
137d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers      std::getline(in, line);
138d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers      if (!in.eof()) {
139d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers        LOG(INFO) << "cpuinfo line: " << line;
140d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers        if (line.find("processor") != std::string::npos && line.find(": 1") != std::string::npos) {
141d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers          smp = true;
142d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers        }
143d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers      }
144d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers    }
145d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers    in.close();
146d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers  } else {
147d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers    LOG(ERROR) << "Failed to open /proc/cpuinfo";
148d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers  }
149c5a3ea7522b59c18daa4325d69703a6f7f743378Andreas Gampe  return new MipsInstructionSetFeatures(smp, fpu_32bit, mips_isa_gte2, r6);
150d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers}
151d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers
152d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogersconst MipsInstructionSetFeatures* MipsInstructionSetFeatures::FromHwcap() {
153d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers  UNIMPLEMENTED(WARNING);
154d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers  return FromCppDefines();
155d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers}
156d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers
157d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogersconst MipsInstructionSetFeatures* MipsInstructionSetFeatures::FromAssembly() {
158d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers  UNIMPLEMENTED(WARNING);
159d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers  return FromCppDefines();
160d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers}
161d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers
162d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogersbool MipsInstructionSetFeatures::Equals(const InstructionSetFeatures* other) const {
163d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers  if (kMips != other->GetInstructionSet()) {
164d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers    return false;
165d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers  }
166d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers  const MipsInstructionSetFeatures* other_as_mips = other->AsMipsInstructionSetFeatures();
167d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers  return (IsSmp() == other->IsSmp()) &&
168d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers      (fpu_32bit_ == other_as_mips->fpu_32bit_) &&
169c5a3ea7522b59c18daa4325d69703a6f7f743378Andreas Gampe      (mips_isa_gte2_ == other_as_mips->mips_isa_gte2_) &&
170c5a3ea7522b59c18daa4325d69703a6f7f743378Andreas Gampe      (r6_ == other_as_mips->r6_);
171d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers}
172d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers
173d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogersuint32_t MipsInstructionSetFeatures::AsBitmap() const {
174d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers  return (IsSmp() ? kSmpBitfield : 0) |
175d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers      (fpu_32bit_ ? kFpu32Bitfield : 0) |
176c5a3ea7522b59c18daa4325d69703a6f7f743378Andreas Gampe      (mips_isa_gte2_ ? kIsaRevGte2Bitfield : 0) |
177c5a3ea7522b59c18daa4325d69703a6f7f743378Andreas Gampe      (r6_ ? kR6 : 0);
178d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers}
179d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers
180d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogersstd::string MipsInstructionSetFeatures::GetFeatureString() const {
181d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers  std::string result;
182d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers  if (IsSmp()) {
183d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers    result += "smp";
184d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers  } else {
185d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers    result += "-smp";
186d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers  }
187d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers  if (fpu_32bit_) {
188d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers    result += ",fpu32";
189d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers  } else {
190d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers    result += ",-fpu32";
191d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers  }
192d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers  if (mips_isa_gte2_) {
193d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers    result += ",mips2";
194d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers  } else {
195d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers    result += ",-mips2";
196d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers  }
197c5a3ea7522b59c18daa4325d69703a6f7f743378Andreas Gampe  if (r6_) {
198c5a3ea7522b59c18daa4325d69703a6f7f743378Andreas Gampe    result += ",r6";
199c5a3ea7522b59c18daa4325d69703a6f7f743378Andreas Gampe  }  // Suppress non-r6.
200d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers  return result;
201d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers}
202d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers
203d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogersconst InstructionSetFeatures* MipsInstructionSetFeatures::AddFeaturesFromSplitString(
204d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers    const bool smp, const std::vector<std::string>& features, std::string* error_msg) const {
205d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers  bool fpu_32bit = fpu_32bit_;
206d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers  bool mips_isa_gte2 = mips_isa_gte2_;
207c5a3ea7522b59c18daa4325d69703a6f7f743378Andreas Gampe  bool r6 = r6_;
208d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers  for (auto i = features.begin(); i != features.end(); i++) {
209d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers    std::string feature = Trim(*i);
210d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers    if (feature == "fpu32") {
211d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers      fpu_32bit = true;
212d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers    } else if (feature == "-fpu32") {
213d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers      fpu_32bit = false;
214d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers    } else if (feature == "mips2") {
215d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers      mips_isa_gte2 = true;
216d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers    } else if (feature == "-mips2") {
217d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers      mips_isa_gte2 = false;
218c5a3ea7522b59c18daa4325d69703a6f7f743378Andreas Gampe    } else if (feature == "r6") {
219c5a3ea7522b59c18daa4325d69703a6f7f743378Andreas Gampe      r6 = true;
220c5a3ea7522b59c18daa4325d69703a6f7f743378Andreas Gampe    } else if (feature == "-r6") {
221c5a3ea7522b59c18daa4325d69703a6f7f743378Andreas Gampe      r6 = false;
222d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers    } else {
223d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers      *error_msg = StringPrintf("Unknown instruction set feature: '%s'", feature.c_str());
224d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers      return nullptr;
225d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers    }
226d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers  }
227c5a3ea7522b59c18daa4325d69703a6f7f743378Andreas Gampe  return new MipsInstructionSetFeatures(smp, fpu_32bit, mips_isa_gte2, r6);
228d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers}
229d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers
230d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers}  // namespace art
231