Skip to content

Commit bd603d6

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 bd603d6

File tree

2 files changed

+33
-7
lines changed

2 files changed

+33
-7
lines changed

emulate.c

Lines changed: 20 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,7 @@ 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+
const uint32_t out = (csr == CSR_FFLAGS) ? *c & FFLAG_MASK : *c;
655657
if (csr_is_writable(csr))
656658
*c |= val;
657659

@@ -901,10 +903,25 @@ static bool op_fp(struct riscv_t *rv, uint32_t insn)
901903
/* dispatch based on func7 (low 2 bits are width) */
902904
switch (funct7) {
903905
case 0b0000000: /* FADD */
904-
rv->F[rd] = rv->F[rs1] + rv->F[rs2];
906+
if (isnan(rv->F[rs1]) || isnan(rv->F[rs2]) ||
907+
isnan(rv->F[rs1] + rv->F[rs2])) {
908+
/* raise invalid operation */
909+
*((uint32_t *) &rv->F[rd]) = RV_NAN;
910+
rv->csr_fcsr |= FFLAG_INVALID_OP;
911+
} else {
912+
rv->F[rd] = rv->F[rs1] + rv->F[rs2];
913+
}
914+
if (isinff(rv->F[rd])) {
915+
rv->csr_fcsr |= FFLAG_OVERFLOW;
916+
rv->csr_fcsr |= FFLAG_INEXACT;
917+
}
905918
break;
906919
case 0b0000100: /* FSUB */
907-
rv->F[rd] = rv->F[rs1] - rv->F[rs2];
920+
if (isnan(rv->F[rs1]) || isnan(rv->F[rs2])) {
921+
*((uint32_t *) &rv->F[rd]) = RV_NAN;
922+
} else {
923+
rv->F[rd] = rv->F[rs1] - rv->F[rs2];
924+
}
908925
break;
909926
case 0b0001000: /* FMUL */
910927
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)