@@ -1012,8 +1012,8 @@ static inline bool op_fp(struct riscv_t *rv, uint32_t insn)
1012
1012
/* dispatch based on func7 (low 2 bits are width) */
1013
1013
switch (funct7 ) {
1014
1014
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 ])) {
1017
1017
/* raise invalid operation */
1018
1018
rv -> F_int [rd ] = RV_NAN ; /* F_int is the integer shortcut of F */
1019
1019
rv -> csr_fcsr |= FFLAG_INVALID_OP ;
@@ -1026,7 +1026,7 @@ static inline bool op_fp(struct riscv_t *rv, uint32_t insn)
1026
1026
}
1027
1027
break ;
1028
1028
case 0b0000100 : /* FSUB */
1029
- if (isnan (rv -> F [rs1 ]) || isnan (rv -> F [rs2 ])) {
1029
+ if (isnanf (rv -> F [rs1 ]) || isnanf (rv -> F [rs2 ])) {
1030
1030
rv -> F_int [rd ] = RV_NAN ;
1031
1031
} else {
1032
1032
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)
1066
1066
}
1067
1067
case 0b0010100 :
1068
1068
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
+ }
1071
1109
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
+
1074
1145
break ;
1146
+ }
1075
1147
default :
1076
1148
rv_except_illegal_insn (rv , insn );
1077
1149
return false;
0 commit comments