1 /*
2 * Copyright (C) 2023 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 #include "instruction_set_features_riscv64.h"
18
19 #include <fstream>
20 #include <sstream>
21
22 #include "android-base/stringprintf.h"
23 #include "android-base/strings.h"
24 #include "base/logging.h"
25
26 namespace art HIDDEN {
27
28 using android::base::StringPrintf;
29
30 // Basic feature set is rv64gcv_zba_zbb_zbs, aka rv64imafdcv_zba_zbb_zbs.
BasicFeatures()31 constexpr uint32_t BasicFeatures() {
32 return Riscv64InstructionSetFeatures::kExtGeneric |
33 Riscv64InstructionSetFeatures::kExtCompressed |
34 Riscv64InstructionSetFeatures::kExtVector |
35 Riscv64InstructionSetFeatures::kExtZba |
36 Riscv64InstructionSetFeatures::kExtZbb |
37 Riscv64InstructionSetFeatures::kExtZbs;
38 }
39
FromVariant(const std::string & variant,std::string * error_msg)40 Riscv64FeaturesUniquePtr Riscv64InstructionSetFeatures::FromVariant(
41 const std::string& variant, [[maybe_unused]] std::string* error_msg) {
42 if (variant != "generic") {
43 LOG(WARNING) << "Unexpected CPU variant for Riscv64 using defaults: " << variant;
44 }
45 return Riscv64FeaturesUniquePtr(new Riscv64InstructionSetFeatures(BasicFeatures()));
46 }
47
FromBitmap(uint32_t bitmap)48 Riscv64FeaturesUniquePtr Riscv64InstructionSetFeatures::FromBitmap(uint32_t bitmap) {
49 return Riscv64FeaturesUniquePtr(new Riscv64InstructionSetFeatures(bitmap));
50 }
51
FromCppDefines()52 Riscv64FeaturesUniquePtr Riscv64InstructionSetFeatures::FromCppDefines() {
53 // Assume kExtGeneric is always present.
54 uint32_t bits = kExtGeneric;
55 #ifdef __riscv_c
56 bits |= kExtCompressed;
57 #endif
58 #ifdef __riscv_v
59 bits |= kExtVector;
60 #endif
61 #ifdef __riscv_zba
62 bits |= kExtZba;
63 #endif
64 #ifdef __riscv_zbb
65 bits |= kExtZbb;
66 #endif
67 #ifdef __riscv_zbs
68 bits |= kExtZbs;
69 #endif
70 return FromBitmap(bits);
71 }
72
FromCpuInfo()73 Riscv64FeaturesUniquePtr Riscv64InstructionSetFeatures::FromCpuInfo() {
74 UNIMPLEMENTED(WARNING);
75 return FromCppDefines();
76 }
77
FromHwcap()78 Riscv64FeaturesUniquePtr Riscv64InstructionSetFeatures::FromHwcap() {
79 UNIMPLEMENTED(WARNING);
80 return FromCppDefines();
81 }
82
FromAssembly()83 Riscv64FeaturesUniquePtr Riscv64InstructionSetFeatures::FromAssembly() {
84 UNIMPLEMENTED(WARNING);
85 return FromCppDefines();
86 }
87
FromCpuFeatures()88 Riscv64FeaturesUniquePtr Riscv64InstructionSetFeatures::FromCpuFeatures() {
89 UNIMPLEMENTED(WARNING);
90 return FromCppDefines();
91 }
92
Equals(const InstructionSetFeatures * other) const93 bool Riscv64InstructionSetFeatures::Equals(const InstructionSetFeatures* other) const {
94 if (InstructionSet::kRiscv64 != other->GetInstructionSet()) {
95 return false;
96 }
97 return bits_ == other->AsRiscv64InstructionSetFeatures()->bits_;
98 }
99
AsBitmap() const100 uint32_t Riscv64InstructionSetFeatures::AsBitmap() const { return bits_; }
101
102 static const std::pair<uint32_t, std::string> kExtensionList[] = {
103 {Riscv64InstructionSetFeatures::kExtGeneric, "rv64g"},
104 {Riscv64InstructionSetFeatures::kExtCompressed, "c"},
105 {Riscv64InstructionSetFeatures::kExtVector, "v"},
106 {Riscv64InstructionSetFeatures::kExtZba, "_zba"},
107 {Riscv64InstructionSetFeatures::kExtZbb, "_zbb"},
108 {Riscv64InstructionSetFeatures::kExtZbs, "_zbs"},
109 };
110
GetFeatureString() const111 std::string Riscv64InstructionSetFeatures::GetFeatureString() const {
112 std::string result = "";
113 for (auto&& [ext_bit, ext_string] : kExtensionList) {
114 if (bits_ & ext_bit) {
115 result += ext_string;
116 }
117 }
118 return result;
119 }
120
121 std::unique_ptr<const InstructionSetFeatures>
AddFeaturesFromSplitString(const std::vector<std::string> & features,std::string * error_msg) const122 Riscv64InstructionSetFeatures::AddFeaturesFromSplitString(const std::vector<std::string>& features,
123 std::string* error_msg) const {
124 uint32_t bits = bits_;
125 if (!features.empty()) {
126 // There should be only one feature, the ISA string.
127 DCHECK_EQ(features.size(), 1U);
128 std::string_view isa_string = features.front();
129 bits = 0;
130 for (auto&& [ext_bit, ext_string] : kExtensionList) {
131 if (isa_string.substr(0, ext_string.length()) == ext_string) {
132 isa_string.remove_prefix(ext_string.length());
133 bits |= ext_bit;
134 }
135 }
136 if (!isa_string.empty()) {
137 *error_msg = StringPrintf("Unknown extension in ISA string: '%s'", features.front().c_str());
138 return nullptr;
139 }
140 DCHECK(bits & kExtGeneric);
141 }
142 return FromBitmap(bits);
143 }
144
145 } // namespace art
146