m68k: preliminary 68040 MMU implementation [R. Belmont]

This commit is contained in:
R. Belmont 2011-10-08 23:02:59 +00:00
parent ec6a340d1d
commit f8aba531d3
4 changed files with 318 additions and 60 deletions

View File

@ -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);

View File

@ -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;

View File

@ -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;

View File

@ -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;
}
}