From d470cd50185cc76be7c3946cb4f45d8eb3a70aa5 Mon Sep 17 00:00:00 2001 From: Yu-Chun Lin Date: Fri, 28 Feb 2025 21:02:40 +0800 Subject: [PATCH] Raise exception when RV32E instructions use x16-x31 Modify rv_decode() to enforce RV32E register constraints by validating rd, rs1, rs2, ensuring they remain within x0-x15. If an instruction attempts to use x16-x31, trigger an illegal instruction exception, aligning with RISC-V privileged architecture behavior. According to The RISC-V Instruction Set Manual Volume I: Unprivileged Architecture, Version 20240411: "RV32E and RV64E ... only registers x0-x15 are provided. All encodings specifying the other registers x16-x31 are reserved." --- src/decode.c | 24 ++++++++++++++++++++---- 1 file changed, 20 insertions(+), 4 deletions(-) diff --git a/src/decode.c b/src/decode.c index f65556da..4471fbb5 100644 --- a/src/decode.c +++ b/src/decode.c @@ -1983,7 +1983,9 @@ typedef bool (*decode_t)(rv_insn_t *ir, uint32_t insn); /* decode RISC-V instruction */ bool rv_decode(rv_insn_t *ir, uint32_t insn) { + bool ret; assert(ir); + decode_t op; #define OP_UNIMP op_unimp #define OP(insn) op_##insn @@ -2024,9 +2026,11 @@ bool rv_decode(rv_insn_t *ir, uint32_t insn) const uint16_t c_index = (insn & FC_FUNC3) >> 11 | (insn & FC_OPCODE); /* decode instruction (compressed instructions) */ - const decode_t op = rvc_jump_table[c_index]; + op = rvc_jump_table[c_index]; assert(op); - return op(ir, insn); + ret = op(ir, insn); + + goto end; } #endif @@ -2034,9 +2038,21 @@ bool rv_decode(rv_insn_t *ir, uint32_t insn) const uint32_t index = (insn & INSN_6_2) >> 2; /* decode instruction */ - const decode_t op = rv_jump_table[index]; + op = rv_jump_table[index]; assert(op); - return op(ir, insn); + ret = op(ir, insn); + +end: + +#if RV32_HAS(RV32E) + /* RV32E forbids x16-x31 for integer registers, but with the F extension, + * floating-point registers are not limited to 16. */ + if ((op != op_store_fp && op != op_load_fp && op != op_op_fp) && + unlikely(ir->rd > 15 || ir->rs1 > 15 || ir->rs2 > 15)) + ret = false; +#endif + + return ret; #undef OP_UNIMP #undef OP