From f182f11a8e2e5253ea602c3192e0124622c66899 Mon Sep 17 00:00:00 2001 From: Stanislav Shwartsman Date: Mon, 5 May 2008 21:23:33 +0000 Subject: [PATCH] - significantly improve FPU debug print - update FPU TW before saving FPU state by FNSAVE or FNSTENV --- bochs/fpu/control_w.h | 6 ++++- bochs/fpu/fpu.cc | 62 ++++++++++++++++++++++++++++++++++--------- 2 files changed, 55 insertions(+), 13 deletions(-) diff --git a/bochs/fpu/control_w.h b/bochs/fpu/control_w.h index 62ad0ccd3..8c52b7df3 100644 --- a/bochs/fpu/control_w.h +++ b/bochs/fpu/control_w.h @@ -1,5 +1,5 @@ ///////////////////////////////////////////////////////////////////////// -// $Id: control_w.h,v 1.8 2007-03-23 21:27:12 sshwarts Exp $ +// $Id: control_w.h,v 1.9 2008-05-05 21:23:33 sshwarts Exp $ ///////////////////////////////////////////////////////////////////////// // // Copyright (c) 2004 Stanislav Shwartsman @@ -27,6 +27,10 @@ /* Control Word */ /* ************ */ +#define FPU_CW_Reserved_Bits (0xe0c0) /* reserved bits */ + +#define FPU_CW_Inf (0x1000) /* infinity control, legacy */ + #define FPU_CW_RC (0x0C00) /* rounding control */ #define FPU_CW_PC (0x0300) /* precision control */ diff --git a/bochs/fpu/fpu.cc b/bochs/fpu/fpu.cc index d7cc99225..a780de9c0 100644 --- a/bochs/fpu/fpu.cc +++ b/bochs/fpu/fpu.cc @@ -1,5 +1,5 @@ ///////////////////////////////////////////////////////////////////////// -// $Id: fpu.cc,v 1.39 2008-04-30 20:41:15 sshwarts Exp $ +// $Id: fpu.cc,v 1.40 2008-05-05 21:23:33 sshwarts Exp $ ///////////////////////////////////////////////////////////////////////// // // Copyright (c) 2003 Stanislav Shwartsman @@ -84,6 +84,15 @@ void BX_CPU_C::FPU_check_pending_exceptions(void) int BX_CPU_C::fpu_save_environment(bxInstruction_c *i) { + /* read all registers in stack order and update x87 tag word */ + for(int n=0;n<8;n++) { + // update tag only if it is not empty + if (! IS_TAG_EMPTY(n)) { + int tag = FPU_tagof(BX_READ_FPU_REG(n)); + BX_CPU_THIS_PTR the_i387.FPU_settagi(tag, n); + } + } + BX_CPU_CALL_METHODR(i->ResolveModrm, (i)); if (protected_mode()) /* Protected Mode */ @@ -296,8 +305,9 @@ int BX_CPU_C::fpu_load_environment(bxInstruction_c *i) } } - /* always set bit 6 - reserved */ - BX_CPU_THIS_PTR the_i387.cwd |= 0x0040; + /* always set bit 6 as '1 */ + BX_CPU_THIS_PTR the_i387.cwd = + (BX_CPU_THIS_PTR the_i387.cwd & ~FPU_CW_Reserved_Bits) | 0x0040; /* check for unmasked exceptions */ if (FPU_PARTIAL_STATUS & ~FPU_CONTROL_WORD & FPU_CW_Exceptions_Mask) @@ -323,7 +333,7 @@ void BX_CPP_AttrRegparmN(1) BX_CPU_C::FLDCW(bxInstruction_c *i) BX_CPU_CALL_METHODR(i->ResolveModrm, (i)); Bit16u cwd = read_virtual_word(i->seg(), RMAddr(i)); - FPU_CONTROL_WORD = cwd | 0x0040; // bit 6 is reserved - always set + FPU_CONTROL_WORD = (cwd & ~FPU_CW_Reserved_Bits) | 0x0040; // bit 6 is reserved as '1 /* check for unmasked exceptions */ if (FPU_PARTIAL_STATUS & ~FPU_CONTROL_WORD & FPU_CW_Exceptions_Mask) @@ -461,12 +471,10 @@ void BX_CPP_AttrRegparmN(1) BX_CPU_C::FLDENV(bxInstruction_c *i) BX_CPU_THIS_PTR prepareFPU(i, CHECK_PENDING_EXCEPTIONS, !UPDATE_LAST_OPCODE); fpu_load_environment(i); - /* read all registers in stack order */ - for(int n=0;n<8;n++) - { + /* read all registers in stack order and update x87 tag word */ + for(int n=0;n<8;n++) { // update tag only if it is not empty - if (! IS_TAG_EMPTY(n)) - { + if (! IS_TAG_EMPTY(n)) { int tag = FPU_tagof(BX_READ_FPU_REG(n)); BX_CPU_THIS_PTR the_i387.FPU_settagi(tag, n); } @@ -526,13 +534,43 @@ void BX_CPP_AttrRegparmN(1) BX_CPU_C::FPLEGACY(bxInstruction_c *i) void BX_CPU_C::print_state_FPU(void) { static double scale_factor = pow(2.0, -63.0); + static char* cw_round_control[] = { + "NEAREST", "DOWN", "UP", "CHOP" + }; + static char* cw_precision_control[] = { + "32", "RES", "64", "80" + }; Bit32u reg; reg = BX_CPU_THIS_PTR the_i387.get_control_word(); - fprintf(stderr, "control word: 0x%04x\n", reg); + fprintf(stderr, "control word: 0x%04x: ", reg); + fprintf(stderr, "%s RC_%s PC_%s %s %s %s %s %s %s\n", + (reg & FPU_CW_Inf) ? "INF" : "inf", + (cw_round_control[(reg & FPU_CW_RC) >> 10]), + (cw_precision_control[(reg & FPU_CW_PC) >> 8]), + (reg & FPU_CW_Precision) ? "PM" : "pm", + (reg & FPU_CW_Underflow) ? "UM" : "um", + (reg & FPU_CW_Overflow) ? "OM" : "om", + (reg & FPU_CW_Zero_Div) ? "ZM" : "zm", + (reg & FPU_CW_Denormal) ? "DM" : "dm", + (reg & FPU_CW_Invalid) ? "IM" : "im"); + reg = BX_CPU_THIS_PTR the_i387.get_status_word(); - fprintf(stderr, "status word: 0x%04x\n", reg); - fprintf(stderr, " TOS : %d\n", FPU_TOS&7); + fprintf(stderr, "status word: 0x%04x: ", reg); + fprintf(stderr, "%s %s TOS%d %s %s %s %s %s %s %s %s %s %s %s\n", + (reg & FPU_SW_Backward) ? "B" : "b", + (reg & FPU_SW_C3) ? "C3" : "c3", (FPU_TOS&7), + (reg & FPU_SW_C2) ? "C2" : "c2", + (reg & FPU_SW_C1) ? "C1" : "c1", + (reg & FPU_SW_C0) ? "C0" : "c0", + (reg & FPU_SW_Summary) ? "ES" : "es", + (reg & FPU_SW_Stack_Fault) ? "SF" : "sf", + (reg & FPU_SW_Precision) ? "PE" : "pe", + (reg & FPU_SW_Underflow) ? "UE" : "ue", + (reg & FPU_SW_Overflow) ? "OE" : "oe", + (reg & FPU_SW_Zero_Div) ? "ZE" : "ze", + (reg & FPU_SW_Denormal_Op) ? "DE" : "de", + (reg & FPU_SW_Invalid) ? "IE" : "ie"); reg = BX_CPU_THIS_PTR the_i387.get_tag_word(); fprintf(stderr, "tag word: 0x%04x\n", reg); reg = BX_CPU_THIS_PTR the_i387.foo;