1
0
Fork 0

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:
Sebastian Strohhäcker 2006-01-07 14:17:53 +00:00
parent 146d4b3380
commit 17ea37fe89
7 changed files with 377 additions and 75 deletions

View file

@ -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

View file

@ -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;

View file

@ -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

View file

@ -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

View file

@ -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);

View file

@ -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;
}
};

View file

@ -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);
}