@@ -1065,8 +1065,8 @@ static inline bool op_fp(struct riscv_t *rv, uint32_t insn)
10651065 /* dispatch based on func7 (low 2 bits are width) */
10661066 switch (funct7 ) {
10671067 case 0b0000000 : /* FADD */
1068- if (isnan (rv -> F [rs1 ]) || isnan (rv -> F [rs2 ]) ||
1069- isnan (rv -> F [rs1 ] + rv -> F [rs2 ])) {
1068+ if (isnanf (rv -> F [rs1 ]) || isnanf (rv -> F [rs2 ]) ||
1069+ isnanf (rv -> F [rs1 ] + rv -> F [rs2 ])) {
10701070 /* raise invalid operation */
10711071 rv -> F_int [rd ] = RV_NAN ; /* F_int is the integer shortcut of F */
10721072 rv -> csr_fcsr |= FFLAG_INVALID_OP ;
@@ -1079,7 +1079,7 @@ static inline bool op_fp(struct riscv_t *rv, uint32_t insn)
10791079 }
10801080 break ;
10811081 case 0b0000100 : /* FSUB */
1082- if (isnan (rv -> F [rs1 ]) || isnan (rv -> F [rs2 ])) {
1082+ if (isnanf (rv -> F [rs1 ]) || isnanf (rv -> F [rs2 ])) {
10831083 rv -> F_int [rd ] = RV_NAN ;
10841084 } else {
10851085 rv -> F [rd ] = rv -> F [rs1 ] - rv -> F [rs2 ];
@@ -1119,12 +1119,84 @@ static inline bool op_fp(struct riscv_t *rv, uint32_t insn)
11191119 }
11201120 case 0b0010100 :
11211121 switch (rm ) {
1122- case 0b000 : /* FMIN */
1123- rv -> F [rd ] = fminf (rv -> F [rs1 ], rv -> F [rs2 ]);
1122+ case 0b000 : { /* FMIN */
1123+ /*
1124+ In IEEE754-201x, fmin(x, y) return
1125+ - min(x,y) if both numbers are not NaN
1126+ - if one is NaN and another is a number, return the number
1127+ - if both are NaN, return NaN
1128+
1129+ When input is signaling NaN, raise invalid operation
1130+ */
1131+ uint32_t x , y ;
1132+ memcpy (& x , rv -> F + rs1 , 4 );
1133+ memcpy (& y , rv -> F + rs2 , 4 );
1134+ if (is_nan (x ) || is_nan (y )) {
1135+ if (is_snan (x ) || is_snan (y ))
1136+ rv -> csr_fcsr |= FFLAG_INVALID_OP ;
1137+ if (is_nan (x ) && !is_nan (y )) {
1138+ rv -> F [rd ] = rv -> F [rs2 ];
1139+ } else if (!is_nan (x ) && is_nan (y )) {
1140+ rv -> F [rd ] = rv -> F [rs1 ];
1141+ } else {
1142+ rv -> F_int [rd ] = RV_NAN ;
1143+ }
1144+ } else {
1145+ uint32_t a_sign , b_sign ;
1146+ a_sign = x & FMASK_SIGN ;
1147+ b_sign = y & FMASK_SIGN ;
1148+ if (a_sign != b_sign ) {
1149+ if (a_sign ) {
1150+ rv -> F [rd ] = rv -> F [rs1 ];
1151+ } else {
1152+ rv -> F [rd ] = rv -> F [rs2 ];
1153+ }
1154+ } else {
1155+ if ((rv -> F [rs1 ] < rv -> F [rs2 ])) {
1156+ rv -> F [rd ] = rv -> F [rs1 ];
1157+ } else {
1158+ rv -> F [rd ] = rv -> F [rs2 ];
1159+ }
1160+ }
1161+ }
11241162 break ;
1125- case 0b001 : /* FMAX */
1126- rv -> F [rd ] = fmaxf (rv -> F [rs1 ], rv -> F [rs2 ]);
1163+ }
1164+ case 0b001 : { /* FMAX */
1165+ uint32_t x , y ;
1166+ memcpy (& x , rv -> F + rs1 , 4 );
1167+ memcpy (& y , rv -> F + rs2 , 4 );
1168+ if (is_nan (x ) || is_nan (y )) {
1169+ if (is_snan (x ) || is_snan (y ))
1170+ rv -> csr_fcsr |= FFLAG_INVALID_OP ;
1171+ if (is_nan (x ) && !is_nan (y )) {
1172+ rv -> F [rd ] = rv -> F [rs2 ];
1173+ } else if (!is_nan (x ) && is_nan (y )) {
1174+ rv -> F [rd ] = rv -> F [rs1 ];
1175+ } else {
1176+ rv -> F_int [rd ] = RV_NAN ;
1177+ }
1178+ } else {
1179+ uint32_t a_sign , b_sign ;
1180+ a_sign = x & FMASK_SIGN ;
1181+ b_sign = y & FMASK_SIGN ;
1182+ if (a_sign != b_sign ) {
1183+ if (a_sign ) {
1184+ rv -> F [rd ] = rv -> F [rs2 ];
1185+ } else {
1186+ rv -> F [rd ] = rv -> F [rs1 ];
1187+ }
1188+ } else {
1189+ if ((rv -> F [rs1 ] > rv -> F [rs2 ])) {
1190+ rv -> F [rd ] = rv -> F [rs1 ];
1191+ } else {
1192+ rv -> F [rd ] = rv -> F [rs2 ];
1193+ }
1194+ }
1195+ }
1196+
1197+
11271198 break ;
1199+ }
11281200 default :
11291201 rv_except_illegal_insn (rv , insn );
11301202 return false;
0 commit comments