diff options
author | 2023-01-25 15:55:55 +0000 | |
---|---|---|
committer | 2023-02-10 11:45:20 +0000 | |
commit | 910c95fe2dd57bc0d70c78bdc0c6cdf4d21ce700 (patch) | |
tree | f075185c2f65183a6f579c759348260d7043f6a2 | |
parent | c137762c96cb8329ea95e1dda27b0a2d9c1f3228 (diff) |
riscv64: define instruction set features.
At the moment we assume the basic extension set G (IMAFD) plus the C
extension (compression). V extension (vector) is also defined, but not
assumed by default.
Test: lunch aosp_riscv64-userdebug && m dist
Co-authored-by: Ulya Trafimovich <skvadrik@google.com>
Change-Id: Ie3e7c1d5ad8e720d8bcab28a82fc602005efbb7f
-rw-r--r-- | runtime/Android.bp | 4 | ||||
-rw-r--r-- | runtime/arch/instruction_set_features.cc | 30 | ||||
-rw-r--r-- | runtime/arch/instruction_set_features.h | 4 | ||||
-rw-r--r-- | runtime/arch/riscv64/instruction_set_features_riscv64.cc | 99 | ||||
-rw-r--r-- | runtime/arch/riscv64/instruction_set_features_riscv64.h | 84 | ||||
-rw-r--r-- | runtime/arch/riscv64/instruction_set_features_riscv64_test.cc | 38 |
6 files changed, 252 insertions, 7 deletions
diff --git a/runtime/Android.bp b/runtime/Android.bp index 18b7252c6c..c4fb600397 100644 --- a/runtime/Android.bp +++ b/runtime/Android.bp @@ -310,8 +310,9 @@ libart_cc_defaults { "arch/arm/registers_arm.cc", "arch/arm64/instruction_set_features_arm64.cc", "arch/arm64/registers_arm64.cc", - "arch/x86/instruction_set_features_x86.cc", + "arch/riscv64/instruction_set_features_riscv64.cc", "arch/riscv64/registers_riscv64.cc", + "arch/x86/instruction_set_features_x86.cc", "arch/x86/registers_x86.cc", "arch/x86_64/registers_x86_64.cc", "entrypoints/entrypoint_utils.cc", @@ -821,6 +822,7 @@ art_cc_defaults { "arch/instruction_set_features_test.cc", "arch/memcmp16_test.cc", "arch/stub_test.cc", + "arch/riscv64/instruction_set_features_riscv64_test.cc", "arch/x86/instruction_set_features_x86_test.cc", "arch/x86_64/instruction_set_features_x86_64_test.cc", "art_method_test.cc", diff --git a/runtime/arch/instruction_set_features.cc b/runtime/arch/instruction_set_features.cc index 7a1e6b05ad..d88c544b35 100644 --- a/runtime/arch/instruction_set_features.cc +++ b/runtime/arch/instruction_set_features.cc @@ -14,20 +14,17 @@ * limitations under the License. */ -#include <algorithm> - #include "instruction_set_features.h" #include <algorithm> #include <ostream> #include "android-base/strings.h" - -#include "base/casts.h" -#include "base/utils.h" - #include "arm/instruction_set_features_arm.h" #include "arm64/instruction_set_features_arm64.h" +#include "base/casts.h" +#include "base/utils.h" +#include "riscv64/instruction_set_features_riscv64.h" #include "x86/instruction_set_features_x86.h" #include "x86_64/instruction_set_features_x86_64.h" @@ -41,6 +38,8 @@ std::unique_ptr<const InstructionSetFeatures> InstructionSetFeatures::FromVarian return ArmInstructionSetFeatures::FromVariant(variant, error_msg); case InstructionSet::kArm64: return Arm64InstructionSetFeatures::FromVariant(variant, error_msg); + case InstructionSet::kRiscv64: + return Riscv64InstructionSetFeatures::FromVariant(variant, error_msg); case InstructionSet::kX86: return X86InstructionSetFeatures::FromVariant(variant, error_msg); case InstructionSet::kX86_64: @@ -91,6 +90,9 @@ std::unique_ptr<const InstructionSetFeatures> InstructionSetFeatures::FromBitmap case InstructionSet::kArm64: result = Arm64InstructionSetFeatures::FromBitmap(bitmap); break; + case InstructionSet::kRiscv64: + result = Riscv64InstructionSetFeatures::FromBitmap(bitmap); + break; case InstructionSet::kX86: result = X86InstructionSetFeatures::FromBitmap(bitmap); break; @@ -113,6 +115,8 @@ std::unique_ptr<const InstructionSetFeatures> InstructionSetFeatures::FromCppDef return ArmInstructionSetFeatures::FromCppDefines(); case InstructionSet::kArm64: return Arm64InstructionSetFeatures::FromCppDefines(); + case InstructionSet::kRiscv64: + return Riscv64InstructionSetFeatures::FromCppDefines(); case InstructionSet::kX86: return X86InstructionSetFeatures::FromCppDefines(); case InstructionSet::kX86_64: @@ -143,6 +147,8 @@ std::unique_ptr<const InstructionSetFeatures> InstructionSetFeatures::FromCpuInf return ArmInstructionSetFeatures::FromCpuInfo(); case InstructionSet::kArm64: return Arm64InstructionSetFeatures::FromCpuInfo(); + case InstructionSet::kRiscv64: + return Riscv64InstructionSetFeatures::FromCpuInfo(); case InstructionSet::kX86: return X86InstructionSetFeatures::FromCpuInfo(); case InstructionSet::kX86_64: @@ -162,6 +168,8 @@ std::unique_ptr<const InstructionSetFeatures> InstructionSetFeatures::FromHwcap( return ArmInstructionSetFeatures::FromHwcap(); case InstructionSet::kArm64: return Arm64InstructionSetFeatures::FromHwcap(); + case InstructionSet::kRiscv64: + return Riscv64InstructionSetFeatures::FromHwcap(); case InstructionSet::kX86: return X86InstructionSetFeatures::FromHwcap(); case InstructionSet::kX86_64: @@ -181,6 +189,8 @@ std::unique_ptr<const InstructionSetFeatures> InstructionSetFeatures::FromAssemb return ArmInstructionSetFeatures::FromAssembly(); case InstructionSet::kArm64: return Arm64InstructionSetFeatures::FromAssembly(); + case InstructionSet::kRiscv64: + return Riscv64InstructionSetFeatures::FromAssembly(); case InstructionSet::kX86: return X86InstructionSetFeatures::FromAssembly(); case InstructionSet::kX86_64: @@ -200,6 +210,8 @@ std::unique_ptr<const InstructionSetFeatures> InstructionSetFeatures::FromCpuFea return ArmInstructionSetFeatures::FromCpuFeatures(); case InstructionSet::kArm64: return Arm64InstructionSetFeatures::FromCpuFeatures(); + case InstructionSet::kRiscv64: + return Riscv64InstructionSetFeatures::FromCpuFeatures(); case InstructionSet::kX86: return X86InstructionSetFeatures::FromCpuFeatures(); case InstructionSet::kX86_64: @@ -276,6 +288,12 @@ const Arm64InstructionSetFeatures* InstructionSetFeatures::AsArm64InstructionSet return down_cast<const Arm64InstructionSetFeatures*>(this); } +const Riscv64InstructionSetFeatures* InstructionSetFeatures::AsRiscv64InstructionSetFeatures() + const { + DCHECK_EQ(InstructionSet::kRiscv64, GetInstructionSet()); + return down_cast<const Riscv64InstructionSetFeatures*>(this); +} + const X86InstructionSetFeatures* InstructionSetFeatures::AsX86InstructionSetFeatures() const { DCHECK(InstructionSet::kX86 == GetInstructionSet() || InstructionSet::kX86_64 == GetInstructionSet()); diff --git a/runtime/arch/instruction_set_features.h b/runtime/arch/instruction_set_features.h index cee8c5d42f..1f41b39023 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 Riscv64InstructionSetFeatures; class X86InstructionSetFeatures; class X86_64InstructionSetFeatures; @@ -121,6 +122,9 @@ class InstructionSetFeatures { // Down cast this Arm64InstructionFeatures. const Arm64InstructionSetFeatures* AsArm64InstructionSetFeatures() const; + // Down cast this Riscv64InstructionFeatures. + const Riscv64InstructionSetFeatures* AsRiscv64InstructionSetFeatures() const; + // Down cast this X86InstructionFeatures. const X86InstructionSetFeatures* AsX86InstructionSetFeatures() const; diff --git a/runtime/arch/riscv64/instruction_set_features_riscv64.cc b/runtime/arch/riscv64/instruction_set_features_riscv64.cc new file mode 100644 index 0000000000..2ef4f8493d --- /dev/null +++ b/runtime/arch/riscv64/instruction_set_features_riscv64.cc @@ -0,0 +1,99 @@ +/* + * Copyright (C) 2023 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_riscv64.h" + +#include <fstream> +#include <sstream> + +#include "android-base/strings.h" +#include "base/logging.h" + +namespace art { + +// Basic feature set is rv64gc, aka rv64imafdc. +constexpr uint32_t BasicFeatures() { + return Riscv64InstructionSetFeatures::kExtGeneric | Riscv64InstructionSetFeatures::kExtCompressed; +} + +Riscv64FeaturesUniquePtr Riscv64InstructionSetFeatures::FromVariant( + const std::string& variant, std::string* error_msg ATTRIBUTE_UNUSED) { + if (variant != "generic") { + LOG(WARNING) << "Unexpected CPU variant for Riscv64 using defaults: " << variant; + } + return Riscv64FeaturesUniquePtr(new Riscv64InstructionSetFeatures(BasicFeatures())); +} + +Riscv64FeaturesUniquePtr Riscv64InstructionSetFeatures::FromBitmap(uint32_t bitmap) { + return Riscv64FeaturesUniquePtr(new Riscv64InstructionSetFeatures(bitmap)); +} + +Riscv64FeaturesUniquePtr Riscv64InstructionSetFeatures::FromCppDefines() { + return Riscv64FeaturesUniquePtr(new Riscv64InstructionSetFeatures(BasicFeatures())); +} + +Riscv64FeaturesUniquePtr Riscv64InstructionSetFeatures::FromCpuInfo() { + UNIMPLEMENTED(WARNING); + return FromCppDefines(); +} + +Riscv64FeaturesUniquePtr Riscv64InstructionSetFeatures::FromHwcap() { + UNIMPLEMENTED(WARNING); + return FromCppDefines(); +} + +Riscv64FeaturesUniquePtr Riscv64InstructionSetFeatures::FromAssembly() { + UNIMPLEMENTED(WARNING); + return FromCppDefines(); +} + +Riscv64FeaturesUniquePtr Riscv64InstructionSetFeatures::FromCpuFeatures() { + UNIMPLEMENTED(WARNING); + return FromCppDefines(); +} + +bool Riscv64InstructionSetFeatures::Equals(const InstructionSetFeatures* other) const { + if (InstructionSet::kRiscv64 != other->GetInstructionSet()) { + return false; + } + return bits_ == other->AsRiscv64InstructionSetFeatures()->bits_; +} + +uint32_t Riscv64InstructionSetFeatures::AsBitmap() const { return bits_; } + +std::string Riscv64InstructionSetFeatures::GetFeatureString() const { + std::string result = "rv64"; + if (bits_ & kExtGeneric) { + result += "g"; + } + if (bits_ & kExtCompressed) { + result += "c"; + } + if (bits_ & kExtVector) { + result += "v"; + } + return result; +} + +std::unique_ptr<const InstructionSetFeatures> +Riscv64InstructionSetFeatures::AddFeaturesFromSplitString( + const std::vector<std::string>& features ATTRIBUTE_UNUSED, + std::string* error_msg ATTRIBUTE_UNUSED) const { + UNIMPLEMENTED(WARNING); + return std::unique_ptr<const InstructionSetFeatures>(new Riscv64InstructionSetFeatures(bits_)); +} + +} // namespace art diff --git a/runtime/arch/riscv64/instruction_set_features_riscv64.h b/runtime/arch/riscv64/instruction_set_features_riscv64.h new file mode 100644 index 0000000000..1ad2ffd830 --- /dev/null +++ b/runtime/arch/riscv64/instruction_set_features_riscv64.h @@ -0,0 +1,84 @@ +/* + * Copyright (C) 2023 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_RISCV64_INSTRUCTION_SET_FEATURES_RISCV64_H_ +#define ART_RUNTIME_ARCH_RISCV64_INSTRUCTION_SET_FEATURES_RISCV64_H_ + +#include "arch/instruction_set_features.h" + +namespace art { + +class Riscv64InstructionSetFeatures; +using Riscv64FeaturesUniquePtr = std::unique_ptr<const Riscv64InstructionSetFeatures>; + +// Instruction set features relevant to the RISCV64 architecture. +class Riscv64InstructionSetFeatures final : public InstructionSetFeatures { + public: + // Bitmap positions for encoding features as a bitmap. + enum { + kExtGeneric = (1 << 0), // G extension covers the basic set IMAFD + kExtCompressed = (1 << 1), // C extension adds compressed instructions + kExtVector = (1 << 2) // V extension adds vector instructions + }; + + static Riscv64FeaturesUniquePtr FromVariant(const std::string& variant, std::string* error_msg); + + // Parse a bitmap and create an InstructionSetFeatures. + static Riscv64FeaturesUniquePtr FromBitmap(uint32_t bitmap); + + // Turn C pre-processor #defines into the equivalent instruction set features. + static Riscv64FeaturesUniquePtr FromCppDefines(); + + // Process /proc/cpuinfo and use kRuntimeISA to produce InstructionSetFeatures. + static Riscv64FeaturesUniquePtr FromCpuInfo(); + + // Process the auxiliary vector AT_HWCAP entry and use kRuntimeISA to produce + // InstructionSetFeatures. + static Riscv64FeaturesUniquePtr 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 Riscv64FeaturesUniquePtr FromAssembly(); + + // Use external cpu_features library. + static Riscv64FeaturesUniquePtr FromCpuFeatures(); + + bool Equals(const InstructionSetFeatures* other) const override; + + InstructionSet GetInstructionSet() const override { return InstructionSet::kRiscv64; } + + uint32_t AsBitmap() const override; + + std::string GetFeatureString() const override; + + virtual ~Riscv64InstructionSetFeatures() {} + + protected: + std::unique_ptr<const InstructionSetFeatures> AddFeaturesFromSplitString( + const std::vector<std::string>& features, std::string* error_msg) const override; + + private: + explicit Riscv64InstructionSetFeatures(uint32_t bits) : InstructionSetFeatures(), bits_(bits) {} + + // Extension bitmap. + const uint32_t bits_; + + DISALLOW_COPY_AND_ASSIGN(Riscv64InstructionSetFeatures); +}; + +} // namespace art + +#endif // ART_RUNTIME_ARCH_RISCV64_INSTRUCTION_SET_FEATURES_RISCV64_H_ diff --git a/runtime/arch/riscv64/instruction_set_features_riscv64_test.cc b/runtime/arch/riscv64/instruction_set_features_riscv64_test.cc new file mode 100644 index 0000000000..aef3d67c00 --- /dev/null +++ b/runtime/arch/riscv64/instruction_set_features_riscv64_test.cc @@ -0,0 +1,38 @@ +/* + * Copyright (C) 2023 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_riscv64.h" + +#include <gtest/gtest.h> + +namespace art { + +TEST(Riscv64InstructionSetFeaturesTest, Riscv64FeaturesFromDefaultVariant) { + std::string error_msg; + std::unique_ptr<const InstructionSetFeatures> riscv64_features( + InstructionSetFeatures::FromVariant(InstructionSet::kRiscv64, "generic", &error_msg)); + ASSERT_TRUE(riscv64_features.get() != nullptr) << error_msg; + + EXPECT_EQ(riscv64_features->GetInstructionSet(), InstructionSet::kRiscv64); + + EXPECT_TRUE(riscv64_features->Equals(riscv64_features.get())); + + uint32_t expected_extensions = + Riscv64InstructionSetFeatures::kExtGeneric | Riscv64InstructionSetFeatures::kExtCompressed; + EXPECT_EQ(riscv64_features->AsBitmap(), expected_extensions); // rv64gc, aka rv64imafdc +} + +} // namespace art |