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