Skip to content

Commit 87688d7

Browse files
committed
Detect fp_exceptions in FADD
Defined several floating-point exceptions and a fflag_mask in riscv_private.h It will now detect invalid_op, overflow, and inexact during execution of FADD and set the corresponding bit in FCSR. Modify csr_get_ptr and csr_csrrs so that insn CSRRS can deal with CSR_FFLAGS. New test passed: fadd_b10-01 fadd_b11-01 fadd_b12-01 fadd_b13-01 fadd_b7-01
1 parent a99d779 commit 87688d7

2 files changed

Lines changed: 36 additions & 7 deletions

File tree

emulate.c

Lines changed: 23 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -617,6 +617,8 @@ static uint32_t *csr_get_ptr(struct riscv_t *rv, uint32_t csr)
617617
case CSR_MIP:
618618
return (uint32_t *) (&rv->csr_mip);
619619
#ifdef ENABLE_RV32F
620+
case CSR_FFLAGS:
621+
return (uint32_t *) (&rv->csr_fcsr);
620622
case CSR_FCSR:
621623
return (uint32_t *) (&rv->csr_fcsr);
622624
#endif
@@ -651,7 +653,10 @@ static uint32_t csr_csrrs(struct riscv_t *rv, uint32_t csr, uint32_t val)
651653
if (!c)
652654
return 0;
653655

654-
const uint32_t out = *c;
656+
uint32_t out = *c;
657+
if (csr == CSR_FFLAGS)
658+
out &= FFLAG_MASK;
659+
655660
if (csr_is_writable(csr))
656661
*c |= val;
657662

@@ -901,10 +906,25 @@ static bool op_fp(struct riscv_t *rv, uint32_t insn)
901906
/* dispatch based on func7 (low 2 bits are width) */
902907
switch (funct7) {
903908
case 0b0000000: /* FADD */
904-
rv->F[rd] = rv->F[rs1] + rv->F[rs2];
909+
if (isnan(rv->F[rs1]) || isnan(rv->F[rs2]) ||
910+
isnan(rv->F[rs1] + rv->F[rs2])) {
911+
/* raise invalid operation */
912+
*((uint32_t *) &rv->F[rd]) = RV_NAN;
913+
rv->csr_fcsr |= FFLAG_INVALID_OP;
914+
} else {
915+
rv->F[rd] = rv->F[rs1] + rv->F[rs2];
916+
}
917+
if (isinff(rv->F[rd])) {
918+
rv->csr_fcsr |= FFLAG_OVERFLOW;
919+
rv->csr_fcsr |= FFLAG_INEXACT;
920+
}
905921
break;
906922
case 0b0000100: /* FSUB */
907-
rv->F[rd] = rv->F[rs1] - rv->F[rs2];
923+
if (isnan(rv->F[rs1]) || isnan(rv->F[rs2])) {
924+
*((uint32_t *) &rv->F[rd]) = RV_NAN;
925+
} else {
926+
rv->F[rd] = rv->F[rs1] - rv->F[rs2];
927+
}
908928
break;
909929
case 0b0001000: /* FMUL */
910930
rv->F[rd] = rv->F[rs1] * rv->F[rs2];

riscv_private.h

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -102,10 +102,19 @@ enum {
102102

103103
#ifdef ENABLE_RV32F
104104
enum {
105-
// ....xxxx....xxxx....xxxx....xxxx
106-
FMASK_SIGN = 0b10000000000000000000000000000000,
107-
FMASK_EXPN = 0b01111111100000000000000000000000,
108-
FMASK_FRAC = 0b00000000011111111111111111111111,
105+
// ....xxxx....xxxx....xxxx....xxxx
106+
FMASK_SIGN = 0b10000000000000000000000000000000,
107+
FMASK_EXPN = 0b01111111100000000000000000000000,
108+
FMASK_FRAC = 0b00000000011111111111111111111111,
109+
// ....xxxx....xxxx....xxxx....xxxx
110+
FFLAG_MASK = 0b00000000000000000000000000011111,
111+
FFLAG_INVALID_OP = 0b00000000000000000000000000010000,
112+
FFLAG_DIV_BY_ZERO = 0b00000000000000000000000000001000,
113+
FFLAG_OVERFLOW = 0b00000000000000000000000000000100,
114+
FFLAG_UNDERFLOW = 0b00000000000000000000000000000010,
115+
FFLAG_INEXACT = 0b00000000000000000000000000000001,
116+
// ....xxxx....xxxx....xxxx....xxxx
117+
RV_NAN = 0b01111111110000000000000000000000
109118
};
110119
#endif
111120
/* clang-format off */

0 commit comments

Comments
 (0)