static inline uint32_t cp_float_is_nan( uint32_t a ) { uint32_t em = uint32_sll( a, 1 ); uint32_t is_nan_msb = uint32_sub( 0xff000000, em ); uint32_t is_nan_pred = uint32_srl( is_nan_msb, 31 ); return (is_nan_pred); }
BX_CONST_FUNC float ldexp(float _a, int32_t _b) { const uint32_t ftob = floatToBits(_a); const uint32_t masked = uint32_and(ftob, UINT32_C(0xff800000) ); const uint32_t expsign0 = uint32_sra(masked, 23); const uint32_t tmp = uint32_iadd(expsign0, _b); const uint32_t expsign1 = uint32_sll(tmp, 23); const uint32_t mantissa = uint32_and(ftob, UINT32_C(0x007fffff) ); const uint32_t bits = uint32_or(mantissa, expsign1); const float result = bitsToFloat(bits); return result; }
/*---------------------------------------------------------------------------- | Normalizes the subnormal single-precision floating-point value represented | by the denormalized significand `a_m'. The normalized exponent and | significand are stored at the locations pointed to by `z_ePtr' and | `z_mPtr', respectively. *----------------------------------------------------------------------------*/ // a_m > 0 static void normalizeFloat32Subnormal( uint32_t a_m, uint32_t* restrict const out_e, uint32_t* restrict const out_m) { uint32_t m_clz = __builtin_clz( a_m ); uint32_t m_sa = uint32_sub( m_clz, 8 ); uint32_t m_normalized = uint32_sll( a_m, m_sa ); uint32_t e_normalized = uint32_sub( 1, m_sa ); *out_m = m_normalized; *out_e = e_normalized; } /*---------------------------------------------------------------------------- | Packs the sign `z_s', exponent `z_e', and significand `z_m' into a | single-precision floating-point value, returning the result. After being | shifted into the proper positions, the three fields are simply added | together to form the result. This means that any integer portion of `z_m' | will be added into the exponent. Since a properly normalized significand | will have an integer portion equal to 1, the `z_e' input should be 1 less | than the desired result exponent whenever `z_m' is a complete, normalized