Skip to content

Commit

Permalink
fpu: Backported helpers for fyl2x and fyl2xp1 from qemu 6.1.0
Browse files Browse the repository at this point in the history
  • Loading branch information
dnivra committed Apr 12, 2022
1 parent 1e7dd2e commit adbfd03
Show file tree
Hide file tree
Showing 4 changed files with 547 additions and 66 deletions.
35 changes: 33 additions & 2 deletions fpu/softfloat-specialize.h
Original file line number Diff line number Diff line change
Expand Up @@ -145,9 +145,25 @@ const float64 float64_default_nan = const_float64(LIT64( 0xFFF8000000000000 ));
#define floatx80_default_nan_low LIT64( 0xC000000000000000 )
#endif

const floatx80 floatx80_default_nan
= make_floatx80_init(floatx80_default_nan_high, floatx80_default_nan_low);
floatx80 floatx80_default_nan(float_status *status)
{
floatx80 r;

/* None of the targets that have snan_bit_is_one use floatx80. */
#if SNAN_BIT_IS_ONE
# error SNAN_BIT_IS_ONE should not be set
#endif

#if defined(TARGET_M68K)
r.low = UINT64_C(0xFFFFFFFFFFFFFFFF);
r.high = 0x7FFF;
#else
/* X86 */
r.low = UINT64_C(0xC000000000000000);
r.high = 0xFFFF;
#endif
return r;
}
/*----------------------------------------------------------------------------
| The pattern for a default generated quadruple-precision NaN. The `high' and
| `low' values hold the most- and least-significant bits, respectively.
Expand Down Expand Up @@ -985,6 +1001,21 @@ floatx80 floatx80_maybe_silence_nan( floatx80 a )
return a;
}

/*----------------------------------------------------------------------------
| Returns a quiet NaN from a signalling NaN for the extended double-precision
| floating point value `a'.
*----------------------------------------------------------------------------*/

floatx80 floatx80_silence_nan(floatx80 a)
{
/* None of the targets that have snan_bit_is_one use floatx80. */
#if SNAN_BIT_IS_ONE
# error SNAN_BIT_IS_ONE should not be set
#endif
a.low |= UINT64_C(0xC000000000000000);
return a;
}

/*----------------------------------------------------------------------------
| Returns the result of converting the extended double-precision floating-
| point NaN `a' to the canonical NaN format. If `a' is a signaling NaN, the
Expand Down
46 changes: 5 additions & 41 deletions fpu/softfloat.c
Original file line number Diff line number Diff line change
Expand Up @@ -685,50 +685,14 @@ static float64

}

/*----------------------------------------------------------------------------
| Returns the fraction bits of the extended double-precision floating-point
| value `a'.
*----------------------------------------------------------------------------*/

static inline uint64_t extractFloatx80Frac( floatx80 a )
{

return a.low;

}

/*----------------------------------------------------------------------------
| Returns the exponent bits of the extended double-precision floating-point
| value `a'.
*----------------------------------------------------------------------------*/

static inline int32 extractFloatx80Exp( floatx80 a )
{

return a.high & 0x7FFF;

}

/*----------------------------------------------------------------------------
| Returns the sign bit of the extended double-precision floating-point value
| `a'.
*----------------------------------------------------------------------------*/

static inline flag extractFloatx80Sign( floatx80 a )
{

return a.high>>15;

}

/*----------------------------------------------------------------------------
| Normalizes the subnormal extended double-precision floating-point value
| represented by the denormalized significand `aSig'. The normalized exponent
| and significand are stored at the locations pointed to by `zExpPtr' and
| `zSigPtr', respectively.
*----------------------------------------------------------------------------*/

static void
void
normalizeFloatx80Subnormal( uint64_t aSig, int32 *zExpPtr, uint64_t *zSigPtr )
{
int8 shiftCount;
Expand Down Expand Up @@ -974,10 +938,10 @@ static floatx80 roundAndPackFloatx80(int8 roundingPrecision, flag zSign,
| normalized.
*----------------------------------------------------------------------------*/

static floatx80 normalizeRoundAndPackFloatx80(int8 roundingPrecision,
flag zSign, int32 zExp,
uint64_t zSig0, uint64_t zSig1,
float_status *status)
floatx80 normalizeRoundAndPackFloatx80(int8 roundingPrecision,
flag zSign, int32 zExp,
uint64_t zSig0, uint64_t zSig1,
float_status *status)
{
int8 shiftCount;

Expand Down
124 changes: 119 additions & 5 deletions include/fpu/softfloat.h
Original file line number Diff line number Diff line change
Expand Up @@ -111,12 +111,12 @@ typedef int64_t int64;
/*----------------------------------------------------------------------------
| Software IEC/IEEE floating-point ordering relations
*----------------------------------------------------------------------------*/
enum {
typedef enum {
float_relation_less = -1,
float_relation_equal = 0,
float_relation_greater = 1,
float_relation_unordered = 2
};
} FloatRelation;

/*----------------------------------------------------------------------------
| Software IEC/IEEE floating-point types.
Expand Down Expand Up @@ -187,13 +187,18 @@ enum {
/*----------------------------------------------------------------------------
| Software IEC/IEEE floating-point rounding mode.
*----------------------------------------------------------------------------*/
enum {

typedef enum __attribute__((__packed__)) {
float_round_nearest_even = 0,
float_round_down = 1,
float_round_up = 2,
float_round_to_zero = 3,
float_round_ties_away = 4,
};
/* Not an IEEE rounding mode: round to closest odd, overflow to max */
float_round_to_odd = 5,
/* Not an IEEE rounding mode: round to closest odd, overflow to inf */
float_round_to_odd_inf = 6,
} FloatRoundMode;

/*----------------------------------------------------------------------------
| Software IEC/IEEE floating-point exception flags.
Expand All @@ -208,6 +213,15 @@ enum {
float_flag_output_denormal = 128
};

/*
* Rounding precision for floatx80.
*/
typedef enum __attribute__((__packed__)) {
floatx80_precision_x,
floatx80_precision_d,
floatx80_precision_s,
} FloatX80RoundPrec;

typedef struct float_status {
signed char float_detect_tininess;
signed char float_rounding_mode;
Expand Down Expand Up @@ -628,6 +642,7 @@ int floatx80_is_quiet_nan( floatx80 );
int floatx80_is_signaling_nan( floatx80 );
floatx80 floatx80_maybe_silence_nan( floatx80 );
floatx80 floatx80_scalbn(floatx80, int, float_status *status);
floatx80 floatx80_silence_nan( floatx80 );

static inline floatx80 floatx80_abs(floatx80 a)
{
Expand Down Expand Up @@ -666,17 +681,116 @@ static inline int floatx80_is_any_nan(floatx80 a)
return ((a.high & 0x7fff) == 0x7fff) && (a.low<<1);
}

/*----------------------------------------------------------------------------
| Return whether the given value is an invalid floatx80 encoding.
| Invalid floatx80 encodings arise when the integer bit is not set, but
| the exponent is not zero. The only times the integer bit is permitted to
| be zero is in subnormal numbers and the value zero.
| This includes what the Intel software developer's manual calls pseudo-NaNs,
| pseudo-infinities and un-normal numbers. It does not include
| pseudo-denormals, which must still be correctly handled as inputs even
| if they are never generated as outputs.
*----------------------------------------------------------------------------*/
static inline bool floatx80_invalid_encoding(floatx80 a)
{
#if defined(TARGET_M68K)
/*-------------------------------------------------------------------------
| With m68k, the explicit integer bit can be zero in the case of:
| - zeros (exp == 0, mantissa == 0)
| - denormalized numbers (exp == 0, mantissa != 0)
| - unnormalized numbers (exp != 0, exp < 0x7FFF)
| - infinities (exp == 0x7FFF, mantissa == 0)
| - not-a-numbers (exp == 0x7FFF, mantissa != 0)
|
| For infinities and NaNs, the explicit integer bit can be either one or
| zero.
|
| The IEEE 754 standard does not define a zero integer bit. Such a number
| is an unnormalized number. Hardware does not directly support
| denormalized and unnormalized numbers, but implicitly supports them by
| trapping them as unimplemented data types, allowing efficient conversion
| in software.
|
| See "M68000 FAMILY PROGRAMMER’S REFERENCE MANUAL",
| "1.6 FLOATING-POINT DATA TYPES"
*------------------------------------------------------------------------*/
return false;
#else
return (a.low & (1ULL << 63)) == 0 && (a.high & 0x7FFF) != 0;
#endif
}

#define floatx80_zero make_floatx80(0x0000, 0x0000000000000000LL)
#define floatx80_one make_floatx80(0x3fff, 0x8000000000000000LL)
#define floatx80_ln2 make_floatx80(0x3ffe, 0xb17217f7d1cf79acLL)
#define floatx80_pi make_floatx80(0x4000, 0xc90fdaa22168c235LL)
#define floatx80_half make_floatx80(0x3ffe, 0x8000000000000000LL)
#define floatx80_infinity make_floatx80(0x7fff, 0x8000000000000000LL)

/*----------------------------------------------------------------------------
| Returns the fraction bits of the extended double-precision floating-point
| value `a'.
*----------------------------------------------------------------------------*/

inline uint64_t extractFloatx80Frac( floatx80 a )
{

return a.low;

}

/*----------------------------------------------------------------------------
| Returns the exponent bits of the extended double-precision floating-point
| value `a'.
*----------------------------------------------------------------------------*/

inline int32 extractFloatx80Exp( floatx80 a )
{

return a.high & 0x7FFF;

}

/*----------------------------------------------------------------------------
| Returns the sign bit of the extended double-precision floating-point value
| `a'.
*----------------------------------------------------------------------------*/

inline flag extractFloatx80Sign( floatx80 a )
{

return a.high>>15;

}

/*----------------------------------------------------------------------------
| Takes an abstract floating-point value having sign `zSign', exponent
| `zExp', and significand formed by the concatenation of `zSig0' and `zSig1',
| and returns the proper extended double-precision floating-point value
| corresponding to the abstract input. This routine is just like
| `roundAndPackFloatx80' except that the input significand does not have to be
| normalized.
*----------------------------------------------------------------------------*/

floatx80 normalizeRoundAndPackFloatx80(int8 roundingPrecision,
flag zSign, int32 zExp,
uint64_t zSig0, uint64_t zSig1,
float_status *status);

/*----------------------------------------------------------------------------
| Normalizes the subnormal extended double-precision floating-point value
| represented by the denormalized significand `aSig'. The normalized exponent
| and significand are stored at the locations pointed to by `zExpPtr' and
| `zSigPtr', respectively.
*----------------------------------------------------------------------------*/

void normalizeFloatx80Subnormal(uint64_t aSig, int32_t *zExpPtr,
uint64_t *zSigPtr);

/*----------------------------------------------------------------------------
| The pattern for a default generated extended double-precision NaN.
*----------------------------------------------------------------------------*/
extern const floatx80 floatx80_default_nan;
floatx80 floatx80_default_nan(float_status *status);

/*----------------------------------------------------------------------------
| Software IEC/IEEE quadruple-precision conversion routines.
Expand Down
Loading

0 comments on commit adbfd03

Please sign in to comment.