1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185
|
/*
* Copyright (C) 2002-2004 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.12 2004/10/12 10:45:10 harekiet Exp $ */
#ifndef _PAGING_H_
#define _PAGING_H_
#include "dosbox.h"
#include "mem.h"
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 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 GetHostPt(Bitu phys_page);
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,HostPt _pt);
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{
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;
} 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;
bool enabled;
};
extern PagingBlock paging;
/* Some support functions */
PageHandler * MEM_GetPageHandler(Bitu phys_page);
/* 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);
/* 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) return mem_unalignedreadw(address);
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);
}
INLINE Bit32u mem_readd_inline(PhysPt address) {
if (address & 3) return mem_unalignedreadd(address);
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);
}
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) {mem_unalignedwritew(address,val);return;}
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);
}
INLINE void mem_writed_inline(PhysPt address,Bit32u val) {
if (address & 3) {mem_unalignedwrited(address,val);return;}
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);
}
#endif
|