@@ -20,8 +20,15 @@ Bits<32> SP_NEG_ZERO = 32'b1_00000000_00000000000000000000000;
2020Bits<32> SP_CANONICAL_NAN = 32'b0_11111111_10000000000000000000000;
2121Bits<16> HP_CANONICAL_NAN = 16'b0_11111_1000000000;
2222
23- Bits<32> WORD_NEG_OVERFLOW = 32'h8000_0000; # minimum 32-bit integer
24- Bits<32> WORD_POS_OVERFLOW = 32'h7FFF_FFFF; # maximum 32-bit integer
23+ Bits<32> WORD_NEG_OVERFLOW = 32'h8000_0000; # minimum signed 32-bit integer
24+ Bits<32> WORD_POS_OVERFLOW = 32'h7FFF_FFFF; # maximum signed 32-bit integer
25+
26+ Bits<32> UI32_NEG_OVERFLOW = 32'h0000_0000; # minimum unsigned 32-bit integer
27+ Bits<32> UI32_POS_OVERFLOW = 32'hFFFF_FFFF; # maximum unsigned 32-bit integer
28+
29+ Bits<32> UI32_NAN = 32'hFFFF_FFFF; # NaN to unsigned 32-bit integer
30+ Bits<32> I32_NAN = 32'h7FFF_FFFF; # NaN to signed 32-bit integer
31+
2532
2633enum RoundingMode {
2734 RNE 0b000 # Round to Nearest, ties to Even
@@ -331,7 +338,7 @@ function softfloat_roundToI32 {
331338 Bits<64> sig,
332339 RoundingMode roundingMode
333340 description {
334- Round to unsigned 32-bit integer, using +rounding_mode+
341+ Round to signed 32-bit integer, using +rounding_mode+
335342 }
336343 body {
337344 Bits<16> roundIncrement = 0x800;
@@ -375,6 +382,58 @@ function softfloat_roundToI32 {
375382 }
376383}
377384
385+ function softfloat_roundToUI32 {
386+ returns Bits<32>
387+ arguments
388+ Bits<1> sign,
389+ Bits<64> sig,
390+ RoundingMode roundingMode
391+ description {
392+ Round to unsigned 32-bit integer, using +rounding_mode+
393+ }
394+ body {
395+ Bits<16> roundIncrement = 0x800;
396+ if (
397+ (roundingMode != RoundingMode::RMM)
398+ && (roundingMode != RoundingMode::RNE)
399+ ) {
400+ roundIncrement = 0;
401+ if ( sign == 1) {
402+ if (sig == 0) { return 0; }
403+ if (roundingMode == RoundingMode::RDN) { set_fp_flag(FpFlag::NV); }
404+ } else {
405+ if (roundingMode == RoundingMode::RUP) { roundIncrement = 0xFFF; }
406+ }
407+ }
408+
409+ Bits<16> roundBits = sig & 0xFFF;
410+ sig = sig + roundIncrement;
411+ if ((sig & 0xFFFFF00000000000) != 0) {
412+ set_fp_flag(FpFlag::NV);
413+ return sign == 1 ? UI32_NEG_OVERFLOW : UI32_POS_OVERFLOW;
414+ }
415+
416+ Bits<32> z = sig >> 12;
417+ if (
418+ (roundBits == 0x800 && (roundingMode == RoundingMode::RNE))
419+ ) {
420+ z = z & ~32'b1;
421+ }
422+
423+
424+
425+ if ((z != 0) && (sign == 1)) {
426+ set_fp_flag(FpFlag::NV);
427+ return sign == 1 ? UI32_NEG_OVERFLOW : UI32_POS_OVERFLOW;
428+ }
429+
430+ if (roundBits != 0) {
431+ set_fp_flag(FpFlag::NX);
432+ }
433+ return z;
434+ }
435+ }
436+
378437function packToF32UI {
379438 returns Bits<32>
380439 arguments
@@ -875,7 +934,7 @@ function i32_to_f32 {
875934 U32 a,
876935 RoundingMode mode
877936 description {
878- Converts 32-bit signed integer to 32-bit floating point
937+ Converts 32-bit signed integer to 32-bit floating point number
879938 }
880939 body {
881940 # sign of integer, it is 1 when negative
@@ -894,7 +953,7 @@ function ui32_to_f32 {
894953 U32 a,
895954 RoundingMode mode
896955 description {
897- Converts 32-bit unsigned integer to 32-bit floating point
956+ Converts 32-bit unsigned integer to 32-bit floating point number
898957 }
899958 body {
900959 # sign of integer, it is 1 when negative
@@ -908,3 +967,77 @@ function ui32_to_f32 {
908967 }
909968 }
910969}
970+
971+ function f32_to_i32 {
972+ returns U32
973+ arguments
974+ U32 a,
975+ RoundingMode mode
976+ description {
977+ Converts 32-bit floating point number to a signed 32-bit integer
978+ }
979+ body {
980+ Bits<1> sign = signF32UI(a);
981+ Bits<8> exp = expF32UI(a);
982+ Bits<23> sig = fracF32UI(a);
983+ Bits<8> shiftDist;
984+ U64 sig64;
985+ # for NaN return the highest positive value and set floating-point flag to invalid.
986+ if ((exp == 8'hFF) && (sig != 0)) {
987+ sign = 0;
988+ set_fp_flag(FpFlag::NV);
989+ return I32_NAN;
990+ }
991+
992+ # MSB of significand is set to 1 because minimum 32-bit integer in IEEE 754 is 32'h80000000
993+ if (exp != 0) {
994+ sig = sig | 32'h00800000;
995+ }
996+
997+ sig64 = sig `<< 32;
998+ shiftDist = 8'hAA - exp;
999+
1000+ if (shiftDist > 0) {
1001+ sig64 = softfloat_shiftRightJam64( sig64, shiftDist);
1002+ }
1003+
1004+ return softfloat_roundToI32(sign, sig64, mode);
1005+ }
1006+ }
1007+
1008+ function f32_to_ui32 {
1009+ returns U32
1010+ arguments
1011+ U32 a,
1012+ RoundingMode mode
1013+ description {
1014+ Converts 32-bit floating point number to an unsigned 32-bit integer
1015+ }
1016+ body {
1017+ Bits<1> sign = signF32UI(a);
1018+ Bits<8> exp = expF32UI(a);
1019+ Bits<23> sig = fracF32UI(a);
1020+ Bits<8> shiftDist;
1021+ U64 sig64;
1022+ # for NaN return the highest positive value and set floating-point flag to invalid.
1023+ if ((exp == 8'hFF) && (sig != 0)) {
1024+ sign = 0;
1025+ set_fp_flag(FpFlag::NV);
1026+ return UI32_NAN;
1027+ }
1028+
1029+ # MSB of significand is set to 1 because minimum 32-bit integer in IEEE 754 is 32'h80000000
1030+ if (exp != 0) {
1031+ sig = sig | 32'h00800000;
1032+ }
1033+
1034+ sig64 = sig `<< 32;
1035+ shiftDist = 8'hAA - exp;
1036+
1037+ if (shiftDist > 0) {
1038+ sig64 = softfloat_shiftRightJam64( sig64, shiftDist);
1039+ }
1040+
1041+ return softfloat_roundToUI32(sign, sig64, mode);
1042+ }
1043+ }
0 commit comments