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