• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 <android-base/stringprintf.h>
23 #include <android-base/strings.h>
24 
25 #include "base/stl_util.h"
26 
27 namespace art {
28 
29 using android::base::StringPrintf;
30 
31 // An enum for the Mips revision.
32 enum class MipsLevel {
33   kBase,
34   kR2,
35   kR5,
36   kR6
37 };
38 
39 #if defined(_MIPS_ARCH_MIPS32R6)
40 static constexpr MipsLevel kRuntimeMipsLevel = MipsLevel::kR6;
41 #elif defined(_MIPS_ARCH_MIPS32R5)
42 static constexpr MipsLevel kRuntimeMipsLevel = MipsLevel::kR5;
43 #elif defined(_MIPS_ARCH_MIPS32R2)
44 static constexpr MipsLevel kRuntimeMipsLevel = MipsLevel::kR2;
45 #else
46 static constexpr MipsLevel kRuntimeMipsLevel = MipsLevel::kBase;
47 #endif
48 
GetFlagsFromCppDefined(bool * mips_isa_gte2,bool * r6,bool * fpu_32bit,bool * msa)49 static void GetFlagsFromCppDefined(bool* mips_isa_gte2, bool* r6, bool* fpu_32bit, bool* msa) {
50   // Override defaults based on compiler flags.
51   if (kRuntimeMipsLevel >= MipsLevel::kR2) {
52     *mips_isa_gte2 = true;
53   } else {
54     *mips_isa_gte2 = false;
55   }
56 
57   if (kRuntimeMipsLevel >= MipsLevel::kR5) {
58     *fpu_32bit = false;
59     *msa = true;
60   } else {
61     *fpu_32bit = true;
62     *msa = false;
63   }
64 
65   if (kRuntimeMipsLevel >= MipsLevel::kR6) {
66     *r6 = true;
67   } else {
68     *r6 = false;
69   }
70 }
71 
FromVariant(const std::string & variant,std::string * error_msg ATTRIBUTE_UNUSED)72 MipsFeaturesUniquePtr MipsInstructionSetFeatures::FromVariant(
73     const std::string& variant, std::string* error_msg ATTRIBUTE_UNUSED) {
74 
75   // Override defaults based on compiler flags.
76   // This is needed when running ART test where the variant is not defined.
77   bool fpu_32bit;
78   bool mips_isa_gte2;
79   bool r6;
80   bool msa;
81   GetFlagsFromCppDefined(&mips_isa_gte2, &r6, &fpu_32bit, &msa);
82 
83   // Override defaults based on variant string.
84   // Only care if it is R1, R2, R5 or R6 and we assume all CPUs will have a FP unit.
85   constexpr const char* kMips32Prefix = "mips32r";
86   const size_t kPrefixLength = strlen(kMips32Prefix);
87   if (variant.compare(0, kPrefixLength, kMips32Prefix, kPrefixLength) == 0 &&
88       variant.size() > kPrefixLength) {
89     r6 = (variant[kPrefixLength] >= '6');
90     fpu_32bit = (variant[kPrefixLength] < '5');
91     mips_isa_gte2 = (variant[kPrefixLength] >= '2');
92     msa = (variant[kPrefixLength] >= '5');
93   } else if (variant == "default") {
94     // Default variant has FPU, is gte2. This is the traditional setting.
95     //
96     // Note, we get FPU bitness and R6-ness from the build (using cpp defines, see above)
97     // and don't override them because many things depend on the "default" variant being
98     // sufficient for most purposes. That is, "default" should work for both R2 and R6.
99     // Use "mips32r#" to get a specific configuration, possibly not matching the runtime
100     // ISA (e.g. for ISA-specific testing of dex2oat internals).
101     mips_isa_gte2 = true;
102   } else {
103     LOG(WARNING) << "Unexpected CPU variant for Mips32 using defaults: " << variant;
104   }
105 
106   return MipsFeaturesUniquePtr(new MipsInstructionSetFeatures(fpu_32bit, mips_isa_gte2, r6, msa));
107 }
108 
FromBitmap(uint32_t bitmap)109 MipsFeaturesUniquePtr MipsInstructionSetFeatures::FromBitmap(uint32_t bitmap) {
110   bool fpu_32bit = (bitmap & kFpu32Bitfield) != 0;
111   bool mips_isa_gte2 = (bitmap & kIsaRevGte2Bitfield) != 0;
112   bool r6 = (bitmap & kR6) != 0;
113   bool msa = (bitmap & kMsaBitfield) != 0;
114   return MipsFeaturesUniquePtr(new MipsInstructionSetFeatures(fpu_32bit, mips_isa_gte2, r6, msa));
115 }
116 
FromCppDefines()117 MipsFeaturesUniquePtr MipsInstructionSetFeatures::FromCppDefines() {
118   bool fpu_32bit;
119   bool mips_isa_gte2;
120   bool r6;
121   bool msa;
122   GetFlagsFromCppDefined(&mips_isa_gte2, &r6, &fpu_32bit, &msa);
123 
124   return MipsFeaturesUniquePtr(new MipsInstructionSetFeatures(fpu_32bit, mips_isa_gte2, r6, msa));
125 }
126 
FromCpuInfo()127 MipsFeaturesUniquePtr MipsInstructionSetFeatures::FromCpuInfo() {
128   bool fpu_32bit;
129   bool mips_isa_gte2;
130   bool r6;
131   bool msa;
132   GetFlagsFromCppDefined(&mips_isa_gte2, &r6, &fpu_32bit, &msa);
133 
134   msa = false;
135 
136   std::ifstream in("/proc/cpuinfo");
137   if (!in.fail()) {
138     while (!in.eof()) {
139       std::string line;
140       std::getline(in, line);
141       if (!in.eof()) {
142         LOG(INFO) << "cpuinfo line: " << line;
143         if (line.find("ASEs") != std::string::npos) {
144           LOG(INFO) << "found Application Specific Extensions";
145           if (line.find("msa") != std::string::npos) {
146             msa = true;
147           }
148         }
149       }
150     }
151     in.close();
152   } else {
153     LOG(ERROR) << "Failed to open /proc/cpuinfo";
154   }
155 
156   return MipsFeaturesUniquePtr(new MipsInstructionSetFeatures(fpu_32bit, mips_isa_gte2, r6, msa));
157 }
158 
FromHwcap()159 MipsFeaturesUniquePtr MipsInstructionSetFeatures::FromHwcap() {
160   UNIMPLEMENTED(WARNING);
161   return FromCppDefines();
162 }
163 
FromAssembly()164 MipsFeaturesUniquePtr MipsInstructionSetFeatures::FromAssembly() {
165   UNIMPLEMENTED(WARNING);
166   return FromCppDefines();
167 }
168 
Equals(const InstructionSetFeatures * other) const169 bool MipsInstructionSetFeatures::Equals(const InstructionSetFeatures* other) const {
170   if (InstructionSet::kMips != other->GetInstructionSet()) {
171     return false;
172   }
173   const MipsInstructionSetFeatures* other_as_mips = other->AsMipsInstructionSetFeatures();
174   return (fpu_32bit_ == other_as_mips->fpu_32bit_) &&
175       (mips_isa_gte2_ == other_as_mips->mips_isa_gte2_) &&
176       (r6_ == other_as_mips->r6_) &&
177       (msa_ == other_as_mips->msa_);
178 }
179 
AsBitmap() const180 uint32_t MipsInstructionSetFeatures::AsBitmap() const {
181   return (fpu_32bit_ ? kFpu32Bitfield : 0) |
182       (mips_isa_gte2_ ? kIsaRevGte2Bitfield : 0) |
183       (r6_ ? kR6 : 0) |
184       (msa_ ? kMsaBitfield : 0);
185 }
186 
GetFeatureString() const187 std::string MipsInstructionSetFeatures::GetFeatureString() const {
188   std::string result;
189   if (fpu_32bit_) {
190     result += "fpu32";
191   } else {
192     result += "-fpu32";
193   }
194   if (mips_isa_gte2_) {
195     result += ",mips2";
196   } else {
197     result += ",-mips2";
198   }
199   if (r6_) {
200     result += ",r6";
201   }  // Suppress non-r6.
202   if (msa_) {
203     result += ",msa";
204   } else {
205     result += ",-msa";
206   }
207   return result;
208 }
209 
210 std::unique_ptr<const InstructionSetFeatures>
AddFeaturesFromSplitString(const std::vector<std::string> & features,std::string * error_msg) const211 MipsInstructionSetFeatures::AddFeaturesFromSplitString(
212     const std::vector<std::string>& features, std::string* error_msg) const {
213   bool fpu_32bit = fpu_32bit_;
214   bool mips_isa_gte2 = mips_isa_gte2_;
215   bool r6 = r6_;
216   bool msa = msa_;
217   for (auto i = features.begin(); i != features.end(); i++) {
218     std::string feature = android::base::Trim(*i);
219     if (feature == "fpu32") {
220       fpu_32bit = true;
221     } else if (feature == "-fpu32") {
222       fpu_32bit = false;
223     } else if (feature == "mips2") {
224       mips_isa_gte2 = true;
225     } else if (feature == "-mips2") {
226       mips_isa_gte2 = false;
227     } else if (feature == "r6") {
228       r6 = true;
229     } else if (feature == "-r6") {
230       r6 = false;
231     } else if (feature == "msa") {
232       msa = true;
233     } else if (feature == "-msa") {
234       msa = false;
235     } else {
236       *error_msg = StringPrintf("Unknown instruction set feature: '%s'", feature.c_str());
237       return nullptr;
238     }
239   }
240   return std::unique_ptr<const InstructionSetFeatures>(
241       new MipsInstructionSetFeatures(fpu_32bit, mips_isa_gte2, r6, msa));
242 }
243 
244 }  // namespace art
245