instruction_set_features_mips.cc revision d582fa4ea62083a7598dded5b82dc2198b3daac7
1/*
2 * Copyright (C) 2014 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#include "instruction_set_features_mips.h"
18
19#include <fstream>
20#include <sstream>
21
22#include "base/stringprintf.h"
23#include "utils.h"  // For Trim.
24
25namespace art {
26
27const MipsInstructionSetFeatures* MipsInstructionSetFeatures::FromVariant(
28    const std::string& variant ATTRIBUTE_UNUSED, std::string* error_msg ATTRIBUTE_UNUSED) {
29  if (variant != "default") {
30    std::ostringstream os;
31    LOG(WARNING) << "Unexpected CPU variant for Mips using defaults: " << variant;
32  }
33  bool smp = true;  // Conservative default.
34  bool fpu_32bit = true;
35  bool mips_isa_gte2 = true;
36  return new MipsInstructionSetFeatures(smp, fpu_32bit, mips_isa_gte2);
37}
38
39const MipsInstructionSetFeatures* MipsInstructionSetFeatures::FromBitmap(uint32_t bitmap) {
40  bool smp = (bitmap & kSmpBitfield) != 0;
41  bool fpu_32bit = (bitmap & kFpu32Bitfield) != 0;
42  bool mips_isa_gte2 = (bitmap & kIsaRevGte2Bitfield) != 0;
43  return new MipsInstructionSetFeatures(smp, fpu_32bit, mips_isa_gte2);
44}
45
46const MipsInstructionSetFeatures* MipsInstructionSetFeatures::FromCppDefines() {
47#if defined(HAVE_ANDROID_OS) && (ANDROID_SMP == 0)
48  const bool smp = false;
49#else
50  const bool smp = true;
51#endif
52
53  // TODO: here we assume the FPU is always 32-bit.
54  const bool fpu_32bit = true;
55
56#if __mips_isa_rev >= 2
57  const bool mips_isa_gte2 = true;
58#else
59  const bool mips_isa_gte2 = false;
60#endif
61
62  return new MipsInstructionSetFeatures(smp, fpu_32bit, mips_isa_gte2);
63}
64
65const MipsInstructionSetFeatures* MipsInstructionSetFeatures::FromCpuInfo() {
66  // Look in /proc/cpuinfo for features we need.  Only use this when we can guarantee that
67  // the kernel puts the appropriate feature flags in here.  Sometimes it doesn't.
68  bool smp = false;
69
70  // TODO: here we assume the FPU is always 32-bit.
71  const bool fpu_32bit = true;
72
73  // TODO: here we assume all MIPS processors are >= v2.
74#if __mips_isa_rev >= 2
75  const bool mips_isa_gte2 = true;
76#else
77  const bool mips_isa_gte2 = false;
78#endif
79
80  std::ifstream in("/proc/cpuinfo");
81  if (!in.fail()) {
82    while (!in.eof()) {
83      std::string line;
84      std::getline(in, line);
85      if (!in.eof()) {
86        LOG(INFO) << "cpuinfo line: " << line;
87        if (line.find("processor") != std::string::npos && line.find(": 1") != std::string::npos) {
88          smp = true;
89        }
90      }
91    }
92    in.close();
93  } else {
94    LOG(ERROR) << "Failed to open /proc/cpuinfo";
95  }
96  return new MipsInstructionSetFeatures(smp, fpu_32bit, mips_isa_gte2);
97}
98
99const MipsInstructionSetFeatures* MipsInstructionSetFeatures::FromHwcap() {
100  UNIMPLEMENTED(WARNING);
101  return FromCppDefines();
102}
103
104const MipsInstructionSetFeatures* MipsInstructionSetFeatures::FromAssembly() {
105  UNIMPLEMENTED(WARNING);
106  return FromCppDefines();
107}
108
109bool MipsInstructionSetFeatures::Equals(const InstructionSetFeatures* other) const {
110  if (kMips != other->GetInstructionSet()) {
111    return false;
112  }
113  const MipsInstructionSetFeatures* other_as_mips = other->AsMipsInstructionSetFeatures();
114  return (IsSmp() == other->IsSmp()) &&
115      (fpu_32bit_ == other_as_mips->fpu_32bit_) &&
116      (mips_isa_gte2_ == other_as_mips->mips_isa_gte2_);
117}
118
119uint32_t MipsInstructionSetFeatures::AsBitmap() const {
120  return (IsSmp() ? kSmpBitfield : 0) |
121      (fpu_32bit_ ? kFpu32Bitfield : 0) |
122      (mips_isa_gte2_ ? kIsaRevGte2Bitfield : 0);
123}
124
125std::string MipsInstructionSetFeatures::GetFeatureString() const {
126  std::string result;
127  if (IsSmp()) {
128    result += "smp";
129  } else {
130    result += "-smp";
131  }
132  if (fpu_32bit_) {
133    result += ",fpu32";
134  } else {
135    result += ",-fpu32";
136  }
137  if (mips_isa_gte2_) {
138    result += ",mips2";
139  } else {
140    result += ",-mips2";
141  }
142  return result;
143}
144
145const InstructionSetFeatures* MipsInstructionSetFeatures::AddFeaturesFromSplitString(
146    const bool smp, const std::vector<std::string>& features, std::string* error_msg) const {
147  bool fpu_32bit = fpu_32bit_;
148  bool mips_isa_gte2 = mips_isa_gte2_;
149  for (auto i = features.begin(); i != features.end(); i++) {
150    std::string feature = Trim(*i);
151    if (feature == "fpu32") {
152      fpu_32bit = true;
153    } else if (feature == "-fpu32") {
154      fpu_32bit = false;
155    } else if (feature == "mips2") {
156      mips_isa_gte2 = true;
157    } else if (feature == "-mips2") {
158      mips_isa_gte2 = false;
159    } else {
160      *error_msg = StringPrintf("Unknown instruction set feature: '%s'", feature.c_str());
161      return nullptr;
162    }
163  }
164  return new MipsInstructionSetFeatures(smp, fpu_32bit, mips_isa_gte2);
165}
166
167}  // namespace art
168