1
0
Fork 0

utilize host fpu directly (dynamic core)

Imported-from: https://svn.code.sf.net/p/dosbox/code-0/dosbox/trunk@2707
This commit is contained in:
Sebastian Strohhäcker 2006-10-12 15:18:32 +00:00
parent da0bb016c5
commit 3cb1e884bd
5 changed files with 199 additions and 59 deletions

View file

@ -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

View file

@ -1,2 +1,2 @@
noinst_HEADERS = cache.h helpers.h decoder.h risc_x86.h string.h \
dyn_fpu.h
dyn_fpu.h dyn_fpu_dh.h

View file

@ -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

View file

@ -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 <assert.h>
#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;

View file

@ -265,6 +265,9 @@
<File
RelativePath="..\src\cpu\core_dyn_x86\dyn_fpu.h">
</File>
<File
RelativePath="..\src\cpu\core_dyn_x86\dyn_fpu_dh.h">
</File>
<File
RelativePath="..\src\cpu\core_dyn_x86\helpers.h">
</File>