@@ -1065,8 +1065,8 @@ static inline bool op_fp(struct riscv_t *rv, uint32_t insn)
1065
1065
/* dispatch based on func7 (low 2 bits are width) */
1066
1066
switch (funct7 ) {
1067
1067
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 ])) {
1070
1070
/* raise invalid operation */
1071
1071
rv -> F_int [rd ] = RV_NAN ; /* F_int is the integer shortcut of F */
1072
1072
rv -> csr_fcsr |= FFLAG_INVALID_OP ;
@@ -1079,7 +1079,7 @@ static inline bool op_fp(struct riscv_t *rv, uint32_t insn)
1079
1079
}
1080
1080
break ;
1081
1081
case 0b0000100 : /* FSUB */
1082
- if (isnan (rv -> F [rs1 ]) || isnan (rv -> F [rs2 ])) {
1082
+ if (isnanf (rv -> F [rs1 ]) || isnanf (rv -> F [rs2 ])) {
1083
1083
rv -> F_int [rd ] = RV_NAN ;
1084
1084
} else {
1085
1085
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)
1119
1119
}
1120
1120
case 0b0010100 :
1121
1121
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
+ }
1124
1162
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
+
1127
1198
break ;
1199
+ }
1128
1200
default :
1129
1201
rv_except_illegal_insn (rv , insn );
1130
1202
return false;
0 commit comments