|
@@ -135,6 +135,46 @@ static void fpu_set_exception(CPUX86State *env, int mask)
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+void cpu_init_fp_statuses(CPUX86State *env)
|
|
|
+{
|
|
|
+ /*
|
|
|
+ * Initialise the non-runtime-varying fields of the various
|
|
|
+ * float_status words to x86 behaviour. This must be called at
|
|
|
+ * CPU reset because the float_status words are in the
|
|
|
+ * "zeroed on reset" portion of the CPU state struct.
|
|
|
+ * Fields in float_status that vary under guest control are set
|
|
|
+ * via the codepath for setting that register, eg cpu_set_fpuc().
|
|
|
+ */
|
|
|
+ /*
|
|
|
+ * Use x87 NaN propagation rules:
|
|
|
+ * SNaN + QNaN => return the QNaN
|
|
|
+ * two SNaNs => return the one with the larger significand, silenced
|
|
|
+ * two QNaNs => return the one with the larger significand
|
|
|
+ * SNaN and a non-NaN => return the SNaN, silenced
|
|
|
+ * QNaN and a non-NaN => return the QNaN
|
|
|
+ *
|
|
|
+ * If we get down to comparing significands and they are the same,
|
|
|
+ * return the NaN with the positive sign bit (if any).
|
|
|
+ */
|
|
|
+ set_float_2nan_prop_rule(float_2nan_prop_x87, &env->fp_status);
|
|
|
+ /*
|
|
|
+ * TODO: These are incorrect: the x86 Software Developer's Manual vol 1
|
|
|
+ * section 4.8.3.5 "Operating on SNaNs and QNaNs" says that the
|
|
|
+ * "larger significand" behaviour is only used for x87 FPU operations.
|
|
|
+ * For SSE the required behaviour is to always return the first NaN,
|
|
|
+ * which is float_2nan_prop_ab.
|
|
|
+ *
|
|
|
+ * mmx_status is used only for the AMD 3DNow! instructions, which
|
|
|
+ * are documented in the "3DNow! Technology Manual" as not supporting
|
|
|
+ * NaNs or infinities as inputs. The result of passing two NaNs is
|
|
|
+ * documented as "undefined", so we can do what we choose.
|
|
|
+ * (Strictly there is some behaviour we don't implement correctly
|
|
|
+ * for these "unsupported" NaN and Inf values, like "NaN * 0 == 0".)
|
|
|
+ */
|
|
|
+ set_float_2nan_prop_rule(float_2nan_prop_x87, &env->mmx_status);
|
|
|
+ set_float_2nan_prop_rule(float_2nan_prop_x87, &env->sse_status);
|
|
|
+}
|
|
|
+
|
|
|
static inline uint8_t save_exception_flags(CPUX86State *env)
|
|
|
{
|
|
|
uint8_t old_flags = get_float_exception_flags(&env->fp_status);
|