From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from eggs.gnu.org ([208.118.235.92]:52933) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ShI5Y-0001Bd-AN for qemu-devel@nongnu.org; Wed, 20 Jun 2012 06:24:46 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1ShI5T-0007do-Fw for qemu-devel@nongnu.org; Wed, 20 Jun 2012 06:24:39 -0400 Received: from mail.ispras.ru ([83.149.199.43]:36334) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ShI5T-0007Xf-4T for qemu-devel@nongnu.org; Wed, 20 Jun 2012 06:24:35 -0400 Received: from PASHAISP (unknown [80.250.189.177]) by mail.ispras.ru (Postfix) with ESMTP id A184A24FE7E for ; Wed, 20 Jun 2012 14:24:22 +0400 (MSK) From: "Pavel Dovgaluk" Date: Wed, 20 Jun 2012 14:24:22 +0400 Message-ID: <001b01cd4ece$dc1a19e0$944e4da0$@Dovgaluk@ispras.ru> MIME-Version: 1.0 Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit Content-Language: ru Subject: [Qemu-devel] [PATCH] Restore FPU round state after loading the VM state List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , To: 'qemu-devel' 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 --- 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(-) diff --git a/target-i386/cpu.c b/target-i386/cpu.c index fdd95be..68d10ba 100644 --- a/target-i386/cpu.c +++ b/target-i386/cpu.c @@ -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; diff --git a/target-i386/cpu.h b/target-i386/cpu.h index bcf663e..6500cc8 100644 --- a/target-i386/cpu.h +++ b/target-i386/cpu.h @@ -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 */ diff --git a/target-i386/machine.c b/target-i386/machine.c index a8be058..e79d98d 100644 --- a/target-i386/machine.c +++ b/target-i386/machine.c @@ -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; diff --git a/target-i386/op_helper.c b/target-i386/op_helper.c index bc3b94e..552f089 100644 --- a/target-i386/op_helper.c +++ b/target-i386/op_helper.c @@ -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;