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:
parent
dda3b2a51f
commit
fe177b4136
11 changed files with 1793 additions and 439 deletions
19
configure.ac
19
configure.ac
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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++;
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
1272
src/cpu/core_dyn_x86/risc_x64.h
Normal file
1272
src/cpu/core_dyn_x86/risc_x64.h
Normal file
File diff suppressed because it is too large
Load diff
|
@ -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
|
||||
|
|
|
@ -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) {
|
||||
|
|
Loading…
Add table
Reference in a new issue