ART: Introduce Mips32 R6
Add an instruction-set feature for Mips R6. Currently restricted
to the interpreter.
Change-Id: Ic6d888e135bc87340229a0543dd94d0c1e863edd
diff --git a/dex2oat/dex2oat.cc b/dex2oat/dex2oat.cc
index 4f279f2..4b4675b 100644
--- a/dex2oat/dex2oat.cc
+++ b/dex2oat/dex2oat.cc
@@ -34,6 +34,7 @@
#include <cutils/trace.h>
#include "arch/instruction_set_features.h"
+#include "arch/mips/instruction_set_features_mips.h"
#include "base/dumpable.h"
#include "base/stl_util.h"
#include "base/stringpiece.h"
@@ -852,7 +853,13 @@
}
if (compiler_filter_string == nullptr) {
- if (instruction_set_ == kMips64) {
+ if (instruction_set_ == kMips &&
+ reinterpret_cast<const MipsInstructionSetFeatures*>(instruction_set_features_.get())->
+ IsR6()) {
+ // For R6, only interpreter mode is working.
+ // TODO: fix compiler for Mips32r6.
+ compiler_filter_string = "interpret-only";
+ } else if (instruction_set_ == kMips64) {
// TODO: fix compiler for Mips64.
compiler_filter_string = "interpret-only";
} else if (image_) {
diff --git a/patchoat/patchoat.cc b/patchoat/patchoat.cc
index b6ec223..28f9668 100644
--- a/patchoat/patchoat.cc
+++ b/patchoat/patchoat.cc
@@ -48,7 +48,7 @@
namespace art {
-static InstructionSet ElfISAToInstructionSet(Elf32_Word isa) {
+static InstructionSet ElfISAToInstructionSet(Elf32_Word isa, Elf32_Word e_flags) {
switch (isa) {
case EM_ARM:
return kArm;
@@ -59,7 +59,12 @@
case EM_X86_64:
return kX86_64;
case EM_MIPS:
- return kMips;
+ if (((e_flags & EF_MIPS_ARCH) == EF_MIPS_ARCH_32R2) ||
+ ((e_flags & EF_MIPS_ARCH) == EF_MIPS_ARCH_32R6)) {
+ return kMips;
+ } else {
+ return kNone;
+ }
default:
return kNone;
}
@@ -212,7 +217,7 @@
LOG(ERROR) << "unable to read elf header";
return false;
}
- isa = ElfISAToInstructionSet(elf_hdr.e_machine);
+ isa = ElfISAToInstructionSet(elf_hdr.e_machine, elf_hdr.e_flags);
}
const char* isa_name = GetInstructionSetString(isa);
std::string image_filename;
diff --git a/runtime/arch/mips/instruction_set_features_mips.cc b/runtime/arch/mips/instruction_set_features_mips.cc
index 11be2a8..00ab613 100644
--- a/runtime/arch/mips/instruction_set_features_mips.cc
+++ b/runtime/arch/mips/instruction_set_features_mips.cc
@@ -25,52 +25,82 @@
namespace art {
const MipsInstructionSetFeatures* MipsInstructionSetFeatures::FromVariant(
- const std::string& variant ATTRIBUTE_UNUSED, std::string* error_msg ATTRIBUTE_UNUSED) {
- if (variant != "default") {
- std::ostringstream os;
- LOG(WARNING) << "Unexpected CPU variant for Mips using defaults: " << variant;
- }
+ const std::string& variant, std::string* error_msg ATTRIBUTE_UNUSED) {
+
bool smp = true; // Conservative default.
bool fpu_32bit = true;
- bool mips_isa_gte2 = true;
- return new MipsInstructionSetFeatures(smp, fpu_32bit, mips_isa_gte2);
+ bool mips_isa_gte2 = false;
+ bool r6 = false;
+
+ // Override defaults based on variant string.
+ // Only care if it is R1, R2 or R6 and we assume all CPUs will have a FP unit.
+ constexpr const char* kMips32Prefix = "mips32r";
+ const size_t kPrefixLength = strlen(kMips32Prefix);
+ if (variant.compare(0, kPrefixLength, kMips32Prefix, kPrefixLength) == 0 &&
+ variant.size() > kPrefixLength) {
+ if (variant[kPrefixLength] >= '6') {
+ fpu_32bit = false;
+ r6 = true;
+ }
+ if (variant[kPrefixLength] >= '2') {
+ mips_isa_gte2 = true;
+ }
+ } else if (variant == "default") {
+ // Default variant is: smp = true, has fpu, is gte2, is not r6. This is the traditional
+ // setting.
+ mips_isa_gte2 = true;
+ } else {
+ LOG(WARNING) << "Unexpected CPU variant for Mips32 using defaults: " << variant;
+ }
+
+ return new MipsInstructionSetFeatures(smp, fpu_32bit, mips_isa_gte2, r6);
}
const MipsInstructionSetFeatures* MipsInstructionSetFeatures::FromBitmap(uint32_t bitmap) {
bool smp = (bitmap & kSmpBitfield) != 0;
bool fpu_32bit = (bitmap & kFpu32Bitfield) != 0;
bool mips_isa_gte2 = (bitmap & kIsaRevGte2Bitfield) != 0;
- return new MipsInstructionSetFeatures(smp, fpu_32bit, mips_isa_gte2);
+ bool r6 = (bitmap & kR6) != 0;
+ return new MipsInstructionSetFeatures(smp, fpu_32bit, mips_isa_gte2, r6);
}
const MipsInstructionSetFeatures* MipsInstructionSetFeatures::FromCppDefines() {
+ // Assume conservative defaults.
const bool smp = true;
+ bool fpu_32bit = true;
+ bool mips_isa_gte2 = false;
+ bool r6 = false;
- // TODO: here we assume the FPU is always 32-bit.
- const bool fpu_32bit = true;
-
-#if __mips_isa_rev >= 2
- const bool mips_isa_gte2 = true;
-#else
- const bool mips_isa_gte2 = false;
+ // Override defaults based on compiler flags.
+#if (_MIPS_ARCH_MIPS32R2) || defined(_MIPS_ARCH_MIPS32R5) || defined(_MIPS_ARCH_MIPS32R6)
+ mips_isa_gte2 = true;
#endif
- return new MipsInstructionSetFeatures(smp, fpu_32bit, mips_isa_gte2);
+#if defined(_MIPS_ARCH_MIPS32R6)
+ r6 = true;
+ fpu_32bit = false;
+#endif
+
+ return new MipsInstructionSetFeatures(smp, fpu_32bit, mips_isa_gte2, r6);
}
const MipsInstructionSetFeatures* MipsInstructionSetFeatures::FromCpuInfo() {
// Look in /proc/cpuinfo for features we need. Only use this when we can guarantee that
// the kernel puts the appropriate feature flags in here. Sometimes it doesn't.
+ // Assume conservative defaults.
bool smp = false;
+ bool fpu_32bit = true;
+ bool mips_isa_gte2 = false;
+ bool r6 = false;
- // TODO: here we assume the FPU is always 32-bit.
- const bool fpu_32bit = true;
+ // Override defaults based on compiler flags.
+#if (_MIPS_ARCH_MIPS32R2) || defined(_MIPS_ARCH_MIPS32R5) || defined(_MIPS_ARCH_MIPS32R6)
+ mips_isa_gte2 = true;
+#endif
- // TODO: here we assume all MIPS processors are >= v2.
-#if __mips_isa_rev >= 2
- const bool mips_isa_gte2 = true;
-#else
- const bool mips_isa_gte2 = false;
+#if defined(_MIPS_ARCH_MIPS32R6)
+ r6 = true;
+ fpu_32bit = false;
#endif
std::ifstream in("/proc/cpuinfo");
@@ -89,7 +119,7 @@
} else {
LOG(ERROR) << "Failed to open /proc/cpuinfo";
}
- return new MipsInstructionSetFeatures(smp, fpu_32bit, mips_isa_gte2);
+ return new MipsInstructionSetFeatures(smp, fpu_32bit, mips_isa_gte2, r6);
}
const MipsInstructionSetFeatures* MipsInstructionSetFeatures::FromHwcap() {
@@ -109,13 +139,15 @@
const MipsInstructionSetFeatures* other_as_mips = other->AsMipsInstructionSetFeatures();
return (IsSmp() == other->IsSmp()) &&
(fpu_32bit_ == other_as_mips->fpu_32bit_) &&
- (mips_isa_gte2_ == other_as_mips->mips_isa_gte2_);
+ (mips_isa_gte2_ == other_as_mips->mips_isa_gte2_) &&
+ (r6_ == other_as_mips->r6_);
}
uint32_t MipsInstructionSetFeatures::AsBitmap() const {
return (IsSmp() ? kSmpBitfield : 0) |
(fpu_32bit_ ? kFpu32Bitfield : 0) |
- (mips_isa_gte2_ ? kIsaRevGte2Bitfield : 0);
+ (mips_isa_gte2_ ? kIsaRevGte2Bitfield : 0) |
+ (r6_ ? kR6 : 0);
}
std::string MipsInstructionSetFeatures::GetFeatureString() const {
@@ -135,6 +167,9 @@
} else {
result += ",-mips2";
}
+ if (r6_) {
+ result += ",r6";
+ } // Suppress non-r6.
return result;
}
@@ -142,6 +177,7 @@
const bool smp, const std::vector<std::string>& features, std::string* error_msg) const {
bool fpu_32bit = fpu_32bit_;
bool mips_isa_gte2 = mips_isa_gte2_;
+ bool r6 = r6_;
for (auto i = features.begin(); i != features.end(); i++) {
std::string feature = Trim(*i);
if (feature == "fpu32") {
@@ -152,12 +188,16 @@
mips_isa_gte2 = true;
} else if (feature == "-mips2") {
mips_isa_gte2 = false;
+ } else if (feature == "r6") {
+ r6 = true;
+ } else if (feature == "-r6") {
+ r6 = false;
} else {
*error_msg = StringPrintf("Unknown instruction set feature: '%s'", feature.c_str());
return nullptr;
}
}
- return new MipsInstructionSetFeatures(smp, fpu_32bit, mips_isa_gte2);
+ return new MipsInstructionSetFeatures(smp, fpu_32bit, mips_isa_gte2, r6);
}
} // namespace art
diff --git a/runtime/arch/mips/instruction_set_features_mips.h b/runtime/arch/mips/instruction_set_features_mips.h
index f7c64fe..aac436e 100644
--- a/runtime/arch/mips/instruction_set_features_mips.h
+++ b/runtime/arch/mips/instruction_set_features_mips.h
@@ -67,6 +67,10 @@
return fpu_32bit_;
}
+ bool IsR6() const {
+ return r6_;
+ }
+
virtual ~MipsInstructionSetFeatures() {}
protected:
@@ -76,19 +80,21 @@
std::string* error_msg) const OVERRIDE;
private:
- MipsInstructionSetFeatures(bool smp, bool fpu_32bit, bool mips_isa_gte2)
- : InstructionSetFeatures(smp), fpu_32bit_(fpu_32bit), mips_isa_gte2_(mips_isa_gte2) {
- }
+ MipsInstructionSetFeatures(bool smp, bool fpu_32bit, bool mips_isa_gte2, bool r6)
+ : InstructionSetFeatures(smp), fpu_32bit_(fpu_32bit), mips_isa_gte2_(mips_isa_gte2), r6_(r6)
+ {}
// Bitmap positions for encoding features as a bitmap.
enum {
kSmpBitfield = 1,
kFpu32Bitfield = 2,
kIsaRevGte2Bitfield = 4,
+ kR6 = 8,
};
const bool fpu_32bit_;
const bool mips_isa_gte2_;
+ const bool r6_;
DISALLOW_COPY_AND_ASSIGN(MipsInstructionSetFeatures);
};
diff --git a/runtime/elf_file.cc b/runtime/elf_file.cc
index 4198905..b6df609 100644
--- a/runtime/elf_file.cc
+++ b/runtime/elf_file.cc
@@ -1332,7 +1332,10 @@
break;
}
case EM_MIPS: {
- elf_ISA = kMips;
+ if ((GetHeader().e_flags & EF_MIPS_ARCH) == EF_MIPS_ARCH_32R2 ||
+ (GetHeader().e_flags & EF_MIPS_ARCH) == EF_MIPS_ARCH_32R6) {
+ elf_ISA = kMips;
+ }
break;
}
}
diff --git a/runtime/elf_utils.h b/runtime/elf_utils.h
index 7b00bad..3579e27 100644
--- a/runtime/elf_utils.h
+++ b/runtime/elf_utils.h
@@ -30,6 +30,7 @@
#define EF_ARM_EABI_VER5 0x05000000
#define EF_MIPS_ABI_O32 0x00001000
#define EF_MIPS_ARCH_32R2 0x70000000
+#define EF_MIPS_ARCH_32R6 0x90000000
#define EI_ABIVERSION 8
#define EM_ARM 40