Thu, 02 Dec 2010 23:03:13 +0000
move memory access and mapping functions into memory.[ch]
This is to tidy up main.c...
Makefile | file | annotate | diff | revisions | |
src/main.c | file | annotate | diff | revisions | |
src/memory.c | file | annotate | diff | revisions | |
src/memory.h | file | annotate | diff | revisions |
1.1 --- a/Makefile Thu Dec 02 22:40:13 2010 +0000 1.2 +++ b/Makefile Thu Dec 02 23:03:13 2010 +0000 1.3 @@ -118,7 +118,7 @@ 1.4 TARGET = freebee 1.5 1.6 # source files that produce object files 1.7 -SRC = main.c state.c 1.8 +SRC = main.c state.c memory.c 1.9 SRC += musashi/m68kcpu.c musashi/m68kdasm.c musashi/m68kops.c musashi/m68kopac.c musashi/m68kopdm.c musashi/m68kopnz.c 1.10 1.11 # source type - either "c" or "cpp" (C or C++)
2.1 --- a/src/main.c Thu Dec 02 22:40:13 2010 +0000 2.2 +++ b/src/main.c Thu Dec 02 23:03:13 2010 +0000 2.3 @@ -10,6 +10,7 @@ 2.4 #include "musashi/m68k.h" 2.5 #include "version.h" 2.6 #include "state.h" 2.7 +#include "memory.h" 2.8 2.9 void FAIL(char *err) 2.10 { 2.11 @@ -18,1222 +19,6 @@ 2.12 exit(EXIT_FAILURE); 2.13 } 2.14 2.15 -/*********************************** 2.16 - * Array read/write utility macros 2.17 - * "Don't Repeat Yourself" :) 2.18 - ***********************************/ 2.19 - 2.20 -/// Array read, 32-bit 2.21 -#define RD32(array, address, andmask) \ 2.22 - (((uint32_t)array[(address + 0) & (andmask)] << 24) | \ 2.23 - ((uint32_t)array[(address + 1) & (andmask)] << 16) | \ 2.24 - ((uint32_t)array[(address + 2) & (andmask)] << 8) | \ 2.25 - ((uint32_t)array[(address + 3) & (andmask)])) 2.26 - 2.27 -/// Array read, 16-bit 2.28 -#define RD16(array, address, andmask) \ 2.29 - (((uint32_t)array[(address + 0) & (andmask)] << 8) | \ 2.30 - ((uint32_t)array[(address + 1) & (andmask)])) 2.31 - 2.32 -/// Array read, 8-bit 2.33 -#define RD8(array, address, andmask) \ 2.34 - ((uint32_t)array[(address + 0) & (andmask)]) 2.35 - 2.36 -/// Array write, 32-bit 2.37 -#define WR32(array, address, andmask, value) { \ 2.38 - array[(address + 0) & (andmask)] = (value >> 24) & 0xff; \ 2.39 - array[(address + 1) & (andmask)] = (value >> 16) & 0xff; \ 2.40 - array[(address + 2) & (andmask)] = (value >> 8) & 0xff; \ 2.41 - array[(address + 3) & (andmask)] = value & 0xff; \ 2.42 -} 2.43 - 2.44 -/// Array write, 16-bit 2.45 -#define WR16(array, address, andmask, value) { \ 2.46 - array[(address + 0) & (andmask)] = (value >> 8) & 0xff; \ 2.47 - array[(address + 1) & (andmask)] = value & 0xff; \ 2.48 -} 2.49 - 2.50 -/// Array write, 8-bit 2.51 -#define WR8(array, address, andmask, value) \ 2.52 - array[(address + 0) & (andmask)] = value & 0xff; 2.53 - 2.54 -/****************** 2.55 - * Memory mapping 2.56 - ******************/ 2.57 - 2.58 -#define MAPRAM(addr) (((uint16_t)state.map[addr*2] << 8) + ((uint16_t)state.map[(addr*2)+1])) 2.59 - 2.60 -uint32_t mapAddr(uint32_t addr, bool writing) 2.61 -{ 2.62 - if (addr < 0x400000) { 2.63 - // RAM access. Check against the Map RAM 2.64 - // Start by getting the original page address 2.65 - uint16_t page = (addr >> 12) & 0x3FF; 2.66 - 2.67 - // Look it up in the map RAM and get the physical page address 2.68 - uint32_t new_page_addr = MAPRAM(page) & 0x3FF; 2.69 - 2.70 - // Update the Page Status bits 2.71 - uint8_t pagebits = (MAPRAM(page) >> 13) & 0x03; 2.72 - if (pagebits != 0) { 2.73 - if (writing) 2.74 - state.map[page*2] |= 0x60; // Page written to (dirty) 2.75 - else 2.76 - state.map[page*2] |= 0x40; // Page accessed but not written 2.77 - } 2.78 - 2.79 - // Return the address with the new physical page spliced in 2.80 - return (new_page_addr << 12) + (addr & 0xFFF); 2.81 - } else { 2.82 - // I/O, VRAM or MapRAM space; no mapping is performed or required 2.83 - // TODO: assert here? 2.84 - return addr; 2.85 - } 2.86 -} 2.87 - 2.88 -typedef enum { 2.89 - MEM_ALLOWED = 0, 2.90 - MEM_PAGEFAULT, // Page fault -- page not present 2.91 - MEM_PAGE_NO_WE, // Page not write enabled 2.92 - MEM_KERNEL, // User attempted to access kernel memory 2.93 - MEM_UIE // User Nonmemory Location Access 2.94 -} MEM_STATUS; 2.95 - 2.96 -// check memory access permissions 2.97 -MEM_STATUS checkMemoryAccess(uint32_t addr, bool writing) 2.98 -{ 2.99 - // Are we in Supervisor mode? 2.100 - if (m68k_get_reg(NULL, M68K_REG_SR) & 0x2000) 2.101 - // Yes. We can do anything we like. 2.102 - return MEM_ALLOWED; 2.103 - 2.104 - // If we're here, then we must be in User mode. 2.105 - // Check that the user didn't access memory outside of the RAM area 2.106 - if (addr >= 0x400000) 2.107 - return MEM_UIE; 2.108 - 2.109 - // This leaves us with Page Fault checking. Get the page bits for this page. 2.110 - uint16_t page = (addr >> 12) & 0x3FF; 2.111 - uint8_t pagebits = (MAPRAM(page) >> 13) & 0x07; 2.112 - 2.113 - // Check page is present 2.114 - if ((pagebits & 0x03) == 0) 2.115 - return MEM_PAGEFAULT; 2.116 - 2.117 - // User attempt to access the kernel 2.118 - // A19, A20, A21, A22 low (kernel access): RAM addr before paging; not in Supervisor mode 2.119 - if (((addr >> 19) & 0x0F) == 0) 2.120 - return MEM_KERNEL; 2.121 - 2.122 - // Check page is write enabled 2.123 - if ((pagebits & 0x04) == 0) 2.124 - return MEM_PAGE_NO_WE; 2.125 - 2.126 - // Page access allowed. 2.127 - return MEM_ALLOWED; 2.128 -} 2.129 - 2.130 -#undef MAPRAM 2.131 - 2.132 -/******************************************************** 2.133 - * m68k memory read/write support functions for Musashi 2.134 - ********************************************************/ 2.135 - 2.136 -/** 2.137 - * @brief Check memory access permissions for a write operation. 2.138 - * @note This used to be a single macro (merged with ACCESS_CHECK_RD), but 2.139 - * gcc throws warnings when you have a return-with-value in a void 2.140 - * function, even if the return-with-value is completely unreachable. 2.141 - * Similarly it doesn't like it if you have a return without a value 2.142 - * in a non-void function, even if it's impossible to ever reach the 2.143 - * return-with-no-value. UGH! 2.144 - */ 2.145 -#define ACCESS_CHECK_WR(address, bits) do { \ 2.146 - bool fault = false; \ 2.147 - /* MEM_STATUS st; */ \ 2.148 - switch (checkMemoryAccess(address, true)) { \ 2.149 - case MEM_ALLOWED: \ 2.150 - /* Access allowed */ \ 2.151 - break; \ 2.152 - case MEM_PAGEFAULT: \ 2.153 - /* Page fault */ \ 2.154 - state.genstat = 0x8FFF; \ 2.155 - fault = true; \ 2.156 - break; \ 2.157 - case MEM_UIE: \ 2.158 - /* User access to memory above 4MB */ \ 2.159 - state.genstat = 0x9EFF; \ 2.160 - fault = true; \ 2.161 - break; \ 2.162 - case MEM_KERNEL: \ 2.163 - case MEM_PAGE_NO_WE: \ 2.164 - /* kernel access or page not write enabled */ \ 2.165 - /* TODO: which regs need setting? */ \ 2.166 - fault = true; \ 2.167 - break; \ 2.168 - } \ 2.169 - \ 2.170 - if (fault) { \ 2.171 - if (bits >= 16) \ 2.172 - state.bsr0 = 0x7F00; \ 2.173 - else \ 2.174 - state.bsr0 = (address & 1) ? 0x7D00 : 0x7E00; \ 2.175 - state.bsr0 |= (address >> 16); \ 2.176 - state.bsr1 = address & 0xffff; \ 2.177 - printf("ERR: BusError WR\n"); \ 2.178 - m68k_pulse_bus_error(); \ 2.179 - return; \ 2.180 - } \ 2.181 - } while (false) 2.182 - 2.183 -/** 2.184 - * @brief Check memory access permissions for a read operation. 2.185 - * @note This used to be a single macro (merged with ACCESS_CHECK_WR), but 2.186 - * gcc throws warnings when you have a return-with-value in a void 2.187 - * function, even if the return-with-value is completely unreachable. 2.188 - * Similarly it doesn't like it if you have a return without a value 2.189 - * in a non-void function, even if it's impossible to ever reach the 2.190 - * return-with-no-value. UGH! 2.191 - */ 2.192 -#define ACCESS_CHECK_RD(address, bits) do { \ 2.193 - bool fault = false; \ 2.194 - /* MEM_STATUS st; */ \ 2.195 - switch (checkMemoryAccess(address, false)) { \ 2.196 - case MEM_ALLOWED: \ 2.197 - /* Access allowed */ \ 2.198 - break; \ 2.199 - case MEM_PAGEFAULT: \ 2.200 - /* Page fault */ \ 2.201 - state.genstat = 0x8FFF; \ 2.202 - fault = true; \ 2.203 - break; \ 2.204 - case MEM_UIE: \ 2.205 - /* User access to memory above 4MB */ \ 2.206 - state.genstat = 0x9EFF; \ 2.207 - fault = true; \ 2.208 - break; \ 2.209 - case MEM_KERNEL: \ 2.210 - case MEM_PAGE_NO_WE: \ 2.211 - /* kernel access or page not write enabled */ \ 2.212 - /* TODO: which regs need setting? */ \ 2.213 - fault = true; \ 2.214 - break; \ 2.215 - } \ 2.216 - \ 2.217 - if (fault) { \ 2.218 - if (bits >= 16) \ 2.219 - state.bsr0 = 0x7F00; \ 2.220 - else \ 2.221 - state.bsr0 = (address & 1) ? 0x7D00 : 0x7E00; \ 2.222 - state.bsr0 |= (address >> 16); \ 2.223 - state.bsr1 = address & 0xffff; \ 2.224 - printf("ERR: BusError RD\n"); \ 2.225 - m68k_pulse_bus_error(); \ 2.226 - return 0xFFFFFFFF; \ 2.227 - } \ 2.228 - } while (false) 2.229 - 2.230 -// Logging macros 2.231 -#define LOG_NOT_HANDLED_R(bits) \ 2.232 - do { \ 2.233 - if (!handled) \ 2.234 - printf("unhandled read%02d, addr=0x%08X\n", bits, address); \ 2.235 - } while (0); 2.236 - 2.237 -#define LOG_NOT_HANDLED_W(bits) \ 2.238 - do { \ 2.239 - if (!handled) \ 2.240 - printf("unhandled write%02d, addr=0x%08X, data=0x%08X\n", bits, address, value); \ 2.241 - } while (0); 2.242 - 2.243 -/** 2.244 - * @brief Read M68K memory, 32-bit 2.245 - */ 2.246 -uint32_t m68k_read_memory_32(uint32_t address) 2.247 -{ 2.248 - uint32_t data = 0xFFFFFFFF; 2.249 - bool handled = false; 2.250 - 2.251 - // If ROMLMAP is set, force system to access ROM 2.252 - if (!state.romlmap) 2.253 - address |= 0x800000; 2.254 - 2.255 - // Check access permissions 2.256 - ACCESS_CHECK_RD(address, 32); 2.257 - 2.258 - if ((address >= 0x800000) && (address <= 0xBFFFFF)) { 2.259 - // ROM access 2.260 - data = RD32(state.rom, address, ROM_SIZE - 1); 2.261 - handled = true; 2.262 - } else if (address <= (state.ram_size - 1)) { 2.263 - // RAM access 2.264 - data = RD32(state.ram, mapAddr(address, false), state.ram_size - 1); 2.265 - handled = true; 2.266 - } else if ((address >= 0x400000) && (address <= 0x7FFFFF)) { 2.267 - // I/O register space, zone A 2.268 - switch (address & 0x0F0000) { 2.269 - case 0x000000: // Map RAM access 2.270 - if (address > 0x4007FF) fprintf(stderr, "NOTE: RD32 from MapRAM mirror, addr=0x%08X\n", address); 2.271 - data = RD32(state.map, address, 0x7FF); 2.272 - handled = true; 2.273 - break; 2.274 - case 0x010000: // General Status Register 2.275 - data = ((uint32_t)state.genstat << 16) + (uint32_t)state.genstat; 2.276 - handled = true; 2.277 - break; 2.278 - case 0x020000: // Video RAM 2.279 - if (address > 0x427FFF) fprintf(stderr, "NOTE: RD32 from VideoRAM mirror, addr=0x%08X\n", address); 2.280 - data = RD32(state.vram, address, 0x7FFF); 2.281 - handled = true; 2.282 - break; 2.283 - case 0x030000: // Bus Status Register 0 2.284 - data = ((uint32_t)state.bsr0 << 16) + (uint32_t)state.bsr0; 2.285 - handled = true; 2.286 - break; 2.287 - case 0x040000: // Bus Status Register 1 2.288 - data = ((uint32_t)state.bsr1 << 16) + (uint32_t)state.bsr1; 2.289 - handled = true; 2.290 - break; 2.291 - case 0x050000: // Phone status 2.292 - break; 2.293 - case 0x060000: // DMA Count 2.294 - break; 2.295 - case 0x070000: // Line Printer Status Register 2.296 - break; 2.297 - case 0x080000: // Real Time Clock 2.298 - break; 2.299 - case 0x090000: // Phone registers 2.300 - switch (address & 0x0FF000) { 2.301 - case 0x090000: // Handset relay 2.302 - case 0x098000: 2.303 - break; 2.304 - case 0x091000: // Line select 2 2.305 - case 0x099000: 2.306 - break; 2.307 - case 0x092000: // Hook relay 1 2.308 - case 0x09A000: 2.309 - break; 2.310 - case 0x093000: // Hook relay 2 2.311 - case 0x09B000: 2.312 - break; 2.313 - case 0x094000: // Line 1 hold 2.314 - case 0x09C000: 2.315 - break; 2.316 - case 0x095000: // Line 2 hold 2.317 - case 0x09D000: 2.318 - break; 2.319 - case 0x096000: // Line 1 A-lead 2.320 - case 0x09E000: 2.321 - break; 2.322 - case 0x097000: // Line 2 A-lead 2.323 - case 0x09F000: 2.324 - break; 2.325 - } 2.326 - break; 2.327 - case 0x0A0000: // Miscellaneous Control Register 2.328 - break; 2.329 - case 0x0B0000: // TM/DIALWR 2.330 - break; 2.331 - case 0x0C0000: // CSR 2.332 - break; 2.333 - case 0x0D0000: // DMA Address Register 2.334 - break; 2.335 - case 0x0E0000: // Disk Control Register 2.336 - break; 2.337 - case 0x0F0000: // Line Printer Data Register 2.338 - break; 2.339 - } 2.340 - } else if ((address >= 0xC00000) && (address <= 0xFFFFFF)) { 2.341 - // I/O register space, zone B 2.342 - switch (address & 0xF00000) { 2.343 - case 0xC00000: // Expansion slots 2.344 - case 0xD00000: 2.345 - switch (address & 0xFC0000) { 2.346 - case 0xC00000: // Expansion slot 0 2.347 - case 0xC40000: // Expansion slot 1 2.348 - case 0xC80000: // Expansion slot 2 2.349 - case 0xCC0000: // Expansion slot 3 2.350 - case 0xD00000: // Expansion slot 4 2.351 - case 0xD40000: // Expansion slot 5 2.352 - case 0xD80000: // Expansion slot 6 2.353 - case 0xDC0000: // Expansion slot 7 2.354 - fprintf(stderr, "NOTE: RD32 from expansion card space, addr=0x%08X\n", address); 2.355 - break; 2.356 - } 2.357 - break; 2.358 - case 0xE00000: // HDC, FDC, MCR2 and RTC data bits 2.359 - case 0xF00000: 2.360 - switch (address & 0x070000) { 2.361 - case 0x000000: // [ef][08]xxxx ==> WD1010 hard disc controller 2.362 - break; 2.363 - case 0x010000: // [ef][19]xxxx ==> WD2797 floppy disc controller 2.364 - break; 2.365 - case 0x020000: // [ef][2a]xxxx ==> Miscellaneous Control Register 2 2.366 - break; 2.367 - case 0x030000: // [ef][3b]xxxx ==> Real Time Clock data bits 2.368 - break; 2.369 - case 0x040000: // [ef][4c]xxxx ==> General Control Register 2.370 - switch (address & 0x077000) { 2.371 - case 0x040000: // [ef][4c][08]xxx ==> EE 2.372 - break; 2.373 - case 0x041000: // [ef][4c][19]xxx ==> P1E 2.374 - break; 2.375 - case 0x042000: // [ef][4c][2A]xxx ==> BP 2.376 - break; 2.377 - case 0x043000: // [ef][4c][3B]xxx ==> ROMLMAP 2.378 - break; 2.379 - case 0x044000: // [ef][4c][4C]xxx ==> L1 MODEM 2.380 - break; 2.381 - case 0x045000: // [ef][4c][5D]xxx ==> L2 MODEM 2.382 - break; 2.383 - case 0x046000: // [ef][4c][6E]xxx ==> D/N CONNECT 2.384 - break; 2.385 - case 0x047000: // [ef][4c][7F]xxx ==> Whole screen reverse video 2.386 - break; 2.387 - } 2.388 - break; 2.389 - case 0x050000: // [ef][5d]xxxx ==> 8274 2.390 - break; 2.391 - case 0x060000: // [ef][6e]xxxx ==> Control regs 2.392 - switch (address & 0x07F000) { 2.393 - default: 2.394 - break; 2.395 - } 2.396 - break; 2.397 - case 0x070000: // [ef][7f]xxxx ==> 6850 Keyboard Controller 2.398 - break; 2.399 - } 2.400 - } 2.401 - } 2.402 - 2.403 - LOG_NOT_HANDLED_R(32); 2.404 - return data; 2.405 -} 2.406 - 2.407 -/** 2.408 - * @brief Read M68K memory, 16-bit 2.409 - */ 2.410 -uint32_t m68k_read_memory_16(uint32_t address) 2.411 -{ 2.412 - uint16_t data = 0xFFFF; 2.413 - bool handled = false; 2.414 - 2.415 - // If ROMLMAP is set, force system to access ROM 2.416 - if (!state.romlmap) 2.417 - address |= 0x800000; 2.418 - 2.419 - // Check access permissions 2.420 - ACCESS_CHECK_RD(address, 16); 2.421 - 2.422 - if ((address >= 0x800000) && (address <= 0xBFFFFF)) { 2.423 - // ROM access 2.424 - data = RD16(state.rom, address, ROM_SIZE - 1); 2.425 - handled = true; 2.426 - } else if (address <= (state.ram_size - 1)) { 2.427 - // RAM access 2.428 - data = RD16(state.ram, mapAddr(address, false), state.ram_size - 1); 2.429 - handled = true; 2.430 - } else if ((address >= 0x400000) && (address <= 0x7FFFFF)) { 2.431 - // I/O register space, zone A 2.432 - switch (address & 0x0F0000) { 2.433 - case 0x000000: // Map RAM access 2.434 - if (address > 0x4007FF) fprintf(stderr, "NOTE: RD16 from MapRAM mirror, addr=0x%08X\n", address); 2.435 - data = RD16(state.map, address, 0x7FF); 2.436 - handled = true; 2.437 - break; 2.438 - case 0x010000: // General Status Register 2.439 - data = state.genstat; 2.440 - handled = true; 2.441 - break; 2.442 - case 0x020000: // Video RAM 2.443 - if (address > 0x427FFF) fprintf(stderr, "NOTE: RD16 from VideoRAM mirror, addr=0x%08X\n", address); 2.444 - data = RD16(state.vram, address, 0x7FFF); 2.445 - handled = true; 2.446 - break; 2.447 - case 0x030000: // Bus Status Register 0 2.448 - data = state.bsr0; 2.449 - handled = true; 2.450 - break; 2.451 - case 0x040000: // Bus Status Register 1 2.452 - data = state.bsr1; 2.453 - handled = true; 2.454 - break; 2.455 - case 0x050000: // Phone status 2.456 - break; 2.457 - case 0x060000: // DMA Count 2.458 - break; 2.459 - case 0x070000: // Line Printer Status Register 2.460 - break; 2.461 - case 0x080000: // Real Time Clock 2.462 - break; 2.463 - case 0x090000: // Phone registers 2.464 - switch (address & 0x0FF000) { 2.465 - case 0x090000: // Handset relay 2.466 - case 0x098000: 2.467 - break; 2.468 - case 0x091000: // Line select 2 2.469 - case 0x099000: 2.470 - break; 2.471 - case 0x092000: // Hook relay 1 2.472 - case 0x09A000: 2.473 - break; 2.474 - case 0x093000: // Hook relay 2 2.475 - case 0x09B000: 2.476 - break; 2.477 - case 0x094000: // Line 1 hold 2.478 - case 0x09C000: 2.479 - break; 2.480 - case 0x095000: // Line 2 hold 2.481 - case 0x09D000: 2.482 - break; 2.483 - case 0x096000: // Line 1 A-lead 2.484 - case 0x09E000: 2.485 - break; 2.486 - case 0x097000: // Line 2 A-lead 2.487 - case 0x09F000: 2.488 - break; 2.489 - } 2.490 - break; 2.491 - case 0x0A0000: // Miscellaneous Control Register 2.492 - break; 2.493 - case 0x0B0000: // TM/DIALWR 2.494 - break; 2.495 - case 0x0C0000: // CSR 2.496 - break; 2.497 - case 0x0D0000: // DMA Address Register 2.498 - break; 2.499 - case 0x0E0000: // Disk Control Register 2.500 - break; 2.501 - case 0x0F0000: // Line Printer Data Register 2.502 - break; 2.503 - } 2.504 - } else if ((address >= 0xC00000) && (address <= 0xFFFFFF)) { 2.505 - // I/O register space, zone B 2.506 - switch (address & 0xF00000) { 2.507 - case 0xC00000: // Expansion slots 2.508 - case 0xD00000: 2.509 - switch (address & 0xFC0000) { 2.510 - case 0xC00000: // Expansion slot 0 2.511 - case 0xC40000: // Expansion slot 1 2.512 - case 0xC80000: // Expansion slot 2 2.513 - case 0xCC0000: // Expansion slot 3 2.514 - case 0xD00000: // Expansion slot 4 2.515 - case 0xD40000: // Expansion slot 5 2.516 - case 0xD80000: // Expansion slot 6 2.517 - case 0xDC0000: // Expansion slot 7 2.518 - fprintf(stderr, "NOTE: RD16 from expansion card space, addr=0x%08X\n", address); 2.519 - break; 2.520 - } 2.521 - break; 2.522 - case 0xE00000: // HDC, FDC, MCR2 and RTC data bits 2.523 - case 0xF00000: 2.524 - switch (address & 0x070000) { 2.525 - case 0x000000: // [ef][08]xxxx ==> WD1010 hard disc controller 2.526 - break; 2.527 - case 0x010000: // [ef][19]xxxx ==> WD2797 floppy disc controller 2.528 - break; 2.529 - case 0x020000: // [ef][2a]xxxx ==> Miscellaneous Control Register 2 2.530 - break; 2.531 - case 0x030000: // [ef][3b]xxxx ==> Real Time Clock data bits 2.532 - break; 2.533 - case 0x040000: // [ef][4c]xxxx ==> General Control Register 2.534 - switch (address & 0x077000) { 2.535 - case 0x040000: // [ef][4c][08]xxx ==> EE 2.536 - break; 2.537 - case 0x041000: // [ef][4c][19]xxx ==> P1E 2.538 - break; 2.539 - case 0x042000: // [ef][4c][2A]xxx ==> BP 2.540 - break; 2.541 - case 0x043000: // [ef][4c][3B]xxx ==> ROMLMAP 2.542 - break; 2.543 - case 0x044000: // [ef][4c][4C]xxx ==> L1 MODEM 2.544 - break; 2.545 - case 0x045000: // [ef][4c][5D]xxx ==> L2 MODEM 2.546 - break; 2.547 - case 0x046000: // [ef][4c][6E]xxx ==> D/N CONNECT 2.548 - break; 2.549 - case 0x047000: // [ef][4c][7F]xxx ==> Whole screen reverse video 2.550 - break; 2.551 - } 2.552 - break; 2.553 - case 0x050000: // [ef][5d]xxxx ==> 8274 2.554 - break; 2.555 - case 0x060000: // [ef][6e]xxxx ==> Control regs 2.556 - switch (address & 0x07F000) { 2.557 - default: 2.558 - break; 2.559 - } 2.560 - break; 2.561 - case 0x070000: // [ef][7f]xxxx ==> 6850 Keyboard Controller 2.562 - break; 2.563 - } 2.564 - } 2.565 - } 2.566 - 2.567 - LOG_NOT_HANDLED_R(32); 2.568 - return data; 2.569 -} 2.570 - 2.571 -/** 2.572 - * @brief Read M68K memory, 8-bit 2.573 - */ 2.574 -uint32_t m68k_read_memory_8(uint32_t address) 2.575 -{ 2.576 - uint8_t data = 0xFF; 2.577 - bool handled = false; 2.578 - 2.579 - // If ROMLMAP is set, force system to access ROM 2.580 - if (!state.romlmap) 2.581 - address |= 0x800000; 2.582 - 2.583 - // Check access permissions 2.584 - ACCESS_CHECK_RD(address, 8); 2.585 - 2.586 - if ((address >= 0x800000) && (address <= 0xBFFFFF)) { 2.587 - // ROM access 2.588 - data = RD8(state.rom, address, ROM_SIZE - 1); 2.589 - handled = true; 2.590 - } else if (address <= (state.ram_size - 1)) { 2.591 - // RAM access 2.592 - data = RD8(state.ram, mapAddr(address, false), state.ram_size - 1); 2.593 - handled = true; 2.594 - } else if ((address >= 0x400000) && (address <= 0x7FFFFF)) { 2.595 - // I/O register space, zone A 2.596 - switch (address & 0x0F0000) { 2.597 - case 0x000000: // Map RAM access 2.598 - if (address > 0x4007FF) fprintf(stderr, "NOTE: RD8 from MapRAM mirror, addr=0x%08X\n", address); 2.599 - data = RD8(state.map, address, 0x7FF); 2.600 - handled = true; 2.601 - break; 2.602 - case 0x010000: // General Status Register 2.603 - if ((address & 1) == 0) 2.604 - data = (state.genstat >> 8) & 0xff; 2.605 - else 2.606 - data = (state.genstat) & 0xff; 2.607 - handled = true; 2.608 - break; 2.609 - case 0x020000: // Video RAM 2.610 - if (address > 0x427FFF) fprintf(stderr, "NOTE: RD8 from VideoRAM mirror, addr=0x%08X\n", address); 2.611 - data = RD8(state.vram, address, 0x7FFF); 2.612 - handled = true; 2.613 - break; 2.614 - case 0x030000: // Bus Status Register 0 2.615 - if ((address & 1) == 0) 2.616 - data = (state.bsr0 >> 8) & 0xff; 2.617 - else 2.618 - data = (state.bsr0) & 0xff; 2.619 - handled = true; 2.620 - break; 2.621 - case 0x040000: // Bus Status Register 1 2.622 - if ((address & 1) == 0) 2.623 - data = (state.bsr1 >> 8) & 0xff; 2.624 - else 2.625 - data = (state.bsr1) & 0xff; 2.626 - handled = true; 2.627 - break; 2.628 - case 0x050000: // Phone status 2.629 - break; 2.630 - case 0x060000: // DMA Count 2.631 - break; 2.632 - case 0x070000: // Line Printer Status Register 2.633 - break; 2.634 - case 0x080000: // Real Time Clock 2.635 - break; 2.636 - case 0x090000: // Phone registers 2.637 - switch (address & 0x0FF000) { 2.638 - case 0x090000: // Handset relay 2.639 - case 0x098000: 2.640 - break; 2.641 - case 0x091000: // Line select 2 2.642 - case 0x099000: 2.643 - break; 2.644 - case 0x092000: // Hook relay 1 2.645 - case 0x09A000: 2.646 - break; 2.647 - case 0x093000: // Hook relay 2 2.648 - case 0x09B000: 2.649 - break; 2.650 - case 0x094000: // Line 1 hold 2.651 - case 0x09C000: 2.652 - break; 2.653 - case 0x095000: // Line 2 hold 2.654 - case 0x09D000: 2.655 - break; 2.656 - case 0x096000: // Line 1 A-lead 2.657 - case 0x09E000: 2.658 - break; 2.659 - case 0x097000: // Line 2 A-lead 2.660 - case 0x09F000: 2.661 - break; 2.662 - } 2.663 - break; 2.664 - case 0x0A0000: // Miscellaneous Control Register 2.665 - break; 2.666 - case 0x0B0000: // TM/DIALWR 2.667 - break; 2.668 - case 0x0C0000: // CSR 2.669 - break; 2.670 - case 0x0D0000: // DMA Address Register 2.671 - break; 2.672 - case 0x0E0000: // Disk Control Register 2.673 - break; 2.674 - case 0x0F0000: // Line Printer Data Register 2.675 - break; 2.676 - } 2.677 - } else if ((address >= 0xC00000) && (address <= 0xFFFFFF)) { 2.678 - // I/O register space, zone B 2.679 - switch (address & 0xF00000) { 2.680 - case 0xC00000: // Expansion slots 2.681 - case 0xD00000: 2.682 - switch (address & 0xFC0000) { 2.683 - case 0xC00000: // Expansion slot 0 2.684 - case 0xC40000: // Expansion slot 1 2.685 - case 0xC80000: // Expansion slot 2 2.686 - case 0xCC0000: // Expansion slot 3 2.687 - case 0xD00000: // Expansion slot 4 2.688 - case 0xD40000: // Expansion slot 5 2.689 - case 0xD80000: // Expansion slot 6 2.690 - case 0xDC0000: // Expansion slot 7 2.691 - fprintf(stderr, "NOTE: RD8 from expansion card space, addr=0x%08X\n", address); 2.692 - break; 2.693 - } 2.694 - break; 2.695 - case 0xE00000: // HDC, FDC, MCR2 and RTC data bits 2.696 - case 0xF00000: 2.697 - switch (address & 0x070000) { 2.698 - case 0x000000: // [ef][08]xxxx ==> WD1010 hard disc controller 2.699 - break; 2.700 - case 0x010000: // [ef][19]xxxx ==> WD2797 floppy disc controller 2.701 - break; 2.702 - case 0x020000: // [ef][2a]xxxx ==> Miscellaneous Control Register 2 2.703 - break; 2.704 - case 0x030000: // [ef][3b]xxxx ==> Real Time Clock data bits 2.705 - break; 2.706 - case 0x040000: // [ef][4c]xxxx ==> General Control Register 2.707 - switch (address & 0x077000) { 2.708 - case 0x040000: // [ef][4c][08]xxx ==> EE 2.709 - break; 2.710 - case 0x041000: // [ef][4c][19]xxx ==> P1E 2.711 - break; 2.712 - case 0x042000: // [ef][4c][2A]xxx ==> BP 2.713 - break; 2.714 - case 0x043000: // [ef][4c][3B]xxx ==> ROMLMAP 2.715 - break; 2.716 - case 0x044000: // [ef][4c][4C]xxx ==> L1 MODEM 2.717 - break; 2.718 - case 0x045000: // [ef][4c][5D]xxx ==> L2 MODEM 2.719 - break; 2.720 - case 0x046000: // [ef][4c][6E]xxx ==> D/N CONNECT 2.721 - break; 2.722 - case 0x047000: // [ef][4c][7F]xxx ==> Whole screen reverse video 2.723 - break; 2.724 - } 2.725 - case 0x050000: // [ef][5d]xxxx ==> 8274 2.726 - break; 2.727 - case 0x060000: // [ef][6e]xxxx ==> Control regs 2.728 - switch (address & 0x07F000) { 2.729 - default: 2.730 - break; 2.731 - } 2.732 - break; 2.733 - case 0x070000: // [ef][7f]xxxx ==> 6850 Keyboard Controller 2.734 - break; 2.735 - } 2.736 - } 2.737 - } 2.738 - 2.739 - LOG_NOT_HANDLED_R(8); 2.740 - 2.741 - return data; 2.742 -} 2.743 - 2.744 -/** 2.745 - * @brief Write M68K memory, 32-bit 2.746 - */ 2.747 -void m68k_write_memory_32(uint32_t address, uint32_t value) 2.748 -{ 2.749 - bool handled = false; 2.750 - 2.751 - // If ROMLMAP is set, force system to access ROM 2.752 - if (!state.romlmap) 2.753 - address |= 0x800000; 2.754 - 2.755 - // Check access permissions 2.756 - ACCESS_CHECK_WR(address, 32); 2.757 - 2.758 - if ((address >= 0x800000) && (address <= 0xBFFFFF)) { 2.759 - // ROM access 2.760 - handled = true; 2.761 - } else if (address <= (state.ram_size - 1)) { 2.762 - // RAM access 2.763 - WR32(state.ram, mapAddr(address, false), state.ram_size - 1, value); 2.764 - handled = true; 2.765 - } else if ((address >= 0x400000) && (address <= 0x7FFFFF)) { 2.766 - // I/O register space, zone A 2.767 - switch (address & 0x0F0000) { 2.768 - case 0x000000: // Map RAM access 2.769 - if (address > 0x4007FF) fprintf(stderr, "NOTE: WR32 to MapRAM mirror, addr=0x%08X, data=0x%08X\n", address, value); 2.770 - WR32(state.map, address, 0x7FF, value); 2.771 - handled = true; 2.772 - break; 2.773 - case 0x010000: // General Status Register 2.774 - state.genstat = (value & 0xffff); 2.775 - handled = true; 2.776 - break; 2.777 - case 0x020000: // Video RAM 2.778 - if (address > 0x427FFF) fprintf(stderr, "NOTE: WR32 to VideoRAM mirror, addr=0x%08X, data=0x%08X\n", address, value); 2.779 - WR32(state.vram, address, 0x7FFF, value); 2.780 - handled = true; 2.781 - break; 2.782 - case 0x030000: // Bus Status Register 0 2.783 - break; 2.784 - case 0x040000: // Bus Status Register 1 2.785 - break; 2.786 - case 0x050000: // Phone status 2.787 - break; 2.788 - case 0x060000: // DMA Count 2.789 - break; 2.790 - case 0x070000: // Line Printer Status Register 2.791 - break; 2.792 - case 0x080000: // Real Time Clock 2.793 - break; 2.794 - case 0x090000: // Phone registers 2.795 - switch (address & 0x0FF000) { 2.796 - case 0x090000: // Handset relay 2.797 - case 0x098000: 2.798 - break; 2.799 - case 0x091000: // Line select 2 2.800 - case 0x099000: 2.801 - break; 2.802 - case 0x092000: // Hook relay 1 2.803 - case 0x09A000: 2.804 - break; 2.805 - case 0x093000: // Hook relay 2 2.806 - case 0x09B000: 2.807 - break; 2.808 - case 0x094000: // Line 1 hold 2.809 - case 0x09C000: 2.810 - break; 2.811 - case 0x095000: // Line 2 hold 2.812 - case 0x09D000: 2.813 - break; 2.814 - case 0x096000: // Line 1 A-lead 2.815 - case 0x09E000: 2.816 - break; 2.817 - case 0x097000: // Line 2 A-lead 2.818 - case 0x09F000: 2.819 - break; 2.820 - } 2.821 - break; 2.822 - case 0x0A0000: // Miscellaneous Control Register 2.823 - break; 2.824 - case 0x0B0000: // TM/DIALWR 2.825 - break; 2.826 - case 0x0C0000: // CSR 2.827 - break; 2.828 - case 0x0D0000: // DMA Address Register 2.829 - break; 2.830 - case 0x0E0000: // Disk Control Register 2.831 - break; 2.832 - case 0x0F0000: // Line Printer Data Register 2.833 - break; 2.834 - } 2.835 - } else if ((address >= 0xC00000) && (address <= 0xFFFFFF)) { 2.836 - // I/O register space, zone B 2.837 - switch (address & 0xF00000) { 2.838 - case 0xC00000: // Expansion slots 2.839 - case 0xD00000: 2.840 - switch (address & 0xFC0000) { 2.841 - case 0xC00000: // Expansion slot 0 2.842 - case 0xC40000: // Expansion slot 1 2.843 - case 0xC80000: // Expansion slot 2 2.844 - case 0xCC0000: // Expansion slot 3 2.845 - case 0xD00000: // Expansion slot 4 2.846 - case 0xD40000: // Expansion slot 5 2.847 - case 0xD80000: // Expansion slot 6 2.848 - case 0xDC0000: // Expansion slot 7 2.849 - fprintf(stderr, "NOTE: WR32 to expansion card space, addr=0x%08X, data=0x%08X\n", address, value); 2.850 - handled = true; 2.851 - break; 2.852 - } 2.853 - break; 2.854 - case 0xE00000: // HDC, FDC, MCR2 and RTC data bits 2.855 - case 0xF00000: 2.856 - switch (address & 0x070000) { 2.857 - case 0x000000: // [ef][08]xxxx ==> WD1010 hard disc controller 2.858 - break; 2.859 - case 0x010000: // [ef][19]xxxx ==> WD2797 floppy disc controller 2.860 - break; 2.861 - case 0x020000: // [ef][2a]xxxx ==> Miscellaneous Control Register 2 2.862 - break; 2.863 - case 0x030000: // [ef][3b]xxxx ==> Real Time Clock data bits 2.864 - break; 2.865 - case 0x040000: // [ef][4c]xxxx ==> General Control Register 2.866 - switch (address & 0x077000) { 2.867 - case 0x040000: // [ef][4c][08]xxx ==> EE 2.868 - break; 2.869 - case 0x041000: // [ef][4c][19]xxx ==> P1E 2.870 - break; 2.871 - case 0x042000: // [ef][4c][2A]xxx ==> BP 2.872 - break; 2.873 - case 0x043000: // [ef][4c][3B]xxx ==> ROMLMAP 2.874 - state.romlmap = ((value & 0x8000) == 0x8000); 2.875 - break; 2.876 - case 0x044000: // [ef][4c][4C]xxx ==> L1 MODEM 2.877 - break; 2.878 - case 0x045000: // [ef][4c][5D]xxx ==> L2 MODEM 2.879 - break; 2.880 - case 0x046000: // [ef][4c][6E]xxx ==> D/N CONNECT 2.881 - break; 2.882 - case 0x047000: // [ef][4c][7F]xxx ==> Whole screen reverse video 2.883 - break; 2.884 - } 2.885 - case 0x050000: // [ef][5d]xxxx ==> 8274 2.886 - break; 2.887 - case 0x060000: // [ef][6e]xxxx ==> Control regs 2.888 - switch (address & 0x07F000) { 2.889 - default: 2.890 - break; 2.891 - } 2.892 - break; 2.893 - case 0x070000: // [ef][7f]xxxx ==> 6850 Keyboard Controller 2.894 - break; 2.895 - } 2.896 - } 2.897 - } 2.898 - 2.899 - LOG_NOT_HANDLED_W(32); 2.900 -} 2.901 - 2.902 -/** 2.903 - * @brief Write M68K memory, 16-bit 2.904 - */ 2.905 -void m68k_write_memory_16(uint32_t address, uint32_t value) 2.906 -{ 2.907 - bool handled = false; 2.908 - 2.909 - // If ROMLMAP is set, force system to access ROM 2.910 - if (!state.romlmap) 2.911 - address |= 0x800000; 2.912 - 2.913 - // Check access permissions 2.914 - ACCESS_CHECK_WR(address, 16); 2.915 - 2.916 - if ((address >= 0x800000) && (address <= 0xBFFFFF)) { 2.917 - // ROM access 2.918 - handled = true; 2.919 - } else if (address <= (state.ram_size - 1)) { 2.920 - // RAM access 2.921 - WR16(state.ram, mapAddr(address, false), state.ram_size - 1, value); 2.922 - handled = true; 2.923 - } else if ((address >= 0x400000) && (address <= 0x7FFFFF)) { 2.924 - // I/O register space, zone A 2.925 - switch (address & 0x0F0000) { 2.926 - case 0x000000: // Map RAM access 2.927 - if (address > 0x4007FF) fprintf(stderr, "NOTE: WR16 to MapRAM mirror, addr=0x%08X, data=0x%04X\n", address, value); 2.928 - WR16(state.map, address, 0x7FF, value); 2.929 - handled = true; 2.930 - break; 2.931 - case 0x010000: // General Status Register (read only) 2.932 - handled = true; 2.933 - break; 2.934 - case 0x020000: // Video RAM 2.935 - if (address > 0x427FFF) fprintf(stderr, "NOTE: WR16 to VideoRAM mirror, addr=0x%08X, data=0x%04X\n", address, value); 2.936 - WR16(state.vram, address, 0x7FFF, value); 2.937 - handled = true; 2.938 - break; 2.939 - case 0x030000: // Bus Status Register 0 (read only) 2.940 - handled = true; 2.941 - break; 2.942 - case 0x040000: // Bus Status Register 1 (read only) 2.943 - handled = true; 2.944 - break; 2.945 - case 0x050000: // Phone status 2.946 - break; 2.947 - case 0x060000: // DMA Count 2.948 - break; 2.949 - case 0x070000: // Line Printer Status Register 2.950 - break; 2.951 - case 0x080000: // Real Time Clock 2.952 - break; 2.953 - case 0x090000: // Phone registers 2.954 - switch (address & 0x0FF000) { 2.955 - case 0x090000: // Handset relay 2.956 - case 0x098000: 2.957 - break; 2.958 - case 0x091000: // Line select 2 2.959 - case 0x099000: 2.960 - break; 2.961 - case 0x092000: // Hook relay 1 2.962 - case 0x09A000: 2.963 - break; 2.964 - case 0x093000: // Hook relay 2 2.965 - case 0x09B000: 2.966 - break; 2.967 - case 0x094000: // Line 1 hold 2.968 - case 0x09C000: 2.969 - break; 2.970 - case 0x095000: // Line 2 hold 2.971 - case 0x09D000: 2.972 - break; 2.973 - case 0x096000: // Line 1 A-lead 2.974 - case 0x09E000: 2.975 - break; 2.976 - case 0x097000: // Line 2 A-lead 2.977 - case 0x09F000: 2.978 - break; 2.979 - } 2.980 - break; 2.981 - case 0x0A0000: // Miscellaneous Control Register 2.982 - break; 2.983 - case 0x0B0000: // TM/DIALWR 2.984 - break; 2.985 - case 0x0C0000: // CSR 2.986 - break; 2.987 - case 0x0D0000: // DMA Address Register 2.988 - break; 2.989 - case 0x0E0000: // Disk Control Register 2.990 - break; 2.991 - case 0x0F0000: // Line Printer Data Register 2.992 - break; 2.993 - } 2.994 - } else if ((address >= 0xC00000) && (address <= 0xFFFFFF)) { 2.995 - // I/O register space, zone B 2.996 - switch (address & 0xF00000) { 2.997 - case 0xC00000: // Expansion slots 2.998 - case 0xD00000: 2.999 - switch (address & 0xFC0000) { 2.1000 - case 0xC00000: // Expansion slot 0 2.1001 - case 0xC40000: // Expansion slot 1 2.1002 - case 0xC80000: // Expansion slot 2 2.1003 - case 0xCC0000: // Expansion slot 3 2.1004 - case 0xD00000: // Expansion slot 4 2.1005 - case 0xD40000: // Expansion slot 5 2.1006 - case 0xD80000: // Expansion slot 6 2.1007 - case 0xDC0000: // Expansion slot 7 2.1008 - fprintf(stderr, "NOTE: WR16 to expansion card space, addr=0x%08X, data=0x%04X\n", address, value); 2.1009 - break; 2.1010 - } 2.1011 - break; 2.1012 - case 0xE00000: // HDC, FDC, MCR2 and RTC data bits 2.1013 - case 0xF00000: 2.1014 - switch (address & 0x070000) { 2.1015 - case 0x000000: // [ef][08]xxxx ==> WD1010 hard disc controller 2.1016 - break; 2.1017 - case 0x010000: // [ef][19]xxxx ==> WD2797 floppy disc controller 2.1018 - break; 2.1019 - case 0x020000: // [ef][2a]xxxx ==> Miscellaneous Control Register 2 2.1020 - break; 2.1021 - case 0x030000: // [ef][3b]xxxx ==> Real Time Clock data bits 2.1022 - break; 2.1023 - case 0x040000: // [ef][4c]xxxx ==> General Control Register 2.1024 - switch (address & 0x077000) { 2.1025 - case 0x040000: // [ef][4c][08]xxx ==> EE 2.1026 - break; 2.1027 - case 0x041000: // [ef][4c][19]xxx ==> P1E 2.1028 - break; 2.1029 - case 0x042000: // [ef][4c][2A]xxx ==> BP 2.1030 - break; 2.1031 - case 0x043000: // [ef][4c][3B]xxx ==> ROMLMAP 2.1032 - state.romlmap = ((value & 0x8000) == 0x8000); 2.1033 - handled = true; 2.1034 - break; 2.1035 - case 0x044000: // [ef][4c][4C]xxx ==> L1 MODEM 2.1036 - break; 2.1037 - case 0x045000: // [ef][4c][5D]xxx ==> L2 MODEM 2.1038 - break; 2.1039 - case 0x046000: // [ef][4c][6E]xxx ==> D/N CONNECT 2.1040 - break; 2.1041 - case 0x047000: // [ef][4c][7F]xxx ==> Whole screen reverse video 2.1042 - break; 2.1043 - } 2.1044 - case 0x050000: // [ef][5d]xxxx ==> 8274 2.1045 - break; 2.1046 - case 0x060000: // [ef][6e]xxxx ==> Control regs 2.1047 - switch (address & 0x07F000) { 2.1048 - default: 2.1049 - break; 2.1050 - } 2.1051 - break; 2.1052 - case 0x070000: // [ef][7f]xxxx ==> 6850 Keyboard Controller 2.1053 - break; 2.1054 - } 2.1055 - } 2.1056 - } 2.1057 - 2.1058 - LOG_NOT_HANDLED_W(16); 2.1059 -} 2.1060 - 2.1061 -/** 2.1062 - * @brief Write M68K memory, 8-bit 2.1063 - */ 2.1064 -void m68k_write_memory_8(uint32_t address, uint32_t value) 2.1065 -{ 2.1066 - bool handled = false; 2.1067 - 2.1068 - // If ROMLMAP is set, force system to access ROM 2.1069 - if (!state.romlmap) 2.1070 - address |= 0x800000; 2.1071 - 2.1072 - // Check access permissions 2.1073 - ACCESS_CHECK_WR(address, 8); 2.1074 - 2.1075 - if ((address >= 0x800000) && (address <= 0xBFFFFF)) { 2.1076 - // ROM access (read only!) 2.1077 - handled = true; 2.1078 - } else if (address <= (state.ram_size - 1)) { 2.1079 - // RAM access 2.1080 - WR8(state.ram, mapAddr(address, false), state.ram_size - 1, value); 2.1081 - handled = true; 2.1082 - } else if ((address >= 0x400000) && (address <= 0x7FFFFF)) { 2.1083 - // I/O register space, zone A 2.1084 - switch (address & 0x0F0000) { 2.1085 - case 0x000000: // Map RAM access 2.1086 - if (address > 0x4007FF) fprintf(stderr, "NOTE: WR8 to MapRAM mirror, addr=%08X, data=%02X\n", address, value); 2.1087 - WR8(state.map, address, 0x7FF, value); 2.1088 - handled = true; 2.1089 - break; 2.1090 - case 0x010000: // General Status Register 2.1091 - handled = true; 2.1092 - break; 2.1093 - case 0x020000: // Video RAM 2.1094 - if (address > 0x427FFF) fprintf(stderr, "NOTE: WR8 to VideoRAM mirror, addr=%08X\n, data=0x%02X", address, value); 2.1095 - WR8(state.vram, address, 0x7FFF, value); 2.1096 - handled = true; 2.1097 - break; 2.1098 - case 0x030000: // Bus Status Register 0 2.1099 - handled = true; 2.1100 - break; 2.1101 - case 0x040000: // Bus Status Register 1 2.1102 - handled = true; 2.1103 - break; 2.1104 - case 0x050000: // Phone status 2.1105 - break; 2.1106 - case 0x060000: // DMA Count 2.1107 - break; 2.1108 - case 0x070000: // Line Printer Status Register 2.1109 - break; 2.1110 - case 0x080000: // Real Time Clock 2.1111 - break; 2.1112 - case 0x090000: // Phone registers 2.1113 - switch (address & 0x0FF000) { 2.1114 - case 0x090000: // Handset relay 2.1115 - case 0x098000: 2.1116 - break; 2.1117 - case 0x091000: // Line select 2 2.1118 - case 0x099000: 2.1119 - break; 2.1120 - case 0x092000: // Hook relay 1 2.1121 - case 0x09A000: 2.1122 - break; 2.1123 - case 0x093000: // Hook relay 2 2.1124 - case 0x09B000: 2.1125 - break; 2.1126 - case 0x094000: // Line 1 hold 2.1127 - case 0x09C000: 2.1128 - break; 2.1129 - case 0x095000: // Line 2 hold 2.1130 - case 0x09D000: 2.1131 - break; 2.1132 - case 0x096000: // Line 1 A-lead 2.1133 - case 0x09E000: 2.1134 - break; 2.1135 - case 0x097000: // Line 2 A-lead 2.1136 - case 0x09F000: 2.1137 - break; 2.1138 - } 2.1139 - break; 2.1140 - case 0x0A0000: // Miscellaneous Control Register 2.1141 - break; 2.1142 - case 0x0B0000: // TM/DIALWR 2.1143 - break; 2.1144 - case 0x0C0000: // CSR 2.1145 - break; 2.1146 - case 0x0D0000: // DMA Address Register 2.1147 - break; 2.1148 - case 0x0E0000: // Disk Control Register 2.1149 - break; 2.1150 - case 0x0F0000: // Line Printer Data Register 2.1151 - break; 2.1152 - } 2.1153 - } else if ((address >= 0xC00000) && (address <= 0xFFFFFF)) { 2.1154 - // I/O register space, zone B 2.1155 - switch (address & 0xF00000) { 2.1156 - case 0xC00000: // Expansion slots 2.1157 - case 0xD00000: 2.1158 - switch (address & 0xFC0000) { 2.1159 - case 0xC00000: // Expansion slot 0 2.1160 - case 0xC40000: // Expansion slot 1 2.1161 - case 0xC80000: // Expansion slot 2 2.1162 - case 0xCC0000: // Expansion slot 3 2.1163 - case 0xD00000: // Expansion slot 4 2.1164 - case 0xD40000: // Expansion slot 5 2.1165 - case 0xD80000: // Expansion slot 6 2.1166 - case 0xDC0000: // Expansion slot 7 2.1167 - fprintf(stderr, "NOTE: WR8 to expansion card space, addr=0x%08X, data=0x%08X\n", address, value); 2.1168 - break; 2.1169 - } 2.1170 - break; 2.1171 - case 0xE00000: // HDC, FDC, MCR2 and RTC data bits 2.1172 - case 0xF00000: 2.1173 - switch (address & 0x070000) { 2.1174 - case 0x000000: // [ef][08]xxxx ==> WD1010 hard disc controller 2.1175 - break; 2.1176 - case 0x010000: // [ef][19]xxxx ==> WD2797 floppy disc controller 2.1177 - break; 2.1178 - case 0x020000: // [ef][2a]xxxx ==> Miscellaneous Control Register 2 2.1179 - break; 2.1180 - case 0x030000: // [ef][3b]xxxx ==> Real Time Clock data bits 2.1181 - break; 2.1182 - case 0x040000: // [ef][4c]xxxx ==> General Control Register 2.1183 - switch (address & 0x077000) { 2.1184 - case 0x040000: // [ef][4c][08]xxx ==> EE 2.1185 - break; 2.1186 - case 0x041000: // [ef][4c][19]xxx ==> P1E 2.1187 - break; 2.1188 - case 0x042000: // [ef][4c][2A]xxx ==> BP 2.1189 - break; 2.1190 - case 0x043000: // [ef][4c][3B]xxx ==> ROMLMAP 2.1191 - if ((address & 1) == 0) 2.1192 - state.romlmap = ((value & 0x80) == 0x80); 2.1193 - handled = true; 2.1194 - break; 2.1195 - case 0x044000: // [ef][4c][4C]xxx ==> L1 MODEM 2.1196 - break; 2.1197 - case 0x045000: // [ef][4c][5D]xxx ==> L2 MODEM 2.1198 - break; 2.1199 - case 0x046000: // [ef][4c][6E]xxx ==> D/N CONNECT 2.1200 - break; 2.1201 - case 0x047000: // [ef][4c][7F]xxx ==> Whole screen reverse video 2.1202 - break; 2.1203 - } 2.1204 - case 0x050000: // [ef][5d]xxxx ==> 8274 2.1205 - break; 2.1206 - case 0x060000: // [ef][6e]xxxx ==> Control regs 2.1207 - switch (address & 0x07F000) { 2.1208 - default: 2.1209 - break; 2.1210 - } 2.1211 - break; 2.1212 - case 0x070000: // [ef][7f]xxxx ==> 6850 Keyboard Controller 2.1213 - break; 2.1214 - default: 2.1215 - fprintf(stderr, "NOTE: WR8 to undefined E/F-block space, addr=0x%08X, data=0x%08X\n", address, value); 2.1216 - break; 2.1217 - } 2.1218 - } 2.1219 - } 2.1220 - 2.1221 - LOG_NOT_HANDLED_W(8); 2.1222 -} 2.1223 - 2.1224 - 2.1225 -// for the disassembler 2.1226 -uint32_t m68k_read_disassembler_32(uint32_t addr) { return m68k_read_memory_32(addr); } 2.1227 -uint32_t m68k_read_disassembler_16(uint32_t addr) { return m68k_read_memory_16(addr); } 2.1228 -uint32_t m68k_read_disassembler_8 (uint32_t addr) { return m68k_read_memory_8 (addr); } 2.1229 - 2.1230 - 2.1231 /**************************** 2.1232 * blessed be thy main()... 2.1233 ****************************/
3.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 3.2 +++ b/src/memory.c Thu Dec 02 23:03:13 2010 +0000 3.3 @@ -0,0 +1,1177 @@ 3.4 +#include <stdio.h> 3.5 +#include <stdlib.h> 3.6 +#include <stdint.h> 3.7 +#include <stdbool.h> 3.8 +#include "musashi/m68k.h" 3.9 +#include "state.h" 3.10 +#include "memory.h" 3.11 + 3.12 +/****************** 3.13 + * Memory mapping 3.14 + ******************/ 3.15 + 3.16 +#define MAPRAM(addr) (((uint16_t)state.map[addr*2] << 8) + ((uint16_t)state.map[(addr*2)+1])) 3.17 + 3.18 +uint32_t mapAddr(uint32_t addr, bool writing) 3.19 +{ 3.20 + if (addr < 0x400000) { 3.21 + // RAM access. Check against the Map RAM 3.22 + // Start by getting the original page address 3.23 + uint16_t page = (addr >> 12) & 0x3FF; 3.24 + 3.25 + // Look it up in the map RAM and get the physical page address 3.26 + uint32_t new_page_addr = MAPRAM(page) & 0x3FF; 3.27 + 3.28 + // Update the Page Status bits 3.29 + uint8_t pagebits = (MAPRAM(page) >> 13) & 0x03; 3.30 + if (pagebits != 0) { 3.31 + if (writing) 3.32 + state.map[page*2] |= 0x60; // Page written to (dirty) 3.33 + else 3.34 + state.map[page*2] |= 0x40; // Page accessed but not written 3.35 + } 3.36 + 3.37 + // Return the address with the new physical page spliced in 3.38 + return (new_page_addr << 12) + (addr & 0xFFF); 3.39 + } else { 3.40 + // I/O, VRAM or MapRAM space; no mapping is performed or required 3.41 + // TODO: assert here? 3.42 + return addr; 3.43 + } 3.44 +} 3.45 + 3.46 +MEM_STATUS checkMemoryAccess(uint32_t addr, bool writing) 3.47 +{ 3.48 + // Are we in Supervisor mode? 3.49 + if (m68k_get_reg(NULL, M68K_REG_SR) & 0x2000) 3.50 + // Yes. We can do anything we like. 3.51 + return MEM_ALLOWED; 3.52 + 3.53 + // If we're here, then we must be in User mode. 3.54 + // Check that the user didn't access memory outside of the RAM area 3.55 + if (addr >= 0x400000) 3.56 + return MEM_UIE; 3.57 + 3.58 + // This leaves us with Page Fault checking. Get the page bits for this page. 3.59 + uint16_t page = (addr >> 12) & 0x3FF; 3.60 + uint8_t pagebits = (MAPRAM(page) >> 13) & 0x07; 3.61 + 3.62 + // Check page is present 3.63 + if ((pagebits & 0x03) == 0) 3.64 + return MEM_PAGEFAULT; 3.65 + 3.66 + // User attempt to access the kernel 3.67 + // A19, A20, A21, A22 low (kernel access): RAM addr before paging; not in Supervisor mode 3.68 + if (((addr >> 19) & 0x0F) == 0) 3.69 + return MEM_KERNEL; 3.70 + 3.71 + // Check page is write enabled 3.72 + if ((pagebits & 0x04) == 0) 3.73 + return MEM_PAGE_NO_WE; 3.74 + 3.75 + // Page access allowed. 3.76 + return MEM_ALLOWED; 3.77 +} 3.78 + 3.79 +#undef MAPRAM 3.80 + 3.81 + 3.82 +/******************************************************** 3.83 + * m68k memory read/write support functions for Musashi 3.84 + ********************************************************/ 3.85 + 3.86 +/** 3.87 + * @brief Check memory access permissions for a write operation. 3.88 + * @note This used to be a single macro (merged with ACCESS_CHECK_RD), but 3.89 + * gcc throws warnings when you have a return-with-value in a void 3.90 + * function, even if the return-with-value is completely unreachable. 3.91 + * Similarly it doesn't like it if you have a return without a value 3.92 + * in a non-void function, even if it's impossible to ever reach the 3.93 + * return-with-no-value. UGH! 3.94 + */ 3.95 +#define ACCESS_CHECK_WR(address, bits) do { \ 3.96 + bool fault = false; \ 3.97 + /* MEM_STATUS st; */ \ 3.98 + switch (checkMemoryAccess(address, true)) { \ 3.99 + case MEM_ALLOWED: \ 3.100 + /* Access allowed */ \ 3.101 + break; \ 3.102 + case MEM_PAGEFAULT: \ 3.103 + /* Page fault */ \ 3.104 + state.genstat = 0x8FFF; \ 3.105 + fault = true; \ 3.106 + break; \ 3.107 + case MEM_UIE: \ 3.108 + /* User access to memory above 4MB */ \ 3.109 + state.genstat = 0x9EFF; \ 3.110 + fault = true; \ 3.111 + break; \ 3.112 + case MEM_KERNEL: \ 3.113 + case MEM_PAGE_NO_WE: \ 3.114 + /* kernel access or page not write enabled */ \ 3.115 + /* TODO: which regs need setting? */ \ 3.116 + fault = true; \ 3.117 + break; \ 3.118 + } \ 3.119 + \ 3.120 + if (fault) { \ 3.121 + if (bits >= 16) \ 3.122 + state.bsr0 = 0x7F00; \ 3.123 + else \ 3.124 + state.bsr0 = (address & 1) ? 0x7D00 : 0x7E00; \ 3.125 + state.bsr0 |= (address >> 16); \ 3.126 + state.bsr1 = address & 0xffff; \ 3.127 + printf("ERR: BusError WR\n"); \ 3.128 + m68k_pulse_bus_error(); \ 3.129 + return; \ 3.130 + } \ 3.131 + } while (false) 3.132 + 3.133 +/** 3.134 + * @brief Check memory access permissions for a read operation. 3.135 + * @note This used to be a single macro (merged with ACCESS_CHECK_WR), but 3.136 + * gcc throws warnings when you have a return-with-value in a void 3.137 + * function, even if the return-with-value is completely unreachable. 3.138 + * Similarly it doesn't like it if you have a return without a value 3.139 + * in a non-void function, even if it's impossible to ever reach the 3.140 + * return-with-no-value. UGH! 3.141 + */ 3.142 +#define ACCESS_CHECK_RD(address, bits) do { \ 3.143 + bool fault = false; \ 3.144 + /* MEM_STATUS st; */ \ 3.145 + switch (checkMemoryAccess(address, false)) { \ 3.146 + case MEM_ALLOWED: \ 3.147 + /* Access allowed */ \ 3.148 + break; \ 3.149 + case MEM_PAGEFAULT: \ 3.150 + /* Page fault */ \ 3.151 + state.genstat = 0x8FFF; \ 3.152 + fault = true; \ 3.153 + break; \ 3.154 + case MEM_UIE: \ 3.155 + /* User access to memory above 4MB */ \ 3.156 + state.genstat = 0x9EFF; \ 3.157 + fault = true; \ 3.158 + break; \ 3.159 + case MEM_KERNEL: \ 3.160 + case MEM_PAGE_NO_WE: \ 3.161 + /* kernel access or page not write enabled */ \ 3.162 + /* TODO: which regs need setting? */ \ 3.163 + fault = true; \ 3.164 + break; \ 3.165 + } \ 3.166 + \ 3.167 + if (fault) { \ 3.168 + if (bits >= 16) \ 3.169 + state.bsr0 = 0x7F00; \ 3.170 + else \ 3.171 + state.bsr0 = (address & 1) ? 0x7D00 : 0x7E00; \ 3.172 + state.bsr0 |= (address >> 16); \ 3.173 + state.bsr1 = address & 0xffff; \ 3.174 + printf("ERR: BusError RD\n"); \ 3.175 + m68k_pulse_bus_error(); \ 3.176 + return 0xFFFFFFFF; \ 3.177 + } \ 3.178 + } while (false) 3.179 + 3.180 +// Logging macros 3.181 +#define LOG_NOT_HANDLED_R(bits) \ 3.182 + do { \ 3.183 + if (!handled) \ 3.184 + printf("unhandled read%02d, addr=0x%08X\n", bits, address); \ 3.185 + } while (0); 3.186 + 3.187 +#define LOG_NOT_HANDLED_W(bits) \ 3.188 + do { \ 3.189 + if (!handled) \ 3.190 + printf("unhandled write%02d, addr=0x%08X, data=0x%08X\n", bits, address, value); \ 3.191 + } while (0); 3.192 + 3.193 +/** 3.194 + * @brief Read M68K memory, 32-bit 3.195 + */ 3.196 +uint32_t m68k_read_memory_32(uint32_t address) 3.197 +{ 3.198 + uint32_t data = 0xFFFFFFFF; 3.199 + bool handled = false; 3.200 + 3.201 + // If ROMLMAP is set, force system to access ROM 3.202 + if (!state.romlmap) 3.203 + address |= 0x800000; 3.204 + 3.205 + // Check access permissions 3.206 + ACCESS_CHECK_RD(address, 32); 3.207 + 3.208 + if ((address >= 0x800000) && (address <= 0xBFFFFF)) { 3.209 + // ROM access 3.210 + data = RD32(state.rom, address, ROM_SIZE - 1); 3.211 + handled = true; 3.212 + } else if (address <= (state.ram_size - 1)) { 3.213 + // RAM access 3.214 + data = RD32(state.ram, mapAddr(address, false), state.ram_size - 1); 3.215 + handled = true; 3.216 + } else if ((address >= 0x400000) && (address <= 0x7FFFFF)) { 3.217 + // I/O register space, zone A 3.218 + switch (address & 0x0F0000) { 3.219 + case 0x000000: // Map RAM access 3.220 + if (address > 0x4007FF) fprintf(stderr, "NOTE: RD32 from MapRAM mirror, addr=0x%08X\n", address); 3.221 + data = RD32(state.map, address, 0x7FF); 3.222 + handled = true; 3.223 + break; 3.224 + case 0x010000: // General Status Register 3.225 + data = ((uint32_t)state.genstat << 16) + (uint32_t)state.genstat; 3.226 + handled = true; 3.227 + break; 3.228 + case 0x020000: // Video RAM 3.229 + if (address > 0x427FFF) fprintf(stderr, "NOTE: RD32 from VideoRAM mirror, addr=0x%08X\n", address); 3.230 + data = RD32(state.vram, address, 0x7FFF); 3.231 + handled = true; 3.232 + break; 3.233 + case 0x030000: // Bus Status Register 0 3.234 + data = ((uint32_t)state.bsr0 << 16) + (uint32_t)state.bsr0; 3.235 + handled = true; 3.236 + break; 3.237 + case 0x040000: // Bus Status Register 1 3.238 + data = ((uint32_t)state.bsr1 << 16) + (uint32_t)state.bsr1; 3.239 + handled = true; 3.240 + break; 3.241 + case 0x050000: // Phone status 3.242 + break; 3.243 + case 0x060000: // DMA Count 3.244 + break; 3.245 + case 0x070000: // Line Printer Status Register 3.246 + break; 3.247 + case 0x080000: // Real Time Clock 3.248 + break; 3.249 + case 0x090000: // Phone registers 3.250 + switch (address & 0x0FF000) { 3.251 + case 0x090000: // Handset relay 3.252 + case 0x098000: 3.253 + break; 3.254 + case 0x091000: // Line select 2 3.255 + case 0x099000: 3.256 + break; 3.257 + case 0x092000: // Hook relay 1 3.258 + case 0x09A000: 3.259 + break; 3.260 + case 0x093000: // Hook relay 2 3.261 + case 0x09B000: 3.262 + break; 3.263 + case 0x094000: // Line 1 hold 3.264 + case 0x09C000: 3.265 + break; 3.266 + case 0x095000: // Line 2 hold 3.267 + case 0x09D000: 3.268 + break; 3.269 + case 0x096000: // Line 1 A-lead 3.270 + case 0x09E000: 3.271 + break; 3.272 + case 0x097000: // Line 2 A-lead 3.273 + case 0x09F000: 3.274 + break; 3.275 + } 3.276 + break; 3.277 + case 0x0A0000: // Miscellaneous Control Register 3.278 + break; 3.279 + case 0x0B0000: // TM/DIALWR 3.280 + break; 3.281 + case 0x0C0000: // CSR 3.282 + break; 3.283 + case 0x0D0000: // DMA Address Register 3.284 + break; 3.285 + case 0x0E0000: // Disk Control Register 3.286 + break; 3.287 + case 0x0F0000: // Line Printer Data Register 3.288 + break; 3.289 + } 3.290 + } else if ((address >= 0xC00000) && (address <= 0xFFFFFF)) { 3.291 + // I/O register space, zone B 3.292 + switch (address & 0xF00000) { 3.293 + case 0xC00000: // Expansion slots 3.294 + case 0xD00000: 3.295 + switch (address & 0xFC0000) { 3.296 + case 0xC00000: // Expansion slot 0 3.297 + case 0xC40000: // Expansion slot 1 3.298 + case 0xC80000: // Expansion slot 2 3.299 + case 0xCC0000: // Expansion slot 3 3.300 + case 0xD00000: // Expansion slot 4 3.301 + case 0xD40000: // Expansion slot 5 3.302 + case 0xD80000: // Expansion slot 6 3.303 + case 0xDC0000: // Expansion slot 7 3.304 + fprintf(stderr, "NOTE: RD32 from expansion card space, addr=0x%08X\n", address); 3.305 + break; 3.306 + } 3.307 + break; 3.308 + case 0xE00000: // HDC, FDC, MCR2 and RTC data bits 3.309 + case 0xF00000: 3.310 + switch (address & 0x070000) { 3.311 + case 0x000000: // [ef][08]xxxx ==> WD1010 hard disc controller 3.312 + break; 3.313 + case 0x010000: // [ef][19]xxxx ==> WD2797 floppy disc controller 3.314 + break; 3.315 + case 0x020000: // [ef][2a]xxxx ==> Miscellaneous Control Register 2 3.316 + break; 3.317 + case 0x030000: // [ef][3b]xxxx ==> Real Time Clock data bits 3.318 + break; 3.319 + case 0x040000: // [ef][4c]xxxx ==> General Control Register 3.320 + switch (address & 0x077000) { 3.321 + case 0x040000: // [ef][4c][08]xxx ==> EE 3.322 + break; 3.323 + case 0x041000: // [ef][4c][19]xxx ==> P1E 3.324 + break; 3.325 + case 0x042000: // [ef][4c][2A]xxx ==> BP 3.326 + break; 3.327 + case 0x043000: // [ef][4c][3B]xxx ==> ROMLMAP 3.328 + break; 3.329 + case 0x044000: // [ef][4c][4C]xxx ==> L1 MODEM 3.330 + break; 3.331 + case 0x045000: // [ef][4c][5D]xxx ==> L2 MODEM 3.332 + break; 3.333 + case 0x046000: // [ef][4c][6E]xxx ==> D/N CONNECT 3.334 + break; 3.335 + case 0x047000: // [ef][4c][7F]xxx ==> Whole screen reverse video 3.336 + break; 3.337 + } 3.338 + break; 3.339 + case 0x050000: // [ef][5d]xxxx ==> 8274 3.340 + break; 3.341 + case 0x060000: // [ef][6e]xxxx ==> Control regs 3.342 + switch (address & 0x07F000) { 3.343 + default: 3.344 + break; 3.345 + } 3.346 + break; 3.347 + case 0x070000: // [ef][7f]xxxx ==> 6850 Keyboard Controller 3.348 + break; 3.349 + } 3.350 + } 3.351 + } 3.352 + 3.353 + LOG_NOT_HANDLED_R(32); 3.354 + return data; 3.355 +} 3.356 + 3.357 +/** 3.358 + * @brief Read M68K memory, 16-bit 3.359 + */ 3.360 +uint32_t m68k_read_memory_16(uint32_t address) 3.361 +{ 3.362 + uint16_t data = 0xFFFF; 3.363 + bool handled = false; 3.364 + 3.365 + // If ROMLMAP is set, force system to access ROM 3.366 + if (!state.romlmap) 3.367 + address |= 0x800000; 3.368 + 3.369 + // Check access permissions 3.370 + ACCESS_CHECK_RD(address, 16); 3.371 + 3.372 + if ((address >= 0x800000) && (address <= 0xBFFFFF)) { 3.373 + // ROM access 3.374 + data = RD16(state.rom, address, ROM_SIZE - 1); 3.375 + handled = true; 3.376 + } else if (address <= (state.ram_size - 1)) { 3.377 + // RAM access 3.378 + data = RD16(state.ram, mapAddr(address, false), state.ram_size - 1); 3.379 + handled = true; 3.380 + } else if ((address >= 0x400000) && (address <= 0x7FFFFF)) { 3.381 + // I/O register space, zone A 3.382 + switch (address & 0x0F0000) { 3.383 + case 0x000000: // Map RAM access 3.384 + if (address > 0x4007FF) fprintf(stderr, "NOTE: RD16 from MapRAM mirror, addr=0x%08X\n", address); 3.385 + data = RD16(state.map, address, 0x7FF); 3.386 + handled = true; 3.387 + break; 3.388 + case 0x010000: // General Status Register 3.389 + data = state.genstat; 3.390 + handled = true; 3.391 + break; 3.392 + case 0x020000: // Video RAM 3.393 + if (address > 0x427FFF) fprintf(stderr, "NOTE: RD16 from VideoRAM mirror, addr=0x%08X\n", address); 3.394 + data = RD16(state.vram, address, 0x7FFF); 3.395 + handled = true; 3.396 + break; 3.397 + case 0x030000: // Bus Status Register 0 3.398 + data = state.bsr0; 3.399 + handled = true; 3.400 + break; 3.401 + case 0x040000: // Bus Status Register 1 3.402 + data = state.bsr1; 3.403 + handled = true; 3.404 + break; 3.405 + case 0x050000: // Phone status 3.406 + break; 3.407 + case 0x060000: // DMA Count 3.408 + break; 3.409 + case 0x070000: // Line Printer Status Register 3.410 + break; 3.411 + case 0x080000: // Real Time Clock 3.412 + break; 3.413 + case 0x090000: // Phone registers 3.414 + switch (address & 0x0FF000) { 3.415 + case 0x090000: // Handset relay 3.416 + case 0x098000: 3.417 + break; 3.418 + case 0x091000: // Line select 2 3.419 + case 0x099000: 3.420 + break; 3.421 + case 0x092000: // Hook relay 1 3.422 + case 0x09A000: 3.423 + break; 3.424 + case 0x093000: // Hook relay 2 3.425 + case 0x09B000: 3.426 + break; 3.427 + case 0x094000: // Line 1 hold 3.428 + case 0x09C000: 3.429 + break; 3.430 + case 0x095000: // Line 2 hold 3.431 + case 0x09D000: 3.432 + break; 3.433 + case 0x096000: // Line 1 A-lead 3.434 + case 0x09E000: 3.435 + break; 3.436 + case 0x097000: // Line 2 A-lead 3.437 + case 0x09F000: 3.438 + break; 3.439 + } 3.440 + break; 3.441 + case 0x0A0000: // Miscellaneous Control Register 3.442 + break; 3.443 + case 0x0B0000: // TM/DIALWR 3.444 + break; 3.445 + case 0x0C0000: // CSR 3.446 + break; 3.447 + case 0x0D0000: // DMA Address Register 3.448 + break; 3.449 + case 0x0E0000: // Disk Control Register 3.450 + break; 3.451 + case 0x0F0000: // Line Printer Data Register 3.452 + break; 3.453 + } 3.454 + } else if ((address >= 0xC00000) && (address <= 0xFFFFFF)) { 3.455 + // I/O register space, zone B 3.456 + switch (address & 0xF00000) { 3.457 + case 0xC00000: // Expansion slots 3.458 + case 0xD00000: 3.459 + switch (address & 0xFC0000) { 3.460 + case 0xC00000: // Expansion slot 0 3.461 + case 0xC40000: // Expansion slot 1 3.462 + case 0xC80000: // Expansion slot 2 3.463 + case 0xCC0000: // Expansion slot 3 3.464 + case 0xD00000: // Expansion slot 4 3.465 + case 0xD40000: // Expansion slot 5 3.466 + case 0xD80000: // Expansion slot 6 3.467 + case 0xDC0000: // Expansion slot 7 3.468 + fprintf(stderr, "NOTE: RD16 from expansion card space, addr=0x%08X\n", address); 3.469 + break; 3.470 + } 3.471 + break; 3.472 + case 0xE00000: // HDC, FDC, MCR2 and RTC data bits 3.473 + case 0xF00000: 3.474 + switch (address & 0x070000) { 3.475 + case 0x000000: // [ef][08]xxxx ==> WD1010 hard disc controller 3.476 + break; 3.477 + case 0x010000: // [ef][19]xxxx ==> WD2797 floppy disc controller 3.478 + break; 3.479 + case 0x020000: // [ef][2a]xxxx ==> Miscellaneous Control Register 2 3.480 + break; 3.481 + case 0x030000: // [ef][3b]xxxx ==> Real Time Clock data bits 3.482 + break; 3.483 + case 0x040000: // [ef][4c]xxxx ==> General Control Register 3.484 + switch (address & 0x077000) { 3.485 + case 0x040000: // [ef][4c][08]xxx ==> EE 3.486 + break; 3.487 + case 0x041000: // [ef][4c][19]xxx ==> P1E 3.488 + break; 3.489 + case 0x042000: // [ef][4c][2A]xxx ==> BP 3.490 + break; 3.491 + case 0x043000: // [ef][4c][3B]xxx ==> ROMLMAP 3.492 + break; 3.493 + case 0x044000: // [ef][4c][4C]xxx ==> L1 MODEM 3.494 + break; 3.495 + case 0x045000: // [ef][4c][5D]xxx ==> L2 MODEM 3.496 + break; 3.497 + case 0x046000: // [ef][4c][6E]xxx ==> D/N CONNECT 3.498 + break; 3.499 + case 0x047000: // [ef][4c][7F]xxx ==> Whole screen reverse video 3.500 + break; 3.501 + } 3.502 + break; 3.503 + case 0x050000: // [ef][5d]xxxx ==> 8274 3.504 + break; 3.505 + case 0x060000: // [ef][6e]xxxx ==> Control regs 3.506 + switch (address & 0x07F000) { 3.507 + default: 3.508 + break; 3.509 + } 3.510 + break; 3.511 + case 0x070000: // [ef][7f]xxxx ==> 6850 Keyboard Controller 3.512 + break; 3.513 + } 3.514 + } 3.515 + } 3.516 + 3.517 + LOG_NOT_HANDLED_R(32); 3.518 + return data; 3.519 +} 3.520 + 3.521 +/** 3.522 + * @brief Read M68K memory, 8-bit 3.523 + */ 3.524 +uint32_t m68k_read_memory_8(uint32_t address) 3.525 +{ 3.526 + uint8_t data = 0xFF; 3.527 + bool handled = false; 3.528 + 3.529 + // If ROMLMAP is set, force system to access ROM 3.530 + if (!state.romlmap) 3.531 + address |= 0x800000; 3.532 + 3.533 + // Check access permissions 3.534 + ACCESS_CHECK_RD(address, 8); 3.535 + 3.536 + if ((address >= 0x800000) && (address <= 0xBFFFFF)) { 3.537 + // ROM access 3.538 + data = RD8(state.rom, address, ROM_SIZE - 1); 3.539 + handled = true; 3.540 + } else if (address <= (state.ram_size - 1)) { 3.541 + // RAM access 3.542 + data = RD8(state.ram, mapAddr(address, false), state.ram_size - 1); 3.543 + handled = true; 3.544 + } else if ((address >= 0x400000) && (address <= 0x7FFFFF)) { 3.545 + // I/O register space, zone A 3.546 + switch (address & 0x0F0000) { 3.547 + case 0x000000: // Map RAM access 3.548 + if (address > 0x4007FF) fprintf(stderr, "NOTE: RD8 from MapRAM mirror, addr=0x%08X\n", address); 3.549 + data = RD8(state.map, address, 0x7FF); 3.550 + handled = true; 3.551 + break; 3.552 + case 0x010000: // General Status Register 3.553 + if ((address & 1) == 0) 3.554 + data = (state.genstat >> 8) & 0xff; 3.555 + else 3.556 + data = (state.genstat) & 0xff; 3.557 + handled = true; 3.558 + break; 3.559 + case 0x020000: // Video RAM 3.560 + if (address > 0x427FFF) fprintf(stderr, "NOTE: RD8 from VideoRAM mirror, addr=0x%08X\n", address); 3.561 + data = RD8(state.vram, address, 0x7FFF); 3.562 + handled = true; 3.563 + break; 3.564 + case 0x030000: // Bus Status Register 0 3.565 + if ((address & 1) == 0) 3.566 + data = (state.bsr0 >> 8) & 0xff; 3.567 + else 3.568 + data = (state.bsr0) & 0xff; 3.569 + handled = true; 3.570 + break; 3.571 + case 0x040000: // Bus Status Register 1 3.572 + if ((address & 1) == 0) 3.573 + data = (state.bsr1 >> 8) & 0xff; 3.574 + else 3.575 + data = (state.bsr1) & 0xff; 3.576 + handled = true; 3.577 + break; 3.578 + case 0x050000: // Phone status 3.579 + break; 3.580 + case 0x060000: // DMA Count 3.581 + break; 3.582 + case 0x070000: // Line Printer Status Register 3.583 + break; 3.584 + case 0x080000: // Real Time Clock 3.585 + break; 3.586 + case 0x090000: // Phone registers 3.587 + switch (address & 0x0FF000) { 3.588 + case 0x090000: // Handset relay 3.589 + case 0x098000: 3.590 + break; 3.591 + case 0x091000: // Line select 2 3.592 + case 0x099000: 3.593 + break; 3.594 + case 0x092000: // Hook relay 1 3.595 + case 0x09A000: 3.596 + break; 3.597 + case 0x093000: // Hook relay 2 3.598 + case 0x09B000: 3.599 + break; 3.600 + case 0x094000: // Line 1 hold 3.601 + case 0x09C000: 3.602 + break; 3.603 + case 0x095000: // Line 2 hold 3.604 + case 0x09D000: 3.605 + break; 3.606 + case 0x096000: // Line 1 A-lead 3.607 + case 0x09E000: 3.608 + break; 3.609 + case 0x097000: // Line 2 A-lead 3.610 + case 0x09F000: 3.611 + break; 3.612 + } 3.613 + break; 3.614 + case 0x0A0000: // Miscellaneous Control Register 3.615 + break; 3.616 + case 0x0B0000: // TM/DIALWR 3.617 + break; 3.618 + case 0x0C0000: // CSR 3.619 + break; 3.620 + case 0x0D0000: // DMA Address Register 3.621 + break; 3.622 + case 0x0E0000: // Disk Control Register 3.623 + break; 3.624 + case 0x0F0000: // Line Printer Data Register 3.625 + break; 3.626 + } 3.627 + } else if ((address >= 0xC00000) && (address <= 0xFFFFFF)) { 3.628 + // I/O register space, zone B 3.629 + switch (address & 0xF00000) { 3.630 + case 0xC00000: // Expansion slots 3.631 + case 0xD00000: 3.632 + switch (address & 0xFC0000) { 3.633 + case 0xC00000: // Expansion slot 0 3.634 + case 0xC40000: // Expansion slot 1 3.635 + case 0xC80000: // Expansion slot 2 3.636 + case 0xCC0000: // Expansion slot 3 3.637 + case 0xD00000: // Expansion slot 4 3.638 + case 0xD40000: // Expansion slot 5 3.639 + case 0xD80000: // Expansion slot 6 3.640 + case 0xDC0000: // Expansion slot 7 3.641 + fprintf(stderr, "NOTE: RD8 from expansion card space, addr=0x%08X\n", address); 3.642 + break; 3.643 + } 3.644 + break; 3.645 + case 0xE00000: // HDC, FDC, MCR2 and RTC data bits 3.646 + case 0xF00000: 3.647 + switch (address & 0x070000) { 3.648 + case 0x000000: // [ef][08]xxxx ==> WD1010 hard disc controller 3.649 + break; 3.650 + case 0x010000: // [ef][19]xxxx ==> WD2797 floppy disc controller 3.651 + break; 3.652 + case 0x020000: // [ef][2a]xxxx ==> Miscellaneous Control Register 2 3.653 + break; 3.654 + case 0x030000: // [ef][3b]xxxx ==> Real Time Clock data bits 3.655 + break; 3.656 + case 0x040000: // [ef][4c]xxxx ==> General Control Register 3.657 + switch (address & 0x077000) { 3.658 + case 0x040000: // [ef][4c][08]xxx ==> EE 3.659 + break; 3.660 + case 0x041000: // [ef][4c][19]xxx ==> P1E 3.661 + break; 3.662 + case 0x042000: // [ef][4c][2A]xxx ==> BP 3.663 + break; 3.664 + case 0x043000: // [ef][4c][3B]xxx ==> ROMLMAP 3.665 + break; 3.666 + case 0x044000: // [ef][4c][4C]xxx ==> L1 MODEM 3.667 + break; 3.668 + case 0x045000: // [ef][4c][5D]xxx ==> L2 MODEM 3.669 + break; 3.670 + case 0x046000: // [ef][4c][6E]xxx ==> D/N CONNECT 3.671 + break; 3.672 + case 0x047000: // [ef][4c][7F]xxx ==> Whole screen reverse video 3.673 + break; 3.674 + } 3.675 + case 0x050000: // [ef][5d]xxxx ==> 8274 3.676 + break; 3.677 + case 0x060000: // [ef][6e]xxxx ==> Control regs 3.678 + switch (address & 0x07F000) { 3.679 + default: 3.680 + break; 3.681 + } 3.682 + break; 3.683 + case 0x070000: // [ef][7f]xxxx ==> 6850 Keyboard Controller 3.684 + break; 3.685 + } 3.686 + } 3.687 + } 3.688 + 3.689 + LOG_NOT_HANDLED_R(8); 3.690 + 3.691 + return data; 3.692 +} 3.693 + 3.694 +/** 3.695 + * @brief Write M68K memory, 32-bit 3.696 + */ 3.697 +void m68k_write_memory_32(uint32_t address, uint32_t value) 3.698 +{ 3.699 + bool handled = false; 3.700 + 3.701 + // If ROMLMAP is set, force system to access ROM 3.702 + if (!state.romlmap) 3.703 + address |= 0x800000; 3.704 + 3.705 + // Check access permissions 3.706 + ACCESS_CHECK_WR(address, 32); 3.707 + 3.708 + if ((address >= 0x800000) && (address <= 0xBFFFFF)) { 3.709 + // ROM access 3.710 + handled = true; 3.711 + } else if (address <= (state.ram_size - 1)) { 3.712 + // RAM access 3.713 + WR32(state.ram, mapAddr(address, false), state.ram_size - 1, value); 3.714 + handled = true; 3.715 + } else if ((address >= 0x400000) && (address <= 0x7FFFFF)) { 3.716 + // I/O register space, zone A 3.717 + switch (address & 0x0F0000) { 3.718 + case 0x000000: // Map RAM access 3.719 + if (address > 0x4007FF) fprintf(stderr, "NOTE: WR32 to MapRAM mirror, addr=0x%08X, data=0x%08X\n", address, value); 3.720 + WR32(state.map, address, 0x7FF, value); 3.721 + handled = true; 3.722 + break; 3.723 + case 0x010000: // General Status Register 3.724 + state.genstat = (value & 0xffff); 3.725 + handled = true; 3.726 + break; 3.727 + case 0x020000: // Video RAM 3.728 + if (address > 0x427FFF) fprintf(stderr, "NOTE: WR32 to VideoRAM mirror, addr=0x%08X, data=0x%08X\n", address, value); 3.729 + WR32(state.vram, address, 0x7FFF, value); 3.730 + handled = true; 3.731 + break; 3.732 + case 0x030000: // Bus Status Register 0 3.733 + break; 3.734 + case 0x040000: // Bus Status Register 1 3.735 + break; 3.736 + case 0x050000: // Phone status 3.737 + break; 3.738 + case 0x060000: // DMA Count 3.739 + break; 3.740 + case 0x070000: // Line Printer Status Register 3.741 + break; 3.742 + case 0x080000: // Real Time Clock 3.743 + break; 3.744 + case 0x090000: // Phone registers 3.745 + switch (address & 0x0FF000) { 3.746 + case 0x090000: // Handset relay 3.747 + case 0x098000: 3.748 + break; 3.749 + case 0x091000: // Line select 2 3.750 + case 0x099000: 3.751 + break; 3.752 + case 0x092000: // Hook relay 1 3.753 + case 0x09A000: 3.754 + break; 3.755 + case 0x093000: // Hook relay 2 3.756 + case 0x09B000: 3.757 + break; 3.758 + case 0x094000: // Line 1 hold 3.759 + case 0x09C000: 3.760 + break; 3.761 + case 0x095000: // Line 2 hold 3.762 + case 0x09D000: 3.763 + break; 3.764 + case 0x096000: // Line 1 A-lead 3.765 + case 0x09E000: 3.766 + break; 3.767 + case 0x097000: // Line 2 A-lead 3.768 + case 0x09F000: 3.769 + break; 3.770 + } 3.771 + break; 3.772 + case 0x0A0000: // Miscellaneous Control Register 3.773 + break; 3.774 + case 0x0B0000: // TM/DIALWR 3.775 + break; 3.776 + case 0x0C0000: // CSR 3.777 + break; 3.778 + case 0x0D0000: // DMA Address Register 3.779 + break; 3.780 + case 0x0E0000: // Disk Control Register 3.781 + break; 3.782 + case 0x0F0000: // Line Printer Data Register 3.783 + break; 3.784 + } 3.785 + } else if ((address >= 0xC00000) && (address <= 0xFFFFFF)) { 3.786 + // I/O register space, zone B 3.787 + switch (address & 0xF00000) { 3.788 + case 0xC00000: // Expansion slots 3.789 + case 0xD00000: 3.790 + switch (address & 0xFC0000) { 3.791 + case 0xC00000: // Expansion slot 0 3.792 + case 0xC40000: // Expansion slot 1 3.793 + case 0xC80000: // Expansion slot 2 3.794 + case 0xCC0000: // Expansion slot 3 3.795 + case 0xD00000: // Expansion slot 4 3.796 + case 0xD40000: // Expansion slot 5 3.797 + case 0xD80000: // Expansion slot 6 3.798 + case 0xDC0000: // Expansion slot 7 3.799 + fprintf(stderr, "NOTE: WR32 to expansion card space, addr=0x%08X, data=0x%08X\n", address, value); 3.800 + handled = true; 3.801 + break; 3.802 + } 3.803 + break; 3.804 + case 0xE00000: // HDC, FDC, MCR2 and RTC data bits 3.805 + case 0xF00000: 3.806 + switch (address & 0x070000) { 3.807 + case 0x000000: // [ef][08]xxxx ==> WD1010 hard disc controller 3.808 + break; 3.809 + case 0x010000: // [ef][19]xxxx ==> WD2797 floppy disc controller 3.810 + break; 3.811 + case 0x020000: // [ef][2a]xxxx ==> Miscellaneous Control Register 2 3.812 + break; 3.813 + case 0x030000: // [ef][3b]xxxx ==> Real Time Clock data bits 3.814 + break; 3.815 + case 0x040000: // [ef][4c]xxxx ==> General Control Register 3.816 + switch (address & 0x077000) { 3.817 + case 0x040000: // [ef][4c][08]xxx ==> EE 3.818 + break; 3.819 + case 0x041000: // [ef][4c][19]xxx ==> P1E 3.820 + break; 3.821 + case 0x042000: // [ef][4c][2A]xxx ==> BP 3.822 + break; 3.823 + case 0x043000: // [ef][4c][3B]xxx ==> ROMLMAP 3.824 + state.romlmap = ((value & 0x8000) == 0x8000); 3.825 + break; 3.826 + case 0x044000: // [ef][4c][4C]xxx ==> L1 MODEM 3.827 + break; 3.828 + case 0x045000: // [ef][4c][5D]xxx ==> L2 MODEM 3.829 + break; 3.830 + case 0x046000: // [ef][4c][6E]xxx ==> D/N CONNECT 3.831 + break; 3.832 + case 0x047000: // [ef][4c][7F]xxx ==> Whole screen reverse video 3.833 + break; 3.834 + } 3.835 + case 0x050000: // [ef][5d]xxxx ==> 8274 3.836 + break; 3.837 + case 0x060000: // [ef][6e]xxxx ==> Control regs 3.838 + switch (address & 0x07F000) { 3.839 + default: 3.840 + break; 3.841 + } 3.842 + break; 3.843 + case 0x070000: // [ef][7f]xxxx ==> 6850 Keyboard Controller 3.844 + break; 3.845 + } 3.846 + } 3.847 + } 3.848 + 3.849 + LOG_NOT_HANDLED_W(32); 3.850 +} 3.851 + 3.852 +/** 3.853 + * @brief Write M68K memory, 16-bit 3.854 + */ 3.855 +void m68k_write_memory_16(uint32_t address, uint32_t value) 3.856 +{ 3.857 + bool handled = false; 3.858 + 3.859 + // If ROMLMAP is set, force system to access ROM 3.860 + if (!state.romlmap) 3.861 + address |= 0x800000; 3.862 + 3.863 + // Check access permissions 3.864 + ACCESS_CHECK_WR(address, 16); 3.865 + 3.866 + if ((address >= 0x800000) && (address <= 0xBFFFFF)) { 3.867 + // ROM access 3.868 + handled = true; 3.869 + } else if (address <= (state.ram_size - 1)) { 3.870 + // RAM access 3.871 + WR16(state.ram, mapAddr(address, false), state.ram_size - 1, value); 3.872 + handled = true; 3.873 + } else if ((address >= 0x400000) && (address <= 0x7FFFFF)) { 3.874 + // I/O register space, zone A 3.875 + switch (address & 0x0F0000) { 3.876 + case 0x000000: // Map RAM access 3.877 + if (address > 0x4007FF) fprintf(stderr, "NOTE: WR16 to MapRAM mirror, addr=0x%08X, data=0x%04X\n", address, value); 3.878 + WR16(state.map, address, 0x7FF, value); 3.879 + handled = true; 3.880 + break; 3.881 + case 0x010000: // General Status Register (read only) 3.882 + handled = true; 3.883 + break; 3.884 + case 0x020000: // Video RAM 3.885 + if (address > 0x427FFF) fprintf(stderr, "NOTE: WR16 to VideoRAM mirror, addr=0x%08X, data=0x%04X\n", address, value); 3.886 + WR16(state.vram, address, 0x7FFF, value); 3.887 + handled = true; 3.888 + break; 3.889 + case 0x030000: // Bus Status Register 0 (read only) 3.890 + handled = true; 3.891 + break; 3.892 + case 0x040000: // Bus Status Register 1 (read only) 3.893 + handled = true; 3.894 + break; 3.895 + case 0x050000: // Phone status 3.896 + break; 3.897 + case 0x060000: // DMA Count 3.898 + break; 3.899 + case 0x070000: // Line Printer Status Register 3.900 + break; 3.901 + case 0x080000: // Real Time Clock 3.902 + break; 3.903 + case 0x090000: // Phone registers 3.904 + switch (address & 0x0FF000) { 3.905 + case 0x090000: // Handset relay 3.906 + case 0x098000: 3.907 + break; 3.908 + case 0x091000: // Line select 2 3.909 + case 0x099000: 3.910 + break; 3.911 + case 0x092000: // Hook relay 1 3.912 + case 0x09A000: 3.913 + break; 3.914 + case 0x093000: // Hook relay 2 3.915 + case 0x09B000: 3.916 + break; 3.917 + case 0x094000: // Line 1 hold 3.918 + case 0x09C000: 3.919 + break; 3.920 + case 0x095000: // Line 2 hold 3.921 + case 0x09D000: 3.922 + break; 3.923 + case 0x096000: // Line 1 A-lead 3.924 + case 0x09E000: 3.925 + break; 3.926 + case 0x097000: // Line 2 A-lead 3.927 + case 0x09F000: 3.928 + break; 3.929 + } 3.930 + break; 3.931 + case 0x0A0000: // Miscellaneous Control Register 3.932 + break; 3.933 + case 0x0B0000: // TM/DIALWR 3.934 + break; 3.935 + case 0x0C0000: // CSR 3.936 + break; 3.937 + case 0x0D0000: // DMA Address Register 3.938 + break; 3.939 + case 0x0E0000: // Disk Control Register 3.940 + break; 3.941 + case 0x0F0000: // Line Printer Data Register 3.942 + break; 3.943 + } 3.944 + } else if ((address >= 0xC00000) && (address <= 0xFFFFFF)) { 3.945 + // I/O register space, zone B 3.946 + switch (address & 0xF00000) { 3.947 + case 0xC00000: // Expansion slots 3.948 + case 0xD00000: 3.949 + switch (address & 0xFC0000) { 3.950 + case 0xC00000: // Expansion slot 0 3.951 + case 0xC40000: // Expansion slot 1 3.952 + case 0xC80000: // Expansion slot 2 3.953 + case 0xCC0000: // Expansion slot 3 3.954 + case 0xD00000: // Expansion slot 4 3.955 + case 0xD40000: // Expansion slot 5 3.956 + case 0xD80000: // Expansion slot 6 3.957 + case 0xDC0000: // Expansion slot 7 3.958 + fprintf(stderr, "NOTE: WR16 to expansion card space, addr=0x%08X, data=0x%04X\n", address, value); 3.959 + break; 3.960 + } 3.961 + break; 3.962 + case 0xE00000: // HDC, FDC, MCR2 and RTC data bits 3.963 + case 0xF00000: 3.964 + switch (address & 0x070000) { 3.965 + case 0x000000: // [ef][08]xxxx ==> WD1010 hard disc controller 3.966 + break; 3.967 + case 0x010000: // [ef][19]xxxx ==> WD2797 floppy disc controller 3.968 + break; 3.969 + case 0x020000: // [ef][2a]xxxx ==> Miscellaneous Control Register 2 3.970 + break; 3.971 + case 0x030000: // [ef][3b]xxxx ==> Real Time Clock data bits 3.972 + break; 3.973 + case 0x040000: // [ef][4c]xxxx ==> General Control Register 3.974 + switch (address & 0x077000) { 3.975 + case 0x040000: // [ef][4c][08]xxx ==> EE 3.976 + break; 3.977 + case 0x041000: // [ef][4c][19]xxx ==> P1E 3.978 + break; 3.979 + case 0x042000: // [ef][4c][2A]xxx ==> BP 3.980 + break; 3.981 + case 0x043000: // [ef][4c][3B]xxx ==> ROMLMAP 3.982 + state.romlmap = ((value & 0x8000) == 0x8000); 3.983 + handled = true; 3.984 + break; 3.985 + case 0x044000: // [ef][4c][4C]xxx ==> L1 MODEM 3.986 + break; 3.987 + case 0x045000: // [ef][4c][5D]xxx ==> L2 MODEM 3.988 + break; 3.989 + case 0x046000: // [ef][4c][6E]xxx ==> D/N CONNECT 3.990 + break; 3.991 + case 0x047000: // [ef][4c][7F]xxx ==> Whole screen reverse video 3.992 + break; 3.993 + } 3.994 + case 0x050000: // [ef][5d]xxxx ==> 8274 3.995 + break; 3.996 + case 0x060000: // [ef][6e]xxxx ==> Control regs 3.997 + switch (address & 0x07F000) { 3.998 + default: 3.999 + break; 3.1000 + } 3.1001 + break; 3.1002 + case 0x070000: // [ef][7f]xxxx ==> 6850 Keyboard Controller 3.1003 + break; 3.1004 + } 3.1005 + } 3.1006 + } 3.1007 + 3.1008 + LOG_NOT_HANDLED_W(16); 3.1009 +} 3.1010 + 3.1011 +/** 3.1012 + * @brief Write M68K memory, 8-bit 3.1013 + */ 3.1014 +void m68k_write_memory_8(uint32_t address, uint32_t value) 3.1015 +{ 3.1016 + bool handled = false; 3.1017 + 3.1018 + // If ROMLMAP is set, force system to access ROM 3.1019 + if (!state.romlmap) 3.1020 + address |= 0x800000; 3.1021 + 3.1022 + // Check access permissions 3.1023 + ACCESS_CHECK_WR(address, 8); 3.1024 + 3.1025 + if ((address >= 0x800000) && (address <= 0xBFFFFF)) { 3.1026 + // ROM access (read only!) 3.1027 + handled = true; 3.1028 + } else if (address <= (state.ram_size - 1)) { 3.1029 + // RAM access 3.1030 + WR8(state.ram, mapAddr(address, false), state.ram_size - 1, value); 3.1031 + handled = true; 3.1032 + } else if ((address >= 0x400000) && (address <= 0x7FFFFF)) { 3.1033 + // I/O register space, zone A 3.1034 + switch (address & 0x0F0000) { 3.1035 + case 0x000000: // Map RAM access 3.1036 + if (address > 0x4007FF) fprintf(stderr, "NOTE: WR8 to MapRAM mirror, addr=%08X, data=%02X\n", address, value); 3.1037 + WR8(state.map, address, 0x7FF, value); 3.1038 + handled = true; 3.1039 + break; 3.1040 + case 0x010000: // General Status Register 3.1041 + handled = true; 3.1042 + break; 3.1043 + case 0x020000: // Video RAM 3.1044 + if (address > 0x427FFF) fprintf(stderr, "NOTE: WR8 to VideoRAM mirror, addr=%08X\n, data=0x%02X", address, value); 3.1045 + WR8(state.vram, address, 0x7FFF, value); 3.1046 + handled = true; 3.1047 + break; 3.1048 + case 0x030000: // Bus Status Register 0 3.1049 + handled = true; 3.1050 + break; 3.1051 + case 0x040000: // Bus Status Register 1 3.1052 + handled = true; 3.1053 + break; 3.1054 + case 0x050000: // Phone status 3.1055 + break; 3.1056 + case 0x060000: // DMA Count 3.1057 + break; 3.1058 + case 0x070000: // Line Printer Status Register 3.1059 + break; 3.1060 + case 0x080000: // Real Time Clock 3.1061 + break; 3.1062 + case 0x090000: // Phone registers 3.1063 + switch (address & 0x0FF000) { 3.1064 + case 0x090000: // Handset relay 3.1065 + case 0x098000: 3.1066 + break; 3.1067 + case 0x091000: // Line select 2 3.1068 + case 0x099000: 3.1069 + break; 3.1070 + case 0x092000: // Hook relay 1 3.1071 + case 0x09A000: 3.1072 + break; 3.1073 + case 0x093000: // Hook relay 2 3.1074 + case 0x09B000: 3.1075 + break; 3.1076 + case 0x094000: // Line 1 hold 3.1077 + case 0x09C000: 3.1078 + break; 3.1079 + case 0x095000: // Line 2 hold 3.1080 + case 0x09D000: 3.1081 + break; 3.1082 + case 0x096000: // Line 1 A-lead 3.1083 + case 0x09E000: 3.1084 + break; 3.1085 + case 0x097000: // Line 2 A-lead 3.1086 + case 0x09F000: 3.1087 + break; 3.1088 + } 3.1089 + break; 3.1090 + case 0x0A0000: // Miscellaneous Control Register 3.1091 + break; 3.1092 + case 0x0B0000: // TM/DIALWR 3.1093 + break; 3.1094 + case 0x0C0000: // CSR 3.1095 + break; 3.1096 + case 0x0D0000: // DMA Address Register 3.1097 + break; 3.1098 + case 0x0E0000: // Disk Control Register 3.1099 + break; 3.1100 + case 0x0F0000: // Line Printer Data Register 3.1101 + break; 3.1102 + } 3.1103 + } else if ((address >= 0xC00000) && (address <= 0xFFFFFF)) { 3.1104 + // I/O register space, zone B 3.1105 + switch (address & 0xF00000) { 3.1106 + case 0xC00000: // Expansion slots 3.1107 + case 0xD00000: 3.1108 + switch (address & 0xFC0000) { 3.1109 + case 0xC00000: // Expansion slot 0 3.1110 + case 0xC40000: // Expansion slot 1 3.1111 + case 0xC80000: // Expansion slot 2 3.1112 + case 0xCC0000: // Expansion slot 3 3.1113 + case 0xD00000: // Expansion slot 4 3.1114 + case 0xD40000: // Expansion slot 5 3.1115 + case 0xD80000: // Expansion slot 6 3.1116 + case 0xDC0000: // Expansion slot 7 3.1117 + fprintf(stderr, "NOTE: WR8 to expansion card space, addr=0x%08X, data=0x%08X\n", address, value); 3.1118 + break; 3.1119 + } 3.1120 + break; 3.1121 + case 0xE00000: // HDC, FDC, MCR2 and RTC data bits 3.1122 + case 0xF00000: 3.1123 + switch (address & 0x070000) { 3.1124 + case 0x000000: // [ef][08]xxxx ==> WD1010 hard disc controller 3.1125 + break; 3.1126 + case 0x010000: // [ef][19]xxxx ==> WD2797 floppy disc controller 3.1127 + break; 3.1128 + case 0x020000: // [ef][2a]xxxx ==> Miscellaneous Control Register 2 3.1129 + break; 3.1130 + case 0x030000: // [ef][3b]xxxx ==> Real Time Clock data bits 3.1131 + break; 3.1132 + case 0x040000: // [ef][4c]xxxx ==> General Control Register 3.1133 + switch (address & 0x077000) { 3.1134 + case 0x040000: // [ef][4c][08]xxx ==> EE 3.1135 + break; 3.1136 + case 0x041000: // [ef][4c][19]xxx ==> P1E 3.1137 + break; 3.1138 + case 0x042000: // [ef][4c][2A]xxx ==> BP 3.1139 + break; 3.1140 + case 0x043000: // [ef][4c][3B]xxx ==> ROMLMAP 3.1141 + if ((address & 1) == 0) 3.1142 + state.romlmap = ((value & 0x80) == 0x80); 3.1143 + handled = true; 3.1144 + break; 3.1145 + case 0x044000: // [ef][4c][4C]xxx ==> L1 MODEM 3.1146 + break; 3.1147 + case 0x045000: // [ef][4c][5D]xxx ==> L2 MODEM 3.1148 + break; 3.1149 + case 0x046000: // [ef][4c][6E]xxx ==> D/N CONNECT 3.1150 + break; 3.1151 + case 0x047000: // [ef][4c][7F]xxx ==> Whole screen reverse video 3.1152 + break; 3.1153 + } 3.1154 + case 0x050000: // [ef][5d]xxxx ==> 8274 3.1155 + break; 3.1156 + case 0x060000: // [ef][6e]xxxx ==> Control regs 3.1157 + switch (address & 0x07F000) { 3.1158 + default: 3.1159 + break; 3.1160 + } 3.1161 + break; 3.1162 + case 0x070000: // [ef][7f]xxxx ==> 6850 Keyboard Controller 3.1163 + break; 3.1164 + default: 3.1165 + fprintf(stderr, "NOTE: WR8 to undefined E/F-block space, addr=0x%08X, data=0x%08X\n", address, value); 3.1166 + break; 3.1167 + } 3.1168 + } 3.1169 + } 3.1170 + 3.1171 + LOG_NOT_HANDLED_W(8); 3.1172 +} 3.1173 + 3.1174 + 3.1175 +// for the disassembler 3.1176 +uint32_t m68k_read_disassembler_32(uint32_t addr) { return m68k_read_memory_32(addr); } 3.1177 +uint32_t m68k_read_disassembler_16(uint32_t addr) { return m68k_read_memory_16(addr); } 3.1178 +uint32_t m68k_read_disassembler_8 (uint32_t addr) { return m68k_read_memory_8 (addr); } 3.1179 + 3.1180 +
4.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 4.2 +++ b/src/memory.h Thu Dec 02 23:03:13 2010 +0000 4.3 @@ -0,0 +1,72 @@ 4.4 +#ifndef _MEMORY_H 4.5 +#define _MEMORY_H 4.6 + 4.7 +/*********************************** 4.8 + * Array read/write utility macros 4.9 + * "Don't Repeat Yourself" :) 4.10 + ***********************************/ 4.11 + 4.12 +/// Array read, 32-bit 4.13 +#define RD32(array, address, andmask) \ 4.14 + (((uint32_t)array[(address + 0) & (andmask)] << 24) | \ 4.15 + ((uint32_t)array[(address + 1) & (andmask)] << 16) | \ 4.16 + ((uint32_t)array[(address + 2) & (andmask)] << 8) | \ 4.17 + ((uint32_t)array[(address + 3) & (andmask)])) 4.18 + 4.19 +/// Array read, 16-bit 4.20 +#define RD16(array, address, andmask) \ 4.21 + (((uint32_t)array[(address + 0) & (andmask)] << 8) | \ 4.22 + ((uint32_t)array[(address + 1) & (andmask)])) 4.23 + 4.24 +/// Array read, 8-bit 4.25 +#define RD8(array, address, andmask) \ 4.26 + ((uint32_t)array[(address + 0) & (andmask)]) 4.27 + 4.28 +/// Array write, 32-bit 4.29 +#define WR32(array, address, andmask, value) { \ 4.30 + array[(address + 0) & (andmask)] = (value >> 24) & 0xff; \ 4.31 + array[(address + 1) & (andmask)] = (value >> 16) & 0xff; \ 4.32 + array[(address + 2) & (andmask)] = (value >> 8) & 0xff; \ 4.33 + array[(address + 3) & (andmask)] = value & 0xff; \ 4.34 +} 4.35 + 4.36 +/// Array write, 16-bit 4.37 +#define WR16(array, address, andmask, value) { \ 4.38 + array[(address + 0) & (andmask)] = (value >> 8) & 0xff; \ 4.39 + array[(address + 1) & (andmask)] = value & 0xff; \ 4.40 +} 4.41 + 4.42 +/// Array write, 8-bit 4.43 +#define WR8(array, address, andmask, value) \ 4.44 + array[(address + 0) & (andmask)] = value & 0xff; 4.45 + 4.46 +/****************** 4.47 + * Memory mapping 4.48 + ******************/ 4.49 + 4.50 +typedef enum { 4.51 + MEM_ALLOWED = 0, 4.52 + MEM_PAGEFAULT, // Page fault -- page not present 4.53 + MEM_PAGE_NO_WE, // Page not write enabled 4.54 + MEM_KERNEL, // User attempted to access kernel memory 4.55 + MEM_UIE // User Nonmemory Location Access 4.56 +} MEM_STATUS; 4.57 + 4.58 +/** 4.59 + * @brief Check memory access permissions for a given address. 4.60 + * @param addr Address. 4.61 + * @param writing true if writing to memory, false if reading. 4.62 + * @return One of the MEM_STATUS constants, specifying whether the access is 4.63 + * permitted, or what error occurred. 4.64 + */ 4.65 +MEM_STATUS checkMemoryAccess(uint32_t addr, bool writing); 4.66 + 4.67 +/** 4.68 + * @brief Map a CPU memory address into physical memory space. 4.69 + * @param addr Address. 4.70 + * @param writing true if writing to memory, false if reading. 4.71 + * @return Address, remapped into physical memory. 4.72 + */ 4.73 +uint32_t mapAddr(uint32_t addr, bool writing); 4.74 + 4.75 +#endif