mirror of
https://github.com/retro100/dosbox-wii.git
synced 2024-11-04 17:35:10 +01:00
343 lines
9.6 KiB
C++
343 lines
9.6 KiB
C++
/*
|
|
* Copyright (C) 2002-2007 The DOSBox Team
|
|
*
|
|
* This program is free software; you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License as published by
|
|
* the Free Software Foundation; either version 2 of the License, or
|
|
* (at your option) any later version.
|
|
*
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with this program; if not, write to the Free Software
|
|
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
|
*/
|
|
|
|
/* $Id: paging.h,v 1.24 2007/01/08 19:45:37 qbix79 Exp $ */
|
|
|
|
#ifndef DOSBOX_PAGING_H
|
|
#define DOSBOX_PAGING_H
|
|
|
|
#ifndef DOSBOX_DOSBOX_H
|
|
#include "dosbox.h"
|
|
#endif
|
|
#ifndef DOSBOX_MEM_H
|
|
#include "mem.h"
|
|
#endif
|
|
|
|
class PageDirectory;
|
|
|
|
#define MEM_PAGE_SIZE (4096)
|
|
#define XMS_START (0x110)
|
|
#define TLB_SIZE (1024*1024)
|
|
|
|
#define PFLAG_READABLE 0x1
|
|
#define PFLAG_WRITEABLE 0x2
|
|
#define PFLAG_HASROM 0x4
|
|
#define PFLAG_HASCODE 0x8 //Page contains dynamic code
|
|
#define PFLAG_NOCODE 0x10 //No dynamic code can be generated here
|
|
#define PFLAG_INIT 0x20 //No dynamic code can be generated here
|
|
|
|
#define LINK_START ((1024+64)/4) //Start right after the HMA
|
|
|
|
//Allow 128 mb of memory to be linked
|
|
#define PAGING_LINKS (128*1024/4)
|
|
|
|
class PageHandler {
|
|
public:
|
|
virtual ~PageHandler(void) { }
|
|
virtual Bitu readb(PhysPt addr);
|
|
virtual Bitu readw(PhysPt addr);
|
|
virtual Bitu readd(PhysPt addr);
|
|
virtual void writeb(PhysPt addr,Bitu val);
|
|
virtual void writew(PhysPt addr,Bitu val);
|
|
virtual void writed(PhysPt addr,Bitu val);
|
|
virtual HostPt GetHostReadPt(Bitu phys_page);
|
|
virtual HostPt GetHostWritePt(Bitu phys_page);
|
|
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);
|
|
Bitu flags;
|
|
};
|
|
|
|
/* Some other functions */
|
|
void PAGING_Enable(bool enabled);
|
|
bool PAGING_Enabled(void);
|
|
|
|
Bitu PAGING_GetDirBase(void);
|
|
void PAGING_SetDirBase(Bitu cr3);
|
|
void PAGING_InitTLB(void);
|
|
void PAGING_ClearTLB(void);
|
|
|
|
void PAGING_LinkPage(Bitu lin_page,Bitu phys_page);
|
|
void PAGING_UnlinkPages(Bitu lin_page,Bitu pages);
|
|
/* This maps the page directly, only use when paging is disabled */
|
|
void PAGING_MapPage(Bitu lin_page,Bitu phys_page);
|
|
bool PAGING_MakePhysPage(Bitu & page);
|
|
|
|
void MEM_SetLFB( Bitu page, Bitu pages, PageHandler *handler);
|
|
void MEM_SetPageHandler(Bitu phys_page, Bitu pages, PageHandler * handler);
|
|
void MEM_ResetPageHandler(Bitu phys_page, Bitu pages);
|
|
|
|
|
|
#ifdef _MSC_VER
|
|
#pragma pack (1)
|
|
#endif
|
|
struct X86_PageEntryBlock{
|
|
#ifdef WORDS_BIGENDIAN
|
|
Bit32u base:20;
|
|
Bit32u avl:3;
|
|
Bit32u g:1;
|
|
Bit32u pat:1;
|
|
Bit32u d:1;
|
|
Bit32u a:1;
|
|
Bit32u pcd:1;
|
|
Bit32u pwt:1;
|
|
Bit32u us:1;
|
|
Bit32u wr:1;
|
|
Bit32u p:1;
|
|
#else
|
|
Bit32u p:1;
|
|
Bit32u wr:1;
|
|
Bit32u us:1;
|
|
Bit32u pwt:1;
|
|
Bit32u pcd:1;
|
|
Bit32u a:1;
|
|
Bit32u d:1;
|
|
Bit32u pat:1;
|
|
Bit32u g:1;
|
|
Bit32u avl:3;
|
|
Bit32u base:20;
|
|
#endif
|
|
} GCC_ATTRIBUTE(packed);
|
|
#ifdef _MSC_VER
|
|
#pragma pack ()
|
|
#endif
|
|
|
|
|
|
union X86PageEntry {
|
|
Bit32u load;
|
|
X86_PageEntryBlock block;
|
|
};
|
|
|
|
struct PagingBlock {
|
|
Bitu cr3;
|
|
Bitu cr2;
|
|
struct {
|
|
Bitu page;
|
|
PhysPt addr;
|
|
} base;
|
|
struct {
|
|
HostPt read[TLB_SIZE];
|
|
HostPt write[TLB_SIZE];
|
|
PageHandler * handler[TLB_SIZE];
|
|
Bit32u phys_page[TLB_SIZE];
|
|
} tlb;
|
|
struct {
|
|
Bitu used;
|
|
Bit32u entries[PAGING_LINKS];
|
|
} links;
|
|
Bit32u firstmb[LINK_START];
|
|
bool enabled;
|
|
};
|
|
|
|
extern PagingBlock paging;
|
|
|
|
/* Some support functions */
|
|
|
|
PageHandler * MEM_GetPageHandler(Bitu phys_page);
|
|
|
|
/* Use this helper function to access linear addresses in readX/writeX functions */
|
|
INLINE PhysPt PAGING_GetPhysicalPage(PhysPt linePage) {
|
|
return (paging.tlb.phys_page[linePage>>12]<<12);
|
|
}
|
|
|
|
INLINE PhysPt PAGING_GetPhysicalAddress(PhysPt linAddr) {
|
|
return (paging.tlb.phys_page[linAddr>>12]<<12)|(linAddr&0xfff);
|
|
}
|
|
|
|
|
|
/* Unaligned address handlers */
|
|
Bit16u mem_unalignedreadw(PhysPt address);
|
|
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) {
|
|
Bitu index=(address>>12);
|
|
if (paging.tlb.read[index]) return host_readb(paging.tlb.read[index]+address);
|
|
else return paging.tlb.handler[index]->readb(address);
|
|
}
|
|
|
|
INLINE Bit16u mem_readw_inline(PhysPt address) {
|
|
if (!(address & 1)) {
|
|
Bitu index=(address>>12);
|
|
|
|
if (paging.tlb.read[index]) return host_readw(paging.tlb.read[index]+address);
|
|
else return paging.tlb.handler[index]->readw(address);
|
|
} else return mem_unalignedreadw(address);
|
|
}
|
|
|
|
INLINE Bit32u mem_readd_inline(PhysPt address) {
|
|
if (!(address & 3)) {
|
|
Bitu index=(address>>12);
|
|
|
|
if (paging.tlb.read[index]) return host_readd(paging.tlb.read[index]+address);
|
|
else return paging.tlb.handler[index]->readd(address);
|
|
} else return mem_unalignedreadd(address);
|
|
}
|
|
|
|
INLINE void mem_writeb_inline(PhysPt address,Bit8u val) {
|
|
Bitu index=(address>>12);
|
|
|
|
if (paging.tlb.write[index]) host_writeb(paging.tlb.write[index]+address,val);
|
|
else paging.tlb.handler[index]->writeb(address,val);
|
|
}
|
|
|
|
INLINE void mem_writew_inline(PhysPt address,Bit16u val) {
|
|
if (!(address & 1)) {
|
|
Bitu index=(address>>12);
|
|
|
|
if (paging.tlb.write[index]) host_writew(paging.tlb.write[index]+address,val);
|
|
else paging.tlb.handler[index]->writew(address,val);
|
|
} else mem_unalignedwritew(address,val);
|
|
}
|
|
|
|
INLINE void mem_writed_inline(PhysPt address,Bit32u val) {
|
|
if (!(address & 3)) {
|
|
Bitu index=(address>>12);
|
|
|
|
if (paging.tlb.write[index]) host_writed(paging.tlb.write[index]+address,val);
|
|
else paging.tlb.handler[index]->writed(address,val);
|
|
} else mem_unalignedwrited(address,val);
|
|
}
|
|
|
|
|
|
INLINE Bit16u mem_readw_dyncorex86(PhysPt address) {
|
|
if ((address & 0xfff)<0xfff) {
|
|
Bitu index=(address>>12);
|
|
|
|
if (paging.tlb.read[index]) return host_readw(paging.tlb.read[index]+address);
|
|
else return paging.tlb.handler[index]->readw(address);
|
|
} else return mem_unalignedreadw(address);
|
|
}
|
|
|
|
INLINE Bit32u mem_readd_dyncorex86(PhysPt address) {
|
|
if ((address & 0xfff)<0xffd) {
|
|
Bitu index=(address>>12);
|
|
|
|
if (paging.tlb.read[index]) return host_readd(paging.tlb.read[index]+address);
|
|
else return paging.tlb.handler[index]->readd(address);
|
|
} else return mem_unalignedreadd(address);
|
|
}
|
|
|
|
INLINE void mem_writew_dyncorex86(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);
|
|
else paging.tlb.handler[index]->writew(address,val);
|
|
} else mem_unalignedwritew(address,val);
|
|
}
|
|
|
|
INLINE void mem_writed_dyncorex86(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);
|
|
else paging.tlb.handler[index]->writed(address,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
|