diff --git a/src/cpu/core_dyn_x86.cpp b/src/cpu/core_dyn_x86.cpp index e77cb969..d6e41ed1 100644 --- a/src/cpu/core_dyn_x86.cpp +++ b/src/cpu/core_dyn_x86.cpp @@ -43,6 +43,7 @@ #include "debug.h" #include "paging.h" #include "inout.h" +#include "fpu.h" #define CACHE_MAXSIZE (4096*2) #define CACHE_PAGES (128*8) @@ -163,6 +164,15 @@ static struct { Bitu callback,readdata; } core_dyn; +struct { + Bit32u state[32]; + FPU_P_Reg temp,temp2; + Bit32u dh_fpu_enabled; + Bit32u state_used; + Bit32u cw,host_cw; + Bit8u temp_state[128]; +} dyn_dh_fpu; + #include "core_dyn_x86/risc_x86.h" @@ -219,6 +229,30 @@ static void dyn_restoreregister(DynReg * src_reg, DynReg * dst_reg) { #include "core_dyn_x86/decoder.h" +#if defined (_MSC_VER) +#define DH_FPU_SAVE_REINIT \ +{ \ + __asm { \ + __asm fnsave dyn_dh_fpu.state[0] \ + } \ + dyn_dh_fpu.state_used=false; \ + dyn_dh_fpu.state[0]|=0x3f; \ +} +#else +#define DH_FPU_SAVE_REINIT \ +{ \ + __asm__ volatile ( \ + "fnsave (%0) \n" \ + : \ + : "m" (dyn_dh_fpu.state[0]) \ + : "memory" \ + ); \ + dyn_dh_fpu.state_used=false; \ + dyn_dh_fpu.state[0]|=0x3f; \ +} +#endif + + Bits CPU_Core_Dyn_X86_Run(void) { /* Determine the linear address of CS:EIP */ restart_core: @@ -232,7 +266,10 @@ restart_core: CPU_Exception(cpu.exception.which,cpu.exception.error); goto restart_core; } - if (!chandler) return CPU_Core_Normal_Run(); + if (!chandler) { + if (dyn_dh_fpu.state_used) DH_FPU_SAVE_REINIT + return CPU_Core_Normal_Run(); + } /* Find correct Dynamic Block to run */ CacheBlock * block=chandler->FindCacheBlock(ip_point&4095); if (!block) { @@ -244,10 +281,15 @@ run_block: switch (ret) { case BR_Iret: #if C_HEAVY_DEBUG - if (DEBUG_HeavyIsBreakpoint()) return debugCallback; + if (DEBUG_HeavyIsBreakpoint()) { + if (dyn_dh_fpu.state_used) DH_FPU_SAVE_REINIT + return debugCallback; + } #endif if (!GETFLAG(TF)) goto restart_core; cpudecoder=CPU_Core_Dyn_X86_Trap_Run; + if (!dyn_dh_fpu.state_used) return CBRET_NONE; + DH_FPU_SAVE_REINIT return CBRET_NONE; case BR_Normal: /* Maybe check if we staying in the same page? */ @@ -259,8 +301,12 @@ run_block: #if C_HEAVY_DEBUG if (DEBUG_HeavyIsBreakpoint()) return debugCallback; #endif + if (!dyn_dh_fpu.state_used) return CBRET_NONE; + DH_FPU_SAVE_REINIT return CBRET_NONE; case BR_CallBack: + if (!dyn_dh_fpu.state_used) return core_dyn.callback; + DH_FPU_SAVE_REINIT return core_dyn.callback; case BR_SMCBlock: // LOG_MSG("selfmodification of running block at %x:%x",SegValue(cs),reg_eip); @@ -269,11 +315,13 @@ run_block: case BR_Opcode: CPU_CycleLeft+=CPU_Cycles; CPU_Cycles=1; + if (dyn_dh_fpu.state_used) DH_FPU_SAVE_REINIT return CPU_Core_Normal_Run(); #if (C_DEBUG) case BR_OpcodeFull: CPU_CycleLeft+=CPU_Cycles; CPU_Cycles=1; + if (dyn_dh_fpu.state_used) DH_FPU_SAVE_REINIT return CPU_Core_Full_Run(); #endif case BR_Link1: @@ -291,6 +339,7 @@ run_block: } goto restart_core; } + if (dyn_dh_fpu.state_used) DH_FPU_SAVE_REINIT return CBRET_NONE; } @@ -366,6 +415,28 @@ void CPU_Core_Dyn_X86_Init(void) { DynRegs[G_EXIT].flags=DYNFLG_HAS16; /* Init the generator */ gen_init(); + + /* Init the fpu state */ + dyn_dh_fpu.dh_fpu_enabled=true; + dyn_dh_fpu.state_used=false; + dyn_dh_fpu.cw=0x37f; +#if defined (_MSC_VER) + __asm { + __asm finit + __asm fsave dyn_dh_fpu.state[0] + __asm fstcw dyn_dh_fpu.host_cw + } +#else + __asm__ volatile ( + "finit \n" + "fsave (%0) \n" + "fstcw (%1) \n" + : + : "m" (dyn_dh_fpu.state[0]), "m" (dyn_dh_fpu.host_cw) + : "memory" + ); +#endif + return; } @@ -378,4 +449,8 @@ void CPU_Core_Dyn_X86_Cache_Close(void) { cache_close(); } +void CPU_Core_Dyn_X86_SetFPUMode(bool dh_fpu) { + dyn_dh_fpu.dh_fpu_enabled=dh_fpu; +} + #endif diff --git a/src/cpu/core_dyn_x86/Makefile.am b/src/cpu/core_dyn_x86/Makefile.am index 8c432515..3d9be090 100644 --- a/src/cpu/core_dyn_x86/Makefile.am +++ b/src/cpu/core_dyn_x86/Makefile.am @@ -1,2 +1,2 @@ noinst_HEADERS = cache.h helpers.h decoder.h risc_x86.h string.h \ - dyn_fpu.h \ No newline at end of file + dyn_fpu.h dyn_fpu_dh.h \ No newline at end of file diff --git a/src/cpu/core_dyn_x86/decoder.h b/src/cpu/core_dyn_x86/decoder.h index a4bb7174..272b28e3 100644 --- a/src/cpu/core_dyn_x86/decoder.h +++ b/src/cpu/core_dyn_x86/decoder.h @@ -16,19 +16,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -#define X86_DYNFPU - -#include "fpu.h" -#define DYN_FPU_ESC(code) { \ - dyn_get_modrm(); \ - if (decode.modrm.val >= 0xc0) { \ - gen_call_function((void*)&FPU_ESC ## code ## _Normal,"%Id",decode.modrm.val); \ - } else { \ - dyn_fill_ea(); \ - gen_call_function((void*)&FPU_ESC ## code ## _EA,"%Id%Dd",decode.modrm.val,DREG(EA)); \ - gen_releasereg(DREG(EA)); \ - } \ -} +#define X86_DYNFPU_DH_ENABLED enum REP_Type { REP_NONE=0,REP_NZ,REP_Z @@ -152,7 +140,7 @@ static INLINE void dyn_set_eip_last(void) { } -enum save_info_type {exception, cycle_check, normal}; +enum save_info_type {exception, cycle_check, normal, fpu_restore}; static struct { @@ -161,6 +149,7 @@ static struct { Bit8u * branch_pos; Bit32u eip_change; Bitu cycles; + Bit8u * return_pos; } save_info[512]; Bitu used_save_info=0; @@ -220,6 +209,21 @@ static void dyn_fill_blocks(void) { dyn_save_critical_regs(); gen_return(BR_Cycles); break; + case fpu_restore: + dyn_loadstate(&save_info[sct].state); + gen_load_host(&dyn_dh_fpu.state_used,DREG(TMPB),4); + gen_sop_word(SOP_INC,true,DREG(TMPB)); + GenReg * gr1=FindDynReg(DREG(TMPB)); + cache_addb(0xdd); // FRSTOR fpu.state (fpu_restore) + cache_addb(0x25); + cache_addd((Bit32u)(&(dyn_dh_fpu.state[0]))); + cache_addb(0x89); // mov fpu.state_used,1 + cache_addb(0x05|(gr1->index<<3)); + cache_addd((Bit32u)(&(dyn_dh_fpu.state_used))); + gen_releasereg(DREG(TMPB)); + dyn_synchstate(&save_info[sct].state); + gen_create_jump(save_info[sct].return_pos); + break; } } used_save_info=0; @@ -1226,9 +1230,22 @@ static void dyn_add_iocheck_var(Bit8u accessed_port,Bitu access_size) { } } -#ifdef X86_DYNFPU -#include "dyn_fpu.h" +#ifdef X86_DYNFPU_DH_ENABLED +#include "dyn_fpu_dh.h" +#define dh_fpu_startup() { \ + fpu_used=true; \ + gen_protectflags(); \ + gen_load_host(&dyn_dh_fpu.state_used,DREG(TMPB),4); \ + gen_dop_word_imm(DOP_CMP,true,DREG(TMPB),0); \ + gen_releasereg(DREG(TMPB)); \ + save_info[used_save_info].branch_pos=gen_create_branch_long(BR_Z); \ + dyn_savestate(&save_info[used_save_info].state); \ + save_info[used_save_info].return_pos=cache.pos; \ + save_info[used_save_info].type=fpu_restore; \ + used_save_info++; \ +} #endif +#include "dyn_fpu.h" static CacheBlock * CreateCacheBlock(CodePageHandler * codepage,PhysPt start,Bitu max_opcodes) { Bits i; @@ -1258,6 +1275,9 @@ static CacheBlock * CreateCacheBlock(CodePageHandler * codepage,PhysPt start,Bit used_save_info++; gen_releasereg(DREG(CYCLES)); decode.cycles=0; +#ifdef X86_DYNFPU_DH_ENABLED + bool fpu_used=false; +#endif while (max_opcodes--) { /* Init prefixes */ decode.big_addr=cpu.code.big; @@ -1467,8 +1487,8 @@ restart_prefix: case 0x8e:dyn_mov_seg_ev();break; /* POP Ev */ case 0x8f:dyn_pop_ev();break; - //NOP - case 0x90: + case 0x90: //NOP + case 0x9b: //WAIT/FWAIT break; //XCHG ax,reg case 0x91:case 0x92:case 0x93:case 0x94:case 0x95:case 0x96:case 0x97: @@ -1575,67 +1595,104 @@ restart_prefix: case 0xd3:dyn_grp2_ev(grp2_cl);break; //FPU #ifdef CPU_FPU -#ifdef X86_DYNFPU case 0xd8: +#ifdef X86_DYNFPU_DH_ENABLED + if (dyn_dh_fpu.dh_fpu_enabled) { + if (fpu_used) dh_fpu_esc0(); + else { + dh_fpu_startup(); + dh_fpu_esc0(); + } + } else +#endif dyn_fpu_esc0(); break; case 0xd9: +#ifdef X86_DYNFPU_DH_ENABLED + if (dyn_dh_fpu.dh_fpu_enabled) { + if (fpu_used) dh_fpu_esc1(); + else { + dh_fpu_startup(); + dh_fpu_esc1(); + } + } else +#endif dyn_fpu_esc1(); break; case 0xda: +#ifdef X86_DYNFPU_DH_ENABLED + if (dyn_dh_fpu.dh_fpu_enabled) { + if (fpu_used) dh_fpu_esc2(); + else { + dh_fpu_startup(); + dh_fpu_esc2(); + } + } else +#endif dyn_fpu_esc2(); break; case 0xdb: +#ifdef X86_DYNFPU_DH_ENABLED + if (dyn_dh_fpu.dh_fpu_enabled) { + if (fpu_used) dh_fpu_esc3(); + else { + dh_fpu_startup(); + dh_fpu_esc3(); + } + } else +#endif dyn_fpu_esc3(); break; case 0xdc: +#ifdef X86_DYNFPU_DH_ENABLED + if (dyn_dh_fpu.dh_fpu_enabled) { + if (fpu_used) dh_fpu_esc4(); + else { + dh_fpu_startup(); + dh_fpu_esc4(); + } + } else +#endif dyn_fpu_esc4(); break; case 0xdd: +#ifdef X86_DYNFPU_DH_ENABLED + if (dyn_dh_fpu.dh_fpu_enabled) { + if (fpu_used) dh_fpu_esc5(); + else { + dh_fpu_startup(); + dh_fpu_esc5(); + } + } else +#endif dyn_fpu_esc5(); break; case 0xde: +#ifdef X86_DYNFPU_DH_ENABLED + if (dyn_dh_fpu.dh_fpu_enabled) { + if (fpu_used) dh_fpu_esc6(); + else { + dh_fpu_startup(); + dh_fpu_esc6(); + } + } else +#endif dyn_fpu_esc6(); break; case 0xdf: +#ifdef X86_DYNFPU_DH_ENABLED + if (dyn_dh_fpu.dh_fpu_enabled) { + if (fpu_used) dh_fpu_esc7(); + else { + dh_fpu_startup(); + dh_fpu_esc7(); + } + } else +#endif dyn_fpu_esc7(); break; -#else - case 0xd8: - DYN_FPU_ESC(0); - break; - case 0xd9: - DYN_FPU_ESC(1); - break; - case 0xda: - DYN_FPU_ESC(2); - break; - case 0xdb: - DYN_FPU_ESC(3); - break; - case 0xdc: - DYN_FPU_ESC(4); - break; - case 0xdd: - DYN_FPU_ESC(5); - break; - case 0xde: - DYN_FPU_ESC(6); - break; - case 0xdf: - dyn_get_modrm(); - if (decode.modrm.val >= 0xc0) { - if (decode.modrm.val == 0xe0) gen_releasereg(DREG(EAX)); /* FSTSW */ - gen_call_function((void*)&FPU_ESC7_Normal,"%Id",decode.modrm.val); - } else { - dyn_fill_ea(); - gen_call_function((void*)&FPU_ESC7_EA,"%Id%Dd",decode.modrm.val,DREG(EA)); - gen_releasereg(DREG(EA)); - } - break; #endif -#endif - //Loop's + //Loops case 0xe2:dyn_loop(LOOP_NONE);goto finish_block; case 0xe3:dyn_loop(LOOP_JCXZ);goto finish_block; //IN AL/AX,imm diff --git a/src/cpu/cpu.cpp b/src/cpu/cpu.cpp index 1b25e1bc..243966be 100644 --- a/src/cpu/cpu.cpp +++ b/src/cpu/cpu.cpp @@ -16,7 +16,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -/* $Id: cpu.cpp,v 1.86 2006-10-04 19:24:52 c2woody Exp $ */ +/* $Id: cpu.cpp,v 1.87 2006-10-12 15:18:31 c2woody Exp $ */ #include #include "dosbox.h" @@ -56,6 +56,7 @@ void CPU_Core_Simple_Init(void); void CPU_Core_Dyn_X86_Init(void); void CPU_Core_Dyn_X86_Cache_Init(bool enable_cache); void CPU_Core_Dyn_X86_Cache_Close(void); +void CPU_Core_Dyn_X86_SetFPUMode(bool dh_fpu); /* In debug mode exceptions are tested and dosbox exits when * a unhandled exception state is detected. @@ -2060,6 +2061,10 @@ public: #if (C_DYNAMIC_X86) else if (!strcasecmp(core,"dynamic")) { cpudecoder=&CPU_Core_Dyn_X86_Run; + CPU_Core_Dyn_X86_SetFPUMode(true); + } else if (!strcasecmp(core,"dynamic_nodhfpu")) { + cpudecoder=&CPU_Core_Dyn_X86_Run; + CPU_Core_Dyn_X86_SetFPUMode(false); } else if (!strcasecmp(core,"auto")) { cpudecoder=&CPU_Core_Normal_Run; CPU_AutoDetermineMode|=CPU_AUTODETERMINE_CORE; @@ -2070,7 +2075,7 @@ public: } #if (C_DYNAMIC_X86) - CPU_Core_Dyn_X86_Cache_Init(!strcasecmp(core,"dynamic")); + CPU_Core_Dyn_X86_Cache_Init(!strcasecmp(core,"dynamic") || !strcasecmp(core,"dynamic_nodhfpu")); #endif if(CPU_CycleMax <= 0) CPU_CycleMax = 2500; diff --git a/visualc_net/dosbox.vcproj b/visualc_net/dosbox.vcproj index 09b10a58..f8c9714d 100644 --- a/visualc_net/dosbox.vcproj +++ b/visualc_net/dosbox.vcproj @@ -265,6 +265,9 @@ + +