riscv: FPU trap: catch CSR access to fcsr, frm and fflags
The FRCSR, FSCSR, FRRM, FSRM, FSRMI, FRFLAGS, FSFLAGS and FSFLAGSI
are in fact CSR instructions targeting the fcsr, frm and fflags
registers. They should be caught as FPU instructions as well.
@@ -180,12 +180,30 @@ SECTION_FUNC(exception.entry, _isr_wrapper)
beqz t1, is_fp
ori t0, t0, 0b0100000
xori t1, t0, 0b0100111 /* LOAD-FP / STORE-FP */
+ beqz t1, is_fp
+ /*
+ * The FRCSR, FSCSR, FRRM, FSRM, FSRMI, FRFLAGS, FSFLAGS and FSFLAGSI
+ * are in fact CSR instructions targeting the fcsr, frm and fflags
+ * registers. They should be caught as FPU instructions as well.
+ *
+ * CSR format: csr#[31-20] src[19-15] op[14-12] dst[11-7] SYSTEM[6-0]
+ * SYSTEM = 0b1110011, op = 0b.xx where xx is never 0
+ * The csr# of interest are: 1=fflags, 2=frm, 3=fcsr
+ */
+ xori t1, t0, 0b1110011 /* SYSTEM opcode */
+ bnez t1, 2f /* not a CSR insn */
+ srli t0, t2, 12
+ andi t0, t0, 0x3
+ beqz t0, 2f /* not a CSR insn */
+ srli t0, t2, 20 /* isolate the csr register number */
+ beqz t0, 2f /* 0=ustatus */
+ andi t0, t0, ~0x3 /* 1=fflags, 2=frm, 3=fcsr */
#if !defined(CONFIG_RISCV_ISA_EXT_C)
- bnez t1, no_fp
+ bnez t0, no_fp
#else
- beqz t1, is_fp
- /* remaining non RVC (0b11) and RVC with 0b01 are not FP instructions */
- andi t1, t0, 1
+ beqz t0, is_fp
+2: /* remaining non RVC (0b11) and RVC with 0b01 are not FP instructions */
+ andi t1, t2, 1
bnez t1, no_fp
/*
* 001...........00 = C.FLD RV32/64 (RV128 = C.LQ)
@@ -214,7 +232,7 @@ is_fp: /* Process the FP trap and quickly return from exception */
la ra, fp_trap_exit
mv a0, sp
tail z_riscv_fpu_trap
-
+2:
no_fp: /* increment _current->arch.exception_depth */
lr t0, ___cpu_t_current_OFFSET(s0)
lb t1, _thread_offset_to_exception_depth(t0)
@@ -223,7 +241,7 @@ no_fp: /* increment _current->arch.exception_depth */
/* configure the FPU for exception mode */
call z_riscv_fpu_enter_exc
-#endif
+#endif /* CONFIG_FPU_SHARING */
#ifdef CONFIG_RISCV_SOC_CONTEXT_SAVE
/* Handle context saving at SOC level. */
