DOSBox-X
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator
include/mem.h
00001 /*
00002  *  Copyright (C) 2002-2015  The DOSBox Team
00003  *
00004  *  This program is free software; you can redistribute it and/or modify
00005  *  it under the terms of the GNU General Public License as published by
00006  *  the Free Software Foundation; either version 2 of the License, or
00007  *  (at your option) any later version.
00008  *
00009  *  This program is distributed in the hope that it will be useful,
00010  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
00011  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00012  *  GNU General Public License for more details.
00013  *
00014  *  You should have received a copy of the GNU General Public License
00015  *  along with this program; if not, write to the Free Software
00016  *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
00017  */
00018 
00019 #ifndef DOSBOX_MEM_H
00020 #define DOSBOX_MEM_H
00021 
00022 #ifndef DOSBOX_DOSBOX_H
00023 #include "dosbox.h"
00024 #endif
00025 
00026 #include "byteorder.h"
00027 
00028 #define MEM_PAGESIZE        (4096U)
00029 
00030 typedef Bit8u const *       ConstHostPt;        /* host (virtual) memory address aka ptr */
00031 
00032 typedef Bit8u *             HostPt;             /* host (virtual) memory address aka ptr */
00033 
00034 typedef Bit32u              PhysPt;      /* guest physical memory pointer */
00035 typedef Bit32u              LinearPt;    /* guest linear memory address */
00036 typedef Bit32u              RealPt;      /* guest real-mode memory address (16:16 -> seg:offset) */
00037 typedef Bit16u              SegmentVal;  /* guest segment value */
00038 
00039 typedef Bit32s              MemHandle;
00040 
00041 extern HostPt               MemBase;
00042 
00043 HostPt                      GetMemBase(void);
00044 bool                        MEM_A20_Enabled(void);
00045 void                        MEM_A20_Enable(bool enable);
00046 
00047 /* Memory management / EMS mapping */
00048 HostPt                      MEM_GetBlockPage(void);
00049 Bitu                        MEM_FreeTotal(void);           //Free 4 kb pages
00050 Bitu                        MEM_FreeLargest(void);         //Largest free 4 kb pages block
00051 Bitu                        MEM_TotalPages(void);          //Total amount of 4 kb pages
00052 Bitu                        MEM_AllocatedPages(MemHandle handle); // amount of allocated pages of handle
00053 MemHandle                   MEM_AllocatePages(Bitu pages,bool sequence);
00054 MemHandle                   MEM_AllocatePages_A20_friendly(Bitu pages,bool sequence);
00055 MemHandle                   MEM_GetNextFreePage(void);
00056 PhysPt                      MEM_AllocatePage(void);
00057 void                        MEM_ReleasePages(MemHandle handle);
00058 bool                        MEM_ReAllocatePages(MemHandle & handle,Bitu pages,bool sequence);
00059 
00060 MemHandle                   MEM_NextHandle(MemHandle handle);
00061 MemHandle                   MEM_NextHandleAt(MemHandle handle,Bitu where);
00062 
00063 /* 
00064     The folowing six functions are used everywhere in the end so these should be changed for
00065     Working on big or little endian machines 
00066 */
00067 
00068 #if !defined(C_UNALIGNED_MEMORY)
00069 /* meaning: we're probably being compiled for a processor that doesn't like unaligned WORD access,
00070             on such processors typecasting memory as uint16_t and higher can cause a fault if the
00071         address is not aligned to that datatype when we read/write through it. */
00072 
00073 static INLINE Bit8u host_readb(ConstHostPt const off) {
00074     return *off;
00075 }
00076 static INLINE Bit16u host_readw(ConstHostPt const off) {
00077     return (Bit16u)host_readb(off) + ((Bit16u)host_readb(off+(uintptr_t)1U) << (Bit16u)8U);
00078 }
00079 static INLINE Bit32u host_readd(ConstHostPt const off) {
00080     return (Bit32u)host_readw(off) + ((Bit32u)host_readw(off+(uintptr_t)2U) << (Bit32u)16U);
00081 }
00082 static INLINE Bit64u host_readq(ConstHostPt const off) {
00083     return (Bit64u)host_readd(off) + ((Bit64u)host_readd(off+(uintptr_t)4U) << (Bit64u)32U);
00084 }
00085 
00086 static INLINE void host_writeb(HostPt const off,const Bit8u val) {
00087     *off = val;
00088 }
00089 static INLINE void host_writew(HostPt const off,const Bit16u val) {
00090     host_writeb(off,   (Bit8u)(val));
00091     host_writeb(off+1U,(Bit8u)(val >> (Bit16u)8U));
00092 }
00093 static INLINE void host_writed(HostPt const off,const Bit32u val) {
00094     host_writew(off,   (Bit16u)(val));
00095     host_writew(off+2U,(Bit16u)(val >> (Bit32u)16U));
00096 }
00097 static INLINE void host_writeq(HostPt const off,const Bit64u val) {
00098     host_writed(off,   (Bit32u)(val));
00099     host_writed(off+4U,(Bit32u)(val >> (Bit64u)32U));
00100 }
00101 
00102 #else
00103 
00104 static INLINE Bit8u host_readb(ConstHostPt const off) {
00105     return *(const Bit8u *)off;
00106 }
00107 static INLINE Bit16u host_readw(ConstHostPt const off) {
00108     return le16toh((*(const Bit16u *)off)); // BSD endian.h
00109 }
00110 static INLINE Bit32u host_readd(ConstHostPt const off) {
00111     return le32toh((*(const Bit32u *)off)); // BSD endian.h
00112 }
00113 static INLINE Bit64u host_readq(ConstHostPt const off) {
00114     return le64toh((*(const Bit64u *)off)); // BSD endian.h
00115 }
00116 
00117 static INLINE void host_writeb(HostPt const off,const Bit8u val) {
00118     *(Bit8u *)(off) = val;
00119 }
00120 static INLINE void host_writew(HostPt const off,const Bit16u val) {
00121     *(Bit16u *)(off) = htole16(val);
00122 }
00123 static INLINE void host_writed(HostPt const off,const Bit32u val) {
00124     *(Bit32u *)(off) = htole32(val);
00125 }
00126 static INLINE void host_writeq(HostPt const off,const Bit64u val) {
00127     *(Bit64u *)(off) = htole64(val);
00128 }
00129 
00130 #endif
00131 
00132 
00133 static INLINE void var_write(Bit8u * const var, const Bit8u val) {
00134     host_writeb((HostPt)var, val);
00135 }
00136 
00137 static INLINE void var_write(Bit16u * const var, const Bit16u val) {
00138     host_writew((HostPt)var, val);
00139 }
00140 
00141 static INLINE void var_write(Bit32u * const var, const Bit32u val) {
00142     host_writed((HostPt)var, val);
00143 }
00144 
00145 static INLINE void var_write(Bit64u * const var, const Bit64u val) {
00146     host_writeq((HostPt)var, val);
00147 }
00148 
00149 /* The Folowing six functions are slower but they recognize the paged memory system */
00150 
00151 Bit8u  mem_readb(const PhysPt pt);
00152 Bit16u mem_readw(const PhysPt pt);
00153 Bit32u mem_readd(const PhysPt pt);
00154 
00155 void mem_writeb(const PhysPt pt,const Bit8u val);
00156 void mem_writew(const PhysPt pt,const Bit16u val);
00157 void mem_writed(const PhysPt pt,const Bit32u val);
00158 
00159 void phys_writes(PhysPt addr, const char* string, Bitu length);
00160 
00161 /* WARNING: These will cause a segfault or out of bounds access IF
00162  *          addr is beyond the end of memory */
00163 
00164 static INLINE void phys_writeb(const PhysPt addr,const Bit8u val) {
00165     host_writeb(MemBase+addr,val);
00166 }
00167 static INLINE void phys_writew(const PhysPt addr,const Bit16u val) {
00168     host_writew(MemBase+addr,val);
00169 }
00170 static INLINE void phys_writed(const PhysPt addr,const Bit32u val) {
00171     host_writed(MemBase+addr,val);
00172 }
00173 
00174 static INLINE Bit8u phys_readb(const PhysPt addr) {
00175     return host_readb(MemBase+addr);
00176 }
00177 static INLINE Bit16u phys_readw(const PhysPt addr) {
00178     return host_readw(MemBase+addr);
00179 }
00180 static INLINE Bit32u phys_readd(const PhysPt addr) {
00181     return host_readd(MemBase+addr);
00182 }
00183 
00184 /* These don't check for alignment, better be sure it's correct */
00185 
00186 void MEM_BlockWrite(PhysPt pt,void const * const data,Bitu size);
00187 void MEM_BlockRead(PhysPt pt,void * data,Bitu size);
00188 void MEM_BlockWrite32(PhysPt pt,void * data,Bitu size);
00189 void MEM_BlockRead32(PhysPt pt,void * data,Bitu size);
00190 void MEM_BlockCopy(PhysPt dest,PhysPt src,Bitu size);
00191 void MEM_StrCopy(PhysPt pt,char * data,Bitu size);
00192 
00193 void mem_memcpy(PhysPt dest,PhysPt src,Bitu size);
00194 Bitu mem_strlen(PhysPt pt);
00195 void mem_strcpy(PhysPt dest,PhysPt src);
00196 
00197 /* The folowing functions are all shortcuts to the above functions using physical addressing */
00198 
00199 static inline constexpr PhysPt PhysMake(const Bit16u seg,const Bit16u off) {
00200     return ((PhysPt)seg << (PhysPt)4U) + (PhysPt)off;
00201 }
00202 
00203 static inline constexpr Bit16u RealSeg(const RealPt pt) {
00204     return (Bit16u)((RealPt)pt >> (RealPt)16U);
00205 }
00206 
00207 static inline constexpr Bit16u RealOff(const RealPt pt) {
00208     return (Bit16u)((RealPt)pt & (RealPt)0xffffu);
00209 }
00210 
00211 static inline constexpr PhysPt Real2Phys(const RealPt pt) {
00212     return (PhysPt)(((PhysPt)RealSeg(pt) << (PhysPt)4U) + (PhysPt)RealOff(pt));
00213 }
00214 
00215 static inline constexpr RealPt RealMake(const Bit16u seg,const Bit16u off) {
00216     return (RealPt)(((RealPt)seg << (RealPt)16U) + (RealPt)off);
00217 }
00218 
00219 /* convert physical address to 4:16 real pointer (example: 0xABCDE -> 0xA000:0xBCDE) */
00220 static inline constexpr RealPt PhysToReal416(const PhysPt phys) {
00221     return RealMake((Bit16u)(((PhysPt)phys >> (PhysPt)4U) & (PhysPt)0xF000U),(Bit16u)((PhysPt)phys & (PhysPt)0xFFFFU));
00222 }
00223 
00224 static inline constexpr PhysPt RealVecAddress(const Bit8u vec) {
00225     return (PhysPt)((unsigned int)vec << 2U);
00226 }
00227 
00228 
00229 static INLINE Bit8u real_readb(const Bit16u seg,const Bit16u off) {
00230     return mem_readb(PhysMake(seg,off));
00231 }
00232 static INLINE Bit16u real_readw(const Bit16u seg,const Bit16u off) {
00233     return mem_readw(PhysMake(seg,off));
00234 }
00235 static INLINE Bit32u real_readd(const Bit16u seg,const Bit16u off) {
00236     return mem_readd(PhysMake(seg,off));
00237 }
00238 
00239 static INLINE void real_writeb(const Bit16u seg,const Bit16u off,const Bit8u val) {
00240     mem_writeb(PhysMake(seg,off),val);
00241 }
00242 static INLINE void real_writew(const Bit16u seg,const Bit16u off,const Bit16u val) {
00243     mem_writew(PhysMake(seg,off),val);
00244 }
00245 static INLINE void real_writed(const Bit16u seg,const Bit16u off,const Bit32u val) {
00246     mem_writed(PhysMake(seg,off),val);
00247 }
00248 
00249 
00250 static INLINE RealPt RealGetVec(const Bit8u vec) {
00251     return mem_readd(RealVecAddress(vec));
00252 }
00253 
00254 static INLINE void RealSetVec(const Bit8u vec,const RealPt pt) {
00255     mem_writed(RealVecAddress(vec),(Bit32u)pt);
00256 }
00257 
00258 static INLINE void RealSetVec(const Bit8u vec,const RealPt pt,RealPt &old) {
00259     const PhysPt addr = RealVecAddress(vec);
00260     old = mem_readd(addr);
00261     mem_writed(addr,pt);
00262 }
00263 
00264 #endif
00265