@@ -333,8 +333,22 @@ typedef enum __attribute__((__packed__)) {
/*
* Are Pseudo-infinities (Inf with the Integer bit zero) valid?
* If so, floatx80_is_infinity() will return true for them.
+ * If not, floatx80_invalid_encoding will return false for them,
+ * and using them as inputs to a float op will raise Invalid.
*/
floatx80_pseudo_inf_valid = 2,
+ /*
+ * Are Pseudo-NaNs (NaNs where the Integer bit is zero) valid?
+ * If not, floatx80_invalid_encoding() will return false for them,
+ * and using them as inputs to a float op will raise Invalid.
+ */
+ floatx80_pseudo_nan_valid = 4,
+ /*
+ * Are Unnormals (0 < exp < 0x7fff, Integer bit zero) valid?
+ * If not, floatx80_invalid_encoding() will return false for them,
+ * and using them as inputs to a float op will raise Invalid.
+ */
+ floatx80_unnormal_valid = 8,
} FloatX80Behaviour;
/*
@@ -1073,41 +1073,45 @@ static inline bool floatx80_unordered_quiet(floatx80 a, floatx80 b,
/*----------------------------------------------------------------------------
| 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.
+| Invalid floatx80 encodings may arise when the integer bit is not set
+| correctly; this is target-specific. In Intel terminology the
+| categories are:
+| exp == 0, int = 0, mantissa == 0 : zeroes
+| exp == 0, int = 0, mantissa != 0 : denormals
+| exp == 0, int = 1 : pseudo-denormals
+| 0 < exp < 0x7fff, int = 0 : unnormals
+| 0 < exp < 0x7fff, int = 1 : normals
+| exp == 0x7fff, int = 0, mantissa == 0 : pseudo-infinities
+| exp == 0x7fff, int = 1, mantissa == 0 : infinities
+| exp == 0x7fff, int = 0, mantissa != 0 : pseudo-NaNs
+| exp == 0x7fff, int = 1, mantissa == 0 : NaNs
+|
+| The usual IEEE cases of zero, denormal, normal, inf and NaN are always valid.
+| x87 permits as input also pseudo-denormals.
+| m68k permits all those and also pseudo-infinities, pseudo-NaNs and unnormals.
+|
+| Since we don't have a target that handles floatx80 but prohibits
+| pseudo-denormals in input, we don't currently have a floatx80_behaviour
+| flag for that case, but instead always accept it. Conveniently this
+| means that all cases with either exponent 0 or the integer bit set are
+| valid for all targets.
*----------------------------------------------------------------------------*/
static inline bool floatx80_invalid_encoding(floatx80 a, float_status *s)
{
-#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
+ if ((a.low >> 63) || (a.high & 0x7fff) == 0) {
+ /* Anything with the Integer bit set or the exponent 0 is valid */
+ return false;
+ }
+
+ if ((a.high & 0x7fff) == 0x7fff) {
+ if (a.low) {
+ return !(s->floatx80_behaviour & floatx80_pseudo_nan_valid);
+ } else {
+ return !(s->floatx80_behaviour & floatx80_pseudo_inf_valid);
+ }
+ } else {
+ return !(s->floatx80_behaviour & floatx80_unnormal_valid);
+ }
}
#define floatx80_zero make_floatx80(0x0000, 0x0000000000000000LL)
@@ -111,9 +111,35 @@ static void m68k_cpu_reset_hold(Object *obj, ResetType type)
* m68k-specific floatx80 behaviour:
* * default Infinity values have a zero Integer bit
* * input Infinities may have the Integer bit either 0 or 1
+ * * pseudo-denormals supported for input and output
+ * * don't raise Invalid for pseudo-NaN/pseudo-Inf/Unnormal
+ *
+ * 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"
+ *
+ * Note though that QEMU's fp emulation does directly handle both
+ * denormal and unnormal values, and does not trap to guest software.
*/
set_floatx80_behaviour(floatx80_default_inf_int_bit_is_zero |
- floatx80_pseudo_inf_valid,
+ floatx80_pseudo_inf_valid |
+ floatx80_pseudo_nan_valid |
+ floatx80_unnormal_valid,
&env->fp_status);
nan = floatx80_default_nan(&env->fp_status);