Tue, 28 Dec 2010 16:59:40 +0000
partial rewrite of memory / I/O handling code to reduce repetition
src/memory.c | file | annotate | diff | revisions |
1.1 --- a/src/memory.c Wed Dec 15 01:20:57 2010 +0000 1.2 +++ b/src/memory.c Tue Dec 28 16:59:40 2010 +0000 1.3 @@ -2,6 +2,7 @@ 1.4 #include <stdlib.h> 1.5 #include <stdint.h> 1.6 #include <stdbool.h> 1.7 +#include <assert.h> 1.8 #include "musashi/m68k.h" 1.9 #include "state.h" 1.10 #include "memory.h" 1.11 @@ -12,7 +13,7 @@ 1.12 1.13 #define MAPRAM(addr) (((uint16_t)state.map[addr*2] << 8) + ((uint16_t)state.map[(addr*2)+1])) 1.14 1.15 -uint32_t mapAddr(uint32_t addr, bool writing) 1.16 +uint32_t mapAddr(uint32_t addr, bool writing)/*{{{*/ 1.17 { 1.18 if (addr < 0x400000) { 1.19 // RAM access. Check against the Map RAM 1.20 @@ -38,9 +39,9 @@ 1.21 // TODO: assert here? 1.22 return addr; 1.23 } 1.24 -} 1.25 +}/*}}}*/ 1.26 1.27 -MEM_STATUS checkMemoryAccess(uint32_t addr, bool writing) 1.28 +MEM_STATUS checkMemoryAccess(uint32_t addr, bool writing)/*{{{*/ 1.29 { 1.30 // Are we in Supervisor mode? 1.31 if (m68k_get_reg(NULL, M68K_REG_SR) & 0x2000) 1.32 @@ -71,7 +72,7 @@ 1.33 1.34 // Page access allowed. 1.35 return MEM_ALLOWED; 1.36 -} 1.37 +}/*}}}*/ 1.38 1.39 #undef MAPRAM 1.40 1.41 @@ -89,7 +90,9 @@ 1.42 * in a non-void function, even if it's impossible to ever reach the 1.43 * return-with-no-value. UGH! 1.44 */ 1.45 -#define ACCESS_CHECK_WR(address, bits) do { \ 1.46 +/*{{{ macro: ACCESS_CHECK_WR(address, bits)*/ 1.47 +#define ACCESS_CHECK_WR(address, bits) \ 1.48 + do { \ 1.49 bool fault = false; \ 1.50 /* MEM_STATUS st; */ \ 1.51 switch (checkMemoryAccess(address, true)) { \ 1.52 @@ -126,6 +129,7 @@ 1.53 return; \ 1.54 } \ 1.55 } while (false) 1.56 +/*}}}*/ 1.57 1.58 /** 1.59 * @brief Check memory access permissions for a read operation. 1.60 @@ -136,7 +140,9 @@ 1.61 * in a non-void function, even if it's impossible to ever reach the 1.62 * return-with-no-value. UGH! 1.63 */ 1.64 -#define ACCESS_CHECK_RD(address, bits) do { \ 1.65 +/*{{{ macro: ACCESS_CHECK_RD(address, bits)*/ 1.66 +#define ACCESS_CHECK_RD(address, bits) \ 1.67 + do { \ 1.68 bool fault = false; \ 1.69 /* MEM_STATUS st; */ \ 1.70 switch (checkMemoryAccess(address, false)) { \ 1.71 @@ -173,81 +179,256 @@ 1.72 return 0xFFFFFFFF; \ 1.73 } \ 1.74 } while (false) 1.75 +/*}}}*/ 1.76 1.77 // Logging macros 1.78 -#define LOG_NOT_HANDLED_R(bits) \ 1.79 - do { \ 1.80 - if (!handled) \ 1.81 - printf("unhandled read%02d, addr=0x%08X\n", bits, address); \ 1.82 - } while (0); 1.83 +#define LOG_NOT_HANDLED_R(bits) \ 1.84 + printf("unhandled read%02d, addr=0x%08X\n", bits, address); 1.85 1.86 -#define LOG_NOT_HANDLED_W(bits) \ 1.87 - do { \ 1.88 - if (!handled) \ 1.89 - printf("unhandled write%02d, addr=0x%08X, data=0x%08X\n", bits, address, value); \ 1.90 - } while (0); 1.91 +#define LOG_NOT_HANDLED_W(bits) \ 1.92 + printf("unhandled write%02d, addr=0x%08X, data=0x%08X\n", bits, address, value); 1.93 + 1.94 +/******************************************************** 1.95 + * I/O read/write functions 1.96 + ********************************************************/ 1.97 1.98 /** 1.99 - * @brief Read M68K memory, 32-bit 1.100 + * Issue a warning if a read operation is made with an invalid size 1.101 */ 1.102 -uint32_t m68k_read_memory_32(uint32_t address) 1.103 +inline static void ENFORCE_SIZE(int bits, uint32_t address, int allowed, char *regname) 1.104 { 1.105 - uint32_t data = 0xFFFFFFFF; 1.106 + assert((bits == 8) || (bits == 16) || (bits == 32)); 1.107 + if ((bits & allowed) == 0) { 1.108 + printf("WARNING: write to 0x%08X (%s) with invalid size %d!\n", address, regname, bits); 1.109 + } 1.110 +} 1.111 + 1.112 +void IoWrite(uint32_t address, uint32_t data, int bits)/*{{{*/ 1.113 +{ 1.114 bool handled = false; 1.115 1.116 - // If ROMLMAP is set, force system to access ROM 1.117 - if (!state.romlmap) 1.118 - address |= 0x800000; 1.119 - 1.120 - // Check access permissions 1.121 - ACCESS_CHECK_RD(address, 32); 1.122 - 1.123 - if ((address >= 0x800000) && (address <= 0xBFFFFF)) { 1.124 - // ROM access 1.125 - data = RD32(state.rom, address, ROM_SIZE - 1); 1.126 - handled = true; 1.127 - } else if (address <= (state.ram_size - 1)) { 1.128 - // RAM access 1.129 - data = RD32(state.ram, mapAddr(address, false), state.ram_size - 1); 1.130 - handled = true; 1.131 - } else if ((address >= 0x400000) && (address <= 0x7FFFFF)) { 1.132 + if ((address >= 0x400000) && (address <= 0x7FFFFF)) { 1.133 // I/O register space, zone A 1.134 switch (address & 0x0F0000) { 1.135 - case 0x000000: // Map RAM access 1.136 - if (address > 0x4007FF) fprintf(stderr, "NOTE: RD32 from MapRAM mirror, addr=0x%08X\n", address); 1.137 - data = RD32(state.map, address, 0x7FF); 1.138 - handled = true; 1.139 - break; 1.140 case 0x010000: // General Status Register 1.141 - data = ((uint32_t)state.genstat << 16) + (uint32_t)state.genstat; 1.142 - handled = true; 1.143 - break; 1.144 - case 0x020000: // Video RAM 1.145 - if (address > 0x427FFF) fprintf(stderr, "NOTE: RD32 from VideoRAM mirror, addr=0x%08X\n", address); 1.146 - data = RD32(state.vram, address, 0x7FFF); 1.147 + if (bits == 16) 1.148 + state.genstat = (data & 0xffff); 1.149 + else if (bits == 8) { 1.150 + if (address & 0) 1.151 + state.genstat = data; 1.152 + else 1.153 + state.genstat = data << 8; 1.154 + } 1.155 handled = true; 1.156 break; 1.157 case 0x030000: // Bus Status Register 0 1.158 - data = ((uint32_t)state.bsr0 << 16) + (uint32_t)state.bsr0; 1.159 - handled = true; 1.160 break; 1.161 case 0x040000: // Bus Status Register 1 1.162 - data = ((uint32_t)state.bsr1 << 16) + (uint32_t)state.bsr1; 1.163 - handled = true; 1.164 break; 1.165 case 0x050000: // Phone status 1.166 break; 1.167 case 0x060000: // DMA Count 1.168 + ENFORCE_SIZE(bits, address, 16, "DMACOUNT"); 1.169 + state.dma_count = (data & 0x3FFF); 1.170 + state.idmarw = ((data & 0x4000) == 0x4000); 1.171 + state.dmaen = ((data & 0x8000) == 0x8000); 1.172 + // This handles the "dummy DMA transfer" mentioned in the docs 1.173 + // TODO: access check, peripheral access 1.174 + if (!state.idmarw) 1.175 + WR32(state.ram, mapAddr(address, false), state.ram_size - 1, 0xDEAD); 1.176 + state.dma_count++; 1.177 + handled = true; 1.178 + break; 1.179 + case 0x070000: // Line Printer Status Register 1.180 + break; 1.181 + case 0x080000: // Real Time Clock 1.182 + break; 1.183 + case 0x090000: // Phone registers 1.184 + switch (address & 0x0FF000) { 1.185 + case 0x090000: // Handset relay 1.186 + case 0x098000: 1.187 + break; 1.188 + case 0x091000: // Line select 2 1.189 + case 0x099000: 1.190 + break; 1.191 + case 0x092000: // Hook relay 1 1.192 + case 0x09A000: 1.193 + break; 1.194 + case 0x093000: // Hook relay 2 1.195 + case 0x09B000: 1.196 + break; 1.197 + case 0x094000: // Line 1 hold 1.198 + case 0x09C000: 1.199 + break; 1.200 + case 0x095000: // Line 2 hold 1.201 + case 0x09D000: 1.202 + break; 1.203 + case 0x096000: // Line 1 A-lead 1.204 + case 0x09E000: 1.205 + break; 1.206 + case 0x097000: // Line 2 A-lead 1.207 + case 0x09F000: 1.208 + break; 1.209 + } 1.210 + break; 1.211 + case 0x0A0000: // Miscellaneous Control Register 1.212 + ENFORCE_SIZE(bits, address, 16, "MISCCON"); 1.213 + // TODO: handle the ctrl bits properly 1.214 + // TODO: &0x8000 --> dismiss 60hz intr 1.215 + state.dma_reading = (data & 0x4000); 1.216 + state.leds = (~data & 0xF00) >> 8; 1.217 + printf("LEDs: %s %s %s %s\n", 1.218 + (state.leds & 8) ? "R" : "-", 1.219 + (state.leds & 4) ? "G" : "-", 1.220 + (state.leds & 2) ? "Y" : "-", 1.221 + (state.leds & 1) ? "R" : "-"); 1.222 + handled = true; 1.223 + break; 1.224 + case 0x0B0000: // TM/DIALWR 1.225 + break; 1.226 + case 0x0C0000: // Clear Status Register 1.227 + state.genstat = 0xFFFF; 1.228 + state.bsr0 = 0xFFFF; 1.229 + state.bsr1 = 0xFFFF; 1.230 + handled = true; 1.231 + break; 1.232 + case 0x0D0000: // DMA Address Register 1.233 + if (address & 0x004000) { 1.234 + // A14 high -- set most significant bits 1.235 + state.dma_address = (state.dma_address & 0x1fe) | ((address & 0x3ffe) << 8); 1.236 + } else { 1.237 + // A14 low -- set least significant bits 1.238 + state.dma_address = (state.dma_address & 0x3ffe00) | (address & 0x1fe); 1.239 + } 1.240 + handled = true; 1.241 + break; 1.242 + case 0x0E0000: // Disk Control Register 1.243 + ENFORCE_SIZE(bits, address, 16, "DISKCON"); 1.244 + // B7 = FDD controller reset 1.245 + if ((data & 0x80) == 0) wd2797_reset(&state.fdc_ctx); 1.246 + // B6 = drive 0 select -- TODO 1.247 + // B5 = motor enable -- TODO 1.248 + // B4 = HDD controller reset -- TODO 1.249 + // B3 = HDD0 select -- TODO 1.250 + // B2,1,0 = HDD0 head select 1.251 + handled = true; 1.252 + break; 1.253 + case 0x0F0000: // Line Printer Data Register 1.254 + break; 1.255 + } 1.256 + } else if ((address >= 0xC00000) && (address <= 0xFFFFFF)) { 1.257 + // I/O register space, zone B 1.258 + switch (address & 0xF00000) { 1.259 + case 0xC00000: // Expansion slots 1.260 + case 0xD00000: 1.261 + switch (address & 0xFC0000) { 1.262 + case 0xC00000: // Expansion slot 0 1.263 + case 0xC40000: // Expansion slot 1 1.264 + case 0xC80000: // Expansion slot 2 1.265 + case 0xCC0000: // Expansion slot 3 1.266 + case 0xD00000: // Expansion slot 4 1.267 + case 0xD40000: // Expansion slot 5 1.268 + case 0xD80000: // Expansion slot 6 1.269 + case 0xDC0000: // Expansion slot 7 1.270 + fprintf(stderr, "NOTE: WR%d to expansion card space, addr=0x%08X, data=0x%08X\n", bits, address, data); 1.271 + handled = true; 1.272 + break; 1.273 + } 1.274 + break; 1.275 + case 0xE00000: // HDC, FDC, MCR2 and RTC data bits 1.276 + case 0xF00000: 1.277 + switch (address & 0x070000) { 1.278 + case 0x000000: // [ef][08]xxxx ==> WD1010 hard disc controller 1.279 + break; 1.280 + case 0x010000: // [ef][19]xxxx ==> WD2797 floppy disc controller 1.281 + ENFORCE_SIZE(bits, address, 16, "FDC REGISTERS"); 1.282 + wd2797_write_reg(&state.fdc_ctx, (address >> 1) & 3, data); 1.283 + handled = true; 1.284 + break; 1.285 + case 0x020000: // [ef][2a]xxxx ==> Miscellaneous Control Register 2 1.286 + break; 1.287 + case 0x030000: // [ef][3b]xxxx ==> Real Time Clock data bits 1.288 + break; 1.289 + case 0x040000: // [ef][4c]xxxx ==> General Control Register 1.290 + switch (address & 0x077000) { 1.291 + case 0x040000: // [ef][4c][08]xxx ==> EE 1.292 + break; 1.293 + case 0x041000: // [ef][4c][19]xxx ==> PIE 1.294 + ENFORCE_SIZE(bits, address, 16, "PIE"); 1.295 + state.pie = ((data & 0x8000) == 0x8000); 1.296 + handled = true; 1.297 + break; 1.298 + case 0x042000: // [ef][4c][2A]xxx ==> BP 1.299 + break; 1.300 + case 0x043000: // [ef][4c][3B]xxx ==> ROMLMAP 1.301 + ENFORCE_SIZE(bits, address, 16, "ROMLMAP"); 1.302 + state.romlmap = ((data & 0x8000) == 0x8000); 1.303 + handled = true; 1.304 + break; 1.305 + case 0x044000: // [ef][4c][4C]xxx ==> L1 MODEM 1.306 + ENFORCE_SIZE(bits, address, 16, "L1 MODEM"); 1.307 + break; 1.308 + case 0x045000: // [ef][4c][5D]xxx ==> L2 MODEM 1.309 + ENFORCE_SIZE(bits, address, 16, "L2 MODEM"); 1.310 + break; 1.311 + case 0x046000: // [ef][4c][6E]xxx ==> D/N CONNECT 1.312 + ENFORCE_SIZE(bits, address, 16, "D/N CONNECT"); 1.313 + break; 1.314 + case 0x047000: // [ef][4c][7F]xxx ==> Whole screen reverse video 1.315 + ENFORCE_SIZE(bits, address, 16, "WHOLE SCREEN REVERSE VIDEO"); 1.316 + break; 1.317 + } 1.318 + case 0x050000: // [ef][5d]xxxx ==> 8274 1.319 + break; 1.320 + case 0x060000: // [ef][6e]xxxx ==> Control regs 1.321 + switch (address & 0x07F000) { 1.322 + default: 1.323 + break; 1.324 + } 1.325 + break; 1.326 + case 0x070000: // [ef][7f]xxxx ==> 6850 Keyboard Controller 1.327 + break; 1.328 + } 1.329 + } 1.330 + } 1.331 +}/*}}}*/ 1.332 + 1.333 +uint32_t IoRead(uint32_t address, int bits)/*{{{*/ 1.334 +{ 1.335 + bool handled = false; 1.336 + uint32_t data = 0xFFFFFFFF; 1.337 + 1.338 + if ((address >= 0x400000) && (address <= 0x7FFFFF)) { 1.339 + // I/O register space, zone A 1.340 + switch (address & 0x0F0000) { 1.341 + case 0x010000: // General Status Register 1.342 + ENFORCE_SIZE(bits, address, 16, "GENSTAT"); 1.343 + return ((uint32_t)state.genstat << 16) + (uint32_t)state.genstat; 1.344 + break; 1.345 + case 0x030000: // Bus Status Register 0 1.346 + ENFORCE_SIZE(bits, address, 16, "BSR0"); 1.347 + return ((uint32_t)state.bsr0 << 16) + (uint32_t)state.bsr0; 1.348 + break; 1.349 + case 0x040000: // Bus Status Register 1 1.350 + ENFORCE_SIZE(bits, address, 16, "BSR1"); 1.351 + return ((uint32_t)state.bsr1 << 16) + (uint32_t)state.bsr1; 1.352 + break; 1.353 + case 0x050000: // Phone status 1.354 + ENFORCE_SIZE(bits, address, 16, "PHONE STATUS"); 1.355 + break; 1.356 + case 0x060000: // DMA Count 1.357 // TODO: U/OERR- is always inactive (bit set)... or should it be = DMAEN+? 1.358 // Bit 14 is always unused, so leave it set 1.359 - data = (state.dma_count & 0x3fff) | 0xC000; 1.360 - handled = true; 1.361 + ENFORCE_SIZE(bits, address, 16, "DMACOUNT"); 1.362 + return (state.dma_count & 0x3fff) | 0xC000; 1.363 break; 1.364 case 0x070000: // Line Printer Status Register 1.365 data = 0x00120012; // no parity error, no line printer error, no irqs from FDD or HDD 1.366 data |= (state.fdc_ctx.irql) ? 0x00080008 : 0; // FIXME! HACKHACKHACK! shouldn't peek inside FDC structs like this 1.367 + return data; 1.368 break; 1.369 case 0x080000: // Real Time Clock 1.370 + printf("READ NOTIMP: Realtime Clock\n"); 1.371 break; 1.372 case 0x090000: // Phone registers 1.373 switch (address & 0x0FF000) { 1.374 @@ -316,9 +497,8 @@ 1.375 case 0x000000: // [ef][08]xxxx ==> WD1010 hard disc controller 1.376 break; 1.377 case 0x010000: // [ef][19]xxxx ==> WD2797 floppy disc controller 1.378 - data = wd2797_read_reg(&state.fdc_ctx, (address >> 1) & 3); 1.379 - printf("WD279X: rd32 %02X ==> %02X\n", (address >> 1) & 3, data); 1.380 - handled = true; 1.381 + ENFORCE_SIZE(bits, address, 16, "FDC REGISTERS"); 1.382 + return wd2797_read_reg(&state.fdc_ctx, (address >> 1) & 3); 1.383 break; 1.384 case 0x020000: // [ef][2a]xxxx ==> Miscellaneous Control Register 2 1.385 break; 1.386 @@ -353,18 +533,61 @@ 1.387 } 1.388 } 1.389 } 1.390 + return data; 1.391 +}/*}}}*/ 1.392 1.393 - LOG_NOT_HANDLED_R(32); 1.394 + 1.395 +/******************************************************** 1.396 + * m68k memory read/write support functions for Musashi 1.397 + ********************************************************/ 1.398 + 1.399 +/** 1.400 + * @brief Read M68K memory, 32-bit 1.401 + */ 1.402 +uint32_t m68k_read_memory_32(uint32_t address)/*{{{*/ 1.403 +{ 1.404 + uint32_t data = 0xFFFFFFFF; 1.405 + 1.406 + // If ROMLMAP is set, force system to access ROM 1.407 + if (!state.romlmap) 1.408 + address |= 0x800000; 1.409 + 1.410 + // Check access permissions 1.411 + ACCESS_CHECK_RD(address, 32); 1.412 + 1.413 + if ((address >= 0x800000) && (address <= 0xBFFFFF)) { 1.414 + // ROM access 1.415 + data = RD32(state.rom, address, ROM_SIZE - 1); 1.416 + } else if (address <= (state.ram_size - 1)) { 1.417 + // RAM access 1.418 + data = RD32(state.ram, mapAddr(address, false), state.ram_size - 1); 1.419 + } else if ((address >= 0x400000) && (address <= 0x7FFFFF)) { 1.420 + // I/O register space, zone A 1.421 + switch (address & 0x0F0000) { 1.422 + case 0x000000: // Map RAM access 1.423 + if (address > 0x4007FF) fprintf(stderr, "NOTE: RD32 from MapRAM mirror, addr=0x%08X\n", address); 1.424 + data = RD32(state.map, address, 0x7FF); 1.425 + break; 1.426 + case 0x020000: // Video RAM 1.427 + if (address > 0x427FFF) fprintf(stderr, "NOTE: RD32 from VideoRAM mirror, addr=0x%08X\n", address); 1.428 + data = RD32(state.vram, address, 0x7FFF); 1.429 + break; 1.430 + default: 1.431 + data = IoRead(address, 32); 1.432 + } 1.433 + } else { 1.434 + data = IoRead(address, 32); 1.435 + } 1.436 + 1.437 return data; 1.438 -} 1.439 +}/*}}}*/ 1.440 1.441 /** 1.442 * @brief Read M68K memory, 16-bit 1.443 */ 1.444 -uint32_t m68k_read_memory_16(uint32_t address) 1.445 +uint32_t m68k_read_memory_16(uint32_t address)/*{{{*/ 1.446 { 1.447 uint16_t data = 0xFFFF; 1.448 - bool handled = false; 1.449 1.450 // If ROMLMAP is set, force system to access ROM 1.451 if (!state.romlmap) 1.452 @@ -376,166 +599,36 @@ 1.453 if ((address >= 0x800000) && (address <= 0xBFFFFF)) { 1.454 // ROM access 1.455 data = RD16(state.rom, address, ROM_SIZE - 1); 1.456 - handled = true; 1.457 } else if (address <= (state.ram_size - 1)) { 1.458 // RAM access 1.459 data = RD16(state.ram, mapAddr(address, false), state.ram_size - 1); 1.460 - handled = true; 1.461 } else if ((address >= 0x400000) && (address <= 0x7FFFFF)) { 1.462 // I/O register space, zone A 1.463 switch (address & 0x0F0000) { 1.464 case 0x000000: // Map RAM access 1.465 if (address > 0x4007FF) fprintf(stderr, "NOTE: RD16 from MapRAM mirror, addr=0x%08X\n", address); 1.466 data = RD16(state.map, address, 0x7FF); 1.467 - handled = true; 1.468 - break; 1.469 - case 0x010000: // General Status Register 1.470 - data = state.genstat; 1.471 - handled = true; 1.472 break; 1.473 case 0x020000: // Video RAM 1.474 if (address > 0x427FFF) fprintf(stderr, "NOTE: RD16 from VideoRAM mirror, addr=0x%08X\n", address); 1.475 data = RD16(state.vram, address, 0x7FFF); 1.476 - handled = true; 1.477 break; 1.478 - case 0x030000: // Bus Status Register 0 1.479 - data = state.bsr0; 1.480 - handled = true; 1.481 - break; 1.482 - case 0x040000: // Bus Status Register 1 1.483 - data = state.bsr1; 1.484 - handled = true; 1.485 - break; 1.486 - case 0x050000: // Phone status 1.487 - break; 1.488 - case 0x060000: // DMA Count 1.489 - // TODO: U/OERR- is always inactive (bit set)... or should it be = DMAEN+? 1.490 - // Bit 14 is always unused, so leave it set 1.491 - data = (state.dma_count & 0x3fff) | 0xC000; 1.492 - handled = true; 1.493 - break; 1.494 - case 0x070000: // Line Printer Status Register 1.495 - data = 0x0012; // no parity error, no line printer error, no irqs from FDD or HDD 1.496 - data |= (state.fdc_ctx.irql) ? 0x0008 : 0; // FIXME! HACKHACKHACK! shouldn't peek inside FDC structs like this 1.497 - break; 1.498 - case 0x080000: // Real Time Clock 1.499 - break; 1.500 - case 0x090000: // Phone registers 1.501 - switch (address & 0x0FF000) { 1.502 - case 0x090000: // Handset relay 1.503 - case 0x098000: 1.504 - break; 1.505 - case 0x091000: // Line select 2 1.506 - case 0x099000: 1.507 - break; 1.508 - case 0x092000: // Hook relay 1 1.509 - case 0x09A000: 1.510 - break; 1.511 - case 0x093000: // Hook relay 2 1.512 - case 0x09B000: 1.513 - break; 1.514 - case 0x094000: // Line 1 hold 1.515 - case 0x09C000: 1.516 - break; 1.517 - case 0x095000: // Line 2 hold 1.518 - case 0x09D000: 1.519 - break; 1.520 - case 0x096000: // Line 1 A-lead 1.521 - case 0x09E000: 1.522 - break; 1.523 - case 0x097000: // Line 2 A-lead 1.524 - case 0x09F000: 1.525 - break; 1.526 - } 1.527 - break; 1.528 - case 0x0A0000: // Miscellaneous Control Register -- write only! 1.529 - handled = true; 1.530 - break; 1.531 - case 0x0B0000: // TM/DIALWR 1.532 - break; 1.533 - case 0x0C0000: // Clear Status Register -- write only! 1.534 - handled = true; 1.535 - break; 1.536 - case 0x0D0000: // DMA Address Register 1.537 - break; 1.538 - case 0x0E0000: // Disk Control Register 1.539 - break; 1.540 - case 0x0F0000: // Line Printer Data Register 1.541 - break; 1.542 + default: 1.543 + data = IoRead(address, 16); 1.544 } 1.545 - } else if ((address >= 0xC00000) && (address <= 0xFFFFFF)) { 1.546 - // I/O register space, zone B 1.547 - switch (address & 0xF00000) { 1.548 - case 0xC00000: // Expansion slots 1.549 - case 0xD00000: 1.550 - switch (address & 0xFC0000) { 1.551 - case 0xC00000: // Expansion slot 0 1.552 - case 0xC40000: // Expansion slot 1 1.553 - case 0xC80000: // Expansion slot 2 1.554 - case 0xCC0000: // Expansion slot 3 1.555 - case 0xD00000: // Expansion slot 4 1.556 - case 0xD40000: // Expansion slot 5 1.557 - case 0xD80000: // Expansion slot 6 1.558 - case 0xDC0000: // Expansion slot 7 1.559 - fprintf(stderr, "NOTE: RD16 from expansion card space, addr=0x%08X\n", address); 1.560 - break; 1.561 - } 1.562 - break; 1.563 - case 0xE00000: // HDC, FDC, MCR2 and RTC data bits 1.564 - case 0xF00000: 1.565 - switch (address & 0x070000) { 1.566 - case 0x000000: // [ef][08]xxxx ==> WD1010 hard disc controller 1.567 - break; 1.568 - case 0x010000: // [ef][19]xxxx ==> WD2797 floppy disc controller 1.569 - data = wd2797_read_reg(&state.fdc_ctx, (address >> 1) & 3); 1.570 - printf("WD279X: rd16 %02X ==> %02X\n", (address >> 1) & 3, data); 1.571 - handled = true; 1.572 - break; 1.573 - case 0x020000: // [ef][2a]xxxx ==> Miscellaneous Control Register 2 1.574 - break; 1.575 - case 0x030000: // [ef][3b]xxxx ==> Real Time Clock data bits 1.576 - break; 1.577 - case 0x040000: // [ef][4c]xxxx ==> General Control Register 1.578 - switch (address & 0x077000) { 1.579 - case 0x040000: // [ef][4c][08]xxx ==> EE 1.580 - case 0x041000: // [ef][4c][19]xxx ==> PIE 1.581 - case 0x042000: // [ef][4c][2A]xxx ==> BP 1.582 - case 0x043000: // [ef][4c][3B]xxx ==> ROMLMAP 1.583 - case 0x044000: // [ef][4c][4C]xxx ==> L1 MODEM 1.584 - case 0x045000: // [ef][4c][5D]xxx ==> L2 MODEM 1.585 - case 0x046000: // [ef][4c][6E]xxx ==> D/N CONNECT 1.586 - // All write-only registers... TODO: bus error? 1.587 - handled = true; 1.588 - break; 1.589 - case 0x047000: // [ef][4c][7F]xxx ==> Whole screen reverse video 1.590 - break; 1.591 - } 1.592 - break; 1.593 - case 0x050000: // [ef][5d]xxxx ==> 8274 1.594 - break; 1.595 - case 0x060000: // [ef][6e]xxxx ==> Control regs 1.596 - switch (address & 0x07F000) { 1.597 - default: 1.598 - break; 1.599 - } 1.600 - break; 1.601 - case 0x070000: // [ef][7f]xxxx ==> 6850 Keyboard Controller 1.602 - break; 1.603 - } 1.604 - } 1.605 + } else { 1.606 + data = IoRead(address, 16); 1.607 } 1.608 1.609 - LOG_NOT_HANDLED_R(16); 1.610 return data; 1.611 -} 1.612 +}/*}}}*/ 1.613 1.614 /** 1.615 * @brief Read M68K memory, 8-bit 1.616 */ 1.617 -uint32_t m68k_read_memory_8(uint32_t address) 1.618 +uint32_t m68k_read_memory_8(uint32_t address)/*{{{*/ 1.619 { 1.620 uint8_t data = 0xFF; 1.621 - bool handled = false; 1.622 1.623 // If ROMLMAP is set, force system to access ROM 1.624 if (!state.romlmap) 1.625 @@ -547,179 +640,35 @@ 1.626 if ((address >= 0x800000) && (address <= 0xBFFFFF)) { 1.627 // ROM access 1.628 data = RD8(state.rom, address, ROM_SIZE - 1); 1.629 - handled = true; 1.630 } else if (address <= (state.ram_size - 1)) { 1.631 // RAM access 1.632 data = RD8(state.ram, mapAddr(address, false), state.ram_size - 1); 1.633 - handled = true; 1.634 } else if ((address >= 0x400000) && (address <= 0x7FFFFF)) { 1.635 // I/O register space, zone A 1.636 switch (address & 0x0F0000) { 1.637 case 0x000000: // Map RAM access 1.638 if (address > 0x4007FF) fprintf(stderr, "NOTE: RD8 from MapRAM mirror, addr=0x%08X\n", address); 1.639 data = RD8(state.map, address, 0x7FF); 1.640 - handled = true; 1.641 - break; 1.642 - case 0x010000: // General Status Register 1.643 - if ((address & 1) == 0) 1.644 - data = (state.genstat >> 8) & 0xff; 1.645 - else 1.646 - data = (state.genstat) & 0xff; 1.647 - handled = true; 1.648 break; 1.649 case 0x020000: // Video RAM 1.650 if (address > 0x427FFF) fprintf(stderr, "NOTE: RD8 from VideoRAM mirror, addr=0x%08X\n", address); 1.651 data = RD8(state.vram, address, 0x7FFF); 1.652 - handled = true; 1.653 break; 1.654 - case 0x030000: // Bus Status Register 0 1.655 - if ((address & 1) == 0) 1.656 - data = (state.bsr0 >> 8) & 0xff; 1.657 - else 1.658 - data = (state.bsr0) & 0xff; 1.659 - handled = true; 1.660 - break; 1.661 - case 0x040000: // Bus Status Register 1 1.662 - if ((address & 1) == 0) 1.663 - data = (state.bsr1 >> 8) & 0xff; 1.664 - else 1.665 - data = (state.bsr1) & 0xff; 1.666 - handled = true; 1.667 - break; 1.668 - case 0x050000: // Phone status 1.669 - break; 1.670 - case 0x060000: // DMA Count 1.671 - // TODO: how to handle this in 8bit mode? 1.672 - break; 1.673 - case 0x070000: // Line Printer Status Register 1.674 - printf("\tLPSR RD8 fdc irql=%d, irqe=%d\n", state.fdc_ctx.irql, state.fdc_ctx.irqe); 1.675 - if (address & 1) { 1.676 - data = 0x12; // no parity error, no line printer error, no irqs from FDD or HDD 1.677 - data |= (state.fdc_ctx.irql) ? 0x08 : 0; // FIXME! HACKHACKHACK! shouldn't peek inside FDC structs like this 1.678 -// data |= 0x04; // HDD interrupt, i.e. command complete -- HACKHACKHACK! 1.679 - } else { 1.680 - data = 0; 1.681 - } 1.682 - handled = true; 1.683 - break; 1.684 - case 0x080000: // Real Time Clock 1.685 - break; 1.686 - case 0x090000: // Phone registers 1.687 - switch (address & 0x0FF000) { 1.688 - case 0x090000: // Handset relay 1.689 - case 0x098000: 1.690 - break; 1.691 - case 0x091000: // Line select 2 1.692 - case 0x099000: 1.693 - break; 1.694 - case 0x092000: // Hook relay 1 1.695 - case 0x09A000: 1.696 - break; 1.697 - case 0x093000: // Hook relay 2 1.698 - case 0x09B000: 1.699 - break; 1.700 - case 0x094000: // Line 1 hold 1.701 - case 0x09C000: 1.702 - break; 1.703 - case 0x095000: // Line 2 hold 1.704 - case 0x09D000: 1.705 - break; 1.706 - case 0x096000: // Line 1 A-lead 1.707 - case 0x09E000: 1.708 - break; 1.709 - case 0x097000: // Line 2 A-lead 1.710 - case 0x09F000: 1.711 - break; 1.712 - } 1.713 - break; 1.714 - case 0x0A0000: // Miscellaneous Control Register -- write only! 1.715 - handled = true; 1.716 - break; 1.717 - case 0x0B0000: // TM/DIALWR 1.718 - break; 1.719 - case 0x0C0000: // Clear Status Register -- write only! 1.720 - handled = true; 1.721 - break; 1.722 - case 0x0D0000: // DMA Address Register 1.723 - break; 1.724 - case 0x0E0000: // Disk Control Register 1.725 - break; 1.726 - case 0x0F0000: // Line Printer Data Register 1.727 - break; 1.728 + default: 1.729 + data = IoRead(address, 8); 1.730 } 1.731 - } else if ((address >= 0xC00000) && (address <= 0xFFFFFF)) { 1.732 - // I/O register space, zone B 1.733 - switch (address & 0xF00000) { 1.734 - case 0xC00000: // Expansion slots 1.735 - case 0xD00000: 1.736 - switch (address & 0xFC0000) { 1.737 - case 0xC00000: // Expansion slot 0 1.738 - case 0xC40000: // Expansion slot 1 1.739 - case 0xC80000: // Expansion slot 2 1.740 - case 0xCC0000: // Expansion slot 3 1.741 - case 0xD00000: // Expansion slot 4 1.742 - case 0xD40000: // Expansion slot 5 1.743 - case 0xD80000: // Expansion slot 6 1.744 - case 0xDC0000: // Expansion slot 7 1.745 - fprintf(stderr, "NOTE: RD8 from expansion card space, addr=0x%08X\n", address); 1.746 - break; 1.747 - } 1.748 - break; 1.749 - case 0xE00000: // HDC, FDC, MCR2 and RTC data bits 1.750 - case 0xF00000: 1.751 - switch (address & 0x070000) { 1.752 - case 0x000000: // [ef][08]xxxx ==> WD1010 hard disc controller 1.753 - break; 1.754 - case 0x010000: // [ef][19]xxxx ==> WD2797 floppy disc controller 1.755 - data = wd2797_read_reg(&state.fdc_ctx, (address >> 1) & 3); 1.756 - printf("WD279X: rd8 %02X ==> %02X\n", (address >> 1) & 3, data); 1.757 - handled = true; 1.758 - break; 1.759 - case 0x020000: // [ef][2a]xxxx ==> Miscellaneous Control Register 2 1.760 - break; 1.761 - case 0x030000: // [ef][3b]xxxx ==> Real Time Clock data bits 1.762 - break; 1.763 - case 0x040000: // [ef][4c]xxxx ==> General Control Register 1.764 - switch (address & 0x077000) { 1.765 - case 0x040000: // [ef][4c][08]xxx ==> EE 1.766 - case 0x041000: // [ef][4c][19]xxx ==> PIE 1.767 - case 0x042000: // [ef][4c][2A]xxx ==> BP 1.768 - case 0x043000: // [ef][4c][3B]xxx ==> ROMLMAP 1.769 - case 0x044000: // [ef][4c][4C]xxx ==> L1 MODEM 1.770 - case 0x045000: // [ef][4c][5D]xxx ==> L2 MODEM 1.771 - case 0x046000: // [ef][4c][6E]xxx ==> D/N CONNECT 1.772 - // All write-only registers... TODO: bus error? 1.773 - handled = true; 1.774 - break; 1.775 - case 0x047000: // [ef][4c][7F]xxx ==> Whole screen reverse video 1.776 - break; 1.777 - } 1.778 - case 0x050000: // [ef][5d]xxxx ==> 8274 1.779 - break; 1.780 - case 0x060000: // [ef][6e]xxxx ==> Control regs 1.781 - switch (address & 0x07F000) { 1.782 - default: 1.783 - break; 1.784 - } 1.785 - break; 1.786 - case 0x070000: // [ef][7f]xxxx ==> 6850 Keyboard Controller 1.787 - break; 1.788 - } 1.789 - } 1.790 + } else { 1.791 + data = IoRead(address, 8); 1.792 } 1.793 1.794 - LOG_NOT_HANDLED_R(8); 1.795 - 1.796 return data; 1.797 -} 1.798 +}/*}}}*/ 1.799 1.800 /** 1.801 * @brief Write M68K memory, 32-bit 1.802 */ 1.803 -void m68k_write_memory_32(uint32_t address, uint32_t value) 1.804 +void m68k_write_memory_32(uint32_t address, uint32_t value)/*{{{*/ 1.805 { 1.806 - bool handled = false; 1.807 - 1.808 // If ROMLMAP is set, force system to access ROM 1.809 if (!state.romlmap) 1.810 address |= 0x800000; 1.811 @@ -729,203 +678,33 @@ 1.812 1.813 if ((address >= 0x800000) && (address <= 0xBFFFFF)) { 1.814 // ROM access 1.815 - handled = true; 1.816 } else if (address <= (state.ram_size - 1)) { 1.817 // RAM access 1.818 WR32(state.ram, mapAddr(address, false), state.ram_size - 1, value); 1.819 - handled = true; 1.820 } else if ((address >= 0x400000) && (address <= 0x7FFFFF)) { 1.821 // I/O register space, zone A 1.822 switch (address & 0x0F0000) { 1.823 case 0x000000: // Map RAM access 1.824 - if (address > 0x4007FF) fprintf(stderr, "NOTE: WR32 to MapRAM mirror, addr=0x%08X, data=0x%08X\n", address, value); 1.825 + if (address > 0x4007FF) fprintf(stderr, "NOTE: RD32 from MapRAM mirror, addr=0x%08X\n", address); 1.826 WR32(state.map, address, 0x7FF, value); 1.827 - handled = true; 1.828 - break; 1.829 - case 0x010000: // General Status Register 1.830 - state.genstat = (value & 0xffff); 1.831 - handled = true; 1.832 break; 1.833 case 0x020000: // Video RAM 1.834 - if (address > 0x427FFF) fprintf(stderr, "NOTE: WR32 to VideoRAM mirror, addr=0x%08X, data=0x%08X\n", address, value); 1.835 + if (address > 0x427FFF) fprintf(stderr, "NOTE: RD32 from VideoRAM mirror, addr=0x%08X\n", address); 1.836 WR32(state.vram, address, 0x7FFF, value); 1.837 - handled = true; 1.838 - break; 1.839 - case 0x030000: // Bus Status Register 0 1.840 - break; 1.841 - case 0x040000: // Bus Status Register 1 1.842 - break; 1.843 - case 0x050000: // Phone status 1.844 - break; 1.845 - case 0x060000: // DMA Count 1.846 - printf("WR32 dmacount %08X\n", value); 1.847 - state.dma_count = (value & 0x3FFF); 1.848 - state.idmarw = ((value & 0x4000) == 0x4000); 1.849 - state.dmaen = ((value & 0x8000) == 0x8000); 1.850 - printf("\tcount %04X, idmarw %d, dmaen %d\n", state.dma_count, state.idmarw, state.dmaen); 1.851 - // This handles the "dummy DMA transfer" mentioned in the docs 1.852 - // TODO: access check, peripheral access 1.853 - if (!state.idmarw) 1.854 - WR32(state.ram, mapAddr(address, false), state.ram_size - 1, 0xDEAD); 1.855 - state.dma_count++; 1.856 - handled = true; 1.857 - break; 1.858 - case 0x070000: // Line Printer Status Register 1.859 - break; 1.860 - case 0x080000: // Real Time Clock 1.861 - break; 1.862 - case 0x090000: // Phone registers 1.863 - switch (address & 0x0FF000) { 1.864 - case 0x090000: // Handset relay 1.865 - case 0x098000: 1.866 - break; 1.867 - case 0x091000: // Line select 2 1.868 - case 0x099000: 1.869 - break; 1.870 - case 0x092000: // Hook relay 1 1.871 - case 0x09A000: 1.872 - break; 1.873 - case 0x093000: // Hook relay 2 1.874 - case 0x09B000: 1.875 - break; 1.876 - case 0x094000: // Line 1 hold 1.877 - case 0x09C000: 1.878 - break; 1.879 - case 0x095000: // Line 2 hold 1.880 - case 0x09D000: 1.881 - break; 1.882 - case 0x096000: // Line 1 A-lead 1.883 - case 0x09E000: 1.884 - break; 1.885 - case 0x097000: // Line 2 A-lead 1.886 - case 0x09F000: 1.887 - break; 1.888 - } 1.889 - break; 1.890 - case 0x0A0000: // Miscellaneous Control Register 1.891 - // TODO: handle the ctrl bits properly 1.892 - // TODO: &0x8000 --> dismiss 60hz intr 1.893 - state.dma_reading = (value & 0x4000); 1.894 - state.leds = (~value & 0xF00) >> 8; 1.895 - printf("LEDs: %s %s %s %s\n", 1.896 - (state.leds & 8) ? "R" : "-", 1.897 - (state.leds & 4) ? "G" : "-", 1.898 - (state.leds & 2) ? "Y" : "-", 1.899 - (state.leds & 1) ? "R" : "-"); 1.900 - handled = true; 1.901 - break; 1.902 - case 0x0B0000: // TM/DIALWR 1.903 - break; 1.904 - case 0x0C0000: // Clear Status Register 1.905 - state.genstat = 0xFFFF; 1.906 - state.bsr0 = 0xFFFF; 1.907 - state.bsr1 = 0xFFFF; 1.908 - handled = true; 1.909 - break; 1.910 - case 0x0D0000: // DMA Address Register 1.911 - if (address & 0x004000) { 1.912 - // A14 high -- set most significant bits 1.913 - state.dma_address = (state.dma_address & 0x1fe) | ((address & 0x3ffe) << 8); 1.914 - } else { 1.915 - // A14 low -- set least significant bits 1.916 - state.dma_address = (state.dma_address & 0x3ffe00) | (address & 0x1fe); 1.917 - } 1.918 - printf("WR32 DMA_ADDR %s, now %08X\n", address & 0x004000 ? "HI" : "LO", state.dma_address); 1.919 - handled = true; 1.920 break; 1.921 - case 0x0E0000: // Disk Control Register 1.922 - // B7 = FDD controller reset 1.923 - if ((value & 0x80) == 0) wd2797_reset(&state.fdc_ctx); 1.924 - // B6 = drive 0 select -- TODO 1.925 - // B5 = motor enable -- TODO 1.926 - // B4 = HDD controller reset -- TODO 1.927 - // B3 = HDD0 select -- TODO 1.928 - // B2,1,0 = HDD0 head select 1.929 - handled = true; 1.930 - break; 1.931 - case 0x0F0000: // Line Printer Data Register 1.932 - break; 1.933 + default: 1.934 + IoWrite(address, value, 32); 1.935 } 1.936 - } else if ((address >= 0xC00000) && (address <= 0xFFFFFF)) { 1.937 - // I/O register space, zone B 1.938 - switch (address & 0xF00000) { 1.939 - case 0xC00000: // Expansion slots 1.940 - case 0xD00000: 1.941 - switch (address & 0xFC0000) { 1.942 - case 0xC00000: // Expansion slot 0 1.943 - case 0xC40000: // Expansion slot 1 1.944 - case 0xC80000: // Expansion slot 2 1.945 - case 0xCC0000: // Expansion slot 3 1.946 - case 0xD00000: // Expansion slot 4 1.947 - case 0xD40000: // Expansion slot 5 1.948 - case 0xD80000: // Expansion slot 6 1.949 - case 0xDC0000: // Expansion slot 7 1.950 - fprintf(stderr, "NOTE: WR32 to expansion card space, addr=0x%08X, data=0x%08X\n", address, value); 1.951 - handled = true; 1.952 - break; 1.953 - } 1.954 - break; 1.955 - case 0xE00000: // HDC, FDC, MCR2 and RTC data bits 1.956 - case 0xF00000: 1.957 - switch (address & 0x070000) { 1.958 - case 0x000000: // [ef][08]xxxx ==> WD1010 hard disc controller 1.959 - break; 1.960 - case 0x010000: // [ef][19]xxxx ==> WD2797 floppy disc controller 1.961 - printf("WD279X: wr32 %02X ==> %02X\n", (address >> 1) & 3, value); 1.962 - wd2797_write_reg(&state.fdc_ctx, (address >> 1) & 3, value); 1.963 - handled = true; 1.964 - break; 1.965 - case 0x020000: // [ef][2a]xxxx ==> Miscellaneous Control Register 2 1.966 - break; 1.967 - case 0x030000: // [ef][3b]xxxx ==> Real Time Clock data bits 1.968 - break; 1.969 - case 0x040000: // [ef][4c]xxxx ==> General Control Register 1.970 - switch (address & 0x077000) { 1.971 - case 0x040000: // [ef][4c][08]xxx ==> EE 1.972 - break; 1.973 - case 0x041000: // [ef][4c][19]xxx ==> PIE 1.974 - state.pie = ((value & 0x8000) == 0x8000); 1.975 - handled = true; 1.976 - break; 1.977 - case 0x042000: // [ef][4c][2A]xxx ==> BP 1.978 - break; 1.979 - case 0x043000: // [ef][4c][3B]xxx ==> ROMLMAP 1.980 - state.romlmap = ((value & 0x8000) == 0x8000); 1.981 - handled = true; 1.982 - break; 1.983 - case 0x044000: // [ef][4c][4C]xxx ==> L1 MODEM 1.984 - break; 1.985 - case 0x045000: // [ef][4c][5D]xxx ==> L2 MODEM 1.986 - break; 1.987 - case 0x046000: // [ef][4c][6E]xxx ==> D/N CONNECT 1.988 - break; 1.989 - case 0x047000: // [ef][4c][7F]xxx ==> Whole screen reverse video 1.990 - break; 1.991 - } 1.992 - case 0x050000: // [ef][5d]xxxx ==> 8274 1.993 - break; 1.994 - case 0x060000: // [ef][6e]xxxx ==> Control regs 1.995 - switch (address & 0x07F000) { 1.996 - default: 1.997 - break; 1.998 - } 1.999 - break; 1.1000 - case 0x070000: // [ef][7f]xxxx ==> 6850 Keyboard Controller 1.1001 - break; 1.1002 - } 1.1003 - } 1.1004 + } else { 1.1005 + IoWrite(address, value, 32); 1.1006 } 1.1007 - 1.1008 - LOG_NOT_HANDLED_W(32); 1.1009 -} 1.1010 +}/*}}}*/ 1.1011 1.1012 /** 1.1013 * @brief Write M68K memory, 16-bit 1.1014 */ 1.1015 -void m68k_write_memory_16(uint32_t address, uint32_t value) 1.1016 +void m68k_write_memory_16(uint32_t address, uint32_t value)/*{{{*/ 1.1017 { 1.1018 - bool handled = false; 1.1019 - 1.1020 // If ROMLMAP is set, force system to access ROM 1.1021 if (!state.romlmap) 1.1022 address |= 0x800000; 1.1023 @@ -935,203 +714,33 @@ 1.1024 1.1025 if ((address >= 0x800000) && (address <= 0xBFFFFF)) { 1.1026 // ROM access 1.1027 - handled = true; 1.1028 } else if (address <= (state.ram_size - 1)) { 1.1029 // RAM access 1.1030 WR16(state.ram, mapAddr(address, false), state.ram_size - 1, value); 1.1031 - handled = true; 1.1032 } else if ((address >= 0x400000) && (address <= 0x7FFFFF)) { 1.1033 // I/O register space, zone A 1.1034 switch (address & 0x0F0000) { 1.1035 case 0x000000: // Map RAM access 1.1036 if (address > 0x4007FF) fprintf(stderr, "NOTE: WR16 to MapRAM mirror, addr=0x%08X, data=0x%04X\n", address, value); 1.1037 WR16(state.map, address, 0x7FF, value); 1.1038 - handled = true; 1.1039 - break; 1.1040 - case 0x010000: // General Status Register (read only) 1.1041 - handled = true; 1.1042 break; 1.1043 case 0x020000: // Video RAM 1.1044 if (address > 0x427FFF) fprintf(stderr, "NOTE: WR16 to VideoRAM mirror, addr=0x%08X, data=0x%04X\n", address, value); 1.1045 WR16(state.vram, address, 0x7FFF, value); 1.1046 - handled = true; 1.1047 break; 1.1048 - case 0x030000: // Bus Status Register 0 (read only) 1.1049 - handled = true; 1.1050 - break; 1.1051 - case 0x040000: // Bus Status Register 1 (read only) 1.1052 - handled = true; 1.1053 - break; 1.1054 - case 0x050000: // Phone status 1.1055 - break; 1.1056 - case 0x060000: // DMA Count 1.1057 - printf("WR16 dmacount %08X\n", value); 1.1058 - state.dma_count = (value & 0x3FFF); 1.1059 - state.idmarw = ((value & 0x4000) == 0x4000); 1.1060 - state.dmaen = ((value & 0x8000) == 0x8000); 1.1061 - printf("\tcount %04X, idmarw %d, dmaen %d\n", state.dma_count, state.idmarw, state.dmaen); 1.1062 - // This handles the "dummy DMA transfer" mentioned in the docs 1.1063 - // TODO: access check, peripheral access 1.1064 - if (!state.idmarw) 1.1065 - WR32(state.ram, mapAddr(address, false), state.ram_size - 1, 0xDEAD); 1.1066 - state.dma_count++; 1.1067 - handled = true; 1.1068 - break; 1.1069 - case 0x070000: // Line Printer Status Register 1.1070 - break; 1.1071 - case 0x080000: // Real Time Clock 1.1072 - break; 1.1073 - case 0x090000: // Phone registers 1.1074 - switch (address & 0x0FF000) { 1.1075 - case 0x090000: // Handset relay 1.1076 - case 0x098000: 1.1077 - break; 1.1078 - case 0x091000: // Line select 2 1.1079 - case 0x099000: 1.1080 - break; 1.1081 - case 0x092000: // Hook relay 1 1.1082 - case 0x09A000: 1.1083 - break; 1.1084 - case 0x093000: // Hook relay 2 1.1085 - case 0x09B000: 1.1086 - break; 1.1087 - case 0x094000: // Line 1 hold 1.1088 - case 0x09C000: 1.1089 - break; 1.1090 - case 0x095000: // Line 2 hold 1.1091 - case 0x09D000: 1.1092 - break; 1.1093 - case 0x096000: // Line 1 A-lead 1.1094 - case 0x09E000: 1.1095 - break; 1.1096 - case 0x097000: // Line 2 A-lead 1.1097 - case 0x09F000: 1.1098 - break; 1.1099 - } 1.1100 - break; 1.1101 - case 0x0A0000: // Miscellaneous Control Register 1.1102 - // TODO: handle the ctrl bits properly 1.1103 - // TODO: &0x8000 --> dismiss 60hz intr 1.1104 - state.dma_reading = (value & 0x4000); 1.1105 - state.leds = (~value & 0xF00) >> 8; 1.1106 - printf("LEDs: %s %s %s %s\n", 1.1107 - (state.leds & 8) ? "R" : "-", 1.1108 - (state.leds & 4) ? "G" : "-", 1.1109 - (state.leds & 2) ? "Y" : "-", 1.1110 - (state.leds & 1) ? "R" : "-"); 1.1111 - handled = true; 1.1112 - break; 1.1113 - case 0x0B0000: // TM/DIALWR 1.1114 - break; 1.1115 - case 0x0C0000: // Clear Status Register 1.1116 - state.genstat = 0xFFFF; 1.1117 - state.bsr0 = 0xFFFF; 1.1118 - state.bsr1 = 0xFFFF; 1.1119 - handled = true; 1.1120 - break; 1.1121 - case 0x0D0000: // DMA Address Register 1.1122 - if (address & 0x004000) { 1.1123 - // A14 high -- set most significant bits 1.1124 - state.dma_address = (state.dma_address & 0x1fe) | ((address & 0x3ffe) << 8); 1.1125 - } else { 1.1126 - // A14 low -- set least significant bits 1.1127 - state.dma_address = (state.dma_address & 0x3ffe00) | (address & 0x1fe); 1.1128 - } 1.1129 - printf("WR16 DMA_ADDR %s, now %08X\n", address & 0x004000 ? "HI" : "LO", state.dma_address); 1.1130 - handled = true; 1.1131 - break; 1.1132 - case 0x0E0000: // Disk Control Register 1.1133 - // B7 = FDD controller reset 1.1134 - if ((value & 0x80) == 0) wd2797_reset(&state.fdc_ctx); 1.1135 - // B6 = drive 0 select -- TODO 1.1136 - // B5 = motor enable -- TODO 1.1137 - // B4 = HDD controller reset -- TODO 1.1138 - // B3 = HDD0 select -- TODO 1.1139 - // B2,1,0 = HDD0 head select 1.1140 - handled = true; 1.1141 - break; 1.1142 - case 0x0F0000: // Line Printer Data Register 1.1143 - break; 1.1144 + default: 1.1145 + IoWrite(address, value, 16); 1.1146 } 1.1147 - } else if ((address >= 0xC00000) && (address <= 0xFFFFFF)) { 1.1148 - // I/O register space, zone B 1.1149 - switch (address & 0xF00000) { 1.1150 - case 0xC00000: // Expansion slots 1.1151 - case 0xD00000: 1.1152 - switch (address & 0xFC0000) { 1.1153 - case 0xC00000: // Expansion slot 0 1.1154 - case 0xC40000: // Expansion slot 1 1.1155 - case 0xC80000: // Expansion slot 2 1.1156 - case 0xCC0000: // Expansion slot 3 1.1157 - case 0xD00000: // Expansion slot 4 1.1158 - case 0xD40000: // Expansion slot 5 1.1159 - case 0xD80000: // Expansion slot 6 1.1160 - case 0xDC0000: // Expansion slot 7 1.1161 - fprintf(stderr, "NOTE: WR16 to expansion card space, addr=0x%08X, data=0x%04X\n", address, value); 1.1162 - break; 1.1163 - } 1.1164 - break; 1.1165 - case 0xE00000: // HDC, FDC, MCR2 and RTC data bits 1.1166 - case 0xF00000: 1.1167 - switch (address & 0x070000) { 1.1168 - case 0x000000: // [ef][08]xxxx ==> WD1010 hard disc controller 1.1169 - break; 1.1170 - case 0x010000: // [ef][19]xxxx ==> WD2797 floppy disc controller 1.1171 - printf("WD279X: wr16 %02X ==> %02X\n", (address >> 1) & 3, value); 1.1172 - wd2797_write_reg(&state.fdc_ctx, (address >> 1) & 3, value); 1.1173 - handled = true; 1.1174 - break; 1.1175 - case 0x020000: // [ef][2a]xxxx ==> Miscellaneous Control Register 2 1.1176 - break; 1.1177 - case 0x030000: // [ef][3b]xxxx ==> Real Time Clock data bits 1.1178 - break; 1.1179 - case 0x040000: // [ef][4c]xxxx ==> General Control Register 1.1180 - switch (address & 0x077000) { 1.1181 - case 0x040000: // [ef][4c][08]xxx ==> EE 1.1182 - break; 1.1183 - case 0x041000: // [ef][4c][19]xxx ==> PIE 1.1184 - state.pie = ((value & 0x8000) == 0x8000); 1.1185 - handled = true; 1.1186 - break; 1.1187 - case 0x042000: // [ef][4c][2A]xxx ==> BP 1.1188 - break; 1.1189 - case 0x043000: // [ef][4c][3B]xxx ==> ROMLMAP 1.1190 - state.romlmap = ((value & 0x8000) == 0x8000); 1.1191 - handled = true; 1.1192 - break; 1.1193 - case 0x044000: // [ef][4c][4C]xxx ==> L1 MODEM 1.1194 - break; 1.1195 - case 0x045000: // [ef][4c][5D]xxx ==> L2 MODEM 1.1196 - break; 1.1197 - case 0x046000: // [ef][4c][6E]xxx ==> D/N CONNECT 1.1198 - break; 1.1199 - case 0x047000: // [ef][4c][7F]xxx ==> Whole screen reverse video 1.1200 - break; 1.1201 - } 1.1202 - case 0x050000: // [ef][5d]xxxx ==> 8274 1.1203 - break; 1.1204 - case 0x060000: // [ef][6e]xxxx ==> Control regs 1.1205 - switch (address & 0x07F000) { 1.1206 - default: 1.1207 - break; 1.1208 - } 1.1209 - break; 1.1210 - case 0x070000: // [ef][7f]xxxx ==> 6850 Keyboard Controller 1.1211 - break; 1.1212 - } 1.1213 - } 1.1214 + } else { 1.1215 + IoWrite(address, value, 16); 1.1216 } 1.1217 - 1.1218 - LOG_NOT_HANDLED_W(16); 1.1219 -} 1.1220 +}/*}}}*/ 1.1221 1.1222 /** 1.1223 * @brief Write M68K memory, 8-bit 1.1224 */ 1.1225 -void m68k_write_memory_8(uint32_t address, uint32_t value) 1.1226 +void m68k_write_memory_8(uint32_t address, uint32_t value)/*{{{*/ 1.1227 { 1.1228 - bool handled = false; 1.1229 - 1.1230 // If ROMLMAP is set, force system to access ROM 1.1231 if (!state.romlmap) 1.1232 address |= 0x800000; 1.1233 @@ -1141,198 +750,27 @@ 1.1234 1.1235 if ((address >= 0x800000) && (address <= 0xBFFFFF)) { 1.1236 // ROM access (read only!) 1.1237 - handled = true; 1.1238 } else if (address <= (state.ram_size - 1)) { 1.1239 // RAM access 1.1240 WR8(state.ram, mapAddr(address, false), state.ram_size - 1, value); 1.1241 - handled = true; 1.1242 } else if ((address >= 0x400000) && (address <= 0x7FFFFF)) { 1.1243 // I/O register space, zone A 1.1244 switch (address & 0x0F0000) { 1.1245 case 0x000000: // Map RAM access 1.1246 - if (address > 0x4007FF) fprintf(stderr, "NOTE: WR8 to MapRAM mirror, addr=%08X, data=%02X\n", address, value); 1.1247 + if (address > 0x4007FF) fprintf(stderr, "NOTE: WR8 to MapRAM mirror, addr=0x%08X, data=0x%04X\n", address, value); 1.1248 WR8(state.map, address, 0x7FF, value); 1.1249 - handled = true; 1.1250 - break; 1.1251 - case 0x010000: // General Status Register 1.1252 - handled = true; 1.1253 break; 1.1254 case 0x020000: // Video RAM 1.1255 - if (address > 0x427FFF) fprintf(stderr, "NOTE: WR8 to VideoRAM mirror, addr=%08X, data=0x%02X\n", address, value); 1.1256 + if (address > 0x427FFF) fprintf(stderr, "NOTE: WR8 to VideoRAM mirror, addr=0x%08X, data=0x%04X\n", address, value); 1.1257 WR8(state.vram, address, 0x7FFF, value); 1.1258 - handled = true; 1.1259 - break; 1.1260 - case 0x030000: // Bus Status Register 0 1.1261 - handled = true; 1.1262 - break; 1.1263 - case 0x040000: // Bus Status Register 1 1.1264 - handled = true; 1.1265 - break; 1.1266 - case 0x050000: // Phone status 1.1267 - break; 1.1268 - case 0x060000: // DMA Count 1.1269 - // TODO: how to handle this in 8bit mode? 1.1270 - break; 1.1271 - case 0x070000: // Line Printer Status Register 1.1272 - break; 1.1273 - case 0x080000: // Real Time Clock 1.1274 - break; 1.1275 - case 0x090000: // Phone registers 1.1276 - switch (address & 0x0FF000) { 1.1277 - case 0x090000: // Handset relay 1.1278 - case 0x098000: 1.1279 - break; 1.1280 - case 0x091000: // Line select 2 1.1281 - case 0x099000: 1.1282 - break; 1.1283 - case 0x092000: // Hook relay 1 1.1284 - case 0x09A000: 1.1285 - break; 1.1286 - case 0x093000: // Hook relay 2 1.1287 - case 0x09B000: 1.1288 - break; 1.1289 - case 0x094000: // Line 1 hold 1.1290 - case 0x09C000: 1.1291 - break; 1.1292 - case 0x095000: // Line 2 hold 1.1293 - case 0x09D000: 1.1294 - break; 1.1295 - case 0x096000: // Line 1 A-lead 1.1296 - case 0x09E000: 1.1297 - break; 1.1298 - case 0x097000: // Line 2 A-lead 1.1299 - case 0x09F000: 1.1300 - break; 1.1301 - } 1.1302 - break; 1.1303 - case 0x0A0000: // Miscellaneous Control Register 1.1304 - // TODO: how to handle this in 8bit mode? 1.1305 -/* 1.1306 - // TODO: handle the ctrl bits properly 1.1307 - if ((address & 1) == 0) { 1.1308 - // low byte 1.1309 - } else { 1.1310 - // hight byte 1.1311 - // TODO: &0x8000 --> dismiss 60hz intr 1.1312 - state.dma_reading = (value & 0x40); 1.1313 - state.leds = (~value & 0xF); 1.1314 - } 1.1315 - printf("LEDs: %s %s %s %s\n", 1.1316 - (state.leds & 8) ? "R" : "-", 1.1317 - (state.leds & 4) ? "G" : "-", 1.1318 - (state.leds & 2) ? "Y" : "-", 1.1319 - (state.leds & 1) ? "R" : "-"); 1.1320 - handled = true; 1.1321 -*/ 1.1322 - break; 1.1323 - case 0x0B0000: // TM/DIALWR 1.1324 - break; 1.1325 - case 0x0C0000: // Clear Status Register 1.1326 - state.genstat = 0xFFFF; 1.1327 - state.bsr0 = 0xFFFF; 1.1328 - state.bsr1 = 0xFFFF; 1.1329 - handled = true; 1.1330 - break; 1.1331 - case 0x0D0000: // DMA Address Register 1.1332 - if (address & 0x004000) { 1.1333 - // A14 high -- set most significant bits 1.1334 - state.dma_address = (state.dma_address & 0x1fe) | ((address & 0x3ffe) << 8); 1.1335 - } else { 1.1336 - // A14 low -- set least significant bits 1.1337 - state.dma_address = (state.dma_address & 0x3ffe00) | (address & 0x1fe); 1.1338 - } 1.1339 - printf("WR08 DMA_ADDR %s, now %08X\n", address & 0x004000 ? "HI" : "LO", state.dma_address); 1.1340 - handled = true; 1.1341 break; 1.1342 - case 0x0E0000: // Disk Control Register 1.1343 - // B7 = FDD controller reset 1.1344 - if ((value & 0x80) == 0) wd2797_reset(&state.fdc_ctx); 1.1345 - // B6 = drive 0 select -- TODO 1.1346 - // B5 = motor enable -- TODO 1.1347 - // B4 = HDD controller reset -- TODO 1.1348 - // B3 = HDD0 select -- TODO 1.1349 - // B2,1,0 = HDD0 head select 1.1350 - handled = true; 1.1351 - break; 1.1352 - case 0x0F0000: // Line Printer Data Register 1.1353 - break; 1.1354 + default: 1.1355 + IoWrite(address, value, 8); 1.1356 } 1.1357 - } else if ((address >= 0xC00000) && (address <= 0xFFFFFF)) { 1.1358 - // I/O register space, zone B 1.1359 - switch (address & 0xF00000) { 1.1360 - case 0xC00000: // Expansion slots 1.1361 - case 0xD00000: 1.1362 - switch (address & 0xFC0000) { 1.1363 - case 0xC00000: // Expansion slot 0 1.1364 - case 0xC40000: // Expansion slot 1 1.1365 - case 0xC80000: // Expansion slot 2 1.1366 - case 0xCC0000: // Expansion slot 3 1.1367 - case 0xD00000: // Expansion slot 4 1.1368 - case 0xD40000: // Expansion slot 5 1.1369 - case 0xD80000: // Expansion slot 6 1.1370 - case 0xDC0000: // Expansion slot 7 1.1371 - fprintf(stderr, "NOTE: WR8 to expansion card space, addr=0x%08X, data=0x%08X\n", address, value); 1.1372 - break; 1.1373 - } 1.1374 - break; 1.1375 - case 0xE00000: // HDC, FDC, MCR2 and RTC data bits 1.1376 - case 0xF00000: 1.1377 - switch (address & 0x070000) { 1.1378 - case 0x000000: // [ef][08]xxxx ==> WD1010 hard disc controller 1.1379 - break; 1.1380 - case 0x010000: // [ef][19]xxxx ==> WD2797 floppy disc controller 1.1381 - printf("WD279X: wr8 %02X ==> %02X\n", (address >> 1) & 3, value); 1.1382 - wd2797_write_reg(&state.fdc_ctx, (address >> 1) & 3, value); 1.1383 - handled = true; 1.1384 - break; 1.1385 - case 0x020000: // [ef][2a]xxxx ==> Miscellaneous Control Register 2 1.1386 - break; 1.1387 - case 0x030000: // [ef][3b]xxxx ==> Real Time Clock data bits 1.1388 - break; 1.1389 - case 0x040000: // [ef][4c]xxxx ==> General Control Register 1.1390 - switch (address & 0x077000) { 1.1391 - case 0x040000: // [ef][4c][08]xxx ==> EE 1.1392 - break; 1.1393 - case 0x041000: // [ef][4c][19]xxx ==> PIE 1.1394 - if ((address & 1) == 0) 1.1395 - state.pie = ((value & 0x80) == 0x80); 1.1396 - handled = true; 1.1397 - break; 1.1398 - case 0x042000: // [ef][4c][2A]xxx ==> BP 1.1399 - break; 1.1400 - case 0x043000: // [ef][4c][3B]xxx ==> ROMLMAP 1.1401 - if ((address & 1) == 0) 1.1402 - state.romlmap = ((value & 0x80) == 0x80); 1.1403 - handled = true; 1.1404 - break; 1.1405 - case 0x044000: // [ef][4c][4C]xxx ==> L1 MODEM 1.1406 - break; 1.1407 - case 0x045000: // [ef][4c][5D]xxx ==> L2 MODEM 1.1408 - break; 1.1409 - case 0x046000: // [ef][4c][6E]xxx ==> D/N CONNECT 1.1410 - break; 1.1411 - case 0x047000: // [ef][4c][7F]xxx ==> Whole screen reverse video 1.1412 - break; 1.1413 - } 1.1414 - case 0x050000: // [ef][5d]xxxx ==> 8274 1.1415 - break; 1.1416 - case 0x060000: // [ef][6e]xxxx ==> Control regs 1.1417 - switch (address & 0x07F000) { 1.1418 - default: 1.1419 - break; 1.1420 - } 1.1421 - break; 1.1422 - case 0x070000: // [ef][7f]xxxx ==> 6850 Keyboard Controller 1.1423 - break; 1.1424 - default: 1.1425 - fprintf(stderr, "NOTE: WR8 to undefined E/F-block space, addr=0x%08X, data=0x%08X\n", address, value); 1.1426 - break; 1.1427 - } 1.1428 - } 1.1429 + } else { 1.1430 + IoWrite(address, value, 8); 1.1431 } 1.1432 - 1.1433 - LOG_NOT_HANDLED_W(8); 1.1434 -} 1.1435 +}/*}}}*/ 1.1436 1.1437 1.1438 // for the disassembler 1.1439 @@ -1340,4 +778,3 @@ 1.1440 uint32_t m68k_read_disassembler_16(uint32_t addr) { return m68k_read_memory_16(addr); } 1.1441 uint32_t m68k_read_disassembler_8 (uint32_t addr) { return m68k_read_memory_8 (addr); } 1.1442 1.1443 -