summaryrefslogtreecommitdiffstats
path: root/runtime
diff options
context:
space:
mode:
authorAndreas Gampe <agampe@google.com>2015-01-14 15:45:59 -0800
committerAndreas Gampe <agampe@google.com>2015-01-15 11:32:48 -0800
commit57b34294758e9c00993913ebe43c7ee4698a5cc6 (patch)
tree981821619027686f83fbe00445299b0522f1df05 /runtime
parent4945bfef00ac446d9c5458e55500229d463ab4c3 (diff)
downloadart-57b34294758e9c00993913ebe43c7ee4698a5cc6.zip
art-57b34294758e9c00993913ebe43c7ee4698a5cc6.tar.gz
art-57b34294758e9c00993913ebe43c7ee4698a5cc6.tar.bz2
ART: Allow to compile interpret-only mips64 files
Include enough infrastructure to allow cross-compiling for mips64, interpret-only. This includes the instruction-set-features, frame size info and utils assembler. Also add a disassembler for oatdump, and support in patchoat. Note: the runtime cannot run mips64, yet. Change-Id: Id106581fa76b478984741c62a8a03be0f370d992
Diffstat (limited to 'runtime')
-rw-r--r--runtime/Android.mk2
-rw-r--r--runtime/arch/instruction_set.cc8
-rw-r--r--runtime/arch/instruction_set.h16
-rw-r--r--runtime/arch/instruction_set_features.cc24
-rw-r--r--runtime/arch/instruction_set_features.h4
-rw-r--r--runtime/arch/instruction_set_test.cc2
-rw-r--r--runtime/arch/mips64/instruction_set_features_mips64.cc116
-rw-r--r--runtime/arch/mips64/instruction_set_features_mips64.h80
-rw-r--r--runtime/arch/mips64/instruction_set_features_mips64_test.cc34
-rw-r--r--runtime/arch/mips64/quick_method_frame_info_mips64.h75
-rw-r--r--runtime/arch/mips64/registers_mips64.cc50
-rw-r--r--runtime/arch/mips64/registers_mips64.h109
-rw-r--r--runtime/elf_file.cc2
-rw-r--r--runtime/elf_utils.h1
-rw-r--r--runtime/entrypoints/quick/callee_save_frame.h3
-rw-r--r--runtime/runtime.cc7
16 files changed, 527 insertions, 6 deletions
diff --git a/runtime/Android.mk b/runtime/Android.mk
index 13a216c..3330b2d 100644
--- a/runtime/Android.mk
+++ b/runtime/Android.mk
@@ -170,6 +170,8 @@ LIBART_COMMON_SRC_FILES += \
arch/arm64/registers_arm64.cc \
arch/mips/instruction_set_features_mips.cc \
arch/mips/registers_mips.cc \
+ arch/mips64/instruction_set_features_mips64.cc \
+ arch/mips64/registers_mips64.cc \
arch/x86/instruction_set_features_x86.cc \
arch/x86/registers_x86.cc \
arch/x86_64/registers_x86_64.cc \
diff --git a/runtime/arch/instruction_set.cc b/runtime/arch/instruction_set.cc
index 92fa727..5ab461b 100644
--- a/runtime/arch/instruction_set.cc
+++ b/runtime/arch/instruction_set.cc
@@ -57,7 +57,7 @@ InstructionSet GetInstructionSetFromString(const char* isa_str) {
} else if (strcmp("mips", isa_str) == 0) {
return kMips;
} else if (strcmp("mips64", isa_str) == 0) {
- return kMips;
+ return kMips64;
}
return kNone;
@@ -76,6 +76,8 @@ size_t GetInstructionSetAlignment(InstructionSet isa) {
case kX86_64:
return kX86Alignment;
case kMips:
+ // Fall-through.
+ case kMips64:
return kMipsAlignment;
case kNone:
LOG(FATAL) << "ISA kNone does not have alignment.";
@@ -88,6 +90,7 @@ size_t GetInstructionSetAlignment(InstructionSet isa) {
static constexpr size_t kDefaultStackOverflowReservedBytes = 16 * KB;
static constexpr size_t kMipsStackOverflowReservedBytes = kDefaultStackOverflowReservedBytes;
+static constexpr size_t kMips64StackOverflowReservedBytes = kDefaultStackOverflowReservedBytes;
static constexpr size_t kArmStackOverflowReservedBytes = 8 * KB;
static constexpr size_t kArm64StackOverflowReservedBytes = 8 * KB;
@@ -106,6 +109,9 @@ size_t GetStackOverflowReservedBytes(InstructionSet isa) {
case kMips:
return kMipsStackOverflowReservedBytes;
+ case kMips64:
+ return kMips64StackOverflowReservedBytes;
+
case kX86:
return kX86StackOverflowReservedBytes;
diff --git a/runtime/arch/instruction_set.h b/runtime/arch/instruction_set.h
index e413880..9135e58 100644
--- a/runtime/arch/instruction_set.h
+++ b/runtime/arch/instruction_set.h
@@ -40,8 +40,10 @@ std::ostream& operator<<(std::ostream& os, const InstructionSet& rhs);
static constexpr InstructionSet kRuntimeISA = kArm;
#elif defined(__aarch64__)
static constexpr InstructionSet kRuntimeISA = kArm64;
-#elif defined(__mips__)
+#elif defined(__mips__) && !defined(__LP64__)
static constexpr InstructionSet kRuntimeISA = kMips;
+#elif defined(__mips__) && defined(__LP64__)
+static constexpr InstructionSet kRuntimeISA = kMips64;
#elif defined(__i386__)
static constexpr InstructionSet kRuntimeISA = kX86;
#elif defined(__x86_64__)
@@ -145,6 +147,8 @@ static inline size_t GetBytesPerGprSpillLocation(InstructionSet isa) {
return 8;
case kMips:
return 4;
+ case kMips64:
+ return 8;
case kNone:
LOG(FATAL) << "ISA kNone does not have spills.";
UNREACHABLE();
@@ -168,6 +172,8 @@ static inline size_t GetBytesPerFprSpillLocation(InstructionSet isa) {
return 8;
case kMips:
return 4;
+ case kMips64:
+ return 8;
case kNone:
LOG(FATAL) << "ISA kNone does not have spills.";
UNREACHABLE();
@@ -186,8 +192,8 @@ size_t GetStackOverflowReservedBytes(InstructionSet isa);
// On x86, ARM32 and MIPS, this is given for a *scalar* 64bit value. The definition thus *must* be
// uint64_t or long long int.
//
-// On x86_64 and ARM64, structs are decomposed for allocation, so we can create a structs of two
-// size_t-sized values.
+// On x86_64, ARM64 and MIPS64, structs are decomposed for allocation, so we can create a structs of
+// two size_t-sized values.
//
// We need two operations:
//
@@ -202,7 +208,7 @@ size_t GetStackOverflowReservedBytes(InstructionSet isa);
// when the garbage collector can move objects concurrently. Ensure that required locks
// are held when using!
-#if defined(__i386__) || defined(__arm__) || defined(__mips__)
+#if defined(__i386__) || defined(__arm__) || (defined(__mips__) && !defined(__LP64__))
typedef uint64_t TwoWordReturn;
// Encodes method_ptr==nullptr and code_ptr==nullptr
@@ -218,7 +224,7 @@ static inline TwoWordReturn GetTwoWordSuccessValue(uintptr_t hi, uintptr_t lo) {
return ((hi64 << 32) | lo32);
}
-#elif defined(__x86_64__) || defined(__aarch64__)
+#elif defined(__x86_64__) || defined(__aarch64__) || (defined(__mips__) && defined(__LP64__))
struct TwoWordReturn {
uintptr_t lo;
uintptr_t hi;
diff --git a/runtime/arch/instruction_set_features.cc b/runtime/arch/instruction_set_features.cc
index 1072562..1fd1dea 100644
--- a/runtime/arch/instruction_set_features.cc
+++ b/runtime/arch/instruction_set_features.cc
@@ -23,6 +23,7 @@
#include "arm/instruction_set_features_arm.h"
#include "arm64/instruction_set_features_arm64.h"
#include "mips/instruction_set_features_mips.h"
+#include "mips64/instruction_set_features_mips64.h"
#include "x86/instruction_set_features_x86.h"
#include "x86_64/instruction_set_features_x86_64.h"
@@ -43,6 +44,9 @@ const InstructionSetFeatures* InstructionSetFeatures::FromVariant(InstructionSet
case kMips:
result = MipsInstructionSetFeatures::FromVariant(variant, error_msg);
break;
+ case kMips64:
+ result = Mips64InstructionSetFeatures::FromVariant(variant, error_msg);
+ break;
case kX86:
result = X86InstructionSetFeatures::FromVariant(variant, error_msg);
break;
@@ -71,6 +75,9 @@ const InstructionSetFeatures* InstructionSetFeatures::FromBitmap(InstructionSet
case kMips:
result = MipsInstructionSetFeatures::FromBitmap(bitmap);
break;
+ case kMips64:
+ result = Mips64InstructionSetFeatures::FromBitmap(bitmap);
+ break;
case kX86:
result = X86InstructionSetFeatures::FromBitmap(bitmap);
break;
@@ -98,6 +105,9 @@ const InstructionSetFeatures* InstructionSetFeatures::FromCppDefines() {
case kMips:
result = MipsInstructionSetFeatures::FromCppDefines();
break;
+ case kMips64:
+ result = Mips64InstructionSetFeatures::FromCppDefines();
+ break;
case kX86:
result = X86InstructionSetFeatures::FromCppDefines();
break;
@@ -125,6 +135,9 @@ const InstructionSetFeatures* InstructionSetFeatures::FromCpuInfo() {
case kMips:
result = MipsInstructionSetFeatures::FromCpuInfo();
break;
+ case kMips64:
+ result = Mips64InstructionSetFeatures::FromCpuInfo();
+ break;
case kX86:
result = X86InstructionSetFeatures::FromCpuInfo();
break;
@@ -151,6 +164,9 @@ const InstructionSetFeatures* InstructionSetFeatures::FromHwcap() {
case kMips:
result = MipsInstructionSetFeatures::FromHwcap();
break;
+ case kMips64:
+ result = Mips64InstructionSetFeatures::FromHwcap();
+ break;
case kX86:
result = X86InstructionSetFeatures::FromHwcap();
break;
@@ -177,6 +193,9 @@ const InstructionSetFeatures* InstructionSetFeatures::FromAssembly() {
case kMips:
result = MipsInstructionSetFeatures::FromAssembly();
break;
+ case kMips64:
+ result = Mips64InstructionSetFeatures::FromAssembly();
+ break;
case kX86:
result = X86InstructionSetFeatures::FromAssembly();
break;
@@ -250,6 +269,11 @@ const MipsInstructionSetFeatures* InstructionSetFeatures::AsMipsInstructionSetFe
return down_cast<const MipsInstructionSetFeatures*>(this);
}
+const Mips64InstructionSetFeatures* InstructionSetFeatures::AsMips64InstructionSetFeatures() const {
+ DCHECK_EQ(kMips64, GetInstructionSet());
+ return down_cast<const Mips64InstructionSetFeatures*>(this);
+}
+
const X86InstructionSetFeatures* InstructionSetFeatures::AsX86InstructionSetFeatures() const {
DCHECK(kX86 == GetInstructionSet() || kX86_64 == GetInstructionSet());
return down_cast<const X86InstructionSetFeatures*>(this);
diff --git a/runtime/arch/instruction_set_features.h b/runtime/arch/instruction_set_features.h
index 2c6e699..e4513ef 100644
--- a/runtime/arch/instruction_set_features.h
+++ b/runtime/arch/instruction_set_features.h
@@ -28,6 +28,7 @@ namespace art {
class ArmInstructionSetFeatures;
class Arm64InstructionSetFeatures;
class MipsInstructionSetFeatures;
+class Mips64InstructionSetFeatures;
class X86InstructionSetFeatures;
class X86_64InstructionSetFeatures;
@@ -87,6 +88,9 @@ class InstructionSetFeatures {
// Down cast this MipsInstructionFeatures.
const MipsInstructionSetFeatures* AsMipsInstructionSetFeatures() const;
+ // Down cast this Mips64InstructionFeatures.
+ const Mips64InstructionSetFeatures* AsMips64InstructionSetFeatures() const;
+
// Down cast this X86InstructionFeatures.
const X86InstructionSetFeatures* AsX86InstructionSetFeatures() const;
diff --git a/runtime/arch/instruction_set_test.cc b/runtime/arch/instruction_set_test.cc
index 932ef32..2f3cf18 100644
--- a/runtime/arch/instruction_set_test.cc
+++ b/runtime/arch/instruction_set_test.cc
@@ -28,6 +28,7 @@ TEST(InstructionSetTest, GetInstructionSetFromString) {
EXPECT_EQ(kX86, GetInstructionSetFromString("x86"));
EXPECT_EQ(kX86_64, GetInstructionSetFromString("x86_64"));
EXPECT_EQ(kMips, GetInstructionSetFromString("mips"));
+ EXPECT_EQ(kMips64, GetInstructionSetFromString("mips64"));
EXPECT_EQ(kNone, GetInstructionSetFromString("none"));
EXPECT_EQ(kNone, GetInstructionSetFromString("random-string"));
}
@@ -39,6 +40,7 @@ TEST(InstructionSetTest, GetInstructionSetString) {
EXPECT_STREQ("x86", GetInstructionSetString(kX86));
EXPECT_STREQ("x86_64", GetInstructionSetString(kX86_64));
EXPECT_STREQ("mips", GetInstructionSetString(kMips));
+ EXPECT_STREQ("mips64", GetInstructionSetString(kMips64));
EXPECT_STREQ("none", GetInstructionSetString(kNone));
}
diff --git a/runtime/arch/mips64/instruction_set_features_mips64.cc b/runtime/arch/mips64/instruction_set_features_mips64.cc
new file mode 100644
index 0000000..26478cb
--- /dev/null
+++ b/runtime/arch/mips64/instruction_set_features_mips64.cc
@@ -0,0 +1,116 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "instruction_set_features_mips64.h"
+
+#include <fstream>
+#include <sstream>
+
+#include "base/stringprintf.h"
+#include "utils.h" // For Trim.
+
+namespace art {
+
+const Mips64InstructionSetFeatures* Mips64InstructionSetFeatures::FromVariant(
+ const std::string& variant, std::string* error_msg ATTRIBUTE_UNUSED) {
+ // TODO: r6 variant.
+ if (variant != "default") {
+ std::ostringstream os;
+ LOG(WARNING) << "Unexpected CPU variant for Mips64 using defaults: " << variant;
+ }
+ bool smp = true; // Conservative default.
+ return new Mips64InstructionSetFeatures(smp);
+}
+
+const Mips64InstructionSetFeatures* Mips64InstructionSetFeatures::FromBitmap(uint32_t bitmap) {
+ bool smp = (bitmap & kSmpBitfield) != 0;
+ return new Mips64InstructionSetFeatures(smp);
+}
+
+const Mips64InstructionSetFeatures* Mips64InstructionSetFeatures::FromCppDefines() {
+ const bool smp = true;
+
+ return new Mips64InstructionSetFeatures(smp);
+}
+
+const Mips64InstructionSetFeatures* Mips64InstructionSetFeatures::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.
+ bool smp = false;
+
+ std::ifstream in("/proc/cpuinfo");
+ if (!in.fail()) {
+ while (!in.eof()) {
+ std::string line;
+ std::getline(in, line);
+ if (!in.eof()) {
+ LOG(INFO) << "cpuinfo line: " << line;
+ if (line.find("processor") != std::string::npos && line.find(": 1") != std::string::npos) {
+ smp = true;
+ }
+ }
+ }
+ in.close();
+ } else {
+ LOG(ERROR) << "Failed to open /proc/cpuinfo";
+ }
+ return new Mips64InstructionSetFeatures(smp);
+}
+
+const Mips64InstructionSetFeatures* Mips64InstructionSetFeatures::FromHwcap() {
+ UNIMPLEMENTED(WARNING);
+ return FromCppDefines();
+}
+
+const Mips64InstructionSetFeatures* Mips64InstructionSetFeatures::FromAssembly() {
+ UNIMPLEMENTED(WARNING);
+ return FromCppDefines();
+}
+
+bool Mips64InstructionSetFeatures::Equals(const InstructionSetFeatures* other) const {
+ if (kMips64 != other->GetInstructionSet()) {
+ return false;
+ }
+ return (IsSmp() == other->IsSmp());
+}
+
+uint32_t Mips64InstructionSetFeatures::AsBitmap() const {
+ return (IsSmp() ? kSmpBitfield : 0);
+}
+
+std::string Mips64InstructionSetFeatures::GetFeatureString() const {
+ std::string result;
+ if (IsSmp()) {
+ result += "smp";
+ } else {
+ result += "-smp";
+ }
+ return result;
+}
+
+const InstructionSetFeatures* Mips64InstructionSetFeatures::AddFeaturesFromSplitString(
+ const bool smp, const std::vector<std::string>& features, std::string* error_msg) const {
+ auto i = features.begin();
+ if (i != features.end()) {
+ // We don't have any features.
+ std::string feature = Trim(*i);
+ *error_msg = StringPrintf("Unknown instruction set feature: '%s'", feature.c_str());
+ return nullptr;
+ }
+ return new Mips64InstructionSetFeatures(smp);
+}
+
+} // namespace art
diff --git a/runtime/arch/mips64/instruction_set_features_mips64.h b/runtime/arch/mips64/instruction_set_features_mips64.h
new file mode 100644
index 0000000..d5d6012
--- /dev/null
+++ b/runtime/arch/mips64/instruction_set_features_mips64.h
@@ -0,0 +1,80 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ART_RUNTIME_ARCH_MIPS64_INSTRUCTION_SET_FEATURES_MIPS64_H_
+#define ART_RUNTIME_ARCH_MIPS64_INSTRUCTION_SET_FEATURES_MIPS64_H_
+
+#include "arch/instruction_set_features.h"
+
+namespace art {
+
+// Instruction set features relevant to the MIPS64 architecture.
+class Mips64InstructionSetFeatures FINAL : public InstructionSetFeatures {
+ public:
+ // Process a CPU variant string like "r4000" and create InstructionSetFeatures.
+ static const Mips64InstructionSetFeatures* FromVariant(const std::string& variant,
+ std::string* error_msg);
+
+ // Parse a bitmap and create an InstructionSetFeatures.
+ static const Mips64InstructionSetFeatures* FromBitmap(uint32_t bitmap);
+
+ // Turn C pre-processor #defines into the equivalent instruction set features.
+ static const Mips64InstructionSetFeatures* FromCppDefines();
+
+ // Process /proc/cpuinfo and use kRuntimeISA to produce InstructionSetFeatures.
+ static const Mips64InstructionSetFeatures* FromCpuInfo();
+
+ // Process the auxiliary vector AT_HWCAP entry and use kRuntimeISA to produce
+ // InstructionSetFeatures.
+ static const Mips64InstructionSetFeatures* FromHwcap();
+
+ // Use assembly tests of the current runtime (ie kRuntimeISA) to determine the
+ // InstructionSetFeatures. This works around kernel bugs in AT_HWCAP and /proc/cpuinfo.
+ static const Mips64InstructionSetFeatures* FromAssembly();
+
+ bool Equals(const InstructionSetFeatures* other) const OVERRIDE;
+
+ InstructionSet GetInstructionSet() const OVERRIDE {
+ return kMips64;
+ }
+
+ uint32_t AsBitmap() const OVERRIDE;
+
+ std::string GetFeatureString() const OVERRIDE;
+
+ virtual ~Mips64InstructionSetFeatures() {}
+
+ protected:
+ // Parse a vector of the form "fpu32", "mips2" adding these to a new Mips64InstructionSetFeatures.
+ virtual const InstructionSetFeatures*
+ AddFeaturesFromSplitString(const bool smp, const std::vector<std::string>& features,
+ std::string* error_msg) const OVERRIDE;
+
+ private:
+ explicit Mips64InstructionSetFeatures(bool smp) : InstructionSetFeatures(smp) {
+ }
+
+ // Bitmap positions for encoding features as a bitmap.
+ enum {
+ kSmpBitfield = 1,
+ };
+
+ DISALLOW_COPY_AND_ASSIGN(Mips64InstructionSetFeatures);
+};
+
+} // namespace art
+
+#endif // ART_RUNTIME_ARCH_MIPS64_INSTRUCTION_SET_FEATURES_MIPS64_H_
diff --git a/runtime/arch/mips64/instruction_set_features_mips64_test.cc b/runtime/arch/mips64/instruction_set_features_mips64_test.cc
new file mode 100644
index 0000000..dc34506
--- /dev/null
+++ b/runtime/arch/mips64/instruction_set_features_mips64_test.cc
@@ -0,0 +1,34 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "instruction_set_features_mips64.h"
+
+#include <gtest/gtest.h>
+
+namespace art {
+
+TEST(Mips64InstructionSetFeaturesTest, Mips64Features) {
+ std::string error_msg;
+ std::unique_ptr<const InstructionSetFeatures> mips64_features(
+ InstructionSetFeatures::FromVariant(kMips64, "default", &error_msg));
+ ASSERT_TRUE(mips64_features.get() != nullptr) << error_msg;
+ EXPECT_EQ(mips64_features->GetInstructionSet(), kMips64);
+ EXPECT_TRUE(mips64_features->Equals(mips64_features.get()));
+ EXPECT_STREQ("smp", mips64_features->GetFeatureString().c_str());
+ EXPECT_EQ(mips64_features->AsBitmap(), 1U);
+}
+
+} // namespace art
diff --git a/runtime/arch/mips64/quick_method_frame_info_mips64.h b/runtime/arch/mips64/quick_method_frame_info_mips64.h
new file mode 100644
index 0000000..281d5e6
--- /dev/null
+++ b/runtime/arch/mips64/quick_method_frame_info_mips64.h
@@ -0,0 +1,75 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ART_RUNTIME_ARCH_MIPS64_QUICK_METHOD_FRAME_INFO_MIPS64_H_
+#define ART_RUNTIME_ARCH_MIPS64_QUICK_METHOD_FRAME_INFO_MIPS64_H_
+
+#include "quick/quick_method_frame_info.h"
+#include "registers_mips64.h"
+#include "runtime.h" // for Runtime::CalleeSaveType.
+
+namespace art {
+namespace mips64 {
+
+static constexpr uint32_t kMips64CalleeSaveRefSpills =
+ (1 << art::mips64::S2) | (1 << art::mips64::S3) | (1 << art::mips64::S4) |
+ (1 << art::mips64::S5) | (1 << art::mips64::S6) | (1 << art::mips64::S7) |
+ (1 << art::mips64::GP) | (1 << art::mips64::S8);
+static constexpr uint32_t kMips64CalleeSaveArgSpills =
+ (1 << art::mips64::A1) | (1 << art::mips64::A2) | (1 << art::mips64::A3) |
+ (1 << art::mips64::A4) | (1 << art::mips64::A5) | (1 << art::mips64::A6) |
+ (1 << art::mips64::A7);
+static constexpr uint32_t kMips64CalleeSaveAllSpills =
+ (1 << art::mips64::S0) | (1 << art::mips64::S1);
+
+static constexpr uint32_t kMips64CalleeSaveFpRefSpills = 0;
+static constexpr uint32_t kMips64CalleeSaveFpArgSpills =
+ (1 << art::mips64::F12) | (1 << art::mips64::F13) | (1 << art::mips64::F14) |
+ (1 << art::mips64::F15) | (1 << art::mips64::F16) | (1 << art::mips64::F17) |
+ (1 << art::mips64::F18) | (1 << art::mips64::F19);
+static constexpr uint32_t kMips64CalleeSaveFpAllSpills =
+ (1 << art::mips64::F24) | (1 << art::mips64::F25) | (1 << art::mips64::F26) |
+ (1 << art::mips64::F27) | (1 << art::mips64::F28) | (1 << art::mips64::F29) |
+ (1 << art::mips64::F30) | (1 << art::mips64::F31);
+
+constexpr uint32_t Mips64CalleeSaveCoreSpills(Runtime::CalleeSaveType type) {
+ return kMips64CalleeSaveRefSpills |
+ (type == Runtime::kRefsAndArgs ? kMips64CalleeSaveArgSpills : 0) |
+ (type == Runtime::kSaveAll ? kMips64CalleeSaveAllSpills : 0) | (1 << art::mips64::RA);
+}
+
+constexpr uint32_t Mips64CalleeSaveFpSpills(Runtime::CalleeSaveType type) {
+ return kMips64CalleeSaveFpRefSpills |
+ (type == Runtime::kRefsAndArgs ? kMips64CalleeSaveFpArgSpills: 0) |
+ (type == Runtime::kSaveAll ? kMips64CalleeSaveFpAllSpills : 0);
+}
+
+constexpr uint32_t Mips64CalleeSaveFrameSize(Runtime::CalleeSaveType type) {
+ return RoundUp((POPCOUNT(Mips64CalleeSaveCoreSpills(type)) /* gprs */ +
+ POPCOUNT(Mips64CalleeSaveFpSpills(type)) /* fprs */ +
+ + 1 /* Method* */) * kMips64PointerSize, kStackAlignment);
+}
+
+constexpr QuickMethodFrameInfo Mips64CalleeSaveMethodFrameInfo(Runtime::CalleeSaveType type) {
+ return QuickMethodFrameInfo(Mips64CalleeSaveFrameSize(type),
+ Mips64CalleeSaveCoreSpills(type),
+ Mips64CalleeSaveFpSpills(type));
+}
+
+} // namespace mips64
+} // namespace art
+
+#endif // ART_RUNTIME_ARCH_MIPS64_QUICK_METHOD_FRAME_INFO_MIPS64_H_
diff --git a/runtime/arch/mips64/registers_mips64.cc b/runtime/arch/mips64/registers_mips64.cc
new file mode 100644
index 0000000..4959208
--- /dev/null
+++ b/runtime/arch/mips64/registers_mips64.cc
@@ -0,0 +1,50 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "registers_mips64.h"
+
+#include <ostream>
+
+namespace art {
+namespace mips64 {
+
+static const char* kRegisterNames[] = {
+ "zero", "at", "v0", "v1", "a0", "a1", "a2", "a3",
+ "a4", "a5", "a6", "a7", "t0", "t1", "t2", "t3",
+ "s0", "s1", "s2", "s3", "s4", "s5", "s6", "s7",
+ "t8", "t9", "k0", "k1", "gp", "sp", "s8", "ra",
+};
+
+std::ostream& operator<<(std::ostream& os, const GpuRegister& rhs) {
+ if (rhs >= ZERO && rhs < kNumberOfGpuRegisters) {
+ os << kRegisterNames[rhs];
+ } else {
+ os << "GpuRegister[" << static_cast<int>(rhs) << "]";
+ }
+ return os;
+}
+
+std::ostream& operator<<(std::ostream& os, const FpuRegister& rhs) {
+ if (rhs >= F0 && rhs < kNumberOfFpuRegisters) {
+ os << "f" << static_cast<int>(rhs);
+ } else {
+ os << "FpuRegister[" << static_cast<int>(rhs) << "]";
+ }
+ return os;
+}
+
+} // namespace mips64
+} // namespace art
diff --git a/runtime/arch/mips64/registers_mips64.h b/runtime/arch/mips64/registers_mips64.h
new file mode 100644
index 0000000..38bc8f2
--- /dev/null
+++ b/runtime/arch/mips64/registers_mips64.h
@@ -0,0 +1,109 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ART_RUNTIME_ARCH_MIPS64_REGISTERS_MIPS64_H_
+#define ART_RUNTIME_ARCH_MIPS64_REGISTERS_MIPS64_H_
+
+#include <iosfwd>
+
+#include "base/logging.h"
+#include "base/macros.h"
+#include "globals.h"
+
+namespace art {
+namespace mips64 {
+
+enum GpuRegister {
+ ZERO = 0,
+ AT = 1, // Assembler temporary.
+ V0 = 2, // Values.
+ V1 = 3,
+ A0 = 4, // Arguments.
+ A1 = 5,
+ A2 = 6,
+ A3 = 7,
+ A4 = 8,
+ A5 = 9,
+ A6 = 10,
+ A7 = 11,
+ T0 = 12, // Temporaries.
+ T1 = 13,
+ T2 = 14,
+ T3 = 15,
+ S0 = 16, // Saved values.
+ S1 = 17,
+ S2 = 18,
+ S3 = 19,
+ S4 = 20,
+ S5 = 21,
+ S6 = 22,
+ S7 = 23,
+ T8 = 24, // More temporaries.
+ T9 = 25,
+ K0 = 26, // Reserved for trap handler.
+ K1 = 27,
+ GP = 28, // Global pointer.
+ SP = 29, // Stack pointer.
+ S8 = 30, // Saved value/frame pointer.
+ RA = 31, // Return address.
+ kNumberOfGpuRegisters = 32,
+ kNoGpuRegister = -1 // Signals an illegal register.
+};
+std::ostream& operator<<(std::ostream& os, const GpuRegister& rhs);
+
+// Values for floating point registers.
+enum FpuRegister {
+ F0 = 0,
+ F1 = 1,
+ F2 = 2,
+ F3 = 3,
+ F4 = 4,
+ F5 = 5,
+ F6 = 6,
+ F7 = 7,
+ F8 = 8,
+ F9 = 9,
+ F10 = 10,
+ F11 = 11,
+ F12 = 12,
+ F13 = 13,
+ F14 = 14,
+ F15 = 15,
+ F16 = 16,
+ F17 = 17,
+ F18 = 18,
+ F19 = 19,
+ F20 = 20,
+ F21 = 21,
+ F22 = 22,
+ F23 = 23,
+ F24 = 24,
+ F25 = 25,
+ F26 = 26,
+ F27 = 27,
+ F28 = 28,
+ F29 = 29,
+ F30 = 30,
+ F31 = 31,
+ kNumberOfFpuRegisters = 32,
+ kNoFpuRegister = -1,
+};
+std::ostream& operator<<(std::ostream& os, const FpuRegister& rhs);
+
+} // namespace mips64
+} // namespace art
+
+#endif // ART_RUNTIME_ARCH_MIPS64_REGISTERS_MIPS64_H_
diff --git a/runtime/elf_file.cc b/runtime/elf_file.cc
index b6df609..1b91aa6 100644
--- a/runtime/elf_file.cc
+++ b/runtime/elf_file.cc
@@ -1335,6 +1335,8 @@ bool ElfFileImpl<Elf_Ehdr, Elf_Phdr, Elf_Shdr, Elf_Word,
if ((GetHeader().e_flags & EF_MIPS_ARCH) == EF_MIPS_ARCH_32R2 ||
(GetHeader().e_flags & EF_MIPS_ARCH) == EF_MIPS_ARCH_32R6) {
elf_ISA = kMips;
+ } else if ((GetHeader().e_flags & EF_MIPS_ARCH) == EF_MIPS_ARCH_64R6) {
+ elf_ISA = kMips64;
}
break;
}
diff --git a/runtime/elf_utils.h b/runtime/elf_utils.h
index 3579e27..418d937 100644
--- a/runtime/elf_utils.h
+++ b/runtime/elf_utils.h
@@ -31,6 +31,7 @@ namespace art {
#define EF_MIPS_ABI_O32 0x00001000
#define EF_MIPS_ARCH_32R2 0x70000000
#define EF_MIPS_ARCH_32R6 0x90000000
+#define EF_MIPS_ARCH_64R6 0xa0000000
#define EI_ABIVERSION 8
#define EM_ARM 40
diff --git a/runtime/entrypoints/quick/callee_save_frame.h b/runtime/entrypoints/quick/callee_save_frame.h
index 9ffd199..8cd6ca6 100644
--- a/runtime/entrypoints/quick/callee_save_frame.h
+++ b/runtime/entrypoints/quick/callee_save_frame.h
@@ -27,6 +27,7 @@
#include "arch/arm/quick_method_frame_info_arm.h"
#include "arch/arm64/quick_method_frame_info_arm64.h"
#include "arch/mips/quick_method_frame_info_mips.h"
+#include "arch/mips64/quick_method_frame_info_mips64.h"
#include "arch/x86/quick_method_frame_info_x86.h"
#include "arch/x86_64/quick_method_frame_info_x86_64.h"
@@ -76,6 +77,7 @@ static constexpr size_t GetCalleeSaveFrameSize(InstructionSet isa, Runtime::Call
return (isa == kArm || isa == kThumb2) ? arm::ArmCalleeSaveFrameSize(type) :
isa == kArm64 ? arm64::Arm64CalleeSaveFrameSize(type) :
isa == kMips ? mips::MipsCalleeSaveFrameSize(type) :
+ isa == kMips64 ? mips64::Mips64CalleeSaveFrameSize(type) :
isa == kX86 ? x86::X86CalleeSaveFrameSize(type) :
isa == kX86_64 ? x86_64::X86_64CalleeSaveFrameSize(type) :
isa == kNone ? (LOG(FATAL) << "kNone has no frame size", 0) :
@@ -88,6 +90,7 @@ static constexpr size_t GetConstExprPointerSize(InstructionSet isa) {
return (isa == kArm || isa == kThumb2) ? kArmPointerSize :
isa == kArm64 ? kArm64PointerSize :
isa == kMips ? kMipsPointerSize :
+ isa == kMips64 ? kMips64PointerSize :
isa == kX86 ? kX86PointerSize :
isa == kX86_64 ? kX86_64PointerSize :
isa == kNone ? (LOG(FATAL) << "kNone has no pointer size", 0) :
diff --git a/runtime/runtime.cc b/runtime/runtime.cc
index fabbbfb..e531091 100644
--- a/runtime/runtime.cc
+++ b/runtime/runtime.cc
@@ -40,6 +40,8 @@
#include "arch/instruction_set_features.h"
#include "arch/mips/quick_method_frame_info_mips.h"
#include "arch/mips/registers_mips.h"
+#include "arch/mips64/quick_method_frame_info_mips64.h"
+#include "arch/mips64/registers_mips64.h"
#include "arch/x86/quick_method_frame_info_x86.h"
#include "arch/x86/registers_x86.h"
#include "arch/x86_64/quick_method_frame_info_x86_64.h"
@@ -1356,6 +1358,11 @@ void Runtime::SetInstructionSet(InstructionSet instruction_set) {
CalleeSaveType type = static_cast<CalleeSaveType>(i);
callee_save_method_frame_infos_[i] = mips::MipsCalleeSaveMethodFrameInfo(type);
}
+ } else if (instruction_set_ == kMips64) {
+ for (int i = 0; i != kLastCalleeSaveType; ++i) {
+ CalleeSaveType type = static_cast<CalleeSaveType>(i);
+ callee_save_method_frame_infos_[i] = mips64::Mips64CalleeSaveMethodFrameInfo(type);
+ }
} else if (instruction_set_ == kX86) {
for (int i = 0; i != kLastCalleeSaveType; ++i) {
CalleeSaveType type = static_cast<CalleeSaveType>(i);