summaryrefslogtreecommitdiffstatshomepage
path: root/src/emu
diff options
context:
space:
mode:
author R. Belmont <rb6502@users.noreply.github.com>2011-10-08 23:02:59 +0000
committer R. Belmont <rb6502@users.noreply.github.com>2011-10-08 23:02:59 +0000
commitf8aba531d3c7c43c01bdb32161b00f71f634d8ce (patch)
tree4068b0b7c6038fd08fdab24654756a7033676c4c /src/emu
parentec6a340d1ddd5dafb9765d48e47aa99743959a55 (diff)
m68k: preliminary 68040 MMU implementation [R. Belmont]
Diffstat (limited to 'src/emu')
-rw-r--r--src/emu/cpu/m68000/m68k_in.c25
-rw-r--r--src/emu/cpu/m68000/m68kcpu.c14
-rw-r--r--src/emu/cpu/m68000/m68kcpu.h2
-rw-r--r--src/emu/cpu/m68000/m68kmmu.h337
4 files changed, 318 insertions, 60 deletions
diff --git a/src/emu/cpu/m68000/m68k_in.c b/src/emu/cpu/m68000/m68k_in.c
index a960eb0e34d..2dff4c05b13 100644
--- a/src/emu/cpu/m68000/m68k_in.c
+++ b/src/emu/cpu/m68000/m68k_in.c
@@ -6586,7 +6586,7 @@ M68KMAKE_OP(movec, 32, cr, .)
case 0x003: /* TC */
if(CPU_TYPE_IS_040_PLUS((mc68kcpu)->cpu_type))
{
- /* TODO */
+ REG_DA(mc68kcpu)[(word2 >> 12) & 15] = mc68kcpu->mmu_tc;
return;
}
m68ki_exception_illegal(mc68kcpu);
@@ -6646,7 +6646,7 @@ M68KMAKE_OP(movec, 32, cr, .)
case 0x805: /* MMUSR */
if(CPU_TYPE_IS_040_PLUS((mc68kcpu)->cpu_type))
{
- /* TODO */
+ REG_DA(mc68kcpu)[(word2 >> 12) & 15] = mc68kcpu->mmu_sr_040;
return;
}
m68ki_exception_illegal(mc68kcpu);
@@ -6654,7 +6654,7 @@ M68KMAKE_OP(movec, 32, cr, .)
case 0x806: /* URP */
if(CPU_TYPE_IS_040_PLUS((mc68kcpu)->cpu_type))
{
- /* TODO */
+ REG_DA(mc68kcpu)[(word2 >> 12) & 15] = mc68kcpu->mmu_urp_aptr;
return;
}
m68ki_exception_illegal(mc68kcpu);
@@ -6662,7 +6662,7 @@ M68KMAKE_OP(movec, 32, cr, .)
case 0x807: /* SRP */
if(CPU_TYPE_IS_040_PLUS((mc68kcpu)->cpu_type))
{
- /* TODO */
+ REG_DA(mc68kcpu)[(word2 >> 12) & 15] = mc68kcpu->mmu_srp_aptr;
return;
}
m68ki_exception_illegal(mc68kcpu);
@@ -6831,7 +6831,16 @@ M68KMAKE_OP(movec, 32, rc, .)
case 0x003: /* TC */
if (CPU_TYPE_IS_040_PLUS((mc68kcpu)->cpu_type))
{
- /* TODO */
+ mc68kcpu->mmu_tc = REG_DA(mc68kcpu)[(word2 >> 12) & 15];
+
+ if (mc68kcpu->mmu_tc & 0x8000)
+ {
+ mc68kcpu->pmmu_enabled = 1;
+ }
+ else
+ {
+ mc68kcpu->pmmu_enabled = 0;
+ }
return;
}
m68ki_exception_illegal(mc68kcpu);
@@ -6891,7 +6900,7 @@ M68KMAKE_OP(movec, 32, rc, .)
case 0x805: /* MMUSR */
if (CPU_TYPE_IS_040_PLUS((mc68kcpu)->cpu_type))
{
- /* TODO */
+ mc68kcpu->mmu_sr_040 = REG_DA(mc68kcpu)[(word2 >> 12) & 15];
return;
}
m68ki_exception_illegal(mc68kcpu);
@@ -6899,7 +6908,7 @@ M68KMAKE_OP(movec, 32, rc, .)
case 0x806: /* URP */
if (CPU_TYPE_IS_040_PLUS((mc68kcpu)->cpu_type))
{
- /* TODO */
+ mc68kcpu->mmu_urp_aptr = REG_DA(mc68kcpu)[(word2 >> 12) & 15];
return;
}
m68ki_exception_illegal(mc68kcpu);
@@ -6907,7 +6916,7 @@ M68KMAKE_OP(movec, 32, rc, .)
case 0x807: /* SRP */
if (CPU_TYPE_IS_040_PLUS((mc68kcpu)->cpu_type))
{
- /* TODO */
+ mc68kcpu->mmu_srp_aptr = REG_DA(mc68kcpu)[(word2 >> 12) & 15];
return;
}
m68ki_exception_illegal(mc68kcpu);
diff --git a/src/emu/cpu/m68000/m68kcpu.c b/src/emu/cpu/m68000/m68kcpu.c
index bd822edc02b..356ecb3c81b 100644
--- a/src/emu/cpu/m68000/m68kcpu.c
+++ b/src/emu/cpu/m68000/m68kcpu.c
@@ -735,20 +735,28 @@ static CPU_TRANSLATE( m68k )
/* only applies to the program address space and only does something if the MMU's enabled */
if (m68k)
{
- if ((space == AS_PROGRAM) && (m68k->pmmu_enabled))
+ /* 68040 needs to call the MMU even when disabled so transparent translation works */
+ if ((space == AS_PROGRAM) && ((m68k->pmmu_enabled) || (CPU_TYPE_IS_040_PLUS(m68k->cpu_type))))
{
// FIXME: mmu_tmp_sr will be overwritten in pmmu_translate_addr_with_fc
UINT16 mmu_tmp_sr = m68k->mmu_tmp_sr;
// UINT32 va=*address;
- *address = pmmu_translate_addr_with_fc(m68k, *address, 4, 1);
+ if (CPU_TYPE_IS_040_PLUS(m68k->cpu_type))
+ {
+ *address = pmmu_translate_addr_with_fc_040(m68k, *address, FUNCTION_CODE_SUPERVISOR_PROGRAM, 1);
+ }
+ else
+ {
+ *address = pmmu_translate_addr_with_fc(m68k, *address, FUNCTION_CODE_SUPERVISOR_PROGRAM, 1);
+ }
if ((m68k->mmu_tmp_sr & M68K_MMU_SR_INVALID) != 0) {
// logerror("cpu_translate_m68k failed with mmu_sr=%04x va=%08x pa=%08x\n",m68k->mmu_tmp_sr,va ,*address);
*address = 0;
}
- m68k->mmu_tmp_sr= mmu_tmp_sr;
+ m68k->mmu_tmp_sr = mmu_tmp_sr;
}
}
return TRUE;
diff --git a/src/emu/cpu/m68000/m68kcpu.h b/src/emu/cpu/m68000/m68kcpu.h
index f1d1dde725d..bcb6fd38d27 100644
--- a/src/emu/cpu/m68000/m68kcpu.h
+++ b/src/emu/cpu/m68000/m68kcpu.h
@@ -692,8 +692,10 @@ public:
/* PMMU registers */
UINT32 mmu_crp_aptr, mmu_crp_limit;
UINT32 mmu_srp_aptr, mmu_srp_limit;
+ UINT32 mmu_urp_aptr; /* 040 only */
UINT32 mmu_tc;
UINT16 mmu_sr;
+ UINT32 mmu_sr_040;
UINT32 mmu_atc_tag[MMU_ATC_ENTRIES], mmu_atc_data[MMU_ATC_ENTRIES];
UINT32 mmu_atc_rr;
UINT32 mmu_tt0, mmu_tt1;
diff --git a/src/emu/cpu/m68000/m68kmmu.h b/src/emu/cpu/m68000/m68kmmu.h
index d00f142e66d..7df23fd31dc 100644
--- a/src/emu/cpu/m68000/m68kmmu.h
+++ b/src/emu/cpu/m68000/m68kmmu.h
@@ -2,7 +2,7 @@
m68kmmu.h - PMMU implementation for 68851/68030/68040
HMMU implementation for 68020 (II and LC variants)
- By R. Belmont
+ By R. Belmont and Hans Ostermeyer
Copyright Nicola Salmoria and the MAME Team.
Visit http://mamedev.org for licensing and usage restrictions.
@@ -148,7 +148,7 @@ void pmmu_atc_add(m68ki_cpu_core *m68k, UINT32 logical, UINT32 physical, int fc)
}
// add the entry
- // logerror("ATC[%2d] add: log %08x -> phys %08x (fc=%d)\n", found, (logical>>ps) << ps, (physical >> ps) << ps, fc);
+ // printf("ATC[%2d] add: log %08x -> phys %08x (fc=%d)\n", found, (logical>>ps) << ps, (physical >> ps) << ps, fc);
m68k->mmu_atc_tag[found] = atc_tag;
m68k->mmu_atc_data[found] = (physical >> ps) << (ps-8);
@@ -166,7 +166,7 @@ void pmmu_atc_add(m68ki_cpu_core *m68k, UINT32 logical, UINT32 physical, int fc)
void pmmu_atc_flush(m68ki_cpu_core *m68k)
{
int i;
- // logerror("ATC flush: pc=%08x\n", REG_PPC(m68k));
+ // printf("ATC flush: pc=%08x\n", REG_PPC(m68k));
for (i = 0; i < MMU_ATC_ENTRIES; i++)
{
@@ -255,13 +255,13 @@ INLINE UINT32 get_dt3_table_entry(m68ki_cpu_core *m68k, UINT32 tptr, UINT8 fc, U
UINT32 address_mask = ((m68k->mmu_tt0 << 8) & 0xff000000) ^ 0xff000000;
if ((addr_in & address_mask) == address_base)
{
-// logerror("PMMU: pc=%x TT0 fc=%x addr_in=%08x address_mask=%08x address_base=%08x\n", m68k->ppc, fc, addr_in, address_mask, address_base);
+// printf("PMMU: pc=%x TT0 fc=%x addr_in=%08x address_mask=%08x address_base=%08x\n", m68k->ppc, fc, addr_in, address_mask, address_base);
return addr_in;
}
}
// if ((++pmmu_access_count % 10000000) == 0) {
-// logerror("pmmu_translate_addr_with_fc: atc usage = %d%%\n", pmmu_atc_count*100/pmmu_access_count);
+// printf("pmmu_translate_addr_with_fc: atc usage = %d%%\n", pmmu_atc_count*100/pmmu_access_count);
// pmmu_atc_count = pmmu_access_count = 0;
// }
@@ -298,7 +298,7 @@ INLINE UINT32 get_dt3_table_entry(m68ki_cpu_core *m68k, UINT32 tptr, UINT8 fc, U
m68k->mmu_tmp_sr = M68K_MMU_SR_MODIFIED;
}
addr_out = (m68k->mmu_atc_data[i] << 8) | (addr_in & ~(~0 << ps));
-// logerror("ATC[%2d] hit: log %08x -> phys %08x pc=%08x fc=%d\n", i, addr_in, addr_out, REG_PPC(m68k), fc);
+// printf("ATC[%2d] hit: log %08x -> phys %08x pc=%08x fc=%d\n", i, addr_in, addr_out, REG_PPC(m68k), fc);
// pmmu_atc_count++;
return addr_out;
}
@@ -323,7 +323,7 @@ INLINE UINT32 get_dt3_table_entry(m68ki_cpu_core *m68k, UINT32 tptr, UINT8 fc, U
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);
+// printf("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);
@@ -338,23 +338,23 @@ INLINE UINT32 get_dt3_table_entry(m68ki_cpu_core *m68k, UINT32 tptr, UINT8 fc, U
case M68K_MMU_DF_DT1: // page descriptor, will cause direct mapping
addr_out = tptr + addr_in;
-// logerror("PMMU: PC=%x root mode %d (addr_in %08x -> %08x)\n", m68k->ppc, M68K_MMU_DF_DT1, addr_in, addr_out);
+// printf("PMMU: PC=%x root mode %d (addr_in %08x -> %08x)\n", m68k->ppc, M68K_MMU_DF_DT1, addr_in, addr_out);
return addr_out;
case M68K_MMU_DF_DT2: // valid 4 byte descriptors
tofs *= 4;
-// if (verbose) logerror("PMMU: reading table A entry at %08x\n", tofs + tptr);
+// if (verbose) printf("PMMU: reading table A entry at %08x\n", tofs + tptr);
tbl_entry = get_dt2_table_entry(m68k, tptr + tofs, ptest);
tamode = tbl_entry & M68K_MMU_DF_DT;
-// if (verbose) logerror("PMMU: addr %08x entry %08x mode %x tofs %x\n", addr_in, tbl_entry, tamode, tofs);
+// if (verbose) printf("PMMU: addr %08x entry %08x mode %x tofs %x\n", addr_in, tbl_entry, tamode, tofs);
break;
case M68K_MMU_DF_DT3: // valid 8 byte descriptors
tofs *= 8;
-// if (verbose) logerror("PMMU: reading table A entries at %08x\n", tofs + tptr);
+// if (verbose) printf("PMMU: reading table A entries at %08x\n", tofs + tptr);
tbl_entry = get_dt3_table_entry(m68k, tofs + tptr, fc, ptest);
tamode = tbl_entry & M68K_MMU_DF_DT;
-// if (verbose) logerror("PMMU: addr %08x entry %08x entry2 %08x mode %x tofs %x\n", addr_in, tbl_entry, tbl_entry2, tamode, tofs);
+// if (verbose) printf("PMMU: addr %08x entry %08x entry2 %08x mode %x tofs %x\n", addr_in, tbl_entry, tbl_entry2, tamode, tofs);
break;
}
@@ -376,19 +376,19 @@ INLINE UINT32 get_dt3_table_entry(m68ki_cpu_core *m68k, UINT32 tptr, UINT8 fc, U
case M68K_MMU_DF_DT2: // 4-byte table B descriptor
tofs *= 4;
-// if (verbose) logerror("PMMU: reading table B entry at %08x\n", tofs + tptr);
+// if (verbose) printf("PMMU: reading table B entry at %08x\n", tofs + tptr);
tbl_entry = get_dt2_table_entry(m68k, tptr + tofs, ptest);
tbmode = tbl_entry & M68K_MMU_DF_DT;
-// if (verbose) logerror("PMMU: addr %08x entry %08x mode %x tofs %x\n", addr_in, tbl_entry, tbmode, tofs);
+// if (verbose) printf("PMMU: addr %08x entry %08x mode %x tofs %x\n", addr_in, tbl_entry, tbmode, tofs);
break;
case M68K_MMU_DF_DT3: // 8-byte table B descriptor
tofs *= 8;
-// if (verbose) logerror("PMMU: reading table B entries at %08x\n", tofs + tptr);
+// if (verbose) printf("PMMU: reading table B entries at %08x\n", tofs + tptr);
tbl_entry = get_dt3_table_entry(m68k, tptr + tofs, fc, ptest);
tbmode = tbl_entry & M68K_MMU_DF_DT;
tbl_entry &= ~M68K_MMU_DF_DT;
-// if (verbose) logerror("PMMU: addr %08x entry %08x entry2 %08x mode %x tofs %x\n", addr_in, tbl_entry, tbl_entry2, tbmode, tofs);
+// if (verbose) printf("PMMU: addr %08x entry %08x entry2 %08x mode %x tofs %x\n", addr_in, tbl_entry, tbl_entry2, tbmode, tofs);
break;
case M68K_MMU_DF_DT1: // early termination descriptor
@@ -420,18 +420,18 @@ INLINE UINT32 get_dt3_table_entry(m68ki_cpu_core *m68k, UINT32 tptr, UINT8 fc, U
case M68K_MMU_DF_DT2: // 4-byte table C descriptor
tofs *= 4;
-// if (verbose) logerror("PMMU: reading table C entry at %08x\n", tofs + tptr);
+// if (verbose) printf("PMMU: reading table C entry at %08x\n", tofs + tptr);
tbl_entry = get_dt2_table_entry(m68k, tptr + tofs, ptest);
tcmode = tbl_entry & M68K_MMU_DF_DT;
-// if (verbose) logerror("PMMU: addr %08x entry %08x mode %x tofs %x\n", addr_in, tbl_entry, tbmode, tofs);
+// if (verbose) printf("PMMU: addr %08x entry %08x mode %x tofs %x\n", addr_in, tbl_entry, tbmode, tofs);
break;
case M68K_MMU_DF_DT3: // 8-byte table C descriptor
tofs *= 8;
-// if (verbose) logerror("PMMU: reading table C entries at %08x\n", tofs + tptr);
+// if (verbose) printf("PMMU: reading table C entries at %08x\n", tofs + tptr);
tbl_entry = get_dt3_table_entry(m68k, tptr+ tofs, fc, ptest);
tcmode = tbl_entry & M68K_MMU_DF_DT;
-// if (verbose) logerror("PMMU: addr %08x entry %08x entry2 %08x mode %x tofs %x\n", addr_in, tbl_entry, tbl_entry2, tcmode, tofs);
+// if (verbose) printf("PMMU: addr %08x entry %08x entry2 %08x mode %x tofs %x\n", addr_in, tbl_entry, tbl_entry2, tcmode, tofs);
break;
case M68K_MMU_DF_DT1: // termination descriptor
@@ -500,7 +500,224 @@ INLINE UINT32 get_dt3_table_entry(m68ki_cpu_core *m68k, UINT32 tptr, UINT8 fc, U
}
}
- //logerror("PMMU: [%08x] => [%08x]\n", addr_in, addr_out);
+ //printf("PMMU: [%08x] => [%08x]\n", addr_in, addr_out);
+
+ return addr_out;
+}
+
+
+// FC bits: 2 = supervisor, 1 = program, 0 = data
+// the 68040 is a subset of the 68851 and 68030 PMMUs - the page table sizes are fixed, there is no early termination, etc, etc.
+/*INLINE*/ static UINT32 pmmu_translate_addr_with_fc_040(m68ki_cpu_core *m68k, UINT32 addr_in, UINT8 fc, UINT8 ptest)
+{
+ UINT32 addr_out, tt0, tt1;
+
+ addr_out = addr_in;
+ m68k->mmu_tmp_sr = 0;
+
+ // transparent translation registers are always in force even if the PMMU itself is disabled
+ // they don't do much in emulation because we never write out of order, but the write-protect and cache control features
+ // are emulatable, and apparently transparent translation regions skip the page table lookup.
+ if (fc & 1) // data, use DTT0/DTT1
+ {
+ tt0 = m68k->mmu_dtt0;
+ tt1 = m68k->mmu_dtt1;
+ }
+ else if (fc & 2) // program, use ITT0/ITT1
+ {
+ tt0 = m68k->mmu_itt0;
+ tt1 = m68k->mmu_itt1;
+ }
+ else
+ {
+ fatalerror("68040: function code %d is neither data nor program!\n", fc&7);
+ }
+
+ if (tt0 & 0x8000)
+ {
+ UINT32 mask = (tt0>>16) & 0xff;
+ mask ^= 0xff;
+ mask <<= 24;
+
+ if ((addr_in & mask) == (tt0 & mask))
+ {
+// printf("TT0 match on address %08x (TT0 = %08x, mask = %08x)\n", addr_in, tt0, mask);
+ if ((tt0 & 4) && !m68k->mmu_tmp_rw && !ptest) // write protect?
+ {
+ if (++m68k->mmu_tmp_buserror_occurred == 1)
+ {
+ m68k->mmu_tmp_buserror_address = addr_in;
+ }
+ }
+
+ return addr_in;
+ }
+ }
+
+ if (tt1 & 0x8000)
+ {
+ UINT32 mask = (tt1>>16) & 0xff;
+ mask ^= 0xff;
+ mask <<= 24;
+
+ if ((addr_in & mask) == (tt1 & mask))
+ {
+// printf("TT1 match on address %08x (TT0 = %08x, mask = %08x)\n", addr_in, tt1, mask);
+ if ((tt1 & 4) && !m68k->mmu_tmp_rw && !ptest) // write protect?
+ {
+ if (++m68k->mmu_tmp_buserror_occurred == 1)
+ {
+ m68k->mmu_tmp_buserror_address = addr_in;
+ }
+ }
+
+ return addr_in;
+ }
+ }
+
+ if (m68k->pmmu_enabled)
+ {
+ UINT32 root_idx = (addr_in>>25) & 0x7f;
+ UINT32 ptr_idx = (addr_in>>18) & 0x7f;
+ UINT32 page_idx, page;
+ UINT32 root_ptr, pointer_ptr, page_ptr;
+ UINT32 root_entry, pointer_entry, page_entry;
+
+ // select supervisor or user root pointer
+ if (fc & 4)
+ {
+ root_ptr = m68k->mmu_srp_aptr + (root_idx<<2);
+ }
+ else
+ {
+ root_ptr = m68k->mmu_urp_aptr + (root_idx<<2);
+ }
+
+ // get the root entry
+ root_entry = m68k->program->read_dword(root_ptr);
+// printf("root entry = %08x\n", root_entry);
+
+ // is UDT marked valid?
+ if (root_entry & 2)
+ {
+ pointer_ptr = (root_entry & ~0x1ff) + (ptr_idx<<2);
+ pointer_entry = m68k->program->read_dword(pointer_ptr);
+
+// printf("pointer entry = %08x\n", pointer_entry);
+
+ // write protected by the root or pointer entries?
+ if ((((root_entry & 4) && !m68k->mmu_tmp_rw) || ((pointer_entry & 4) && !m68k->mmu_tmp_rw)) && !ptest)
+ {
+ if (++m68k->mmu_tmp_buserror_occurred == 1)
+ {
+ m68k->mmu_tmp_buserror_address = addr_in;
+ }
+
+ return addr_in;
+ }
+
+ // is UDT valid on the pointer entry?
+ if (!(pointer_entry & 2) && !ptest)
+ {
+// printf("Invalid pointer entry! PC=%x, addr=%x\n", m68k->ppc, addr_in);
+ if (++m68k->mmu_tmp_buserror_occurred == 1)
+ {
+ m68k->mmu_tmp_buserror_address = addr_in;
+ }
+
+ return addr_in;
+ }
+
+ // (fall out of these ifs into the page lookup below)
+ }
+ else // throw an error
+ {
+// printf("Invalid root entry! PC=%x, addr=%x\n", m68k->ppc, addr_in);
+ if (!ptest)
+ {
+ if (++m68k->mmu_tmp_buserror_occurred == 1)
+ {
+ m68k->mmu_tmp_buserror_address = addr_in;
+ }
+ }
+
+ return addr_in;
+ }
+
+ // now do the page lookup
+ if (m68k->mmu_tc & 0x4000) // 8k pages?
+ {
+ page_idx = (addr_in >> 13) & 0x1f;
+ page = addr_in & 0x1fff;
+ pointer_entry &= ~0x7f;
+
+// printf("8k pages: index %x page %x\n", page_idx, page);
+ }
+ else // 4k pages
+ {
+ page_idx = (addr_in >> 12) & 0x3f;
+ page = addr_in & 0xfff;
+ pointer_entry &= ~0xff;
+
+// printf("4k pages: index %x page %x\n", page_idx, page);
+ }
+
+ page_ptr = pointer_entry + (page_idx<<2);
+ page_entry = m68k->program->read_dword(page_ptr);
+
+// printf("page_entry = %08x\n", page_entry);
+
+ // resolve indirect page pointers
+ while ((page_entry & 3) == 2)
+ {
+ page_entry = m68k->program->read_dword(page_entry & ~0x3);
+ }
+
+ // is the page write protected or supervisor protected?
+ if ((((page_entry & 4) && !m68k->mmu_tmp_rw) || ((page_entry & 0x80) && !(fc&4))) && !ptest)
+ {
+ if (++m68k->mmu_tmp_buserror_occurred == 1)
+ {
+ m68k->mmu_tmp_buserror_address = addr_in;
+ }
+
+ return addr_in;
+ }
+
+ switch (page_entry & 3)
+ {
+ case 0: // invalid
+// printf("Invalid page entry! PC=%x, addr=%x\n", m68k->ppc, addr_in);
+ if (!ptest)
+ {
+ if (++m68k->mmu_tmp_buserror_occurred == 1)
+ {
+ m68k->mmu_tmp_buserror_address = addr_in;
+ }
+ }
+
+ return addr_in;
+
+ case 1:
+ case 3: // normal
+ if (m68k->mmu_tc & 0x4000) // 8k pages?
+ {
+ addr_out = (page_entry & ~0x1fff) | page;
+ }
+ else
+ {
+ addr_out = (page_entry & ~0xfff) | page;
+ }
+
+
+ break;
+
+ case 2: // shouldn't happen
+ fatalerror("68040: got indirect final page pointer, shouldn't be possible\n");
+ break;
+ }
+// if (addr_in != addr_out) printf("040MMU: [%08x] => [%08x]\n", addr_in, addr_out);
+ }
return addr_out;
}
@@ -510,10 +727,19 @@ INLINE UINT32 get_dt3_table_entry(m68ki_cpu_core *m68k, UINT32 tptr, UINT8 fc, U
*/
/*INLINE*/ static UINT32 pmmu_translate_addr(m68ki_cpu_core *m68k, UINT32 addr_in)
{
- UINT32 addr_out = pmmu_translate_addr_with_fc(m68k, addr_in, m68k->mmu_tmp_fc, 0);
+ UINT32 addr_out;
+
+ if (CPU_TYPE_IS_040_PLUS(m68k->cpu_type))
+ {
+ addr_out = pmmu_translate_addr_with_fc_040(m68k, addr_in, m68k->mmu_tmp_fc, 0);
+ }
+ else
+ {
+ addr_out = pmmu_translate_addr_with_fc(m68k, addr_in, m68k->mmu_tmp_fc, 0);
+ }
// if (m68k->mmu_tmp_buserror_occurred > 0) {
-// logerror("PMMU: pc=%08x sp=%08x va=%08x pa=%08x - invalid Table mode for level=%d (buserror %d)\n",
+// printf("PMMU: pc=%08x sp=%08x va=%08x pa=%08x - invalid Table mode for level=%d (buserror %d)\n",
// REG_PPC(m68k), REG_A(m68k)[7], addr_in, addr_out, m68k->mmu_tmp_sr & M68K_MMU_SR_LEVEL_3,
// m68k->mmu_tmp_buserror_occurred);
// }
@@ -522,8 +748,7 @@ INLINE UINT32 get_dt3_table_entry(m68ki_cpu_core *m68k, UINT32 tptr, UINT8 fc, U
}
/*
- m68881_mmu_ops: COP 0 MMU opcode handling
-
+ m68851_mmu_ops: COP 0 MMU opcode handling
*/
void m68881_mmu_ops(m68ki_cpu_core *m68k)
@@ -536,12 +761,12 @@ void m68881_mmu_ops(m68ki_cpu_core *m68k)
// catch the 2 "weird" encodings up front (PBcc)
if ((m68k->ir & 0xffc0) == 0xf0c0)
{
- logerror("680x0: unhandled PBcc\n");
+ printf("680x0: unhandled PBcc\n");
return;
}
else if ((m68k->ir & 0xffc0) == 0xf080)
{
- logerror("680x0: unhandled PBcc\n");
+ printf("680x0: unhandled PBcc\n");
return;
}
else // the rest are 1111000xxxXXXXXX where xxx is the instruction family
@@ -559,10 +784,17 @@ void m68881_mmu_ops(m68ki_cpu_core *m68k)
ptmp = ltmp;
if (m68k->pmmu_enabled)
{
- ptmp = pmmu_translate_addr_with_fc(m68k, ltmp, modes & 0x07, 0);
+ if (CPU_TYPE_IS_040_PLUS(m68k->cpu_type))
+ {
+ ptmp = pmmu_translate_addr_with_fc_040(m68k, ltmp, modes & 0x07, 0);
+ }
+ else
+ {
+ ptmp = pmmu_translate_addr_with_fc(m68k, ltmp, modes & 0x07, 0);
+ }
}
- logerror("680x0: PLOADing ATC with logical %08x => phys %08x\n", ltmp, ptmp);
+ printf("680x0: PLOADing ATC with logical %08x => phys %08x\n", ltmp, ptmp);
// FIXME: rw bit?
pmmu_atc_add(m68k, ltmp, ptmp, modes & 0x07);
return;
@@ -579,12 +811,12 @@ void m68881_mmu_ops(m68ki_cpu_core *m68k)
}
else if (modes == 0x2800) // PVALID (FORMAT 1)
{
- logerror("680x0: unhandled PVALID1\n");
+ printf("680x0: unhandled PVALID1\n");
return;
}
else if ((modes & 0xfff8) == 0x2c00) // PVALID (FORMAT 2)
{
- logerror("680x0: unhandled PVALID2\n");
+ printf("680x0: unhandled PVALID2\n");
return;
}
else if ((modes & 0xe000) == 0x8000) // PTEST
@@ -604,10 +836,17 @@ void m68881_mmu_ops(m68ki_cpu_core *m68k)
break;
}
- p_addr = pmmu_translate_addr_with_fc(m68k, v_addr, fc, 1);
+ if (CPU_TYPE_IS_040_PLUS(m68k->cpu_type))
+ {
+ p_addr = pmmu_translate_addr_with_fc_040(m68k, v_addr, fc, 1);
+ }
+ else
+ {
+ p_addr = pmmu_translate_addr_with_fc(m68k, v_addr, fc, 1);
+ }
m68k->mmu_sr = m68k->mmu_tmp_sr;
-// logerror("PMMU: pc=%08x sp=%08x va=%08x pa=%08x PTEST fc=%x level=%x mmu_sr=%04x\n",
+// printf("PMMU: pc=%08x sp=%08x va=%08x pa=%08x PTEST fc=%x level=%x mmu_sr=%04x\n",
// m68k->ppc, REG_A(m68k)[7], v_addr, p_addr, fc, (modes >> 10) & 0x07, m68k->mmu_sr);
if (modes & 0x100)
@@ -629,29 +868,29 @@ void m68881_mmu_ops(m68ki_cpu_core *m68k)
{
case 0x02: // transparent translation register 0
WRITE_EA_32(m68k, ea, m68k->mmu_tt0);
-// logerror("PMMU: pc=%x PMOVE from mmu_tt0=%08x\n", m68k->ppc, m68k->mmu_tt0);
+// printf("PMMU: pc=%x PMOVE from mmu_tt0=%08x\n", m68k->ppc, m68k->mmu_tt0);
break;
case 0x03: // transparent translation register 1
WRITE_EA_32(m68k, ea, m68k->mmu_tt1);
-// logerror("PMMU: pc=%x PMOVE from mmu_tt1=%08x\n", m68k->ppc, m68k->mmu_tt1);
+// printf("PMMU: pc=%x PMOVE from mmu_tt1=%08x\n", m68k->ppc, m68k->mmu_tt1);
break;
case 0x10: // translation control register
WRITE_EA_32(m68k, ea, m68k->mmu_tc);
-// logerror("PMMU: pc=%x PMOVE from mmu_tc=%08x\n", m68k->ppc, m68k->mmu_tc);
+// printf("PMMU: pc=%x PMOVE from mmu_tc=%08x\n", m68k->ppc, m68k->mmu_tc);
break;
case 0x12: // supervisor root pointer
WRITE_EA_64(m68k, ea, (UINT64)m68k->mmu_srp_limit<<32 | (UINT64)m68k->mmu_srp_aptr);
-// logerror("PMMU: pc=%x PMOVE from SRP limit = %08x, aptr = %08x\n", REG_PPC(m68k), m68k->mmu_srp_limit, m68k->mmu_srp_aptr);
+// printf("PMMU: pc=%x PMOVE from SRP limit = %08x, aptr = %08x\n", REG_PPC(m68k), m68k->mmu_srp_limit, m68k->mmu_srp_aptr);
break;
case 0x13: // CPU root pointer
WRITE_EA_64(m68k, ea, (UINT64)m68k->mmu_crp_limit<<32 | (UINT64)m68k->mmu_crp_aptr);
-// logerror("PMMU: pc=%x PMOVE from CRP limit = %08x, aptr = %08x\n", REG_PPC(m68k), m68k->mmu_crp_limit, m68k->mmu_crp_aptr);
+// printf("PMMU: pc=%x PMOVE from CRP limit = %08x, aptr = %08x\n", REG_PPC(m68k), m68k->mmu_crp_limit, m68k->mmu_crp_aptr);
break;
default:
- logerror("680x0: PMOVE from unknown MMU register %x, PC %x\n", (modes>>10) & 7, m68k->pc);
+ printf("680x0: PMOVE from unknown MMU register %x, PC %x\n", (modes>>10) & 7, m68k->pc);
break;
}
@@ -676,7 +915,7 @@ void m68881_mmu_ops(m68ki_cpu_core *m68k)
break;
case 1:
- logerror("680x0: unknown PMOVE case 1, PC %x\n", m68k->pc);
+ printf("680x0: unknown PMOVE case 1, PC %x\n", m68k->pc);
break;
case 2:
@@ -684,17 +923,17 @@ void m68881_mmu_ops(m68ki_cpu_core *m68k)
{
case 0: // translation control register
m68k->mmu_tc = READ_EA_32(m68k, ea);
-// logerror("PMMU: TC = %08x\n", m68k->mmu_tc);
+// printf("PMMU: TC = %08x\n", m68k->mmu_tc);
if (m68k->mmu_tc & 0x80000000)
{
m68k->pmmu_enabled = 1;
-// logerror("PMMU enabled\n");
+// printf("PMMU enabled\n");
}
else
{
m68k->pmmu_enabled = 0;
-// logerror("PMMU disabled\n");
+// printf("PMMU disabled\n");
}
if (!(modes & 0x100)) // flush ATC on moves to TC, SRP, CRP with FD bit clear
@@ -707,7 +946,7 @@ void m68881_mmu_ops(m68ki_cpu_core *m68k)
temp64 = READ_EA_64(m68k, ea);
m68k->mmu_srp_limit = (temp64>>32) & 0xffffffff;
m68k->mmu_srp_aptr = temp64 & 0xffffffff;
-// logerror("PMMU: SRP limit = %08x aptr = %08x\n", m68k->mmu_srp_limit, m68k->mmu_srp_aptr);
+// printf("PMMU: SRP limit = %08x aptr = %08x\n", m68k->mmu_srp_limit, m68k->mmu_srp_aptr);
if (!(modes & 0x100))
{
pmmu_atc_flush(m68k);
@@ -718,7 +957,7 @@ void m68881_mmu_ops(m68ki_cpu_core *m68k)
temp64 = READ_EA_64(m68k, ea);
m68k->mmu_crp_limit = (temp64>>32) & 0xffffffff;
m68k->mmu_crp_aptr = temp64 & 0xffffffff;
-// logerror("PMMU: CRP limit = %08x aptr = %08x\n", m68k->mmu_crp_limit, m68k->mmu_crp_aptr);
+// printf("PMMU: CRP limit = %08x aptr = %08x\n", m68k->mmu_crp_limit, m68k->mmu_crp_aptr);
if (!(modes & 0x100))
{
pmmu_atc_flush(m68k);
@@ -726,7 +965,7 @@ void m68881_mmu_ops(m68ki_cpu_core *m68k)
break;
default:
- logerror("680x0: PMOVE to unknown MMU register %x, PC %x\n", (modes>>10) & 7, m68k->pc);
+ printf("680x0: PMOVE to unknown MMU register %x, PC %x\n", (modes>>10) & 7, m68k->pc);
break;
}
break;
@@ -734,7 +973,7 @@ void m68881_mmu_ops(m68ki_cpu_core *m68k)
case 3: // MMU status
{
UINT32 temp = READ_EA_32(m68k, ea);
- logerror("680x0: unsupported PMOVE %x to MMU status, PC %x\n", temp, m68k->pc);
+ printf("680x0: unsupported PMOVE %x to MMU status, PC %x\n", temp, m68k->pc);
}
break;
}
@@ -753,7 +992,7 @@ void m68881_mmu_ops(m68ki_cpu_core *m68k)
break;
default:
- logerror("680x0: unknown PMOVE mode %x (modes %04x) (PC %x)\n", (modes>>13) & 0x7, modes, m68k->pc);
+ printf("680x0: unknown PMOVE mode %x (modes %04x) (PC %x)\n", (modes>>13) & 0x7, modes, m68k->pc);
break;
}
@@ -761,7 +1000,7 @@ void m68881_mmu_ops(m68ki_cpu_core *m68k)
break;
default:
- logerror("680x0: unknown PMMU instruction group %d\n", (m68k->ir>>9) & 0x7);
+ printf("680x0: unknown PMMU instruction group %d\n", (m68k->ir>>9) & 0x7);
break;
}
}