1 /* Header file for the Memory and the Memory Management Unit (MMU). 2 Module MEM_MMU.[hc] Copyright (C) 1998/1999 by Andreas Gerlich (agl) 3 4 This file is part of yaze-ag - yet another Z80 emulator by ag. 5 6 Yaze-ag is free software; you can redistribute it and/or modify it under 7 the terms of the GNU General Public License as published by the Free 8 Software Foundation; either version 2 of the License, or (at your 9 option) any later version. 10 11 This program is distributed in the hope that it will be useful, but 12 WITHOUT ANY WARRANTY; without even the implied warranty of 13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 General Public License for more details. 15 16 You should have received a copy of the GNU General Public License 17 along with this program; if not, write to the Free Software 18 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ 19 20 #include "ytypes.h" 21 /* Definitions for BYTE and WORD moved to ytypes.h for separate inclusion 22 to reduce coupling between modules. */ 23 24 /* FASTREG needs to be at least 16 bits wide and efficient for the 25 host architecture */ 26 #if UINT_MAX >= 65535 27 typedef unsigned int FASTREG; 28 #else 29 typedef unsigned long FASTREG; 30 #endif 31 32 /* FASTWORK needs to be wider than 16 bits and efficient for the host 33 architecture */ 34 #if UINT_MAX > 65535 35 typedef unsigned int FASTWORK; 36 #else 37 typedef unsigned long FASTWORK; 38 #endif 39 40 41 /*-------------------------------- definitions for memory space --------*/ 42 43 #define Z80MEMSIZE 64 /* logical Addressspace of the Z80 */ 44 45 #ifndef MEMSIZE /* if MEMSIZE are not given */ 46 #ifdef MMU 47 #define MEMSIZE 16*Z80MEMSIZE /* default with MMU: MEMSIZE = 8*Z80MEMSIZE */ 48 #else 49 #define MEMSIZE Z80MEMSIZE /* default without MMU: MEMSIZE = Z80MEMSIZE */ 50 #endif 51 #endif 52 53 extern BYTE ram[MEMSIZE*1024]; /* RAM which is present */ 54 55 /*---------------------------------- definitions for MMU tables --------*/ 56 57 #ifdef MMU 58 59 #ifndef MMUTABLES 60 #define MMUTABLES 16 /* default: 16 MMU page tables */ 61 #endif 62 63 #ifndef YAZEPAGESIZE 64 #define YAZEPAGESIZE 4 /* Pagesize 4 KByte */ 65 #endif /* if you want to modify then it is also */ 66 /* nessasary to modify the section */ 67 /* "central definitions for memory access" */ 68 69 #define RAMPAGES MEMSIZE/YAZEPAGESIZE /* No. of pages of RAM */ 70 71 #define MMUPAGEPOINTERS Z80MEMSIZE/YAZEPAGESIZE /* No. of Page-Pointers */ 72 73 typedef struct { 74 BYTE *page[MMUPAGEPOINTERS]; /* page table for Z80 (64KB) */ 75 } pagetab_struct; 76 77 extern pagetab_struct MMUtable[MMUTABLES];/* MMU page tables */ 78 extern pagetab_struct *mmu; /* Pointers to one MMU-pagetable */ 79 extern pagetab_struct *dmmu; /* ^ to destination MMU-pagetbl */ 80 extern pagetab_struct *mmuget,*mmuput; /* Pointer for get/put */ 81 extern int mmutab; /* selected MMU-pagetable */ 82 83 /* choose */ 84 #define ChooseMMUtab(mmut) mmu=&MMUtable[mmutab=mmut] /* mmutable */ 85 86 #define PP(cp) (ram + ((cp)<<12)) /* calculate page pointer */ 87 88 #endif 89 90 91 /*----------------------- central definitions for memory access -----------*/ 92 93 #ifdef MMU 94 /* The following macros are necessary for Access to Memory through a 95 MMU-table : */ 96 /* normal access to Memory: */ 97 #define RAM(a) *( (mmu->page[(((a)&0xffff)>>12)]) + ((a)&0x0fff) ) 98 99 /* normal access to Memory with MMUpointer: */ 100 #define MRAM(xmmu,a) *((xmmu->page[(((a)&0xffff)>>12)]) + ((a)&0x0fff) ) 101 102 103 /* after access make a++ */ 104 #define RAM_pp(a) *(tmp2=(a++), \ 105 (mmu->page[((tmp2&0xffff)>>12)]) + (tmp2&0x0fff) ) 106 /* with MMUpointer; after access make a++ */ 107 #define MRAM_pp(xmmu,a) *(tmp2=(a++), \ 108 (xmmu->page[((tmp2&0xffff)>>12)]) + (tmp2&0x0fff) ) 109 110 111 /* after access make a-- */ 112 #define RAM_mm(a) *(tmp2=(a--), \ 113 (mmu->page[((tmp2&0xffff)>>12)]) + (tmp2&0x0fff) ) 114 /* with MMUpointer; after access make a-- */ 115 #define MRAM_mm(xmmu,a) *(tmp2=(a--), \ 116 (xmmu->page[((tmp2&0xffff)>>12)]) + (tmp2&0x0fff) ) 117 118 119 /* before access make --a */ 120 #define mm_RAM(a) *(tmp2=(--a), \ 121 (mmu->page[((tmp2&0xffff)>>12)]) + (tmp2&0x0fff) ) 122 /* before access make --a */ 123 #define mm_MRAM(xmmu,a) *(tmp2=(--a), \ 124 (xmmu->page[((tmp2&0xffff)>>12)]) + (tmp2&0x0fff) ) 125 126 #else 127 /* ram access without MMU, like Version 1.05/1.06/1.10 */ 128 #define RAM(a) ram[(a)&0xffff] 129 #define MRAM(xmmu,a) ram[(a)&0xffff] 130 131 #define RAM_pp(a) ram[(a++)&0xffff] 132 #define MRAM_pp(xmmu,a) ram[(a++)&0xffff] 133 134 #define RAM_mm(a) ram[(a--)&0xffff] 135 #define MRAM_mm(xmmu,a) ram[(a--)&0xffff] 136 137 #define mm_RAM(a) ram[(--a)&0xffff] 138 #define mm_MRAM(xmmu,a) ram[(--a)&0xffff] 139 #endif 140 141 /* Some important macros. They are the interface between an access from 142 the simz80-/yaze-Modules and the method of the memory access: */ 143 144 #define GetBYTE(a) RAM(a) 145 #define GetBYTE_pp(a) RAM_pp(a) 146 #define GetBYTE_mm(a) RAM_mm(a) 147 #define mm_GetBYTE(a) mm_RAM(a) 148 #define PutBYTE(a, v) RAM(a) = v 149 #define PutBYTE_pp(a,v) RAM_pp(a) = v 150 #define PutBYTE_mm(a,v) RAM_mm(a) = v 151 #define GetWORD(a) (RAM(a) | (RAM((a)+1) << 8)) 152 153 /* don't work: #define GetWORD_pppp(a) (RAM_pp(a) + (RAM_pp(a) << 8)) */ 154 /* make once more a try at 18.10.1999/21:45 ... with the following macro: */ 155 /* works also not #define GetWORD_pppp(a) (RAM_pp(a) | (RAM_pp(a) << 8)) */ 156 /* I dont know what the optimizer do with such macro. 157 If someone knows about it - I'am very interessed to that knowledge. 158 */ 159 160 #define PutWORD(a, v) \ 161 do { RAM(a) = (BYTE)(v); \ 162 RAM((a)+1) = (v) >> 8; \ 163 } while (0) 164 165 166 /*------------------- Some macros for manipulating Z80-memory : -------*/ 167 168 #define memcpy_get_z(d,s,n) \ 169 do { size_t len = n; \ 170 size_t source = s; \ 171 BYTE *p1 = d; \ 172 while (len--) *p1++ = GetBYTE_pp(source); \ 173 } while (0) 174 175 176 #define memcpy_M_get_z(xm,d,s,n) \ 177 do { size_t len = n; \ 178 size_t source = s; \ 179 BYTE *p1 = d; \ 180 while (len--) *p1++ = MRAM_pp(xm,source); \ 181 } while (0) 182 183 184 #define memcpy_put_z(d,s,n) \ 185 do { size_t len = n; \ 186 size_t dest = d; \ 187 BYTE *p1 = s; \ 188 while (len--) PutBYTE_pp(dest,*p1++); \ 189 } while (0) 190 191 192 #define memcpy_M_put_z(xm,d,s,n) \ 193 do { size_t len = n; \ 194 size_t dest = d; \ 195 BYTE *p1 = s; \ 196 while (len--) MRAM_pp(xm,dest) = *p1++; \ 197 } while (0) 198 199 200 #define memset_M_z(xm,p,v,n) \ 201 do { size_t len = n; \ 202 while (len--) MRAM_pp(xm,p) = v; \ 203 } while (0) 204 205 206 #define memset_z(p,v,n) \ 207 do { size_t len = n; \ 208 while (len--) PutBYTE_pp(p,v); \ 209 } while (0) 210 211 212 /*-------------------- Some macros for unix-memory operations : -------*/ 213 214 #ifdef BSD 215 #if defined(sun) 216 #include <memory.h> 217 #include <string.h> 218 #endif 219 #ifndef strchr 220 #define strchr index 221 #endif 222 #ifndef strrchr 223 #define strrchr rindex 224 #endif 225 #define memclr(p,n) bzero(p,n) 226 #define memcpy(t,f,n) bcopy(f,t,n) 227 #define memcmp(p1,p2,n) bcmp(p1,p2,n) 228 #define memset(p,v,n) \ 229 do { size_t len = n; \ 230 char *p1 = p; \ 231 while (len--) *p1++ = v; \ 232 } while (0) 233 #else 234 #include <string.h> 235 #define memclr(p,n) (void) memset(p,0,n) 236 #endif 237 238 239 /*-------------------------------------------- prototyping -------------*/ 240 void initMEM(); 241 void initMMU(); 242 void loadMMU(); 243 void printMMU(); 244