add pagefault checking memory functions to the dynamic core
Imported-from: https://svn.code.sf.net/p/dosbox/code-0/dosbox/trunk@2424
This commit is contained in:
parent
146d4b3380
commit
17ea37fe89
7 changed files with 377 additions and 75 deletions
|
@ -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
|
||||
|
|
|
@ -20,6 +20,8 @@
|
|||
|
||||
#if (C_DYNAMIC_X86)
|
||||
|
||||
#define CHECKED_MEMORY_ACCESS
|
||||
|
||||
#include <assert.h>
|
||||
#include <stdarg.h>
|
||||
#include <stdio.h>
|
||||
|
@ -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;
|
||||
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue