lib: sbi: Enhance CSR Handling in system_opcode_insn

- Completed TODO in `system_opcode_insn` to ensure CSR read/write
  instruction handling.
- Refactored to use new macros `GET_RS1_NUM` and `GET_CSR_NUM`.
- Updated `GET_RM` macro and replaced hardcoded funct3 values with
  constants (`CSRRW`, `CSRRS`, `CSRRC`, etc.).
- Removed redundant `GET_RM` from `riscv_fp.h`.
- Improved validation and error handling for CSR instructions.

This patch enhances the clarity and correctness of CSR handling
in `system_opcode_insn`.

Signed-off-by: Dongdong Zhang <zhangdongdong@eswincomputing.com>
Reviewed-by: Anup Patel <anup@brainfault.org>
This commit is contained in:
Dongdong Zhang
2024-07-18 13:43:57 +08:00
committed by Anup Patel
parent b9c091ed89
commit d4322eebd0
3 changed files with 41 additions and 16 deletions

View File

@@ -48,9 +48,10 @@ static int misc_mem_opcode_insn(ulong insn, struct sbi_trap_regs *regs)
static int system_opcode_insn(ulong insn, struct sbi_trap_regs *regs)
{
int do_write, rs1_num = (insn >> 15) & 0x1f;
ulong rs1_val = GET_RS1(insn, regs);
int csr_num = (u32)insn >> 20;
bool do_write = false;
int rs1_num = GET_RS1_NUM(insn);
ulong rs1_val = GET_RS1(insn, regs);
int csr_num = GET_CSR_NUM((u32)insn);
ulong prev_mode = (regs->mstatus & MSTATUS_MPP) >> MSTATUS_MPP_SHIFT;
ulong csr_val, new_csr_val;
@@ -60,32 +61,41 @@ static int system_opcode_insn(ulong insn, struct sbi_trap_regs *regs)
return SBI_EFAIL;
}
/* TODO: Ensure that we got CSR read/write instruction */
/* Ensure that we got CSR read/write instruction */
int funct3 = GET_RM(insn);
if (funct3 == 0 || funct3 == 4) {
sbi_printf("%s: Invalid opcode for CSR read/write instruction",
__func__);
return truly_illegal_insn(insn, regs);
}
if (sbi_emulate_csr_read(csr_num, regs, &csr_val))
return truly_illegal_insn(insn, regs);
do_write = rs1_num;
switch (GET_RM(insn)) {
case 1:
switch (funct3) {
case CSRRW:
new_csr_val = rs1_val;
do_write = 1;
do_write = true;
break;
case 2:
case CSRRS:
new_csr_val = csr_val | rs1_val;
do_write = (rs1_num != 0);
break;
case 3:
case CSRRC:
new_csr_val = csr_val & ~rs1_val;
do_write = (rs1_num != 0);
break;
case 5:
case CSRRWI:
new_csr_val = rs1_num;
do_write = 1;
do_write = true;
break;
case 6:
case CSRRSI:
new_csr_val = csr_val | rs1_num;
do_write = (rs1_num != 0);
break;
case 7:
case CSRRCI:
new_csr_val = csr_val & ~rs1_num;
do_write = (rs1_num != 0);
break;
default:
return truly_illegal_insn(insn, regs);