summaryrefslogtreecommitdiffstatshomepage
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/emu/cpu/m68000/m68000.h2
-rw-r--r--src/emu/cpu/m68000/m68k_in.c76
-rw-r--r--src/emu/cpu/m68000/m68kcpu.c187
-rw-r--r--src/emu/cpu/m68000/m68kcpu.h9
-rw-r--r--src/emu/cpu/m68000/m68kdasm.c28
-rw-r--r--src/emu/cpu/m68000/m68kmmu.h180
6 files changed, 474 insertions, 8 deletions
diff --git a/src/emu/cpu/m68000/m68000.h b/src/emu/cpu/m68000/m68000.h
index a28cef1e56f..a8682feee46 100644
--- a/src/emu/cpu/m68000/m68000.h
+++ b/src/emu/cpu/m68000/m68000.h
@@ -76,6 +76,7 @@ CPU_GET_INFO( m68008 );
CPU_GET_INFO( m68010 );
CPU_GET_INFO( m68ec020 );
CPU_GET_INFO( m68020 );
+CPU_GET_INFO( m68020pmmu );
CPU_GET_INFO( m68ec030 );
CPU_GET_INFO( m68030 );
CPU_GET_INFO( m68ec040 );
@@ -88,6 +89,7 @@ CPU_GET_INFO( scc68070 );
#define CPU_M68010 CPU_GET_INFO_NAME( m68010 )
#define CPU_M68EC020 CPU_GET_INFO_NAME( m68ec020 )
#define CPU_M68020 CPU_GET_INFO_NAME( m68020 )
+#define CPU_M68020_68851 CPU_GET_INFO_NAME( m68020pmmu )
#define CPU_M68EC030 CPU_GET_INFO_NAME( m68ec030 )
#define CPU_M68030 CPU_GET_INFO_NAME( m68030 )
#define CPU_M68EC040 CPU_GET_INFO_NAME( m68ec040 )
diff --git a/src/emu/cpu/m68000/m68k_in.c b/src/emu/cpu/m68000/m68k_in.c
index db5d58d45d9..6002804a24a 100644
--- a/src/emu/cpu/m68000/m68k_in.c
+++ b/src/emu/cpu/m68000/m68k_in.c
@@ -8014,8 +8014,82 @@ M68KMAKE_OP(pmove, 32, ., .)
{
modes = m68ki_read_imm_16(m68k);
ea = M68KMAKE_GET_EA_AY_32;
+
+ if ((modes & 0xfde0) == 0x2000) // PLOAD
+ {
+ logerror("680x0: unhandled PLOAD\n");
+ return;
+ }
+
+ if ((modes & 0xe200) == 0x2000) // PFLUSHA
+ {
+ logerror("680x0: unhandled PFLUSHA\n");
+ return;
+ }
+
+ switch ((modes>>13) & 0x7)
+ {
+ case 0: // MC68030/040 form with FD bit
+ case 2: // MC68881 form, FD never set
+ if (modes & 0x200)
+ {
+ logerror("680x0: PMOVE from MMU not supported\n");
+ }
+ else
+ {
+ switch ((modes>>10) & 7)
+ {
+ case 0: // translation control register
+ m68k->mmu_tc = memory_read_word_32be(m68k->program, ea)<<16;
+ m68k->mmu_tc |= memory_read_word_32be(m68k->program, ea+2);
+
+ if (m68k->mmu_tc & 0x80000000)
+ {
+ m68k->pmmu_enabled = 1;
+ }
+ else
+ {
+ m68k->pmmu_enabled = 0;
+ }
+ break;
+
+ case 2: // supervisor root pointer
+ m68k->mmu_srp_limit = memory_read_word_32be(m68k->program, ea)<<16;
+ m68k->mmu_srp_limit |= memory_read_word_32be(m68k->program, ea+2);
+ m68k->mmu_srp_aptr = memory_read_word_32be(m68k->program, ea+4)<<16;
+ m68k->mmu_srp_aptr |= memory_read_word_32be(m68k->program, ea+6);
+ break;
+
+ case 3: // CPU root pointer
+ m68k->mmu_crp_limit = memory_read_word_32be(m68k->program, ea)<<16;
+ m68k->mmu_crp_limit |= memory_read_word_32be(m68k->program, ea+2);
+ m68k->mmu_crp_aptr = memory_read_word_32be(m68k->program, ea+4)<<16;
+ m68k->mmu_crp_aptr |= memory_read_word_32be(m68k->program, ea+6);
+ break;
+
+ default:
+ logerror("680x0: PMOVE to unknown MMU register %x\n", (modes>>10) & 7);
+ break;
+ }
+ }
+ break;
+
+ case 3: // MC68030 to/from status reg
+ if (modes & 0x200)
+ {
+ memory_write_word_32be(m68k->program, ea, m68k->mmu_sr);
+ }
+ else
+ {
+ m68k->mmu_sr = memory_read_word_32be(m68k->program, ea);
+ }
+ break;
+
+ default:
+ logerror("680x0: unknown PMOVE mode %x (modes %04x) (PC %x)\n", (modes>>13) & 0x7, modes, m68k->pc);
+ break;
+ }
- logerror("680x0: unhandled PMOVE modes %x ea %x\n", modes, ea);
}
else
{
diff --git a/src/emu/cpu/m68000/m68kcpu.c b/src/emu/cpu/m68000/m68kcpu.c
index ee25c763a80..8ca8f6cb5ce 100644
--- a/src/emu/cpu/m68000/m68kcpu.c
+++ b/src/emu/cpu/m68000/m68kcpu.c
@@ -5,7 +5,7 @@
#if 0
static const char copyright_notice[] =
"MUSASHI\n"
-"Version 4.10 (2009-09-27)\n"
+"Version 4.5 (2009-10-09)\n"
"A portable Motorola M680x0 processor emulation engine.\n"
"Copyright Karl Stenerud. All rights reserved.\n"
"\n"
@@ -38,6 +38,8 @@ static const char copyright_notice[] =
#include "m68kfpu.c"
#include "debugger.h"
+#include "m68kmmu.h"
+
extern void m68040_fpu_op0(m68ki_cpu_core *m68k);
extern void m68040_fpu_op1(m68ki_cpu_core *m68k);
@@ -611,6 +613,21 @@ static void m68k_postload(running_machine *machine, void *param)
m68ki_jump(m68k, REG_PC);
}
+/* translate logical to physical addresses */
+static CPU_TRANSLATE( m68k )
+{
+ m68ki_cpu_core *m68k = get_safe_token(device);
+
+ /* only applies to the program address space and only does something if the MMU's enabled */
+ if (m68k)
+ {
+ if ((space == ADDRESS_SPACE_PROGRAM) && (m68k->pmmu_enabled))
+ {
+ *address = pmmu_translate_addr(m68k, *address);
+ }
+ }
+ return TRUE;
+}
/* Execute some instructions until we use up cycles clock cycles */
static CPU_EXECUTE( m68k )
@@ -718,6 +735,9 @@ static CPU_RESET( m68k )
{
m68ki_cpu_core *m68k = get_safe_token(device);
+ /* Disable the PMMU on reset */
+ m68k->pmmu_enabled = 0;
+
/* Clear all stop levels and eat up all remaining cycles */
m68k->stopped = 0;
if (m68k->remaining_cycles > 0)
@@ -890,6 +910,7 @@ static CPU_GET_INFO( m68k )
case CPUINFO_FCT_DISASSEMBLE: info->disassemble = CPU_DISASSEMBLE_NAME(m68k); break;
case CPUINFO_FCT_IMPORT_STATE: info->import_state = CPU_IMPORT_STATE_NAME(m68k); break;
case CPUINFO_FCT_EXPORT_STATE: info->export_state = CPU_EXPORT_STATE_NAME(m68k); break;
+ case CPUINFO_FCT_TRANSLATE: info->translate = CPU_TRANSLATE_NAME(m68k); break;
/* --- the following bits of info are returned as pointers --- */
case CPUINFO_PTR_INSTRUCTION_COUNTER: info->icount = &m68k->remaining_cycles; break;
@@ -898,7 +919,7 @@ static CPU_GET_INFO( m68k )
/* --- the following bits of info are returned as NULL-terminated strings --- */
case DEVINFO_STR_NAME: /* set per-core */ break;
case DEVINFO_STR_FAMILY: strcpy(info->s, "Motorola 68K"); break;
- case DEVINFO_STR_VERSION: strcpy(info->s, "4.00"); break;
+ case DEVINFO_STR_VERSION: strcpy(info->s, "4.50"); break;
case DEVINFO_STR_SOURCE_FILE: strcpy(info->s, __FILE__); break;
case DEVINFO_STR_CREDITS: strcpy(info->s, "Copyright Karl Stenerud. All rights reserved. (2.1 fixes HJB)"); break;
@@ -1062,7 +1083,139 @@ static const m68k_memory_interface interface_d32 =
writelong_d32
};
+/* interface for 32-bit data bus with PMMU (68EC020, 68020) */
+static UINT8 read_byte_32_mmu(const address_space *space, offs_t address)
+{
+ m68ki_cpu_core *m68k = get_safe_token(space->cpu);
+
+ if (m68k->pmmu_enabled)
+ {
+ address = pmmu_translate_addr(m68k, address);
+ }
+
+ return memory_read_byte_32be(space, address);
+}
+
+static void write_byte_32_mmu(const address_space *space, offs_t address, UINT8 data)
+{
+ m68ki_cpu_core *m68k = get_safe_token(space->cpu);
+
+ if (m68k->pmmu_enabled)
+ {
+ address = pmmu_translate_addr(m68k, address);
+ }
+
+ memory_write_byte_32be(space, address, data);
+}
+
+static UINT16 read_immediate_16_mmu(const address_space *space, offs_t address)
+{
+ m68ki_cpu_core *m68k = get_safe_token(space->cpu);
+
+ if (m68k->pmmu_enabled)
+ {
+ address = pmmu_translate_addr(m68k, address);
+ }
+
+ return memory_decrypted_read_word(space, (address) ^ m68k->memory.opcode_xor);
+}
+
+/* potentially misaligned 16-bit reads with a 32-bit data bus (and 24-bit address bus) */
+static UINT16 readword_d32_mmu(const address_space *space, offs_t address)
+{
+ m68ki_cpu_core *m68k = get_safe_token(space->cpu);
+ UINT16 result;
+
+ if (m68k->pmmu_enabled)
+ {
+ address = pmmu_translate_addr(m68k, address);
+ }
+
+ if (!(address & 1))
+ return memory_read_word_32be(space, address);
+ result = memory_read_byte_32be(space, address) << 8;
+ return result | memory_read_byte_32be(space, address + 1);
+}
+
+/* potentially misaligned 16-bit writes with a 32-bit data bus (and 24-bit address bus) */
+static void writeword_d32_mmu(const address_space *space, offs_t address, UINT16 data)
+{
+ m68ki_cpu_core *m68k = get_safe_token(space->cpu);
+
+ if (m68k->pmmu_enabled)
+ {
+ address = pmmu_translate_addr(m68k, address);
+ }
+ if (!(address & 1))
+ {
+ memory_write_word_32be(space, address, data);
+ return;
+ }
+ memory_write_byte_32be(space, address, data >> 8);
+ memory_write_byte_32be(space, address + 1, data);
+}
+
+/* potentially misaligned 32-bit reads with a 32-bit data bus (and 24-bit address bus) */
+static UINT32 readlong_d32_mmu(const address_space *space, offs_t address)
+{
+ m68ki_cpu_core *m68k = get_safe_token(space->cpu);
+ UINT32 result;
+
+ if (m68k->pmmu_enabled)
+ {
+ address = pmmu_translate_addr(m68k, address);
+ }
+
+ if (!(address & 3))
+ return memory_read_dword_32be(space, address);
+ else if (!(address & 1))
+ {
+ result = memory_read_word_32be(space, address) << 16;
+ return result | memory_read_word_32be(space, address + 2);
+ }
+ result = memory_read_byte_32be(space, address) << 24;
+ result |= memory_read_word_32be(space, address + 1) << 8;
+ return result | memory_read_byte_32be(space, address + 3);
+}
+
+/* potentially misaligned 32-bit writes with a 32-bit data bus (and 24-bit address bus) */
+static void writelong_d32_mmu(const address_space *space, offs_t address, UINT32 data)
+{
+ m68ki_cpu_core *m68k = get_safe_token(space->cpu);
+
+ if (m68k->pmmu_enabled)
+ {
+ address = pmmu_translate_addr(m68k, address);
+ }
+
+ if (!(address & 3))
+ {
+ memory_write_dword_32be(space, address, data);
+ return;
+ }
+ else if (!(address & 1))
+ {
+ memory_write_word_32be(space, address, data >> 16);
+ memory_write_word_32be(space, address + 2, data);
+ return;
+ }
+ memory_write_byte_32be(space, address, data >> 24);
+ memory_write_word_32be(space, address + 1, data >> 8);
+ memory_write_byte_32be(space, address + 3, data);
+}
+
+static const m68k_memory_interface interface_d32_mmu =
+{
+ WORD_XOR_BE(0),
+ read_immediate_16_mmu,
+ read_byte_32_mmu,
+ readword_d32_mmu,
+ readlong_d32_mmu,
+ write_byte_32_mmu,
+ writeword_d32_mmu,
+ writelong_d32_mmu
+};
void m68k_set_reset_callback(const device_config *device, m68k_reset_func callback)
@@ -1301,6 +1454,30 @@ CPU_GET_INFO( m68020 )
}
}
+// 68020 with 68851 PMMU
+static CPU_INIT( m68020pmmu )
+{
+ m68ki_cpu_core *m68k = get_safe_token(device);
+
+ CPU_INIT_CALL(m68020);
+
+ m68k->has_pmmu = 1;
+ m68k->memory = interface_d32_mmu;
+}
+
+CPU_GET_INFO( m68020pmmu )
+{
+ switch (state)
+ {
+ /* --- the following bits of info are returned as pointers to data or functions --- */
+ case CPUINFO_FCT_INIT: info->init = CPU_INIT_NAME(m68020pmmu); break;
+
+ /* --- the following bits of info are returned as NULL-terminated strings --- */
+ case DEVINFO_STR_NAME: strcpy(info->s, "68020, 68851"); break;
+
+ default: CPU_GET_INFO_CALL(m68020); break;
+ }
+}
/****************************************************************************
* M680EC20 section
@@ -1361,7 +1538,7 @@ static CPU_INIT( m68030 )
m68k->cpu_type = CPU_TYPE_030;
m68k->state.subtypemask = m68k->cpu_type;
m68k->dasm_type = M68K_CPU_TYPE_68030;
- m68k->memory = interface_d32;
+ m68k->memory = interface_d32_mmu;
m68k->sr_mask = 0xf71f; /* T1 T0 S M -- I2 I1 I0 -- -- -- X N Z V C */
m68k->cyc_instruction = m68ki_cycles[3];
m68k->cyc_exception = m68ki_exception_cycle_table[3];
@@ -1480,7 +1657,7 @@ static CPU_INIT( m68040 )
m68k->cpu_type = CPU_TYPE_040;
m68k->state.subtypemask = m68k->cpu_type;
m68k->dasm_type = M68K_CPU_TYPE_68040;
- m68k->memory = interface_d32;
+ m68k->memory = interface_d32_mmu;
m68k->sr_mask = 0xf71f; /* T1 T0 S M -- I2 I1 I0 -- -- -- X N Z V C */
m68k->cyc_instruction = m68ki_cycles[4];
m68k->cyc_exception = m68ki_exception_cycle_table[4];
@@ -1568,7 +1745,7 @@ static CPU_INIT( m68ec040 )
m68k->cyc_movem_l = 2;
m68k->cyc_shift = 0;
m68k->cyc_reset = 518;
- m68k->has_pmmu = 1;
+ m68k->has_pmmu = 0;
}
CPU_GET_INFO( m68ec040 )
diff --git a/src/emu/cpu/m68000/m68kcpu.h b/src/emu/cpu/m68000/m68kcpu.h
index d074569906d..6f8245b937c 100644
--- a/src/emu/cpu/m68000/m68kcpu.h
+++ b/src/emu/cpu/m68000/m68kcpu.h
@@ -3,7 +3,7 @@
/* ======================================================================== */
/*
* MUSASHI
- * Version 4.00
+ * Version 4.50
*
* A portable Motorola M680x0 processor emulation engine.
* Copyright Karl Stenerud. All rights reserved.
@@ -581,6 +581,7 @@ struct _m68ki_cpu_core
UINT32 instr_mode; /* Stores whether we are in instruction mode or group 0/1 exception mode */
UINT32 run_mode; /* Stores whether we are processing a reset, bus error, address error, or something else */
int has_pmmu; /* Indicates if a PMMU available (yes on 030, 040, no on EC030) */
+ int pmmu_enabled; /* Indicates if the PMMU is enabled */
/* Clocks required for instructions / exceptions */
UINT32 cyc_bcc_notake_b;
@@ -635,6 +636,12 @@ struct _m68ki_cpu_core
UINT16 save_sr;
UINT8 save_stopped;
UINT8 save_halted;
+
+ /* PMMU registers */
+ UINT32 mmu_crp_aptr, mmu_crp_limit;
+ UINT32 mmu_srp_aptr, mmu_srp_limit;
+ UINT32 mmu_tc;
+ UINT16 mmu_sr;
};
diff --git a/src/emu/cpu/m68000/m68kdasm.c b/src/emu/cpu/m68000/m68kdasm.c
index ecb77953ffd..de8f34ba652 100644
--- a/src/emu/cpu/m68000/m68kdasm.c
+++ b/src/emu/cpu/m68000/m68kdasm.c
@@ -3027,6 +3027,32 @@ static void d68030_pmove(void)
// do this after fetching the second PMOVE word so we properly get the 3rd if necessary
str = get_ea_mode_str_32(g_cpu_ir);
+ if ((modes & 0xfde0) == 0x2000) // PLOAD
+ {
+ if (modes & 0x0200)
+ {
+ sprintf(g_dasm_str, "pload #%d, %s", (modes>>10)&7, str);
+ }
+ else
+ {
+ sprintf(g_dasm_str, "pload %s, #%d", str, (modes>>10)&7);
+ }
+ return;
+ }
+
+ if ((modes & 0xe200) == 0x2000) // PFLUSHA
+ {
+ if (modes & 0x0200)
+ {
+ sprintf(g_dasm_str, "pflush %s, %s", g_mmuregs[(modes>>10)&7], str);
+ }
+ else
+ {
+ sprintf(g_dasm_str, "pflush %s, %s", str, g_mmuregs[(modes>>10)&7]);
+ }
+ return;
+ }
+
switch ((modes>>13) & 0x7)
{
case 0: // MC68030/040 form with FD bit
@@ -3803,7 +3829,7 @@ CPU_DISASSEMBLE( m68040 )
return m68k_disassemble_raw(buffer, pc, oprom, opram, M68K_CPU_TYPE_68040);
}
-
+// f028 2215 0008
/* ======================================================================== */
/* ============================== END OF FILE ============================= */
diff --git a/src/emu/cpu/m68000/m68kmmu.h b/src/emu/cpu/m68000/m68kmmu.h
new file mode 100644
index 00000000000..63db4faad95
--- /dev/null
+++ b/src/emu/cpu/m68000/m68kmmu.h
@@ -0,0 +1,180 @@
+/*
+ m68kmmu.h - PMMU implementation for 68851/68030/68040
+
+ By R. Belmont
+
+ Copyright Nicola Salmoria and the MAME Team.
+ Visit http://mamedev.org for licensing and usage restrictions.
+*/
+
+/*
+ pmmu_translate_addr: perform 68851/68030-style PMMU address translation
+*/
+INLINE UINT32 pmmu_translate_addr(m68ki_cpu_core *m68k, UINT32 addr_in)
+{
+ UINT32 addr_out, tbl_entry, tbl_entry2, tamode, tbmode;
+ UINT32 root_aptr, root_limit, tofs, is, abits, bbits, cbits;
+ UINT32 resolved, tptr, shift;
+
+ resolved = 0;
+ addr_out = addr_in;
+
+ // if SRP is enabled and we're in supervisor mode, use it
+ if ((m68k->mmu_tc & 0x02000000) && (m68ki_get_sr(m68k) & 0x2000))
+ {
+ root_aptr = m68k->mmu_srp_aptr;
+ root_limit = m68k->mmu_srp_limit;
+ }
+ else // else use the CRP
+ {
+ root_aptr = m68k->mmu_crp_aptr;
+ root_limit = m68k->mmu_crp_limit;
+ }
+
+ // get initial shift (# of top bits to ignore)
+ is = (m68k->mmu_tc>>16) & 0xf;
+ abits = (m68k->mmu_tc>>12)&0xf;
+ bbits = (m68k->mmu_tc>>8)&0xf;
+ cbits = (m68k->mmu_tc>>4)&0xf;
+
+// logerror("PMMU: tcr %08x limit %08x aptr %08x is %x abits %d bbits %d cbits %d\n", m68k->mmu_tc, root_limit, root_aptr, is, abits, bbits, cbits);
+
+ // get table A offset
+ tofs = (addr_in<<is)>>(32-abits);
+
+ // find out what format table A is
+ switch (root_limit & 3)
+ {
+ case 0: // invalid, should cause MMU exception
+ case 1: // page descriptor, should cause direct mapping
+ fatalerror("680x0 PMMU: Unhandled root mode\n");
+ break;
+
+ case 2: // valid 4 byte descriptors
+ tofs *= 4;
+// logerror("PMMU: reading table A entry at %08x\n", tofs + (root_aptr & 0xfffffffc));
+ tbl_entry = memory_read_dword_32be(m68k->program, tofs + (root_aptr & 0xfffffffc));
+ tamode = tbl_entry & 3;
+// logerror("PMMU: addr %08x entry %08x mode %x tofs %x\n", addr_in, tbl_entry, tamode, tofs);
+ break;
+
+ case 3: // valid 8 byte descriptors
+ tofs *= 8;
+// logerror("PMMU: reading table A entries at %08x\n", tofs + (root_aptr & 0xfffffffc));
+ tbl_entry2 = memory_read_dword_32be(m68k->program, tofs + (root_aptr & 0xfffffffc));
+ tbl_entry = memory_read_dword_32be(m68k->program, tofs + (root_aptr & 0xfffffffc)+4);
+ tamode = tbl_entry2 & 3;
+// logerror("PMMU: addr %08x entry %08x entry2 %08x mode %x tofs %x\n", addr_in, tbl_entry, tbl_entry2, tamode, tofs);
+ break;
+ }
+
+ // get table B offset and pointer
+ tofs = (addr_in<<(is+abits))>>(32-bbits);
+ tptr = tbl_entry & 0xfffffff0;
+
+ // find out what format table B is, if any
+ switch (tamode)
+ {
+ case 0: // invalid, should cause MMU exception
+ fatalerror("680x0 PMMU: Unhandled Table A mode %d (addr_in %08x)\n", tamode, addr_in);
+ break;
+
+ case 2: // 4-byte table B descriptor
+ tofs *= 4;
+// logerror("PMMU: reading table B entry at %08x\n", tofs + tptr);
+ tbl_entry = memory_read_dword_32be(m68k->program, tofs + tptr);
+ tbmode = tbl_entry & 3;
+// logerror("PMMU: addr %08x entry %08x mode %x tofs %x\n", addr_in, tbl_entry, tbmode, tofs);
+ break;
+
+ case 3: // 8-byte table B descriptor
+ tofs *= 8;
+// logerror("PMMU: reading table B entries at %08x\n", tofs + tptr);
+ tbl_entry2 = memory_read_dword_32be(m68k->program, tofs + tptr);
+ tbl_entry = memory_read_dword_32be(m68k->program, tofs + tptr + 4);
+ tbmode = tbl_entry2 & 3;
+// logerror("PMMU: addr %08x entry %08x entry2 %08x mode %x tofs %x\n", addr_in, tbl_entry, tbl_entry2, tbmode, tofs);
+ break;
+
+ case 1: // early termination descriptor
+ tbl_entry &= 0xffffff00;
+
+ shift = is+abits;
+ addr_out = ((addr_in<<shift)>>shift) + tbl_entry;
+ resolved = 1;
+ break;
+ }
+
+ // if table A wasn't early-out, continue to process table B
+ if (!resolved)
+ {
+ switch (tbmode)
+ {
+ case 0: // invalid, should cause MMU exception
+ case 2: // 4-byte table C descriptor
+ case 3: // 8-byte table C descriptor
+ fatalerror("680x0 PMMU: Unhandled Table B mode %d (addr_in %08x)\n", tbmode, addr_in);
+ break;
+
+ case 1: // early termination descriptor
+ tbl_entry &= 0xffffff00;
+
+ shift = is+abits+bbits;
+ addr_out = ((addr_in<<shift)>>shift) + tbl_entry;
+ resolved = 1;
+ break;
+ }
+ }
+
+// if ((addr_in < 0x40000000) || (addr_in > 0x4fffffff)) printf("PMMU: [%08x] => [%08x]\n", addr_in, addr_out);
+
+ return addr_out;
+}
+
+/*
+
+maincpu at 40804366: called unimplemented instruction f000 (cpgen)
+PMMU: tcr 80f05570 limit 7fff0003 aptr 043ffcc0 is 0
+PMMU: reading table A entries at 043ffce0
+PMMU: addr 4080438a entry 00000000 entry2 7ffffc18 mode 0 aofs 20
+680x0 PMMU: Unhandled Table A mode 0
+
+enable, PS = f
+
+tblA @ 043ffcc0:
+
+043ffcc0 0001fc0a 043ffcb0 => 00000019 04000019
+043ffcc8 7ffffc18 00000000
+043ffcd0 7ffffc18 00000000
+043ffcd8 7ffffc18 00000000
+043ffce0 7ffffc18 00000000
+043ffce8 7ffffc18 00000000
+043ffcf0 7ffffc18 00000000
+043ffcf8 7ffffc18 00000000
+043ffd00 7ffffc19 40000000
+043ffd08 7ffffc19 48000000
+043ffd10 7ffffc59 50000000
+043ffd18 7ffffc59 58000000
+043ffd20 7ffffc59 60000000
+043ffd28 7ffffc59 68000000
+043ffd30 7ffffc59 70000000
+043ffd38 7ffffc59 78000000
+043ffd40 7ffffc59 80000000
+043ffd48 7ffffc59 88000000
+043ffd50 7ffffc59 90000000
+043ffd58 7ffffc59 98000000
+043ffd60 7ffffc59 a0000000
+043ffd68 7ffffc59 a8000000
+043ffd70 7ffffc59 b0000000
+043ffd78 7ffffc59 b8000000
+043ffd80 7ffffc59 c0000000
+043ffd88 7ffffc59 c8000000
+043ffd90 7ffffc59 d0000000
+043ffd98 7ffffc59 d8000000
+043ffda0 7ffffc59 e0000000
+043ffda8 7ffffc59 e8000000
+043ffdb0 7ffffc59 f0000000
+043ffdb8 7ffffc59 f8000000
+
+*/
+