diff --git a/examples/fp/softfloat_demo/Makefile b/examples/fp/softfloat_demo/Makefile index cc98d0cfb..373d131ca 100644 --- a/examples/fp/softfloat_demo/Makefile +++ b/examples/fp/softfloat_demo/Makefile @@ -6,7 +6,7 @@ LFLAGS = -L. # Link against the riscv-isa-sim version of SoftFloat rather than # the regular version to get RISC-V NaN behavior #IFLAGS = -I$(RISCV)/riscv-isa-sim/softfloat -#LIBS = $(RISCV)/riscv-isa-sim/build/libsoftfloat.a +#LIBS = $(RISCV)/riscv-isa-sim/build/libsoftfloat.a -lm -lquadmath IFLAGS = -I../../../addins/SoftFloat-3e/source/include/ LIBS = ../../../addins/SoftFloat-3e/build/Linux-x86_64-GCC/softfloat.a -lm -lquadmath SRCS = $(wildcard *.c) diff --git a/examples/fp/softfloat_demo/softfloat_demoDP.c b/examples/fp/softfloat_demo/softfloat_demoDP.c index 50b3d0b53..b46103eed 100644 --- a/examples/fp/softfloat_demo/softfloat_demoDP.c +++ b/examples/fp/softfloat_demo/softfloat_demoDP.c @@ -38,16 +38,19 @@ void printF64 (char *msg, float64_t d) { int i, j; conv.v = d.v; // use union to convert between hexadecimal and floating-point views printf("%s: ", msg); // print out nicely - printf("0x%08x_%08x = %g\n", (conv.v >> 32),(conv.v & 0xFFFFFFFF), conv.d); + printf("0x%08lx_%08lx = %g\n", (conv.v >> 32),(conv.v & 0xFFFFFFFF), conv.d); } void printF128 (char *msg, float128_t q) { qp conv; int i, j; + char buf[64]; conv.v[0] = q.v[0]; // use union to convert between hexadecimal and floating-point views conv.v[1] = q.v[1]; // use union to convert between hexadecimal and floating-point views printf("%s: ", msg); // print out nicely - printf("0x%016" PRIx64 "_%016" PRIx64 " = %1.15Qe\n", q.v[1], q.v[0], conv.q); + //printf("0x%016" PRIx64 "_%016" PRIx64 " = %1.15Qe\n", q.v[1], q.v[0], conv.q); + quadmath_snprintf (buf, sizeof buf, "%1.15Qe", conv.q); + printf("0x%016" PRIx64 "_%016" PRIx64 " = %s\n", q.v[1], q.v[0], buf); } void printFlags(void) { diff --git a/examples/fp/softfloat_demo/softfloat_demoQP.c b/examples/fp/softfloat_demo/softfloat_demoQP.c index 03f0e5edb..0f97d3bf6 100644 --- a/examples/fp/softfloat_demo/softfloat_demoQP.c +++ b/examples/fp/softfloat_demo/softfloat_demoQP.c @@ -38,16 +38,23 @@ void printF64 (char *msg, float64_t d) { int i, j; conv.v = d.v; // use union to convert between hexadecimal and floating-point views printf("%s: ", msg); // print out nicely - printf("0x%08x_%08x = %g\n", (conv.v >> 32),(conv.v & 0xFFFFFFFF), conv.d); + printf("0x%08lx_%08lx = %g\n", (conv.v >> 32),(conv.v & 0xFFFFFFFF), conv.d); } void printF128 (char *msg, float128_t q) { qp conv; int i, j; + char buf[64]; conv.v[0] = q.v[0]; // use union to convert between hexadecimal and floating-point views conv.v[1] = q.v[1]; // use union to convert between hexadecimal and floating-point views printf("%s: ", msg); // print out nicely - printf("0x%016" PRIx64 "_%016" PRIx64 " = %1.15Qe\n", q.v[1], q.v[0], conv.q); + + // Some compilers can understand %Q for printf on quad precision instead of the + // API call of quadmath_snprintf + // printf("0x%016" PRIx64 "_%016" PRIx64 " = %1.15Qe\n", q.v[1], q.v[0], conv.q); + quadmath_snprintf (buf, sizeof buf, "%1.15Qe", conv.q); + printf("0x%016" PRIx64 "_%016" PRIx64 " = %s\n", q.v[1], q.v[0], buf); + } void printFlags(void) { @@ -74,6 +81,8 @@ int main() { float128_t x, y, z; float128_t r; + uint32_t u, v, w; + int32_t a, b, c; x.v[1] = 0xBFFF988ECE97DFEB; x.v[0] = 0xC3BBA082445B4836; diff --git a/examples/fp/softfloat_demo/softfloat_demoSP.c b/examples/fp/softfloat_demo/softfloat_demoSP.c index 55c5ef991..bbc39438e 100644 --- a/examples/fp/softfloat_demo/softfloat_demoSP.c +++ b/examples/fp/softfloat_demo/softfloat_demoSP.c @@ -38,16 +38,19 @@ void printF64 (char *msg, float64_t d) { int i, j; conv.v = d.v; // use union to convert between hexadecimal and floating-point views printf("%s: ", msg); // print out nicely - printf("0x%08x_%08x = %g\n", (conv.v >> 32),(conv.v & 0xFFFFFFFF), conv.d); + printf("0x%08lx_%08lx = %g\n", (conv.v >> 32),(conv.v & 0xFFFFFFFF), conv.d); } void printF128 (char *msg, float128_t q) { qp conv; int i, j; + char buf[64]; conv.v[0] = q.v[0]; // use union to convert between hexadecimal and floating-point views conv.v[1] = q.v[1]; // use union to convert between hexadecimal and floating-point views printf("%s: ", msg); // print out nicely - printf("0x%016" PRIx64 "_%016" PRIx64 " = %1.15Qe\n", q.v[1], q.v[0], conv.q); + //printf("0x%016" PRIx64 "_%016" PRIx64 " = %1.15Qe\n", q.v[1], q.v[0], conv.q); + quadmath_snprintf (buf, sizeof buf, "%1.15Qe", conv.q); + printf("0x%016" PRIx64 "_%016" PRIx64 " = %s\n", q.v[1], q.v[0], buf); } void printFlags(void) { diff --git a/src/fpu/postproc/specialcase.sv b/src/fpu/postproc/specialcase.sv index c8442595a..5161bc645 100644 --- a/src/fpu/postproc/specialcase.sv +++ b/src/fpu/postproc/specialcase.sv @@ -266,6 +266,30 @@ module specialcase import cvw::*; #(parameter cvw_t P) ( // integer result selection /////////////////////////////////////////////////////////////////////////////////////// + // Causes undefined behavior for invalid: + + // Invalid cases are different for IEEE 754 vs. RISC-V. For RISC-V, typical results are used + // unsigned: if invalid (e.g., negative fp to unsigned int, result should overflow and + // overflows to the maximum value + // signed: if invalid, result should overflow to maximum negative value + // but is undefined and used for information only + // Note: The IEEE 754 result comes from values in TestFloat for x86_64 + + // IEEE 754 + // select the overflow integer res + // - negitive infinity and out of range negitive input + // | int | long | + // signed | -2^31 | -2^63 | + // unsigned | 2^32-1 | 2^64-1 | + // + // - positive infinity and out of range positive input and NaNs + // | int | long | + // signed | -2^31 |-2^63 | + // unsigned | 2^32-1 | 2^64-1 | + // + // other: 32 bit unsigned res should be sign extended as if it were a signed number + + // RISC-V // select the overflow integer res // - negitive infinity and out of range negitive input // | int | long | @@ -278,17 +302,34 @@ module specialcase import cvw::*; #(parameter cvw_t P) ( // unsigned | 2^32-1 | 2^64-1 | // // other: 32 bit unsinged res should be sign extended as if it were a signed number - always_comb - if(Signed) - if(Xs&~NaNIn) // signed negitive - if(Int64) OfIntRes = {1'b1, {P.XLEN-1{1'b0}}}; - else OfIntRes = {{P.XLEN-32{1'b1}}, 1'b1, {31{1'b0}}}; - else // signed positive - if(Int64) OfIntRes = {1'b0, {P.XLEN-1{1'b1}}}; - else OfIntRes = {{P.XLEN-32{1'b0}}, 1'b0, {31{1'b1}}}; - else - if(Xs&~NaNIn) OfIntRes = {P.XLEN{1'b0}}; // unsigned negitive - else OfIntRes = {P.XLEN{1'b1}}; // unsigned positive + + if(P.IEEE754) begin + always_comb + if(Signed) + if(Xs&~NaNIn) // signed negitive + if(Int64) OfIntRes = {1'b1, {P.XLEN-1{1'b0}}}; + else OfIntRes = {{P.XLEN-32{1'b1}}, 1'b1, {31{1'b0}}}; + else // signed positive + if(Int64) OfIntRes = {1'b1, {P.XLEN-1{1'b0}}}; + else OfIntRes = {{P.XLEN-32{1'b1}}, 1'b1, {31{1'b0}}}; + else + if(Xs&~NaNIn) OfIntRes = {P.XLEN{1'b1}}; // unsigned negitive + else OfIntRes = {P.XLEN{1'b1}}; // unsigned positive + end // if (P.IEEE754) + else begin + always_comb + if(Signed) + if(Xs&~NaNIn) // signed negitive + if(Int64) OfIntRes = {1'b1, {P.XLEN-1{1'b0}}}; + else OfIntRes = {{P.XLEN-32{1'b1}}, 1'b1, {31{1'b0}}}; + else // signed positive + if(Int64) OfIntRes = {1'b0, {P.XLEN-1{1'b1}}}; + else OfIntRes = {{P.XLEN-32{1'b0}}, 1'b0, {31{1'b1}}}; + else + if(Xs&~NaNIn) OfIntRes = {P.XLEN{1'b0}}; // unsigned negitive + else OfIntRes = {P.XLEN{1'b1}}; // unsigned positive + end // else: !if(P.IEEE754) + // select the integer output // - if the input is invalid (out of bounds NaN or Inf) then output overflow res