move memory access and mapping functions into memory.[ch]

Thu, 02 Dec 2010 23:03:13 +0000

author
Philip Pemberton <philpem@philpem.me.uk>
date
Thu, 02 Dec 2010 23:03:13 +0000
changeset 40
239bc48590ba
parent 39
cab49f90c3b9
child 41
75887b42d7e5

move memory access and mapping functions into memory.[ch]

This is to tidy up main.c...

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