Skip to content

Commit 54c97c0

Browse files
committed
fpu: Backported helpers for fyl2x and fyl2xp1 from qemu 6.1.0
1 parent df29d24 commit 54c97c0

File tree

4 files changed

+547
-66
lines changed

4 files changed

+547
-66
lines changed

fpu/softfloat-specialize.h

Lines changed: 33 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -145,9 +145,25 @@ const float64 float64_default_nan = const_float64(LIT64( 0xFFF8000000000000 ));
145145
#define floatx80_default_nan_low LIT64( 0xC000000000000000 )
146146
#endif
147147

148-
const floatx80 floatx80_default_nan
149-
= make_floatx80_init(floatx80_default_nan_high, floatx80_default_nan_low);
148+
floatx80 floatx80_default_nan(float_status *status)
149+
{
150+
floatx80 r;
151+
152+
/* None of the targets that have snan_bit_is_one use floatx80. */
153+
#if SNAN_BIT_IS_ONE
154+
# error SNAN_BIT_IS_ONE should not be set
155+
#endif
150156

157+
#if defined(TARGET_M68K)
158+
r.low = UINT64_C(0xFFFFFFFFFFFFFFFF);
159+
r.high = 0x7FFF;
160+
#else
161+
/* X86 */
162+
r.low = UINT64_C(0xC000000000000000);
163+
r.high = 0xFFFF;
164+
#endif
165+
return r;
166+
}
151167
/*----------------------------------------------------------------------------
152168
| The pattern for a default generated quadruple-precision NaN. The `high' and
153169
| `low' values hold the most- and least-significant bits, respectively.
@@ -985,6 +1001,21 @@ floatx80 floatx80_maybe_silence_nan( floatx80 a )
9851001
return a;
9861002
}
9871003

1004+
/*----------------------------------------------------------------------------
1005+
| Returns a quiet NaN from a signalling NaN for the extended double-precision
1006+
| floating point value `a'.
1007+
*----------------------------------------------------------------------------*/
1008+
1009+
floatx80 floatx80_silence_nan(floatx80 a)
1010+
{
1011+
/* None of the targets that have snan_bit_is_one use floatx80. */
1012+
#if SNAN_BIT_IS_ONE
1013+
# error SNAN_BIT_IS_ONE should not be set
1014+
#endif
1015+
a.low |= UINT64_C(0xC000000000000000);
1016+
return a;
1017+
}
1018+
9881019
/*----------------------------------------------------------------------------
9891020
| Returns the result of converting the extended double-precision floating-
9901021
| point NaN `a' to the canonical NaN format. If `a' is a signaling NaN, the

fpu/softfloat.c

Lines changed: 5 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -685,50 +685,14 @@ static float64
685685

686686
}
687687

688-
/*----------------------------------------------------------------------------
689-
| Returns the fraction bits of the extended double-precision floating-point
690-
| value `a'.
691-
*----------------------------------------------------------------------------*/
692-
693-
static inline uint64_t extractFloatx80Frac( floatx80 a )
694-
{
695-
696-
return a.low;
697-
698-
}
699-
700-
/*----------------------------------------------------------------------------
701-
| Returns the exponent bits of the extended double-precision floating-point
702-
| value `a'.
703-
*----------------------------------------------------------------------------*/
704-
705-
static inline int32 extractFloatx80Exp( floatx80 a )
706-
{
707-
708-
return a.high & 0x7FFF;
709-
710-
}
711-
712-
/*----------------------------------------------------------------------------
713-
| Returns the sign bit of the extended double-precision floating-point value
714-
| `a'.
715-
*----------------------------------------------------------------------------*/
716-
717-
static inline flag extractFloatx80Sign( floatx80 a )
718-
{
719-
720-
return a.high>>15;
721-
722-
}
723-
724688
/*----------------------------------------------------------------------------
725689
| Normalizes the subnormal extended double-precision floating-point value
726690
| represented by the denormalized significand `aSig'. The normalized exponent
727691
| and significand are stored at the locations pointed to by `zExpPtr' and
728692
| `zSigPtr', respectively.
729693
*----------------------------------------------------------------------------*/
730694

731-
static void
695+
void
732696
normalizeFloatx80Subnormal( uint64_t aSig, int32 *zExpPtr, uint64_t *zSigPtr )
733697
{
734698
int8 shiftCount;
@@ -974,10 +938,10 @@ static floatx80 roundAndPackFloatx80(int8 roundingPrecision, flag zSign,
974938
| normalized.
975939
*----------------------------------------------------------------------------*/
976940

977-
static floatx80 normalizeRoundAndPackFloatx80(int8 roundingPrecision,
978-
flag zSign, int32 zExp,
979-
uint64_t zSig0, uint64_t zSig1,
980-
float_status *status)
941+
floatx80 normalizeRoundAndPackFloatx80(int8 roundingPrecision,
942+
flag zSign, int32 zExp,
943+
uint64_t zSig0, uint64_t zSig1,
944+
float_status *status)
981945
{
982946
int8 shiftCount;
983947

include/fpu/softfloat.h

Lines changed: 119 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -111,12 +111,12 @@ typedef int64_t int64;
111111
/*----------------------------------------------------------------------------
112112
| Software IEC/IEEE floating-point ordering relations
113113
*----------------------------------------------------------------------------*/
114-
enum {
114+
typedef enum {
115115
float_relation_less = -1,
116116
float_relation_equal = 0,
117117
float_relation_greater = 1,
118118
float_relation_unordered = 2
119-
};
119+
} FloatRelation;
120120

121121
/*----------------------------------------------------------------------------
122122
| Software IEC/IEEE floating-point types.
@@ -187,13 +187,18 @@ enum {
187187
/*----------------------------------------------------------------------------
188188
| Software IEC/IEEE floating-point rounding mode.
189189
*----------------------------------------------------------------------------*/
190-
enum {
190+
191+
typedef enum __attribute__((__packed__)) {
191192
float_round_nearest_even = 0,
192193
float_round_down = 1,
193194
float_round_up = 2,
194195
float_round_to_zero = 3,
195196
float_round_ties_away = 4,
196-
};
197+
/* Not an IEEE rounding mode: round to closest odd, overflow to max */
198+
float_round_to_odd = 5,
199+
/* Not an IEEE rounding mode: round to closest odd, overflow to inf */
200+
float_round_to_odd_inf = 6,
201+
} FloatRoundMode;
197202

198203
/*----------------------------------------------------------------------------
199204
| Software IEC/IEEE floating-point exception flags.
@@ -208,6 +213,15 @@ enum {
208213
float_flag_output_denormal = 128
209214
};
210215

216+
/*
217+
* Rounding precision for floatx80.
218+
*/
219+
typedef enum __attribute__((__packed__)) {
220+
floatx80_precision_x,
221+
floatx80_precision_d,
222+
floatx80_precision_s,
223+
} FloatX80RoundPrec;
224+
211225
typedef struct float_status {
212226
signed char float_detect_tininess;
213227
signed char float_rounding_mode;
@@ -628,6 +642,7 @@ int floatx80_is_quiet_nan( floatx80 );
628642
int floatx80_is_signaling_nan( floatx80 );
629643
floatx80 floatx80_maybe_silence_nan( floatx80 );
630644
floatx80 floatx80_scalbn(floatx80, int, float_status *status);
645+
floatx80 floatx80_silence_nan( floatx80 );
631646

632647
static inline floatx80 floatx80_abs(floatx80 a)
633648
{
@@ -666,17 +681,116 @@ static inline int floatx80_is_any_nan(floatx80 a)
666681
return ((a.high & 0x7fff) == 0x7fff) && (a.low<<1);
667682
}
668683

684+
/*----------------------------------------------------------------------------
685+
| Return whether the given value is an invalid floatx80 encoding.
686+
| Invalid floatx80 encodings arise when the integer bit is not set, but
687+
| the exponent is not zero. The only times the integer bit is permitted to
688+
| be zero is in subnormal numbers and the value zero.
689+
| This includes what the Intel software developer's manual calls pseudo-NaNs,
690+
| pseudo-infinities and un-normal numbers. It does not include
691+
| pseudo-denormals, which must still be correctly handled as inputs even
692+
| if they are never generated as outputs.
693+
*----------------------------------------------------------------------------*/
694+
static inline bool floatx80_invalid_encoding(floatx80 a)
695+
{
696+
#if defined(TARGET_M68K)
697+
/*-------------------------------------------------------------------------
698+
| With m68k, the explicit integer bit can be zero in the case of:
699+
| - zeros (exp == 0, mantissa == 0)
700+
| - denormalized numbers (exp == 0, mantissa != 0)
701+
| - unnormalized numbers (exp != 0, exp < 0x7FFF)
702+
| - infinities (exp == 0x7FFF, mantissa == 0)
703+
| - not-a-numbers (exp == 0x7FFF, mantissa != 0)
704+
|
705+
| For infinities and NaNs, the explicit integer bit can be either one or
706+
| zero.
707+
|
708+
| The IEEE 754 standard does not define a zero integer bit. Such a number
709+
| is an unnormalized number. Hardware does not directly support
710+
| denormalized and unnormalized numbers, but implicitly supports them by
711+
| trapping them as unimplemented data types, allowing efficient conversion
712+
| in software.
713+
|
714+
| See "M68000 FAMILY PROGRAMMER’S REFERENCE MANUAL",
715+
| "1.6 FLOATING-POINT DATA TYPES"
716+
*------------------------------------------------------------------------*/
717+
return false;
718+
#else
719+
return (a.low & (1ULL << 63)) == 0 && (a.high & 0x7FFF) != 0;
720+
#endif
721+
}
722+
669723
#define floatx80_zero make_floatx80(0x0000, 0x0000000000000000LL)
670724
#define floatx80_one make_floatx80(0x3fff, 0x8000000000000000LL)
671725
#define floatx80_ln2 make_floatx80(0x3ffe, 0xb17217f7d1cf79acLL)
672726
#define floatx80_pi make_floatx80(0x4000, 0xc90fdaa22168c235LL)
673727
#define floatx80_half make_floatx80(0x3ffe, 0x8000000000000000LL)
674728
#define floatx80_infinity make_floatx80(0x7fff, 0x8000000000000000LL)
675729

730+
/*----------------------------------------------------------------------------
731+
| Returns the fraction bits of the extended double-precision floating-point
732+
| value `a'.
733+
*----------------------------------------------------------------------------*/
734+
735+
inline uint64_t extractFloatx80Frac( floatx80 a )
736+
{
737+
738+
return a.low;
739+
740+
}
741+
742+
/*----------------------------------------------------------------------------
743+
| Returns the exponent bits of the extended double-precision floating-point
744+
| value `a'.
745+
*----------------------------------------------------------------------------*/
746+
747+
inline int32 extractFloatx80Exp( floatx80 a )
748+
{
749+
750+
return a.high & 0x7FFF;
751+
752+
}
753+
754+
/*----------------------------------------------------------------------------
755+
| Returns the sign bit of the extended double-precision floating-point value
756+
| `a'.
757+
*----------------------------------------------------------------------------*/
758+
759+
inline flag extractFloatx80Sign( floatx80 a )
760+
{
761+
762+
return a.high>>15;
763+
764+
}
765+
766+
/*----------------------------------------------------------------------------
767+
| Takes an abstract floating-point value having sign `zSign', exponent
768+
| `zExp', and significand formed by the concatenation of `zSig0' and `zSig1',
769+
| and returns the proper extended double-precision floating-point value
770+
| corresponding to the abstract input. This routine is just like
771+
| `roundAndPackFloatx80' except that the input significand does not have to be
772+
| normalized.
773+
*----------------------------------------------------------------------------*/
774+
775+
floatx80 normalizeRoundAndPackFloatx80(int8 roundingPrecision,
776+
flag zSign, int32 zExp,
777+
uint64_t zSig0, uint64_t zSig1,
778+
float_status *status);
779+
780+
/*----------------------------------------------------------------------------
781+
| Normalizes the subnormal extended double-precision floating-point value
782+
| represented by the denormalized significand `aSig'. The normalized exponent
783+
| and significand are stored at the locations pointed to by `zExpPtr' and
784+
| `zSigPtr', respectively.
785+
*----------------------------------------------------------------------------*/
786+
787+
void normalizeFloatx80Subnormal(uint64_t aSig, int32_t *zExpPtr,
788+
uint64_t *zSigPtr);
789+
676790
/*----------------------------------------------------------------------------
677791
| The pattern for a default generated extended double-precision NaN.
678792
*----------------------------------------------------------------------------*/
679-
extern const floatx80 floatx80_default_nan;
793+
floatx80 floatx80_default_nan(float_status *status);
680794

681795
/*----------------------------------------------------------------------------
682796
| Software IEC/IEEE quadruple-precision conversion routines.

0 commit comments

Comments
 (0)