@@ -75,6 +75,12 @@ static inline void set_floatx80_rounding_precision(FloatX80RoundPrec val,
status->floatx80_rounding_precision = val;
}
+static inline void set_floatx80_behaviour(FloatX80Behaviour b,
+ float_status *status)
+{
+ status->floatx80_behaviour = b;
+}
+
static inline void set_float_2nan_prop_rule(Float2NaNPropRule rule,
float_status *status)
{
@@ -151,6 +157,12 @@ get_floatx80_rounding_precision(const float_status *status)
return status->floatx80_rounding_precision;
}
+static inline FloatX80Behaviour
+get_floatx80_behaviour(const float_status *status)
+{
+ return status->floatx80_behaviour;
+}
+
static inline Float2NaNPropRule
get_float_2nan_prop_rule(const float_status *status)
{
@@ -320,6 +320,18 @@ typedef enum __attribute__((__packed__)) {
float_ftz_before_rounding = 1,
} FloatFTZDetection;
+/*
+ * floatx80 is primarily used by x86 and m68k, and there are
+ * differences in the handling, largely related to the explicit
+ * Integer bit which floatx80 has and the other float formats do not.
+ * These flag values allow specification of the target's requirements
+ * and can be ORed together to set floatx80_behaviour.
+ */
+typedef enum __attribute__((__packed__)) {
+ /* In the default Infinity value, is the Integer bit 0 ? */
+ floatx80_default_inf_int_bit_is_zero = 1,
+} FloatX80Behaviour;
+
/*
* Floating Point Status. Individual architectures may maintain
* several versions of float_status for different functions. The
@@ -331,6 +343,7 @@ typedef struct float_status {
uint16_t float_exception_flags;
FloatRoundMode float_rounding_mode;
FloatX80RoundPrec floatx80_rounding_precision;
+ FloatX80Behaviour floatx80_behaviour;
Float2NaNPropRule float_2nan_prop_rule;
Float3NaNPropRule float_3nan_prop_rule;
FloatInfZeroNaNRule float_infzeronan_rule;
@@ -961,6 +961,7 @@ float128 floatx80_to_float128(floatx80, float_status *status);
| The pattern for an extended double-precision inf.
*----------------------------------------------------------------------------*/
extern const floatx80 floatx80_infinity;
+floatx80 floatx80_default_inf(bool zSign, float_status *status);
/*----------------------------------------------------------------------------
| Software IEC/IEEE extended double-precision operations.
@@ -1860,7 +1860,8 @@ static floatx80 floatx80_round_pack_canonical(FloatParts128 *p,
case float_class_inf:
/* x86 and m68k differ in the setting of the integer bit. */
- frac = floatx80_infinity_low;
+ frac = s->floatx80_behaviour & floatx80_default_inf_int_bit_is_zero ?
+ 0 : (1ULL << 63);
exp = fmt->exp_max;
break;
@@ -5144,9 +5145,7 @@ floatx80 roundAndPackFloatx80(FloatX80RoundPrec roundingPrecision, bool zSign,
) {
return packFloatx80( zSign, 0x7FFE, ~ roundMask );
}
- return packFloatx80(zSign,
- floatx80_infinity_high,
- floatx80_infinity_low);
+ return floatx80_default_inf(zSign, status);
}
if ( zExp <= 0 ) {
isTiny = status->tininess_before_rounding
@@ -107,6 +107,12 @@ static void m68k_cpu_reset_hold(Object *obj, ResetType type)
set_float_2nan_prop_rule(float_2nan_prop_ab, &env->fp_status);
/* Default NaN: sign bit clear, all frac bits set */
set_float_default_nan_pattern(0b01111111, &env->fp_status);
+ /*
+ * m68k-specific floatx80 behaviour:
+ * * default Infinity values have a zero Integer bit
+ */
+ set_floatx80_behaviour(floatx80_default_inf_int_bit_is_zero,
+ &env->fp_status);
nan = floatx80_default_nan(&env->fp_status);
for (i = 0; i < 8; i++) {
@@ -227,6 +227,16 @@ floatx80 floatx80_default_nan(float_status *status)
| The pattern for a default generated extended double-precision inf.
*----------------------------------------------------------------------------*/
+floatx80 floatx80_default_inf(bool zSign, float_status *status)
+{
+ /*
+ * Whether the Integer bit is set in the default Infinity is
+ * target dependent.
+ */
+ bool z = status->floatx80_behaviour & floatx80_default_inf_int_bit_is_zero;
+ return packFloatx80(zSign, 0x7fff, z ? 0 : (1ULL << 63));
+}
+
#define floatx80_infinity_high 0x7FFF
#if defined(TARGET_M68K)
#define floatx80_infinity_low UINT64_C(0x0000000000000000)