@samitouri / QOSamiQemu / commits / dc2fe85523

disas/riscv: Handle c.{srli,srai} imm during decode

Zero shift immediate to c.srli and c.srai are not illegal, but are reserved as HINTs. Go ahead and disassemble as shifts rather than falling back to invalid. On the other hand, shift immediate >= 32 with RV32 is reserved for custom extensions, and we need to reject those early so that the extension disassemblers get a look in. Reviewed-by: Alistair Francis <alistair.francis@wdc.com> Signed-off-by: Richard Henderson <richard.henderson@linaro.org> Message-ID: <20260812223142.349142-17-richard.henderson@linaro.org> Signed-off-by: Alistair Francis <alistair.francis@wdc.com>

Richard Henderson committed Aug 12, 2026 at 15:31 UTC dc2fe85523d059d34c7f4ba35aae57bf7218b396
1 file changed +10 -4
disas/riscv.c
+10 -4
@@ -1906,9 +1906,9 @@ static const rv_opcode_data rvi_opcode_data[] = {
1906 { "c.lui", rv_codec_ci_lui, rv_fmt_rd_uimm, NULL, rv_op_lui, rv_op_lui,
1907 rv_op_lui },
1908 { "c.srli", rv_codec_cb_sh6, rv_fmt_rd_rs1_imm, NULL, rv_op_srli,
1909 - rv_op_srli, rv_op_srli, rvcd_imm_nz },
1909 + rv_op_srli, rv_op_srli },
1910 { "c.srai", rv_codec_cb_sh6, rv_fmt_rd_rs1_imm, NULL, rv_op_srai,
1911 - rv_op_srai, rv_op_srai, rvcd_imm_nz },
1911 + rv_op_srai, rv_op_srai },
1912 { "c.andi", rv_codec_cb_imm, rv_fmt_rd_rs1_imm, NULL, rv_op_andi,
1913 rv_op_andi, rv_op_andi },
1914 { "c.sub", rv_codec_cs, rv_fmt_rd_rs1_rs2, NULL, rv_op_sub, rv_op_sub,
@@ -3042,10 +3042,16 @@ static void decode_inst_opcode(rv_decode *dec, rv_isa isa)
3042 case 4:
3043 switch ((inst >> 10) & 0b11) {
3044 case 0:
3045 - op = rv_op_c_srli;
3045 + /* For rv32, shamt[5]=1 is designated for custom extensions. */
3046 + if (isa != rv32 || (inst & 0x1000) == 0) {
3047 + op = rv_op_c_srli; /* or unspecified HINT */
3048 + }
3049 break;
3050 case 1:
3048 - op = rv_op_c_srai;
3051 + /* For rv32, shamt[5]=1 is designated for custom extensions. */
3052 + if (isa != rv32 || (inst & 0x1000) == 0) {
3053 + op = rv_op_c_srai; /* or unspecified HINT */
3054 + }
3055 break;
3056 case 2: op = rv_op_c_andi; break;
3057 case 3: