8389223: RISC-V: Implement CRC32C intrinsic using Zbc extension

This commit is contained in:
Peijun Xu 2026-07-14 16:35:44 +08:00 committed by xupeijun
parent 44ef3188ad
commit c26b5178eb
10 changed files with 316 additions and 5 deletions

View File

@ -2713,6 +2713,9 @@ enum Nf {
INSN(maxu, 0b0110011, 0b111, 0b0000101);
INSN(min, 0b0110011, 0b100, 0b0000101);
INSN(minu, 0b0110011, 0b101, 0b0000101);
INSN(clmul, 0b0110011, 0b001, 0b0000101);
INSN(clmulh, 0b0110011, 0b011, 0b0000101);
INSN(clmulr, 0b0110011, 0b010, 0b0000101);
#undef INSN

View File

@ -119,6 +119,7 @@ define_pd_global(intx, InlineSmallCode, 1000);
product(bool, UseZtso, false, EXPERIMENTAL, "Assume Ztso memory model") \
product(bool, UseZvbb, false, DIAGNOSTIC, "Use Zvbb instructions") \
product(bool, UseZvbc, false, DIAGNOSTIC, "Use Zvbc instructions") \
product(bool, UseZbc, false, EXPERIMENTAL, "Use Zbc instructions") \
product(bool, UseZvfh, false, DIAGNOSTIC, "Use Zvfh instructions") \
product(bool, UseZvfhmin, false, DIAGNOSTIC, "Use Zvfhmin instructions") \
product(bool, UseZvkg, false, DIAGNOSTIC, "Use Zvkg instructions") \

View File

@ -2731,6 +2731,185 @@ void MacroAssembler::kernel_crc32(Register crc, Register buf, Register len,
andn(crc, tmp5, crc);
}
// Advance buf to the next 8-byte boundary, folding each byte into crc via the
// byte lookup table. tmp1 holds the alignment count, tmp2 the loaded byte.
void MacroAssembler::kernel_crc32c_clmul_align(Register crc, Register buf, Register len,
Register table, Register tmp1, Register tmp2) {
assert_different_registers(crc, buf, len, table, tmp1, tmp2);
Label L_adjust, L_loop, L_done;
// bytes to next 8-byte boundary: (-buf) & 7 = 8 - (buf & 7)
neg(tmp1, buf);
andi(tmp1, tmp1, 7);
// tmp1 = min(tmp1, len)
bleu(tmp1, len, L_adjust);
mv(tmp1, len);
bind(L_adjust);
subw(len, len, tmp1);
beqz(tmp1, L_done);
bind(L_loop);
lbu(tmp2, Address(buf, 0));
addi(buf, buf, 1);
update_byte_crc32(crc, tmp2, table);
addi(tmp1, tmp1, -1);
bnez(tmp1, L_loop);
bind(L_done);
}
// Fold 128 bits of input into the 128-bit accumulator (accum_hi:accum_lo).
// With the next 16 input bytes as (data_hi:data_lo) and * = carry-less mul:
// accum_lo' = (accum_lo*k1)[63:0] XOR (accum_hi*k2)[63:0] XOR data_lo
// accum_hi' = (accum_lo*k1)[127:64] XOR (accum_hi*k2)[127:64] XOR data_hi
void MacroAssembler::kernel_crc32c_clmul_fold_128(Register accum_lo, Register accum_hi,
Register k1, Register k2, Register buf, Register tmp1, Register tmp2) {
assert_different_registers(accum_lo, accum_hi, k1, k2, buf, tmp1, tmp2);
clmul(tmp1, accum_lo, k1);
clmulh(tmp2, accum_lo, k1);
clmul(accum_lo, accum_hi, k2);
clmulh(accum_hi, accum_hi, k2);
xorr(accum_lo, accum_lo, tmp1);
ld(tmp1, Address(buf, 0)); // tmp1 = data_lo
xorr(accum_lo, accum_lo, tmp1);
xorr(accum_hi, accum_hi, tmp2);
ld(tmp1, Address(buf, 8)); // tmp1 = data_hi
xorr(accum_hi, accum_hi, tmp1);
}
// Reduce the 128-bit accumulator (accum_hi:accum_lo) to 64 bits using the
// ISA-L two-constant method. With rk1 at OFF_REDUCE_HI and rk2 at OFF_REDUCE_LO:
// x = accum_lo
// y0 = accum_hi XOR clmul(x, rk1)[63:0]
// y1 = clmulh(x, rk1)[95:64]
// accum_lo' = clmul(y0[31:0], rk2)[63:0] XOR (y1 : y0[63:32])
void MacroAssembler::kernel_crc32c_clmul_reduce_128_to_64(Register accum_lo, Register accum_hi,
Register clmul_table, Register k, Register tmp1, Register tmp2) {
assert_different_registers(accum_lo, accum_hi, clmul_table, k, tmp1, tmp2);
const int OFF_REDUCE_LO = 16;
const int OFF_REDUCE_HI = 24;
ld(k, Address(clmul_table, OFF_REDUCE_HI));
clmul(tmp1, accum_lo, k); // tmp1 = clmul(x, rk1)[63:0]
clmulh(tmp2, accum_lo, k); // tmp2 = clmulh(x, rk1) = clmul(x, rk1)[127:64]
xorr(accum_hi, accum_hi, tmp1); // y0 = accum_hi XOR clmul(x, rk1)[63:0]
zext(tmp1, accum_hi, 32); // tmp1 = y0[31:0]
srli(accum_hi, accum_hi, 32); // accum_hi = y0[63:32]
ld(k, Address(clmul_table, OFF_REDUCE_LO));
clmul(accum_lo, tmp1, k); // accum_lo' = clmul(y0[31:0], rk2)[63:0]
slli(tmp2, tmp2, 32); // tmp2 = clmul(x, rk1)[95:64] << 32 = y1 : 0
xorr(tmp2, tmp2, accum_hi); // tmp2 = y1 : y0[63:32]
xorr(accum_lo, accum_lo, tmp2); // accum_lo' XOR= (y1 : y0[63:32])
}
// Reduce the 64-bit accumulator accum_lo to a residue mod P (the 33-bit
// CRC32C polynomial) using Barrett reduction, with mu = floor(x^64/P) at
// OFF_BARRETT_MU and poly = P at OFF_BARRETT_POLY:
// q = (accum_lo[31:0] * mu)[31:0] // quotient estimate
// accum_lo XOR= (q * poly)[63:0] // subtract q*P
// The high 32 bits of accum_lo then hold the final CRC.
void MacroAssembler::kernel_crc32c_clmul_barrett_64_to_32(Register accum_lo, Register clmul_table,
Register k, Register tmp) {
assert_different_registers(accum_lo, clmul_table, k, tmp);
const int OFF_BARRETT_MU = 32;
const int OFF_BARRETT_POLY = 40;
zext(tmp, accum_lo, 32); // tmp = accum_lo[31:0]
ld(k, Address(clmul_table, OFF_BARRETT_MU));
clmul(tmp, tmp, k);
zext(tmp, tmp, 32); // tmp = q = (accum_lo[31:0] * mu)[31:0]
ld(k, Address(clmul_table, OFF_BARRETT_POLY));
clmul(tmp, tmp, k);
xorr(accum_lo, accum_lo, tmp);
}
void MacroAssembler::kernel_crc32c_clmul_fold(Register crc, Register buf, Register len,
Register byte_table, Register clmul_table,
Register tmp1, Register tmp2, Register tmp3, Register tmp4, Register tmp5, Register tmp6) {
assert_different_registers(crc, buf, len, byte_table, clmul_table, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6);
Label L_fold_loop, L_tail, L_tail_loop, L_exit;
const int FOLD_THRESHOLD = 64; // fold only for inputs >= 4 FOLD_STEPs
const int FOLD_STEP = 16;
const int OFF_FOLD_K1 = 0;
const int OFF_FOLD_K2 = 8;
mv(tmp4, FOLD_THRESHOLD);
blt(len, tmp4, L_tail);
kernel_crc32c_clmul_align(crc, buf, len, byte_table, tmp4, tmp5);
beqz(len, L_exit);
// fold_end = buf + len - (len mod 16); len = tail
const Register fold_end = tmp6;
add(fold_end, buf, len);
andi(len, len, FOLD_STEP - 1);
sub(fold_end, fold_end, len);
// accum = (buf[0:8] XOR crc) : buf[8:16]
const Register accum_lo = crc;
const Register accum_hi = tmp1;
ld(tmp4, Address(buf, 0));
xorr(accum_lo, tmp4, crc);
ld(accum_hi, Address(buf, 8));
addi(buf, buf, FOLD_STEP);
ld(tmp2, Address(clmul_table, OFF_FOLD_K1));
ld(tmp3, Address(clmul_table, OFF_FOLD_K2));
bind(L_fold_loop);
kernel_crc32c_clmul_fold_128(accum_lo, accum_hi, tmp2, tmp3, buf, tmp4, tmp5);
addi(buf, buf, 16);
blt(buf, fold_end, L_fold_loop);
// reduce 128->64 (ISA-L) then 64->32 (Barrett); tmp2 = k; tmp4..tmp5 reused as scratch
kernel_crc32c_clmul_reduce_128_to_64(accum_lo, accum_hi, clmul_table, tmp2, tmp4, tmp5);
kernel_crc32c_clmul_barrett_64_to_32(accum_lo, clmul_table, tmp2, tmp4);
srli(crc, accum_lo, 32);
bind(L_tail);
add(tmp5, buf, len); // tmp5 = tail_end
bind(L_tail_loop);
bgeu(buf, tmp5, L_exit);
lbu(tmp4, Address(buf, 0));
addi(buf, buf, 1);
update_byte_crc32(crc, tmp4, byte_table);
j(L_tail_loop);
bind(L_exit);
}
void MacroAssembler::kernel_crc32c(Register crc, Register buf, Register len,
Register byte_table, Register clmul_table,
Register tmp1, Register tmp2, Register tmp3, Register tmp4, Register tmp5, Register tmp6) {
assert_different_registers(crc, buf, len, byte_table, clmul_table, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6);
assert(UseZbc, "CRC32C intrinsic requires Zbc");
zext(crc, crc, 32);
// _crc32c_table is followed by the clmul constants
const int64_t single_table_size = 256;
const ExternalAddress table_addr = StubRoutines::crc32c_table_addr();
la(byte_table, table_addr);
add(clmul_table, byte_table, 1 * single_table_size * sizeof(juint), tmp4);
kernel_crc32c_clmul_fold(crc, buf, len, byte_table, clmul_table,
tmp1, tmp2, tmp3, tmp4, tmp5, tmp6);
}
#ifdef COMPILER2
// Push vector registers in the bitset supplied.
// Return the number of words pushed

View File

@ -1367,6 +1367,23 @@ public:
bool upper);
void update_byte_crc32(Register crc, Register val, Register table);
// CRC32C code for java.util.zip.CRC32C::updateBytes() intrinsic,
// accelerated with Zbc carry-less multiplication (clmul/clmulh).
void kernel_crc32c(Register crc, Register buf, Register len,
Register byte_table, Register clmul_table,
Register tmp1, Register tmp2, Register tmp3, Register tmp4, Register tmp5, Register tmp6);
void kernel_crc32c_clmul_fold(Register crc, Register buf, Register len,
Register byte_table, Register clmul_table,
Register tmp1, Register tmp2, Register tmp3, Register tmp4, Register tmp5, Register tmp6);
void kernel_crc32c_clmul_align(Register crc, Register buf, Register len,
Register table, Register tmp1, Register tmp2);
void kernel_crc32c_clmul_fold_128(Register accum_lo, Register accum_hi,
Register k1, Register k2, Register buf, Register tmp1, Register tmp2);
void kernel_crc32c_clmul_reduce_128_to_64(Register accum_lo, Register accum_hi,
Register clmul_table, Register k, Register tmp1, Register tmp2);
void kernel_crc32c_clmul_barrett_64_to_32(Register accum_lo, Register clmul_table,
Register k, Register tmp);
#ifdef COMPILER2
void vector_update_crc32(Register crc, Register buf, Register len,
Register tmp1, Register tmp2, Register tmp3, Register tmp4, Register tmp5,

View File

@ -7262,6 +7262,33 @@ static const int64_t right_3_bits = right_n_bits(3);
return start;
}
address generate_updateBytesCRC32C(){
assert(UseCRC32CIntrinsics, "what are we doing here?");
__ align(CodeEntryAlignment);
StubId stub_id = StubId::stubgen_updateBytesCRC32C_id;
StubCodeMark mark(this, stub_id);
address start = __ pc();
const Register crc = c_rarg0; // crc
const Register buf = c_rarg1; // source java byte array address
const Register len = c_rarg2; // length
BLOCK_COMMENT("Entry:");
__ enter(); // required for proper stackwalking of RuntimeStub frame
// c_rarg3/c_rarg4 are reused as the two table base pointers; the rest are scratch.
__ kernel_crc32c(crc, buf, len,
c_rarg3, c_rarg4, // byte_table, clmul_table
c_rarg5, c_rarg6, c_rarg7, // accum_hi, k1, k2
t2, t3, t4); // scratch1, scratch2, fold_end
__ leave(); // required for proper stackwalking of RuntimeStub frame
__ ret();
return start;
}
// exception handler for upcall stubs
address generate_upcall_stub_exception_handler() {
StubId stub_id = StubId::stubgen_upcall_stub_exception_handler_id;
@ -7333,6 +7360,10 @@ static const int64_t right_3_bits = right_n_bits(3);
StubRoutines::_updateBytesCRC32 = generate_updateBytesCRC32();
}
if (UseCRC32CIntrinsics) {
StubRoutines::_updateBytesCRC32C = generate_updateBytesCRC32C();
}
if (vmIntrinsics::is_intrinsic_available(vmIntrinsics::_float16ToFloat) &&
vmIntrinsics::is_intrinsic_available(vmIntrinsics::_floatToFloat16)) {
StubRoutines::_hf2f = generate_float16ToFloat();

View File

@ -58,7 +58,7 @@ bool StubRoutines::riscv::_completed = false;
*/
address StubRoutines::crc_table_addr() { return (address)StubRoutines::riscv::_crc_table; }
address StubRoutines::crc32c_table_addr() { ShouldNotCallThis(); return nullptr; }
address StubRoutines::crc32c_table_addr() { return (address)StubRoutines::riscv::_crc32c_table; }
ATTRIBUTE_ALIGNED(4096) juint StubRoutines::riscv::_crc_table[] =
{
@ -506,6 +506,69 @@ ATTRIBUTE_ALIGNED(4096) juint StubRoutines::riscv::_crc_table[] =
0xccaa009eUL, 0x00000000UL,
};
ATTRIBUTE_ALIGNED(4096) juint StubRoutines::riscv::_crc32c_table[] ={
0x00000000UL, 0xF26B8303UL, 0xE13B70F7UL, 0x1350F3F4UL, 0xC79A971FUL,
0x35F1141CUL, 0x26A1E7E8UL, 0xD4CA64EBUL, 0x8AD958CFUL, 0x78B2DBCCUL,
0x6BE22838UL, 0x9989AB3BUL, 0x4D43CFD0UL, 0xBF284CD3UL, 0xAC78BF27UL,
0x5E133C24UL, 0x105EC76FUL, 0xE235446CUL, 0xF165B798UL, 0x030E349BUL,
0xD7C45070UL, 0x25AFD373UL, 0x36FF2087UL, 0xC494A384UL, 0x9A879FA0UL,
0x68EC1CA3UL, 0x7BBCEF57UL, 0x89D76C54UL, 0x5D1D08BFUL, 0xAF768BBCUL,
0xBC267848UL, 0x4E4DFB4BUL, 0x20BD8EDEUL, 0xD2D60DDDUL, 0xC186FE29UL,
0x33ED7D2AUL, 0xE72719C1UL, 0x154C9AC2UL, 0x061C6936UL, 0xF477EA35UL,
0xAA64D611UL, 0x580F5512UL, 0x4B5FA6E6UL, 0xB93425E5UL, 0x6DFE410EUL,
0x9F95C20DUL, 0x8CC531F9UL, 0x7EAEB2FAUL, 0x30E349B1UL, 0xC288CAB2UL,
0xD1D83946UL, 0x23B3BA45UL, 0xF779DEAEUL, 0x05125DADUL, 0x1642AE59UL,
0xE4292D5AUL, 0xBA3A117EUL, 0x4851927DUL, 0x5B016189UL, 0xA96AE28AUL,
0x7DA08661UL, 0x8FCB0562UL, 0x9C9BF696UL, 0x6EF07595UL, 0x417B1DBCUL,
0xB3109EBFUL, 0xA0406D4BUL, 0x522BEE48UL, 0x86E18AA3UL, 0x748A09A0UL,
0x67DAFA54UL, 0x95B17957UL, 0xCBA24573UL, 0x39C9C670UL, 0x2A993584UL,
0xD8F2B687UL, 0x0C38D26CUL, 0xFE53516FUL, 0xED03A29BUL, 0x1F682198UL,
0x5125DAD3UL, 0xA34E59D0UL, 0xB01EAA24UL, 0x42752927UL, 0x96BF4DCCUL,
0x64D4CECFUL, 0x77843D3BUL, 0x85EFBE38UL, 0xDBFC821CUL, 0x2997011FUL,
0x3AC7F2EBUL, 0xC8AC71E8UL, 0x1C661503UL, 0xEE0D9600UL, 0xFD5D65F4UL,
0x0F36E6F7UL, 0x61C69362UL, 0x93AD1061UL, 0x80FDE395UL, 0x72966096UL,
0xA65C047DUL, 0x5437877EUL, 0x4767748AUL, 0xB50CF789UL, 0xEB1FCBADUL,
0x197448AEUL, 0x0A24BB5AUL, 0xF84F3859UL, 0x2C855CB2UL, 0xDEEEDFB1UL,
0xCDBE2C45UL, 0x3FD5AF46UL, 0x7198540DUL, 0x83F3D70EUL, 0x90A324FAUL,
0x62C8A7F9UL, 0xB602C312UL, 0x44694011UL, 0x5739B3E5UL, 0xA55230E6UL,
0xFB410CC2UL, 0x092A8FC1UL, 0x1A7A7C35UL, 0xE811FF36UL, 0x3CDB9BDDUL,
0xCEB018DEUL, 0xDDE0EB2AUL, 0x2F8B6829UL, 0x82F63B78UL, 0x709DB87BUL,
0x63CD4B8FUL, 0x91A6C88CUL, 0x456CAC67UL, 0xB7072F64UL, 0xA457DC90UL,
0x563C5F93UL, 0x082F63B7UL, 0xFA44E0B4UL, 0xE9141340UL, 0x1B7F9043UL,
0xCFB5F4A8UL, 0x3DDE77ABUL, 0x2E8E845FUL, 0xDCE5075CUL, 0x92A8FC17UL,
0x60C37F14UL, 0x73938CE0UL, 0x81F80FE3UL, 0x55326B08UL, 0xA759E80BUL,
0xB4091BFFUL, 0x466298FCUL, 0x1871A4D8UL, 0xEA1A27DBUL, 0xF94AD42FUL,
0x0B21572CUL, 0xDFEB33C7UL, 0x2D80B0C4UL, 0x3ED04330UL, 0xCCBBC033UL,
0xA24BB5A6UL, 0x502036A5UL, 0x4370C551UL, 0xB11B4652UL, 0x65D122B9UL,
0x97BAA1BAUL, 0x84EA524EUL, 0x7681D14DUL, 0x2892ED69UL, 0xDAF96E6AUL,
0xC9A99D9EUL, 0x3BC21E9DUL, 0xEF087A76UL, 0x1D63F975UL, 0x0E330A81UL,
0xFC588982UL, 0xB21572C9UL, 0x407EF1CAUL, 0x532E023EUL, 0xA145813DUL,
0x758FE5D6UL, 0x87E466D5UL, 0x94B49521UL, 0x66DF1622UL, 0x38CC2A06UL,
0xCAA7A905UL, 0xD9F75AF1UL, 0x2B9CD9F2UL, 0xFF56BD19UL, 0x0D3D3E1AUL,
0x1E6DCDEEUL, 0xEC064EEDUL, 0xC38D26C4UL, 0x31E6A5C7UL, 0x22B65633UL,
0xD0DDD530UL, 0x0417B1DBUL, 0xF67C32D8UL, 0xE52CC12CUL, 0x1747422FUL,
0x49547E0BUL, 0xBB3FFD08UL, 0xA86F0EFCUL, 0x5A048DFFUL, 0x8ECEE914UL,
0x7CA56A17UL, 0x6FF599E3UL, 0x9D9E1AE0UL, 0xD3D3E1ABUL, 0x21B862A8UL,
0x32E8915CUL, 0xC083125FUL, 0x144976B4UL, 0xE622F5B7UL, 0xF5720643UL,
0x07198540UL, 0x590AB964UL, 0xAB613A67UL, 0xB831C993UL, 0x4A5A4A90UL,
0x9E902E7BUL, 0x6CFBAD78UL, 0x7FAB5E8CUL, 0x8DC0DD8FUL, 0xE330A81AUL,
0x115B2B19UL, 0x020BD8EDUL, 0xF0605BEEUL, 0x24AA3F05UL, 0xD6C1BC06UL,
0xC5914FF2UL, 0x37FACCF1UL, 0x69E9F0D5UL, 0x9B8273D6UL, 0x88D28022UL,
0x7AB90321UL, 0xAE7367CAUL, 0x5C18E4C9UL, 0x4F48173DUL, 0xBD23943EUL,
0xF36E6F75UL, 0x0105EC76UL, 0x12551F82UL, 0xE03E9C81UL, 0x34F4F86AUL,
0xC69F7B69UL, 0xD5CF889DUL, 0x27A40B9EUL, 0x79B737BAUL, 0x8BDCB4B9UL,
0x988C474DUL, 0x6AE7C44EUL, 0xBE2DA0A5UL, 0x4C4623A6UL, 0x5F16D052UL,
0xAD7D5351UL,
// CRC32C constants for carry-less multiplication implementation
0xF20C0DFEUL, 0x00000000UL,
0x493C7D27UL, 0x00000000UL,
0xDD45AAB8UL, 0x00000000UL,
0x493C7D27UL, 0x00000000UL,
0xDEA713F1UL, 0x00000000UL,
0x05EC76F1UL, 0x00000001UL,
};
#if INCLUDE_CDS
// nothing to do for riscv
void StubRoutines::init_AOTAddressTable() {

View File

@ -99,6 +99,7 @@ private:
private:
static juint _crc_table[];
static juint _crc32c_table[];
};
#endif // CPU_RISCV_STUBROUTINES_RISCV_HPP

View File

@ -214,9 +214,15 @@ void VM_Version::common_initialize() {
FLAG_SET_DEFAULT(UseCRC32Intrinsics, false);
}
if (UseCRC32CIntrinsics) {
warning("CRC32C intrinsics are not available on this CPU.");
FLAG_SET_DEFAULT(UseCRC32CIntrinsics, false);
if (UseZbc) {
if (FLAG_IS_DEFAULT(UseCRC32CIntrinsics)) {
FLAG_SET_DEFAULT(UseCRC32CIntrinsics, true);
}
} else {
if (UseCRC32CIntrinsics) {
warning("CRC32C intrinsic are not available on this CPU.");
FLAG_SET_DEFAULT(UseCRC32CIntrinsics, false);
}
}
}
@ -495,6 +501,12 @@ bool VM_Version::is_intrinsic_supported(vmIntrinsicID id) {
return false;
}
break;
case vmIntrinsics::_updateBytesCRC32C:
case vmIntrinsics::_updateDirectByteBufferCRC32C:
if (!UseCRC32CIntrinsics) {
return false;
}
break;
default:
break;
}

View File

@ -248,7 +248,7 @@ class VM_Version : public Abstract_VM_Version {
/* Zbb Basic bit-manipulation */ \
decl(Zbb , RV_NO_FLAG_BIT, true , UPDATE_DEFAULT(UseZbb)) \
/* Zbc Carry-less multiplication */ \
decl(Zbc , RV_NO_FLAG_BIT, true , NO_UPDATE_DEFAULT) \
decl(Zbc , RV_NO_FLAG_BIT, true , UPDATE_DEFAULT(UseZbc)) \
/* Bitmanip instructions for Cryptography */ \
decl(Zbkb , RV_NO_FLAG_BIT, true , UPDATE_DEFAULT(UseZbkb)) \
/* Zbs Single-bit instructions */ \
@ -434,6 +434,7 @@ private:
RV_ENABLE_EXTENSION(UseRVV) \
RV_ENABLE_EXTENSION(UseZba) \
RV_ENABLE_EXTENSION(UseZbb) \
RV_ENABLE_EXTENSION(UseZbc) \
RV_ENABLE_EXTENSION(UseZbs) \
RV_ENABLE_EXTENSION(UseZcb) \
RV_ENABLE_EXTENSION(UseZfa) \

View File

@ -207,6 +207,9 @@ void RiscvHwprobe::add_features_from_query_result() {
if (is_set(RISCV_HWPROBE_KEY_IMA_EXT_0, RISCV_HWPROBE_EXT_ZBB)) {
VM_Version::ext_Zbb.enable_feature();
}
if (is_set(RISCV_HWPROBE_KEY_IMA_EXT_0, RISCV_HWPROBE_EXT_ZBC)) {
VM_Version::ext_Zbc.enable_feature();
}
#ifndef PRODUCT
if (is_set(RISCV_HWPROBE_KEY_IMA_EXT_0, RISCV_HWPROBE_EXT_ZBKB)) {
VM_Version::ext_Zbkb.enable_feature();