DOSBox-X
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Defines
include/mem.h
00001 /*
00002  *  Copyright (C) 2002-2020  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 along
00015  *  with this program; if not, write to the Free Software Foundation, Inc.,
00016  *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, 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 enabled);
00046 
00047 /* Memory management / EMS mapping */
00048 Bitu                        MEM_FreeTotal(void);           //Free 4 kb pages
00049 Bitu                        MEM_FreeLargest(void);         //Largest free 4 kb pages block
00050 Bitu                        MEM_TotalPages(void);          //Total amount of 4 kb pages
00051 Bitu                        MEM_AllocatedPages(MemHandle handle); // amount of allocated pages of handle
00052 MemHandle                   MEM_AllocatePages(Bitu pages,bool sequence);
00053 MemHandle                   MEM_AllocatePages_A20_friendly(Bitu pages,bool sequence);
00054 MemHandle                   MEM_GetNextFreePage(void);
00055 void                        MEM_ReleasePages(MemHandle handle);
00056 bool                        MEM_ReAllocatePages(MemHandle & handle,Bitu pages,bool sequence);
00057 
00058 MemHandle                   MEM_NextHandle(MemHandle handle);
00059 MemHandle                   MEM_NextHandleAt(MemHandle handle,Bitu where);
00060 
00061 /* 
00062     The folowing six functions are used everywhere in the end so these should be changed for
00063     Working on big or little endian machines 
00064 */
00065 
00066 #if !defined(C_UNALIGNED_MEMORY)
00067 /* meaning: we're probably being compiled for a processor that doesn't like unaligned WORD access,
00068             on such processors typecasting memory as uint16_t and higher can cause a fault if the
00069         address is not aligned to that datatype when we read/write through it. */
00070 
00071 static INLINE Bit8u host_readb(ConstHostPt const off) {
00072     return *off;
00073 }
00074 static INLINE Bit16u host_readw(ConstHostPt const off) {
00075     return (Bit16u)host_readb(off) + ((Bit16u)host_readb(off+(uintptr_t)1U) << (Bit16u)8U);
00076 }
00077 static INLINE Bit32u host_readd(ConstHostPt const off) {
00078     return (Bit32u)host_readw(off) + ((Bit32u)host_readw(off+(uintptr_t)2U) << (Bit32u)16U);
00079 }
00080 static INLINE Bit64u host_readq(ConstHostPt const off) {
00081     return (Bit64u)host_readd(off) + ((Bit64u)host_readd(off+(uintptr_t)4U) << (Bit64u)32U);
00082 }
00083 
00084 static INLINE void host_writeb(HostPt const off,const Bit8u val) {
00085     *off = val;
00086 }
00087 static INLINE void host_writew(HostPt const off,const Bit16u val) {
00088     host_writeb(off,   (Bit8u)(val));
00089     host_writeb(off+1U,(Bit8u)(val >> (Bit16u)8U));
00090 }
00091 static INLINE void host_writed(HostPt const off,const Bit32u val) {
00092     host_writew(off,   (Bit16u)(val));
00093     host_writew(off+2U,(Bit16u)(val >> (Bit32u)16U));
00094 }
00095 static INLINE void host_writeq(HostPt const off,const Bit64u val) {
00096     host_writed(off,   (Bit32u)(val));
00097     host_writed(off+4U,(Bit32u)(val >> (Bit64u)32U));
00098 }
00099 
00100 #else
00101 
00102 static INLINE Bit8u host_readb(ConstHostPt const off) {
00103     return *(const Bit8u *)off;
00104 }
00105 static INLINE Bit16u host_readw(ConstHostPt const off) {
00106     return le16toh((*(const Bit16u *)off)); // BSD endian.h
00107 }
00108 static INLINE Bit32u host_readd(ConstHostPt const off) {
00109     return le32toh((*(const Bit32u *)off)); // BSD endian.h
00110 }
00111 static INLINE Bit64u host_readq(ConstHostPt const off) {
00112     return le64toh((*(const Bit64u *)off)); // BSD endian.h
00113 }
00114 
00115 static INLINE void host_writeb(HostPt const off,const Bit8u val) {
00116     *(Bit8u *)(off) = val;
00117 }
00118 static INLINE void host_writew(HostPt const off,const Bit16u val) {
00119     *(Bit16u *)(off) = htole16(val);
00120 }
00121 static INLINE void host_writed(HostPt const off,const Bit32u val) {
00122     *(Bit32u *)(off) = htole32(val);
00123 }
00124 static INLINE void host_writeq(HostPt const off,const Bit64u val) {
00125     *(Bit64u *)(off) = htole64(val);
00126 }
00127 
00128 #endif
00129 
00130 
00131 static INLINE void var_write(Bit8u * const var, const Bit8u val) {
00132     host_writeb((HostPt)var, val);
00133 }
00134 
00135 static INLINE void var_write(Bit16u * const var, const Bit16u val) {
00136     host_writew((HostPt)var, val);
00137 }
00138 
00139 static INLINE void var_write(Bit32u * const var, const Bit32u val) {
00140     host_writed((HostPt)var, val);
00141 }
00142 
00143 static INLINE void var_write(Bit64u * const var, const Bit64u val) {
00144     host_writeq((HostPt)var, val);
00145 }
00146 
00147 /* The Folowing six functions are slower but they recognize the paged memory system */
00148 
00149 Bit8u  mem_readb(const PhysPt address);
00150 Bit16u mem_readw(const PhysPt address);
00151 Bit32u mem_readd(const PhysPt address);
00152 
00153 void mem_writeb(const PhysPt address,const Bit8u val);
00154 void mem_writew(const PhysPt address,const Bit16u val);
00155 void mem_writed(const PhysPt address,const Bit32u val);
00156 
00157 void phys_writes(PhysPt addr, const char* string, Bitu length);
00158 
00159 /* WARNING: These will cause a segfault or out of bounds access IF
00160  *          addr is beyond the end of memory */
00161 
00162 static INLINE void phys_writeb(const PhysPt addr,const Bit8u val) {
00163     host_writeb(MemBase+addr,val);
00164 }
00165 static INLINE void phys_writew(const PhysPt addr,const Bit16u val) {
00166     host_writew(MemBase+addr,val);
00167 }
00168 static INLINE void phys_writed(const PhysPt addr,const Bit32u val) {
00169     host_writed(MemBase+addr,val);
00170 }
00171 
00172 static INLINE Bit8u phys_readb(const PhysPt addr) {
00173     return host_readb(MemBase+addr);
00174 }
00175 static INLINE Bit16u phys_readw(const PhysPt addr) {
00176     return host_readw(MemBase+addr);
00177 }
00178 static INLINE Bit32u phys_readd(const PhysPt addr) {
00179     return host_readd(MemBase+addr);
00180 }
00181 
00182 /* These don't check for alignment, better be sure it's correct */
00183 
00184 void MEM_BlockWrite(PhysPt pt,void const * const data,Bitu size);
00185 void MEM_BlockRead(PhysPt pt,void * data,Bitu size);
00186 void MEM_BlockWrite32(PhysPt pt,void * data,Bitu size);
00187 void MEM_BlockRead32(PhysPt pt,void * data,Bitu size);
00188 void MEM_BlockCopy(PhysPt dest,PhysPt src,Bitu size);
00189 void MEM_StrCopy(PhysPt pt,char * data,Bitu size);
00190 
00191 void mem_memcpy(PhysPt dest,PhysPt src,Bitu size);
00192 Bitu mem_strlen(PhysPt pt);
00193 void mem_strcpy(PhysPt dest,PhysPt src);
00194 
00195 /* The folowing functions are all shortcuts to the above functions using physical addressing */
00196 
00197 static inline constexpr PhysPt PhysMake(const Bit16u seg,const Bit16u off) {
00198     return ((PhysPt)seg << (PhysPt)4U) + (PhysPt)off;
00199 }
00200 
00201 static inline constexpr Bit16u RealSeg(const RealPt pt) {
00202     return (Bit16u)((RealPt)pt >> (RealPt)16U);
00203 }
00204 
00205 static inline constexpr Bit16u RealOff(const RealPt pt) {
00206     return (Bit16u)((RealPt)pt & (RealPt)0xffffu);
00207 }
00208 
00209 static inline constexpr PhysPt Real2Phys(const RealPt pt) {
00210     return (PhysPt)(((PhysPt)RealSeg(pt) << (PhysPt)4U) + (PhysPt)RealOff(pt));
00211 }
00212 
00213 static inline constexpr RealPt RealMake(const Bit16u seg,const Bit16u off) {
00214     return (RealPt)(((RealPt)seg << (RealPt)16U) + (RealPt)off);
00215 }
00216 
00217 /* convert physical address to 4:16 real pointer (example: 0xABCDE -> 0xA000:0xBCDE) */
00218 static inline constexpr RealPt PhysToReal416(const PhysPt phys) {
00219     return RealMake((Bit16u)(((PhysPt)phys >> (PhysPt)4U) & (PhysPt)0xF000U),(Bit16u)((PhysPt)phys & (PhysPt)0xFFFFU));
00220 }
00221 
00222 static inline constexpr PhysPt RealVecAddress(const Bit8u vec) {
00223     return (PhysPt)((unsigned int)vec << 2U);
00224 }
00225 
00226 
00227 static INLINE Bit8u real_readb(const Bit16u seg,const Bit16u off) {
00228     return mem_readb(PhysMake(seg,off));
00229 }
00230 static INLINE Bit16u real_readw(const Bit16u seg,const Bit16u off) {
00231     return mem_readw(PhysMake(seg,off));
00232 }
00233 static INLINE Bit32u real_readd(const Bit16u seg,const Bit16u off) {
00234     return mem_readd(PhysMake(seg,off));
00235 }
00236 
00237 static INLINE void real_writeb(const Bit16u seg,const Bit16u off,const Bit8u val) {
00238     mem_writeb(PhysMake(seg,off),val);
00239 }
00240 static INLINE void real_writew(const Bit16u seg,const Bit16u off,const Bit16u val) {
00241     mem_writew(PhysMake(seg,off),val);
00242 }
00243 static INLINE void real_writed(const Bit16u seg,const Bit16u off,const Bit32u val) {
00244     mem_writed(PhysMake(seg,off),val);
00245 }
00246 
00247 
00248 static INLINE RealPt RealGetVec(const Bit8u vec) {
00249     return mem_readd(RealVecAddress(vec));
00250 }
00251 
00252 static INLINE void RealSetVec(const Bit8u vec,const RealPt pt) {
00253     mem_writed(RealVecAddress(vec),(Bit32u)pt);
00254 }
00255 
00256 static INLINE void RealSetVec(const Bit8u vec,const RealPt pt,RealPt &old) {
00257     const PhysPt addr = RealVecAddress(vec);
00258     old = mem_readd(addr);
00259     mem_writed(addr,pt);
00260 }
00261 
00262 #endif
00263