src/memory.c

Fri, 12 Apr 2013 16:26:25 +0100

author
Philip Pemberton <philpem@philpem.me.uk>
date
Fri, 12 Apr 2013 16:26:25 +0100
branch
experimental_memory_mapper_v2
changeset 144
609707511166
parent 141
8460d432606f
permissions
-rw-r--r--

Don't set PS1 if there is a level-7 interrupt or bus error

PS1 should only be set if the page was originally present (PS1 or PS0 set). If
PS0 and PS1 are clear (page not present) then do NOT set PS1.

Once again the TRM is blatantly and spectacularly wrong...

     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 // The value which will be returned if the CPU attempts to read from empty memory
    12 // TODO (FIXME?) - need to figure out if R/W ops wrap around. This seems to appease the UNIX kernel and P4TEST.
    13 #define EMPTY 0xFFFFFFFFUL
    14 //#define EMPTY 0x55555555UL
    15 //#define EMPTY 0x00000000UL
    17 /******************
    18  * Memory mapping
    19  ******************/
    21 /// Set a page bit
    22 #define MAP_SET_PAGEBIT(addr, bit) state.map[(MAP_ADDR_TO_PAGE(addr))*2] |=  ((uint8_t)bit << 2)
    23 /// Clear a page bit
    24 #define MAP_CLR_PAGEBIT(addr, bit) state.map[(MAP_ADDR_TO_PAGE(addr))*2] &= ~((uint8_t)bit << 2)
    27 /********************************************************
    28  * m68k memory read/write support functions for Musashi
    29  ********************************************************/
    31 /**
    32  * @brief	Check memory access permissions for a write operation.
    33  * @note	This used to be a single macro (merged with ACCESS_CHECK_RD), but
    34  * 			gcc throws warnings when you have a return-with-value in a void
    35  * 			function, even if the return-with-value is completely unreachable.
    36  * 			Similarly it doesn't like it if you have a return without a value
    37  * 			in a non-void function, even if it's impossible to ever reach the
    38  * 			return-with-no-value. UGH!
    39  */
    40 /*{{{ macro: ACCESS_CHECK_WR(address, bits)*/
    41 #define ACCESS_CHECK_WR(address, bits)								\
    42 	do {															\
    43 		if (access_check_cpu(address, bits, true)) {				\
    44 			return;													\
    45 		}															\
    46 	} while (0)
    47 /*}}}*/
    49 /**
    50  * @brief Check memory access permissions for a read operation.
    51  * @note	This used to be a single macro (merged with ACCESS_CHECK_WR), but
    52  * 			gcc throws warnings when you have a return-with-value in a void
    53  * 			function, even if the return-with-value is completely unreachable.
    54  * 			Similarly it doesn't like it if you have a return without a value
    55  * 			in a non-void function, even if it's impossible to ever reach the
    56  * 			return-with-no-value. UGH!
    57  */
    58 /*{{{ macro: ACCESS_CHECK_RD(address, bits)*/
    59 #define ACCESS_CHECK_RD(address, bits)								\
    60 	do {															\
    61 		if (access_check_cpu(address, bits, false)) {				\
    62 			if (bits == 32)											\
    63 				return EMPTY & 0xFFFFFFFF;							\
    64 			else													\
    65 				return EMPTY & ((1UL << bits)-1);					\
    66 		}															\
    67 	} while (0)
    68 /*}}}*/
    71 /**
    72  * Update the page bits for a given memory address
    73  *
    74  * @param	addr	Memory address being accessed
    75  * @param	l7intr	Set to <i>true</i> if a level-seven interrupt has been
    76  * 					signalled (even if <b>ENABLE ERROR</b> isn't set).
    77  * @param	write	Set to <i>true</i> if the address is being written to.
    78  */
    79 static void update_page_bits(uint32_t addr, bool l7intr, bool write)
    80 {
    81 	bool ps0_state = false;
    83 	// Don't try and update pagebits for non-RAM addresses
    84 	if (addr > 0x3FFFFF)
    85 		return;
    87 	if (l7intr) {
    88 //		if (!(MAP_PAGEBITS(addr) & PAGE_BIT_PS0)) {
    89 			// FIXME FUCKUP The ruddy TRM is wrong AGAIN! If above line is uncommented, Really Bad Things Happen.
    90 		if ((MAP_PAGEBITS(addr) & PAGE_BIT_PS0)) {
    91 			// Level 7 interrupt, PS0 set, PS1 don't-care. Set PS0.
    92 			ps0_state = true;
    93 		}
    94 	} else {
    95 		// No L7 interrupt
    96 		if ((write && !(MAP_PAGEBITS(addr) & PAGE_BIT_PS1) &&  (MAP_PAGEBITS(addr) & PAGE_BIT_PS0)) ||
    97 			(write &&  (MAP_PAGEBITS(addr) & PAGE_BIT_PS1) && !(MAP_PAGEBITS(addr) & PAGE_BIT_PS0)) ||
    98 			(          (MAP_PAGEBITS(addr) & PAGE_BIT_PS1) &&  (MAP_PAGEBITS(addr) & PAGE_BIT_PS0)))  /* NOTE -- Once again, this case was missing from the PAL equations in the TRM... */
    99 		{
   100 			// No L7 interrupt, PS[1:0] = 0b01, write
   101 			// No L7 interrupt, PS[1:0] = 0b10, write
   102 			ps0_state = true;
   103 		}
   104 	}
   106 #ifdef MAPRAM_BIT_TEST
   107 	LOG("Starting Mapram Bit Test");
   108 	state.map[0] = state.map[1] = 0;
   109 	LOG("Start   = %04X %02X", MAPRAM_ADDR(0), MAP_PAGEBITS(0));
   110 	MAP_SET_PAGEBIT(0, PAGE_BIT_WE);
   111 	LOG("Set WE  = %04X %02X", MAPRAM_ADDR(0), MAP_PAGEBITS(0));
   112 	MAP_SET_PAGEBIT(0, PAGE_BIT_PS1);
   113 	LOG("Set PS1 = %04X %02X", MAPRAM_ADDR(0), MAP_PAGEBITS(0));
   114 	MAP_SET_PAGEBIT(0, PAGE_BIT_PS0);
   115 	LOG("Set PS0 = %04X %02X", MAPRAM_ADDR(0), MAP_PAGEBITS(0));
   117 	MAP_CLR_PAGEBIT(0, PAGE_BIT_WE);
   118 	LOG("Clr WE  = %04X %02X", MAPRAM_ADDR(0), MAP_PAGEBITS(0));
   119 	MAP_CLR_PAGEBIT(0, PAGE_BIT_PS1);
   120 	LOG("Clr PS1 = %04X %02X", MAPRAM_ADDR(0), MAP_PAGEBITS(0));
   121 	MAP_CLR_PAGEBIT(0, PAGE_BIT_PS0);
   122 	LOG("Clr PS0 = %04X %02X", MAPRAM_ADDR(0), MAP_PAGEBITS(0));
   123 	exit(-1);
   124 #endif
   126 	if (!l7intr) {
   127 		// PS1 is always set on access if no fault
   128 		MAP_SET_PAGEBIT(addr, PAGE_BIT_PS1);
   130 		// Update PS0
   131 		if (ps0_state) {
   132 			MAP_SET_PAGEBIT(addr, PAGE_BIT_PS0);
   133 		} else {
   134 			MAP_CLR_PAGEBIT(addr, PAGE_BIT_PS0);
   135 		}
   136 	}
   138 #ifdef MAPRAM_DEBUG_MESSAGES
   139 	uint16_t new_pagebit2 = MAP_PAGEBITS(addr);
   140 	switch (addr) {
   141 		case 0x000000:
   142 		case 0x001000:
   143 		case 0x002000:
   144 		case 0x003000:
   145 		case 0x004000:
   146 		case 0x033000:
   147 		case 0x034000:
   148 		case 0x035000:
   149 			LOG("Addr %08X %s MapNew %04X Page %04X -- Pagebit update -- ps0 %d, old %s%s => %s%s => %s%s",
   150 					addr,
   151 					write ? "Wr" : "Rd",
   152 					MAPRAM_ADDR(addr),
   153 					MAP_ADDR_TO_PAGE(addr),
   154 					ps0_state,
   155 					old_pagebits & PAGE_BIT_PS0 ? "PS0" : "",
   156 					old_pagebits & PAGE_BIT_PS1 ? "PS1" : "",
   157 					new_pagebit1 & PAGE_BIT_PS0 ? "PS0" : "",
   158 					new_pagebit1 & PAGE_BIT_PS1 ? "PS1" : "",
   159 					new_pagebit2 & PAGE_BIT_PS0 ? "PS0" : "",
   160 					new_pagebit2 & PAGE_BIT_PS1 ? "PS1" : ""
   161 			   );
   162 		default:
   163 			break;
   164 	}
   165 #endif // MAPRAM_DEBUG_MESSAGES
   166 }
   168 bool access_check_dma(void)
   169 {
   170 	// TODO FIXME BUGBUG Sanity check - Make sure DMAC is only accessing RAM addresses
   172 	// DMA access check -- make sure the page is mapped in
   173 	if (!(MAP_PAGEBITS(state.dma_address) & PAGE_BIT_PS0) && !(MAP_PAGEBITS(state.dma_address) & PAGE_BIT_PS1)) {
   174 		// DMA access to page which is not mapped in.
   175 		// Level 7 interrupt, page fault, DMA invoked
   176 		state.genstat = 0xABFF
   177 			| (state.dma_reading ? 0x4000 : 0)
   178 			| (state.pie ? 0x0400 : 0);
   180 		// XXX: Check all this stuff.
   181 		state.bsr0 = 0x3C00;
   182 		state.bsr0 |= (state.dma_address >> 16);
   183 		state.bsr1 = state.dma_address & 0xffff;
   185 		// Update page bits for this transfer
   186 		update_page_bits(state.dma_address, true, !state.dma_reading);
   188 		// XXX: is this right?
   189 		// Fire a Level 7 interrupt
   190 		/*if (state.ee)*/ m68k_set_irq(7);
   192 		LOG("BUS ERROR FROM DMA: genstat=%04X, bsr0=%04X, bsr1=%04X\n", state.genstat, state.bsr0, state.bsr1);
   193 		return false;
   194 	} else {
   195 		// No errors. Just update the page bits.
   196 		update_page_bits(state.dma_address, false, !state.dma_reading);
   197 		return true;
   198 	}
   199 }
   201 /**
   202  * Check memory access permissions for a CPU memory access.
   203  *
   204  * @param	addr	Virtual memory address being accessed (from CPU address bus).
   205  * @param	bits	Word size of this transfer (8, 16 or 32 bits).
   206  * @param	write	<i>true</i> if this is a write operation, <i>false</i> if it is a read operation.
   207  * @return	<i>true</i> if the access was denied and a level-7 interrupt and/or bus error raised.
   208  * 			<i>false</i> if the access was allowed.
   209  */
   210 bool access_check_cpu(uint32_t addr, int bits, bool write)
   211 {
   212 	bool supervisor = (m68k_get_reg(NULL, M68K_REG_SR) & 0x2000);
   213 	bool fault = false;
   215 	// TODO FIXME BUGBUG? Do we need to check for supervisor access here?
   216 	if ((addr >= 0x000000) && (addr <= 0x3FFFFF) && !(MAP_PAGEBITS(addr) & PAGE_BIT_PS1) && !(MAP_PAGEBITS(addr) & PAGE_BIT_PS0)) {
   217 		// (A) Page Fault -- user access to page which is not mapped in
   218 		// Level 7 Interrupt, Bus Error, regs=PAGEFAULT
   219 		if (write) {
   220 			state.genstat = 0x8BFF | (state.pie ? 0x0400 : 0);
   221 		} else {
   222 			state.genstat = 0xCBFF | (state.pie ? 0x0400 : 0);
   223 		}
   224 		fault = true;
   225 	} else if (!supervisor && (addr >= 0x000000) && (addr <= 0x07FFFF)) {
   226 		// (B) User attempted to access the kernel
   227 		// Level 7 Interrupt, Bus Error, regs=KERNEL
   228 		if (write) {
   229 			// XXX: BUGBUG? Is this correct?
   230 			state.genstat = 0x9BFF | (state.pie ? 0x0400 : 0);
   231 		} else {
   232 			state.genstat = 0xDBFF | (state.pie ? 0x0400 : 0);
   233 		}
   234 		fault = true;
   235 	} else if (!supervisor && write && (addr >= 0x000000) && (addr <= 0x3FFFFF) && !(MAP_PAGEBITS(addr) & PAGE_BIT_WE)) {
   236 		// (C) User attempted to write to a page which is not write enabled
   237 		// Level 7 Interrupt, Bus Error, regs=WRITE_EN
   238 		if (write) {
   239 			// XXX: BUGBUG? Is this correct?
   240 			state.genstat = 0x9BFF | (state.pie ? 0x0400 : 0);
   241 		} else {
   242 			state.genstat = 0xDBFF | (state.pie ? 0x0400 : 0);
   243 		}
   244 		fault = true;
   245 	} else if (!supervisor && (addr >= 0x400000) && (addr <= 0xFFFFFF)) {
   246 		// (D) UIE - user I/O exception
   247 		// Bus Error only, regs=UIE
   248 		if (write) {
   249 			state.genstat = 0x9AFF | (state.pie ? 0x0400 : 0);
   250 		} else {
   251 			state.genstat = 0xDAFF | (state.pie ? 0x0400 : 0);
   252 		}
   253 		fault = true;
   254 	}
   256 	unsigned char pagebits_preup = MAP_PAGEBITS(addr & 0x3fffff);
   258 	// Update the page bits first
   259 	update_page_bits(addr, fault, write);
   261 	if (fault) {
   262 		if (bits >= 16)
   263 			state.bsr0 = 0x7C00;
   264 		else
   265 			state.bsr0 = (addr & 1) ? 0x7E00 : 0x7D00;
   266 		// FIXME? Physical or virtual address here?
   267 		state.bsr0 |= (addr >> 16);
   268 		state.bsr1 = addr & 0xffff;
   270 		LOG("CPU Bus Error or L7Intr while %s, vaddr %08X, map %08X, pagebits 0x%02X=>0x%02X bsr0=%04X bsr1=%04X genstat=%04X", 
   271 				write ? "writing" : "reading", addr,
   272 				MAPRAM_ADDR(addr & 0x3fffff),
   273 				pagebits_preup,
   274 				MAP_PAGEBITS(addr & 0x3fffff),
   275 				state.bsr0, state.bsr1, state.genstat);
   277 		// FIXME? BUGBUG? Does EE disable one or both of these?
   278 		// /*if (state.ee)*/ m68k_set_irq(7);
   279 		/*if (state.ee)*/ m68k_pulse_bus_error();
   280 	}
   282 	return fault;
   283 }
   285 // Logging macros
   286 #define LOG_NOT_HANDLED_R(bits)															\
   287 	if (!handled) fprintf(stderr, "unhandled read%02d, addr=0x%08X\n", bits, address);
   289 #define LOG_NOT_HANDLED_W(bits)															\
   290 	if (!handled) fprintf(stderr, "unhandled write%02d, addr=0x%08X, data=0x%08X\n", bits, address, data);
   292 /********************************************************
   293  * I/O read/write functions
   294  ********************************************************/
   296 /**
   297  * Issue a warning if a read operation is made with an invalid size
   298  */
   299 inline static void ENFORCE_SIZE(int bits, uint32_t address, bool read, int allowed, char *regname)
   300 {
   301 	assert((bits == 8) || (bits == 16) || (bits == 32));
   302 	if ((bits & allowed) == 0) {
   303 		LOG("WARNING: %s 0x%08X (%s) with invalid size %d!\n", read ? "read from" : "write to", address, regname, bits);
   304 	}
   305 }
   307 inline static void ENFORCE_SIZE_R(int bits, uint32_t address, int allowed, char *regname)
   308 {
   309 	ENFORCE_SIZE(bits, address, true, allowed, regname);
   310 }
   312 inline static void ENFORCE_SIZE_W(int bits, uint32_t address, int allowed, char *regname)
   313 {
   314 	ENFORCE_SIZE(bits, address, false, allowed, regname);
   315 }
   317 void IoWrite(uint32_t address, uint32_t data, int bits)/*{{{*/
   318 {
   319 	bool handled = false;
   321 	if ((address >= 0x400000) && (address <= 0x7FFFFF)) {
   322 		// I/O register space, zone A
   323 		switch (address & 0x0F0000) {
   324 			case 0x010000:				// General Status Register
   325 				if (bits == 16)
   326 					state.genstat = (data & 0xffff);
   327 				else if (bits == 8) {
   328 					if (address & 0)
   329 						state.genstat = data;
   330 					else
   331 						state.genstat = data << 8;
   332 				}
   333 				handled = true;
   334 				break;
   335 			case 0x030000:				// Bus Status Register 0
   336 				break;
   337 			case 0x040000:				// Bus Status Register 1
   338 				break;
   339 			case 0x050000:				// Phone status
   340 				break;
   341 			case 0x060000:				// DMA Count
   342 				ENFORCE_SIZE_W(bits, address, 16, "DMACOUNT");
   343 				state.dma_count = (data & 0x3FFF);
   344 				state.idmarw = ((data & 0x4000) == 0x4000);
   345 				state.dmaen = ((data & 0x8000) == 0x8000);
   346 				// This handles the "dummy DMA transfer" mentioned in the docs
   347 				// disabled because it causes the floppy test to fail
   348 #if 0
   349 				if (!state.idmarw){
   350 					if (access_check_dma(true)){
   351 						uint32_t newAddr = mapAddr(state.dma_address, true);
   352 						// RAM access
   353 						if (newAddr <= 0x1fffff)
   354 							WR16(state.base_ram, newAddr, state.base_ram_size - 1, 0xFF);
   355 						else if (address <= 0x3FFFFF)
   356 							WR16(state.exp_ram, newAddr - 0x200000, state.exp_ram_size - 1, 0xFF);
   357 					}
   358 				}
   359 #endif
   360 				state.dma_count++;
   361 				handled = true;
   362 				break;
   363 			case 0x070000:				// Line Printer Status Register
   364 				break;
   365 			case 0x080000:				// Real Time Clock
   366 				LOGS("REAL TIME CLOCK WRITE");
   367 				break;
   368 			case 0x090000:				// Phone registers
   369 				switch (address & 0x0FF000) {
   370 					case 0x090000:		// Handset relay
   371 					case 0x098000:
   372 						break;
   373 					case 0x091000:		// Line select 2
   374 					case 0x099000:
   375 						break;
   376 					case 0x092000:		// Hook relay 1
   377 					case 0x09A000:
   378 						break;
   379 					case 0x093000:		// Hook relay 2
   380 					case 0x09B000:
   381 						break;
   382 					case 0x094000:		// Line 1 hold
   383 					case 0x09C000:
   384 						break;
   385 					case 0x095000:		// Line 2 hold
   386 					case 0x09D000:
   387 						break;
   388 					case 0x096000:		// Line 1 A-lead
   389 					case 0x09E000:
   390 						break;
   391 					case 0x097000:		// Line 2 A-lead
   392 					case 0x09F000:
   393 						break;
   394 				}
   395 				break;
   396 			case 0x0A0000:				// Miscellaneous Control Register
   397 				ENFORCE_SIZE_W(bits, address, 16, "MISCCON");
   398 				// TODO: handle the ctrl bits properly
   399 				if (data & 0x8000){
   400 					state.timer_enabled = 1;
   401 				}else{
   402 					state.timer_enabled = 0;
   403 					state.timer_asserted = 0;
   404 				}
   405 				state.dma_reading = (data & 0x4000);
   406 				if (state.leds != ((~data & 0xF00) >> 8)) {
   407 					state.leds = (~data & 0xF00) >> 8;
   408 #ifdef SHOW_LEDS
   409 					printf("LEDs: %s %s %s %s\n",
   410 							(state.leds & 8) ? "R" : "-",
   411 							(state.leds & 4) ? "G" : "-",
   412 							(state.leds & 2) ? "Y" : "-",
   413 							(state.leds & 1) ? "R" : "-");
   414 #endif
   415 				}
   416 				handled = true;
   417 				break;
   418 			case 0x0B0000:				// TM/DIALWR
   419 				break;
   420 			case 0x0C0000:				// Clear Status Register
   421 				state.genstat = 0xFFFF;
   422 				state.bsr0 = 0xFFFF;
   423 				state.bsr1 = 0xFFFF;
   424 				handled = true;
   425 				break;
   426 			case 0x0D0000:				// DMA Address Register
   427 				if (address & 0x004000) {
   428 					// A14 high -- set most significant bits
   429 					state.dma_address = (state.dma_address & 0x1fe) | ((address & 0x3ffe) << 8);
   430 				} else {
   431 					// A14 low -- set least significant bits
   432 					state.dma_address = (state.dma_address & 0x3ffe00) | (address & 0x1fe);
   433 				}
   434 				handled = true;
   435 				break;
   436 			case 0x0E0000:				// Disk Control Register
   437 				{
   438 					bool fd_selected;
   439 					bool hd_selected;
   440 					ENFORCE_SIZE_W(bits, address, 16, "DISKCON");
   441 					// B7 = FDD controller reset
   442 					if ((data & 0x80) == 0) wd2797_reset(&state.fdc_ctx);
   443 					// B6 = drive 0 select
   444 					fd_selected = (data & 0x40) != 0;
   445 					// B5 = motor enable -- TODO
   446 					// B4 = HDD controller reset
   447 					if ((data & 0x10) == 0) wd2010_reset(&state.hdc_ctx);
   448 					// B3 = HDD0 select
   449 					hd_selected = (data & 0x08) != 0;
   450 					// B2,1,0 = HDD0 head select -- TODO?
   451 					if (hd_selected && !state.hd_selected){
   452 						state.fd_selected = false;
   453 						state.hd_selected = true;
   454 					}else if (fd_selected && !state.fd_selected){
   455 						state.hd_selected = false;
   456 						state.fd_selected = true;
   457 					}
   458 					handled = true;
   459 					break;
   460 				}
   461 			case 0x0F0000:				// Line Printer Data Register
   462 				break;
   463 		}
   464 	} else if ((address >= 0xC00000) && (address <= 0xFFFFFF)) {
   465 		// I/O register space, zone B
   466 		switch (address & 0xF00000) {
   467 			case 0xC00000:				// Expansion slots
   468 			case 0xD00000:
   469 				switch (address & 0xFC0000) {
   470 					case 0xC00000:		// Expansion slot 0
   471 					case 0xC40000:		// Expansion slot 1
   472 					case 0xC80000:		// Expansion slot 2
   473 					case 0xCC0000:		// Expansion slot 3
   474 					case 0xD00000:		// Expansion slot 4
   475 					case 0xD40000:		// Expansion slot 5
   476 					case 0xD80000:		// Expansion slot 6
   477 					case 0xDC0000:		// Expansion slot 7
   478 						fprintf(stderr, "NOTE: WR%d to expansion card space, addr=0x%08X, data=0x%08X\n", bits, address, data);
   479 						handled = true;
   480 						break;
   481 				}
   482 				break;
   483 			case 0xE00000:				// HDC, FDC, MCR2 and RTC data bits
   484 			case 0xF00000:
   485 				switch (address & 0x070000) {
   486 					case 0x000000:		// [ef][08]xxxx ==> WD2010 hard disc controller
   487 						wd2010_write_reg(&state.hdc_ctx, (address >> 1) & 7, data);
   488 						handled = true;
   489 						break;
   490 					case 0x010000:		// [ef][19]xxxx ==> WD2797 floppy disc controller
   491 						/*ENFORCE_SIZE_W(bits, address, 16, "FDC REGISTERS");*/
   492 						wd2797_write_reg(&state.fdc_ctx, (address >> 1) & 3, data);
   493 						handled = true;
   494 						break;
   495 					case 0x020000:		// [ef][2a]xxxx ==> Miscellaneous Control Register 2
   496 						// MCR2 - UNIX PC Rev. P5.1 HDD head select b3 and potential HDD#2 select
   497 						wd2010_write_reg(&state.hdc_ctx, UNIXPC_REG_MCR2, data);
   498 						handled = true;
   499 						break;
   500 					case 0x030000:		// [ef][3b]xxxx ==> Real Time Clock data bits
   501 						LOGS("REAL TIME CLOCK DATA WRITE");
   502 						break;
   503 					case 0x040000:		// [ef][4c]xxxx ==> General Control Register
   504 						switch (address & 0x077000) {
   505 							case 0x040000:		// [ef][4c][08]xxx ==> EE
   506 								// Error Enable. If =0, Level7 intrs and bus errors are masked.
   507 								ENFORCE_SIZE_W(bits, address, 16, "EE");
   508 								state.ee = ((data & 0x8000) == 0x8000);
   509 								handled = true;
   510 								break;
   511 							case 0x041000:		// [ef][4c][19]xxx ==> PIE
   512 								ENFORCE_SIZE_W(bits, address, 16, "PIE");
   513 								state.pie = ((data & 0x8000) == 0x8000);
   514 								handled = true;
   515 								break;
   516 							case 0x042000:		// [ef][4c][2A]xxx ==> BP
   517 								break;
   518 							case 0x043000:		// [ef][4c][3B]xxx ==> ROMLMAP
   519 								ENFORCE_SIZE_W(bits, address, 16, "ROMLMAP");
   520 								state.romlmap = ((data & 0x8000) == 0x8000);
   521 								handled = true;
   522 								break;
   523 							case 0x044000:		// [ef][4c][4C]xxx ==> L1 MODEM
   524 								ENFORCE_SIZE_W(bits, address, 16, "L1 MODEM");
   525 								break;
   526 							case 0x045000:		// [ef][4c][5D]xxx ==> L2 MODEM
   527 								ENFORCE_SIZE_W(bits, address, 16, "L2 MODEM");
   528 								break;
   529 							case 0x046000:		// [ef][4c][6E]xxx ==> D/N CONNECT
   530 								ENFORCE_SIZE_W(bits, address, 16, "D/N CONNECT");
   531 								break;
   532 							case 0x047000:		// [ef][4c][7F]xxx ==> Whole screen reverse video
   533 								ENFORCE_SIZE_W(bits, address, 16, "WHOLE SCREEN REVERSE VIDEO");
   534 								break;
   535 						}
   536 					case 0x050000:		// [ef][5d]xxxx ==> 8274
   537 						break;
   538 					case 0x060000:		// [ef][6e]xxxx ==> Control regs
   539 						switch (address & 0x07F000) {
   540 							default:
   541 								break;
   542 						}
   543 						break;
   544 					case 0x070000:		// [ef][7f]xxxx ==> 6850 Keyboard Controller
   545 						// TODO: figure out which sizes are valid (probably just 8 and 16)
   546 						// ENFORCE_SIZE_W(bits, address, 16, "KEYBOARD CONTROLLER");
   547 						if (bits == 8) {
   548 #ifdef LOG_KEYBOARD_WRITES
   549 							LOG("KBD WR %02X => %02X\n", (address >> 1) & 3, data);
   550 #endif
   551 							keyboard_write(&state.kbd, (address >> 1) & 3, data);
   552 							handled = true;
   553 						} else if (bits == 16) {
   554 #ifdef LOG_KEYBOARD_WRITES
   555 							LOG("KBD WR %02X => %04X\n", (address >> 1) & 3, data);
   556 #endif
   557 							keyboard_write(&state.kbd, (address >> 1) & 3, data >> 8);
   558 							handled = true;
   559 						}
   560 						break;
   561 				}
   562 		}
   563 	}
   565 	LOG_NOT_HANDLED_W(bits);
   566 }/*}}}*/
   568 uint32_t IoRead(uint32_t address, int bits)/*{{{*/
   569 {
   570 	bool handled = false;
   571 	uint32_t data = EMPTY & 0xFFFFFFFF;
   573 	if ((address >= 0x400000) && (address <= 0x7FFFFF)) {
   574 		// I/O register space, zone A
   575 		switch (address & 0x0F0000) {
   576 			case 0x010000:				// General Status Register
   577 				/* ENFORCE_SIZE_R(bits, address, 16, "GENSTAT"); */
   578 				if (bits == 32) {
   579 					return ((uint32_t)state.genstat << 16) + (uint32_t)state.genstat;
   580 				} else if (bits == 16) {
   581 					return (uint16_t)state.genstat;
   582 				} else {
   583 					return (uint8_t)(state.genstat & 0xff);
   584 				}
   585 				break;
   586 			case 0x030000:				// Bus Status Register 0
   587 				ENFORCE_SIZE_R(bits, address, 16, "BSR0");
   588 				return ((uint32_t)state.bsr0 << 16) + (uint32_t)state.bsr0;
   589 				break;
   590 			case 0x040000:				// Bus Status Register 1
   591 				ENFORCE_SIZE_R(bits, address, 16, "BSR1");
   592 				return ((uint32_t)state.bsr1 << 16) + (uint32_t)state.bsr1;
   593 				break;
   594 			case 0x050000:				// Phone status
   595 				ENFORCE_SIZE_R(bits, address, 8 | 16, "PHONE STATUS");
   596 				break;
   597 			case 0x060000:				// DMA Count
   598 				// TODO: U/OERR- is always inactive (bit set)... or should it be = DMAEN+?
   599 				// Bit 14 is always unused, so leave it set
   600 				ENFORCE_SIZE_R(bits, address, 16, "DMACOUNT");
   601 				return (state.dma_count & 0x3fff) | 0xC000;
   602 				break;
   603 			case 0x070000:				// Line Printer Status Register
   604 				data = 0x00120012;	// no parity error, no line printer error, no irqs from FDD or HDD
   605 				data |= wd2797_get_irq(&state.fdc_ctx) ? 0x00080008 : 0;
   606 				data |= wd2010_get_irq(&state.hdc_ctx) ? 0x00040004 : 0;
   607 				return data;
   608 				break;
   609 			case 0x080000:				// Real Time Clock
   610 				LOGS("REAL TIME CLOCK READ");
   611 				break;
   612 			case 0x090000:				// Phone registers
   613 				switch (address & 0x0FF000) {
   614 					case 0x090000:		// Handset relay
   615 					case 0x098000:
   616 						break;
   617 					case 0x091000:		// Line select 2
   618 					case 0x099000:
   619 						break;
   620 					case 0x092000:		// Hook relay 1
   621 					case 0x09A000:
   622 						break;
   623 					case 0x093000:		// Hook relay 2
   624 					case 0x09B000:
   625 						break;
   626 					case 0x094000:		// Line 1 hold
   627 					case 0x09C000:
   628 						break;
   629 					case 0x095000:		// Line 2 hold
   630 					case 0x09D000:
   631 						break;
   632 					case 0x096000:		// Line 1 A-lead
   633 					case 0x09E000:
   634 						break;
   635 					case 0x097000:		// Line 2 A-lead
   636 					case 0x09F000:
   637 						break;
   638 				}
   639 				break;
   640 			case 0x0A0000:				// Miscellaneous Control Register -- write only!
   641 				handled = true;
   642 				break;
   643 			case 0x0B0000:				// TM/DIALWR
   644 				break;
   645 			case 0x0C0000:				// Clear Status Register -- write only!
   646 				handled = true;
   647 				break;
   648 			case 0x0D0000:				// DMA Address Register
   649 				break;
   650 			case 0x0E0000:				// Disk Control Register
   651 				break;
   652 			case 0x0F0000:				// Line Printer Data Register
   653 				break;
   654 		}
   655 	} else if ((address >= 0xC00000) && (address <= 0xFFFFFF)) {
   656 		// I/O register space, zone B
   657 		switch (address & 0xF00000) {
   658 			case 0xC00000:				// Expansion slots
   659 			case 0xD00000:
   660 				switch (address & 0xFC0000) {
   661 					case 0xC00000:		// Expansion slot 0
   662 					case 0xC40000:		// Expansion slot 1
   663 					case 0xC80000:		// Expansion slot 2
   664 					case 0xCC0000:		// Expansion slot 3
   665 					case 0xD00000:		// Expansion slot 4
   666 					case 0xD40000:		// Expansion slot 5
   667 					case 0xD80000:		// Expansion slot 6
   668 					case 0xDC0000:		// Expansion slot 7
   669 						fprintf(stderr, "NOTE: RD%d from expansion card space, addr=0x%08X\n", bits, address);
   670 						handled = true;
   671 						break;
   672 				}
   673 				break;
   674 			case 0xE00000:				// HDC, FDC, MCR2 and RTC data bits
   675 			case 0xF00000:
   676 				switch (address & 0x070000) {
   677 					case 0x000000:		// [ef][08]xxxx ==> WD1010 hard disc controller
   678 						return (wd2010_read_reg(&state.hdc_ctx, (address >> 1) & 7));
   680 						break;
   681 					case 0x010000:		// [ef][19]xxxx ==> WD2797 floppy disc controller
   682 						/*ENFORCE_SIZE_R(bits, address, 16, "FDC REGISTERS");*/
   683 						return wd2797_read_reg(&state.fdc_ctx, (address >> 1) & 3);
   684 						break;
   685 					case 0x020000:		// [ef][2a]xxxx ==> Miscellaneous Control Register 2
   686 						break;
   687 					case 0x030000:		// [ef][3b]xxxx ==> Real Time Clock data bits
   688 						LOGS("REAL TIME CLOCK DATA READ");
   689 						break;
   690 					case 0x040000:		// [ef][4c]xxxx ==> General Control Register
   691 						switch (address & 0x077000) {
   692 							case 0x040000:		// [ef][4c][08]xxx ==> EE
   693 							case 0x041000:		// [ef][4c][19]xxx ==> PIE
   694 							case 0x042000:		// [ef][4c][2A]xxx ==> BP
   695 							case 0x043000:		// [ef][4c][3B]xxx ==> ROMLMAP
   696 							case 0x044000:		// [ef][4c][4C]xxx ==> L1 MODEM
   697 							case 0x045000:		// [ef][4c][5D]xxx ==> L2 MODEM
   698 							case 0x046000:		// [ef][4c][6E]xxx ==> D/N CONNECT
   699 								// All write-only registers... TODO: bus error?
   700 								handled = true;
   701 								break;
   702 							case 0x047000:		// [ef][4c][7F]xxx ==> Whole screen reverse video [FIXME: not in TRM]
   703 								break;
   704 						}
   705 						break;
   706 					case 0x050000:		// [ef][5d]xxxx ==> 8274
   707 						break;
   708 					case 0x060000:		// [ef][6e]xxxx ==> Control regs
   709 						switch (address & 0x07F000) {
   710 							default:
   711 								break;
   712 						}
   713 						break;
   714 					case 0x070000:		// [ef][7f]xxxx ==> 6850 Keyboard Controller
   715 						// TODO: figure out which sizes are valid (probably just 8 and 16)
   716 						//ENFORCE_SIZE_R(bits, address, 16, "KEYBOARD CONTROLLER");
   717 						{
   718 							if (bits == 8) {
   719 								return keyboard_read(&state.kbd, (address >> 1) & 3);
   720 							} else {
   721 								return keyboard_read(&state.kbd, (address >> 1) & 3) << 8;
   722 							}
   723 							return data;
   724 						}
   725 						break;
   726 				}
   727 		}
   728 	}
   730 	LOG_NOT_HANDLED_R(bits);
   732 	return data;
   733 }/*}}}*/
   736 /********************************************************
   737  * m68k memory read/write support functions for Musashi
   738  ********************************************************/
   740 /**
   741  * @brief Read M68K memory, 32-bit
   742  */
   743 uint32_t m68k_read_memory_32(uint32_t address)/*{{{*/
   744 {
   745 	uint32_t data = EMPTY & 0xFFFFFFFF;
   747 	// If ROMLMAP is set, force system to access ROM
   748 	if (!state.romlmap)
   749 		address |= 0x800000;
   751 	// Check access permissions
   752 	ACCESS_CHECK_RD(address, 32);
   754 	if ((address >= 0x800000) && (address <= 0xBFFFFF)) {
   755 		// ROM access
   756 		return RD32(state.rom, address, ROM_SIZE - 1);
   757 	} else if (address <= 0x3fffff) {
   758 		// RAM access
   759 		uint32_t newAddr = MAP_ADDR(address);
   761 		if (newAddr <= 0x1fffff) {
   762 			// Base memory wraps around
   763 			return RD32(state.base_ram, newAddr, state.base_ram_size - 1);
   764 		} else {
   765 			if ((newAddr <= (state.exp_ram_size + 0x200000 - 1)) && (newAddr >= 0x200000))
   766 				return RD32(state.exp_ram, newAddr - 0x200000, state.exp_ram_size - 1);
   767 			else
   768 				return EMPTY & 0xffffffff;
   769 		}
   770 	} else if ((address >= 0x400000) && (address <= 0x7FFFFF)) {
   771 		// I/O register space, zone A
   772 		switch (address & 0x0F0000) {
   773 			case 0x000000:				// Map RAM access
   774 				if (address > 0x4007FF) fprintf(stderr, "NOTE: RD32 from MapRAM mirror, addr=0x%08X\n", address);
   775 				return RD32(state.map, address, 0x7FF);
   776 				break;
   777 			case 0x020000:				// Video RAM
   778 				if (address > 0x427FFF) fprintf(stderr, "NOTE: RD32 from VideoRAM mirror, addr=0x%08X\n", address);
   779 				return RD32(state.vram, address, 0x7FFF);
   780 				break;
   781 			default:
   782 				return IoRead(address, 32);
   783 		}
   784 	} else {
   785 		return IoRead(address, 32);
   786 	}
   788 	return data;
   789 }/*}}}*/
   791 /**
   792  * @brief Read M68K memory, 16-bit
   793  */
   794 uint32_t m68k_read_memory_16(uint32_t address)/*{{{*/
   795 {
   796 	uint16_t data = EMPTY & 0xFFFF;
   798 	// If ROMLMAP is set, force system to access ROM
   799 	if (!state.romlmap)
   800 		address |= 0x800000;
   802 	// Check access permissions
   803 	ACCESS_CHECK_RD(address, 16);
   805 	if ((address >= 0x800000) && (address <= 0xBFFFFF)) {
   806 		// ROM access
   807 		data = RD16(state.rom, address, ROM_SIZE - 1);
   808 	} else if (address <= 0x3fffff) {
   809 		// RAM access
   810 		uint32_t newAddr = MAP_ADDR(address);
   812 		if (newAddr <= 0x1fffff) {
   813 			// Base memory wraps around
   814 			return RD16(state.base_ram, newAddr, state.base_ram_size - 1);
   815 		} else {
   816 			if ((newAddr <= (state.exp_ram_size + 0x200000 - 1)) && (newAddr >= 0x200000))
   817 				return RD16(state.exp_ram, newAddr - 0x200000, state.exp_ram_size - 1);
   818 			else
   819 				return EMPTY & 0xffff;
   820 		}
   821 	} else if ((address >= 0x400000) && (address <= 0x7FFFFF)) {
   822 		// I/O register space, zone A
   823 		switch (address & 0x0F0000) {
   824 			case 0x000000:				// Map RAM access
   825 				if (address > 0x4007FF) fprintf(stderr, "NOTE: RD16 from MapRAM mirror, addr=0x%08X\n", address);
   826 				data = RD16(state.map, address, 0x7FF);
   827 				break;
   828 			case 0x020000:				// Video RAM
   829 				if (address > 0x427FFF) fprintf(stderr, "NOTE: RD16 from VideoRAM mirror, addr=0x%08X\n", address);
   830 				data = RD16(state.vram, address, 0x7FFF);
   831 				break;
   832 			default:
   833 				data = IoRead(address, 16);
   834 		}
   835 	} else {
   836 		data = IoRead(address, 16);
   837 	}
   839 	return data;
   840 }/*}}}*/
   842 /**
   843  * @brief Read M68K memory, 8-bit
   844  */
   845 uint32_t m68k_read_memory_8(uint32_t address)/*{{{*/
   846 {
   847 	uint8_t data = EMPTY & 0xFF;
   849 	// If ROMLMAP is set, force system to access ROM
   850 	if (!state.romlmap)
   851 		address |= 0x800000;
   853 	// Check access permissions
   854 	ACCESS_CHECK_RD(address, 8);
   856 	if ((address >= 0x800000) && (address <= 0xBFFFFF)) {
   857 		// ROM access
   858 		data = RD8(state.rom, address, ROM_SIZE - 1);
   859 	} else if (address <= 0x3fffff) {
   860 		// RAM access
   861 		uint32_t newAddr = MAP_ADDR(address);
   863 		if (newAddr <= 0x1fffff) {
   864 			// Base memory wraps around
   865 			return RD8(state.base_ram, newAddr, state.base_ram_size - 1);
   866 		} else {
   867 			if ((newAddr <= (state.exp_ram_size + 0x200000 - 1)) && (newAddr >= 0x200000))
   868 				return RD8(state.exp_ram, newAddr - 0x200000, state.exp_ram_size - 1);
   869 			else
   870 				return EMPTY & 0xff;
   871 		}
   872 	} else if ((address >= 0x400000) && (address <= 0x7FFFFF)) {
   873 		// I/O register space, zone A
   874 		switch (address & 0x0F0000) {
   875 			case 0x000000:				// Map RAM access
   876 				if (address > 0x4007FF) fprintf(stderr, "NOTE: RD8 from MapRAM mirror, addr=0x%08X\n", address);
   877 				data = RD8(state.map, address, 0x7FF);
   878 				break;
   879 			case 0x020000:				// Video RAM
   880 				if (address > 0x427FFF) fprintf(stderr, "NOTE: RD8 from VideoRAM mirror, addr=0x%08X\n", address);
   881 				data = RD8(state.vram, address, 0x7FFF);
   882 				break;
   883 			default:
   884 				data = IoRead(address, 8);
   885 		}
   886 	} else {
   887 		data = IoRead(address, 8);
   888 	}
   890 	return data;
   891 }/*}}}*/
   893 /**
   894  * @brief Write M68K memory, 32-bit
   895  */
   896 void m68k_write_memory_32(uint32_t address, uint32_t value)/*{{{*/
   897 {
   898 	// If ROMLMAP is set, force system to access ROM
   899 	if (!state.romlmap)
   900 		address |= 0x800000;
   902 	// Check access permissions
   903 	ACCESS_CHECK_WR(address, 32);
   905 	if ((address >= 0x800000) && (address <= 0xBFFFFF)) {
   906 		// ROM access
   907 	} else if (address <= 0x3FFFFF) {
   908 		// RAM access
   909 		uint32_t newAddr = MAP_ADDR(address);
   911 		if (newAddr <= 0x1fffff) {
   912 			if (newAddr < state.base_ram_size) {
   913 				WR32(state.base_ram, newAddr, state.base_ram_size - 1, value);
   914 			}
   915 		} else {
   916 			if ((newAddr - 0x200000) < state.exp_ram_size) {
   917 				WR32(state.exp_ram, newAddr - 0x200000, state.exp_ram_size - 1, value);
   918 			}
   919 		}
   920 	} else if ((address >= 0x400000) && (address <= 0x7FFFFF)) {
   921 		// I/O register space, zone A
   922 		switch (address & 0x0F0000) {
   923 			case 0x000000:				// Map RAM access
   924 				if (address > 0x4007FF) fprintf(stderr, "NOTE: WR32 to MapRAM mirror, addr=0x%08X\n", address);
   925 				WR32(state.map, address, 0x7FF, value);
   926 				break;
   927 			case 0x020000:				// Video RAM
   928 				if (address > 0x427FFF) fprintf(stderr, "NOTE: WR32 to VideoRAM mirror, addr=0x%08X\n", address);
   929 				WR32(state.vram, address, 0x7FFF, value);
   930 				break;
   931 			default:
   932 				IoWrite(address, value, 32);
   933 		}
   934 	} else {
   935 		IoWrite(address, value, 32);
   936 	}
   937 }/*}}}*/
   939 /**
   940  * @brief Write M68K memory, 16-bit
   941  */
   942 void m68k_write_memory_16(uint32_t address, uint32_t value)/*{{{*/
   943 {
   944 	// If ROMLMAP is set, force system to access ROM
   945 	if (!state.romlmap)
   946 		address |= 0x800000;
   948 	// Check access permissions
   949 	ACCESS_CHECK_WR(address, 16);
   951 	if ((address >= 0x800000) && (address <= 0xBFFFFF)) {
   952 		// ROM access
   953 	} else if (address <= 0x3FFFFF) {
   954 		// RAM access
   955 		uint32_t newAddr = MAP_ADDR(address);
   957 		if (newAddr <= 0x1fffff) {
   958 			if (newAddr < state.base_ram_size) {
   959 				WR16(state.base_ram, newAddr, state.base_ram_size - 1, value);
   960 			}
   961 		} else {
   962 			if ((newAddr - 0x200000) < state.exp_ram_size) {
   963 				WR16(state.exp_ram, newAddr - 0x200000, state.exp_ram_size - 1, value);
   964 			}
   965 		}
   966 	} else if ((address >= 0x400000) && (address <= 0x7FFFFF)) {
   967 		// I/O register space, zone A
   968 		switch (address & 0x0F0000) {
   969 			case 0x000000:				// Map RAM access
   970 				if (address > 0x4007FF) fprintf(stderr, "NOTE: WR16 to MapRAM mirror, addr=0x%08X, data=0x%04X\n", address, value);
   971 				WR16(state.map, address, 0x7FF, value);
   972 				break;
   973 			case 0x020000:				// Video RAM
   974 				if (address > 0x427FFF) fprintf(stderr, "NOTE: WR16 to VideoRAM mirror, addr=0x%08X, data=0x%04X\n", address, value);
   975 				WR16(state.vram, address, 0x7FFF, value);
   976 				break;
   977 			default:
   978 				IoWrite(address, value, 16);
   979 		}
   980 	} else {
   981 		IoWrite(address, value, 16);
   982 	}
   983 }/*}}}*/
   985 /**
   986  * @brief Write M68K memory, 8-bit
   987  */
   988 void m68k_write_memory_8(uint32_t address, uint32_t value)/*{{{*/
   989 {
   990 	// If ROMLMAP is set, force system to access ROM
   991 	if (!state.romlmap)
   992 		address |= 0x800000;
   994 	// Check access permissions
   995 	ACCESS_CHECK_WR(address, 8);
   997 	if ((address >= 0x800000) && (address <= 0xBFFFFF)) {
   998 		// ROM access (read only!)
   999 	} else if (address <= 0x3FFFFF) {
  1000 		// RAM access
  1001 		uint32_t newAddr = MAP_ADDR(address);
  1003 		if (newAddr <= 0x1fffff) {
  1004 			if (newAddr < state.base_ram_size) {
  1005 				WR8(state.base_ram, newAddr, state.base_ram_size - 1, value);
  1007 		} else {
  1008 			if ((newAddr - 0x200000) < state.exp_ram_size) {
  1009 				WR8(state.exp_ram, newAddr - 0x200000, state.exp_ram_size - 1, value);
  1012 	} else if ((address >= 0x400000) && (address <= 0x7FFFFF)) {
  1013 		// I/O register space, zone A
  1014 		switch (address & 0x0F0000) {
  1015 			case 0x000000:				// Map RAM access
  1016 				if (address > 0x4007FF) fprintf(stderr, "NOTE: WR8 to MapRAM mirror, addr=0x%08X, data=0x%04X\n", address, value);
  1017 				WR8(state.map, address, 0x7FF, value);
  1018 				break;
  1019 			case 0x020000:				// Video RAM
  1020 				if (address > 0x427FFF) fprintf(stderr, "NOTE: WR8 to VideoRAM mirror, addr=0x%08X, data=0x%04X\n", address, value);
  1021 				WR8(state.vram, address, 0x7FFF, value);
  1022 				break;
  1023 			default:
  1024 				IoWrite(address, value, 8);
  1026 	} else {
  1027 		IoWrite(address, value, 8);
  1029 }/*}}}*/
  1032 // for the disassembler
  1033 uint32_t m68k_read_disassembler_32(uint32_t addr)
  1035 	if (addr < 0x400000) {
  1036 		// XXX FIXME BUGBUG update this to use the new mapper macros!
  1037 		uint16_t page = (addr >> 12) & 0x3FF;
  1038 		uint32_t new_page_addr = MAPRAM(page) & 0x3FF;
  1039 		uint32_t newAddr = (new_page_addr << 12) + (addr & 0xFFF);
  1040 		if (newAddr <= 0x1fffff) {
  1041 			if (newAddr >= state.base_ram_size)
  1042 				return EMPTY;
  1043 			else
  1044 				return RD32(state.base_ram, newAddr, state.base_ram_size - 1);
  1045 		} else {
  1046 			if ((newAddr <= (state.exp_ram_size + 0x200000 - 1)) && (newAddr >= 0x200000))
  1047 				return RD32(state.exp_ram, newAddr - 0x200000, state.exp_ram_size - 1);
  1048 			else
  1049 				return EMPTY;
  1051 	} else {
  1052 		LOG("WARNING: Disassembler RD32 out of range 0x%08X\n", addr);
  1053 		return EMPTY;
  1057 uint32_t m68k_read_disassembler_16(uint32_t addr)
  1059 	if (addr < 0x400000) {
  1060 		uint16_t page = (addr >> 12) & 0x3FF;
  1061 		uint32_t new_page_addr = MAPRAM(page) & 0x3FF;
  1062 		uint32_t newAddr = (new_page_addr << 12) + (addr & 0xFFF);
  1063 		if (newAddr <= 0x1fffff) {
  1064 			if (newAddr >= state.base_ram_size)
  1065 				return EMPTY & 0xffff;
  1066 			else
  1067 				return RD16(state.base_ram, newAddr, state.base_ram_size - 1);
  1068 		} else {
  1069 			if ((newAddr <= (state.exp_ram_size + 0x200000 - 1)) && (newAddr >= 0x200000))
  1070 				return RD16(state.exp_ram, newAddr - 0x200000, state.exp_ram_size - 1);
  1071 			else
  1072 				return EMPTY & 0xffff;
  1074 	} else {
  1075 		LOG("WARNING: Disassembler RD16 out of range 0x%08X\n", addr);
  1076 		return EMPTY & 0xffff;
  1080 uint32_t m68k_read_disassembler_8 (uint32_t addr)
  1082 	if (addr < 0x400000) {
  1083 		uint16_t page = (addr >> 12) & 0x3FF;
  1084 		uint32_t new_page_addr = MAPRAM(page) & 0x3FF;
  1085 		uint32_t newAddr = (new_page_addr << 12) + (addr & 0xFFF);
  1086 		if (newAddr <= 0x1fffff) {
  1087 			if (newAddr >= state.base_ram_size)
  1088 				return EMPTY & 0xff;
  1089 			else
  1090 				return RD8(state.base_ram, newAddr, state.base_ram_size - 1);
  1091 		} else {
  1092 			if ((newAddr <= (state.exp_ram_size + 0x200000 - 1)) && (newAddr >= 0x200000))
  1093 				return RD8(state.exp_ram, newAddr - 0x200000, state.exp_ram_size - 1);
  1094 			else
  1095 				return EMPTY & 0xff;
  1097 	} else {
  1098 		LOG("WARNING: Disassembler RD8 out of range 0x%08X\n", addr);
  1099 		return EMPTY & 0xff;