Skip to content

Commit 5f5a041

Browse files
committed
Add support of FMIN/MAX
Passed 2 more test in riscv-arch-test. Supports of fmin and fmax is complete.
1 parent c979c35 commit 5f5a041

File tree

2 files changed

+90
-7
lines changed

2 files changed

+90
-7
lines changed

emulate.c

Lines changed: 79 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1012,8 +1012,8 @@ static inline bool op_fp(struct riscv_t *rv, uint32_t insn)
10121012
/* dispatch based on func7 (low 2 bits are width) */
10131013
switch (funct7) {
10141014
case 0b0000000: /* FADD */
1015-
if (isnan(rv->F[rs1]) || isnan(rv->F[rs2]) ||
1016-
isnan(rv->F[rs1] + rv->F[rs2])) {
1015+
if (isnanf(rv->F[rs1]) || isnanf(rv->F[rs2]) ||
1016+
isnanf(rv->F[rs1] + rv->F[rs2])) {
10171017
/* raise invalid operation */
10181018
rv->F_int[rd] = RV_NAN; /* F_int is the integer shortcut of F */
10191019
rv->csr_fcsr |= FFLAG_INVALID_OP;
@@ -1026,7 +1026,7 @@ static inline bool op_fp(struct riscv_t *rv, uint32_t insn)
10261026
}
10271027
break;
10281028
case 0b0000100: /* FSUB */
1029-
if (isnan(rv->F[rs1]) || isnan(rv->F[rs2])) {
1029+
if (isnanf(rv->F[rs1]) || isnanf(rv->F[rs2])) {
10301030
rv->F_int[rd] = RV_NAN;
10311031
} else {
10321032
rv->F[rd] = rv->F[rs1] - rv->F[rs2];
@@ -1066,12 +1066,84 @@ static inline bool op_fp(struct riscv_t *rv, uint32_t insn)
10661066
}
10671067
case 0b0010100:
10681068
switch (rm) {
1069-
case 0b000: /* FMIN */
1070-
rv->F[rd] = fminf(rv->F[rs1], rv->F[rs2]);
1069+
case 0b000: { /* FMIN */
1070+
/*
1071+
In IEEE754-201x, fmin(x, y) return
1072+
- min(x,y) if both numbers are not NaN
1073+
- if one is NaN and another is a number, return the number
1074+
- if both are NaN, return NaN
1075+
1076+
When input is signaling NaN, raise invalid operation
1077+
*/
1078+
uint32_t x, y;
1079+
memcpy(&x, rv->F + rs1, 4);
1080+
memcpy(&y, rv->F + rs2, 4);
1081+
if (is_nan(x) || is_nan(y)) {
1082+
if (is_signan(x) || is_signan(y))
1083+
rv->csr_fcsr |= FFLAG_INVALID_OP;
1084+
if (is_nan(x) && !is_nan(y)) {
1085+
rv->F[rd] = rv->F[rs2];
1086+
} else if (!is_nan(x) && is_nan(y)) {
1087+
rv->F[rd] = rv->F[rs1];
1088+
} else {
1089+
rv->F_int[rd] = RV_NAN;
1090+
}
1091+
} else {
1092+
uint32_t a_sign, b_sign;
1093+
a_sign = x & FMASK_SIGN;
1094+
b_sign = y & FMASK_SIGN;
1095+
if (a_sign != b_sign) {
1096+
if (a_sign) {
1097+
rv->F[rd] = rv->F[rs1];
1098+
} else {
1099+
rv->F[rd] = rv->F[rs2];
1100+
}
1101+
} else {
1102+
if ((rv->F[rs1] < rv->F[rs2])) {
1103+
rv->F[rd] = rv->F[rs1];
1104+
} else {
1105+
rv->F[rd] = rv->F[rs2];
1106+
}
1107+
}
1108+
}
10711109
break;
1072-
case 0b001: /* FMAX */
1073-
rv->F[rd] = fmaxf(rv->F[rs1], rv->F[rs2]);
1110+
}
1111+
case 0b001:{ /* FMAX */
1112+
uint32_t x, y;
1113+
memcpy(&x, rv->F + rs1, 4);
1114+
memcpy(&y, rv->F + rs2, 4);
1115+
if (is_nan(x) || is_nan(y)) {
1116+
if (is_signan(x) || is_signan(y))
1117+
rv->csr_fcsr |= FFLAG_INVALID_OP;
1118+
if (is_nan(x) && !is_nan(y)) {
1119+
rv->F[rd] = rv->F[rs2];
1120+
} else if (!is_nan(x) && is_nan(y)) {
1121+
rv->F[rd] = rv->F[rs1];
1122+
} else {
1123+
rv->F_int[rd] = RV_NAN;
1124+
}
1125+
} else {
1126+
uint32_t a_sign, b_sign;
1127+
a_sign = x & FMASK_SIGN;
1128+
b_sign = y & FMASK_SIGN;
1129+
if (a_sign != b_sign) {
1130+
if (a_sign) {
1131+
rv->F[rd] = rv->F[rs2];
1132+
} else {
1133+
rv->F[rd] = rv->F[rs1];
1134+
}
1135+
} else {
1136+
if ((rv->F[rs1] > rv->F[rs2])) {
1137+
rv->F[rd] = rv->F[rs1];
1138+
} else {
1139+
rv->F[rd] = rv->F[rs2];
1140+
}
1141+
}
1142+
}
1143+
1144+
10741145
break;
1146+
}
10751147
default:
10761148
rv_except_illegal_insn(rv, insn);
10771149
return false;

riscv_private.h

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -333,6 +333,17 @@ static inline uint32_t calc_fclass(uint32_t f) {
333333

334334
return out;
335335
}
336+
static inline bool is_nan(uint32_t f){
337+
const uint32_t expn = f & FMASK_EXPN;
338+
const uint32_t frac = f & FMASK_FRAC;
339+
return (expn == FMASK_EXPN && frac);
340+
}
341+
342+
static inline bool is_signan(uint32_t f){
343+
const uint32_t expn = f & FMASK_EXPN;
344+
const uint32_t frac = f & FMASK_FRAC;
345+
return (expn == FMASK_EXPN && frac && !(frac & FMASK_QNAN));
346+
}
336347
#endif
337348

338349
#ifdef ENABLE_RV32C

0 commit comments

Comments
 (0)