src/memory.c

Sat, 17 Nov 2012 19:18:29 +0000

author
Philip Pemberton <philpem@philpem.me.uk>
date
Sat, 17 Nov 2012 19:18:29 +0000
changeset 112
a392eb8f9806
parent 108
5f7faf5ecbf4
child 113
d3bb6a6a04b7
permissions
-rw-r--r--

add HDD support + fixes

Patch-Author: Andrew Warkentin <andreww591!gmail>
Patch-Message-ID: <50A772FC.8020009@gmail.com>

I have added floppy write support, full hard disk emulation, and proper handling of DMA page faults to FreeBee. I also fixed the floppy step commands, changed the "force interrupt" floppy command to generate a type 1 status, and changed the DMA address counter to reset to 3fff when a transfer completes (which is what Unix seems to expect - without it, the kernel says that the floppy isn't ready). The floppy, hard disk, and DMA page fault tests all pass. Initializing hard disks and floppies also works (the geometry for both is still fixed by the size of the image, though, and format commands only appear to succeed, but they don't modify the image). Unix still doesn't run, though (it hangs after reading some sectors from the floppy).

     1 #include <stdio.h>
     2 #include <stdlib.h>
     3 #include <stdint.h>
     4 #include <stdbool.h>
     5 #include <assert.h>
     6 #include "musashi/m68k.h"
     7 #include "state.h"
     8 #include "utils.h"
     9 #include "memory.h"
    11 /******************
    12  * Memory mapping
    13  ******************/
    15 #define MAPRAM(addr) (((uint16_t)state.map[addr*2] << 8) + ((uint16_t)state.map[(addr*2)+1]))
    17 uint32_t mapAddr(uint32_t addr, bool writing)/*{{{*/
    18 {
    19 	if (addr < 0x400000) {
    20 		// RAM access. Check against the Map RAM
    21 		// Start by getting the original page address
    22 		uint16_t page = (addr >> 12) & 0x3FF;
    24 		// Look it up in the map RAM and get the physical page address
    25 		uint32_t new_page_addr = MAPRAM(page) & 0x3FF;
    27 		// Update the Page Status bits
    28 		uint8_t pagebits = (MAPRAM(page) >> 13) & 0x03;
    29 		// Pagebits --
    30 		//   0 = not present
    31 		//   1 = present but not accessed
    32 		//   2 = present, accessed (read from)
    33 		//   3 = present, dirty (written to)
    34 		switch (pagebits) {
    35 			case 0:
    36 				// Page not present
    37 				// This should cause a page fault
    38 				LOGS("Whoa! Pagebit update, when the page is not present!");
    39 				break;
    41 			case 1:
    42 				// Page present -- first access
    43 				state.map[page*2] &= 0x9F;	// turn off "present" bit (but not write enable!)
    44 				if (writing)
    45 					state.map[page*2] |= 0x60;		// Page written to (dirty)
    46 				else
    47 					state.map[page*2] |= 0x40;		// Page accessed but not written
    48 				break;
    50 			case 2:
    51 			case 3:
    52 				// Page present, 2nd or later access
    53 				if (writing)
    54 					state.map[page*2] |= 0x60;		// Page written to (dirty)
    55 				break;
    56 		}
    58 		// Return the address with the new physical page spliced in
    59 		return (new_page_addr << 12) + (addr & 0xFFF);
    60 	} else {
    61 		// I/O, VRAM or MapRAM space; no mapping is performed or required
    62 		// TODO: assert here?
    63 		return addr;
    64 	}
    65 }/*}}}*/
    67 MEM_STATUS checkMemoryAccess(uint32_t addr, bool writing)/*{{{*/
    68 {
    69 	// Get the page bits for this page.
    70 	uint16_t page = (addr >> 12) & 0x3FF;
    71 	uint8_t pagebits = (MAPRAM(page) >> 13) & 0x07;
    73 	// Check page is present (but only for RAM zone)
    74 	if ((addr < 0x400000) && ((pagebits & 0x03) == 0)) {
    75 		LOG("Page not mapped in: addr %08X, page %04X, mapbits %04X", addr, page, MAPRAM(page));
    76 		return MEM_PAGEFAULT;
    77 	}
    79 	// Are we in Supervisor mode?
    80 	if (m68k_get_reg(NULL, M68K_REG_SR) & 0x2000)
    81 		// Yes. We can do anything we like.
    82 		return MEM_ALLOWED;
    84 	// If we're here, then we must be in User mode.
    85 	// Check that the user didn't access memory outside of the RAM area
    86 	if (addr >= 0x400000) {
    87 		LOGS("User accessed privileged memory");
    88 		return MEM_UIE;
    89 	}
    91 	// User attempt to access the kernel
    92 	// A19, A20, A21, A22 low (kernel access): RAM addr before paging; not in Supervisor mode
    93 	if (((addr >> 19) & 0x0F) == 0) {
    94 		LOGS("Attempt by user code to access kernel space");
    95 		return MEM_KERNEL;
    96 	}
    98 	// Check page is write enabled
    99 	if (writing && ((pagebits & 0x04) == 0)) {
   100 		LOG("Page not write enabled: inaddr %08X, page %04X, mapram %04X [%02X %02X], pagebits %d",
   101 				addr, page, MAPRAM(page), state.map[page*2], state.map[(page*2)+1], pagebits);
   102 		return MEM_PAGE_NO_WE;
   103 	}
   105 	// Page access allowed.
   106 	return MEM_ALLOWED;
   107 }/*}}}*/
   109 #undef MAPRAM
   112 /********************************************************
   113  * m68k memory read/write support functions for Musashi
   114  ********************************************************/
   116 /**
   117  * @brief	Check memory access permissions for a write operation.
   118  * @note	This used to be a single macro (merged with ACCESS_CHECK_RD), but
   119  * 			gcc throws warnings when you have a return-with-value in a void
   120  * 			function, even if the return-with-value is completely unreachable.
   121  * 			Similarly it doesn't like it if you have a return without a value
   122  * 			in a non-void function, even if it's impossible to ever reach the
   123  * 			return-with-no-value. UGH!
   124  */
   125 /*{{{ macro: ACCESS_CHECK_WR(address, bits)*/
   126 #define ACCESS_CHECK_WR(address, bits)								\
   127 	do {															\
   128 		bool fault = false;											\
   129 		MEM_STATUS st;												\
   130 		switch (st = checkMemoryAccess(address, true)) {			\
   131 			case MEM_ALLOWED:										\
   132 				/* Access allowed */								\
   133 				break;												\
   134 			case MEM_PAGEFAULT:										\
   135 				/* Page fault */									\
   136 				state.genstat = 0x8BFF | (state.pie ? 0x0400 : 0);	\
   137 				fault = true;										\
   138 				break;												\
   139 			case MEM_UIE:											\
   140 				/* User access to memory above 4MB */				\
   141 				state.genstat = 0x9AFF | (state.pie ? 0x0400 : 0);	\
   142 				fault = true;										\
   143 				break;												\
   144 			case MEM_KERNEL:										\
   145 			case MEM_PAGE_NO_WE:									\
   146 				/* kernel access or page not write enabled */		\
   147 				/* XXX: is this the correct value? */				\
   148 				state.genstat = 0x9BFF | (state.pie ? 0x0400 : 0);	\
   149 				fault = true;										\
   150 				break;												\
   151 		}															\
   152 																	\
   153 		if (fault) {												\
   154 			if (bits >= 16)											\
   155 				state.bsr0 = 0x7C00;								\
   156 			else													\
   157 				state.bsr0 = (address & 1) ? 0x7E00 : 0x7D00;		\
   158 			state.bsr0 |= (address >> 16);							\
   159 			state.bsr1 = address & 0xffff;							\
   160 			LOG("Bus Error while writing, addr %08X, statcode %d", address, st);		\
   161 			if (state.ee) m68k_pulse_bus_error();					\
   162 			return;													\
   163 		}															\
   164 	} while (0)
   165 /*}}}*/
   167 /**
   168  * @brief Check memory access permissions for a read operation.
   169  * @note	This used to be a single macro (merged with ACCESS_CHECK_WR), but
   170  * 			gcc throws warnings when you have a return-with-value in a void
   171  * 			function, even if the return-with-value is completely unreachable.
   172  * 			Similarly it doesn't like it if you have a return without a value
   173  * 			in a non-void function, even if it's impossible to ever reach the
   174  * 			return-with-no-value. UGH!
   175  */
   176 /*{{{ macro: ACCESS_CHECK_RD(address, bits)*/
   177 #define ACCESS_CHECK_RD(address, bits)								\
   178 	do {															\
   179 		bool fault = false;											\
   180 		MEM_STATUS st;												\
   181 		switch (st = checkMemoryAccess(address, false)) {			\
   182 			case MEM_ALLOWED:										\
   183 				/* Access allowed */								\
   184 				break;												\
   185 			case MEM_PAGEFAULT:										\
   186 				/* Page fault */									\
   187 				state.genstat = 0xCBFF | (state.pie ? 0x0400 : 0);	\
   188 				fault = true;										\
   189 				break;												\
   190 			case MEM_UIE:											\
   191 				/* User access to memory above 4MB */				\
   192 				state.genstat = 0xDAFF | (state.pie ? 0x0400 : 0);	\
   193 				fault = true;										\
   194 				break;												\
   195 			case MEM_KERNEL:										\
   196 			case MEM_PAGE_NO_WE:									\
   197 				/* kernel access or page not write enabled */		\
   198 				/* XXX: is this the correct value? */				\
   199 				state.genstat = 0xDBFF | (state.pie ? 0x0400 : 0);	\
   200 				fault = true;										\
   201 				break;												\
   202 		}															\
   203 																	\
   204 		if (fault) {												\
   205 			if (bits >= 16)											\
   206 				state.bsr0 = 0x7C00;								\
   207 			else													\
   208 				state.bsr0 = (address & 1) ? 0x7E00 : 0x7D00;		\
   209 			state.bsr0 |= (address >> 16);							\
   210 			state.bsr1 = address & 0xffff;							\
   211 			LOG("Bus Error while reading, addr %08X, statcode %d", address, st);		\
   212 			if (state.ee) m68k_pulse_bus_error();					\
   213 			return 0xFFFFFFFF;										\
   214 		}															\
   215 	} while (0)
   216 /*}}}*/
   218 bool access_check_dma(int reading)
   219 {
   220 	// Check memory access permissions
   221 	bool access_ok;
   222 	switch (checkMemoryAccess(state.dma_address, !reading)) {
   223 		case MEM_PAGEFAULT:
   224 			// Page fault
   225 			state.genstat = 0xABFF
   226 				| (reading ? 0x4000 : 0)
   227 				| (state.pie ? 0x0400 : 0);
   228 			access_ok = false;
   229 			break;
   231 		case MEM_UIE:
   232 			// User access to memory above 4MB
   233 			// FIXME? Shouldn't be possible with DMA... assert this?
   234 			state.genstat = 0xBAFF
   235 				| (reading ? 0x4000 : 0)
   236 				| (state.pie ? 0x0400 : 0);
   237 			access_ok = false;
   238 			break;
   240 		case MEM_KERNEL:
   241 		case MEM_PAGE_NO_WE:
   242 			// Kernel access or page not write enabled
   243 			/* XXX: is this correct? */
   244 			state.genstat = 0xBBFF
   245 				| (reading ? 0x4000 : 0)
   246 				| (state.pie ? 0x0400 : 0);
   247 			access_ok = false;
   248 			break;
   250 		case MEM_ALLOWED:
   251 			access_ok = true;
   252 			break;
   253 	}
   254 	if (!access_ok) {
   255 		state.bsr0 = 0x3C00;
   256 		state.bsr0 |= (state.dma_address >> 16);
   257 		state.bsr1 = state.dma_address & 0xffff;
   258 		if (state.ee) m68k_set_irq(7);
   259 		printf("BUS ERROR FROM DMA: genstat=%04X, bsr0=%04X, bsr1=%04X\n", state.genstat, state.bsr0, state.bsr1);
   260 	}
   261 	return (access_ok);
   262 }
   264 // Logging macros
   265 #define LOG_NOT_HANDLED_R(bits)															\
   266 	if (!handled) printf("unhandled read%02d, addr=0x%08X\n", bits, address);
   268 #define LOG_NOT_HANDLED_W(bits)															\
   269 	if (!handled) printf("unhandled write%02d, addr=0x%08X, data=0x%08X\n", bits, address, data);
   271 /********************************************************
   272  * I/O read/write functions
   273  ********************************************************/
   275 /**
   276  * Issue a warning if a read operation is made with an invalid size
   277  */
   278 inline static void ENFORCE_SIZE(int bits, uint32_t address, bool read, int allowed, char *regname)
   279 {
   280 	assert((bits == 8) || (bits == 16) || (bits == 32));
   281 	if ((bits & allowed) == 0) {
   282 		printf("WARNING: %s 0x%08X (%s) with invalid size %d!\n", read ? "read from" : "write to", address, regname, bits);
   283 	}
   284 }
   286 inline static void ENFORCE_SIZE_R(int bits, uint32_t address, int allowed, char *regname)
   287 {
   288 	ENFORCE_SIZE(bits, address, true, allowed, regname);
   289 }
   291 inline static void ENFORCE_SIZE_W(int bits, uint32_t address, int allowed, char *regname)
   292 {
   293 	ENFORCE_SIZE(bits, address, false, allowed, regname);
   294 }
   296 void IoWrite(uint32_t address, uint32_t data, int bits)/*{{{*/
   297 {
   298 	bool handled = false;
   300 	if ((address >= 0x400000) && (address <= 0x7FFFFF)) {
   301 		// I/O register space, zone A
   302 		switch (address & 0x0F0000) {
   303 			case 0x010000:				// General Status Register
   304 				if (bits == 16)
   305 					state.genstat = (data & 0xffff);
   306 				else if (bits == 8) {
   307 					if (address & 0)
   308 						state.genstat = data;
   309 					else
   310 						state.genstat = data << 8;
   311 				}
   312 				handled = true;
   313 				break;
   314 			case 0x030000:				// Bus Status Register 0
   315 				break;
   316 			case 0x040000:				// Bus Status Register 1
   317 				break;
   318 			case 0x050000:				// Phone status
   319 				break;
   320 			case 0x060000:				// DMA Count
   321 				ENFORCE_SIZE_W(bits, address, 16, "DMACOUNT");
   322 				state.dma_count = (data & 0x3FFF);
   323 				state.idmarw = ((data & 0x4000) == 0x4000);
   324 				state.dmaen = ((data & 0x8000) == 0x8000);
   325 				// This handles the "dummy DMA transfer" mentioned in the docs
   326 				// disabled because it causes the floppy test to fail
   327 #if 0
   328 				if (!state.idmarw){
   329 					if (access_check_dma(true)){
   330 						uint32_t newAddr = mapAddr(state.dma_address, true);
   331 						// RAM access
   332 						if (newAddr <= 0x1fffff)
   333 							WR16(state.base_ram, newAddr, state.base_ram_size - 1, 0xFF);
   334 						else if (address <= 0x3FFFFF)
   335 							WR16(state.exp_ram, newAddr - 0x200000, state.exp_ram_size - 1, 0xFF);
   336 					}
   337 				}
   338 #endif
   339 				state.dma_count++;
   340 				handled = true;
   341 				break;
   342 			case 0x070000:				// Line Printer Status Register
   343 				break;
   344 			case 0x080000:				// Real Time Clock
   345 				break;
   346 			case 0x090000:				// Phone registers
   347 				switch (address & 0x0FF000) {
   348 					case 0x090000:		// Handset relay
   349 					case 0x098000:
   350 						break;
   351 					case 0x091000:		// Line select 2
   352 					case 0x099000:
   353 						break;
   354 					case 0x092000:		// Hook relay 1
   355 					case 0x09A000:
   356 						break;
   357 					case 0x093000:		// Hook relay 2
   358 					case 0x09B000:
   359 						break;
   360 					case 0x094000:		// Line 1 hold
   361 					case 0x09C000:
   362 						break;
   363 					case 0x095000:		// Line 2 hold
   364 					case 0x09D000:
   365 						break;
   366 					case 0x096000:		// Line 1 A-lead
   367 					case 0x09E000:
   368 						break;
   369 					case 0x097000:		// Line 2 A-lead
   370 					case 0x09F000:
   371 						break;
   372 				}
   373 				break;
   374 			case 0x0A0000:				// Miscellaneous Control Register
   375 				ENFORCE_SIZE_W(bits, address, 16, "MISCCON");
   376 				// TODO: handle the ctrl bits properly
   377 				if (data & 0x8000){
   378 					state.timer_enabled = 1;
   379 				}else{
   380 					state.timer_enabled = 0;
   381 					state.timer_asserted = 0;
   382 				}
   383 				state.dma_reading = (data & 0x4000);
   384 				if (state.leds != ((~data & 0xF00) >> 8)) {
   385 					state.leds = (~data & 0xF00) >> 8;
   386 					printf("LEDs: %s %s %s %s\n",
   387 							(state.leds & 8) ? "R" : "-",
   388 							(state.leds & 4) ? "G" : "-",
   389 							(state.leds & 2) ? "Y" : "-",
   390 							(state.leds & 1) ? "R" : "-");
   391 				}
   392 				handled = true;
   393 				break;
   394 			case 0x0B0000:				// TM/DIALWR
   395 				break;
   396 			case 0x0C0000:				// Clear Status Register
   397 				state.genstat = 0xFFFF;
   398 				state.bsr0 = 0xFFFF;
   399 				state.bsr1 = 0xFFFF;
   400 				handled = true;
   401 				break;
   402 			case 0x0D0000:				// DMA Address Register
   403 				if (address & 0x004000) {
   404 					// A14 high -- set most significant bits
   405 					state.dma_address = (state.dma_address & 0x1fe) | ((address & 0x3ffe) << 8);
   406 				} else {
   407 					// A14 low -- set least significant bits
   408 					state.dma_address = (state.dma_address & 0x3ffe00) | (address & 0x1fe);
   409 				}
   410 				handled = true;
   411 				break;
   412 			case 0x0E0000:				// Disk Control Register
   413 				{
   414 					bool fd_selected;
   415 					bool hd_selected;
   416 					ENFORCE_SIZE_W(bits, address, 16, "DISKCON");
   417 					// B7 = FDD controller reset
   418 					if ((data & 0x80) == 0) wd2797_reset(&state.fdc_ctx);
   419 					// B6 = drive 0 select
   420 					fd_selected = (data & 0x40) != 0;
   421 					// B5 = motor enable -- TODO
   422 					// B4 = HDD controller reset
   423 					if ((data & 0x10) == 0) wd2010_reset(&state.hdc_ctx);
   424 					// B3 = HDD0 select
   425 					hd_selected = (data & 0x08) != 0;
   426 					// B2,1,0 = HDD0 head select -- TODO?
   427 					if (hd_selected && !state.hd_selected){
   428 						state.fd_selected = false;
   429 						state.hd_selected = true;
   430 					}else if (fd_selected && !state.fd_selected){
   431 						state.hd_selected = false;
   432 						state.fd_selected = true;
   433 					}
   434 					handled = true;
   435 					break;
   436 				}
   437 			case 0x0F0000:				// Line Printer Data Register
   438 				break;
   439 		}
   440 	} else if ((address >= 0xC00000) && (address <= 0xFFFFFF)) {
   441 		// I/O register space, zone B
   442 		switch (address & 0xF00000) {
   443 			case 0xC00000:				// Expansion slots
   444 			case 0xD00000:
   445 				switch (address & 0xFC0000) {
   446 					case 0xC00000:		// Expansion slot 0
   447 					case 0xC40000:		// Expansion slot 1
   448 					case 0xC80000:		// Expansion slot 2
   449 					case 0xCC0000:		// Expansion slot 3
   450 					case 0xD00000:		// Expansion slot 4
   451 					case 0xD40000:		// Expansion slot 5
   452 					case 0xD80000:		// Expansion slot 6
   453 					case 0xDC0000:		// Expansion slot 7
   454 						fprintf(stderr, "NOTE: WR%d to expansion card space, addr=0x%08X, data=0x%08X\n", bits, address, data);
   455 						handled = true;
   456 						break;
   457 				}
   458 				break;
   459 			case 0xE00000:				// HDC, FDC, MCR2 and RTC data bits
   460 			case 0xF00000:
   461 				switch (address & 0x070000) {
   462 					case 0x000000:		// [ef][08]xxxx ==> WD2010 hard disc controller
   463 						wd2010_write_reg(&state.hdc_ctx, (address >> 1) & 7, data);
   464 						handled = true;
   465 						break;
   466 					case 0x010000:		// [ef][19]xxxx ==> WD2797 floppy disc controller
   467 						/*ENFORCE_SIZE_W(bits, address, 16, "FDC REGISTERS");*/
   468 						wd2797_write_reg(&state.fdc_ctx, (address >> 1) & 3, data);
   469 						handled = true;
   470 						break;
   471 					case 0x020000:		// [ef][2a]xxxx ==> Miscellaneous Control Register 2
   472 						/*TODO: implement P5.1 second hard drive select*/
   473 						break;
   474 					case 0x030000:		// [ef][3b]xxxx ==> Real Time Clock data bits
   475 						break;
   476 					case 0x040000:		// [ef][4c]xxxx ==> General Control Register
   477 						switch (address & 0x077000) {
   478 							case 0x040000:		// [ef][4c][08]xxx ==> EE
   479 								// Error Enable. If =0, Level7 intrs and bus errors are masked.
   480 								ENFORCE_SIZE_W(bits, address, 16, "EE");
   481 								state.ee = ((data & 0x8000) == 0x8000);
   482 								handled = true;
   483 								break;
   484 							case 0x041000:		// [ef][4c][19]xxx ==> PIE
   485 								ENFORCE_SIZE_W(bits, address, 16, "PIE");
   486 								state.pie = ((data & 0x8000) == 0x8000);
   487 								handled = true;
   488 								break;
   489 							case 0x042000:		// [ef][4c][2A]xxx ==> BP
   490 								break;
   491 							case 0x043000:		// [ef][4c][3B]xxx ==> ROMLMAP
   492 								ENFORCE_SIZE_W(bits, address, 16, "ROMLMAP");
   493 								state.romlmap = ((data & 0x8000) == 0x8000);
   494 								handled = true;
   495 								break;
   496 							case 0x044000:		// [ef][4c][4C]xxx ==> L1 MODEM
   497 								ENFORCE_SIZE_W(bits, address, 16, "L1 MODEM");
   498 								break;
   499 							case 0x045000:		// [ef][4c][5D]xxx ==> L2 MODEM
   500 								ENFORCE_SIZE_W(bits, address, 16, "L2 MODEM");
   501 								break;
   502 							case 0x046000:		// [ef][4c][6E]xxx ==> D/N CONNECT
   503 								ENFORCE_SIZE_W(bits, address, 16, "D/N CONNECT");
   504 								break;
   505 							case 0x047000:		// [ef][4c][7F]xxx ==> Whole screen reverse video
   506 								ENFORCE_SIZE_W(bits, address, 16, "WHOLE SCREEN REVERSE VIDEO");
   507 								break;
   508 						}
   509 					case 0x050000:		// [ef][5d]xxxx ==> 8274
   510 						break;
   511 					case 0x060000:		// [ef][6e]xxxx ==> Control regs
   512 						switch (address & 0x07F000) {
   513 							default:
   514 								break;
   515 						}
   516 						break;
   517 					case 0x070000:		// [ef][7f]xxxx ==> 6850 Keyboard Controller
   518 						// TODO: figure out which sizes are valid (probably just 8 and 16)
   519 						// ENFORCE_SIZE_W(bits, address, 16, "KEYBOARD CONTROLLER");
   520 						if (bits == 8) {
   521 							printf("KBD WR %02X => %02X\n", (address >> 1) & 3, data);
   522 							keyboard_write(&state.kbd, (address >> 1) & 3, data);
   523 							handled = true;
   524 						} else if (bits == 16) {
   525 							printf("KBD WR %02X => %04X\n", (address >> 1) & 3, data);
   526 							keyboard_write(&state.kbd, (address >> 1) & 3, data >> 8);
   527 							handled = true;
   528 						}
   529 						break;
   530 				}
   531 		}
   532 	}
   534 	LOG_NOT_HANDLED_W(bits);
   535 }/*}}}*/
   537 uint32_t IoRead(uint32_t address, int bits)/*{{{*/
   538 {
   539 	bool handled = false;
   540 	uint32_t data = 0xFFFFFFFF;
   542 	if ((address >= 0x400000) && (address <= 0x7FFFFF)) {
   543 		// I/O register space, zone A
   544 		switch (address & 0x0F0000) {
   545 			case 0x010000:				// General Status Register
   546 				ENFORCE_SIZE_R(bits, address, 16, "GENSTAT");
   547 				return ((uint32_t)state.genstat << 16) + (uint32_t)state.genstat;
   548 				break;
   549 			case 0x030000:				// Bus Status Register 0
   550 				ENFORCE_SIZE_R(bits, address, 16, "BSR0");
   551 				return ((uint32_t)state.bsr0 << 16) + (uint32_t)state.bsr0;
   552 				break;
   553 			case 0x040000:				// Bus Status Register 1
   554 				ENFORCE_SIZE_R(bits, address, 16, "BSR1");
   555 				return ((uint32_t)state.bsr1 << 16) + (uint32_t)state.bsr1;
   556 				break;
   557 			case 0x050000:				// Phone status
   558 				ENFORCE_SIZE_R(bits, address, 8 | 16, "PHONE STATUS");
   559 				break;
   560 			case 0x060000:				// DMA Count
   561 				// TODO: U/OERR- is always inactive (bit set)... or should it be = DMAEN+?
   562 				// Bit 14 is always unused, so leave it set
   563 				ENFORCE_SIZE_R(bits, address, 16, "DMACOUNT");
   564 				return (state.dma_count & 0x3fff) | 0xC000;
   565 				break;
   566 			case 0x070000:				// Line Printer Status Register
   567 				data = 0x00120012;	// no parity error, no line printer error, no irqs from FDD or HDD
   568 				data |= wd2797_get_irq(&state.fdc_ctx) ? 0x00080008 : 0;
   569 				data |= wd2010_get_irq(&state.hdc_ctx) ? 0x00040004 : 0;
   570 				return data;
   571 				break;
   572 			case 0x080000:				// Real Time Clock
   573 				printf("READ NOTIMP: Realtime Clock\n");
   574 				break;
   575 			case 0x090000:				// Phone registers
   576 				switch (address & 0x0FF000) {
   577 					case 0x090000:		// Handset relay
   578 					case 0x098000:
   579 						break;
   580 					case 0x091000:		// Line select 2
   581 					case 0x099000:
   582 						break;
   583 					case 0x092000:		// Hook relay 1
   584 					case 0x09A000:
   585 						break;
   586 					case 0x093000:		// Hook relay 2
   587 					case 0x09B000:
   588 						break;
   589 					case 0x094000:		// Line 1 hold
   590 					case 0x09C000:
   591 						break;
   592 					case 0x095000:		// Line 2 hold
   593 					case 0x09D000:
   594 						break;
   595 					case 0x096000:		// Line 1 A-lead
   596 					case 0x09E000:
   597 						break;
   598 					case 0x097000:		// Line 2 A-lead
   599 					case 0x09F000:
   600 						break;
   601 				}
   602 				break;
   603 			case 0x0A0000:				// Miscellaneous Control Register -- write only!
   604 				handled = true;
   605 				break;
   606 			case 0x0B0000:				// TM/DIALWR
   607 				break;
   608 			case 0x0C0000:				// Clear Status Register -- write only!
   609 				handled = true;
   610 				break;
   611 			case 0x0D0000:				// DMA Address Register
   612 				break;
   613 			case 0x0E0000:				// Disk Control Register
   614 				break;
   615 			case 0x0F0000:				// Line Printer Data Register
   616 				break;
   617 		}
   618 	} else if ((address >= 0xC00000) && (address <= 0xFFFFFF)) {
   619 		// I/O register space, zone B
   620 		switch (address & 0xF00000) {
   621 			case 0xC00000:				// Expansion slots
   622 			case 0xD00000:
   623 				switch (address & 0xFC0000) {
   624 					case 0xC00000:		// Expansion slot 0
   625 					case 0xC40000:		// Expansion slot 1
   626 					case 0xC80000:		// Expansion slot 2
   627 					case 0xCC0000:		// Expansion slot 3
   628 					case 0xD00000:		// Expansion slot 4
   629 					case 0xD40000:		// Expansion slot 5
   630 					case 0xD80000:		// Expansion slot 6
   631 					case 0xDC0000:		// Expansion slot 7
   632 						fprintf(stderr, "NOTE: RD%d from expansion card space, addr=0x%08X\n", bits, address);
   633 						handled = true;
   634 						break;
   635 				}
   636 				break;
   637 			case 0xE00000:				// HDC, FDC, MCR2 and RTC data bits
   638 			case 0xF00000:
   639 				switch (address & 0x070000) {
   640 					case 0x000000:		// [ef][08]xxxx ==> WD1010 hard disc controller
   641 						return (wd2010_read_reg(&state.hdc_ctx, (address >> 1) & 7));
   643 						break;
   644 					case 0x010000:		// [ef][19]xxxx ==> WD2797 floppy disc controller
   645 						/*ENFORCE_SIZE_R(bits, address, 16, "FDC REGISTERS");*/
   646 						return wd2797_read_reg(&state.fdc_ctx, (address >> 1) & 3);
   647 						break;
   648 					case 0x020000:		// [ef][2a]xxxx ==> Miscellaneous Control Register 2
   649 						break;
   650 					case 0x030000:		// [ef][3b]xxxx ==> Real Time Clock data bits
   651 						break;
   652 					case 0x040000:		// [ef][4c]xxxx ==> General Control Register
   653 						switch (address & 0x077000) {
   654 							case 0x040000:		// [ef][4c][08]xxx ==> EE
   655 							case 0x041000:		// [ef][4c][19]xxx ==> PIE
   656 							case 0x042000:		// [ef][4c][2A]xxx ==> BP
   657 							case 0x043000:		// [ef][4c][3B]xxx ==> ROMLMAP
   658 							case 0x044000:		// [ef][4c][4C]xxx ==> L1 MODEM
   659 							case 0x045000:		// [ef][4c][5D]xxx ==> L2 MODEM
   660 							case 0x046000:		// [ef][4c][6E]xxx ==> D/N CONNECT
   661 								// All write-only registers... TODO: bus error?
   662 								handled = true;
   663 								break;
   664 							case 0x047000:		// [ef][4c][7F]xxx ==> Whole screen reverse video [FIXME: not in TRM]
   665 								break;
   666 						}
   667 						break;
   668 					case 0x050000:		// [ef][5d]xxxx ==> 8274
   669 						break;
   670 					case 0x060000:		// [ef][6e]xxxx ==> Control regs
   671 						switch (address & 0x07F000) {
   672 							default:
   673 								break;
   674 						}
   675 						break;
   676 					case 0x070000:		// [ef][7f]xxxx ==> 6850 Keyboard Controller
   677 						// TODO: figure out which sizes are valid (probably just 8 and 16)
   678 						//ENFORCE_SIZE_R(bits, address, 16, "KEYBOARD CONTROLLER");
   679 						{
   680 							if (bits == 8) {
   681 								return keyboard_read(&state.kbd, (address >> 1) & 3);
   682 							} else {
   683 								return keyboard_read(&state.kbd, (address >> 1) & 3) << 8;
   684 							}
   685 							return data;
   686 						}
   687 						break;
   688 				}
   689 		}
   690 	}
   692 	LOG_NOT_HANDLED_R(bits);
   694 	return data;
   695 }/*}}}*/
   698 /********************************************************
   699  * m68k memory read/write support functions for Musashi
   700  ********************************************************/
   702 /**
   703  * @brief Read M68K memory, 32-bit
   704  */
   705 uint32_t m68k_read_memory_32(uint32_t address)/*{{{*/
   706 {
   707 	uint32_t data = 0xFFFFFFFF;
   709 	// If ROMLMAP is set, force system to access ROM
   710 	if (!state.romlmap)
   711 		address |= 0x800000;
   713 	// Check access permissions
   714 	ACCESS_CHECK_RD(address, 32);
   716 	if ((address >= 0x800000) && (address <= 0xBFFFFF)) {
   717 		// ROM access
   718 		return RD32(state.rom, address, ROM_SIZE - 1);
   719 	} else if (address <= 0x3fffff) {
   720 		// RAM access
   721 		uint32_t newAddr = mapAddr(address, false);
   722 		if (newAddr <= 0x1fffff) {
   723 			return RD32(state.base_ram, newAddr, state.base_ram_size - 1);
   724 		} else {
   725 			if (newAddr <= (state.exp_ram_size + 0x200000 - 1))
   726 				return RD32(state.exp_ram, newAddr - 0x200000, state.exp_ram_size - 1);
   727 			else
   728 				return 0xffffffff;
   729 		}
   730 	} else if ((address >= 0x400000) && (address <= 0x7FFFFF)) {
   731 		// I/O register space, zone A
   732 		switch (address & 0x0F0000) {
   733 			case 0x000000:				// Map RAM access
   734 				if (address > 0x4007FF) fprintf(stderr, "NOTE: RD32 from MapRAM mirror, addr=0x%08X\n", address);
   735 				return RD32(state.map, address, 0x7FF);
   736 				break;
   737 			case 0x020000:				// Video RAM
   738 				if (address > 0x427FFF) fprintf(stderr, "NOTE: RD32 from VideoRAM mirror, addr=0x%08X\n", address);
   739 				return RD32(state.vram, address, 0x7FFF);
   740 				break;
   741 			default:
   742 				return IoRead(address, 32);
   743 		}
   744 	} else {
   745 		return IoRead(address, 32);
   746 	}
   748 	return data;
   749 }/*}}}*/
   751 /**
   752  * @brief Read M68K memory, 16-bit
   753  */
   754 uint32_t m68k_read_memory_16(uint32_t address)/*{{{*/
   755 {
   756 	uint16_t data = 0xFFFF;
   758 	// If ROMLMAP is set, force system to access ROM
   759 	if (!state.romlmap)
   760 		address |= 0x800000;
   762 	// Check access permissions
   763 	ACCESS_CHECK_RD(address, 16);
   765 	if ((address >= 0x800000) && (address <= 0xBFFFFF)) {
   766 		// ROM access
   767 		data = RD16(state.rom, address, ROM_SIZE - 1);
   768 	} else if (address <= 0x3fffff) {
   769 		// RAM access
   770 		uint32_t newAddr = mapAddr(address, false);
   771 		if (newAddr <= 0x1fffff) {
   772 			return RD16(state.base_ram, newAddr, state.base_ram_size - 1);
   773 		} else {
   774 			if (newAddr <= (state.exp_ram_size + 0x200000 - 1))
   775 				return RD16(state.exp_ram, newAddr - 0x200000, state.exp_ram_size - 1);
   776 			else
   777 				return 0xffff;
   778 		}
   779 	} else if ((address >= 0x400000) && (address <= 0x7FFFFF)) {
   780 		// I/O register space, zone A
   781 		switch (address & 0x0F0000) {
   782 			case 0x000000:				// Map RAM access
   783 				if (address > 0x4007FF) fprintf(stderr, "NOTE: RD16 from MapRAM mirror, addr=0x%08X\n", address);
   784 				data = RD16(state.map, address, 0x7FF);
   785 				break;
   786 			case 0x020000:				// Video RAM
   787 				if (address > 0x427FFF) fprintf(stderr, "NOTE: RD16 from VideoRAM mirror, addr=0x%08X\n", address);
   788 				data = RD16(state.vram, address, 0x7FFF);
   789 				break;
   790 			default:
   791 				data = IoRead(address, 16);
   792 		}
   793 	} else {
   794 		data = IoRead(address, 16);
   795 	}
   797 	return data;
   798 }/*}}}*/
   800 /**
   801  * @brief Read M68K memory, 8-bit
   802  */
   803 uint32_t m68k_read_memory_8(uint32_t address)/*{{{*/
   804 {
   805 	uint8_t data = 0xFF;
   807 	// If ROMLMAP is set, force system to access ROM
   808 	if (!state.romlmap)
   809 		address |= 0x800000;
   811 	// Check access permissions
   812 	ACCESS_CHECK_RD(address, 8);
   814 	if ((address >= 0x800000) && (address <= 0xBFFFFF)) {
   815 		// ROM access
   816 		data = RD8(state.rom, address, ROM_SIZE - 1);
   817 	} else if (address <= 0x3fffff) {
   818 		// RAM access
   819 		uint32_t newAddr = mapAddr(address, false);
   820 		if (newAddr <= 0x1fffff) {
   821 			return RD8(state.base_ram, newAddr, state.base_ram_size - 1);
   822 		} else {
   823 			if (newAddr <= (state.exp_ram_size + 0x200000 - 1))
   824 				return RD8(state.exp_ram, newAddr - 0x200000, state.exp_ram_size - 1);
   825 			else
   826 				return 0xff;
   827 		}
   828 	} else if ((address >= 0x400000) && (address <= 0x7FFFFF)) {
   829 		// I/O register space, zone A
   830 		switch (address & 0x0F0000) {
   831 			case 0x000000:				// Map RAM access
   832 				if (address > 0x4007FF) fprintf(stderr, "NOTE: RD8 from MapRAM mirror, addr=0x%08X\n", address);
   833 				data = RD8(state.map, address, 0x7FF);
   834 				break;
   835 			case 0x020000:				// Video RAM
   836 				if (address > 0x427FFF) fprintf(stderr, "NOTE: RD8 from VideoRAM mirror, addr=0x%08X\n", address);
   837 				data = RD8(state.vram, address, 0x7FFF);
   838 				break;
   839 			default:
   840 				data = IoRead(address, 8);
   841 		}
   842 	} else {
   843 		data = IoRead(address, 8);
   844 	}
   846 	return data;
   847 }/*}}}*/
   849 /**
   850  * @brief Write M68K memory, 32-bit
   851  */
   852 void m68k_write_memory_32(uint32_t address, uint32_t value)/*{{{*/
   853 {
   854 	// If ROMLMAP is set, force system to access ROM
   855 	if (!state.romlmap)
   856 		address |= 0x800000;
   858 	// Check access permissions
   859 	ACCESS_CHECK_WR(address, 32);
   861 	if ((address >= 0x800000) && (address <= 0xBFFFFF)) {
   862 		// ROM access
   863 	} else if (address <= 0x3FFFFF) {
   864 		// RAM access
   865 		uint32_t newAddr = mapAddr(address, true);
   866 		if (newAddr <= 0x1fffff)
   867 			WR32(state.base_ram, newAddr, state.base_ram_size - 1, value);
   868 		else
   869 			WR32(state.exp_ram, newAddr - 0x200000, state.exp_ram_size - 1, value);
   870 	} else if ((address >= 0x400000) && (address <= 0x7FFFFF)) {
   871 		// I/O register space, zone A
   872 		switch (address & 0x0F0000) {
   873 			case 0x000000:				// Map RAM access
   874 				if (address > 0x4007FF) fprintf(stderr, "NOTE: WR32 to MapRAM mirror, addr=0x%08X\n", address);
   875 				WR32(state.map, address, 0x7FF, value);
   876 				break;
   877 			case 0x020000:				// Video RAM
   878 				if (address > 0x427FFF) fprintf(stderr, "NOTE: WR32 to VideoRAM mirror, addr=0x%08X\n", address);
   879 				WR32(state.vram, address, 0x7FFF, value);
   880 				break;
   881 			default:
   882 				IoWrite(address, value, 32);
   883 		}
   884 	} else {
   885 		IoWrite(address, value, 32);
   886 	}
   887 }/*}}}*/
   889 /**
   890  * @brief Write M68K memory, 16-bit
   891  */
   892 void m68k_write_memory_16(uint32_t address, uint32_t value)/*{{{*/
   893 {
   894 	// If ROMLMAP is set, force system to access ROM
   895 	if (!state.romlmap)
   896 		address |= 0x800000;
   898 	// Check access permissions
   899 	ACCESS_CHECK_WR(address, 16);
   901 	if ((address >= 0x800000) && (address <= 0xBFFFFF)) {
   902 		// ROM access
   903 	} else if (address <= 0x3FFFFF) {
   904 		// RAM access
   905 		uint32_t newAddr = mapAddr(address, true);
   907 		if (newAddr <= 0x1fffff)
   908 			WR16(state.base_ram, newAddr, state.base_ram_size - 1, value);
   909 		else
   910 			WR16(state.exp_ram, newAddr - 0x200000, state.exp_ram_size - 1, value);
   911 	} else if ((address >= 0x400000) && (address <= 0x7FFFFF)) {
   912 		// I/O register space, zone A
   913 		switch (address & 0x0F0000) {
   914 			case 0x000000:				// Map RAM access
   915 				if (address > 0x4007FF) fprintf(stderr, "NOTE: WR16 to MapRAM mirror, addr=0x%08X, data=0x%04X\n", address, value);
   916 				WR16(state.map, address, 0x7FF, value);
   917 				break;
   918 			case 0x020000:				// Video RAM
   919 				if (address > 0x427FFF) fprintf(stderr, "NOTE: WR16 to VideoRAM mirror, addr=0x%08X, data=0x%04X\n", address, value);
   920 				WR16(state.vram, address, 0x7FFF, value);
   921 				break;
   922 			default:
   923 				IoWrite(address, value, 16);
   924 		}
   925 	} else {
   926 		IoWrite(address, value, 16);
   927 	}
   928 }/*}}}*/
   930 /**
   931  * @brief Write M68K memory, 8-bit
   932  */
   933 void m68k_write_memory_8(uint32_t address, uint32_t value)/*{{{*/
   934 {
   935 	// If ROMLMAP is set, force system to access ROM
   936 	if (!state.romlmap)
   937 		address |= 0x800000;
   939 	// Check access permissions
   940 	ACCESS_CHECK_WR(address, 8);
   942 	if ((address >= 0x800000) && (address <= 0xBFFFFF)) {
   943 		// ROM access (read only!)
   944 	} else if (address <= 0x3FFFFF) {
   945 		// RAM access
   946 		uint32_t newAddr = mapAddr(address, true);
   947 		if (newAddr <= 0x1fffff)
   948 			WR8(state.base_ram, newAddr, state.base_ram_size - 1, value);
   949 		else
   950 			WR8(state.exp_ram, newAddr - 0x200000, state.exp_ram_size - 1, value);
   951 	} else if ((address >= 0x400000) && (address <= 0x7FFFFF)) {
   952 		// I/O register space, zone A
   953 		switch (address & 0x0F0000) {
   954 			case 0x000000:				// Map RAM access
   955 				if (address > 0x4007FF) fprintf(stderr, "NOTE: WR8 to MapRAM mirror, addr=0x%08X, data=0x%04X\n", address, value);
   956 				WR8(state.map, address, 0x7FF, value);
   957 				break;
   958 			case 0x020000:				// Video RAM
   959 				if (address > 0x427FFF) fprintf(stderr, "NOTE: WR8 to VideoRAM mirror, addr=0x%08X, data=0x%04X\n", address, value);
   960 				WR8(state.vram, address, 0x7FFF, value);
   961 				break;
   962 			default:
   963 				IoWrite(address, value, 8);
   964 		}
   965 	} else {
   966 		IoWrite(address, value, 8);
   967 	}
   968 }/*}}}*/
   971 // for the disassembler
   972 uint32_t m68k_read_disassembler_32(uint32_t addr) { return m68k_read_memory_32(addr); }
   973 uint32_t m68k_read_disassembler_16(uint32_t addr) { return m68k_read_memory_16(addr); }
   974 uint32_t m68k_read_disassembler_8 (uint32_t addr) { return m68k_read_memory_8 (addr); }