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