OSDN Git Service

ART: Introduce Mips32 R6
authorAndreas Gampe <agampe@google.com>
Wed, 14 Jan 2015 00:41:53 +0000 (16:41 -0800)
committerAndreas Gampe <agampe@google.com>
Wed, 14 Jan 2015 04:19:56 +0000 (20:19 -0800)
Add an instruction-set feature for Mips R6. Currently restricted
to the interpreter.

Change-Id: Ic6d888e135bc87340229a0543dd94d0c1e863edd

dex2oat/dex2oat.cc
patchoat/patchoat.cc
runtime/arch/mips/instruction_set_features_mips.cc
runtime/arch/mips/instruction_set_features_mips.h
runtime/elf_file.cc
runtime/elf_utils.h

index 4f279f2..4b4675b 100644 (file)
@@ -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 @@ class Dex2Oat FINAL {
     }
 
     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_) {
index b6ec223..28f9668 100644 (file)
@@ -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 @@ static InstructionSet ElfISAToInstructionSet(Elf32_Word isa) {
     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 @@ bool PatchOat::Patch(File* input_oat, const std::string& image_location, off_t d
       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;
index 11be2a8..00ab613 100644 (file)
 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;
+  // Override defaults based on compiler flags.
+#if (_MIPS_ARCH_MIPS32R2) || defined(_MIPS_ARCH_MIPS32R5) || defined(_MIPS_ARCH_MIPS32R6)
+  mips_isa_gte2 = true;
+#endif
 
-#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
 
-  return new MipsInstructionSetFeatures(smp, fpu_32bit, mips_isa_gte2);
+  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 @@ const MipsInstructionSetFeatures* MipsInstructionSetFeatures::FromCpuInfo() {
   } 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 @@ bool MipsInstructionSetFeatures::Equals(const InstructionSetFeatures* other) con
   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 @@ std::string MipsInstructionSetFeatures::GetFeatureString() const {
   } else {
     result += ",-mips2";
   }
+  if (r6_) {
+    result += ",r6";
+  }  // Suppress non-r6.
   return result;
 }
 
@@ -142,6 +177,7 @@ const InstructionSetFeatures* MipsInstructionSetFeatures::AddFeaturesFromSplitSt
     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 @@ const InstructionSetFeatures* MipsInstructionSetFeatures::AddFeaturesFromSplitSt
       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
index f7c64fe..aac436e 100644 (file)
@@ -67,6 +67,10 @@ class MipsInstructionSetFeatures FINAL : public InstructionSetFeatures {
     return fpu_32bit_;
   }
 
+  bool IsR6() const {
+    return r6_;
+  }
+
   virtual ~MipsInstructionSetFeatures() {}
 
  protected:
@@ -76,19 +80,21 @@ class MipsInstructionSetFeatures FINAL : public InstructionSetFeatures {
                                  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);
 };
index 4198905..b6df609 100644 (file)
@@ -1332,7 +1332,10 @@ bool ElfFileImpl<Elf_Ehdr, Elf_Phdr, Elf_Shdr, Elf_Word,
         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;
       }
     }
index 7b00bad..3579e27 100644 (file)
@@ -30,6 +30,7 @@ namespace art {
 #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