1 /*
2 * Copyright (c) 1997, 2026, Oracle and/or its affiliates. All rights reserved.
3 * Copyright (c) 2014, 2020, Red Hat Inc. All rights reserved.
4 * Copyright (c) 2020, 2023, Huawei Technologies Co., Ltd. All rights reserved.
5 * Copyright (c) 2023, Rivos Inc. All rights reserved.
6 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
7 *
8 * This code is free software; you can redistribute it and/or modify it
9 * under the terms of the GNU General Public License version 2 only, as
10 * published by the Free Software Foundation.
11 *
12 * This code is distributed in the hope that it will be useful, but WITHOUT
13 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
14 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
15 * version 2 for more details (a copy is included in the LICENSE file that
16 * accompanied this code).
17 *
18 * You should have received a copy of the GNU General Public License version
19 * 2 along with this work; if not, write to the Free Software Foundation,
20 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
21 *
22 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
23 * or visit www.oracle.com if you need additional information or have any
24 * questions.
25 *
26 */
27
28 #ifndef CPU_RISCV_VM_VERSION_RISCV_HPP
29 #define CPU_RISCV_VM_VERSION_RISCV_HPP
30
31 #include "runtime/abstract_vm_version.hpp"
32 #include "runtime/arguments.hpp"
33 #include "runtime/globals_extension.hpp"
34 #include "utilities/globalDefinitions.hpp"
35 #include "utilities/ostream.hpp"
36 #include "utilities/sizes.hpp"
37
38 class RiscvHwprobe;
39
40 class VM_Version : public Abstract_VM_Version {
41 friend RiscvHwprobe;
42 private:
43
44 // JEDEC encoded as ((bank - 1) << 7) | (0x7f & JEDEC)
45 enum VendorId {
46 RIVOS = 0x6cf, // JEDEC: 0x4f, Bank: 14
47 };
48
49 class RVExtFeatures;
50
51 class RVFeatureValue {
52 const char* const _pretty;
53 const bool _feature_string;
54 const uint64_t _linux_feature_bit;
55
56 public:
57 RVFeatureValue(const char* pretty, int linux_bit_num, bool fstring) :
58 _pretty(pretty), _feature_string(fstring), _linux_feature_bit(nth_bit<uint64_t>(linux_bit_num)) {
59 }
60 virtual void enable_feature(int64_t value = 0) = 0;
61 virtual void disable_feature() = 0;
62 const char* pretty() { return _pretty; }
63 uint64_t feature_bit() { return _linux_feature_bit; }
64 bool feature_string() { return _feature_string; }
65 virtual bool enabled() = 0;
66 virtual void update_flag() = 0;
67 virtual void log_enabled() = 0;
68 };
69
70 #define UPDATE_DEFAULT(flag) \
71 void update_flag() { \
72 assert(enabled(), "Must be."); \
73 if (FLAG_IS_DEFAULT(flag)) { \
74 FLAG_SET_DEFAULT(flag, true); \
75 } else { \
76 /* Sync CPU features with flags */ \
77 if (!flag) { \
78 disable_feature(); \
79 } \
80 } \
81 } \
82
83 #define UPDATE_DEFAULT_DEP(flag, dep0, ...) \
84 void update_flag() { \
85 assert(enabled(), "Must be."); \
86 DEBUG_ONLY(verify_deps(dep0, ##__VA_ARGS__)); \
87 if (FLAG_IS_DEFAULT(flag)) { \
88 if (deps_all_enabled(dep0, ##__VA_ARGS__)) { \
89 FLAG_SET_DEFAULT(flag, true); \
90 } else { \
91 FLAG_SET_DEFAULT(flag, false); \
92 /* Sync CPU features with flags */ \
93 disable_feature(); \
94 stringStream ss; \
95 ss.print("missing dependent extension(s): "); \
96 deps_string(ss, dep0, ##__VA_ARGS__); \
97 log_disabled(ss.as_string(true)); \
98 } \
99 } else { \
100 /* Sync CPU features with flags */ \
101 if (!flag) { \
102 disable_feature(); \
103 } else if (!deps_all_enabled(dep0, ##__VA_ARGS__)) { \
104 FLAG_SET_DEFAULT(flag, false); \
105 /* Sync CPU features with flags */ \
106 disable_feature(); \
107 stringStream ss; \
108 ss.print("missing dependent extension(s): "); \
109 deps_string(ss, dep0, ##__VA_ARGS__); \
110 log_disabled(ss.as_string(true)); \
111 } \
112 } \
113 } \
114
115 #define NO_UPDATE_DEFAULT \
116 void update_flag() {} \
117
118
119 class RVExtFeatureValue : public RVFeatureValue {
120 const uint32_t _cpu_feature_index;
121
122 public:
123 RVExtFeatureValue(const char* pretty, int linux_bit_num, uint32_t cpu_feature_index, bool fstring) :
124 RVFeatureValue(pretty, linux_bit_num, fstring),
125 _cpu_feature_index(cpu_feature_index) {
126 }
127 int cpu_feature_index() {
128 // Can be used to check, for example, v is declared before Zvfh in RV_EXT_FEATURE_FLAGS.
129 return _cpu_feature_index;
130 }
131 bool enabled() {
132 return RVExtFeatures::current()->support_feature(_cpu_feature_index);
133 }
134 void enable_feature(int64_t value = 0) {
135 RVExtFeatures::current()->set_feature(_cpu_feature_index);
136 }
137 void disable_feature() {
138 RVExtFeatures::current()->clear_feature(_cpu_feature_index);
139 }
140 void log_enabled();
141 void log_disabled(const char* reason);
142
143 protected:
144 bool deps_all_enabled(RVExtFeatureValue* dep0, ...) {
145 assert(dep0 != nullptr, "must not");
146
147 va_list va;
148 va_start(va, dep0);
149 RVExtFeatureValue* next = dep0;
150 bool enabled = true;
151 while (next != nullptr && enabled) {
152 enabled = next->enabled();
153 next = va_arg(va, RVExtFeatureValue*);
154 }
155 va_end(va);
156 return enabled;
157 }
158
159 void deps_string(stringStream& ss, RVExtFeatureValue* dep0, ...) {
160 assert(dep0 != nullptr, "must not");
161 ss.print("%s (%s)", dep0->pretty(), dep0->enabled() ? "enabled" : "disabled");
162
163 va_list va;
164 va_start(va, dep0);
165 RVExtFeatureValue* next = nullptr;
166 while ((next = va_arg(va, RVExtFeatureValue*)) != nullptr) {
167 ss.print(", %s (%s)", next->pretty(), next->enabled() ? "enabled" : "disabled");
168 }
169 va_end(va);
170 }
171
172 #ifdef ASSERT
173 void verify_deps(RVExtFeatureValue* dep0, ...) {
174 assert(dep0 != nullptr, "must not");
175 assert(cpu_feature_index() >= 0, "must");
176
177 va_list va;
178 va_start(va, dep0);
179 RVExtFeatureValue* next = dep0;
180 while (next != nullptr) {
181 assert(next->cpu_feature_index() >= 0, "must");
182 // We only need to check depenency relationship for extension flags.
183 // The dependant ones must be declared before this, for example, v must be declared
184 // before Zvfh in RV_EXT_FEATURE_FLAGS. The reason is in setup_cpu_available_features
185 // we need to make sure v is `update_flag`ed before Zvfh, so Zvfh is `update_flag`ed
186 // based on v.
187 assert(cpu_feature_index() > next->cpu_feature_index(), "Invalid");
188 next = va_arg(va, RVExtFeatureValue*);
189 }
190 va_end(va);
191 }
192 #endif // ASSERT
193 };
194
195 class RVNonExtFeatureValue : public RVFeatureValue {
196 static const int64_t DEFAULT_VALUE = -1;
197 int64_t _value;
198
199 public:
200 RVNonExtFeatureValue(const char* pretty, int linux_bit_num, bool fstring) :
201 RVFeatureValue(pretty, linux_bit_num, fstring),
202 _value(DEFAULT_VALUE) {
203 }
204 bool enabled() { return _value != DEFAULT_VALUE; }
205 void enable_feature(int64_t value) {
206 assert(value != DEFAULT_VALUE, "Sanity");
207 _value = value;
208 }
209 void disable_feature() { _value = DEFAULT_VALUE; }
210 int64_t value() { return _value; }
211 void log_enabled();
212 };
213
214 public:
215
216 #define RV_NO_FLAG_BIT (BitsPerWord+1) // nth_bit will return 0 on values larger than BitsPerWord
217
218 // Note: the order matters, depender should be after their dependee. E.g. ext_V before ext_Zvbb.
219 //
220 // Fields description in `decl`:
221 // declaration name, extension name, bit value from linux, feature string?, mapped flag)
222 #define RV_EXT_FEATURE_FLAGS(decl) \
223 /* A Atomic Instructions */ \
224 decl(a , ('A' - 'A'), true , NO_UPDATE_DEFAULT) \
225 /* C Compressed Instructions */ \
226 decl(c , ('C' - 'A'), true , UPDATE_DEFAULT(UseRVC)) \
227 /* D Single-Precision Floating-Point */ \
228 decl(d , ('D' - 'A'), true , NO_UPDATE_DEFAULT) \
229 /* F Single-Precision Floating-Point */ \
230 decl(f , ('F' - 'A'), true , NO_UPDATE_DEFAULT) \
231 /* H Hypervisor */ \
232 decl(h , ('H' - 'A'), true , NO_UPDATE_DEFAULT) \
233 /* I RV64I */ \
234 decl(i , ('I' - 'A'), true , NO_UPDATE_DEFAULT) \
235 /* M Integer Multiplication and Division */ \
236 decl(m , ('M' - 'A'), true , NO_UPDATE_DEFAULT) \
237 /* Q Quad-Precision Floating-Point */ \
238 decl(q , ('Q' - 'A'), true , NO_UPDATE_DEFAULT) \
239 /* V Vector */ \
240 decl(v , ('V' - 'A'), true , UPDATE_DEFAULT(UseRVV)) \
241 \
242 /* ----------------------- Other extensions ----------------------- */ \
243 \
244 /* Atomic compare-and-swap (CAS) instructions */ \
245 decl(Zacas , RV_NO_FLAG_BIT, true , UPDATE_DEFAULT(UseZacas)) \
246 /* Zba Address generation instructions */ \
247 decl(Zba , RV_NO_FLAG_BIT, true , UPDATE_DEFAULT(UseZba)) \
248 /* Zbb Basic bit-manipulation */ \
249 decl(Zbb , RV_NO_FLAG_BIT, true , UPDATE_DEFAULT(UseZbb)) \
250 /* Zbc Carry-less multiplication */ \
251 decl(Zbc , RV_NO_FLAG_BIT, true , NO_UPDATE_DEFAULT) \
252 /* Bitmanip instructions for Cryptography */ \
253 decl(Zbkb , RV_NO_FLAG_BIT, true , UPDATE_DEFAULT(UseZbkb)) \
254 /* Zbs Single-bit instructions */ \
255 decl(Zbs , RV_NO_FLAG_BIT, true , UPDATE_DEFAULT(UseZbs)) \
256 /* Zcb Simple code-size saving instructions */ \
257 decl(Zcb , RV_NO_FLAG_BIT, true , UPDATE_DEFAULT(UseZcb)) \
258 /* Additional Floating-Point instructions */ \
259 decl(Zfa , RV_NO_FLAG_BIT, true , UPDATE_DEFAULT(UseZfa)) \
260 /* Zfh Half-Precision Floating-Point instructions */ \
261 decl(Zfh , RV_NO_FLAG_BIT, true , UPDATE_DEFAULT(UseZfh)) \
262 /* Zfhmin Minimal Half-Precision Floating-Point instructions */ \
263 decl(Zfhmin , RV_NO_FLAG_BIT, true , UPDATE_DEFAULT(UseZfhmin)) \
264 /* Zicbom Cache Block Management Operations */ \
265 decl(Zicbom , RV_NO_FLAG_BIT, true , UPDATE_DEFAULT(UseZicbom)) \
266 /* Zicbop Cache Block Prefetch Operations */ \
267 decl(Zicbop , RV_NO_FLAG_BIT, true , UPDATE_DEFAULT(UseZicbop)) \
268 /* Zicboz Cache Block Zero Operations */ \
269 decl(Zicboz , RV_NO_FLAG_BIT, true , UPDATE_DEFAULT(UseZicboz)) \
270 /* Base Counters and Timers */ \
271 decl(Zicntr , RV_NO_FLAG_BIT, true , NO_UPDATE_DEFAULT) \
272 /* Zicond Conditional operations */ \
273 decl(Zicond , RV_NO_FLAG_BIT, true , UPDATE_DEFAULT(UseZicond)) \
274 /* Zicsr Control and Status Register (CSR) Instructions */ \
275 decl(Zicsr , RV_NO_FLAG_BIT, true , NO_UPDATE_DEFAULT) \
276 /* Zic64b Cache blocks must be 64 bytes in size, naturally aligned in the address space. */ \
277 decl(Zic64b , RV_NO_FLAG_BIT, true , UPDATE_DEFAULT(UseZic64b)) \
278 /* Zifencei Instruction-Fetch Fence */ \
279 decl(Zifencei , RV_NO_FLAG_BIT, true , NO_UPDATE_DEFAULT) \
280 /* Zihintpause Pause instruction HINT */ \
281 decl(Zihintpause , RV_NO_FLAG_BIT, true , UPDATE_DEFAULT(UseZihintpause)) \
282 /* Total Store Ordering */ \
283 decl(Ztso , RV_NO_FLAG_BIT, true , UPDATE_DEFAULT(UseZtso)) \
284 /* Vector Basic Bit-manipulation */ \
285 decl(Zvbb , RV_NO_FLAG_BIT, true , UPDATE_DEFAULT_DEP(UseZvbb, &ext_v, nullptr)) \
286 /* Vector Carryless Multiplication */ \
287 decl(Zvbc , RV_NO_FLAG_BIT, true , UPDATE_DEFAULT_DEP(UseZvbc, &ext_v, nullptr)) \
288 /* Vector Extension for Half-Precision Floating-Point */ \
289 decl(Zvfh , RV_NO_FLAG_BIT, true , UPDATE_DEFAULT_DEP(UseZvfh, &ext_v, &ext_Zfh, nullptr)) \
290 /* Shorthand for Zvkned + Zvknhb + Zvkb + Zvkt */ \
291 decl(Zvkn , RV_NO_FLAG_BIT, true , UPDATE_DEFAULT_DEP(UseZvkn, &ext_v, nullptr)) \
292 /* Zvkg crypto extension for ghash and gcm */ \
293 decl(Zvkg , RV_NO_FLAG_BIT, true , UPDATE_DEFAULT_DEP(UseZvkg, &ext_v, nullptr)) \
294
295 #define DECLARE_RV_EXT_FEATURE(PRETTY, LINUX_BIT, FSTRING, FLAGF) \
296 struct ext_##PRETTY##RVExtFeatureValue : public RVExtFeatureValue { \
297 ext_##PRETTY##RVExtFeatureValue() : \
298 RVExtFeatureValue(#PRETTY, LINUX_BIT, RVExtFeatures::CPU_##ext_##PRETTY, FSTRING) {} \
299 FLAGF; \
300 }; \
301 static ext_##PRETTY##RVExtFeatureValue ext_##PRETTY; \
302
303 RV_EXT_FEATURE_FLAGS(DECLARE_RV_EXT_FEATURE)
304 #undef DECLARE_RV_EXT_FEATURE
305
306 // Non-extension features
307 //
308 #define RV_NON_EXT_FEATURE_FLAGS(decl) \
309 /* Id for microarch. Mvendorid plus marchid uniquely identify the microarch. */ \
310 decl(marchid , RV_NO_FLAG_BIT, false, NO_UPDATE_DEFAULT) \
311 /* A unique encoding of the version of the processor implementation. */ \
312 decl(mimpid , RV_NO_FLAG_BIT, false, NO_UPDATE_DEFAULT) \
313 /* Manufactory JEDEC id encoded, ISA vol 2 3.1.2.. */ \
314 decl(mvendorid , RV_NO_FLAG_BIT, false, NO_UPDATE_DEFAULT) \
315 /* SATP bits (number of virtual addr bits) mbare, sv39, sv48, sv57, sv64 */ \
316 decl(satp_mode , RV_NO_FLAG_BIT, false, NO_UPDATE_DEFAULT) \
317 /* Performance of misaligned scalar accesses (unknown, emulated, slow, fast, unsupported) */ \
318 decl(unaligned_scalar , RV_NO_FLAG_BIT, false, NO_UPDATE_DEFAULT) \
319 /* Performance of misaligned vector accesses (unknown, unspported, slow, fast) */ \
320 decl(unaligned_vector , RV_NO_FLAG_BIT, false, NO_UPDATE_DEFAULT) \
321 decl(zicboz_block_size , RV_NO_FLAG_BIT, false, NO_UPDATE_DEFAULT) \
322
323 #define DECLARE_RV_NON_EXT_FEATURE(PRETTY, LINUX_BIT, FSTRING, FLAGF) \
324 struct PRETTY##RVNonExtFeatureValue : public RVNonExtFeatureValue { \
325 PRETTY##RVNonExtFeatureValue() : \
326 RVNonExtFeatureValue(#PRETTY, LINUX_BIT, FSTRING) {} \
327 FLAGF; \
328 }; \
329 static PRETTY##RVNonExtFeatureValue PRETTY; \
330
331 RV_NON_EXT_FEATURE_FLAGS(DECLARE_RV_NON_EXT_FEATURE)
332 #undef DECLARE_RV_NON_EXT_FEATURE
333
334 private:
335 // Utility for AOT CPU feature store/check.
336 class RVExtFeatures : public CHeapObj<mtCode> {
337 public:
338 enum RVFeatureIndex {
339 #define DECLARE_RV_FEATURE_ENUM(PRETTY, LINUX_BIT, FSTRING, FLAGF) CPU_##ext_##PRETTY,
340
341 RV_EXT_FEATURE_FLAGS(DECLARE_RV_FEATURE_ENUM)
342 MAX_CPU_FEATURE_INDEX
343 #undef DECLARE_RV_FEATURE_ENUM
344 };
345 private:
346 uint64_t _features_bitmap[(MAX_CPU_FEATURE_INDEX / BitsPerLong) + 1];
347 STATIC_ASSERT(sizeof(_features_bitmap) * BitsPerByte >= MAX_CPU_FEATURE_INDEX);
348
349 // Number of 8-byte elements in _features_bitmap.
350 constexpr static int element_count() {
351 return sizeof(_features_bitmap) / sizeof(uint64_t);
352 }
353
354 static int element_index(RVFeatureIndex feature) {
355 int idx = feature / BitsPerLong;
356 assert(idx < element_count(), "Features array index out of bounds");
357 return idx;
358 }
359
360 static uint64_t feature_bit(RVFeatureIndex feature) {
361 return (1ULL << (feature % BitsPerLong));
362 }
363
364 static RVFeatureIndex convert(uint32_t index) {
365 assert(index < MAX_CPU_FEATURE_INDEX, "must");
366 return (RVFeatureIndex)index;
367 }
368
369 public:
370 static RVExtFeatures* current() {
371 return _rv_ext_features;
372 }
373
374 RVExtFeatures() {
375 for (int i = 0; i < element_count(); i++) {
376 _features_bitmap[i] = 0;
377 }
378 }
379
380 void set_feature(uint32_t feature) {
381 RVFeatureIndex f = convert(feature);
382 int idx = element_index(f);
383 _features_bitmap[idx] |= feature_bit(f);
384 }
385
386 void clear_feature(uint32_t feature) {
387 RVFeatureIndex f = convert(feature);
388 int idx = element_index(f);
389 _features_bitmap[idx] &= ~feature_bit(f);
390 }
391
392 bool support_feature(uint32_t feature) {
393 RVFeatureIndex f = convert(feature);
394 int idx = element_index(f);
395 return (_features_bitmap[idx] & feature_bit(f)) != 0;
396 }
397 };
398
399 // enable extensions based on profile, current supported profiles:
400 // RVA20U64
401 // RVA22U64
402 // RVA23U64
403 // NOTE: we only enable the mandatory extensions, not optional extension.
404 #define RV_ENABLE_EXTENSION(UseExtension) \
405 if (FLAG_IS_DEFAULT(UseExtension)) { \
406 FLAG_SET_DEFAULT(UseExtension, true); \
407 } \
408
409 // https://github.com/riscv/riscv-profiles/blob/main/src/profiles.adoc#rva20-profiles
410 #define RV_USE_RVA20U64 \
411 RV_ENABLE_EXTENSION(UseRVC) \
412
413 static void useRVA20U64Profile();
414
415 // https://github.com/riscv/riscv-profiles/blob/main/src/profiles.adoc#rva22-profiles
416 #define RV_USE_RVA22U64 \
417 RV_ENABLE_EXTENSION(UseRVC) \
418 RV_ENABLE_EXTENSION(UseZba) \
419 RV_ENABLE_EXTENSION(UseZbb) \
420 RV_ENABLE_EXTENSION(UseZbs) \
421 RV_ENABLE_EXTENSION(UseZic64b) \
422 RV_ENABLE_EXTENSION(UseZicbom) \
423 RV_ENABLE_EXTENSION(UseZicbop) \
424 RV_ENABLE_EXTENSION(UseZicboz) \
425 RV_ENABLE_EXTENSION(UseZihintpause) \
426
427 static void useRVA22U64Profile();
428
429 // https://github.com/riscv/riscv-profiles/blob/main/src/rva23-profile.adoc#rva23u64-profile
430 #define RV_USE_RVA23U64 \
431 RV_ENABLE_EXTENSION(UseRVC) \
432 RV_ENABLE_EXTENSION(UseRVV) \
433 RV_ENABLE_EXTENSION(UseZba) \
434 RV_ENABLE_EXTENSION(UseZbb) \
435 RV_ENABLE_EXTENSION(UseZbs) \
436 RV_ENABLE_EXTENSION(UseZcb) \
437 RV_ENABLE_EXTENSION(UseZfa) \
438 RV_ENABLE_EXTENSION(UseZfhmin) \
439 RV_ENABLE_EXTENSION(UseZic64b) \
440 RV_ENABLE_EXTENSION(UseZicbom) \
441 RV_ENABLE_EXTENSION(UseZicbop) \
442 RV_ENABLE_EXTENSION(UseZicboz) \
443 RV_ENABLE_EXTENSION(UseZicond) \
444 RV_ENABLE_EXTENSION(UseZihintpause) \
445
446 static void useRVA23U64Profile();
447
448 // VM modes (satp.mode) privileged ISA 1.10
449 enum VM_MODE : int {
450 VM_NOTSET = -1,
451 VM_MBARE = 0,
452 VM_SV39 = 39,
453 VM_SV48 = 48,
454 VM_SV57 = 57,
455 VM_SV64 = 64
456 };
457
458 static VM_MODE parse_satp_mode(const char* vm_mode);
459
460 // Values from riscv_hwprobe()
461 enum UNALIGNED_SCALAR_ACCESS : int {
462 MISALIGNED_SCALAR_UNKNOWN = 0,
463 MISALIGNED_SCALAR_EMULATED = 1,
464 MISALIGNED_SCALAR_SLOW = 2,
465 MISALIGNED_SCALAR_FAST = 3,
466 MISALIGNED_SCALAR_UNSUPPORTED = 4
467 };
468
469 enum UNALIGNED_VECTOR_ACCESS : int {
470 MISALIGNED_VECTOR_UNKNOWN = 0,
471 MISALIGNED_VECTOR_SLOW = 2,
472 MISALIGNED_VECTOR_FAST = 3,
473 MISALIGNED_VECTOR_UNSUPPORTED = 4
474 };
475
476 // Null terminated list
477 static RVFeatureValue* _feature_list[];
478 static RVExtFeatures* _rv_ext_features;
479
480 // Enables features in _feature_list
481 static void setup_cpu_available_features();
482 // Helper for specific queries
483 static void os_aux_features();
484 static char* os_uarch_additional_features();
485 static void vendor_features();
486 // Vendors specific features
487 static void rivos_features();
488
489 // Determine vector length iff ext_V/UseRVV
490 static uint32_t cpu_vector_length();
491 static uint32_t _initial_vector_length;
492
493 static void common_initialize();
494
495 #ifdef COMPILER2
496 static void c2_initialize();
497 #endif // COMPILER2
498
499 public:
500 // Initialization
501 static void initialize();
502 static void initialize_cpu_information();
503
504 constexpr static bool supports_stack_watermark_barrier() { return true; }
505
506 constexpr static bool supports_recursive_fast_locking() { return true; }
507
508 constexpr static bool supports_secondary_supers_table() { return true; }
509
510 static bool supports_on_spin_wait() { return UseZihintpause; }
511
512 // RISCV64 supports fast class initialization checks
513 static bool supports_fast_class_init_checks() { return true; }
514 static bool supports_fencei_barrier() { return ext_Zifencei.enabled(); }
515
516 static bool supports_float16_float_conversion() {
517 return UseZfh || UseZfhmin;
518 }
519
520 // Check intrinsic support
521 static bool is_intrinsic_supported(vmIntrinsicID id);
522 };
523
524 #endif // CPU_RISCV_VM_VERSION_RISCV_HPP