Skip to content

Commit bcd1862

Browse files
committed
Handle fp_exceptions in fadd
Defined several floating-point exceptions in riscv_private.h Detect invalid_op, overflow, and inexact in FADD. Modify csr_get_ptr and csr_csrrs so that it 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 80801fe commit bcd1862

File tree

2 files changed

+24
-15
lines changed

2 files changed

+24
-15
lines changed

emulate.c

Lines changed: 11 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -134,14 +134,6 @@ static void rv_except_illegal_insn(struct riscv_t *rv, uint32_t insn)
134134
rv->csr_mcause = code;
135135
}
136136

137-
/* no trap supports on floating point exceptions */
138-
/* TODO: implement fp_exception functions */
139-
static void rv_except_fp_invalid_operation(struct riscv_t *rv);
140-
static void rv_except_fp_divived_by_zero(struct riscv_t *rv);
141-
static void rv_except_fp_overflow(struct riscv_t *rv);
142-
static void rv_except_fp_underflow(struct riscv_t *rv);
143-
static void rv_except_fp_inexact(struct riscv_t *rv);
144-
145137
static bool op_load(struct riscv_t *rv, uint32_t insn UNUSED)
146138
{
147139
/* I-type format */
@@ -625,6 +617,8 @@ static uint32_t *csr_get_ptr(struct riscv_t *rv, uint32_t csr)
625617
case CSR_MIP:
626618
return (uint32_t *) (&rv->csr_mip);
627619
#ifdef ENABLE_RV32F
620+
case CSR_FFLAGS:
621+
return (uint32_t *) (&rv->csr_fcsr);
628622
case CSR_FCSR:
629623
return (uint32_t *) (&rv->csr_fcsr);
630624
#endif
@@ -659,7 +653,7 @@ static uint32_t csr_csrrs(struct riscv_t *rv, uint32_t csr, uint32_t val)
659653
if (!c)
660654
return 0;
661655

662-
const uint32_t out = *c;
656+
const uint32_t out = (csr == CSR_FFLAGS) ? *c & FFLAG_MASK : *c;
663657
if (csr_is_writable(csr))
664658
*c |= val;
665659

@@ -909,11 +903,18 @@ static bool op_fp(struct riscv_t *rv, uint32_t insn)
909903
/* dispatch based on func7 (low 2 bits are width) */
910904
switch (funct7) {
911905
case 0b0000000: /* FADD */
912-
if (isnan(rv->F[rs1]) || isnan(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 */
913909
*((uint32_t *) &rv->F[rd]) = RV_NAN;
910+
rv->csr_fcsr |= FFLAG_INVALID_OP;
914911
} else {
915912
rv->F[rd] = rv->F[rs1] + rv->F[rs2];
916913
}
914+
if (isinff(rv->F[rd])) {
915+
rv->csr_fcsr |= FFLAG_OVERFLOW;
916+
rv->csr_fcsr |= FFLAG_INEXACT;
917+
}
917918
break;
918919
case 0b0000100: /* FSUB */
919920
if (isnan(rv->F[rs1]) || isnan(rv->F[rs2])) {

riscv_private.h

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@
44
#include "riscv.h"
55

66
#define RV_NUM_REGS 32
7-
#define RV_NAN 0x7fc00000
87

98
/* csrs */
109
enum {
@@ -103,10 +102,19 @@ enum {
103102

104103
#ifdef ENABLE_RV32F
105104
enum {
106-
// ....xxxx....xxxx....xxxx....xxxx
107-
FMASK_SIGN = 0b10000000000000000000000000000000,
108-
FMASK_EXPN = 0b01111111100000000000000000000000,
109-
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
110118
};
111119
#endif
112120
/* clang-format off */

0 commit comments

Comments
 (0)