Skip to content

Detect NaN in FADD and FSUB #24

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Aug 2, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
39 changes: 34 additions & 5 deletions emulate.c
Original file line number Diff line number Diff line change
Expand Up @@ -617,6 +617,8 @@ static uint32_t *csr_get_ptr(struct riscv_t *rv, uint32_t csr)
case CSR_MIP:
return (uint32_t *) (&rv->csr_mip);
#ifdef ENABLE_RV32F
case CSR_FFLAGS:
return (uint32_t *) (&rv->csr_fcsr);
case CSR_FCSR:
return (uint32_t *) (&rv->csr_fcsr);
#endif
Expand All @@ -637,7 +639,11 @@ static uint32_t csr_csrrw(struct riscv_t *rv, uint32_t csr, uint32_t val)
if (!c)
return 0;

const uint32_t out = *c;
uint32_t out = *c;
#ifdef ENABLE_RV32F
if (csr == CSR_FFLAGS)
out &= FFLAG_MASK;
#endif
if (csr_is_writable(csr))
*c = val;

Expand All @@ -651,7 +657,11 @@ static uint32_t csr_csrrs(struct riscv_t *rv, uint32_t csr, uint32_t val)
if (!c)
return 0;

const uint32_t out = *c;
uint32_t out = *c;
#ifdef ENABLE_RV32F
if (csr == CSR_FFLAGS)
out &= FFLAG_MASK;
#endif
if (csr_is_writable(csr))
*c |= val;

Expand All @@ -665,7 +675,11 @@ static uint32_t csr_csrrc(struct riscv_t *rv, uint32_t csr, uint32_t val)
if (!c)
return 0;

const uint32_t out = *c;
uint32_t out = *c;
#ifdef ENABLE_RV32F
if (csr == CSR_FFLAGS)
out &= FFLAG_MASK;
#endif
if (csr_is_writable(csr))
*c &= ~val;
return out;
Expand Down Expand Up @@ -901,10 +915,25 @@ static bool op_fp(struct riscv_t *rv, uint32_t insn)
/* dispatch based on func7 (low 2 bits are width) */
switch (funct7) {
case 0b0000000: /* FADD */
rv->F[rd] = rv->F[rs1] + rv->F[rs2];
if (isnan(rv->F[rs1]) || isnan(rv->F[rs2]) ||
isnan(rv->F[rs1] + rv->F[rs2])) {
/* raise invalid operation */
*((uint32_t *) &rv->F[rd]) = RV_NAN;
rv->csr_fcsr |= FFLAG_INVALID_OP;
} else {
rv->F[rd] = rv->F[rs1] + rv->F[rs2];
}
if (isinff(rv->F[rd])) {
rv->csr_fcsr |= FFLAG_OVERFLOW;
rv->csr_fcsr |= FFLAG_INEXACT;
}
break;
case 0b0000100: /* FSUB */
rv->F[rd] = rv->F[rs1] - rv->F[rs2];
if (isnan(rv->F[rs1]) || isnan(rv->F[rs2])) {
*((uint32_t *) &rv->F[rd]) = RV_NAN;
} else {
rv->F[rd] = rv->F[rs1] - rv->F[rs2];
}
break;
case 0b0001000: /* FMUL */
rv->F[rd] = rv->F[rs1] * rv->F[rs2];
Expand Down
17 changes: 13 additions & 4 deletions riscv_private.h
Original file line number Diff line number Diff line change
Expand Up @@ -102,10 +102,19 @@ enum {

#ifdef ENABLE_RV32F
enum {
// ....xxxx....xxxx....xxxx....xxxx
FMASK_SIGN = 0b10000000000000000000000000000000,
FMASK_EXPN = 0b01111111100000000000000000000000,
FMASK_FRAC = 0b00000000011111111111111111111111,
// ....xxxx....xxxx....xxxx....xxxx
FMASK_SIGN = 0b10000000000000000000000000000000,
FMASK_EXPN = 0b01111111100000000000000000000000,
FMASK_FRAC = 0b00000000011111111111111111111111,
// ....xxxx....xxxx....xxxx....xxxx
FFLAG_MASK = 0b00000000000000000000000000011111,
FFLAG_INVALID_OP = 0b00000000000000000000000000010000,
FFLAG_DIV_BY_ZERO = 0b00000000000000000000000000001000,
FFLAG_OVERFLOW = 0b00000000000000000000000000000100,
FFLAG_UNDERFLOW = 0b00000000000000000000000000000010,
FFLAG_INEXACT = 0b00000000000000000000000000000001,
// ....xxxx....xxxx....xxxx....xxxx
RV_NAN = 0b01111111110000000000000000000000
};
#endif
/* clang-format off */
Expand Down