diff options
author | Andreas Gampe <agampe@google.com> | 2015-01-14 15:45:59 -0800 |
---|---|---|
committer | Andreas Gampe <agampe@google.com> | 2015-01-15 11:32:48 -0800 |
commit | 57b34294758e9c00993913ebe43c7ee4698a5cc6 (patch) | |
tree | 981821619027686f83fbe00445299b0522f1df05 /runtime | |
parent | 4945bfef00ac446d9c5458e55500229d463ab4c3 (diff) | |
download | art-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.mk | 2 | ||||
-rw-r--r-- | runtime/arch/instruction_set.cc | 8 | ||||
-rw-r--r-- | runtime/arch/instruction_set.h | 16 | ||||
-rw-r--r-- | runtime/arch/instruction_set_features.cc | 24 | ||||
-rw-r--r-- | runtime/arch/instruction_set_features.h | 4 | ||||
-rw-r--r-- | runtime/arch/instruction_set_test.cc | 2 | ||||
-rw-r--r-- | runtime/arch/mips64/instruction_set_features_mips64.cc | 116 | ||||
-rw-r--r-- | runtime/arch/mips64/instruction_set_features_mips64.h | 80 | ||||
-rw-r--r-- | runtime/arch/mips64/instruction_set_features_mips64_test.cc | 34 | ||||
-rw-r--r-- | runtime/arch/mips64/quick_method_frame_info_mips64.h | 75 | ||||
-rw-r--r-- | runtime/arch/mips64/registers_mips64.cc | 50 | ||||
-rw-r--r-- | runtime/arch/mips64/registers_mips64.h | 109 | ||||
-rw-r--r-- | runtime/elf_file.cc | 2 | ||||
-rw-r--r-- | runtime/elf_utils.h | 1 | ||||
-rw-r--r-- | runtime/entrypoints/quick/callee_save_frame.h | 3 | ||||
-rw-r--r-- | runtime/runtime.cc | 7 |
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); |