avoid code invalidation on certain types of self modification and adjust cache sizes (dynamic core);
add partial memory function inlining for dynamic core memory access; remove a float div in the pic Imported-from: https://svn.code.sf.net/p/dosbox/code-0/dosbox/trunk@2769
This commit is contained in:
parent
6296e3fff4
commit
76f1d11252
6 changed files with 815 additions and 80 deletions
|
@ -40,6 +40,10 @@ INLINE float PIC_TickIndex(void) {
|
|||
return (CPU_CycleMax-CPU_CycleLeft-CPU_Cycles)/(float)CPU_CycleMax;
|
||||
}
|
||||
|
||||
INLINE Bits PIC_TickIndexND(void) {
|
||||
return CPU_CycleMax-CPU_CycleLeft-CPU_Cycles;
|
||||
}
|
||||
|
||||
INLINE Bits PIC_MakeCycles(double amount) {
|
||||
return (Bits)(CPU_CycleMax*amount);
|
||||
}
|
||||
|
|
|
@ -46,8 +46,8 @@
|
|||
#include "fpu.h"
|
||||
|
||||
#define CACHE_MAXSIZE (4096*2)
|
||||
#define CACHE_PAGES (128*8)
|
||||
#define CACHE_TOTAL (CACHE_PAGES*4096)
|
||||
#define CACHE_TOTAL (1024*1024*8)
|
||||
#define CACHE_PAGES (512)
|
||||
#define CACHE_BLOCKS (64*1024)
|
||||
#define CACHE_ALIGN (16)
|
||||
#define DYN_HASH_SHIFT (4)
|
||||
|
@ -161,7 +161,8 @@ static void IllegalOption(const char* msg) {
|
|||
#include "core_dyn_x86/cache.h"
|
||||
|
||||
static struct {
|
||||
Bitu callback,readdata;
|
||||
Bitu callback;
|
||||
Bit32u readdata;
|
||||
} core_dyn;
|
||||
|
||||
struct {
|
||||
|
@ -273,7 +274,20 @@ restart_core:
|
|||
/* Find correct Dynamic Block to run */
|
||||
CacheBlock * block=chandler->FindCacheBlock(ip_point&4095);
|
||||
if (!block) {
|
||||
block=CreateCacheBlock(chandler,ip_point,32);
|
||||
if (!chandler->invalidation_map || (chandler->invalidation_map[ip_point&4095]<4)) {
|
||||
block=CreateCacheBlock(chandler,ip_point,32);
|
||||
} else {
|
||||
Bitu old_cycles=CPU_Cycles;
|
||||
CPU_Cycles=1;
|
||||
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;
|
||||
}
|
||||
CPU_CycleLeft+=old_cycles;
|
||||
return nc_retcode;
|
||||
}
|
||||
}
|
||||
run_block:
|
||||
cache.block.running=0;
|
||||
|
|
|
@ -28,7 +28,6 @@ public:
|
|||
CacheBlock * crossblock;
|
||||
};
|
||||
|
||||
class CacheBlock;
|
||||
static struct {
|
||||
struct {
|
||||
CacheBlock * first;
|
||||
|
@ -44,9 +43,11 @@ static struct {
|
|||
|
||||
static CacheBlock link_blocks[2];
|
||||
|
||||
class CodePageHandler :public PageHandler {
|
||||
class CodePageHandler : public PageHandler {
|
||||
public:
|
||||
CodePageHandler() {}
|
||||
CodePageHandler() {
|
||||
invalidation_map=NULL;
|
||||
}
|
||||
void SetupAt(Bitu _phys_page,PageHandler * _old_pagehandler) {
|
||||
phys_page=_phys_page;
|
||||
old_pagehandler=_old_pagehandler;
|
||||
|
@ -56,6 +57,10 @@ public:
|
|||
active_count=16;
|
||||
memset(&hash_map,0,sizeof(hash_map));
|
||||
memset(&write_map,0,sizeof(write_map));
|
||||
if (invalidation_map!=NULL) {
|
||||
free(invalidation_map);
|
||||
invalidation_map=NULL;
|
||||
}
|
||||
}
|
||||
bool InvalidateRange(Bitu start,Bitu end) {
|
||||
Bits index=1+(start>>DYN_HASH_SHIFT);
|
||||
|
@ -81,69 +86,114 @@ public:
|
|||
}
|
||||
void writeb(PhysPt addr,Bitu val){
|
||||
addr&=4095;
|
||||
if (host_readb(hostmem+addr)==(Bit8u)val) return;
|
||||
host_writeb(hostmem+addr,val);
|
||||
if (!*(Bit8u*)&write_map[addr]) {
|
||||
if (active_blocks) return;
|
||||
active_count--;
|
||||
if (!active_count) Release();
|
||||
} else InvalidateRange(addr,addr);
|
||||
return;
|
||||
} else if (!invalidation_map) {
|
||||
invalidation_map=(Bit8u*)malloc(4096);
|
||||
memset(invalidation_map,0,4096);
|
||||
}
|
||||
invalidation_map[addr]++;
|
||||
InvalidateRange(addr,addr);
|
||||
}
|
||||
void writew(PhysPt addr,Bitu val){
|
||||
addr&=4095;
|
||||
if (host_readw(hostmem+addr)==(Bit16u)val) return;
|
||||
host_writew(hostmem+addr,val);
|
||||
if (!*(Bit16u*)&write_map[addr]) {
|
||||
if (active_blocks) return;
|
||||
active_count--;
|
||||
if (!active_count) Release();
|
||||
} else InvalidateRange(addr,addr+1);
|
||||
return;
|
||||
} else if (!invalidation_map) {
|
||||
invalidation_map=(Bit8u*)malloc(4096);
|
||||
memset(invalidation_map,0,4096);
|
||||
}
|
||||
(*(Bit16u*)&invalidation_map[addr])+=0x101;
|
||||
InvalidateRange(addr,addr+1);
|
||||
}
|
||||
void writed(PhysPt addr,Bitu val){
|
||||
addr&=4095;
|
||||
if (host_readd(hostmem+addr)==(Bit32u)val) return;
|
||||
host_writed(hostmem+addr,val);
|
||||
if (!*(Bit32u*)&write_map[addr]) {
|
||||
if (active_blocks) return;
|
||||
active_count--;
|
||||
if (!active_count) Release();
|
||||
} else InvalidateRange(addr,addr+3);
|
||||
return;
|
||||
} else if (!invalidation_map) {
|
||||
invalidation_map=(Bit8u*)malloc(4096);
|
||||
memset(invalidation_map,0,4096);
|
||||
}
|
||||
(*(Bit32u*)&invalidation_map[addr])+=0x1010101;
|
||||
InvalidateRange(addr,addr+3);
|
||||
}
|
||||
bool writeb_checked(PhysPt addr,Bitu val) {
|
||||
addr&=4095;
|
||||
if (host_readb(hostmem+addr)==(Bit8u)val) return false;
|
||||
if (!*(Bit8u*)&write_map[addr]) {
|
||||
if (!active_blocks) {
|
||||
active_count--;
|
||||
if (!active_count) Release();
|
||||
}
|
||||
} else if (InvalidateRange(addr,addr)) {
|
||||
cpu.exception.which=SMC_CURRENT_BLOCK;
|
||||
return true;
|
||||
} else {
|
||||
if (!invalidation_map) {
|
||||
invalidation_map=(Bit8u*)malloc(4096);
|
||||
memset(invalidation_map,0,4096);
|
||||
}
|
||||
invalidation_map[addr]++;
|
||||
if (InvalidateRange(addr,addr)) {
|
||||
cpu.exception.which=SMC_CURRENT_BLOCK;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
host_writeb(hostmem+addr,val);
|
||||
return false;
|
||||
}
|
||||
bool writew_checked(PhysPt addr,Bitu val) {
|
||||
addr&=4095;
|
||||
if (host_readw(hostmem+addr)==(Bit16u)val) return false;
|
||||
if (!*(Bit16u*)&write_map[addr]) {
|
||||
if (!active_blocks) {
|
||||
active_count--;
|
||||
if (!active_count) Release();
|
||||
}
|
||||
} else if (InvalidateRange(addr,addr+1)) {
|
||||
cpu.exception.which=SMC_CURRENT_BLOCK;
|
||||
return true;
|
||||
} else {
|
||||
if (!invalidation_map) {
|
||||
invalidation_map=(Bit8u*)malloc(4096);
|
||||
memset(invalidation_map,0,4096);
|
||||
}
|
||||
(*(Bit16u*)&invalidation_map[addr])+=0x101;
|
||||
if (InvalidateRange(addr,addr+1)) {
|
||||
cpu.exception.which=SMC_CURRENT_BLOCK;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
host_writew(hostmem+addr,val);
|
||||
return false;
|
||||
}
|
||||
bool writed_checked(PhysPt addr,Bitu val) {
|
||||
addr&=4095;
|
||||
if (host_readd(hostmem+addr)==(Bit32u)val) return false;
|
||||
if (!*(Bit32u*)&write_map[addr]) {
|
||||
if (!active_blocks) {
|
||||
active_count--;
|
||||
if (!active_count) Release();
|
||||
}
|
||||
} else if (InvalidateRange(addr,addr+3)) {
|
||||
cpu.exception.which=SMC_CURRENT_BLOCK;
|
||||
return true;
|
||||
} else {
|
||||
if (!invalidation_map) {
|
||||
invalidation_map=(Bit8u*)malloc(4096);
|
||||
memset(invalidation_map,0,4096);
|
||||
}
|
||||
(*(Bit32u*)&invalidation_map[addr])+=0x1010101;
|
||||
if (InvalidateRange(addr,addr+3)) {
|
||||
cpu.exception.which=SMC_CURRENT_BLOCK;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
host_writed(hostmem+addr,val);
|
||||
return false;
|
||||
|
@ -216,6 +266,7 @@ public:
|
|||
}
|
||||
public:
|
||||
Bit8u write_map[4096];
|
||||
Bit8u * invalidation_map;
|
||||
CodePageHandler * next, * prev;
|
||||
private:
|
||||
PageHandler * old_pagehandler;
|
||||
|
@ -460,7 +511,16 @@ static void cache_init(bool enable) {
|
|||
}
|
||||
|
||||
static void cache_close(void) {
|
||||
/* if (cache_blocks != NULL) {
|
||||
/* 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) {
|
||||
free(cache_blocks);
|
||||
cache_blocks = NULL;
|
||||
}
|
||||
|
|
|
@ -17,6 +17,8 @@
|
|||
*/
|
||||
|
||||
#define X86_DYNFPU_DH_ENABLED
|
||||
#define X86_INLINED_MEMACCESS
|
||||
|
||||
|
||||
enum REP_Type {
|
||||
REP_NONE=0,REP_NZ,REP_Z
|
||||
|
@ -36,6 +38,7 @@ static struct DynDecode {
|
|||
CodePageHandler * code;
|
||||
Bitu index;
|
||||
Bit8u * wmap;
|
||||
Bit8u * invmap;
|
||||
Bitu first;
|
||||
} page;
|
||||
struct {
|
||||
|
@ -48,7 +51,7 @@ static struct DynDecode {
|
|||
} decode;
|
||||
|
||||
static Bit8u decode_fetchb(void) {
|
||||
if (decode.page.index>=4096) {
|
||||
if (GCC_UNLIKELY(decode.page.index>=4096)) {
|
||||
/* Advance to the next page */
|
||||
decode.active_block->page.end=4095;
|
||||
/* trigger possible page fault here */
|
||||
|
@ -61,6 +64,7 @@ static Bit8u decode_fetchb(void) {
|
|||
decode.active_block->page.start=0;
|
||||
decode.page.code->AddCrossBlock(decode.active_block);
|
||||
decode.page.wmap=decode.page.code->write_map;
|
||||
decode.page.invmap=decode.page.code->invalidation_map;
|
||||
decode.page.index=0;
|
||||
}
|
||||
decode.page.wmap[decode.page.index]+=0x01;
|
||||
|
@ -69,7 +73,7 @@ static Bit8u decode_fetchb(void) {
|
|||
return mem_readb(decode.code-1);
|
||||
}
|
||||
static Bit16u decode_fetchw(void) {
|
||||
if (decode.page.index>=4095) {
|
||||
if (GCC_UNLIKELY(decode.page.index>=4095)) {
|
||||
Bit16u val=decode_fetchb();
|
||||
val|=decode_fetchb() << 8;
|
||||
return val;
|
||||
|
@ -79,7 +83,7 @@ static Bit16u decode_fetchw(void) {
|
|||
return mem_readw(decode.code-2);
|
||||
}
|
||||
static Bit32u decode_fetchd(void) {
|
||||
if (decode.page.index>=4093) {
|
||||
if (GCC_UNLIKELY(decode.page.index>=4093)) {
|
||||
Bit32u val=decode_fetchb();
|
||||
val|=decode_fetchb() << 8;
|
||||
val|=decode_fetchb() << 16;
|
||||
|
@ -92,6 +96,46 @@ static Bit32u decode_fetchd(void) {
|
|||
return mem_readd(decode.code-4);
|
||||
}
|
||||
|
||||
static bool decode_fetchb_imm(Bitu & val) {
|
||||
if (decode.page.index<4096) {
|
||||
Bitu index=(decode.code>>12);
|
||||
if (paging.tlb.read[index]) {
|
||||
val=(Bitu)(paging.tlb.read[index]+decode.code);
|
||||
decode.code++;
|
||||
decode.page.index++;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
val=(Bit32u)decode_fetchb();
|
||||
return false;
|
||||
}
|
||||
static bool decode_fetchw_imm(Bitu & val) {
|
||||
if (decode.page.index<4095) {
|
||||
Bitu index=(decode.code>>12);
|
||||
if (paging.tlb.read[index]) {
|
||||
val=(Bitu)(paging.tlb.read[index]+decode.code);
|
||||
decode.code+=2;
|
||||
decode.page.index+=2;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
val=decode_fetchw();
|
||||
return false;
|
||||
}
|
||||
static bool decode_fetchd_imm(Bitu & val) {
|
||||
if (decode.page.index<4093) {
|
||||
Bitu index=(decode.code>>12);
|
||||
if (paging.tlb.read[index]) {
|
||||
val=(Bitu)(paging.tlb.read[index]+decode.code);
|
||||
decode.code+=4;
|
||||
decode.page.index+=4;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
val=decode_fetchd();
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
static void dyn_reduce_cycles(void) {
|
||||
gen_protectflags();
|
||||
|
@ -204,6 +248,17 @@ static void dyn_check_irqrequest(void) {
|
|||
used_save_info++;
|
||||
}
|
||||
|
||||
static void dyn_check_bool_exception_ne(void) {
|
||||
save_info[used_save_info].branch_pos=gen_create_branch_long(BR_Z);
|
||||
dyn_savestate(&save_info[used_save_info].state);
|
||||
if (!decode.cycles) decode.cycles++;
|
||||
save_info[used_save_info].cycles=decode.cycles;
|
||||
save_info[used_save_info].eip_change=decode.op_start-decode.code_start;
|
||||
if (!cpu.code.big) save_info[used_save_info].eip_change&=0xffff;
|
||||
save_info[used_save_info].type=exception;
|
||||
used_save_info++;
|
||||
}
|
||||
|
||||
static void dyn_fill_blocks(void) {
|
||||
for (Bitu sct=0; sct<used_save_info; sct++) {
|
||||
gen_fill_branch_long(save_info[sct].branch_pos);
|
||||
|
@ -245,6 +300,8 @@ static void dyn_fill_blocks(void) {
|
|||
used_save_info=0;
|
||||
}
|
||||
|
||||
|
||||
#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_x86,"%Dd%Id",addr,&core_dyn.readdata);
|
||||
|
@ -276,7 +333,7 @@ static void dyn_read_byte_release(DynReg * addr,DynReg * dst,Bitu high) {
|
|||
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) {
|
||||
static void dyn_write_byte_release(DynReg * addr,DynReg * val,Bitu high) {
|
||||
gen_protectflags();
|
||||
if (high) gen_call_function((void *)&mem_writeb_checked_x86,"%Ddr%Dh",addr,val);
|
||||
else gen_call_function((void *)&mem_writeb_checked_x86,"%Ddr%Dd",addr,val);
|
||||
|
@ -296,6 +353,435 @@ static void dyn_write_word_release(DynReg * addr,DynReg * val,bool dword) {
|
|||
dyn_check_bool_exception_al();
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
static void dyn_read_intro(DynReg * addr,bool release_addr=true) {
|
||||
gen_protectflags();
|
||||
|
||||
if (addr->genreg) {
|
||||
// addr already in a register
|
||||
Bit8u reg_idx=(Bit8u)addr->genreg->index;
|
||||
x86gen.regs[X86_REG_ECX]->Clear();
|
||||
if (reg_idx!=1) {
|
||||
cache_addw(0xc88b+(reg_idx<<8)); //Mov ecx,reg
|
||||
}
|
||||
x86gen.regs[X86_REG_EAX]->Clear();
|
||||
if (release_addr) gen_releasereg(addr);
|
||||
} else {
|
||||
// addr still in memory, directly move into ecx
|
||||
x86gen.regs[X86_REG_EAX]->Clear();
|
||||
x86gen.regs[X86_REG_ECX]->Clear();
|
||||
cache_addw(0x0d8b); //Mov ecx,[data]
|
||||
cache_addd((Bit32u)addr->data);
|
||||
}
|
||||
x86gen.regs[X86_REG_EDX]->Clear();
|
||||
|
||||
cache_addw(0xc18b); // mov eax,ecx
|
||||
}
|
||||
|
||||
bool mem_readb_checked_x86x(PhysPt address) {
|
||||
Bitu index=(address>>12);
|
||||
Bitu uval;
|
||||
bool retval;
|
||||
retval=paging.tlb.handler[index]->readb_checked(address, &uval);
|
||||
core_dyn.readdata=(Bit8u)uval;
|
||||
return retval;
|
||||
}
|
||||
|
||||
static void dyn_read_byte(DynReg * addr,DynReg * dst,Bitu high) {
|
||||
dyn_read_intro(addr,false);
|
||||
|
||||
cache_addw(0xe8c1); // shr eax,0x0c
|
||||
cache_addb(0x0c);
|
||||
cache_addw(0x048b); // mov eax,paging.tlb.read[eax*TYPE Bit32u]
|
||||
cache_addb(0x85);
|
||||
cache_addd((Bit32u)(&paging.tlb.read[0]));
|
||||
cache_addw(0xc085); // test eax,eax
|
||||
Bit8u* je_loc=gen_create_branch(BR_Z);
|
||||
|
||||
|
||||
cache_addw(0x048a); // mov al,[eax+ecx]
|
||||
cache_addb(0x08);
|
||||
|
||||
Bit8u* jmp_loc=gen_create_jump();
|
||||
gen_fill_branch(je_loc);
|
||||
cache_addb(0x51); // push ecx
|
||||
cache_addb(0xe8);
|
||||
cache_addd(((Bit32u)&mem_readb_checked_x86x) - (Bit32u)cache.pos-4);
|
||||
cache_addw(0xc483); // add esp,4
|
||||
cache_addb(0x04);
|
||||
cache_addw(0x012c); // sub al,1
|
||||
|
||||
dyn_check_bool_exception_ne();
|
||||
|
||||
cache_addw(0x058a); //mov al,[]
|
||||
cache_addd((Bit32u)(&core_dyn.readdata));
|
||||
|
||||
gen_fill_jump(jmp_loc);
|
||||
|
||||
x86gen.regs[X86_REG_EAX]->notusable=true;
|
||||
GenReg * genreg=FindDynReg(dst);
|
||||
x86gen.regs[X86_REG_EAX]->notusable=false;
|
||||
cache_addw(0xc08a+(genreg->index<<11)+(high?0x2000:0));
|
||||
dst->flags|=DYNFLG_CHANGED;
|
||||
}
|
||||
|
||||
static void dyn_read_byte_release(DynReg * addr,DynReg * dst,Bitu high) {
|
||||
dyn_read_intro(addr);
|
||||
|
||||
cache_addw(0xe8c1); // shr eax,0x0c
|
||||
cache_addb(0x0c);
|
||||
cache_addw(0x048b); // mov eax,paging.tlb.read[eax*TYPE Bit32u]
|
||||
cache_addb(0x85);
|
||||
cache_addd((Bit32u)(&paging.tlb.read[0]));
|
||||
cache_addw(0xc085); // test eax,eax
|
||||
Bit8u* je_loc=gen_create_branch(BR_Z);
|
||||
|
||||
|
||||
cache_addw(0x048a); // mov al,[eax+ecx]
|
||||
cache_addb(0x08);
|
||||
|
||||
Bit8u* jmp_loc=gen_create_jump();
|
||||
gen_fill_branch(je_loc);
|
||||
cache_addb(0x51); // push ecx
|
||||
cache_addb(0xe8);
|
||||
cache_addd(((Bit32u)&mem_readb_checked_x86x) - (Bit32u)cache.pos-4);
|
||||
cache_addw(0xc483); // add esp,4
|
||||
cache_addb(0x04);
|
||||
cache_addw(0x012c); // sub al,1
|
||||
|
||||
dyn_check_bool_exception_ne();
|
||||
|
||||
cache_addw(0x058a); //mov al,[]
|
||||
cache_addd((Bit32u)(&core_dyn.readdata));
|
||||
|
||||
gen_fill_jump(jmp_loc);
|
||||
|
||||
x86gen.regs[X86_REG_EAX]->notusable=true;
|
||||
GenReg * genreg=FindDynReg(dst);
|
||||
x86gen.regs[X86_REG_EAX]->notusable=false;
|
||||
cache_addw(0xc08a+(genreg->index<<11)+(high?0x2000:0));
|
||||
dst->flags|=DYNFLG_CHANGED;
|
||||
}
|
||||
|
||||
bool mem_readd_checked_x86x(PhysPt address) {
|
||||
if ((address & 0xfff)<0xffd) {
|
||||
Bitu index=(address>>12);
|
||||
if (paging.tlb.read[index]) {
|
||||
core_dyn.readdata=host_readd(paging.tlb.read[index]+address);
|
||||
return false;
|
||||
} else {
|
||||
Bitu uval;
|
||||
bool retval;
|
||||
retval=paging.tlb.handler[index]->readd_checked(address, &uval);
|
||||
core_dyn.readdata=(Bit32u)uval;
|
||||
return retval;
|
||||
}
|
||||
} else return mem_unalignedreadd_checked_x86(address, &core_dyn.readdata);
|
||||
}
|
||||
|
||||
static void dyn_read_word(DynReg * addr,DynReg * dst,bool dword) {
|
||||
if (dword) {
|
||||
dyn_read_intro(addr,false);
|
||||
|
||||
cache_addw(0xe8d1); // shr eax,0x1
|
||||
Bit8u* jb_loc1=gen_create_branch(BR_B);
|
||||
cache_addw(0xe8d1); // shr eax,0x1
|
||||
Bit8u* jb_loc2=gen_create_branch(BR_B);
|
||||
cache_addw(0xe8c1); // shr eax,0x0a
|
||||
cache_addb(0x0a);
|
||||
cache_addw(0x048b); // mov eax,paging.tlb.read[eax*TYPE Bit32u]
|
||||
cache_addb(0x85);
|
||||
cache_addd((Bit32u)(&paging.tlb.read[0]));
|
||||
cache_addw(0xc085); // test eax,eax
|
||||
Bit8u* je_loc=gen_create_branch(BR_Z);
|
||||
|
||||
GenReg * genreg=FindDynReg(dst,true);
|
||||
|
||||
cache_addw(0x048b+(genreg->index <<(8+3))); // mov dest,[eax+ecx]
|
||||
cache_addb(0x08);
|
||||
|
||||
Bit8u* jmp_loc=gen_create_jump();
|
||||
gen_fill_branch(jb_loc1);
|
||||
gen_fill_branch(jb_loc2);
|
||||
gen_fill_branch(je_loc);
|
||||
cache_addb(0x51); // push ecx
|
||||
cache_addb(0xe8);
|
||||
cache_addd(((Bit32u)&mem_readd_checked_x86x) - (Bit32u)cache.pos-4);
|
||||
cache_addw(0xc483); // add esp,4
|
||||
cache_addb(0x04);
|
||||
cache_addw(0x012c); // sub al,1
|
||||
|
||||
dyn_check_bool_exception_ne();
|
||||
|
||||
gen_mov_host(&core_dyn.readdata,dst,4);
|
||||
dst->flags|=DYNFLG_CHANGED;
|
||||
|
||||
gen_fill_jump(jmp_loc);
|
||||
} else {
|
||||
gen_protectflags();
|
||||
gen_call_function((void *)&mem_readw_checked_x86,"%Dd%Id",addr,&core_dyn.readdata);
|
||||
dyn_check_bool_exception_al();
|
||||
gen_mov_host(&core_dyn.readdata,dst,2);
|
||||
}
|
||||
}
|
||||
|
||||
static void dyn_read_word_release(DynReg * addr,DynReg * dst,bool dword) {
|
||||
if (dword) {
|
||||
dyn_read_intro(addr);
|
||||
|
||||
cache_addw(0xe8d1); // shr eax,0x1
|
||||
Bit8u* jb_loc1=gen_create_branch(BR_B);
|
||||
cache_addw(0xe8d1); // shr eax,0x1
|
||||
Bit8u* jb_loc2=gen_create_branch(BR_B);
|
||||
cache_addw(0xe8c1); // shr eax,0x0a
|
||||
cache_addb(0x0a);
|
||||
cache_addw(0x048b); // mov eax,paging.tlb.read[eax*TYPE Bit32u]
|
||||
cache_addb(0x85);
|
||||
cache_addd((Bit32u)(&paging.tlb.read[0]));
|
||||
cache_addw(0xc085); // test eax,eax
|
||||
Bit8u* je_loc=gen_create_branch(BR_Z);
|
||||
|
||||
GenReg * genreg=FindDynReg(dst,true);
|
||||
|
||||
cache_addw(0x048b+(genreg->index <<(8+3))); // mov dest,[eax+ecx]
|
||||
cache_addb(0x08);
|
||||
|
||||
Bit8u* jmp_loc=gen_create_jump();
|
||||
gen_fill_branch(jb_loc1);
|
||||
gen_fill_branch(jb_loc2);
|
||||
gen_fill_branch(je_loc);
|
||||
cache_addb(0x51); // push ecx
|
||||
cache_addb(0xe8);
|
||||
cache_addd(((Bit32u)&mem_readd_checked_x86x) - (Bit32u)cache.pos-4);
|
||||
cache_addw(0xc483); // add esp,4
|
||||
cache_addb(0x04);
|
||||
cache_addw(0x012c); // sub al,1
|
||||
|
||||
dyn_check_bool_exception_ne();
|
||||
|
||||
gen_mov_host(&core_dyn.readdata,dst,4);
|
||||
dst->flags|=DYNFLG_CHANGED;
|
||||
|
||||
gen_fill_jump(jmp_loc);
|
||||
} else {
|
||||
gen_protectflags();
|
||||
gen_call_function((void *)&mem_readw_checked_x86,"%Ddr%Id",addr,&core_dyn.readdata);
|
||||
dyn_check_bool_exception_al();
|
||||
gen_mov_host(&core_dyn.readdata,dst,2);
|
||||
}
|
||||
}
|
||||
|
||||
static void dyn_write_intro(DynReg * addr,bool release_addr=true) {
|
||||
gen_protectflags();
|
||||
|
||||
if (addr->genreg) {
|
||||
// addr in a register
|
||||
Bit8u reg_idx_addr=(Bit8u)addr->genreg->index;
|
||||
|
||||
x86gen.regs[X86_REG_EAX]->Clear();
|
||||
x86gen.regs[X86_REG_EAX]->notusable=true;
|
||||
x86gen.regs[X86_REG_ECX]->Clear();
|
||||
x86gen.regs[X86_REG_ECX]->notusable=true;
|
||||
|
||||
if (reg_idx_addr) {
|
||||
// addr!=eax
|
||||
cache_addb(0x8b); //Mov eax,reg
|
||||
cache_addb(0xc0+reg_idx_addr);
|
||||
}
|
||||
if (release_addr) gen_releasereg(addr);
|
||||
} else {
|
||||
// addr still in memory, directly move into eax
|
||||
x86gen.regs[X86_REG_EAX]->Clear();
|
||||
x86gen.regs[X86_REG_EAX]->notusable=true;
|
||||
x86gen.regs[X86_REG_ECX]->Clear();
|
||||
x86gen.regs[X86_REG_ECX]->notusable=true;
|
||||
cache_addb(0xa1); //Mov eax,[data]
|
||||
cache_addd((Bit32u)addr->data);
|
||||
}
|
||||
|
||||
cache_addw(0xc88b); // mov ecx,eax
|
||||
}
|
||||
|
||||
static void dyn_write_byte(DynReg * addr,DynReg * val,bool high) {
|
||||
dyn_write_intro(addr,false);
|
||||
|
||||
GenReg * genreg=FindDynReg(val);
|
||||
cache_addw(0xe9c1); // shr ecx,0x0c
|
||||
cache_addb(0x0c);
|
||||
cache_addw(0x0c8b); // mov ecx,paging.tlb.read[ecx*TYPE Bit32u]
|
||||
cache_addb(0x8d);
|
||||
cache_addd((Bit32u)(&paging.tlb.write[0]));
|
||||
cache_addw(0xc985); // test ecx,ecx
|
||||
Bit8u* je_loc=gen_create_branch(BR_Z);
|
||||
|
||||
cache_addw(0x0488+(genreg->index<<11)+(high?0x2000:0)); // mov [eax+ecx],reg
|
||||
cache_addb(0x08);
|
||||
|
||||
Bit8u* jmp_loc=gen_create_jump();
|
||||
gen_fill_branch(je_loc);
|
||||
|
||||
if (GCC_UNLIKELY(high)) cache_addw(0xe086+((genreg->index+(genreg->index<<3))<<8));
|
||||
cache_addb(0x52); // push edx
|
||||
cache_addb(0x50+genreg->index);
|
||||
cache_addb(0x50); // push eax
|
||||
if (GCC_UNLIKELY(high)) cache_addw(0xe086+((genreg->index+(genreg->index<<3))<<8));
|
||||
cache_addb(0xe8);
|
||||
cache_addd(((Bit32u)&mem_writeb_checked_x86) - (Bit32u)cache.pos-4);
|
||||
cache_addw(0xc483); // add esp,8
|
||||
cache_addb(0x08);
|
||||
cache_addw(0x012c); // sub al,1
|
||||
cache_addb(0x5a); // pop edx
|
||||
|
||||
// Restore registers to be used again
|
||||
x86gen.regs[X86_REG_EAX]->notusable=false;
|
||||
x86gen.regs[X86_REG_ECX]->notusable=false;
|
||||
|
||||
dyn_check_bool_exception_ne();
|
||||
|
||||
gen_fill_jump(jmp_loc);
|
||||
}
|
||||
|
||||
static void dyn_write_byte_release(DynReg * addr,DynReg * val,bool high) {
|
||||
dyn_write_intro(addr);
|
||||
|
||||
GenReg * genreg=FindDynReg(val);
|
||||
cache_addw(0xe9c1); // shr ecx,0x0c
|
||||
cache_addb(0x0c);
|
||||
cache_addw(0x0c8b); // mov ecx,paging.tlb.read[ecx*TYPE Bit32u]
|
||||
cache_addb(0x8d);
|
||||
cache_addd((Bit32u)(&paging.tlb.write[0]));
|
||||
cache_addw(0xc985); // test ecx,ecx
|
||||
Bit8u* je_loc=gen_create_branch(BR_Z);
|
||||
|
||||
cache_addw(0x0488+(genreg->index<<11)+(high?0x2000:0)); // mov [eax+ecx],reg
|
||||
cache_addb(0x08);
|
||||
|
||||
Bit8u* jmp_loc=gen_create_jump();
|
||||
gen_fill_branch(je_loc);
|
||||
|
||||
cache_addb(0x52); // push edx
|
||||
if (GCC_UNLIKELY(high)) cache_addw(0xe086+((genreg->index+(genreg->index<<3))<<8));
|
||||
cache_addb(0x50+genreg->index);
|
||||
cache_addb(0x50); // push eax
|
||||
if (GCC_UNLIKELY(high)) cache_addw(0xe086+((genreg->index+(genreg->index<<3))<<8));
|
||||
cache_addb(0xe8);
|
||||
cache_addd(((Bit32u)&mem_writeb_checked_x86) - (Bit32u)cache.pos-4);
|
||||
cache_addw(0xc483); // add esp,8
|
||||
cache_addb(0x08);
|
||||
cache_addw(0x012c); // sub al,1
|
||||
cache_addb(0x5a); // pop edx
|
||||
|
||||
// Restore registers to be used again
|
||||
x86gen.regs[X86_REG_EAX]->notusable=false;
|
||||
x86gen.regs[X86_REG_ECX]->notusable=false;
|
||||
|
||||
dyn_check_bool_exception_ne();
|
||||
|
||||
gen_fill_jump(jmp_loc);
|
||||
}
|
||||
|
||||
static void dyn_write_word(DynReg * addr,DynReg * val,bool dword) {
|
||||
if (dword) {
|
||||
dyn_write_intro(addr,false);
|
||||
|
||||
GenReg * genreg=FindDynReg(val);
|
||||
cache_addw(0xe9d1); // shr ecx,0x1
|
||||
Bit8u* jb_loc1=gen_create_branch(BR_B);
|
||||
cache_addw(0xe9d1); // shr ecx,0x1
|
||||
Bit8u* jb_loc2=gen_create_branch(BR_B);
|
||||
cache_addw(0xe9c1); // shr ecx,0x0a
|
||||
cache_addb(0x0a);
|
||||
cache_addw(0x0c8b); // mov ecx,paging.tlb.read[ecx*TYPE Bit32u]
|
||||
cache_addb(0x8d);
|
||||
cache_addd((Bit32u)(&paging.tlb.write[0]));
|
||||
cache_addw(0xc985); // test ecx,ecx
|
||||
Bit8u* je_loc=gen_create_branch(BR_Z);
|
||||
|
||||
cache_addw(0x0489+(genreg->index <<(8+3))); // mov [eax+ecx],reg
|
||||
cache_addb(0x08);
|
||||
|
||||
Bit8u* jmp_loc=gen_create_jump();
|
||||
gen_fill_branch(jb_loc1);
|
||||
gen_fill_branch(jb_loc2);
|
||||
gen_fill_branch(je_loc);
|
||||
|
||||
cache_addb(0x52); // push edx
|
||||
cache_addb(0x50+genreg->index);
|
||||
cache_addb(0x50); // push eax
|
||||
cache_addb(0xe8);
|
||||
cache_addd(((Bit32u)&mem_writed_checked_x86) - (Bit32u)cache.pos-4);
|
||||
cache_addw(0xc483); // add esp,8
|
||||
cache_addb(0x08);
|
||||
cache_addw(0x012c); // sub al,1
|
||||
cache_addb(0x5a); // pop edx
|
||||
|
||||
// Restore registers to be used again
|
||||
x86gen.regs[X86_REG_EAX]->notusable=false;
|
||||
x86gen.regs[X86_REG_ECX]->notusable=false;
|
||||
|
||||
dyn_check_bool_exception_ne();
|
||||
|
||||
gen_fill_jump(jmp_loc);
|
||||
} else {
|
||||
gen_protectflags();
|
||||
gen_call_function((void *)&mem_writew_checked_x86,"%Dd%Dd",addr,val);
|
||||
dyn_check_bool_exception_al();
|
||||
}
|
||||
}
|
||||
|
||||
static void dyn_write_word_release(DynReg * addr,DynReg * val,bool dword) {
|
||||
if (dword) {
|
||||
dyn_write_intro(addr);
|
||||
|
||||
GenReg * genreg=FindDynReg(val);
|
||||
cache_addw(0xe9d1); // shr ecx,0x1
|
||||
Bit8u* jb_loc1=gen_create_branch(BR_B);
|
||||
cache_addw(0xe9d1); // shr ecx,0x1
|
||||
Bit8u* jb_loc2=gen_create_branch(BR_B);
|
||||
cache_addw(0xe9c1); // shr ecx,0x0a
|
||||
cache_addb(0x0a);
|
||||
cache_addw(0x0c8b); // mov ecx,paging.tlb.read[ecx*TYPE Bit32u]
|
||||
cache_addb(0x8d);
|
||||
cache_addd((Bit32u)(&paging.tlb.write[0]));
|
||||
cache_addw(0xc985); // test ecx,ecx
|
||||
Bit8u* je_loc=gen_create_branch(BR_Z);
|
||||
|
||||
cache_addw(0x0489+(genreg->index <<(8+3))); // mov [eax+ecx],reg
|
||||
cache_addb(0x08);
|
||||
|
||||
Bit8u* jmp_loc=gen_create_jump();
|
||||
gen_fill_branch(jb_loc1);
|
||||
gen_fill_branch(jb_loc2);
|
||||
gen_fill_branch(je_loc);
|
||||
|
||||
cache_addb(0x52); // push edx
|
||||
cache_addb(0x50+genreg->index);
|
||||
cache_addb(0x50); // push eax
|
||||
cache_addb(0xe8);
|
||||
cache_addd(((Bit32u)&mem_writed_checked_x86) - (Bit32u)cache.pos-4);
|
||||
cache_addw(0xc483); // add esp,8
|
||||
cache_addb(0x08);
|
||||
cache_addw(0x012c); // sub al,1
|
||||
cache_addb(0x5a); // pop edx
|
||||
|
||||
// Restore registers to be used again
|
||||
x86gen.regs[X86_REG_EAX]->notusable=false;
|
||||
x86gen.regs[X86_REG_ECX]->notusable=false;
|
||||
|
||||
dyn_check_bool_exception_ne();
|
||||
|
||||
gen_fill_jump(jmp_loc);
|
||||
} else {
|
||||
gen_protectflags();
|
||||
gen_call_function((void *)&mem_writew_checked_x86,"%Ddr%Dd",addr,val);
|
||||
dyn_check_bool_exception_al();
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
static void dyn_push_unchecked(DynReg * dynreg) {
|
||||
gen_protectflags();
|
||||
gen_lea(DREG(STACK),DREG(ESP),0,0,decode.big_op?(-4):(-2));
|
||||
|
@ -436,6 +922,12 @@ skip_extend_word:
|
|||
case 4: /* SIB */
|
||||
{
|
||||
Bitu sib=decode_fetchb();
|
||||
static DynReg * scaledtable[8]={
|
||||
DREG(EAX),DREG(ECX),DREG(EDX),DREG(EBX),
|
||||
0,DREG(EBP),DREG(ESI),DREG(EDI),
|
||||
};
|
||||
scaled=scaledtable[(sib >> 3) &7];
|
||||
scale=(sib >> 6);
|
||||
switch (sib & 7) {
|
||||
case 0:base=DREG(EAX);segbase=DREG(DS);break;
|
||||
case 1:base=DREG(ECX);segbase=DREG(DS);break;
|
||||
|
@ -446,18 +938,25 @@ skip_extend_word:
|
|||
if (decode.modrm.mod) {
|
||||
base=DREG(EBP);segbase=DREG(SS);
|
||||
} else {
|
||||
imm=(Bit32s)decode_fetchd();segbase=DREG(DS);
|
||||
segbase=DREG(DS);
|
||||
Bitu val;
|
||||
if (decode_fetchd_imm(val)) {
|
||||
gen_mov_host((void*)val,DREG(EA),4);
|
||||
if (!addseg) {
|
||||
gen_lea(reg_ea,DREG(EA),scaled,scale,0);
|
||||
} else {
|
||||
DynReg** seg = decode.segprefix ? &decode.segprefix : &segbase;
|
||||
gen_lea(DREG(EA),DREG(EA),scaled,scale,0);
|
||||
gen_lea(reg_ea,DREG(EA),*seg,0,0);
|
||||
}
|
||||
return;
|
||||
}
|
||||
imm=(Bit32s)val;
|
||||
}
|
||||
break;
|
||||
case 6:base=DREG(ESI);segbase=DREG(DS);break;
|
||||
case 7:base=DREG(EDI);segbase=DREG(DS);break;
|
||||
}
|
||||
static DynReg * scaledtable[8]={
|
||||
DREG(EAX),DREG(ECX),DREG(EDX),DREG(EBX),
|
||||
0,DREG(EBP),DREG(ESI),DREG(EDI),
|
||||
};
|
||||
scaled=scaledtable[(sib >> 3) &7];
|
||||
scale=(sib >> 6);
|
||||
}
|
||||
break; /* SIB Break */
|
||||
case 5:
|
||||
|
@ -472,7 +971,33 @@ skip_extend_word:
|
|||
}
|
||||
switch (decode.modrm.mod) {
|
||||
case 1:imm=(Bit8s)decode_fetchb();break;
|
||||
case 2:imm=(Bit32s)decode_fetchd();break;
|
||||
case 2: {
|
||||
Bitu val;
|
||||
if (decode_fetchd_imm(val)) {
|
||||
gen_mov_host((void*)val,DREG(EA),4);
|
||||
if (!addseg) {
|
||||
gen_lea(DREG(EA),DREG(EA),scaled,scale,0);
|
||||
gen_lea(reg_ea,DREG(EA),base,0,0);
|
||||
} else {
|
||||
DynReg** seg = decode.segprefix ? &decode.segprefix : &segbase;
|
||||
if (!base) {
|
||||
gen_lea(DREG(EA),DREG(EA),scaled,scale,0);
|
||||
gen_lea(reg_ea,DREG(EA),*seg,0,0);
|
||||
} else if (!scaled) {
|
||||
gen_lea(DREG(EA),DREG(EA),*seg,0,0);
|
||||
gen_lea(reg_ea,DREG(EA),base,0,0);
|
||||
} else {
|
||||
gen_lea(DREG(EA),DREG(EA),scaled,scale,0);
|
||||
gen_lea(DREG(EA),DREG(EA),base,0,0);
|
||||
gen_lea(reg_ea,DREG(EA),decode.segprefix ? decode.segprefix : segbase,0,0);
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
imm=(Bit32s)val;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!addseg) {
|
||||
gen_lea(reg_ea,base,scaled,scale,imm);
|
||||
|
@ -481,13 +1006,40 @@ skip_extend_word:
|
|||
if (!base) gen_lea(reg_ea,*seg,scaled,scale,imm);
|
||||
else if (!scaled) gen_lea(reg_ea,base,*seg,0,imm);
|
||||
else {
|
||||
gen_lea(reg_ea,base,scaled,scale,imm);
|
||||
gen_lea(reg_ea,reg_ea,decode.segprefix ? decode.segprefix : segbase,0,0);
|
||||
gen_lea(DREG(EA),base,scaled,scale,imm);
|
||||
gen_lea(reg_ea,DREG(EA),decode.segprefix ? decode.segprefix : segbase,0,0);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void dyn_dop_word_imm(DualOps op,bool dword,DynReg * dr1) {
|
||||
Bitu val;
|
||||
if (dword) {
|
||||
if (decode_fetchd_imm(val)) {
|
||||
gen_dop_word_imm_mem(op,true,dr1,(void*)val);
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
if (decode_fetchw_imm(val)) {
|
||||
gen_dop_word_imm_mem(op,false,dr1,(void*)val);
|
||||
return;
|
||||
}
|
||||
}
|
||||
gen_dop_word_imm(op,dword,dr1,val);
|
||||
}
|
||||
|
||||
static void dyn_dop_byte_imm(DualOps op,DynReg * dr1,Bit8u di1) {
|
||||
Bitu val;
|
||||
if (decode_fetchb_imm(val)) {
|
||||
gen_dop_byte_imm_mem(op,dr1,di1,(void*)val);
|
||||
} else {
|
||||
gen_dop_byte_imm(op,dr1,di1,(Bit8u)val);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#include "helpers.h"
|
||||
#include "string.h"
|
||||
|
||||
|
@ -734,7 +1286,7 @@ static void dyn_grp1_eb_ib(void) {
|
|||
if (op==DOP_ADC || op==DOP_SBB) gen_needcarry();
|
||||
else gen_discardflags();
|
||||
}
|
||||
gen_dop_byte_imm(op,&DynRegs[decode.modrm.rm&3],decode.modrm.rm&4,decode_fetchb());
|
||||
dyn_dop_byte_imm(op,&DynRegs[decode.modrm.rm&3],decode.modrm.rm&4);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -745,22 +1297,28 @@ static void dyn_grp1_ev_ivx(bool withbyte) {
|
|||
dyn_fill_ea();
|
||||
if ((op<=DOP_TEST) && (op!=DOP_ADC && op!=DOP_SBB)) set_skipflags(true);
|
||||
dyn_read_word(DREG(EA),DREG(TMPW),decode.big_op);
|
||||
Bits imm=withbyte ? (Bit8s)decode_fetchb() : (decode.big_op ? decode_fetchd(): decode_fetchw());
|
||||
if (op<=DOP_TEST) {
|
||||
if (op==DOP_ADC || op==DOP_SBB) gen_needcarry();
|
||||
else set_skipflags(false);
|
||||
}
|
||||
gen_dop_word_imm(op,decode.big_op,DREG(TMPW),imm);
|
||||
if (!withbyte) {
|
||||
dyn_dop_word_imm(op,decode.big_op,DREG(TMPW));
|
||||
} else {
|
||||
gen_dop_word_imm(op,decode.big_op,DREG(TMPW),(Bit8s)decode_fetchb());
|
||||
}
|
||||
if (op!=DOP_CMP) dyn_write_word_release(DREG(EA),DREG(TMPW),decode.big_op);
|
||||
else gen_releasereg(DREG(EA));
|
||||
gen_releasereg(DREG(TMPW));
|
||||
} else {
|
||||
Bits imm=withbyte ? (Bit8s)decode_fetchb() : (decode.big_op ? decode_fetchd(): decode_fetchw());
|
||||
if (op<=DOP_TEST) {
|
||||
if (op==DOP_ADC || op==DOP_SBB) gen_needcarry();
|
||||
else gen_discardflags();
|
||||
}
|
||||
gen_dop_word_imm(op,decode.big_op,&DynRegs[decode.modrm.rm],imm);
|
||||
if (!withbyte) {
|
||||
dyn_dop_word_imm(op,decode.big_op,&DynRegs[decode.modrm.rm]);
|
||||
} else {
|
||||
gen_dop_word_imm(op,decode.big_op,&DynRegs[decode.modrm.rm],(Bit8s)decode_fetchb());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -822,7 +1380,16 @@ static void dyn_grp2_ev(grp2_types type) {
|
|||
gen_shift_word_imm(decode.modrm.reg,decode.big_op,src,1);
|
||||
break;
|
||||
case grp2_imm: {
|
||||
Bit8u imm=decode_fetchb();
|
||||
Bitu val;
|
||||
if (decode_fetchb_imm(val)) {
|
||||
if (decode.modrm.reg < 4) gen_needflags();
|
||||
else gen_discardflags();
|
||||
gen_load_host((void*)val,DREG(TMPB),1);
|
||||
gen_shift_word_cl(decode.modrm.reg,decode.big_op,src,DREG(TMPB));
|
||||
gen_releasereg(DREG(TMPB));
|
||||
break;
|
||||
}
|
||||
Bit8u imm=(Bit8u)val;
|
||||
if (imm) {
|
||||
/* rotates (first 4 ops) alter cf/of only; shifts (last 4 ops) alter all flags */
|
||||
if (decode.modrm.reg < 4) gen_needflags();
|
||||
|
@ -1272,6 +1839,7 @@ static CacheBlock * CreateCacheBlock(CodePageHandler * codepage,PhysPt start,Bit
|
|||
decode.page.code=codepage;
|
||||
decode.page.index=start&4095;
|
||||
decode.page.wmap=codepage->write_map;
|
||||
decode.page.invmap=codepage->invalidation_map;
|
||||
decode.page.first=start >> 12;
|
||||
decode.active_block=decode.block=cache_openblock();
|
||||
decode.block->page.start=decode.page.index;
|
||||
|
@ -1303,7 +1871,18 @@ static CacheBlock * CreateCacheBlock(CodePageHandler * codepage,PhysPt start,Bit
|
|||
decode.cycles++;
|
||||
decode.op_start=decode.code;
|
||||
restart_prefix:
|
||||
Bitu opcode=decode_fetchb();
|
||||
Bitu opcode;
|
||||
if (!decode.page.invmap) opcode=decode_fetchb();
|
||||
else {
|
||||
if (decode.page.index<4096) {
|
||||
if (GCC_UNLIKELY(decode.page.invmap[decode.page.index]>=4)) goto illegalopcode;
|
||||
opcode=decode_fetchb();
|
||||
} else {
|
||||
opcode=decode_fetchb();
|
||||
if (GCC_UNLIKELY(decode.page.invmap &&
|
||||
(decode.page.invmap[decode.page.index-1]>=4))) goto illegalopcode;
|
||||
}
|
||||
}
|
||||
switch (opcode) {
|
||||
|
||||
case 0x00:dyn_dop_ebgb(DOP_ADD);break;
|
||||
|
@ -1311,7 +1890,7 @@ restart_prefix:
|
|||
case 0x02:dyn_dop_gbeb(DOP_ADD);break;
|
||||
case 0x03:dyn_dop_gvev(DOP_ADD);break;
|
||||
case 0x04:gen_discardflags();gen_dop_byte_imm(DOP_ADD,DREG(EAX),0,decode_fetchb());break;
|
||||
case 0x05:gen_discardflags();gen_dop_word_imm(DOP_ADD,decode.big_op,DREG(EAX),decode.big_op ? decode_fetchd() : decode_fetchw());break;
|
||||
case 0x05:gen_discardflags();dyn_dop_word_imm(DOP_ADD,decode.big_op,DREG(EAX));break;
|
||||
case 0x06:dyn_push_seg(es);break;
|
||||
case 0x07:dyn_pop_seg(es);break;
|
||||
|
||||
|
@ -1384,7 +1963,7 @@ restart_prefix:
|
|||
case 0x22:dyn_dop_gbeb(DOP_AND);break;
|
||||
case 0x23:dyn_dop_gvev(DOP_AND);break;
|
||||
case 0x24:gen_discardflags();gen_dop_byte_imm(DOP_AND,DREG(EAX),0,decode_fetchb());break;
|
||||
case 0x25:gen_discardflags();gen_dop_word_imm(DOP_AND,decode.big_op,DREG(EAX),decode.big_op ? decode_fetchd() : decode_fetchw());break;
|
||||
case 0x25:gen_discardflags();dyn_dop_word_imm(DOP_AND,decode.big_op,DREG(EAX));break;
|
||||
case 0x26:dyn_segprefix(es);goto restart_prefix;
|
||||
|
||||
case 0x28:dyn_dop_ebgb(DOP_SUB);break;
|
||||
|
@ -1488,7 +2067,7 @@ restart_prefix:
|
|||
case 0x8b:dyn_mov_gvev();break;
|
||||
/* MOV ev,seg */
|
||||
case 0x8c:dyn_mov_ev_seg();break;
|
||||
/* LEA Gv */
|
||||
/* LEA Gv */
|
||||
case 0x8d:
|
||||
dyn_get_modrm();
|
||||
if (decode.big_op) {
|
||||
|
@ -1550,9 +2129,18 @@ restart_prefix:
|
|||
break;
|
||||
/* MOV direct address,AL */
|
||||
case 0xa2:
|
||||
gen_lea(DREG(EA),decode.segprefix ? decode.segprefix : DREG(DS),0,0,
|
||||
decode.big_addr ? decode_fetchd() : decode_fetchw());
|
||||
dyn_write_byte_release(DREG(EA),DREG(EAX),false);
|
||||
if (decode.big_addr) {
|
||||
Bitu val;
|
||||
if (decode_fetchd_imm(val)) {
|
||||
gen_lea_imm_mem(DREG(EA),decode.segprefix ? decode.segprefix : DREG(DS),(void*)val);
|
||||
} else {
|
||||
gen_lea(DREG(EA),decode.segprefix ? decode.segprefix : DREG(DS),0,0,(Bits)val);
|
||||
}
|
||||
dyn_write_byte_release(DREG(EA),DREG(EAX),false);
|
||||
} else {
|
||||
gen_lea(DREG(EA),decode.segprefix ? decode.segprefix : DREG(DS),0,0,decode_fetchw());
|
||||
dyn_write_byte_release(DREG(EA),DREG(EAX),false);
|
||||
}
|
||||
break;
|
||||
/* MOV direct addresses,AX */
|
||||
case 0xa3:
|
||||
|
@ -1578,7 +2166,11 @@ restart_prefix:
|
|||
break;
|
||||
//Mov word reg imm byte,word,
|
||||
case 0xb8:case 0xb9:case 0xba:case 0xbb:case 0xbc:case 0xbd:case 0xbe:case 0xbf:
|
||||
gen_dop_word_imm(DOP_MOV,decode.big_op,&DynRegs[opcode&7],decode.big_op ? decode_fetchd() : decode_fetchw());break;
|
||||
if (decode.big_op) {
|
||||
dyn_dop_word_imm(DOP_MOV,decode.big_op,&DynRegs[opcode&7]);break;
|
||||
} else {
|
||||
gen_dop_word_imm(DOP_MOV,decode.big_op,&DynRegs[opcode&7],decode_fetchw());break;
|
||||
}
|
||||
break;
|
||||
//GRP2 Eb/Ev,Ib
|
||||
case 0xc0:dyn_grp2_eb(grp2_imm);break;
|
||||
|
|
|
@ -283,6 +283,36 @@ static void gen_reinit(void) {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
static void gen_load_host(void * data,DynReg * dr1,Bitu size) {
|
||||
GenReg * gr1=FindDynReg(dr1,true);
|
||||
switch (size) {
|
||||
case 1:cache_addw(0xb60f);break; //movzx byte
|
||||
case 2:cache_addw(0xb70f);break; //movzx word
|
||||
case 4:cache_addb(0x8b);break; //mov
|
||||
default:
|
||||
IllegalOption("gen_load_host");
|
||||
}
|
||||
cache_addb(0x5+(gr1->index<<3));
|
||||
cache_addd((Bit32u)data);
|
||||
dr1->flags|=DYNFLG_CHANGED;
|
||||
}
|
||||
|
||||
static void gen_mov_host(void * data,DynReg * dr1,Bitu size,Bit8u di1=0) {
|
||||
GenReg * gr1=FindDynReg(dr1,(size==4));
|
||||
switch (size) {
|
||||
case 1:cache_addb(0x8a);break; //mov byte
|
||||
case 2:cache_addb(0x66); //mov word
|
||||
case 4:cache_addb(0x8b);break; //mov
|
||||
default:
|
||||
IllegalOption("gen_load_host");
|
||||
}
|
||||
cache_addb(0x5+((gr1->index+(di1?4:0))<<3));
|
||||
cache_addd((Bit32u)data);
|
||||
dr1->flags|=DYNFLG_CHANGED;
|
||||
}
|
||||
|
||||
|
||||
static void gen_dop_byte(DualOps op,DynReg * dr1,Bit8u di1,DynReg * dr2,Bit8u di2) {
|
||||
GenReg * gr1=FindDynReg(dr1);GenReg * gr2=FindDynReg(dr2);
|
||||
Bit8u tmp;
|
||||
|
@ -332,6 +362,29 @@ finish:
|
|||
cache_addb(imm);
|
||||
}
|
||||
|
||||
static void gen_dop_byte_imm_mem(DualOps op,DynReg * dr1,Bit8u di1,void* data) {
|
||||
GenReg * gr1=FindDynReg(dr1);
|
||||
Bit16u tmp;
|
||||
switch (op) {
|
||||
case DOP_ADD: tmp=0x0502; break;
|
||||
case DOP_ADC: tmp=0x0512; break;
|
||||
case DOP_SUB: tmp=0x052a; break;
|
||||
case DOP_SBB: tmp=0x051a; break;
|
||||
case DOP_CMP: tmp=0x053a; goto nochange; //Doesn't change
|
||||
case DOP_XOR: tmp=0x0532; break;
|
||||
case DOP_AND: tmp=0x0522; break;
|
||||
case DOP_OR: tmp=0x050a; break;
|
||||
case DOP_TEST: tmp=0x0584; goto nochange; //Doesn't change
|
||||
case DOP_MOV: tmp=0x0585; break;
|
||||
default:
|
||||
IllegalOption("gen_dop_byte_imm_mem");
|
||||
}
|
||||
dr1->flags|=DYNFLG_CHANGED;
|
||||
nochange:
|
||||
cache_addw(tmp+((gr1->index+di1)<<11));
|
||||
cache_addd((Bit32u)data);
|
||||
}
|
||||
|
||||
static void gen_sop_byte(SingleOps op,DynReg * dr1,Bit8u di1) {
|
||||
GenReg * gr1=FindDynReg(dr1);
|
||||
Bit16u tmp;
|
||||
|
@ -413,6 +466,19 @@ static void gen_lea(DynReg * ddr,DynReg * dsr1,DynReg * dsr2,Bitu scale,Bits imm
|
|||
ddr->flags|=DYNFLG_CHANGED;
|
||||
}
|
||||
|
||||
static void gen_lea_imm_mem(DynReg * ddr,DynReg * dsr,void* data) {
|
||||
GenReg * gdr=FindDynReg(ddr);
|
||||
Bit8u rm_base=(gdr->index << 3);
|
||||
cache_addw(0x058b+(rm_base<<8));
|
||||
cache_addd((Bit32u)data);
|
||||
GenReg * gsr=FindDynReg(dsr);
|
||||
cache_addb(0x8d); //LEA
|
||||
cache_addb(rm_base+0x44);
|
||||
cache_addb(rm_base+gsr->index);
|
||||
cache_addb(0x00);
|
||||
ddr->flags|=DYNFLG_CHANGED;
|
||||
}
|
||||
|
||||
static void gen_dop_word(DualOps op,bool dword,DynReg * dr1,DynReg * dr2) {
|
||||
GenReg * gr2=FindDynReg(dr2);
|
||||
GenReg * gr1=FindDynReg(dr1,dword && op==DOP_MOV);
|
||||
|
@ -473,6 +539,33 @@ finish:
|
|||
else cache_addw(imm);
|
||||
}
|
||||
|
||||
static void gen_dop_word_imm_mem(DualOps op,bool dword,DynReg * dr1,void* data) {
|
||||
GenReg * gr1=FindDynReg(dr1,dword && op==DOP_MOV);
|
||||
Bit16u tmp;
|
||||
switch (op) {
|
||||
case DOP_ADD: tmp=0x0503; break;
|
||||
case DOP_ADC: tmp=0x0513; break;
|
||||
case DOP_SUB: tmp=0x052b; break;
|
||||
case DOP_SBB: tmp=0x051b; break;
|
||||
case DOP_CMP: tmp=0x053b; goto nochange; //Doesn't change
|
||||
case DOP_XOR: tmp=0x0533; break;
|
||||
case DOP_AND: tmp=0x0523; break;
|
||||
case DOP_OR: tmp=0x050b; break;
|
||||
case DOP_TEST: tmp=0x0585; goto nochange; //Doesn't change
|
||||
case DOP_MOV:
|
||||
gen_mov_host(data,dr1,dword?4:2);
|
||||
dr1->flags|=DYNFLG_CHANGED;
|
||||
return;
|
||||
default:
|
||||
IllegalOption("gen_dop_word_imm_mem");
|
||||
}
|
||||
dr1->flags|=DYNFLG_CHANGED;
|
||||
nochange:
|
||||
if (!dword) cache_addb(0x66);
|
||||
cache_addw(tmp+(gr1->index<<11));
|
||||
cache_addd((Bit32u)data);
|
||||
}
|
||||
|
||||
static void gen_dop_word_var(DualOps op,bool dword,DynReg * dr1,void* drd) {
|
||||
GenReg * gr1=FindDynReg(dr1,dword && op==DOP_MOV);
|
||||
Bit8u tmp;
|
||||
|
@ -923,34 +1016,6 @@ static void gen_save_host_direct(void * data,Bits imm) {
|
|||
cache_addd(imm);
|
||||
}
|
||||
|
||||
static void gen_load_host(void * data,DynReg * dr1,Bitu size) {
|
||||
GenReg * gr1=FindDynReg(dr1);
|
||||
switch (size) {
|
||||
case 1:cache_addw(0xb60f);break; //movzx byte
|
||||
case 2:cache_addw(0xb70f);break; //movzx word
|
||||
case 4:cache_addb(0x8b);break; //mov
|
||||
default:
|
||||
IllegalOption("gen_load_host");
|
||||
}
|
||||
cache_addb(0x5+(gr1->index<<3));
|
||||
cache_addd((Bit32u)data);
|
||||
dr1->flags|=DYNFLG_CHANGED;
|
||||
}
|
||||
|
||||
static void gen_mov_host(void * data,DynReg * dr1,Bitu size,Bit8u di1=0) {
|
||||
GenReg * gr1=FindDynReg(dr1);
|
||||
switch (size) {
|
||||
case 1:cache_addb(0x8a);break; //mov byte
|
||||
case 2:cache_addb(0x66); //mov word
|
||||
case 4:cache_addb(0x8b);break; //mov
|
||||
default:
|
||||
IllegalOption("gen_load_host");
|
||||
}
|
||||
cache_addb(0x5+((gr1->index+(di1?4:0))<<3));
|
||||
cache_addd((Bit32u)data);
|
||||
dr1->flags|=DYNFLG_CHANGED;
|
||||
}
|
||||
|
||||
static void gen_return(BlockReturn retcode) {
|
||||
gen_protectflags();
|
||||
cache_addb(0x59); //POP ECX, the flags
|
||||
|
|
|
@ -16,7 +16,7 @@
|
|||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
/* $Id: pic.cpp,v 1.38 2007-01-09 17:18:52 c2woody Exp $ */
|
||||
/* $Id: pic.cpp,v 1.39 2007-01-18 14:57:59 c2woody Exp $ */
|
||||
|
||||
#include <list>
|
||||
|
||||
|
@ -453,8 +453,8 @@ bool PIC_RunQueue(void) {
|
|||
return false;
|
||||
}
|
||||
/* Check the queue for an entry */
|
||||
double index=PIC_TickIndex();
|
||||
while (pic.next_entry && pic.next_entry->index<=index) {
|
||||
Bits index_nd=PIC_TickIndexND();
|
||||
while (pic.next_entry && (pic.next_entry->index*CPU_CycleMax<=index_nd)) {
|
||||
PICEntry * entry=pic.next_entry;
|
||||
pic.next_entry=entry->next;
|
||||
(entry->event)(entry->value);
|
||||
|
@ -464,7 +464,7 @@ bool PIC_RunQueue(void) {
|
|||
}
|
||||
/* Check when to set the new cycle end */
|
||||
if (pic.next_entry) {
|
||||
Bits cycles=PIC_MakeCycles(pic.next_entry->index-index);
|
||||
Bits cycles=(Bits)(pic.next_entry->index*CPU_CycleMax-index_nd);
|
||||
if (!cycles) cycles=1;
|
||||
if (cycles<CPU_CycleLeft) {
|
||||
CPU_Cycles=cycles;
|
||||
|
|
Loading…
Add table
Reference in a new issue