sh4/mmu: Import the old mmu implementation from nullDC.

Reicast doesn't support exceptions yet, so this isn't of much use now,
and is intended mostly as documentation. nullDC used some call stack
hooking magic to handle exceptions, which was never generic and clean
enough to be worth the effort to port to Reicast.
This commit is contained in:
Stefanos Kornilios Mitsis Poiitidis 2015-08-27 16:57:22 +02:00
parent 053ea61137
commit dcd77326cc
9 changed files with 745 additions and 11 deletions

View File

@ -258,3 +258,17 @@ void Sh4_int_Term()
Sh4_int_Stop(); Sh4_int_Stop();
printf("Sh4 Term\n"); printf("Sh4 Term\n");
} }
/*
bool sh4_exept_raised;
void sh4_int_RaiseExeption(u32 ExeptionCode, u32 VectorAddress)
{
sh4_exept_raised = true;
sh4_ex_ExeptionCode = ExeptionCode;
sh4_ex_VectorAddress = VectorAddress;
//save reg context
SaveSh4Regs(&sh4_ex_SRC);
}
*/

View File

@ -1265,7 +1265,8 @@ INLINE void DYNACALL do_sqw(u32 Dest)
//Translate the SQ addresses as needed //Translate the SQ addresses as needed
if (mmu_on) if (mmu_on)
{ {
Address=mmu_TranslateSQW(Dest); if (!mmu_TranslateSQW(Dest, &Address))
return;
} }
else else
{ {

View File

@ -7,15 +7,17 @@
#include "hw/mem/_vmem.h" #include "hw/mem/_vmem.h"
//SQ fast remap , mainly hackish , assumes 1MB pages
//max 64MB can be remapped on SQ
u32 sq_remap[64];
TLB_Entry UTLB[64]; TLB_Entry UTLB[64];
TLB_Entry ITLB[4]; TLB_Entry ITLB[4];
#if defined(NO_MMU)
//SQ fast remap , mainly hackish , assumes 1MB pages
//max 64MB can be remapped on SQ
u32 sq_remap[64];
//Sync memory mapping to MMU , suspend compiled blocks if needed.entry is a UTLB entry # , -1 is for full sync //Sync memory mapping to MMU , suspend compiled blocks if needed.entry is a UTLB entry # , -1 is for full sync
void UTLB_Sync(u32 entry) bool UTLB_Sync(u32 entry)
{ {
if ((UTLB[entry].Address.VPN & (0xFC000000 >> 10)) == (0xE0000000 >> 10)) if ((UTLB[entry].Address.VPN & (0xFC000000 >> 10)) == (0xE0000000 >> 10))
{ {
@ -27,6 +29,8 @@ void UTLB_Sync(u32 entry)
{ {
printf("MEM remap %d : 0x%X to 0x%X\n", entry, UTLB[entry].Address.VPN << 10, UTLB[entry].Data.PPN << 10); printf("MEM remap %d : 0x%X to 0x%X\n", entry, UTLB[entry].Address.VPN << 10, UTLB[entry].Data.PPN << 10);
} }
return true;
} }
//Sync memory mapping to MMU, suspend compiled blocks if needed.entry is a ITLB entry # , -1 is for full sync //Sync memory mapping to MMU, suspend compiled blocks if needed.entry is a ITLB entry # , -1 is for full sync
void ITLB_Sync(u32 entry) void ITLB_Sync(u32 entry)
@ -48,3 +52,661 @@ void MMU_reset()
void MMU_term() void MMU_term()
{ {
} }
#else
/*
MMU support code
This is mostly hacked-on as the core was never meant to have mmu support
There are two modes, one with 'full' mmu emulation (for wince/bleem/wtfever)
and a fast-hack mode for 1mb sqremaps (for katana)
defining NO_MMU disables the full mmu emulation
*/
#include "mmu.h"
#include "mmu_impl.h"
#include "hw/sh4/sh4_if.h"
#include "ccn.h"
#include "hw/sh4/sh4_interrupts.h"
#include "hw/sh4/sh4_if.h"
#include "hw/mem/_vmem.h"
#define printf_mmu
#define printf_win32 log
//SQ fast remap , mailny hackish , assumes 1 mb pages
//max 64 mb can be remapped on SQ
const u32 mmu_mask[4] =
{
((0xFFFFFFFF) >> 10) << 10, //1 kb page
((0xFFFFFFFF) >> 12) << 12, //4 kb page
((0xFFFFFFFF) >> 16) << 16, //64 kb page
((0xFFFFFFFF) >> 20) << 20 //1 MB page
};
const u32 fast_reg_lut[8] =
{
0, 0, 0, 0 //P0-U0
, 1 //P1
, 1 //P2
, 0 //P3
, 1 //P4
};
const u32 ITLB_LRU_OR[4] =
{
0x00,//000xxx
0x20,//1xx00x
0x14,//x1x1x0
0x0B,//xx1x11
};
const u32 ITLB_LRU_AND[4] =
{
0x07,//000xxx
0x39,//1xx00x
0x3E,//x1x1x0
0x3F,//xx1x11
};
u32 ITLB_LRU_USE[64];
//sync mem mapping to mmu , suspend compiled blocks if needed.entry is a UTLB entry # , -1 is for full sync
bool UTLB_Sync(u32 entry)
{
printf_mmu("UTLB MEM remap %d : 0x%X to 0x%X : %d\n", entry, UTLB[entry].Address.VPN << 10, UTLB[entry].Data.PPN << 10, UTLB[entry].Data.V);
if (UTLB[entry].Data.V == 0)
return true;
if ((UTLB[entry].Address.VPN & (0xFC000000 >> 10)) == (0xE0000000 >> 10))
{
#ifdef NO_MMU
u32 vpn_sq = ((UTLB[entry].Address.VPN & (0x3FFFFFF >> 10)) >> 10) & 0x3F;//upper bits are allways known [0xE0/E1/E2/E3]
sq_remap[vpn_sq] = UTLB[entry].Data.PPN << 10;
log("SQ remap %d : 0x%X to 0x%X\n", entry, UTLB[entry].Address.VPN << 10, UTLB[entry].Data.PPN << 10);
#endif
return true;
}
else
{
#ifdef NO_MMU
if ((UTLB[entry].Address.VPN&(0x1FFFFFFF >> 10)) == (UTLB[entry].Data.PPN&(0x1FFFFFFF >> 10)))
{
log("Static remap %d : 0x%X to 0x%X\n", entry, UTLB[entry].Address.VPN << 10, UTLB[entry].Data.PPN << 10);
return true;
}
log("Dynamic remap %d : 0x%X to 0x%X\n", entry, UTLB[entry].Address.VPN << 10, UTLB[entry].Data.PPN << 10);
#endif
return false;//log("MEM remap %d : 0x%X to 0x%X\n",entry,UTLB[entry].Address.VPN<<10,UTLB[entry].Data.PPN<<10);
}
}
//sync mem mapping to mmu , suspend compiled blocks if needed.entry is a ITLB entry # , -1 is for full sync
void ITLB_Sync(u32 entry)
{
printf_mmu("ITLB MEM remap %d : 0x%X to 0x%X : %d\n", entry, ITLB[entry].Address.VPN << 10, ITLB[entry].Data.PPN << 10, ITLB[entry].Data.V);
}
void RaiseException(u32 a, u32 b) {
msgboxf("Can't raise exceptions yet", MBX_ICONERROR);
}
u32 mmu_error_TT;
void mmu_raise_exeption(u32 mmu_error, u32 address, u32 am)
{
printf_mmu("mmu_raise_exeption -> pc = 0x%X : ", next_pc);
CCN_TEA = address;
CCN_PTEH.VPN = address >> 10;
//save translation type error :)
mmu_error_TT = am;
switch (mmu_error)
{
//No error
case MMU_ERROR_NONE:
printf("Error : mmu_raise_exeption(MMU_ERROR_NONE)\n");
getc(stdin);
break;
//TLB miss
case MMU_ERROR_TLB_MISS:
printf_mmu("MMU_ERROR_UTLB_MISS 0x%X, handled\n", address);
if (am == MMU_TT_DWRITE) //WTLBMISS - Write Data TLB Miss Exception
RaiseException(0x60, 0x400);
else if (am == MMU_TT_DREAD) //RTLBMISS - Read Data TLB Miss Exception
RaiseException(0x40, 0x400);
else //ITLBMISS - Instruction TLB Miss Exception
RaiseException(0x40, 0x400);
return;
break;
//TLB Multyhit
case MMU_ERROR_TLB_MHIT:
printf("MMU_ERROR_TLB_MHIT @ 0x%X\n", address);
break;
//Mem is read/write protected (depends on translation type)
case MMU_ERROR_PROTECTED:
printf_mmu("MMU_ERROR_PROTECTED 0x%X, handled\n", address);
if (am == MMU_TT_DWRITE) //WRITEPROT - Write Data TLB Protection Violation Exception
RaiseException(0xC0, 0x100);
else if (am == MMU_TT_DREAD) //READPROT - Data TLB Protection Violation Exception
RaiseException(0xA0, 0x100);
else
{
verify(false);
}
return;
break;
//Mem is write protected , firstwrite
case MMU_ERROR_FIRSTWRITE:
printf_mmu("MMU_ERROR_FIRSTWRITE\n");
verify(am == MMU_TT_DWRITE);
//FIRSTWRITE - Initial Page Write Exception
RaiseException(0x80, 0x100);
return;
break;
//data read/write missasligned
case MMU_ERROR_BADADDR:
if (am == MMU_TT_DWRITE) //WADDERR - Write Data Address Error
RaiseException(0x100, 0x100);
else if (am == MMU_TT_DREAD) //RADDERR - Read Data Address Error
RaiseException(0xE0, 0x100);
else //IADDERR - Instruction Address Error
{
printf("MMU_ERROR_BADADDR(i) 0x%X\n", address);
RaiseException(0xE0, 0x100);
return;
}
printf_mmu("MMU_ERROR_BADADDR(d) 0x%X, handled\n", address);
return;
break;
//Can't Execute
case MMU_ERROR_EXECPROT:
printf("MMU_ERROR_EXECPROT 0x%X\n", address);
//EXECPROT - Instruction TLB Protection Violation Exception
RaiseException(0xA0, 0x100);
return;
break;
}
__debugbreak();
}
bool mmu_match(u32 va, CCN_PTEH_type Address, CCN_PTEL_type Data)
{
if (Data.V == 0)
return false;
u32 sz = Data.SZ1 * 2 + Data.SZ0;
u32 mask = mmu_mask[sz];
if ((((Address.VPN << 10)&mask) == (va&mask)))
{
bool asid_match = (Data.SH == 0) && ((sr.MD == 0) || (CCN_MMUCR.SV == 0));
if ((asid_match == false) || (Address.ASID == CCN_PTEH.ASID))
{
return true;
}
}
return false;
}
//Do a full lookup on the UTLB entry's
u32 mmu_full_lookup(u32 va, u32& idx, u32& rv)
{
CCN_MMUCR.URC++;
if (CCN_MMUCR.URB == CCN_MMUCR.URC)
CCN_MMUCR.URC = 0;
u32 entry = 0;
u32 nom = 0;
for (u32 i = 0; i<64; i++)
{
//verify(sz!=0);
if (mmu_match(va, UTLB[i].Address, UTLB[i].Data))
{
entry = i;
nom++;
u32 sz = UTLB[i].Data.SZ1 * 2 + UTLB[i].Data.SZ0;
u32 mask = mmu_mask[sz];
//VPN->PPN | low bits
rv = ((UTLB[i].Data.PPN << 10)&mask) | (va&(~mask));
}
}
if (nom != 1)
{
if (nom)
{
return MMU_ERROR_TLB_MHIT;
}
else
{
return MMU_ERROR_TLB_MISS;
}
}
idx = entry;
return MMU_ERROR_NONE;
}
//Simple QACR translation for mmu (when AT is off)
u32 mmu_QACR_SQ(u32 va)
{
u32 QACR;
//default to sq 0
QACR = CCN_QACR_TR[0];
//sq1 ? if so use QACR1
if (va & 0x20)
QACR = CCN_QACR_TR[1];
va &= ~0x1f;
return QACR + va;
}
template<u32 translation_type>
u32 mmu_full_SQ(u32 va, u32& rv)
{
if ((va & 3) || (CCN_MMUCR.SQMD == 1 && sr.MD == 0))
{
//here, or after ?
return MMU_ERROR_BADADDR;
}
if (CCN_MMUCR.AT)
{
//Address=Dest&0xFFFFFFE0;
u32 entry;
u32 lookup = mmu_full_lookup(va, entry, rv);
rv &= ~31;//lower 5 bits are forced to 0
if (lookup != MMU_ERROR_NONE)
return lookup;
u32 md = UTLB[entry].Data.PR >> 1;
//Priv mode protection
if ((md == 0) && sr.MD == 0)
{
return MMU_ERROR_PROTECTED;
}
//Write Protection (Lock or FW)
if (translation_type == MMU_TT_DWRITE)
{
if ((UTLB[entry].Data.PR & 1) == 0)
return MMU_ERROR_PROTECTED;
else if (UTLB[entry].Data.D == 0)
return MMU_ERROR_FIRSTWRITE;
}
}
else
{
rv = mmu_QACR_SQ(va);
}
return MMU_ERROR_NONE;
}
template<u32 translation_type>
u32 mmu_data_translation(u32 va, u32& rv)
{
//*opt notice* this could be only checked for writes, as reads are invalid
if ((va & 0xFC000000) == 0xE0000000)
{
u32 lookup = mmu_full_SQ<translation_type>(va, rv);
if (lookup != MMU_ERROR_NONE)
return lookup;
rv = va; //SQ writes are not translated, only write backs are.
return MMU_ERROR_NONE;
}
if ((sr.MD == 0) && (va & 0x80000000) != 0)
{
//if on kernel, and not SQ addr -> error
return MMU_ERROR_BADADDR;
}
if (sr.MD == 1 && ((va & 0xFC000000) == 0x7C000000))
{
rv = va;
return MMU_ERROR_NONE;
}
if ((CCN_MMUCR.AT == 0) || (fast_reg_lut[va >> 29] != 0))
{
rv = va;
return MMU_ERROR_NONE;
}
/*
if ( CCN_CCR.ORA && ((va&0xFC000000)==0x7C000000))
{
verify(false);
return va;
}
*/
u32 entry;
u32 lookup = mmu_full_lookup(va, entry, rv);
if (lookup != MMU_ERROR_NONE)
return lookup;
u32 md = UTLB[entry].Data.PR >> 1;
//0X & User mode-> protection violation
//Priv mode protection
if ((md == 0) && sr.MD == 0)
{
return MMU_ERROR_PROTECTED;
}
//X0 -> read olny
//X1 -> read/write , can be FW
//Write Protection (Lock or FW)
if (translation_type == MMU_TT_DWRITE)
{
if ((UTLB[entry].Data.PR & 1) == 0)
return MMU_ERROR_PROTECTED;
else if (UTLB[entry].Data.D == 0)
return MMU_ERROR_FIRSTWRITE;
}
return MMU_ERROR_NONE;
}
u32 mmu_instruction_translation(u32 va, u32& rv)
{
if ((sr.MD == 0) && (va & 0x80000000) != 0)
{
//if SQ disabled , or if if SQ on but out of SQ mem then BAD ADDR ;)
if (va >= 0xE0000000)
return MMU_ERROR_BADADDR;
}
if ((CCN_MMUCR.AT == 0) || (fast_reg_lut[va >> 29] != 0))
{
rv = va;
return MMU_ERROR_NONE;
}
bool mmach = false;
retry_ITLB_Match:
u32 entry = 4;
u32 nom = 0;
for (u32 i = 0; i<4; i++)
{
if (ITLB[i].Data.V == 0)
continue;
u32 sz = ITLB[i].Data.SZ1 * 2 + ITLB[i].Data.SZ0;
u32 mask = mmu_mask[sz];
if ((((ITLB[i].Address.VPN << 10)&mask) == (va&mask)))
{
bool asid_match = (ITLB[i].Data.SH == 0) && ((sr.MD == 0) || (CCN_MMUCR.SV == 0));
if ((asid_match == false) || (ITLB[i].Address.ASID == CCN_PTEH.ASID))
{
//verify(sz!=0);
entry = i;
nom++;
//VPN->PPN | low bits
rv = ((ITLB[i].Data.PPN << 10)&mask) | (va&(~mask));
}
}
}
if (entry == 4)
{
verify(mmach == false);
u32 lookup = mmu_full_lookup(va, entry, rv);
if (lookup != MMU_ERROR_NONE)
return lookup;
u32 replace_index = ITLB_LRU_USE[CCN_MMUCR.LRUI];
verify(replace_index != 0xFFFFFFFF);
ITLB[replace_index] = UTLB[entry];
entry = replace_index;
ITLB_Sync(entry);
mmach = true;
goto retry_ITLB_Match;
}
else if (nom != 1)
{
if (nom)
{
return MMU_ERROR_TLB_MHIT;
}
else
{
return MMU_ERROR_TLB_MISS;
}
}
CCN_MMUCR.LRUI &= ITLB_LRU_AND[entry];
CCN_MMUCR.LRUI |= ITLB_LRU_OR[entry];
u32 md = ITLB[entry].Data.PR >> 1;
//0X & User mode-> protection violation
//Priv mode protection
if ((md == 0) && sr.MD == 0)
{
return MMU_ERROR_PROTECTED;
}
return MMU_ERROR_NONE;
}
void MMU_init()
{
memset(ITLB_LRU_USE, 0xFF, sizeof(ITLB_LRU_USE));
for (u32 e = 0; e<4; e++)
{
u32 match_key = ((~ITLB_LRU_AND[e]) & 0x3F);
u32 match_mask = match_key | ITLB_LRU_OR[e];
for (u32 i = 0; i<64; i++)
{
if ((i & match_mask) == match_key)
{
verify(ITLB_LRU_USE[i] == 0xFFFFFFFF);
ITLB_LRU_USE[i] = e;
}
}
}
}
void MMU_reset()
{
memset(UTLB, 0, sizeof(UTLB));
memset(ITLB, 0, sizeof(ITLB));
}
void MMU_term()
{
}
u8 DYNACALL mmu_ReadMem8(u32 adr)
{
u32 addr;
u32 tv = mmu_data_translation<MMU_TT_DREAD>(adr, addr);
if (tv == 0)
return _vmem_ReadMem8(addr);
else
mmu_raise_exeption(tv, adr, MMU_TT_DREAD);
return 0;
}
u16 DYNACALL mmu_ReadMem16(u32 adr)
{
if (adr & 1)
{
mmu_raise_exeption(MMU_ERROR_BADADDR, adr, MMU_TT_DREAD);
return 0;
}
u32 addr;
u32 tv = mmu_data_translation<MMU_TT_DREAD>(adr, addr);
if (tv == 0)
return _vmem_ReadMem16(addr);
else
mmu_raise_exeption(tv, adr, MMU_TT_DREAD);
return 0;
}
u16 DYNACALL mmu_IReadMem16(u32 adr)
{
if (adr & 1)
{
mmu_raise_exeption(MMU_ERROR_BADADDR, adr, MMU_TT_IREAD);
return 0;
}
u32 addr;
u32 tv = mmu_instruction_translation(adr, addr);
if (tv == 0)
return _vmem_ReadMem16(addr);
else
mmu_raise_exeption(tv, adr, MMU_TT_IREAD);
return 0;
}
u32 DYNACALL mmu_ReadMem32(u32 adr)
{
if (adr & 3)
{
mmu_raise_exeption(MMU_ERROR_BADADDR, adr, MMU_TT_DREAD);
return 0;
}
u32 addr;
u32 tv = mmu_data_translation<MMU_TT_DREAD>(adr, addr);
if (tv == 0)
return _vmem_ReadMem32(addr);
else
mmu_raise_exeption(tv, adr, MMU_TT_DREAD);
return 0;
}
u64 DYNACALL mmu_ReadMem64(u32 adr)
{
if (adr & 7)
{
mmu_raise_exeption(MMU_ERROR_BADADDR, adr, MMU_TT_DREAD);
return 0;
}
u32 addr;
u32 tv = mmu_data_translation<MMU_TT_DREAD>(adr, addr);
if (tv == 0)
{
return _vmem_ReadMem64(addr);
}
else
mmu_raise_exeption(tv, adr, MMU_TT_DREAD);
return 0;
}
void DYNACALL mmu_WriteMem8(u32 adr, u8 data)
{
u32 addr;
u32 tv = mmu_data_translation<MMU_TT_DWRITE>(adr, addr);
if (tv == 0)
{
_vmem_WriteMem8(addr, data);
return;
}
else
mmu_raise_exeption(tv, adr, MMU_TT_DWRITE);
}
void DYNACALL mmu_WriteMem16(u32 adr, u16 data)
{
if (adr & 1)
{
mmu_raise_exeption(MMU_ERROR_BADADDR, adr, MMU_TT_DWRITE);
return;
}
u32 addr;
u32 tv = mmu_data_translation<MMU_TT_DWRITE>(adr, addr);
if (tv == 0)
{
_vmem_WriteMem16(addr, data);
return;
}
else
mmu_raise_exeption(tv, adr, MMU_TT_DWRITE);
}
void DYNACALL mmu_WriteMem32(u32 adr, u32 data)
{
if (adr & 3)
{
mmu_raise_exeption(MMU_ERROR_BADADDR, adr, MMU_TT_DWRITE);
return;
}
u32 addr;
u32 tv = mmu_data_translation<MMU_TT_DWRITE>(adr, addr);
if (tv == 0)
{
_vmem_WriteMem32(addr, data);
return;
}
else
mmu_raise_exeption(tv, adr, MMU_TT_DWRITE);
}
void DYNACALL mmu_WriteMem64(u32 adr, u64 data)
{
if (adr & 7)
{
mmu_raise_exeption(MMU_ERROR_BADADDR, adr, MMU_TT_DWRITE);
return;
}
u32 addr;
u32 tv = mmu_data_translation<MMU_TT_DWRITE>(adr, addr);
if (tv == 0)
{
_vmem_WriteMem64(addr, data);
return;
}
else
mmu_raise_exeption(tv, adr, MMU_TT_DWRITE);
}
bool mmu_TranslateSQW(u32 adr, u32* out)
{
#ifndef NO_MMU
u32 addr;
u32 tv = mmu_full_SQ<MMU_TT_DREAD>(adr, addr);
if (tv != 0)
{
mmu_raise_exeption(tv, adr, MMU_TT_DREAD);
return false;
}
*out = addr;
#else
//This will olny work for 1 mb pages .. hopefully nothing else is used
//*FIXME* to work for all page sizes ?
if (CCN_MMUCR.AT == 0)
{ //simple translation
*out = mmu_QACR_SQ(adr);
}
else
{ //remap table
*out = sq_remap[(adr >> 20) & 0x3F] | (adr & 0xFFFE0);
}
#endif
return true;
}
#endif

View File

@ -13,7 +13,25 @@ extern TLB_Entry ITLB[4];
extern u32 sq_remap[64]; extern u32 sq_remap[64];
//These are working only for SQ remaps on ndce //These are working only for SQ remaps on ndce
void UTLB_Sync(u32 entry); bool UTLB_Sync(u32 entry);
void ITLB_Sync(u32 entry); void ITLB_Sync(u32 entry);
#define mmu_TranslateSQW(adr) (sq_remap[(adr>>20)&0x3F] | (adr & 0xFFFE0)) #if defined(NO_MMU)
bool inline mmu_TranslateSQW(u32 addr, u32* mapped) {
*mapped = sq_remap[(addr>>20)&0x3F] | (addr & 0xFFFE0);
return true;
}
#else
u8 DYNACALL mmu_ReadMem8(u32 addr);
u16 DYNACALL mmu_ReadMem16(u32 addr);
u16 DYNACALL mmu_IReadMem16(u32 addr);
u32 DYNACALL mmu_ReadMem32(u32 addr);
u64 DYNACALL mmu_ReadMem64(u32 addr);
void DYNACALL mmu_WriteMem8(u32 addr, u8 data);
void DYNACALL mmu_WriteMem16(u32 addr, u16 data);
void DYNACALL mmu_WriteMem32(u32 addr, u32 data);
void DYNACALL mmu_WriteMem64(u32 addr, u64 data);
bool mmu_TranslateSQW(u32 addr, u32* mapped);
#endif

View File

@ -0,0 +1,37 @@
#pragma once
#include "types.h"
#include "ccn.h"
#include "mmu.h"
//Do a full lookup on the UTLB entry's
//Return Values
//Translation was sucessfull , rv contains return
#define MMU_ERROR_NONE 0
//TLB miss
#define MMU_ERROR_TLB_MISS 1
//TLB Multyhit
#define MMU_ERROR_TLB_MHIT 2
//Mem is read/write protected (depends on translation type)
#define MMU_ERROR_PROTECTED 3
//Mem is write protected , firstwrite
#define MMU_ERROR_FIRSTWRITE 4
//data-Opcode read/write missasligned
#define MMU_ERROR_BADADDR 5
//Can't Execute
#define MMU_ERROR_EXECPROT 6
//Translation Types
//Opcode read
#define MMU_TT_IREAD 0
//Data write
#define MMU_TT_DWRITE 1
//Data write
#define MMU_TT_DREAD 2
//Do an mmu lookup for va , returns translation status , if MMU_ERROR_NONE , rv is set to translated index
extern u32 mmu_error_TT;
void MMU_Init();
void MMU_Reset(bool Manual);
void MMU_Term();

View File

@ -172,6 +172,7 @@ bool Do_Exeption(u32 epc, u32 expEvn, u32 CallVect)
next_pc = vbr + CallVect; next_pc = vbr + CallVect;
printf("RaiseException: from %08X , pc errh %08X\n", spc, epc);
return true; return true;
} }

View File

@ -21,6 +21,7 @@ extern VArray2 mem_b;
#define WriteMem64 _vmem_WriteMem64 #define WriteMem64 _vmem_WriteMem64
//#define WriteMem64(addr,reg) { _vmem_WriteMem32(addr,((u32*)reg)[0]);_vmem_WriteMem32((addr)+4, ((u32*)reg)[1]); } //#define WriteMem64(addr,reg) { _vmem_WriteMem32(addr,((u32*)reg)[0]);_vmem_WriteMem32((addr)+4, ((u32*)reg)[1]); }
#else #else
#include "modules/mmu.h"
#define ReadMem8 mmu_ReadMem8 #define ReadMem8 mmu_ReadMem8
#define ReadMem16 mmu_ReadMem16 #define ReadMem16 mmu_ReadMem16
#define IReadMem16 mmu_IReadMem16 #define IReadMem16 mmu_IReadMem16

View File

@ -288,8 +288,8 @@
<ClInclude Include="..\core\hw\sh4\interpr\sh4_opcodes.h" /> <ClInclude Include="..\core\hw\sh4\interpr\sh4_opcodes.h" />
<ClInclude Include="..\core\hw\sh4\modules\ccn.h" /> <ClInclude Include="..\core\hw\sh4\modules\ccn.h" />
<ClInclude Include="..\core\hw\sh4\modules\dmac.h" /> <ClInclude Include="..\core\hw\sh4\modules\dmac.h" />
<ClInclude Include="..\core\hw\sh4\modules\intc.h" />
<ClInclude Include="..\core\hw\sh4\modules\mmu.h" /> <ClInclude Include="..\core\hw\sh4\modules\mmu.h" />
<ClInclude Include="..\core\hw\sh4\modules\mmu_impl.h" />
<ClInclude Include="..\core\hw\sh4\modules\modules.h" /> <ClInclude Include="..\core\hw\sh4\modules\modules.h" />
<ClInclude Include="..\core\hw\sh4\modules\tmu.h" /> <ClInclude Include="..\core\hw\sh4\modules\tmu.h" />
<ClInclude Include="..\core\hw\sh4\sh4_if.h" /> <ClInclude Include="..\core\hw\sh4\sh4_if.h" />

View File

@ -775,9 +775,6 @@
<ClInclude Include="..\core\hw\sh4\modules\dmac.h"> <ClInclude Include="..\core\hw\sh4\modules\dmac.h">
<Filter>hw\sh4\modules</Filter> <Filter>hw\sh4\modules</Filter>
</ClInclude> </ClInclude>
<ClInclude Include="..\core\hw\sh4\modules\intc.h">
<Filter>hw\sh4\modules</Filter>
</ClInclude>
<ClInclude Include="..\core\hw\sh4\modules\mmu.h"> <ClInclude Include="..\core\hw\sh4\modules\mmu.h">
<Filter>hw\sh4\modules</Filter> <Filter>hw\sh4\modules</Filter>
</ClInclude> </ClInclude>
@ -946,6 +943,9 @@
<ClInclude Include="..\core\cfg\ini.h"> <ClInclude Include="..\core\cfg\ini.h">
<Filter>cfg</Filter> <Filter>cfg</Filter>
</ClInclude> </ClInclude>
<ClInclude Include="..\core\hw\sh4\modules\mmu_impl.h">
<Filter>hw\sh4\modules</Filter>
</ClInclude>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<None Include="..\core\deps\zlib\Makefile"> <None Include="..\core\deps\zlib\Makefile">