diff --git a/include/paging.h b/include/paging.h index 4652b6a8..d0ffa03b 100644 --- a/include/paging.h +++ b/include/paging.h @@ -16,7 +16,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -/* $Id: paging.h,v 1.19 2005-12-20 08:42:40 qbix79 Exp $ */ +/* $Id: paging.h,v 1.20 2006-01-07 14:17:53 c2woody Exp $ */ #ifndef DOSBOX_PAGING_H #define DOSBOX_PAGING_H @@ -54,6 +54,12 @@ public: virtual void writeb(PhysPt addr,Bitu val); virtual void writew(PhysPt addr,Bitu val); virtual void writed(PhysPt addr,Bitu val); + virtual bool readb_checked(PhysPt addr, Bitu * val); + virtual bool readw_checked(PhysPt addr, Bitu * val); + virtual bool readd_checked(PhysPt addr, Bitu * val); + virtual bool writeb_checked(PhysPt addr,Bitu val); + virtual bool writew_checked(PhysPt addr,Bitu val); + virtual bool writed_checked(PhysPt addr,Bitu val); virtual HostPt GetHostPt(Bitu phys_page); Bitu flags; }; @@ -159,6 +165,11 @@ Bit32u mem_unalignedreadd(PhysPt address); void mem_unalignedwritew(PhysPt address,Bit16u val); void mem_unalignedwrited(PhysPt address,Bit32u val); +bool mem_unalignedreadw_checked_x86(PhysPt address,Bit16u * val); +bool mem_unalignedreadd_checked_x86(PhysPt address,Bit32u * val); +bool mem_unalignedwritew_checked_x86(PhysPt address,Bit16u val); +bool mem_unalignedwrited_checked_x86(PhysPt address,Bit32u val); + /* Special inlined memory reading/writing */ INLINE Bit8u mem_readb_inline(PhysPt address) { @@ -247,4 +258,81 @@ INLINE void mem_writed_dyncorex86(PhysPt address,Bit32u val) { } else mem_unalignedwrited(address,val); } + +INLINE bool mem_readb_checked_x86(PhysPt address, Bit8u * val) { + Bitu index=(address>>12); + if (paging.tlb.read[index]) { + *val=host_readb(paging.tlb.read[index]+address); + return false; + } else { + Bitu uval; + bool retval; + retval=paging.tlb.handler[index]->readb_checked(address, &uval); + *val=(Bit8u)uval; + return retval; + } +} + +INLINE bool mem_readw_checked_x86(PhysPt address, Bit16u * val) { + if ((address & 0xfff)<0xfff) { + Bitu index=(address>>12); + if (paging.tlb.read[index]) { + *val=host_readw(paging.tlb.read[index]+address); + return false; + } else { + Bitu uval; + bool retval; + retval=paging.tlb.handler[index]->readw_checked(address, &uval); + *val=(Bit16u)uval; + return retval; + } + } else return mem_unalignedreadw_checked_x86(address, val); +} + + +INLINE bool mem_readd_checked_x86(PhysPt address, Bit32u * val) { + if ((address & 0xfff)<0xffd) { + Bitu index=(address>>12); + if (paging.tlb.read[index]) { + *val=host_readd(paging.tlb.read[index]+address); + return false; + } else { + Bitu uval; + bool retval; + retval=paging.tlb.handler[index]->readd_checked(address, &uval); + *val=(Bit32u)uval; + return retval; + } + } else return mem_unalignedreadd_checked_x86(address, val); +} + +INLINE bool mem_writeb_checked_x86(PhysPt address,Bit8u val) { + Bitu index=(address>>12); + if (paging.tlb.write[index]) { + host_writeb(paging.tlb.write[index]+address,val); + return false; + } else return paging.tlb.handler[index]->writeb_checked(address,val); +} + +INLINE bool mem_writew_checked_x86(PhysPt address,Bit16u val) { + if ((address & 0xfff)<0xfff) { + Bitu index=(address>>12); + if (paging.tlb.write[index]) { + host_writew(paging.tlb.write[index]+address,val); + return false; + } else return paging.tlb.handler[index]->writew_checked(address,val); + } else return mem_unalignedwritew_checked_x86(address,val); +} + +INLINE bool mem_writed_checked_x86(PhysPt address,Bit32u val) { + if ((address & 0xfff)<0xffd) { + Bitu index=(address>>12); + if (paging.tlb.write[index]) { + host_writed(paging.tlb.write[index]+address,val); + return false; + } else return paging.tlb.handler[index]->writed_checked(address,val); + } else return mem_unalignedwrited_checked_x86(address,val); +} + + #endif diff --git a/src/cpu/core_dyn_x86.cpp b/src/cpu/core_dyn_x86.cpp index 07bfa63e..09569015 100644 --- a/src/cpu/core_dyn_x86.cpp +++ b/src/cpu/core_dyn_x86.cpp @@ -20,6 +20,8 @@ #if (C_DYNAMIC_X86) +#define CHECKED_MEMORY_ACCESS + #include #include #include @@ -43,8 +45,13 @@ #include "paging.h" #include "inout.h" +#ifdef CHECKED_MEMORY_ACCESS +#define CACHE_TOTAL (1024*1024) +#define CACHE_MAXSIZE (4096*3) +#else #define CACHE_TOTAL (512*1024) #define CACHE_MAXSIZE (4096) +#endif #define CACHE_BLOCKS (32*1024) #define CACHE_ALIGN (16) #define CACHE_PAGES (128) @@ -154,7 +161,7 @@ static void IllegalOption(const char* msg) { #include "core_dyn_x86/cache.h" static struct { - Bitu callback; + Bitu callback,readdata; } core_dyn; diff --git a/src/cpu/core_dyn_x86/decoder.h b/src/cpu/core_dyn_x86/decoder.h index c0c53e01..323bc5bf 100644 --- a/src/cpu/core_dyn_x86/decoder.h +++ b/src/cpu/core_dyn_x86/decoder.h @@ -100,41 +100,6 @@ static Bit32u decode_fetchd(void) { return mem_readd(decode.code-4); } -static void dyn_read_byte(DynReg * addr,DynReg * dst,Bitu high) { - if (high) gen_call_function((void *)&mem_readb,"%Dd%Rh",addr,dst); - else gen_call_function((void *)&mem_readb,"%Dd%Rl",addr,dst); -} -static void dyn_write_byte(DynReg * addr,DynReg * val,Bitu high) { - if (high) gen_call_function((void *)&mem_writeb,"%Dd%Dh",addr,val); - else gen_call_function((void *)&mem_writeb,"%Dd%Dd",addr,val); -} -static void dyn_read_word(DynReg * addr,DynReg * dst,bool dword) { - if (dword) gen_call_function((void *)&mem_readd_dyncorex86,"%Dd%Rd",addr,dst); - else gen_call_function((void *)&mem_readw_dyncorex86,"%Dd%Rw",addr,dst); -} -static void dyn_write_word(DynReg * addr,DynReg * val,bool dword) { - if (dword) gen_call_function((void *)&mem_writed_dyncorex86,"%Dd%Dd",addr,val); - else gen_call_function((void *)&mem_writew_dyncorex86,"%Dd%Dd",addr,val); -} - - -static void dyn_read_byte_release(DynReg * addr,DynReg * dst,Bitu high) { - if (high) gen_call_function((void *)&mem_readb,"%Drd%Rh",addr,dst); - else gen_call_function((void *)&mem_readb,"%Drd%Rl",addr,dst); -} -static void dyn_write_byte_release(DynReg * addr,DynReg * val,Bitu high) { - if (high) gen_call_function((void *)&mem_writeb,"%Drd%Dh",addr,val); - else gen_call_function((void *)&mem_writeb,"%Drd%Dd",addr,val); -} -static void dyn_read_word_release(DynReg * addr,DynReg * dst,bool dword) { - if (dword) gen_call_function((void *)&mem_readd_dyncorex86,"%Drd%Rd",addr,dst); - else gen_call_function((void *)&mem_readw_dyncorex86,"%Drd%Rw",addr,dst); -} -static void dyn_write_word_release(DynReg * addr,DynReg * val,bool dword) { - if (dword) gen_call_function((void *)&mem_writed_dyncorex86,"%Drd%Dd",addr,val); - else gen_call_function((void *)&mem_writew_dyncorex86,"%Drd%Dd",addr,val); -} - static void dyn_reduce_cycles(void) { gen_protectflags(); @@ -166,16 +131,139 @@ static void dyn_set_eip_last_end(DynReg * endreg) { gen_dop_word_imm(DOP_ADD,decode.big_op,DREG(EIP),decode.op_start-decode.code_start); } - static INLINE void dyn_set_eip_end(void) { - gen_protectflags(); +static INLINE void dyn_set_eip_end(void) { + gen_protectflags(); gen_dop_word_imm(DOP_ADD,cpu.code.big,DREG(EIP),decode.code-decode.code_start); - } +} - static INLINE void dyn_set_eip_last(void) { - gen_protectflags(); +static INLINE void dyn_set_eip_last(void) { + gen_protectflags(); gen_dop_word_imm(DOP_ADD,cpu.code.big,DREG(EIP),decode.op_start-decode.code_start); } + +static void DynRunException(void) { + CPU_Exception(cpu.exception.which,cpu.exception.error); +} + +static void dyn_check_bool_exception(DynReg * check) { + Bit8u * branch;DynState state; + gen_dop_byte(DOP_OR,check,0,check,0); + branch=gen_create_branch(BR_Z); + dyn_savestate(&state); + dyn_flags_gen_to_host(); + dyn_reduce_cycles(); + dyn_set_eip_last(); + dyn_save_critical_regs(); + gen_call_function((void *)&DynRunException,""); + dyn_flags_host_to_gen(); + gen_return(BR_Normal); + dyn_loadstate(&state); + gen_fill_branch(branch); +} + +static void dyn_check_bool_exception_al(void) { + Bit8u * branch;DynState state; + cache_addw(0xc00a); // or al, al + branch=gen_create_branch(BR_Z); + dyn_savestate(&state); + dyn_flags_gen_to_host(); + dyn_reduce_cycles(); + dyn_set_eip_last(); + dyn_save_critical_regs(); + gen_call_function((void *)&DynRunException,""); + dyn_flags_host_to_gen(); + gen_return(BR_Normal); + dyn_loadstate(&state); + gen_fill_branch(branch); +} + +#ifdef CHECKED_MEMORY_ACCESS +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); + dyn_check_bool_exception_al(); + gen_mov_host(&core_dyn.readdata,dst,1,high); +} +static void dyn_write_byte(DynReg * addr,DynReg * val,Bitu high) { + gen_protectflags(); + if (high) gen_call_function((void *)&mem_writeb_checked_x86,"%Dd%Dh",addr,val); + else gen_call_function((void *)&mem_writeb_checked_x86,"%Dd%Dd",addr,val); + dyn_check_bool_exception_al(); +} +static void dyn_read_word(DynReg * addr,DynReg * dst,bool dword) { + gen_protectflags(); + if (dword) gen_call_function((void *)&mem_readd_checked_x86,"%Dd%Id",addr,&core_dyn.readdata); + else 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,dword?4:2); +} +static void dyn_write_word(DynReg * addr,DynReg * val,bool dword) { + gen_protectflags(); + if (dword) gen_call_function((void *)&mem_writed_checked_x86,"%Dd%Dd",addr,val); + else gen_call_function((void *)&mem_writew_checked_x86,"%Dd%Dd",addr,val); + dyn_check_bool_exception_al(); +} +static void dyn_read_byte_release(DynReg * addr,DynReg * dst,Bitu high) { + gen_protectflags(); + gen_call_function((void *)&mem_readb_checked_x86,"%Ddr%Id",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_x86,"%Ddr%Dh",addr,val); + else gen_call_function((void *)&mem_writeb_checked_x86,"%Ddr%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_x86,"%Ddr%Id",addr,&core_dyn.readdata); + else 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,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_x86,"%Ddr%Dd",addr,val); + else gen_call_function((void *)&mem_writew_checked_x86,"%Ddr%Dd",addr,val); + dyn_check_bool_exception_al(); +} +#else +static void dyn_read_byte(DynReg * addr,DynReg * dst,Bitu high) { + if (high) gen_call_function((void *)&mem_readb,"%Dd%Rh",addr,dst); + else gen_call_function((void *)&mem_readb,"%Dd%Rl",addr,dst); +} +static void dyn_write_byte(DynReg * addr,DynReg * val,Bitu high) { + if (high) gen_call_function((void *)&mem_writeb,"%Dd%Dh",addr,val); + else gen_call_function((void *)&mem_writeb,"%Dd%Dd",addr,val); +} +static void dyn_read_word(DynReg * addr,DynReg * dst,bool dword) { + if (dword) gen_call_function((void *)&mem_readd_dyncorex86,"%Dd%Rd",addr,dst); + else gen_call_function((void *)&mem_readw_dyncorex86,"%Dd%Rw",addr,dst); +} +static void dyn_write_word(DynReg * addr,DynReg * val,bool dword) { + if (dword) gen_call_function((void *)&mem_writed_dyncorex86,"%Dd%Dd",addr,val); + else gen_call_function((void *)&mem_writew_dyncorex86,"%Dd%Dd",addr,val); +} +static void dyn_read_byte_release(DynReg * addr,DynReg * dst,Bitu high) { + if (high) gen_call_function((void *)&mem_readb,"%Ddr%Rh",addr,dst); + else gen_call_function((void *)&mem_readb,"%Ddr%Rl",addr,dst); +} +static void dyn_write_byte_release(DynReg * addr,DynReg * val,Bitu high) { + if (high) gen_call_function((void *)&mem_writeb,"%Ddr%Dh",addr,val); + else gen_call_function((void *)&mem_writeb,"%Ddr%Dd",addr,val); +} +static void dyn_read_word_release(DynReg * addr,DynReg * dst,bool dword) { + if (dword) gen_call_function((void *)&mem_readd_dyncorex86,"%Ddr%Rd",addr,dst); + else gen_call_function((void *)&mem_readw_dyncorex86,"%Ddr%Rw",addr,dst); +} +static void dyn_write_word_release(DynReg * addr,DynReg * val,bool dword) { + if (dword) gen_call_function((void *)&mem_writed_dyncorex86,"%Ddr%Dd",addr,val); + else gen_call_function((void *)&mem_writew_dyncorex86,"%Ddr%Dd",addr,val); +} +#endif + static void dyn_push(DynReg * dynreg) { gen_protectflags(); if (decode.big_op) { @@ -345,26 +433,6 @@ skip_extend_word: #include "helpers.h" #include "string.h" -static void DynRunException(void) { - CPU_Exception(cpu.exception.which,cpu.exception.error); -} - -static void dyn_check_bool_exception(DynReg * check) { - Bit8u * branch;DynState state; - gen_dop_byte(DOP_OR,check,0,check,0); - branch=gen_create_branch(BR_Z); - dyn_savestate(&state); - dyn_flags_gen_to_host(); - dyn_reduce_cycles(); - dyn_set_eip_last(); - dyn_save_critical_regs(); - gen_call_function((void *)&DynRunException,""); - dyn_flags_host_to_gen(); - gen_return(BR_Normal); - dyn_loadstate(&state); - gen_fill_branch(branch); -} - static void dyn_dop_ebgb(DualOps op) { dyn_get_modrm();DynReg * rm_reg=&DynRegs[decode.modrm.reg&3]; @@ -416,6 +484,9 @@ static void dyn_mov_ebib(void) { if (decode.modrm.mod<3) { dyn_fill_ea(); gen_call_write(DREG(EA),decode_fetchb(),1); +#ifdef CHECKED_MEMORY_ACCESS + dyn_check_bool_exception_al(); +#endif } else { gen_dop_byte_imm(DOP_MOV,&DynRegs[decode.modrm.rm&3],decode.modrm.rm&4,decode_fetchb()); } @@ -534,6 +605,9 @@ static void dyn_mov_eviv(void) { if (decode.modrm.mod<3) { dyn_fill_ea(); gen_call_write(DREG(EA),decode.big_op ? decode_fetchd() : decode_fetchw(),decode.big_op?4:2); +#ifdef CHECKED_MEMORY_ACCESS + dyn_check_bool_exception_al(); +#endif } else { gen_dop_word_imm(DOP_MOV,decode.big_op,&DynRegs[decode.modrm.rm],decode.big_op ? decode_fetchd() : decode_fetchw()); } @@ -597,7 +671,7 @@ static void dyn_grp1_eb_ib(void) { if (op==DOP_ADC || op==DOP_SBB) gen_needcarry(); else set_skipflags(false); } - gen_dop_byte_imm(grp1_table[decode.modrm.reg],DREG(TMPB),0,decode_fetchb()); + gen_dop_byte_imm(op,DREG(TMPB),0,decode_fetchb()); if (op!=DOP_CMP) dyn_write_byte_release(DREG(EA),DREG(TMPB),false); else gen_releasereg(DREG(EA)); gen_releasereg(DREG(TMPB)); @@ -606,7 +680,7 @@ static void dyn_grp1_eb_ib(void) { if (op==DOP_ADC || op==DOP_SBB) gen_needcarry(); else gen_discardflags(); } - gen_dop_byte_imm(grp1_table[decode.modrm.reg],&DynRegs[decode.modrm.rm&3],decode.modrm.rm&4,decode_fetchb()); + gen_dop_byte_imm(op,&DynRegs[decode.modrm.rm&3],decode.modrm.rm&4,decode_fetchb()); } } @@ -622,7 +696,7 @@ static void dyn_grp1_ev_ivx(bool withbyte) { if (op==DOP_ADC || op==DOP_SBB) gen_needcarry(); else set_skipflags(false); } - gen_dop_word_imm(grp1_table[decode.modrm.reg],decode.big_op,DREG(TMPW),imm); + gen_dop_word_imm(op,decode.big_op,DREG(TMPW),imm); if (op!=DOP_CMP) dyn_write_word_release(DREG(EA),DREG(TMPW),decode.big_op); else gen_releasereg(DREG(EA)); gen_releasereg(DREG(TMPW)); @@ -632,7 +706,7 @@ static void dyn_grp1_ev_ivx(bool withbyte) { if (op==DOP_ADC || op==DOP_SBB) gen_needcarry(); else gen_discardflags(); } - gen_dop_word_imm(grp1_table[decode.modrm.reg],decode.big_op,&DynRegs[decode.modrm.rm],imm); + gen_dop_word_imm(op,decode.big_op,&DynRegs[decode.modrm.rm],imm); } } @@ -1604,9 +1678,9 @@ restart_prefix: { dyn_get_modrm();DynReg * src; if (decode.modrm.mod<3) { - dyn_fill_ea(); - dyn_read_word(DREG(EA),DREG(TMPW),decode.big_op); - src=DREG(TMPW); + dyn_fill_ea(); + dyn_read_word(DREG(EA),DREG(TMPW),decode.big_op); + src=DREG(TMPW); } else src=&DynRegs[decode.modrm.rm]; switch (decode.modrm.reg) { case 0x0://INC Ev diff --git a/src/cpu/core_dyn_x86/risc_x86.h b/src/cpu/core_dyn_x86/risc_x86.h index 11430f1b..e7d0f6fa 100644 --- a/src/cpu/core_dyn_x86/risc_x86.h +++ b/src/cpu/core_dyn_x86/risc_x86.h @@ -721,12 +721,21 @@ static void gen_call_write(DynReg * dr,Bit32u val,Bitu write_size) { x86gen.regs[X86_REG_EDX]->Clear(); /* Do the actual call to the procedure */ cache_addb(0xe8); +#ifdef CHECKED_MEMORY_ACCESS + switch (write_size) { + case 1: cache_addd((Bit32u)mem_writeb_checked_x86 - (Bit32u)cache.pos-4); break; + case 2: cache_addd((Bit32u)mem_writew_checked_x86 - (Bit32u)cache.pos-4); break; + case 4: cache_addd((Bit32u)mem_writed_checked_x86 - (Bit32u)cache.pos-4); break; + default: IllegalOption("gen_call_write"); + } +#else switch (write_size) { case 1: cache_addd((Bit32u)mem_writeb - (Bit32u)cache.pos-4); break; case 2: cache_addd((Bit32u)mem_writew_dyncorex86 - (Bit32u)cache.pos-4); break; case 4: cache_addd((Bit32u)mem_writed_dyncorex86 - (Bit32u)cache.pos-4); break; default: IllegalOption("gen_call_write"); } +#endif cache_addw(0xc483); //ADD ESP,8 cache_addb(2*4); @@ -812,6 +821,20 @@ static void gen_load_host(void * data,DynReg * dr1,Bitu size) { 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/cpu/core_dyn_x86/string.h b/src/cpu/core_dyn_x86/string.h index 4c8a710c..13748c56 100644 --- a/src/cpu/core_dyn_x86/string.h +++ b/src/cpu/core_dyn_x86/string.h @@ -80,13 +80,12 @@ static void dyn_string(STRING_OP op) { dyn_savestate(&rep_state); Bit8u * rep_start=cache.pos; Bit8u * rep_ecx_jmp; - /* Check if ECX!=zero and decrease it */ + /* Check if ECX!=zero */ if (decode.rep) { gen_dop_word(DOP_OR,decode.big_addr,DREG(ECX),DREG(ECX)); Bit8u * branch_ecx=gen_create_branch(BR_NZ); rep_ecx_jmp=gen_create_jump(); gen_fill_branch(branch_ecx); - gen_sop_word(SOP_DEC,decode.big_addr,DREG(ECX)); } if (usesi) { if (!decode.big_addr) { @@ -95,7 +94,6 @@ static void dyn_string(STRING_OP op) { } else { gen_lea(DREG(EA),si_base,DREG(ESI),0,0); } - gen_dop_word(DOP_ADD,decode.big_addr,DREG(ESI),DREG(TMPW)); switch (op&3) { case 0:dyn_read_byte(DREG(EA),tmp_reg,false);break; case 1:dyn_read_word(DREG(EA),tmp_reg,false);break; @@ -117,7 +115,6 @@ static void dyn_string(STRING_OP op) { } else { gen_lea(DREG(EA),di_base,DREG(EDI),0,0); } - gen_dop_word(DOP_ADD,decode.big_addr,DREG(EDI),DREG(TMPW)); /* Maybe something special to be done to fill the value */ switch (op) { case STR_INSB: @@ -143,8 +140,14 @@ static void dyn_string(STRING_OP op) { } } gen_releasereg(DREG(EA));gen_releasereg(DREG(TMPB)); + + /* update registers */ + if (usesi) gen_dop_word(DOP_ADD,decode.big_addr,DREG(ESI),DREG(TMPW)); + if (usedi) gen_dop_word(DOP_ADD,decode.big_addr,DREG(EDI),DREG(TMPW)); + if (decode.rep) { DynState cycle_state; + gen_sop_word(SOP_DEC,decode.big_addr,DREG(ECX)); gen_sop_word(SOP_DEC,true,DREG(CYCLES)); gen_releasereg(DREG(CYCLES)); dyn_savestate(&cycle_state); diff --git a/src/cpu/paging.cpp b/src/cpu/paging.cpp index 65f3d4ee..b80c7c0e 100644 --- a/src/cpu/paging.cpp +++ b/src/cpu/paging.cpp @@ -67,6 +67,25 @@ void PageHandler::writed(PhysPt addr,Bitu val) { writeb(addr+3,(Bit8u) (val >> 24)); }; +bool PageHandler::readb_checked(PhysPt addr, Bitu * val) { + *val=readb(addr); return false; +} +bool PageHandler::readw_checked(PhysPt addr, Bitu * val) { + *val=readw(addr); return false; +} +bool PageHandler::readd_checked(PhysPt addr, Bitu * val) { + *val=readd(addr); return false; +} +bool PageHandler::writeb_checked(PhysPt addr,Bitu val) { + writeb(addr,val); return false; +} +bool PageHandler::writew_checked(PhysPt addr,Bitu val) { + writew(addr,val); return false; +} +bool PageHandler::writed_checked(PhysPt addr,Bitu val) { + writed(addr,val); return false; +} + HostPt PageHandler::GetHostPt(Bitu phys_page) { return 0; } @@ -161,7 +180,43 @@ public: InitPage(addr,true); mem_writed(addr,val); } - void InitPage(Bitu lin_addr,bool writing) { + bool readb_checked(PhysPt addr, Bitu * val) { + if (InitPage(addr,false,true)) { + *val=mem_readb(addr); + return false; + } else return true; + } + bool readw_checked(PhysPt addr, Bitu * val) { + if (InitPage(addr,false,true)){ + *val=mem_readw(addr); + return false; + } else return true; + } + bool readd_checked(PhysPt addr, Bitu * val) { + if (InitPage(addr,false,true)) { + *val=mem_readd(addr); + return false; + } else return true; + } + bool writeb_checked(PhysPt addr,Bitu val) { + if (InitPage(addr,true,true)) { + mem_writeb(addr,val); + return false; + } else return true; + } + bool writew_checked(PhysPt addr,Bitu val) { + if (InitPage(addr,true,true)) { + mem_writew(addr,val); + return false; + } else return true; + } + bool writed_checked(PhysPt addr,Bitu val) { + if (InitPage(addr,true,true)) { + mem_writed(addr,val); + return false; + } else return true; + } + bool InitPage(Bitu lin_addr,bool writing,bool check_only=false) { Bitu lin_page=lin_addr >> 12; Bitu phys_page; if (paging.enabled) { @@ -171,6 +226,12 @@ public: X86PageEntry table; table.load=phys_readd(table_addr); if (!table.block.p) { + if (check_only) { + paging.cr2=lin_addr; + cpu.exception.which=14; + cpu.exception.error=writing?0x02:0x00; + return false; + } LOG(LOG_PAGING,LOG_NORMAL)("NP Table"); PAGING_PageFault(lin_addr,table_addr,false,writing?0x02:0x00); table.load=phys_readd(table_addr); @@ -185,6 +246,12 @@ public: Bitu entry_addr=(table.block.base<<12)+t_index*4; entry.load=phys_readd(entry_addr); if (!entry.block.p) { + if (check_only) { + paging.cr2=lin_addr; + cpu.exception.which=14; + cpu.exception.error=writing?0x02:0x00; + return false; + } // LOG(LOG_PAGING,LOG_NORMAL)("NP Page"); PAGING_PageFault(lin_addr,entry_addr,false,writing?0x02:0x00); entry.load=phys_readd(entry_addr); @@ -194,9 +261,16 @@ public: if (cpu.cpl==3) { if ((entry.block.us==0) || (table.block.us==0) && (((entry.block.wr==0) || (table.block.wr==0)) && writing)) { LOG(LOG_PAGING,LOG_NORMAL)("Page access denied: cpl=%i, %x:%x:%x:%x",cpu.cpl,entry.block.us,table.block.us,entry.block.wr,table.block.wr); + if (check_only) { + paging.cr2=lin_addr; + cpu.exception.which=14; + cpu.exception.error=0x05 | (writing?0x02:0x00); + return false; + } PAGING_PageFault(lin_addr,entry_addr,writing,0x05 | (writing?0x02:0x00)); } } + if (check_only) return true; if ((!entry.block.a) || (!entry.block.d)) { entry.block.a=1; //Set access entry.block.d=1; //Set dirty @@ -208,6 +282,7 @@ public: else phys_page=lin_page; } PAGING_LinkPage(lin_page,phys_page); + return true; } }; diff --git a/src/hardware/memory.cpp b/src/hardware/memory.cpp index c434ca9a..b433960c 100644 --- a/src/hardware/memory.cpp +++ b/src/hardware/memory.cpp @@ -16,7 +16,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -/* $Id: memory.cpp,v 1.41 2005-12-05 21:25:56 c2woody Exp $ */ +/* $Id: memory.cpp,v 1.42 2006-01-07 14:17:53 c2woody Exp $ */ #include "dosbox.h" #include "mem.h" @@ -437,6 +437,38 @@ void mem_unalignedwrited(PhysPt address,Bit32u val) { } +bool mem_unalignedreadw_checked_x86(PhysPt address, Bit16u * val) { + Bit8u rval1,rval2; + if (mem_readb_checked_x86(address+0, &rval1)) return true; + if (mem_readb_checked_x86(address+1, &rval2)) return true; + *val=(Bit16u)(((Bit8u)rval1) | (((Bit8u)rval2) << 8)); + return false; +} + +bool mem_unalignedreadd_checked_x86(PhysPt address, Bit32u * val) { + Bit8u rval1,rval2,rval3,rval4; + if (mem_readb_checked_x86(address+0, &rval1)) return true; + if (mem_readb_checked_x86(address+1, &rval2)) return true; + if (mem_readb_checked_x86(address+2, &rval3)) return true; + if (mem_readb_checked_x86(address+3, &rval4)) return true; + *val=(Bit32u)(((Bit8u)rval1) | (((Bit8u)rval2) << 8) | (((Bit8u)rval3) << 16) | (((Bit8u)rval4) << 24)); + return false; +} + +bool mem_unalignedwritew_checked_x86(PhysPt address,Bit16u val) { + if (mem_writeb_checked_x86(address,(Bit8u)(val & 0xff))) return true;val>>=8; + if (mem_writeb_checked_x86(address+1,(Bit8u)(val & 0xff))) return true; + return false; +} + +bool mem_unalignedwrited_checked_x86(PhysPt address,Bit32u val) { + if (mem_writeb_checked_x86(address,(Bit8u)(val & 0xff))) return true;val>>=8; + if (mem_writeb_checked_x86(address+1,(Bit8u)(val & 0xff))) return true;val>>=8; + if (mem_writeb_checked_x86(address+2,(Bit8u)(val & 0xff))) return true;val>>=8; + if (mem_writeb_checked_x86(address+3,(Bit8u)(val & 0xff))) return true; + return false; +} + Bit8u mem_readb(PhysPt address) { return mem_readb_inline(address); }