summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Samuel Holland <samuel.holland@sifive.com> 2023-10-18 14:53:08 -0700
committer Samuel Holland <samuel.holland@sifive.com> 2023-10-20 13:11:58 -0700
commit4e700fbd656c0f5ae928f776cbb79b4a0e42f97c (patch)
tree83fd1c4ae44bae5e6aa9e82c470509f1531b6535
parent9465d1c60d004b0734127678821198ab198742bf (diff)
riscv64: Implement Riscv64InstructionSetFeatures::AddFeaturesFromSplitString
This only parses a subset of the ISA string format: the known extensions in their canonical order, as generated by GetFeatureString. The ISA string is assumed to be complete, so when present we ignore the existing value of bits_. To simplify future changes, reuse kExtensionList in GetFeatureString. Test: m test-art-host-gtest-art_runtime_tests64 Change-Id: I0e9cd0423d9850d2b4f81c338743b82d488c4fa4
-rw-r--r--runtime/arch/riscv64/instruction_set_features_riscv64.cc49
-rw-r--r--runtime/arch/riscv64/instruction_set_features_riscv64.h7
-rw-r--r--runtime/arch/riscv64/instruction_set_features_riscv64_test.cc17
3 files changed, 59 insertions, 14 deletions
diff --git a/runtime/arch/riscv64/instruction_set_features_riscv64.cc b/runtime/arch/riscv64/instruction_set_features_riscv64.cc
index 7e5299dce4..947ea54ddb 100644
--- a/runtime/arch/riscv64/instruction_set_features_riscv64.cc
+++ b/runtime/arch/riscv64/instruction_set_features_riscv64.cc
@@ -19,11 +19,14 @@
#include <fstream>
#include <sstream>
+#include "android-base/stringprintf.h"
#include "android-base/strings.h"
#include "base/logging.h"
namespace art {
+using android::base::StringPrintf;
+
// Basic feature set is rv64gcv, aka rv64imafdcv.
constexpr uint32_t BasicFeatures() {
return Riscv64InstructionSetFeatures::kExtGeneric |
@@ -83,26 +86,44 @@ bool Riscv64InstructionSetFeatures::Equals(const InstructionSetFeatures* other)
uint32_t Riscv64InstructionSetFeatures::AsBitmap() const { return bits_; }
+static const std::pair<uint32_t, std::string> kExtensionList[] = {
+ {Riscv64InstructionSetFeatures::kExtGeneric, "rv64g"},
+ {Riscv64InstructionSetFeatures::kExtCompressed, "c"},
+ {Riscv64InstructionSetFeatures::kExtVector, "v"},
+};
+
std::string Riscv64InstructionSetFeatures::GetFeatureString() const {
- std::string result = "rv64";
- if (bits_ & kExtGeneric) {
- result += "g";
- }
- if (bits_ & kExtCompressed) {
- result += "c";
- }
- if (bits_ & kExtVector) {
- result += "v";
+ std::string result = "";
+ for (auto&& [ext_bit, ext_string] : kExtensionList) {
+ if (bits_ & ext_bit) {
+ result += ext_string;
+ }
}
return result;
}
std::unique_ptr<const InstructionSetFeatures>
-Riscv64InstructionSetFeatures::AddFeaturesFromSplitString(
- [[maybe_unused]] const std::vector<std::string>& features,
- [[maybe_unused]] std::string* error_msg) const {
- UNIMPLEMENTED(WARNING);
- return std::unique_ptr<const InstructionSetFeatures>(new Riscv64InstructionSetFeatures(bits_));
+Riscv64InstructionSetFeatures::AddFeaturesFromSplitString(const std::vector<std::string>& features,
+ std::string* error_msg) const {
+ uint32_t bits = bits_;
+ if (!features.empty()) {
+ // There should be only one feature, the ISA string.
+ DCHECK_EQ(features.size(), 1U);
+ std::string_view isa_string = features.front();
+ bits = 0;
+ for (auto&& [ext_bit, ext_string] : kExtensionList) {
+ if (isa_string.substr(0, ext_string.length()) == ext_string) {
+ isa_string.remove_prefix(ext_string.length());
+ bits |= ext_bit;
+ }
+ }
+ if (!isa_string.empty()) {
+ *error_msg = StringPrintf("Unknown extension in ISA string: '%s'", features.front().c_str());
+ return nullptr;
+ }
+ DCHECK(bits & kExtGeneric);
+ }
+ return FromBitmap(bits);
}
} // namespace art
diff --git a/runtime/arch/riscv64/instruction_set_features_riscv64.h b/runtime/arch/riscv64/instruction_set_features_riscv64.h
index 1ad2ffd830..56c41f085b 100644
--- a/runtime/arch/riscv64/instruction_set_features_riscv64.h
+++ b/runtime/arch/riscv64/instruction_set_features_riscv64.h
@@ -67,6 +67,13 @@ class Riscv64InstructionSetFeatures final : public InstructionSetFeatures {
virtual ~Riscv64InstructionSetFeatures() {}
protected:
+ // If `features` is empty, this method doesn't add/remove anything from the
+ // existing set of features.
+ // If `features` is not empty, this method expects it to have exactly one value
+ // which is assumed to be a complete and valid features string. In this case, the
+ // new features will override the old ones. For example, if the existing set of
+ // features were `rv64gcv_zba_zbb_zbs` but `features` is `{"rv64gcv"}`, then the
+ // new features will not have the bits set for Zba, Zbb, or Zbs.
std::unique_ptr<const InstructionSetFeatures> AddFeaturesFromSplitString(
const std::vector<std::string>& features, std::string* error_msg) const override;
diff --git a/runtime/arch/riscv64/instruction_set_features_riscv64_test.cc b/runtime/arch/riscv64/instruction_set_features_riscv64_test.cc
index 0f0cbda8b7..fd9e83b81a 100644
--- a/runtime/arch/riscv64/instruction_set_features_riscv64_test.cc
+++ b/runtime/arch/riscv64/instruction_set_features_riscv64_test.cc
@@ -37,4 +37,21 @@ TEST(Riscv64InstructionSetFeaturesTest, Riscv64FeaturesFromDefaultVariant) {
EXPECT_EQ(riscv64_features->AsBitmap(), expected_extensions);
}
+TEST(Riscv64InstructionSetFeaturesTest, Riscv64FeaturesFromString) {
+ std::string error_msg;
+ std::unique_ptr<const InstructionSetFeatures> generic_features(
+ InstructionSetFeatures::FromVariant(InstructionSet::kRiscv64, "generic", &error_msg));
+ ASSERT_TRUE(generic_features.get() != nullptr) << error_msg;
+
+ std::unique_ptr<const InstructionSetFeatures> rv64gv_features(
+ generic_features->AddFeaturesFromString("rv64gv", &error_msg));
+ ASSERT_TRUE(rv64gv_features.get() != nullptr) << error_msg;
+
+ EXPECT_FALSE(generic_features->Equals(rv64gv_features.get()));
+
+ uint32_t expected_extensions = Riscv64InstructionSetFeatures::kExtGeneric |
+ Riscv64InstructionSetFeatures::kExtVector;
+ EXPECT_EQ(rv64gv_features->AsBitmap(), expected_extensions);
+}
+
} // namespace art