From: Alice Zhang Date: Tue, 10 Nov 2020 18:11:13 +0000 (-0500) Subject: PR13838: Add float32 support and corresponding test cases X-Git-Tag: release-4.5~153 X-Git-Url: https://sourceware.org/git/?a=commitdiff_plain;h=25afbb60a974b17bdcd7129d071e811a95516a3d;p=systemtap.git PR13838: Add float32 support and corresponding test cases runtime/softfloat.* & runtime/softfloat/: add f32 support and f32 to f64 conversion tapset/floatingpoint.stp: fixed some documentation typos & add f32_tp_f64 tapset function testsuite/buildok/floatingpoint.stp: add f32 related test cases main.cxx: add float parameter to sdt_benchmark_thread function for test purpose runtime/softfloat.c & tapset/floatingpoint.stp : delete unnecessary functions to keep the code concise --- diff --git a/main.cxx b/main.cxx index e63be8f16..f3a0d9830 100644 --- a/main.cxx +++ b/main.cxx @@ -375,10 +375,11 @@ setup_signals (sighandler_t handler) static void -sdt_benchmark_thread(unsigned long i, double *fpointer) +sdt_benchmark_thread(unsigned long i, double *fpointer, float *fpointer2) { PROBE(stap, benchmark__thread__start); *fpointer += 0.0; + *fpointer2 += 0.0; while (i--) PROBE1(stap, benchmark, i); PROBE(stap, benchmark__thread__end); @@ -405,8 +406,9 @@ run_sdt_benchmark(systemtap_session& s) { vector handles; double f = 2.71828; + float f2 = 1.41421; for (unsigned long i = 0; i < threads; ++i) - handles.push_back(thread(sdt_benchmark_thread, loops,&f)); + handles.push_back(thread(sdt_benchmark_thread, loops, &f, &f2)); for (unsigned long i = 0; i < threads; ++i) handles[i].join(); } diff --git a/runtime/softfloat.c b/runtime/softfloat.c index 7122c6625..695193370 100644 --- a/runtime/softfloat.c +++ b/runtime/softfloat.c @@ -52,6 +52,30 @@ THREAD_LOCAL uint_fast8_t softfloat_exceptionFlags = 0; THREAD_LOCAL uint_fast8_t extF80_roundingPrecision = 80; +#ifndef softfloat_countLeadingZeros32 + +#define softfloat_countLeadingZeros32 softfloat_countLeadingZeros32 + +uint_fast8_t softfloat_countLeadingZeros32( uint32_t a ) +{ + uint_fast8_t count; + + count = 0; + if ( a < 0x10000 ) { + count = 16; + a <<= 16; + } + if ( a < 0x1000000 ) { + count += 8; + a <<= 8; + } + count += softfloat_countLeadingZeros8[a>>24]; + return count; + +} + +#endif + #ifndef softfloat_countLeadingZeros64 #define softfloat_countLeadingZeros64 softfloat_countLeadingZeros64 @@ -178,7 +202,6 @@ void #endif - #ifndef softfloat_shiftRightJam64 uint64_t softfloat_shiftRightJam64( uint64_t a, uint_fast32_t dist ) @@ -501,6 +524,17 @@ int_fast64_t f64_to_i64( float64_t a, uint_fast8_t roundingMode, bool exact ) } +/*---------------------------------------------------------------------------- +| Converts the common NaN pointed to by 'aPtr' into a 32-bit floating-point +| NaN, and returns the bit pattern of this value as an unsigned integer. +*----------------------------------------------------------------------------*/ +uint_fast32_t softfloat_commonNaNToF32UI( const struct commonNaN *aPtr ) +{ + + return (uint_fast32_t) aPtr->sign<<31 | 0x7FC00000 | aPtr->v64>>41; + +} + /*---------------------------------------------------------------------------- | Converts the common NaN pointed to by 'aPtr' into a 64-bit floating-point | NaN, and returns the bit pattern of this value as an unsigned integer. @@ -512,6 +546,24 @@ uint_fast64_t softfloat_commonNaNToF64UI( const struct commonNaN *aPtr ) | aPtr->v64>>12; } +/*---------------------------------------------------------------------------- +| Assuming 'uiA' has the bit pattern of a 32-bit floating-point NaN, converts +| this NaN to the common NaN form, and stores the resulting common NaN at the +| location pointed to by 'zPtr'. If the NaN is a signaling NaN, the invalid +| exception is raised. +*----------------------------------------------------------------------------*/ +void softfloat_f32UIToCommonNaN( uint_fast32_t uiA, struct commonNaN *zPtr ) +{ + + if ( softfloat_isSigNaNF32UI( uiA ) ) { + softfloat_raiseFlags( softfloat_flag_invalid ); + } + zPtr->sign = uiA>>31; + zPtr->v64 = (uint_fast64_t) uiA<<41; + zPtr->v0 = 0; + +} + /*---------------------------------------------------------------------------- | Assuming 'uiA' has the bit pattern of a 64-bit floating-point NaN, converts | this NaN to the common NaN form, and stores the resulting common NaN at the @@ -977,7 +1029,7 @@ float64_t *------------------------------------------------------------------------*/ if ( ! expA ) { if ( ! sigA ) goto zeroProd; - normExpSig = softfloat_normSubnormalF64Sig( sigA ); + expA = normExpSig.exp; sigA = normExpSig.sig; } @@ -1657,6 +1709,18 @@ void softfloat_mul64To128M( uint64_t a, uint64_t b, uint32_t *zPtr ) #endif +struct exp16_sig32 softfloat_normSubnormalF32Sig( uint_fast32_t sig ) +{ + int_fast8_t shiftDist; + struct exp16_sig32 z; + + shiftDist = softfloat_countLeadingZeros32( sig ) - 8; + z.exp = 1 - shiftDist; + z.sig = sig<>31)) +#define expF32UI( a ) ((int_fast16_t) ((a)>>23) & 0xFF) +#define fracF32UI( a ) ((a) & 0x007FFFFF) +#define packToF32UI( sign, exp, sig ) (((uint32_t) (sign)<<31) + ((uint32_t) (exp)<<23) + (sig)) + +#define isNaNF32UI( a ) (((~(a) & 0x7F800000) == 0) && ((a) & 0x007FFFFF)) + +struct exp16_sig32 { int_fast16_t exp; uint_fast32_t sig; }; +struct exp16_sig32 softfloat_normSubnormalF32Sig( uint_fast32_t ); +float32_t softfloat_roundPackToF32( bool, int_fast16_t, uint_fast32_t ); +float32_t softfloat_normRoundPackToF32( bool, int_fast16_t, uint_fast32_t ); + +/*----------------------------------------------------------------------------*/ /*----------------------------------------------------------------------------*/ #define signF64UI( a ) ((bool) ((uint64_t) (a)>>63)) #define expF64UI( a ) ((int_fast16_t) ((a)>>52) & 0x7FF) diff --git a/runtime/softfloat/primitives.h b/runtime/softfloat/primitives.h index 606de8777..a67539c5d 100644 --- a/runtime/softfloat/primitives.h +++ b/runtime/softfloat/primitives.h @@ -57,6 +57,27 @@ uint64_t softfloat_shortShiftRightJam64( uint64_t a, uint_fast8_t dist ); #endif #endif +#ifndef softfloat_shiftRightJam32 +/*---------------------------------------------------------------------------- +| Shifts 'a' right by the number of bits given in 'dist', which must not +| be zero. If any nonzero bits are shifted off, they are "jammed" into the +| least-significant bit of the shifted value by setting the least-significant +| bit to 1. This shifted-and-jammed value is returned. +| The value of 'dist' can be arbitrarily large. In particular, if 'dist' is +| greater than 32, the result will be either 0 or 1, depending on whether 'a' +| is zero or nonzero. +*----------------------------------------------------------------------------*/ +#if defined INLINE_LEVEL && (2 <= INLINE_LEVEL) +INLINE uint32_t softfloat_shiftRightJam32( uint32_t a, uint_fast16_t dist ) +{ + return + (dist < 31) ? a>>dist | ((uint32_t) (a<<(-dist & 31)) != 0) : (a != 0); +} +#else +uint32_t softfloat_shiftRightJam32( uint32_t a, uint_fast16_t dist ); +#endif +#endif + #ifndef softfloat_shiftRightJam64 /*---------------------------------------------------------------------------- | Shifts 'a' right by the number of bits given in 'dist', which must not diff --git a/runtime/softfloat/specialize.h b/runtime/softfloat/specialize.h index a3a3eb218..03e937382 100644 --- a/runtime/softfloat/specialize.h +++ b/runtime/softfloat/specialize.h @@ -82,6 +82,46 @@ struct commonNaN { #endif }; +/*---------------------------------------------------------------------------- +| The bit pattern for a default generated 32-bit floating-point NaN. +*----------------------------------------------------------------------------*/ +#define defaultNaNF32UI 0x7FC00000 + +/*---------------------------------------------------------------------------- +| Returns true when 32-bit unsigned integer 'uiA' has the bit pattern of a +| 32-bit floating-point signaling NaN. +| Note: This macro evaluates its argument more than once. +*----------------------------------------------------------------------------*/ +#define softfloat_isSigNaNF32UI( uiA ) ((((uiA) & 0x7FC00000) == 0x7F800000) && ((uiA) & 0x003FFFFF)) + +/*---------------------------------------------------------------------------- +| Assuming 'uiA' has the bit pattern of a 32-bit floating-point NaN, converts +| this NaN to the common NaN form, and stores the resulting common NaN at the +| location pointed to by 'zPtr'. If the NaN is a signaling NaN, the invalid +| exception is raised. +*----------------------------------------------------------------------------*/ +void softfloat_f32UIToCommonNaN( uint_fast32_t uiA, struct commonNaN *zPtr ); + +/*---------------------------------------------------------------------------- +| Converts the common NaN pointed to by 'aPtr' into a 32-bit floating-point +| NaN, and returns the bit pattern of this value as an unsigned integer. +*----------------------------------------------------------------------------*/ +uint_fast32_t softfloat_commonNaNToF32UI( const struct commonNaN *aPtr ); + +/*---------------------------------------------------------------------------- +| Interpreting 'uiA' and 'uiB' as the bit patterns of two 32-bit floating- +| point values, at least one of which is a NaN, returns the bit pattern of +| the combined NaN result. If either 'uiA' or 'uiB' has the pattern of a +| signaling NaN, the invalid exception is raised. +*----------------------------------------------------------------------------*/ +uint_fast32_t + softfloat_propagateNaNF32UI( uint_fast32_t uiA, uint_fast32_t uiB ); + +/*---------------------------------------------------------------------------- +| The bit pattern for a default generated 64-bit floating-point NaN. +*----------------------------------------------------------------------------*/ +#define defaultNaNF64UI UINT64_C( 0x7FF8000000000000 ) + /*---------------------------------------------------------------------------- | The bit pattern for a default generated 64-bit floating-point NaN. *----------------------------------------------------------------------------*/ diff --git a/tapset/floatingpoint.stp b/tapset/floatingpoint.stp index c7be79015..9e1084bb0 100644 --- a/tapset/floatingpoint.stp +++ b/tapset/floatingpoint.stp @@ -51,8 +51,7 @@ function string_to_fp:long (input:string) * * @input: a long integer * - * Description: Convert from a long to a softfloat floating point, then - * print the floating point value. + * Description: Convert from a long to a 64 bit softfloat floating point. */ function long_to_fp:long (input:long) %{ @@ -151,7 +150,7 @@ function fp_mul:long (mul1:long, mul2:long) %} /* - *function fp_div - fp divide + * sfunction fp_div - fp divide * * @div1: the 64 bit floating point dividend * @div2: 64 bit floating point divisor @@ -249,7 +248,7 @@ function fp_le:long (infp1:long, infp2:long) %} /** - * sfunction fp_le - fp comparison function less than + * sfunction fp_lt - fp comparison function less than * * @infp1: the 64 bit floating point input * @infp2: second 64 bit floating point input @@ -266,3 +265,21 @@ function fp_lt:long (infp1:long, infp2:long) STAP_RETVALUE = f64_lt(fp1, fp2); %} + +/** + * sfunction fp32_to_fp64 - Convert fp32 to 64 bit floating point + * + * @input: a long integer + * + * Description: Convert from 32 bit floating point to a 64 bit softfloat floating point. + */ +function fp32_to_fp64:long (input:long) +%{ + float64_t fp64; + float32_t fp32; + fp32.v = STAP_ARG_input; + + fp64 = f32_to_f64(fp32); + STAP_RETVALUE = fp64.v; +%} + diff --git a/testsuite/buildok/floatingpoint.stp b/testsuite/buildok/floatingpoint.stp index 56fb95961..30907f8ac 100755 --- a/testsuite/buildok/floatingpoint.stp +++ b/testsuite/buildok/floatingpoint.stp @@ -7,12 +7,20 @@ function printlnfp(a) { println(fp_to_string(a,5)) } probe process("stap").function("sdt_benchmark_thread") { fp = user_long($fpointer) printlnfp(fp) + fp32 = user_int($fpointer2) + printlnfp(fp32_to_fp64(fp32)) exit() } probe begin { a = 4614253070214989087 //3.14 b = 4622500287032611308 //11.21 + + a32 = 1078523331 //3.14 + b32 = 3219463864 //-1.79 + + printlnfp(fp32_to_fp64(a32)) + printlnfp(fp32_to_fp64(b32)) println(fp_to_string(a, 5)) // 3.14 printlnfp(string_to_fp("3.14"))