From 76f1d11252a5772441ee92eaf03e29f0be4f8ae7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20Strohh=C3=A4cker?= Date: Thu, 18 Jan 2007 14:57:59 +0000 Subject: [PATCH] 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 --- include/pic.h | 4 + src/cpu/core_dyn_x86.cpp | 22 +- src/cpu/core_dyn_x86/cache.h | 92 ++++- src/cpu/core_dyn_x86/decoder.h | 648 ++++++++++++++++++++++++++++++-- src/cpu/core_dyn_x86/risc_x86.h | 121 ++++-- src/hardware/pic.cpp | 8 +- 6 files changed, 815 insertions(+), 80 deletions(-) diff --git a/include/pic.h b/include/pic.h index 47bb2a56..4d37dedb 100644 --- a/include/pic.h +++ b/include/pic.h @@ -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); } diff --git a/src/cpu/core_dyn_x86.cpp b/src/cpu/core_dyn_x86.cpp index 7e50cfb3..ebfa816b 100644 --- a/src/cpu/core_dyn_x86.cpp +++ b/src/cpu/core_dyn_x86.cpp @@ -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; diff --git a/src/cpu/core_dyn_x86/cache.h b/src/cpu/core_dyn_x86/cache.h index ecee1b9e..41512c32 100644 --- a/src/cpu/core_dyn_x86/cache.h +++ b/src/cpu/core_dyn_x86/cache.h @@ -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; } diff --git a/src/cpu/core_dyn_x86/decoder.h b/src/cpu/core_dyn_x86/decoder.h index 10973317..35cdd147 100644 --- a/src/cpu/core_dyn_x86/decoder.h +++ b/src/cpu/core_dyn_x86/decoder.h @@ -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; sctgenreg) { + // 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; diff --git a/src/cpu/core_dyn_x86/risc_x86.h b/src/cpu/core_dyn_x86/risc_x86.h index afbbe4f2..d5f15bf7 100644 --- a/src/cpu/core_dyn_x86/risc_x86.h +++ b/src/cpu/core_dyn_x86/risc_x86.h @@ -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 diff --git a/src/hardware/pic.cpp b/src/hardware/pic.cpp index 3b79e162..ebe58f01 100644 --- a/src/hardware/pic.cpp +++ b/src/hardware/pic.cpp @@ -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 @@ -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