Skip to content

Commit

Permalink
Add support of FMIN/MAX
Browse files Browse the repository at this point in the history
Passed 2 more test in riscv-arch-test.
Supports of fmin and fmax is complete.
  • Loading branch information
2011eric committed Sep 8, 2022
1 parent c979c35 commit 6f142f4
Show file tree
Hide file tree
Showing 2 changed files with 86 additions and 4 deletions.
79 changes: 75 additions & 4 deletions emulate.c
Original file line number Diff line number Diff line change
Expand Up @@ -1012,8 +1012,8 @@ static inline bool op_fp(struct riscv_t *rv, uint32_t insn)
/* dispatch based on func7 (low 2 bits are width) */
switch (funct7) {
case 0b0000000: /* FADD */
if (isnan(rv->F[rs1]) || isnan(rv->F[rs2]) ||
isnan(rv->F[rs1] + rv->F[rs2])) {
if (isnanf(rv->F[rs1]) || isnanf(rv->F[rs2]) ||
isnanf(rv->F[rs1] + rv->F[rs2])) {
/* raise invalid operation */
rv->F_int[rd] = RV_NAN; /* F_int is the integer shortcut of F */
rv->csr_fcsr |= FFLAG_INVALID_OP;
Expand All @@ -1026,7 +1026,7 @@ static inline bool op_fp(struct riscv_t *rv, uint32_t insn)
}
break;
case 0b0000100: /* FSUB */
if (isnan(rv->F[rs1]) || isnan(rv->F[rs2])) {
if (isnanf(rv->F[rs1]) || isnanf(rv->F[rs2])) {
rv->F_int[rd] = RV_NAN;
} else {
rv->F[rd] = rv->F[rs1] - rv->F[rs2];
Expand Down Expand Up @@ -1067,9 +1067,80 @@ static inline bool op_fp(struct riscv_t *rv, uint32_t insn)
case 0b0010100:
switch (rm) {
case 0b000: /* FMIN */
rv->F[rd] = fminf(rv->F[rs1], rv->F[rs2]);
/*
In IEEE754-201x, fmin(x, y) return
- min(x,y) if both numbers are not NaN
- if one is NaN and another is a number, return the number
- if both are NaN, return NaN
When input is signaling NaN, raise invalid operation
*/
uint32_t x, y;
memcpy(&x, rv->F + rs1, 4);
memcpy(&y, rv->F + rs2, 4);
if (is_nan(x) || is_nan(y)) {
if (is_signan(x) || is_signan(y))
rv->csr_fcsr |= FFLAG_INVALID_OP;
if (is_nan(x) && !is_nan(y)) {
rv->F[rd] = rv->F[rs2];
} else if (!is_nan(x) && is_nan(y)) {
rv->F[rd] = rv->F[rs1];
} else {
rv->F_int[rd] = RV_NAN;
}
} else {
uint32_t a_sign, b_sign;
a_sign = x & FMASK_SIGN;
b_sign = y & FMASK_SIGN;
if (a_sign != b_sign) {
if (a_sign) {
rv->F[rd] = rv->F[rs1];
} else {
rv->F[rd] = rv->F[rs2];
}
} else {
if ((rv->F[rs1] < rv->F[rs2])) {
rv->F[rd] = rv->F[rs1];
} else {
rv->F[rd] = rv->F[rs2];
}
}
}
break;
case 0b001: /* FMAX */

memcpy(&x, rv->F + rs1, 4);
memcpy(&y, rv->F + rs2, 4);
if (is_nan(x) || is_nan(y)) {
if (is_signan(x) || is_signan(y))
rv->csr_fcsr |= FFLAG_INVALID_OP;
if (is_nan(x) && !is_nan(y)) {
rv->F[rd] = rv->F[rs2];
} else if (!is_nan(x) && is_nan(y)) {
rv->F[rd] = rv->F[rs1];
} else {
rv->F_int[rd] = RV_NAN;
}
} else {
uint32_t a_sign, b_sign;
a_sign = x & FMASK_SIGN;
b_sign = y & FMASK_SIGN;
if (a_sign != b_sign) {
if (a_sign) {
rv->F[rd] = rv->F[rs2];
} else {
rv->F[rd] = rv->F[rs1];
}
} else {
if ((rv->F[rs1] > rv->F[rs2])) {
rv->F[rd] = rv->F[rs1];
} else {
rv->F[rd] = rv->F[rs2];
}
}
}


rv->F[rd] = fmaxf(rv->F[rs1], rv->F[rs2]);
break;
default:
Expand Down
11 changes: 11 additions & 0 deletions riscv_private.h
Original file line number Diff line number Diff line change
Expand Up @@ -333,6 +333,17 @@ static inline uint32_t calc_fclass(uint32_t f) {

return out;
}
static inline bool is_nan(uint32_t f){
const uint32_t expn = f & FMASK_EXPN;
const uint32_t frac = f & FMASK_FRAC;
return (expn == FMASK_EXPN && frac);
}

static inline bool is_signan(uint32_t f){
const uint32_t expn = f & FMASK_EXPN;
const uint32_t frac = f & FMASK_FRAC;
return (expn == FMASK_EXPN && frac && !(frac & FMASK_QNAN));
}
#endif

#ifdef ENABLE_RV32C
Expand Down

0 comments on commit 6f142f4

Please sign in to comment.