diff --git a/src/cpu/core_dyn_x86.cpp b/src/cpu/core_dyn_x86.cpp index 09569015..1aa13e98 100644 --- a/src/cpu/core_dyn_x86.cpp +++ b/src/cpu/core_dyn_x86.cpp @@ -46,15 +46,15 @@ #include "inout.h" #ifdef CHECKED_MEMORY_ACCESS -#define CACHE_TOTAL (1024*1024) -#define CACHE_MAXSIZE (4096*3) +#define CACHE_PAGES (128*2) +#define CACHE_MAXSIZE (4096*2) #else -#define CACHE_TOTAL (512*1024) +#define CACHE_PAGES (128) #define CACHE_MAXSIZE (4096) #endif +#define CACHE_TOTAL (CACHE_PAGES*4096) #define CACHE_BLOCKS (32*1024) #define CACHE_ALIGN (16) -#define CACHE_PAGES (128) #define DYN_HASH_SHIFT (4) #define DYN_PAGE_HASH (4096>>DYN_HASH_SHIFT) #define DYN_LINKS (16) @@ -119,8 +119,12 @@ enum BlockReturn { BR_OpcodeFull, #endif BR_CallBack, + BR_SMCBlock }; +#define SMC_CURRENT_BLOCK 0xffff + + #define DYNFLG_HAS16 0x1 //Would like 8-bit host reg support #define DYNFLG_HAS8 0x2 //Would like 16-bit host reg support #define DYNFLG_LOAD 0x4 //Load value when accessed @@ -252,6 +256,10 @@ run_block: return CBRET_NONE; case BR_CallBack: return core_dyn.callback; + case BR_SMCBlock: +// LOG_MSG("selfmodification of running block at %x:%x",SegValue(cs),reg_eip); + cpu.exception.which=0; + // fallthrough, let the normal core handle the block-modifying instruction case BR_Opcode: CPU_CycleLeft+=CPU_Cycles; CPU_Cycles=1; diff --git a/src/cpu/core_dyn_x86/cache.h b/src/cpu/core_dyn_x86/cache.h index 9bd30b5e..5f507a5b 100644 --- a/src/cpu/core_dyn_x86/cache.h +++ b/src/cpu/core_dyn_x86/cache.h @@ -66,21 +66,27 @@ public: memset(&hash_map,0,sizeof(hash_map)); memset(&write_map,0,sizeof(write_map)); } - void InvalidateRange(Bitu start,Bitu end) { + bool InvalidateRange(Bitu start,Bitu end) { Bits index=1+(start>>DYN_HASH_SHIFT); + bool is_current_block=false; + Bit32u ip_point=SegPhys(cs)+reg_eip; + ip_point=((paging.tlb.phys_page[ip_point>>12]-phys_page)<<12)+(ip_point&0xfff); while (index>=0) { Bitu map=0; for (Bitu count=start;count<=end;count++) map+=write_map[count]; - if (!map) return; + if (!map) return is_current_block; CacheBlock * block=hash_map[index]; while (block) { CacheBlock * nextblock=block->hash.next; - if (start<=block->page.end && end>=block->page.start) + if (start<=block->page.end && end>=block->page.start) { + if (ip_point<=block->page.end && ip_point>=block->page.start) is_current_block=true; block->Clear(); + } block=nextblock; } index--; } + return is_current_block; } void writeb(PhysPt addr,Bitu val){ addr&=4095; @@ -109,6 +115,45 @@ public: if (!active_count) Release(); } else InvalidateRange(addr,addr+3); } + bool writeb_checked(PhysPt addr,Bitu val) { + addr&=4095; + host_writeb(hostmem+addr,val); + if (!*(Bit8u*)&write_map[addr]) { + if (active_blocks) return false; + active_count--; + if (!active_count) Release(); + } else if (InvalidateRange(addr,addr)) { + cpu.exception.which=SMC_CURRENT_BLOCK; + return true; + } + return false; + } + bool writew_checked(PhysPt addr,Bitu val) { + addr&=4095; + host_writew(hostmem+addr,val); + if (!*(Bit16u*)&write_map[addr]) { + if (active_blocks) return false; + active_count--; + if (!active_count) Release(); + } else if (InvalidateRange(addr,addr+1)) { + cpu.exception.which=SMC_CURRENT_BLOCK; + return true; + } + return false; + } + bool writed_checked(PhysPt addr,Bitu val) { + addr&=4095; + host_writed(hostmem+addr,val); + if (!*(Bit32u*)&write_map[addr]) { + if (active_blocks) return false; + active_count--; + if (!active_count) Release(); + } else if (InvalidateRange(addr,addr+3)) { + cpu.exception.which=SMC_CURRENT_BLOCK; + return true; + } + return false; + } void AddCacheBlock(CacheBlock * block) { Bitu index=1+(block->page.start>>DYN_HASH_SHIFT); block->hash.next=hash_map[index]; diff --git a/src/cpu/core_dyn_x86/decoder.h b/src/cpu/core_dyn_x86/decoder.h index 79a1979c..30f6bdd2 100644 --- a/src/cpu/core_dyn_x86/decoder.h +++ b/src/cpu/core_dyn_x86/decoder.h @@ -142,11 +142,13 @@ static INLINE void dyn_set_eip_last(void) { } -static void DynRunException(Bit32u eip_add,Bit32u cycle_sub,Bit32u dflags) { +static BlockReturn DynRunException(Bit32u eip_add,Bit32u cycle_sub,Bit32u dflags) { reg_flags=(dflags&FMASK_TEST) | (reg_flags&(~FMASK_TEST)); reg_eip+=eip_add; CPU_Cycles-=cycle_sub; + if (cpu.exception.which==SMC_CURRENT_BLOCK) return BR_SMCBlock; CPU_Exception(cpu.exception.which,cpu.exception.error); + return BR_Normal; } static void dyn_check_bool_exception(DynReg * check) { @@ -158,7 +160,7 @@ static void dyn_check_bool_exception(DynReg * check) { dyn_save_critical_regs(); if (cpu.code.big) gen_call_function((void *)&DynRunException,"%Id%Id%F",decode.op_start-decode.code_start,decode.cycles); else gen_call_function((void *)&DynRunException,"%Iw%Id%F",(decode.op_start-decode.code_start)&0xffff,decode.cycles); - gen_return_fast(BR_Normal,false); + gen_return_fast(BR_Normal,true); dyn_loadstate(&state); gen_fill_branch(branch); } @@ -172,7 +174,7 @@ static void dyn_check_bool_exception_al(void) { dyn_save_critical_regs(); if (cpu.code.big) gen_call_function((void *)&DynRunException,"%Id%Id%F",decode.op_start-decode.code_start,decode.cycles); else gen_call_function((void *)&DynRunException,"%Iw%Id%F",(decode.op_start-decode.code_start)&0xffff,decode.cycles); - gen_return_fast(BR_Normal,false); + gen_return_fast(BR_Normal,true); dyn_loadstate(&state); gen_fill_branch(branch); } diff --git a/src/cpu/core_dyn_x86/risc_x86.h b/src/cpu/core_dyn_x86/risc_x86.h index ba662e6f..65d1ab68 100644 --- a/src/cpu/core_dyn_x86/risc_x86.h +++ b/src/cpu/core_dyn_x86/risc_x86.h @@ -853,18 +853,18 @@ static void gen_return(BlockReturn retcode) { cache_addb(0xc3); //RET } -static void gen_return_fast(BlockReturn retcode,bool popflags=true) { +static void gen_return_fast(BlockReturn retcode,bool ret_exception=false) { if (GCC_UNLIKELY(x86gen.flagsactive)) IllegalOption("gen_return_fast"); cache_addw(0x0d8b); //MOV ECX, the flags cache_addd((Bit32u)&cpu_regs.flags); - if (popflags) { + if (!ret_exception) { cache_addw(0xc483); //ADD ESP,4 cache_addb(0x4); - } - if (retcode==0) cache_addw(0xc033); //MOV EAX, 0 - else { - cache_addb(0xb8); //MOV EAX, retcode - cache_addd(retcode); + if (retcode==0) cache_addw(0xc033); //MOV EAX, 0 + else { + cache_addb(0xb8); //MOV EAX, retcode + cache_addd(retcode); + } } cache_addb(0xc3); //RET }