1
0
Fork 0

Add 64-bit support to dynamic_x86 core from vogons topic 67673. Thanks jmarsh!

Imported-from: https://svn.code.sf.net/p/dosbox/code-0/dosbox/trunk@4260
This commit is contained in:
Peter Veenstra 2019-09-30 18:30:11 +00:00
parent dda3b2a51f
commit fe177b4136
11 changed files with 1793 additions and 439 deletions

View file

@ -340,7 +340,7 @@ AC_MSG_CHECKING(whether x86 dynamic cpu core will be enabled)
if test x$enable_dynamic_x86 = xno -o x$enable_dynamic_core = xno; then
AC_MSG_RESULT(no)
else
if test x$c_targetcpu = xx86 ; then
if test x$c_targetcpu = xx86 -o x$c_targetcpu = xx86_64; then
AC_DEFINE(C_DYNAMIC_X86,1)
AC_MSG_RESULT(yes)
else
@ -355,7 +355,7 @@ if test x$enable_dynrec = xno -o x$enable_dynamic_core = xno; then
AC_MSG_RESULT(no)
else
dnl x86 only enable it if dynamic-x86 is disabled.
if test x$c_targetcpu = xx86 ; then
if test x$c_targetcpu = xx86 -o x$c_targetcpu = xx86_64; then
if test x$enable_dynamic_x86 = xno ; then
AC_DEFINE(C_DYNREC,1)
AC_MSG_RESULT(yes)
@ -363,16 +363,11 @@ dnl x86 only enable it if dynamic-x86 is disabled.
AC_MSG_RESULT([no, using dynamic-x86])
fi
else
if test x$c_targetcpu = xx86_64 ; then
AC_DEFINE(C_DYNREC,1)
AC_MSG_RESULT(yes)
else
if test x$c_targetcpu = xarm ; then
AC_DEFINE(C_DYNREC,1)
AC_MSG_RESULT(yes)
else
AC_MSG_RESULT(no)
fi
if test x$c_targetcpu = xarm ; then
AC_DEFINE(C_DYNREC,1)
AC_MSG_RESULT(yes)
else
AC_MSG_RESULT(no)
fi
fi
fi

View file

@ -65,6 +65,7 @@
#if C_FPU
#define CPU_FPU 1 //Enable FPU escape instructions
#define X86_DYNFPU_DH_ENABLED
#endif
enum {
@ -154,7 +155,7 @@ static DynReg DynRegs[G_MAX];
#define DREG(_WHICH_) &DynRegs[G_ ## _WHICH_ ]
static struct {
Bitu ea,tmpb,tmpd,stack,shift,newesp;
Bit32u ea,tmpb,tmpd,stack,shift,newesp;
} extra_regs;
static void IllegalOption(const char* msg) {
@ -168,17 +169,37 @@ static struct {
Bit32u readdata;
} core_dyn;
#if defined(X86_DYNFPU_DH_ENABLED)
static struct {
Bit32u state[32];
Bit16u cw,host_cw;
bool state_used;
// some fields expanded here for alignment purposes
struct {
Bit32u cw;
Bit32u sw;
Bit32u tag;
Bit32u ip;
Bit32u cs;
Bit32u ea;
Bit32u ds;
Bit8u st_reg[8][10];
} state;
FPU_P_Reg temp,temp2;
Bit32u dh_fpu_enabled;
Bit32u state_used;
Bit32u cw,host_cw;
Bit8u temp_state[128];
} dyn_dh_fpu;
#endif
#define X86 0x01
#define X86_64 0x02
#if C_TARGETCPU == X86_64
#include "core_dyn_x86/risc_x64.h"
#elif C_TARGETCPU == X86
#include "core_dyn_x86/risc_x86.h"
#else
#error DYN_X86 core not supported for this CPU target.
#endif
struct DynState {
DynReg regs[G_MAX];
@ -233,31 +254,19 @@ 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) {
// helper class to auto-save DH_FPU state on function exit
class auto_dh_fpu {
public:
~auto_dh_fpu(void) {
#if defined(X86_DYNFPU_DH_ENABLED)
if (dyn_dh_fpu.state_used)
gen_dh_fpu_save();
#endif
};
};
auto_dh_fpu fpu_saver;
/* Determine the linear address of CS:EIP */
restart_core:
PhysPt ip_point=SegPhys(cs)+reg_eip;
@ -272,7 +281,6 @@ restart_core:
goto restart_core;
}
if (!chandler) {
if (dyn_dh_fpu.state_used) DH_FPU_SAVE_REINIT
return CPU_Core_Normal_Run();
}
/* Find correct Dynamic Block to run */
@ -281,10 +289,11 @@ restart_core:
if (!chandler->invalidation_map || (chandler->invalidation_map[ip_point&4095]<4)) {
block=CreateCacheBlock(chandler,ip_point,32);
} else {
Bitu old_cycles=CPU_Cycles;
Bit32s old_cycles=CPU_Cycles;
CPU_Cycles=1;
// manually save
fpu_saver = auto_dh_fpu();
Bits nc_retcode=CPU_Core_Normal_Run();
if (dyn_dh_fpu.state_used) DH_FPU_SAVE_REINIT
if (!nc_retcode) {
CPU_Cycles=old_cycles-1;
goto restart_core;
@ -304,21 +313,17 @@ run_block:
#if C_DEBUG
#if C_HEAVY_DEBUG
if (DEBUG_HeavyIsBreakpoint()) {
if (dyn_dh_fpu.state_used) DH_FPU_SAVE_REINIT
return debugCallback;
}
#endif
#endif
if (!GETFLAG(TF)) {
if (GETFLAG(IF) && PIC_IRQCheck) {
if (dyn_dh_fpu.state_used) DH_FPU_SAVE_REINIT
return CBRET_NONE;
}
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? */
@ -334,12 +339,8 @@ run_block:
if (DEBUG_HeavyIsBreakpoint()) return debugCallback;
#endif
#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);
@ -348,19 +349,17 @@ 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:
case BR_Link2:
{
Bitu temp_ip=SegPhys(cs)+reg_eip;
Bit32u temp_ip=SegPhys(cs)+reg_eip;
CodePageHandler * temp_handler=(CodePageHandler *)get_tlb_readhandler(temp_ip);
if (temp_handler->flags & (cpu.code.big ? PFLAG_HASCODE32:PFLAG_HASCODE16)) {
block=temp_handler->FindCacheBlock(temp_ip & 4095);
@ -371,12 +370,11 @@ run_block:
}
goto restart_core;
}
if (dyn_dh_fpu.state_used) DH_FPU_SAVE_REINIT
return CBRET_NONE;
}
Bits CPU_Core_Dyn_X86_Trap_Run(void) {
Bits oldCycles = CPU_Cycles;
Bit32s oldCycles = CPU_Cycles;
CPU_Cycles = 1;
cpu.trap_skip = false;
@ -449,25 +447,15 @@ void CPU_Core_Dyn_X86_Init(void) {
/* Init the generator */
gen_init();
#if defined(X86_DYNFPU_DH_ENABLED)
/* 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"
);
// FINIT
memset(&dyn_dh_fpu.state, 0, sizeof(dyn_dh_fpu.state));
dyn_dh_fpu.state.cw = 0x37F;
dyn_dh_fpu.state.tag = 0xFFFF;
#endif
return;
@ -482,62 +470,10 @@ void CPU_Core_Dyn_X86_Cache_Close(void) {
cache_close();
}
void CPU_Core_Dyn_X86_Cache_Reset(void) {
cache_reset();
}
void CPU_Core_Dyn_X86_SetFPUMode(bool dh_fpu) {
#if defined(X86_DYNFPU_DH_ENABLED)
dyn_dh_fpu.dh_fpu_enabled=dh_fpu;
}
Bit32u fpu_state[32];
void CPU_Core_Dyn_X86_SaveDHFPUState(void) {
if (dyn_dh_fpu.dh_fpu_enabled) {
if (dyn_dh_fpu.state_used!=0) {
#if defined (_MSC_VER)
__asm {
__asm fsave fpu_state[0]
__asm finit
}
#else
__asm__ volatile (
"fsave %0 \n"
"finit \n"
: "=m" (fpu_state[0])
:
: "memory"
);
#endif
}
}
}
void CPU_Core_Dyn_X86_RestoreDHFPUState(void) {
if (dyn_dh_fpu.dh_fpu_enabled) {
if (dyn_dh_fpu.state_used!=0) {
#if defined (_MSC_VER)
__asm {
__asm frstor fpu_state[0]
}
#else
__asm__ volatile (
"frstor %0 \n"
:
: "m" (fpu_state[0])
:
);
#endif
}
}
}
#else
void CPU_Core_Dyn_X86_SaveDHFPUState(void) {
}
void CPU_Core_Dyn_X86_RestoreDHFPUState(void) {
}
#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_dh.h
noinst_HEADERS = cache.h helpers.h decoder.h risc_x86.h risc_x64.h string.h \
dyn_fpu.h dyn_fpu_dh.h

View file

@ -466,6 +466,10 @@ static INLINE void cache_addd(Bit32u val) {
cache.pos+=4;
}
static INLINE void cache_addq(Bit64u val) {
*(Bit64u*)cache.pos=val;
cache.pos+=8;
}
static void gen_return(BlockReturn retcode);
@ -569,75 +573,3 @@ static void cache_close(void) {
cache_code_link_blocks = NULL;
cache_initialized = false; */
}
static void cache_reset(void) {
if (cache_initialized) {
for (;;) {
if (cache.used_pages) {
CodePageHandler * cpage=cache.used_pages;
CodePageHandler * npage=cache.used_pages->next;
cpage->ClearRelease();
delete cpage;
cache.used_pages=npage;
} else break;
}
if (cache_blocks == NULL) {
cache_blocks=(CacheBlock*)malloc(CACHE_BLOCKS*sizeof(CacheBlock));
if(!cache_blocks) E_Exit("Allocating cache_blocks has failed");
}
memset(cache_blocks,0,sizeof(CacheBlock)*CACHE_BLOCKS);
cache.block.free=&cache_blocks[0];
for (Bits i=0;i<CACHE_BLOCKS-1;i++) {
cache_blocks[i].link[0].to=(CacheBlock *)1;
cache_blocks[i].link[1].to=(CacheBlock *)1;
cache_blocks[i].cache.next=&cache_blocks[i+1];
}
if (cache_code_start_ptr==NULL) {
#if defined (WIN32)
cache_code_start_ptr=(Bit8u*)VirtualAlloc(0,CACHE_TOTAL+CACHE_MAXSIZE+PAGESIZE_TEMP-1+PAGESIZE_TEMP,
MEM_COMMIT,PAGE_EXECUTE_READWRITE);
if (!cache_code_start_ptr)
cache_code_start_ptr=(Bit8u*)malloc(CACHE_TOTAL+CACHE_MAXSIZE+PAGESIZE_TEMP-1+PAGESIZE_TEMP);
#else
cache_code_start_ptr=(Bit8u*)malloc(CACHE_TOTAL+CACHE_MAXSIZE+PAGESIZE_TEMP-1+PAGESIZE_TEMP);
#endif
if (!cache_code_start_ptr) E_Exit("Allocating dynamic core cache memory failed");
cache_code=(Bit8u*)(((Bitu)cache_code_start_ptr + PAGESIZE_TEMP-1) & ~(PAGESIZE_TEMP-1)); //Bitu is same size as a pointer.
cache_code_link_blocks=cache_code;
cache_code+=PAGESIZE_TEMP;
#if (C_HAVE_MPROTECT)
if(mprotect(cache_code_link_blocks,CACHE_TOTAL+CACHE_MAXSIZE+PAGESIZE_TEMP,PROT_WRITE|PROT_READ|PROT_EXEC))
LOG_MSG("Setting execute permission on the code cache has failed!");
#endif
}
CacheBlock * block=cache_getblock();
cache.block.first=block;
cache.block.active=block;
block->cache.start=&cache_code[0];
block->cache.size=CACHE_TOTAL;
block->cache.next=0; //Last block in the list
/* Setup the default blocks for block linkage returns */
cache.pos=&cache_code_link_blocks[0];
link_blocks[0].cache.start=cache.pos;
gen_return(BR_Link1);
cache.pos=&cache_code_link_blocks[32];
link_blocks[1].cache.start=cache.pos;
gen_return(BR_Link2);
cache.free_pages=0;
cache.last_page=0;
cache.used_pages=0;
/* Setup the code pages */
for (Bitu i=0;i<CACHE_PAGES;i++) {
CodePageHandler * newpage=new CodePageHandler();
newpage->next=cache.free_pages;
cache.free_pages=newpage;
}
}
}

View file

@ -17,7 +17,6 @@
*/
#define X86_DYNFPU_DH_ENABLED
#define X86_INLINED_MEMACCESS
@ -332,7 +331,7 @@ static BlockReturn DynRunException(Bit32u eip_add,Bit32u cycle_sub,Bit32u dflags
}
static void dyn_check_bool_exception(DynReg * check) {
gen_dop_byte(DOP_OR,check,0,check,0);
gen_dop_byte(DOP_TEST,check,0,check,0);
save_info[used_save_info].branch_pos=gen_create_branch_long(BR_NZ);
dyn_savestate(&save_info[used_save_info].state);
if (!decode.cycles) decode.cycles++;
@ -344,7 +343,7 @@ static void dyn_check_bool_exception(DynReg * check) {
}
static void dyn_check_bool_exception_al(void) {
cache_addw(0xc00a); // or al, al
cache_addw(0xC084); // test al,al
save_info[used_save_info].branch_pos=gen_create_branch_long(BR_NZ);
dyn_savestate(&save_info[used_save_info].state);
if (!decode.cycles) decode.cycles++;
@ -359,7 +358,7 @@ static void dyn_check_bool_exception_al(void) {
static void dyn_check_irqrequest(void) {
gen_load_host(&PIC_IRQCheck,DREG(TMPB),4);
gen_dop_word(DOP_OR,true,DREG(TMPB),DREG(TMPB));
gen_dop_word(DOP_TEST,true,DREG(TMPB),DREG(TMPB));
save_info[used_save_info].branch_pos=gen_create_branch_long(BR_NZ);
gen_releasereg(DREG(TMPB));
dyn_savestate(&save_info[used_save_info].state);
@ -403,21 +402,29 @@ static void dyn_fill_blocks(void) {
dyn_save_critical_regs();
gen_return(BR_Cycles);
break;
#ifdef X86_DYNFPU_DH_ENABLED
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));
#if C_TARGETCPU == X86
cache_addb(0xd9); // FNSTCW fpu.host_cw
cache_addb(0x3d);
cache_addd((Bit32u)(&dyn_dh_fpu.host_cw));
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));
cache_addd((Bit32u)(&dyn_dh_fpu.state));
cache_addb(0xC6); // mov byte [fpu.state_used], 1
cache_addb(0x05);
cache_addd((Bit32u)(&dyn_dh_fpu.state_used));
cache_addb(1);
#else // X86_64
opcode(7).setabsaddr(&dyn_dh_fpu.host_cw).Emit8(0xD9); // FNSTCW [&fpu.host_cw]
opcode(4).setabsaddr(&dyn_dh_fpu.state).Emit8(0xDD); // FRSTOR [&fpu.state]
opcode(0).setimm(1,1).setabsaddr(&dyn_dh_fpu.state_used).Emit8(0xC6); // mov byte[], imm8
#endif
dyn_synchstate(&save_info[sct].state);
gen_create_jump(save_info[sct].return_pos);
break;
#endif
}
}
used_save_info=0;
@ -427,7 +434,7 @@ static void dyn_fill_blocks(void) {
#if !defined(X86_INLINED_MEMACCESS)
static void dyn_read_byte(DynReg * addr,DynReg * dst,Bitu high) {
gen_protectflags();
gen_call_function((void *)&mem_readb_checked,"%Dd%Id",addr,&core_dyn.readdata);
gen_call_function((void *)&mem_readb_checked,"%Dd%Ip",addr,&core_dyn.readdata);
dyn_check_bool_exception_al();
gen_mov_host(&core_dyn.readdata,dst,1,high);
}
@ -439,8 +446,8 @@ static void dyn_write_byte(DynReg * addr,DynReg * val,Bitu high) {
}
static void dyn_read_word(DynReg * addr,DynReg * dst,bool dword) {
gen_protectflags();
if (dword) gen_call_function((void *)&mem_readd_checked,"%Dd%Id",addr,&core_dyn.readdata);
else gen_call_function((void *)&mem_readw_checked,"%Dd%Id",addr,&core_dyn.readdata);
if (dword) gen_call_function((void *)&mem_readd_checked,"%Dd%Ip",addr,&core_dyn.readdata);
else gen_call_function((void *)&mem_readw_checked,"%Dd%Ip",addr,&core_dyn.readdata);
dyn_check_bool_exception_al();
gen_mov_host(&core_dyn.readdata,dst,dword?4:2);
}
@ -452,31 +459,32 @@ static void dyn_write_word(DynReg * addr,DynReg * val,bool dword) {
}
static void dyn_read_byte_release(DynReg * addr,DynReg * dst,Bitu high) {
gen_protectflags();
gen_call_function((void *)&mem_readb_checked,"%Ddr%Id",addr,&core_dyn.readdata);
gen_call_function((void *)&mem_readb_checked,"%Drd%Ip",addr,&core_dyn.readdata);
dyn_check_bool_exception_al();
gen_mov_host(&core_dyn.readdata,dst,1,high);
}
static void dyn_write_byte_release(DynReg * addr,DynReg * val,Bitu high) {
gen_protectflags();
if (high) gen_call_function((void *)&mem_writeb_checked,"%Ddr%Dh",addr,val);
else gen_call_function((void *)&mem_writeb_checked,"%Ddr%Dd",addr,val);
if (high) gen_call_function((void *)&mem_writeb_checked,"%Drd%Dh",addr,val);
else gen_call_function((void *)&mem_writeb_checked,"%Drd%Dd",addr,val);
dyn_check_bool_exception_al();
}
static void dyn_read_word_release(DynReg * addr,DynReg * dst,bool dword) {
gen_protectflags();
if (dword) gen_call_function((void *)&mem_readd_checked,"%Ddr%Id",addr,&core_dyn.readdata);
else gen_call_function((void *)&mem_readw_checked,"%Ddr%Id",addr,&core_dyn.readdata);
if (dword) gen_call_function((void *)&mem_readd_checked,"%Drd%Ip",addr,&core_dyn.readdata);
else gen_call_function((void *)&mem_readw_checked,"%Drd%Ip",addr,&core_dyn.readdata);
dyn_check_bool_exception_al();
gen_mov_host(&core_dyn.readdata,dst,dword?4:2);
}
static void dyn_write_word_release(DynReg * addr,DynReg * val,bool dword) {
gen_protectflags();
if (dword) gen_call_function((void *)&mem_writed_checked,"%Ddr%Dd",addr,val);
else gen_call_function((void *)&mem_writew_checked,"%Ddr%Dd",addr,val);
if (dword) gen_call_function((void *)&mem_writed_checked,"%Drd%Dd",addr,val);
else gen_call_function((void *)&mem_writew_checked,"%Drd%Dd",addr,val);
dyn_check_bool_exception_al();
}
#else
#if C_TARGETCPU == X86
static void dyn_read_intro(DynReg * addr,bool release_addr=true) {
gen_protectflags();
@ -634,7 +642,7 @@ static void dyn_read_word(DynReg * addr,DynReg * dst,bool dword) {
gen_fill_jump(jmp_loc);
} else {
gen_protectflags();
gen_call_function((void *)&mem_readw_checked,"%Dd%Id",addr,&core_dyn.readdata);
gen_call_function((void *)&mem_readw_checked,"%Dd%Ip",addr,&core_dyn.readdata);
dyn_check_bool_exception_al();
gen_mov_host(&core_dyn.readdata,dst,2);
}
@ -680,7 +688,7 @@ static void dyn_read_word_release(DynReg * addr,DynReg * dst,bool dword) {
gen_fill_jump(jmp_loc);
} else {
gen_protectflags();
gen_call_function((void *)&mem_readw_checked,"%Ddr%Id",addr,&core_dyn.readdata);
gen_call_function((void *)&mem_readw_checked,"%Drd%Ip",addr,&core_dyn.readdata);
dyn_check_bool_exception_al();
gen_mov_host(&core_dyn.readdata,dst,2);
}
@ -888,11 +896,247 @@ static void dyn_write_word_release(DynReg * addr,DynReg * val,bool dword) {
gen_fill_jump(jmp_loc);
} else {
gen_protectflags();
gen_call_function((void *)&mem_writew_checked,"%Ddr%Dd",addr,val);
gen_call_function((void *)&mem_writew_checked,"%Drd%Dd",addr,val);
dyn_check_bool_exception_al();
}
}
#else // X86_64
static bool mem_readd_checked_dcx64(PhysPt address, Bit32u* dst) {
return get_tlb_readhandler(address)->readd_checked(address, dst);
}
static bool mem_readw_checked_dcx64(PhysPt address, Bit16u* dst) {
return get_tlb_readhandler(address)->readw_checked(address, dst);
}
static bool mem_writed_checked_dcx64(PhysPt address, Bitu val) {
return get_tlb_writehandler(address)->writed_checked(address, val);
}
static bool mem_writew_checked_dcx64(PhysPt address, Bitu val) {
return get_tlb_writehandler(address)->writew_checked(address, val);
}
static bool mem_readb_checked_dcx64(PhysPt address, Bit8u* dst) {
return get_tlb_readhandler(address)->readb_checked(address, dst);
}
static bool mem_writeb_checked_dcx64(PhysPt address, Bitu val) {
return get_tlb_writehandler(address)->writeb_checked(address, val);
}
static void dyn_read_word_internal(DynReg * addr,DynReg * dst,bool dword,bool release) {
DynState callstate;
gen_protectflags();
x64gen.regs[X64_REG_RAX]->Clear();
x64gen.regs[X64_REG_RAX]->notusable = true;
GenReg *gensrc = FindDynReg(addr);
if (dword && release) gen_releasereg(addr);
GenReg *gendst = FindDynReg(dst,dword);
if (!dword && release) gen_releasereg(addr);
x64gen.regs[X64_REG_RAX]->notusable = false;
dyn_savestate(&callstate);
Bit8u *page_brk;
opcode(0).set64().setea(gensrc->index,-1,0,dword?3:1).Emit8(0x8D); // lea rax, [dst+(dword?3:1)]
if (dword) {
opcode(0).set64().setimm(~0xFFF,4).Emit8Reg(0x25); // and rax, ~0xFFF
opcode(gensrc->index).set64().setrm(0).Emit8(0x39); // cmp rax,src
page_brk=gen_create_branch(BR_NBE);
} else {
opcode(0,false).setimm(0xFFF,2).Emit8Reg(0xA9); // test ax,0xFFF
page_brk=gen_create_branch(BR_Z);
}
opcode(5).setrm(0).setimm(12,1).Emit8(0xC1); // shr eax,12
// mov rax, [8*rax+paging.tlb.read(rbp)]
opcode(0).set64().setea(5,0,3,(Bits)paging.tlb.read-(Bits)&cpu_regs).Emit8(0x8B);
opcode(0).set64().setrm(0).Emit8(0x85); // test rax,rax
Bit8u *nomap=gen_create_branch(BR_Z);
//mov dst, [RAX+src]
opcode(gendst->index,dword).setea(0,gensrc->index).Emit8(0x8B);
Bit8u* jmp_loc = gen_create_short_jump();
gen_fill_branch(page_brk);
gen_load_imm(0, (Bitu)(dword?(void*)mem_unalignedreadd_checked:(void*)mem_unalignedreadw_checked));
Bit8u* page_jmp = gen_create_short_jump();
gen_fill_branch(nomap);
gen_load_imm(0, (Bitu)(dword?(void*)mem_readd_checked_dcx64:(void*)mem_readw_checked_dcx64));
gen_fill_short_jump(page_jmp);
if (gensrc->index != ARG0_REG) {
x64gen.regs[reg_args[0]]->Clear();
opcode(ARG0_REG).setrm(gensrc->index).Emit8(0x8B);
}
x64gen.regs[reg_args[1]]->Clear();
gen_load_imm(ARG1_REG, (Bitu)dst->data);
gendst->Clear();
gen_call_ptr();
dyn_check_bool_exception_al();
dyn_synchstate(&callstate);
dst->flags |= DYNFLG_CHANGED;
gen_fill_short_jump(jmp_loc);
}
static void dyn_read_word(DynReg * addr,DynReg * dst,bool dword) {
dyn_read_word_internal(addr,dst,dword,false);
}
static void dyn_read_word_release(DynReg * addr,DynReg * dst,bool dword) {
dyn_read_word_internal(addr,dst,dword,true);
}
static void dyn_read_byte_internal(DynReg * addr,DynReg * dst,bool high,bool release) {
DynState callstate;
gen_protectflags();
x64gen.regs[X64_REG_RAX]->Clear();
x64gen.regs[X64_REG_RAX]->notusable = true;
GenReg *gensrc = FindDynReg(addr);
GenReg *gendst = FindDynReg(dst);
if (release) gen_releasereg(addr);
x64gen.regs[X64_REG_RAX]->notusable = false;
dyn_savestate(&callstate);
if (gendst->index>3) IllegalOption("dyn_read_byte");
opcode(0).setrm(gensrc->index).Emit8(0x8B); // mov eax, src
opcode(5).setrm(0).setimm(12,1).Emit8(0xC1); // shr eax,12
// mov rax, [8*rax+paging.tlb.read(rbp)]
opcode(0).set64().setea(5,0,3,(Bits)paging.tlb.read-(Bits)&cpu_regs).Emit8(0x8B);
opcode(0).set64().setrm(0).Emit8(0x85); // test rax,rax
Bit8u *nomap=gen_create_branch(BR_Z);
int src = gensrc->index;
if (high && src>=8) { // can't use REX prefix with high-byte reg
opcode(0).set64().setrm(src).Emit8(0x03); // add rax, src
src = -1;
}
// mov dst, byte [rax+src]
opcode(gendst->index,true,high?4:0).setea(0,src).Emit8(0x8A);
Bit8u* jmp_loc=gen_create_short_jump();
gen_fill_branch(nomap);
if (gensrc->index != ARG0_REG) {
x64gen.regs[reg_args[0]]->Clear();
opcode(ARG0_REG).setrm(gensrc->index).Emit8(0x8B); // mov ARG0,src
}
x64gen.regs[reg_args[1]]->Clear();
gen_load_imm(ARG1_REG, (Bitu)(high?((Bit8u*)dst->data)+1:dst->data));
gendst->Clear();
gen_call_ptr((void*)mem_readb_checked_dcx64);
dyn_check_bool_exception_al();
dyn_synchstate(&callstate);
dst->flags |= DYNFLG_CHANGED;
gen_fill_short_jump(jmp_loc);
}
static void dyn_read_byte(DynReg * addr,DynReg * dst,bool high) {
dyn_read_byte_internal(addr,dst,high,false);
}
static void dyn_read_byte_release(DynReg * addr,DynReg * dst,bool high) {
dyn_read_byte_internal(addr,dst,high,true);
}
static void dyn_write_word_internal(DynReg * addr,DynReg * val,bool dword,bool release) {
DynState callstate;
gen_protectflags();
x64gen.regs[X64_REG_RAX]->Clear();
x64gen.regs[X64_REG_RAX]->notusable = true;
GenReg *gendst = FindDynReg(addr);
GenReg *genval = FindDynReg(val);
if (release) gen_releasereg(addr);
x64gen.regs[X64_REG_RAX]->notusable = false;
dyn_savestate(&callstate);
Bit8u *page_brk;
opcode(0).set64().setea(gendst->index,-1,0,dword?3:1).Emit8(0x8D); // lea rax, [dst+(dword?3:1)]
if (dword) {
opcode(0).set64().setimm(~0xFFF,4).Emit8Reg(0x25); // and rax, ~0xFFF
opcode(gendst->index).set64().setrm(0).Emit8(0x39); // cmp rax,dst
page_brk=gen_create_branch(BR_NBE);
} else {
opcode(0,false).setimm(0xFFF,2).Emit8Reg(0xA9); // test ax,0xFFF
page_brk=gen_create_branch(BR_Z);
}
opcode(5).setrm(0).setimm(12,1).Emit8(0xC1); // shr eax,12
// mov rax, [8*rax+paging.tlb.write(rbp)]
opcode(0).set64().setea(5,0,3,(Bits)paging.tlb.write-(Bits)&cpu_regs).Emit8(0x8B);
opcode(0).set64().setrm(0).Emit8(0x85); // test rax,rax
Bit8u *nomap=gen_create_branch(BR_Z);
//mov [RAX+src], dst
opcode(genval->index,dword).setea(0,gendst->index).Emit8(0x89);
Bit8u* jmp_loc = gen_create_short_jump();
gen_fill_branch(page_brk);
gen_load_imm(0, (Bitu)(dword?(void*)mem_unalignedwrited_checked:(void*)mem_unalignedwritew_checked));
Bit8u* page_jmp = gen_create_short_jump();
gen_fill_branch(nomap);
gen_load_imm(0, (Bitu)(dword?(void*)mem_writed_checked_dcx64:(void*)mem_writew_checked_dcx64));
gen_fill_short_jump(page_jmp);
if (gendst->index != ARG0_REG) {
x64gen.regs[reg_args[0]]->Clear();
opcode(ARG0_REG).setrm(gendst->index).Emit8(0x8B);
}
gen_load_arg_reg(1, val, dword ? "d":"w");
gen_call_ptr();
dyn_check_bool_exception_al();
dyn_synchstate(&callstate);
gen_fill_short_jump(jmp_loc);
}
static void dyn_write_word(DynReg * addr,DynReg * val,bool dword) {
dyn_write_word_internal(addr, val, dword, false);
}
static void dyn_write_word_release(DynReg * addr,DynReg * val,bool dword) {
dyn_write_word_internal(addr, val, dword, true);
}
static void dyn_write_byte_internal(DynReg * addr,DynReg * val,bool high,bool release) {
DynState callstate;
gen_protectflags();
x64gen.regs[X64_REG_RAX]->Clear();
x64gen.regs[X64_REG_RAX]->notusable = true;
GenReg *gendst = FindDynReg(addr);
GenReg *genval = FindDynReg(val);
if (release) gen_releasereg(addr);
x64gen.regs[X64_REG_RAX]->notusable = false;
dyn_savestate(&callstate);
if (genval->index>3) IllegalOption("dyn_write_byte");
opcode(0).setrm(gendst->index).Emit8(0x8B); // mov eax, dst
opcode(5).setrm(0).setimm(12,1).Emit8(0xC1); // shr eax,12
// mov rax, [8*rax+paging.tlb.write(rbp)]
opcode(0).set64().setea(5,0,3,(Bits)paging.tlb.write-(Bits)&cpu_regs).Emit8(0x8B);
opcode(0).set64().setrm(0).Emit8(0x85); // test rax,rax
Bit8u *nomap=gen_create_branch(BR_Z);
int dst = gendst->index;
if (high && dst>=8) { // can't use REX prefix with high-byte reg
opcode(0).set64().setrm(dst).Emit8(0x03); // add rax, dst
dst = -1;
}
// mov byte [rax+src], val
opcode(genval->index,true,high?4:0).setea(0,dst).Emit8(0x88);
Bit8u* jmp_loc=gen_create_short_jump();
gen_fill_branch(nomap);
if (gendst->index != ARG0_REG) {
x64gen.regs[reg_args[0]]->Clear();
opcode(ARG0_REG).setrm(gendst->index).Emit8(0x8B); // mov ARG0,dst
}
gen_load_arg_reg(1, val, high ? "h":"l");
gen_call_ptr((void*)mem_writeb_checked_dcx64);
dyn_check_bool_exception_al();
dyn_synchstate(&callstate);
gen_fill_short_jump(jmp_loc);
}
static void dyn_write_byte(DynReg * addr,DynReg * src,bool high) {
dyn_write_byte_internal(addr,src,high,false);
}
static void dyn_write_byte_release(DynReg * addr,DynReg * src,bool high) {
dyn_write_byte_internal(addr,src,high,true);
}
#endif
#endif
@ -938,9 +1182,9 @@ static void dyn_pop(DynReg * dynreg,bool checked=true) {
gen_dop_word(DOP_ADD,true,DREG(STACK),DREG(SS));
if (checked) {
if (decode.big_op) {
gen_call_function((void *)&mem_readd_checked,"%Drd%Id",DREG(STACK),&core_dyn.readdata);
gen_call_function((void *)&mem_readd_checked,"%Drd%Ip",DREG(STACK),&core_dyn.readdata);
} else {
gen_call_function((void *)&mem_readw_checked,"%Drd%Id",DREG(STACK),&core_dyn.readdata);
gen_call_function((void *)&mem_readw_checked,"%Drd%Ip",DREG(STACK),&core_dyn.readdata);
}
dyn_check_bool_exception_al();
gen_mov_host(&core_dyn.readdata,dynreg,decode.big_op?4:2);
@ -1055,7 +1299,7 @@ skip_extend_word:
segbase=DREG(DS);
Bitu val;
if (decode_fetchd_imm(val)) {
gen_mov_host((void*)val,DREG(EA),4);
gen_dop_word_imm_mem(DOP_MOV,true,DREG(EA),(void*)val);
if (!addseg) {
gen_lea(reg_ea,DREG(EA),scaled,scale,0);
} else {
@ -1088,7 +1332,7 @@ skip_extend_word:
case 2: {
Bitu val;
if (decode_fetchd_imm(val)) {
gen_mov_host((void*)val,DREG(EA),4);
gen_dop_word_imm_mem(DOP_MOV,true,DREG(EA),(void*)val);
if (!addseg) {
gen_lea(DREG(EA),DREG(EA),scaled,scale,0);
gen_lea(reg_ea,DREG(EA),base,0,0);
@ -1560,7 +1804,7 @@ static void dyn_grp2_ev(grp2_types type) {
if (decode_fetchb_imm(val)) {
if (decode.modrm.reg < 4) gen_needflags();
else gen_discardflags();
gen_load_host((void*)val,DREG(TMPB),1);
gen_dop_byte_imm_mem(DOP_MOV,DREG(TMPB),0,(void*)val);
gen_shift_word_cl(decode.modrm.reg,decode.big_op,src,DREG(TMPB));
gen_releasereg(DREG(TMPB));
break;
@ -1619,7 +1863,7 @@ static void dyn_grp3_eb(void) {
gen_dop_byte(DOP_MOV,DREG(TMPB),0,&DynRegs[decode.modrm.rm&3],decode.modrm.rm&4);
gen_releasereg(DREG(EAX));
gen_call_function((decode.modrm.reg==6) ? (void *)&dyn_helper_divb : (void *)&dyn_helper_idivb,
"%Rd%Dd",DREG(TMPB),DREG(TMPB));
"%Rd%Drd",DREG(TMPB),DREG(TMPB));
dyn_check_bool_exception(DREG(TMPB));
goto skipsave;
}
@ -1661,7 +1905,7 @@ static void dyn_grp3_ev(void) {
void * func=(decode.modrm.reg==6) ?
(decode.big_op ? (void *)&dyn_helper_divd : (void *)&dyn_helper_divw) :
(decode.big_op ? (void *)&dyn_helper_idivd : (void *)&dyn_helper_idivw);
gen_call_function(func,"%Rd%Dd",DREG(TMPB),DREG(TMPW));
gen_call_function(func,"%Rd%Drd",DREG(TMPB),DREG(TMPW));
dyn_check_bool_exception(DREG(TMPB));
gen_releasereg(DREG(TMPB));
goto skipsave;
@ -1739,8 +1983,8 @@ static void dyn_pop_ev(void) {
if (decode.modrm.mod<3) {
dyn_fill_ea();
// dyn_write_word_release(DREG(EA),DREG(TMPW),decode.big_op);
if (decode.big_op) gen_call_function((void *)&mem_writed_inline,"%Ddr%Dd",DREG(EA),DREG(TMPW));
else gen_call_function((void *)&mem_writew_inline,"%Ddr%Dd",DREG(EA),DREG(TMPW));
if (decode.big_op) gen_call_function((void *)&mem_writed_inline,"%Drd%Dd",DREG(EA),DREG(TMPW));
else gen_call_function((void *)&mem_writew_inline,"%Drd%Dd",DREG(EA),DREG(TMPW));
} else {
gen_dop_word(DOP_MOV,decode.big_op,&DynRegs[decode.modrm.rm],DREG(TMPW));
}
@ -1861,7 +2105,7 @@ static void dyn_loop(LoopTypes type) {
branch2=gen_create_branch(BR_Z);
break;
case LOOP_JCXZ:
gen_dop_word(DOP_OR,decode.big_addr,DREG(ECX),DREG(ECX));
gen_dop_word(DOP_TEST,decode.big_addr,DREG(ECX),DREG(ECX));
gen_releasereg(DREG(ECX));
branch2=gen_create_branch(BR_NZ);
break;
@ -1982,8 +2226,8 @@ static void dyn_add_iocheck_var(Bit8u accessed_port,Bitu access_size) {
#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_load_host(&dyn_dh_fpu.state_used,DREG(TMPB),1); \
gen_dop_byte(DOP_TEST,DREG(TMPB),0,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); \
@ -2009,15 +2253,15 @@ static CacheBlock * CreateCacheBlock(CodePageHandler * codepage,PhysPt start,Bit
decode.block->page.start=decode.page.index;
codepage->AddCacheBlock(decode.block);
gen_save_host_direct(&cache.block.running,(Bit32u)decode.block);
for (i=0;i<G_MAX;i++) {
DynRegs[i].flags&=~(DYNFLG_ACTIVE|DYNFLG_CHANGED);
DynRegs[i].genreg=0;
}
gen_reinit();
gen_save_host_direct(&cache.block.running,(Bitu)decode.block);
/* Start with the cycles check */
gen_protectflags();
gen_dop_word_imm(DOP_CMP,true,DREG(CYCLES),0);
gen_dop_word(DOP_TEST,true,DREG(CYCLES),DREG(CYCLES));
save_info[used_save_info].branch_pos=gen_create_branch_long(BR_LE);
save_info[used_save_info].type=cycle_check;
used_save_info++;

View file

@ -64,29 +64,29 @@ static void dyn_eatree() {
Bitu group=(decode.modrm.val >> 3) & 7;
switch (group){
case 0x00: /* FADD ST,STi */
gen_call_function((void*)&FPU_FADD_EA,"%Ddr",DREG(TMPB));
gen_call_function((void*)&FPU_FADD_EA,"%Drd",DREG(TMPB));
break;
case 0x01: /* FMUL ST,STi */
gen_call_function((void*)&FPU_FMUL_EA,"%Ddr",DREG(TMPB));
gen_call_function((void*)&FPU_FMUL_EA,"%Drd",DREG(TMPB));
break;
case 0x02: /* FCOM STi */
gen_call_function((void*)&FPU_FCOM_EA,"%Ddr",DREG(TMPB));
gen_call_function((void*)&FPU_FCOM_EA,"%Drd",DREG(TMPB));
break;
case 0x03: /* FCOMP STi */
gen_call_function((void*)&FPU_FCOM_EA,"%Ddr",DREG(TMPB));
gen_call_function((void*)&FPU_FCOM_EA,"%Drd",DREG(TMPB));
gen_call_function((void*)&FPU_FPOP,"");
break;
case 0x04: /* FSUB ST,STi */
gen_call_function((void*)&FPU_FSUB_EA,"%Ddr",DREG(TMPB));
gen_call_function((void*)&FPU_FSUB_EA,"%Drd",DREG(TMPB));
break;
case 0x05: /* FSUBR ST,STi */
gen_call_function((void*)&FPU_FSUBR_EA,"%Ddr",DREG(TMPB));
gen_call_function((void*)&FPU_FSUBR_EA,"%Drd",DREG(TMPB));
break;
case 0x06: /* FDIV ST,STi */
gen_call_function((void*)&FPU_FDIV_EA,"%Ddr",DREG(TMPB));
gen_call_function((void*)&FPU_FDIV_EA,"%Drd",DREG(TMPB));
break;
case 0x07: /* FDIVR ST,STi */
gen_call_function((void*)&FPU_FDIVR_EA,"%Ddr",DREG(TMPB));
gen_call_function((void*)&FPU_FDIVR_EA,"%Drd",DREG(TMPB));
break;
default:
break;
@ -101,36 +101,36 @@ static void dyn_fpu_esc0(){
Bitu sub=(decode.modrm.val & 7);
switch (group){
case 0x00: //FADD ST,STi /
gen_call_function((void*)&FPU_FADD,"%Ddr%Ddr",DREG(TMPB),DREG(EA));
gen_call_function((void*)&FPU_FADD,"%Drd%Drd",DREG(TMPB),DREG(EA));
break;
case 0x01: // FMUL ST,STi /
gen_call_function((void*)&FPU_FMUL,"%Ddr%Ddr",DREG(TMPB),DREG(EA));
gen_call_function((void*)&FPU_FMUL,"%Drd%Drd",DREG(TMPB),DREG(EA));
break;
case 0x02: // FCOM STi /
gen_call_function((void*)&FPU_FCOM,"%Ddr%Ddr",DREG(TMPB),DREG(EA));
gen_call_function((void*)&FPU_FCOM,"%Drd%Drd",DREG(TMPB),DREG(EA));
break;
case 0x03: // FCOMP STi /
gen_call_function((void*)&FPU_FCOM,"%Ddr%Ddr",DREG(TMPB),DREG(EA));
gen_call_function((void*)&FPU_FCOM,"%Drd%Drd",DREG(TMPB),DREG(EA));
gen_call_function((void*)&FPU_FPOP,"");
break;
case 0x04: // FSUB ST,STi /
gen_call_function((void*)&FPU_FSUB,"%Ddr%Ddr",DREG(TMPB),DREG(EA));
gen_call_function((void*)&FPU_FSUB,"%Drd%Drd",DREG(TMPB),DREG(EA));
break;
case 0x05: // FSUBR ST,STi /
gen_call_function((void*)&FPU_FSUBR,"%Ddr%Ddr",DREG(TMPB),DREG(EA));
gen_call_function((void*)&FPU_FSUBR,"%Drd%Drd",DREG(TMPB),DREG(EA));
break;
case 0x06: // FDIV ST,STi /
gen_call_function((void*)&FPU_FDIV,"%Ddr%Ddr",DREG(TMPB),DREG(EA));
gen_call_function((void*)&FPU_FDIV,"%Drd%Drd",DREG(TMPB),DREG(EA));
break;
case 0x07: // FDIVR ST,STi /
gen_call_function((void*)&FPU_FDIVR,"%Ddr%Ddr",DREG(TMPB),DREG(EA));
gen_call_function((void*)&FPU_FDIVR,"%Drd%Drd",DREG(TMPB),DREG(EA));
break;
default:
break;
}
} else {
dyn_fill_ea();
gen_call_function((void*)&FPU_FLD_F32_EA,"%Ddr",DREG(EA));
gen_call_function((void*)&FPU_FLD_F32_EA,"%Drd",DREG(EA));
gen_load_host(&TOP,DREG(TMPB),4);
dyn_eatree();
}
@ -149,18 +149,18 @@ static void dyn_fpu_esc1(){
gen_dop_word_imm(DOP_AND,true,DREG(EA),7);
gen_call_function((void*)&FPU_PREP_PUSH,"");
gen_load_host(&TOP,DREG(TMPB),4);
gen_call_function((void*)&FPU_FST,"%Ddr%Ddr",DREG(EA),DREG(TMPB));
gen_call_function((void*)&FPU_FST,"%Drd%Drd",DREG(EA),DREG(TMPB));
break;
case 0x01: /* FXCH STi */
dyn_fpu_top();
gen_call_function((void*)&FPU_FXCH,"%Ddr%Ddr",DREG(TMPB),DREG(EA));
gen_call_function((void*)&FPU_FXCH,"%Drd%Drd",DREG(TMPB),DREG(EA));
break;
case 0x02: /* FNOP */
gen_call_function((void*)&FPU_FNOP,"");
break;
case 0x03: /* FSTP STi */
dyn_fpu_top();
gen_call_function((void*)&FPU_FST,"%Ddr%Ddr",DREG(TMPB),DREG(EA));
gen_call_function((void*)&FPU_FST,"%Drd%Drd",DREG(TMPB),DREG(EA));
gen_call_function((void*)&FPU_FPOP,"");
break;
case 0x04:
@ -290,29 +290,29 @@ static void dyn_fpu_esc1(){
gen_protectflags();
gen_call_function((void*)&FPU_PREP_PUSH,"");
gen_load_host(&TOP,DREG(TMPB),4);
gen_call_function((void*)&FPU_FLD_F32,"%Ddr%Ddr",DREG(EA),DREG(TMPB));
gen_call_function((void*)&FPU_FLD_F32,"%Drd%Drd",DREG(EA),DREG(TMPB));
break;
case 0x01: /* UNKNOWN */
LOG(LOG_FPU,LOG_WARN)("ESC EA 1:Unhandled group %d subfunction %d",group,sub);
break;
case 0x02: /* FST float*/
gen_call_function((void*)&FPU_FST_F32,"%Ddr",DREG(EA));
gen_call_function((void*)&FPU_FST_F32,"%Drd",DREG(EA));
break;
case 0x03: /* FSTP float*/
gen_call_function((void*)&FPU_FST_F32,"%Ddr",DREG(EA));
gen_call_function((void*)&FPU_FST_F32,"%Drd",DREG(EA));
gen_call_function((void*)&FPU_FPOP,"");
break;
case 0x04: /* FLDENV */
gen_call_function((void*)&FPU_FLDENV,"%Ddr",DREG(EA));
gen_call_function((void*)&FPU_FLDENV,"%Drd",DREG(EA));
break;
case 0x05: /* FLDCW */
gen_call_function((void *)&FPU_FLDCW,"%Ddr",DREG(EA));
gen_call_function((void *)&FPU_FLDCW,"%Drd",DREG(EA));
break;
case 0x06: /* FSTENV */
gen_call_function((void *)&FPU_FSTENV,"%Ddr",DREG(EA));
gen_call_function((void *)&FPU_FSTENV,"%Drd",DREG(EA));
break;
case 0x07: /* FNSTCW*/
gen_call_function((void *)&FPU_FNSTCW,"%Ddr",DREG(EA));
gen_call_function((void *)&FPU_FNSTCW,"%Drd",DREG(EA));
break;
default:
LOG(LOG_FPU,LOG_WARN)("ESC EA 1:Unhandled group %d subfunction %d",group,sub);
@ -335,7 +335,7 @@ static void dyn_fpu_esc2(){
gen_dop_word_imm(DOP_ADD,true,DREG(EA),1);
gen_dop_word_imm(DOP_AND,true,DREG(EA),7);
gen_load_host(&TOP,DREG(TMPB),4);
gen_call_function((void *)&FPU_FUCOM,"%Ddr%Ddr",DREG(TMPB),DREG(EA));
gen_call_function((void *)&FPU_FUCOM,"%Drd%Drd",DREG(TMPB),DREG(EA));
gen_call_function((void *)&FPU_FPOP,"");
gen_call_function((void *)&FPU_FPOP,"");
break;
@ -350,7 +350,7 @@ static void dyn_fpu_esc2(){
}
} else {
dyn_fill_ea();
gen_call_function((void*)&FPU_FLD_I32_EA,"%Ddr",DREG(EA));
gen_call_function((void*)&FPU_FLD_I32_EA,"%Drd",DREG(EA));
gen_load_host(&TOP,DREG(TMPB),4);
dyn_eatree();
}
@ -395,24 +395,24 @@ static void dyn_fpu_esc3(){
gen_call_function((void*)&FPU_PREP_PUSH,"");
gen_protectflags();
gen_load_host(&TOP,DREG(TMPB),4);
gen_call_function((void*)&FPU_FLD_I32,"%Ddr%Ddr",DREG(EA),DREG(TMPB));
gen_call_function((void*)&FPU_FLD_I32,"%Drd%Drd",DREG(EA),DREG(TMPB));
break;
case 0x01: /* FISTTP */
LOG(LOG_FPU,LOG_WARN)("ESC 3 EA:Unhandled group %d subfunction %d",group,sub);
break;
case 0x02: /* FIST */
gen_call_function((void*)&FPU_FST_I32,"%Ddr",DREG(EA));
gen_call_function((void*)&FPU_FST_I32,"%Drd",DREG(EA));
break;
case 0x03: /* FISTP */
gen_call_function((void*)&FPU_FST_I32,"%Ddr",DREG(EA));
gen_call_function((void*)&FPU_FST_I32,"%Drd",DREG(EA));
gen_call_function((void*)&FPU_FPOP,"");
break;
case 0x05: /* FLD 80 Bits Real */
gen_call_function((void*)&FPU_PREP_PUSH,"");
gen_call_function((void*)&FPU_FLD_F80,"%Ddr",DREG(EA));
gen_call_function((void*)&FPU_FLD_F80,"%Drd",DREG(EA));
break;
case 0x07: /* FSTP 80 Bits Real */
gen_call_function((void*)&FPU_FST_F80,"%Ddr",DREG(EA));
gen_call_function((void*)&FPU_FST_F80,"%Drd",DREG(EA));
gen_call_function((void*)&FPU_FPOP,"");
break;
default:
@ -429,36 +429,36 @@ static void dyn_fpu_esc4(){
dyn_fpu_top();
switch(group){
case 0x00: /* FADD STi,ST*/
gen_call_function((void*)&FPU_FADD,"%Ddr%Ddr",DREG(EA),DREG(TMPB));
gen_call_function((void*)&FPU_FADD,"%Drd%Drd",DREG(EA),DREG(TMPB));
break;
case 0x01: /* FMUL STi,ST*/
gen_call_function((void*)&FPU_FMUL,"%Ddr%Ddr",DREG(EA),DREG(TMPB));
gen_call_function((void*)&FPU_FMUL,"%Drd%Drd",DREG(EA),DREG(TMPB));
break;
case 0x02: /* FCOM*/
gen_call_function((void*)&FPU_FCOM,"%Ddr%Ddr",DREG(TMPB),DREG(EA));
gen_call_function((void*)&FPU_FCOM,"%Drd%Drd",DREG(TMPB),DREG(EA));
break;
case 0x03: /* FCOMP*/
gen_call_function((void*)&FPU_FCOM,"%Ddr%Ddr",DREG(TMPB),DREG(EA));
gen_call_function((void*)&FPU_FCOM,"%Drd%Drd",DREG(TMPB),DREG(EA));
gen_call_function((void*)&FPU_FPOP,"");
break;
case 0x04: /* FSUBR STi,ST*/
gen_call_function((void*)&FPU_FSUBR,"%Ddr%Ddr",DREG(EA),DREG(TMPB));
gen_call_function((void*)&FPU_FSUBR,"%Drd%Drd",DREG(EA),DREG(TMPB));
break;
case 0x05: /* FSUB STi,ST*/
gen_call_function((void*)&FPU_FSUB,"%Ddr%Ddr",DREG(EA),DREG(TMPB));
gen_call_function((void*)&FPU_FSUB,"%Drd%Drd",DREG(EA),DREG(TMPB));
break;
case 0x06: /* FDIVR STi,ST*/
gen_call_function((void*)&FPU_FDIVR,"%Ddr%Ddr",DREG(EA),DREG(TMPB));
gen_call_function((void*)&FPU_FDIVR,"%Drd%Drd",DREG(EA),DREG(TMPB));
break;
case 0x07: /* FDIV STi,ST*/
gen_call_function((void*)&FPU_FDIV,"%Ddr%Ddr",DREG(EA),DREG(TMPB));
gen_call_function((void*)&FPU_FDIV,"%Drd%Drd",DREG(EA),DREG(TMPB));
break;
default:
break;
}
} else {
dyn_fill_ea();
gen_call_function((void*)&FPU_FLD_F64_EA,"%Ddr",DREG(EA));
gen_call_function((void*)&FPU_FLD_F64_EA,"%Drd",DREG(EA));
gen_load_host(&TOP,DREG(TMPB),4);
dyn_eatree();
}
@ -472,23 +472,23 @@ static void dyn_fpu_esc5(){
dyn_fpu_top();
switch(group){
case 0x00: /* FFREE STi */
gen_call_function((void*)&FPU_FFREE,"%Ddr",DREG(EA));
gen_call_function((void*)&FPU_FFREE,"%Drd",DREG(EA));
break;
case 0x01: /* FXCH STi*/
gen_call_function((void*)&FPU_FXCH,"%Ddr%Ddr",DREG(TMPB),DREG(EA));
gen_call_function((void*)&FPU_FXCH,"%Drd%Drd",DREG(TMPB),DREG(EA));
break;
case 0x02: /* FST STi */
gen_call_function((void*)&FPU_FST,"%Ddr%Ddr",DREG(TMPB),DREG(EA));
gen_call_function((void*)&FPU_FST,"%Drd%Drd",DREG(TMPB),DREG(EA));
break;
case 0x03: /* FSTP STi*/
gen_call_function((void*)&FPU_FST,"%Ddr%Ddr",DREG(TMPB),DREG(EA));
gen_call_function((void*)&FPU_FST,"%Drd%Drd",DREG(TMPB),DREG(EA));
gen_call_function((void*)&FPU_FPOP,"");
break;
case 0x04: /* FUCOM STi */
gen_call_function((void*)&FPU_FUCOM,"%Ddr%Ddr",DREG(TMPB),DREG(EA));
gen_call_function((void*)&FPU_FUCOM,"%Drd%Drd",DREG(TMPB),DREG(EA));
break;
case 0x05: /*FUCOMP STi */
gen_call_function((void*)&FPU_FUCOM,"%Ddr%Ddr",DREG(TMPB),DREG(EA));
gen_call_function((void*)&FPU_FUCOM,"%Drd%Drd",DREG(TMPB),DREG(EA));
gen_call_function((void*)&FPU_FPOP,"");
break;
default:
@ -504,30 +504,30 @@ static void dyn_fpu_esc5(){
gen_call_function((void*)&FPU_PREP_PUSH,"");
gen_protectflags();
gen_load_host(&TOP,DREG(TMPB),4);
gen_call_function((void*)&FPU_FLD_F64,"%Ddr%Ddr",DREG(EA),DREG(TMPB));
gen_call_function((void*)&FPU_FLD_F64,"%Drd%Drd",DREG(EA),DREG(TMPB));
break;
case 0x01: /* FISTTP longint*/
LOG(LOG_FPU,LOG_WARN)("ESC 5 EA:Unhandled group %d subfunction %d",group,sub);
break;
case 0x02: /* FST double real*/
gen_call_function((void*)&FPU_FST_F64,"%Ddr",DREG(EA));
gen_call_function((void*)&FPU_FST_F64,"%Drd",DREG(EA));
break;
case 0x03: /* FSTP double real*/
gen_call_function((void*)&FPU_FST_F64,"%Ddr",DREG(EA));
gen_call_function((void*)&FPU_FST_F64,"%Drd",DREG(EA));
gen_call_function((void*)&FPU_FPOP,"");
break;
case 0x04: /* FRSTOR */
gen_call_function((void*)&FPU_FRSTOR,"%Ddr",DREG(EA));
gen_call_function((void*)&FPU_FRSTOR,"%Drd",DREG(EA));
break;
case 0x06: /* FSAVE */
gen_call_function((void*)&FPU_FSAVE,"%Ddr",DREG(EA));
gen_call_function((void*)&FPU_FSAVE,"%Drd",DREG(EA));
break;
case 0x07: /*FNSTSW */
gen_protectflags();
gen_load_host(&TOP,DREG(TMPB),4);
gen_call_function((void*)&FPU_SET_TOP,"%Dd",DREG(TMPB));
gen_load_host(&fpu.sw,DREG(TMPB),4);
gen_call_function((void*)&mem_writew,"%Ddr%Ddr",DREG(EA),DREG(TMPB));
gen_call_function((void*)&mem_writew,"%Drd%Drd",DREG(EA),DREG(TMPB));
break;
default:
LOG(LOG_FPU,LOG_WARN)("ESC 5 EA:Unhandled group %d subfunction %d",group,sub);
@ -543,13 +543,13 @@ static void dyn_fpu_esc6(){
dyn_fpu_top();
switch(group){
case 0x00: /*FADDP STi,ST*/
gen_call_function((void*)&FPU_FADD,"%Ddr%Ddr",DREG(EA),DREG(TMPB));
gen_call_function((void*)&FPU_FADD,"%Drd%Drd",DREG(EA),DREG(TMPB));
break;
case 0x01: /* FMULP STi,ST*/
gen_call_function((void*)&FPU_FMUL,"%Ddr%Ddr",DREG(EA),DREG(TMPB));
gen_call_function((void*)&FPU_FMUL,"%Drd%Drd",DREG(EA),DREG(TMPB));
break;
case 0x02: /* FCOMP5*/
gen_call_function((void*)&FPU_FCOM,"%Ddr%Ddr",DREG(TMPB),DREG(EA));
gen_call_function((void*)&FPU_FCOM,"%Drd%Drd",DREG(TMPB),DREG(EA));
break; /* TODO IS THIS ALLRIGHT ????????? */
case 0x03: /*FCOMPP*/
if(sub != 1) {
@ -559,20 +559,20 @@ static void dyn_fpu_esc6(){
gen_load_host(&TOP,DREG(EA),4);
gen_dop_word_imm(DOP_ADD,true,DREG(EA),1);
gen_dop_word_imm(DOP_AND,true,DREG(EA),7);
gen_call_function((void*)&FPU_FCOM,"%Ddr%Ddr",DREG(TMPB),DREG(EA));
gen_call_function((void*)&FPU_FCOM,"%Drd%Drd",DREG(TMPB),DREG(EA));
gen_call_function((void*)&FPU_FPOP,""); /* extra pop at the bottom*/
break;
case 0x04: /* FSUBRP STi,ST*/
gen_call_function((void*)&FPU_FSUBR,"%Ddr%Ddr",DREG(EA),DREG(TMPB));
gen_call_function((void*)&FPU_FSUBR,"%Drd%Drd",DREG(EA),DREG(TMPB));
break;
case 0x05: /* FSUBP STi,ST*/
gen_call_function((void*)&FPU_FSUB,"%Ddr%Ddr",DREG(EA),DREG(TMPB));
gen_call_function((void*)&FPU_FSUB,"%Drd%Drd",DREG(EA),DREG(TMPB));
break;
case 0x06: /* FDIVRP STi,ST*/
gen_call_function((void*)&FPU_FDIVR,"%Ddr%Ddr",DREG(EA),DREG(TMPB));
gen_call_function((void*)&FPU_FDIVR,"%Drd%Drd",DREG(EA),DREG(TMPB));
break;
case 0x07: /* FDIVP STi,ST*/
gen_call_function((void*)&FPU_FDIV,"%Ddr%Ddr",DREG(EA),DREG(TMPB));
gen_call_function((void*)&FPU_FDIV,"%Drd%Drd",DREG(EA),DREG(TMPB));
break;
default:
break;
@ -580,7 +580,7 @@ static void dyn_fpu_esc6(){
gen_call_function((void*)&FPU_FPOP,"");
} else {
dyn_fill_ea();
gen_call_function((void*)&FPU_FLD_I16_EA,"%Ddr",DREG(EA));
gen_call_function((void*)&FPU_FLD_I16_EA,"%Drd",DREG(EA));
gen_load_host(&TOP,DREG(TMPB),4);
dyn_eatree();
}
@ -594,24 +594,24 @@ static void dyn_fpu_esc7(){
switch (group){
case 0x00: /* FFREEP STi*/
dyn_fpu_top();
gen_call_function((void*)&FPU_FFREE,"%Ddr",DREG(EA));
gen_call_function((void*)&FPU_FFREE,"%Drd",DREG(EA));
gen_call_function((void*)&FPU_FPOP,"");
break;
case 0x01: /* FXCH STi*/
dyn_fpu_top();
gen_call_function((void*)&FPU_FXCH,"%Ddr%Ddr",DREG(TMPB),DREG(EA));
gen_call_function((void*)&FPU_FXCH,"%Drd%Drd",DREG(TMPB),DREG(EA));
break;
case 0x02: /* FSTP STi*/
case 0x03: /* FSTP STi*/
dyn_fpu_top();
gen_call_function((void*)&FPU_FST,"%Ddr%Ddr",DREG(TMPB),DREG(EA));
gen_call_function((void*)&FPU_FST,"%Drd%Drd",DREG(TMPB),DREG(EA));
gen_call_function((void*)&FPU_FPOP,"");
break;
case 0x04:
switch(sub){
case 0x00: /* FNSTSW AX*/
gen_load_host(&TOP,DREG(TMPB),4);
gen_call_function((void*)&FPU_SET_TOP,"%Ddr",DREG(TMPB));
gen_call_function((void*)&FPU_SET_TOP,"%Drd",DREG(TMPB));
gen_mov_host(&fpu.sw,DREG(EAX),2);
break;
default:
@ -629,34 +629,34 @@ static void dyn_fpu_esc7(){
case 0x00: /* FILD Bit16s */
gen_call_function((void*)&FPU_PREP_PUSH,"");
gen_load_host(&TOP,DREG(TMPB),4);
gen_call_function((void*)&FPU_FLD_I16,"%Ddr%Ddr",DREG(EA),DREG(TMPB));
gen_call_function((void*)&FPU_FLD_I16,"%Drd%Drd",DREG(EA),DREG(TMPB));
break;
case 0x01:
LOG(LOG_FPU,LOG_WARN)("ESC 7 EA:Unhandled group %d subfunction %d",group,sub);
break;
case 0x02: /* FIST Bit16s */
gen_call_function((void*)&FPU_FST_I16,"%Ddr",DREG(EA));
gen_call_function((void*)&FPU_FST_I16,"%Drd",DREG(EA));
break;
case 0x03: /* FISTP Bit16s */
gen_call_function((void*)&FPU_FST_I16,"%Ddr",DREG(EA));
gen_call_function((void*)&FPU_FST_I16,"%Drd",DREG(EA));
gen_call_function((void*)&FPU_FPOP,"");
break;
case 0x04: /* FBLD packed BCD */
gen_call_function((void*)&FPU_PREP_PUSH,"");
gen_load_host(&TOP,DREG(TMPB),4);
gen_call_function((void*)&FPU_FBLD,"%Ddr%Ddr",DREG(EA),DREG(TMPB));
gen_call_function((void*)&FPU_FBLD,"%Drd%Drd",DREG(EA),DREG(TMPB));
break;
case 0x05: /* FILD Bit64s */
gen_call_function((void*)&FPU_PREP_PUSH,"");
gen_load_host(&TOP,DREG(TMPB),4);
gen_call_function((void*)&FPU_FLD_I64,"%Ddr%Ddr",DREG(EA),DREG(TMPB));
gen_call_function((void*)&FPU_FLD_I64,"%Drd%Drd",DREG(EA),DREG(TMPB));
break;
case 0x06: /* FBSTP packed BCD */
gen_call_function((void*)&FPU_FBST,"%Ddr",DREG(EA));
gen_call_function((void*)&FPU_FBST,"%Drd",DREG(EA));
gen_call_function((void*)&FPU_FPOP,"");
break;
case 0x07: /* FISTP Bit64s */
gen_call_function((void*)&FPU_FST_I64,"%Ddr",DREG(EA));
gen_call_function((void*)&FPU_FST_I64,"%Drd",DREG(EA));
gen_call_function((void*)&FPU_FPOP,"");
break;
default:

View file

@ -148,6 +148,16 @@ static void FPU_FRSTOR_DH(PhysPt addr){
}
}
static void dh_fpu_mem(Bit8u inst, Bitu reg=decode.modrm.reg, void* mem=&dyn_dh_fpu.temp.m1) {
#if C_TARGETCPU == X86
cache_addb(inst);
cache_addb(0x05|(reg<<3));
cache_addd((Bit32u)(mem));
#else // X86_64
opcode(reg).setabsaddr(mem).Emit8(inst);
#endif
}
static void dh_fpu_esc0(){
dyn_get_modrm();
if (decode.modrm.val >= 0xc0) {
@ -155,10 +165,8 @@ static void dh_fpu_esc0(){
cache_addb(decode.modrm.val);
} else {
dyn_fill_ea();
gen_call_function((void*)&FPU_FLD_32,"%Ddr",DREG(EA));
cache_addb(0xd8);
cache_addb(0x05|(decode.modrm.reg<<3));
cache_addd((Bit32u)(&(dyn_dh_fpu.temp.m1)));
gen_call_function((void*)&FPU_FLD_32,"%Drd",DREG(EA));
dh_fpu_mem(0xd8);
}
}
@ -173,46 +181,34 @@ static void dh_fpu_esc1(){
dyn_fill_ea();
switch(group){
case 0x00: /* FLD float*/
gen_call_function((void*)&FPU_FLD_32,"%Ddr",DREG(EA));
cache_addb(0xd9);
cache_addb(0x05|(decode.modrm.reg<<3));
cache_addd((Bit32u)(&(dyn_dh_fpu.temp.m1)));
gen_call_function((void*)&FPU_FLD_32,"%Drd",DREG(EA));
dh_fpu_mem(0xd9);
break;
case 0x01: /* UNKNOWN */
LOG(LOG_FPU,LOG_WARN)("ESC EA 1:Unhandled group %d subfunction %d",group,sub);
break;
case 0x02: /* FST float*/
cache_addb(0xd9);
cache_addb(0x05|(decode.modrm.reg<<3));
cache_addd((Bit32u)(&(dyn_dh_fpu.temp.m1)));
gen_call_function((void*)&FPU_FST_32,"%Ddr",DREG(EA));
dh_fpu_mem(0xd9);
gen_call_function((void*)&FPU_FST_32,"%Drd",DREG(EA));
break;
case 0x03: /* FSTP float*/
cache_addb(0xd9);
cache_addb(0x05|(decode.modrm.reg<<3));
cache_addd((Bit32u)(&(dyn_dh_fpu.temp.m1)));
gen_call_function((void*)&FPU_FST_32,"%Ddr",DREG(EA));
dh_fpu_mem(0xd9);
gen_call_function((void*)&FPU_FST_32,"%Drd",DREG(EA));
break;
case 0x04: /* FLDENV */
gen_call_function((void*)&FPU_FLDENV_DH,"%Ddr",DREG(EA));
cache_addb(0xd9);
cache_addb(0x05|(decode.modrm.reg<<3));
cache_addd((Bit32u)(&(dyn_dh_fpu.temp.m1)));
gen_call_function((void*)&FPU_FLDENV_DH,"%Drd",DREG(EA));
dh_fpu_mem(0xd9);
break;
case 0x05: /* FLDCW */
gen_call_function((void *)&FPU_FLDCW_DH,"%Ddr",DREG(EA));
cache_addb(0xd9);
cache_addb(0x05|(decode.modrm.reg<<3));
cache_addd((Bit32u)(&(dyn_dh_fpu.temp.m1)));
gen_call_function((void *)&FPU_FLDCW_DH,"%Drd",DREG(EA));
dh_fpu_mem(0xd9);
break;
case 0x06: /* FSTENV */
cache_addb(0xd9);
cache_addb(0x05|(decode.modrm.reg<<3));
cache_addd((Bit32u)(&(dyn_dh_fpu.temp.m1)));
gen_call_function((void*)&FPU_FSTENV_DH,"%Ddr",DREG(EA));
dh_fpu_mem(0xd9);
gen_call_function((void*)&FPU_FSTENV_DH,"%Drd",DREG(EA));
break;
case 0x07: /* FNSTCW*/
gen_call_function((void*)&FPU_FNSTCW_DH,"%Ddr",DREG(EA));
gen_call_function((void*)&FPU_FNSTCW_DH,"%Drd",DREG(EA));
break;
default:
LOG(LOG_FPU,LOG_WARN)("ESC EA 1:Unhandled group %d subfunction %d",group,sub);
@ -228,10 +224,8 @@ static void dh_fpu_esc2(){
cache_addb(decode.modrm.val);
} else {
dyn_fill_ea();
gen_call_function((void*)&FPU_FLD_32,"%Ddr",DREG(EA));
cache_addb(0xda);
cache_addb(0x05|(decode.modrm.reg<<3));
cache_addd((Bit32u)(&(dyn_dh_fpu.temp.m1)));
gen_call_function((void*)&FPU_FLD_32,"%Drd",DREG(EA));
dh_fpu_mem(0xda);
}
}
@ -274,37 +268,27 @@ static void dh_fpu_esc3(){
dyn_fill_ea();
switch(group){
case 0x00: /* FILD */
gen_call_function((void*)&FPU_FLD_32,"%Ddr",DREG(EA));
cache_addb(0xdb);
cache_addb(0x05|(decode.modrm.reg<<3));
cache_addd((Bit32u)(&(dyn_dh_fpu.temp.m1)));
gen_call_function((void*)&FPU_FLD_32,"%Drd",DREG(EA));
dh_fpu_mem(0xdb);
break;
case 0x01: /* FISTTP */
LOG(LOG_FPU,LOG_WARN)("ESC 3 EA:Unhandled group %d subfunction %d",group,sub);
break;
case 0x02: /* FIST */
cache_addb(0xdb);
cache_addb(0x05|(decode.modrm.reg<<3));
cache_addd((Bit32u)(&(dyn_dh_fpu.temp.m1)));
gen_call_function((void*)&FPU_FST_32,"%Ddr",DREG(EA));
dh_fpu_mem(0xdb);
gen_call_function((void*)&FPU_FST_32,"%Drd",DREG(EA));
break;
case 0x03: /* FISTP */
cache_addb(0xdb);
cache_addb(0x05|(decode.modrm.reg<<3));
cache_addd((Bit32u)(&(dyn_dh_fpu.temp.m1)));
gen_call_function((void*)&FPU_FST_32,"%Ddr",DREG(EA));
dh_fpu_mem(0xdb);
gen_call_function((void*)&FPU_FST_32,"%Drd",DREG(EA));
break;
case 0x05: /* FLD 80 Bits Real */
gen_call_function((void*)&FPU_FLD_80,"%Ddr",DREG(EA));
cache_addb(0xdb);
cache_addb(0x05|(decode.modrm.reg<<3));
cache_addd((Bit32u)(&(dyn_dh_fpu.temp.m1)));
gen_call_function((void*)&FPU_FLD_80,"%Drd",DREG(EA));
dh_fpu_mem(0xdb);
break;
case 0x07: /* FSTP 80 Bits Real */
cache_addb(0xdb);
cache_addb(0x05|(decode.modrm.reg<<3));
cache_addd((Bit32u)(&(dyn_dh_fpu.temp.m1)));
gen_call_function((void*)&FPU_FST_80,"%Ddr",DREG(EA));
dh_fpu_mem(0xdb);
gen_call_function((void*)&FPU_FST_80,"%Drd",DREG(EA));
break;
default:
LOG(LOG_FPU,LOG_WARN)("ESC 3 EA:Unhandled group %d subfunction %d",group,sub);
@ -321,10 +305,8 @@ static void dh_fpu_esc4(){
cache_addb(decode.modrm.val);
} else {
dyn_fill_ea();
gen_call_function((void*)&FPU_FLD_64,"%Ddr",DREG(EA));
cache_addb(0xdc);
cache_addb(0x05|(decode.modrm.reg<<3));
cache_addd((Bit32u)(&(dyn_dh_fpu.temp.m1)));
gen_call_function((void*)&FPU_FLD_64,"%Drd",DREG(EA));
dh_fpu_mem(0xdc);
}
}
@ -339,45 +321,32 @@ static void dh_fpu_esc5(){
Bitu sub=(decode.modrm.val & 7);
switch(group){
case 0x00: /* FLD double real*/
gen_call_function((void*)&FPU_FLD_64,"%Ddr",DREG(EA));
cache_addb(0xdd);
cache_addb(0x05|(decode.modrm.reg<<3));
cache_addd((Bit32u)(&(dyn_dh_fpu.temp.m1)));
gen_call_function((void*)&FPU_FLD_64,"%Drd",DREG(EA));
dh_fpu_mem(0xdd);
break;
case 0x01: /* FISTTP longint*/
LOG(LOG_FPU,LOG_WARN)("ESC 5 EA:Unhandled group %d subfunction %d",group,sub);
break;
case 0x02: /* FST double real*/
cache_addb(0xdd);
cache_addb(0x05|(decode.modrm.reg<<3));
cache_addd((Bit32u)(&(dyn_dh_fpu.temp.m1)));
gen_call_function((void*)&FPU_FST_64,"%Ddr",DREG(EA));
dh_fpu_mem(0xdd);
gen_call_function((void*)&FPU_FST_64,"%Drd",DREG(EA));
break;
case 0x03: /* FSTP double real*/
cache_addb(0xdd);
cache_addb(0x05|(decode.modrm.reg<<3));
cache_addd((Bit32u)(&(dyn_dh_fpu.temp.m1)));
gen_call_function((void*)&FPU_FST_64,"%Ddr",DREG(EA));
dh_fpu_mem(0xdd);
gen_call_function((void*)&FPU_FST_64,"%Drd",DREG(EA));
break;
case 0x04: /* FRSTOR */
gen_call_function((void*)&FPU_FRSTOR_DH,"%Ddr",DREG(EA));
cache_addb(0xdd);
cache_addb(0x05|(decode.modrm.reg<<3));
cache_addd((Bit32u)(&(dyn_dh_fpu.temp_state[0])));
gen_call_function((void*)&FPU_FRSTOR_DH,"%Drd",DREG(EA));
dh_fpu_mem(0xdd, decode.modrm.reg, &(dyn_dh_fpu.temp_state[0]));
break;
case 0x06: /* FSAVE */
cache_addb(0xdd);
cache_addb(0x05|(decode.modrm.reg<<3));
cache_addd((Bit32u)(&(dyn_dh_fpu.temp_state[0])));
gen_call_function((void*)&FPU_FSAVE_DH,"%Ddr",DREG(EA));
cache_addb(0xdb);
cache_addb(0xe3);
dh_fpu_mem(0xdd, decode.modrm.reg, &(dyn_dh_fpu.temp_state[0]));
gen_call_function((void*)&FPU_FSAVE_DH,"%Drd",DREG(EA));
cache_addw(0xE3DB);
break;
case 0x07: /* FNSTSW */
cache_addb(0xdd);
cache_addb(0x05|(decode.modrm.reg<<3));
cache_addd((Bit32u)(&(dyn_dh_fpu.temp.m1)));
gen_call_function((void*)&FPU_FST_16,"%Ddr",DREG(EA));
dh_fpu_mem(0xdd);
gen_call_function((void*)&FPU_FST_16,"%Drd",DREG(EA));
break;
default:
LOG(LOG_FPU,LOG_WARN)("ESC 5 EA:Unhandled group %d subfunction %d",group,sub);
@ -394,10 +363,8 @@ static void dh_fpu_esc6(){
cache_addb(decode.modrm.val);
} else {
dyn_fill_ea();
gen_call_function((void*)&FPU_FLD_16,"%Ddr",DREG(EA));
cache_addb(0xde);
cache_addb(0x05|(decode.modrm.reg<<3));
cache_addd((Bit32u)(&(dyn_dh_fpu.temp.m1)));
gen_call_function((void*)&FPU_FLD_16,"%Drd",DREG(EA));
dh_fpu_mem(0xde);
}
}
@ -423,9 +390,7 @@ static void dh_fpu_esc7(){
case 0x04:
switch(sub){
case 0x00: /* FNSTSW AX*/
cache_addb(0xdd);
cache_addb(0x05|(0x07<<3));
cache_addd((Bit32u)(&(dyn_dh_fpu.temp.m1)));
dh_fpu_mem(0xdd, 7);
gen_load_host(&(dyn_dh_fpu.temp.m1),DREG(TMPB),4);
gen_dop_word(DOP_MOV,false,DREG(EAX),DREG(TMPB));
gen_releasereg(DREG(TMPB));
@ -443,49 +408,35 @@ static void dh_fpu_esc7(){
dyn_fill_ea();
switch(group){
case 0x00: /* FILD Bit16s */
gen_call_function((void*)&FPU_FLD_16,"%Ddr",DREG(EA));
cache_addb(0xdf);
cache_addb(0x05|(decode.modrm.reg<<3));
cache_addd((Bit32u)(&(dyn_dh_fpu.temp.m1)));
gen_call_function((void*)&FPU_FLD_16,"%Drd",DREG(EA));
dh_fpu_mem(0xdf);
break;
case 0x01:
LOG(LOG_FPU,LOG_WARN)("ESC 7 EA:Unhandled group %d subfunction %d",group,sub);
break;
case 0x02: /* FIST Bit16s */
cache_addb(0xdf);
cache_addb(0x05|(decode.modrm.reg<<3));
cache_addd((Bit32u)(&(dyn_dh_fpu.temp.m1)));
gen_call_function((void*)&FPU_FST_16,"%Ddr",DREG(EA));
dh_fpu_mem(0xdf);
gen_call_function((void*)&FPU_FST_16,"%Drd",DREG(EA));
break;
case 0x03: /* FISTP Bit16s */
cache_addb(0xdf);
cache_addb(0x05|(decode.modrm.reg<<3));
cache_addd((Bit32u)(&(dyn_dh_fpu.temp.m1)));
gen_call_function((void*)&FPU_FST_16,"%Ddr",DREG(EA));
dh_fpu_mem(0xdf);
gen_call_function((void*)&FPU_FST_16,"%Drd",DREG(EA));
break;
case 0x04: /* FBLD packed BCD */
gen_call_function((void*)&FPU_FLD_80,"%Ddr",DREG(EA));
cache_addb(0xdf);
cache_addb(0x05|(decode.modrm.reg<<3));
cache_addd((Bit32u)(&(dyn_dh_fpu.temp.m1)));
gen_call_function((void*)&FPU_FLD_80,"%Drd",DREG(EA));
dh_fpu_mem(0xdf);
break;
case 0x05: /* FILD Bit64s */
gen_call_function((void*)&FPU_FLD_64,"%Ddr",DREG(EA));
cache_addb(0xdf);
cache_addb(0x05|(decode.modrm.reg<<3));
cache_addd((Bit32u)(&(dyn_dh_fpu.temp.m1)));
gen_call_function((void*)&FPU_FLD_64,"%Drd",DREG(EA));
dh_fpu_mem(0xdf);
break;
case 0x06: /* FBSTP packed BCD */
cache_addb(0xdf);
cache_addb(0x05|(decode.modrm.reg<<3));
cache_addd((Bit32u)(&(dyn_dh_fpu.temp.m1)));
gen_call_function((void*)&FPU_FST_80,"%Ddr",DREG(EA));
dh_fpu_mem(0xdf);
gen_call_function((void*)&FPU_FST_80,"%Drd",DREG(EA));
break;
case 0x07: /* FISTP Bit64s */
cache_addb(0xdf);
cache_addb(0x05|(decode.modrm.reg<<3));
cache_addd((Bit32u)(&(dyn_dh_fpu.temp.m1)));
gen_call_function((void*)&FPU_FST_64,"%Ddr",DREG(EA));
dh_fpu_mem(0xdf);
gen_call_function((void*)&FPU_FST_64,"%Drd",DREG(EA));
break;
default:
LOG(LOG_FPU,LOG_WARN)("ESC 7 EA:Unhandled group %d subfunction %d",group,sub);

View file

@ -40,8 +40,8 @@ static bool dyn_helper_idivb(Bit8s val) {
static bool dyn_helper_divw(Bit16u val) {
if (!val) return CPU_PrepareException(0,0);
Bitu num=(reg_dx<<16)|reg_ax;
Bitu quo=num/val;
Bit32u num=(((Bit32u)reg_dx)<<16)|reg_ax;
Bit32u quo=num/val;
Bit16u rem=(Bit16u)(num % val);
Bit16u quo16=(Bit16u)(quo&0xffff);
if (quo!=(Bit32u)quo16) return CPU_PrepareException(0,0);
@ -52,8 +52,8 @@ static bool dyn_helper_divw(Bit16u val) {
static bool dyn_helper_idivw(Bit16s val) {
if (!val) return CPU_PrepareException(0,0);
Bits num=(reg_dx<<16)|reg_ax;
Bits quo=num/val;
Bit32s num=(((Bit32u)reg_dx)<<16)|reg_ax;
Bit32s quo=num/val;
Bit16s rem=(Bit16s)(num % val);
Bit16s quo16s=(Bit16s)quo;
if (quo!=(Bit32s)quo16s) return CPU_PrepareException(0,0);

File diff suppressed because it is too large Load diff

View file

@ -1069,4 +1069,28 @@ static void gen_init(void) {
x86gen.regs[X86_REG_EDI]=new GenReg(7);
}
#if defined(X86_DYNFPU_DH_ENABLED)
static void gen_dh_fpu_save(void)
#if defined (_MSC_VER)
{
__asm {
__asm fnsave dyn_dh_fpu.state
__asm fldcw dyn_dh_fpu.host_cw
}
dyn_dh_fpu.state_used=false;
dyn_dh_fpu.state.cw|=0x3f;
}
#else
{
__asm__ volatile (
"fnsave %0 \n"
"fldcw %1 \n"
: "=m" (dyn_dh_fpu.state)
: "m" (dyn_dh_fpu.host_cw)
: "memory"
);
dyn_dh_fpu.state_used=false;
dyn_dh_fpu.state.cw|=0x3f;
}
#endif
#endif

View file

@ -82,7 +82,7 @@ static void dyn_string(STRING_OP op) {
Bit8u * rep_ecx_jmp;
/* Check if ECX!=zero */
if (decode.rep) {
gen_dop_word(DOP_OR,decode.big_addr,DREG(ECX),DREG(ECX));
gen_dop_word(DOP_TEST,decode.big_addr,DREG(ECX),DREG(ECX));
rep_ecx_jmp=gen_create_branch_long(BR_Z);
}
if (usesi) {
@ -99,11 +99,11 @@ static void dyn_string(STRING_OP op) {
}
switch (op) {
case STR_OUTSB:
gen_call_function((void*)&IO_WriteB,"%Id%Dl",DREG(EDX),tmp_reg);break;
gen_call_function((void*)&IO_WriteB,"%Dw%Dl",DREG(EDX),tmp_reg);break;
case STR_OUTSW:
gen_call_function((void*)&IO_WriteW,"%Id%Dw",DREG(EDX),tmp_reg);break;
gen_call_function((void*)&IO_WriteW,"%Dw%Dw",DREG(EDX),tmp_reg);break;
case STR_OUTSD:
gen_call_function((void*)&IO_WriteD,"%Id%Dd",DREG(EDX),tmp_reg);break;
gen_call_function((void*)&IO_WriteD,"%Dw%Dd",DREG(EDX),tmp_reg);break;
}
}
if (usedi) {