@@ -1675,6 +1675,7 @@ static void x86_cpu_reset(CPUState *s)
env->fptags[i] = 1;
}
env->fpuc = 0x37f;
+ update_fp_status(env);
env->mxcsr = 0x1f80;
@@ -1086,4 +1086,6 @@ uint32_t cpu_cc_compute_all(CPUX86State *env1, int op);
void cpu_report_tpr_access(CPUX86State *env, TPRAccess access);
+void update_fp_status(CPUState *env1);
+
#endif /* CPU_I386_H */
@@ -255,7 +255,7 @@ static int cpu_post_load(void *opaque, int version_id)
CPUX86State *env = opaque;
int i;
- /* XXX: restore FPU round state */
+ update_fp_status(env);
env->fpstt = (env->fpus_vmstate >> 11) & 7;
env->fpus = env->fpus_vmstate & ~0x3800;
env->fptag_vmstate ^= 0xff;
@@ -4018,12 +4018,12 @@ uint32_t helper_fnstcw(void)
return env->fpuc;
}
-static void update_fp_status(void)
+void update_fp_status(CPUState *env1)
{
int rnd_type;
/* set rounding mode */
- switch(env->fpuc & FPU_RC_MASK) {
+ switch (env1->fpuc & FPU_RC_MASK) {
default:
case FPU_RC_NEAR:
rnd_type = float_round_nearest_even;
@@ -4038,8 +4038,8 @@ static void update_fp_status(void)
rnd_type = float_round_to_zero;
break;
}
- set_float_rounding_mode(rnd_type, &env->fp_status);
- switch((env->fpuc >> 8) & 3) {
+ set_float_rounding_mode(rnd_type, &env1->fp_status);
+ switch ((env1->fpuc >> 8) & 3) {
case 0:
rnd_type = 32;
break;
@@ -4051,13 +4051,13 @@ static void update_fp_status(void)
rnd_type = 80;
break;
}
- set_floatx80_rounding_precision(rnd_type, &env->fp_status);
+ set_floatx80_rounding_precision(rnd_type, &env1->fp_status);
}
void helper_fldcw(uint32_t val)
{
env->fpuc = val;
- update_fp_status();
+ update_fp_status(env);
}
void helper_fclex(void)
@@ -4076,6 +4076,7 @@ void helper_fninit(void)
env->fpus = 0;
env->fpstt = 0;
env->fpuc = 0x37f;
+ update_fp_status(env);
env->fptags[0] = 1;
env->fptags[1] = 1;
env->fptags[2] = 1;
@@ -4494,6 +4495,7 @@ void helper_fldenv(target_ulong ptr, int data32)
fpus = lduw(ptr + 2);
fptag = lduw(ptr + 4);
}
+ update_fp_status(env);
env->fpstt = (fpus >> 11) & 7;
env->fpus = fpus & ~0x3800;
for(i = 0;i < 8; i++) {
@@ -4520,6 +4522,7 @@ void helper_fsave(target_ulong ptr, int data32)
env->fpus = 0;
env->fpstt = 0;
env->fpuc = 0x37f;
+ update_fp_status(env);
env->fptags[0] = 1;
env->fptags[1] = 1;
env->fptags[2] = 1;
@@ -4661,6 +4664,7 @@ void helper_fxrstor(target_ulong ptr, int data64)
}
env->fpuc = lduw(ptr);
+ update_fp_status(env);
fpus = lduw(ptr + 2);
fptag = lduw(ptr + 4);
env->fpstt = (fpus >> 11) & 7;
Restore FPU round state after loading the VM state. This patch fixes different behavior after loading VM state with different FPU flags set. Signed-off-by: Pavel Dovgalyuk<pavel.dovgaluk@gmail.com> --- target-i386/cpu.c | 1 + target-i386/cpu.h | 2 ++ target-i386/machine.c | 2 +- target-i386/op_helper.c | 16 ++++++++++------ 4 files changed, 14 insertions(+), 7 deletions(-)