area 7 access to sh4 mm registers only through mmu translation

on-chip ram area isn't translated in both user and supervisor modes
vmem: return 0 for non-mapped region reads
Fixes dolphin blue crash/freeze. Issue #62
Fixes Resident Evil - Code Veronica X (Chris) floor 1F crash
This commit is contained in:
Flyinghead 2021-04-01 13:30:37 +02:00
parent 4d815570d0
commit b3de6a166d
8 changed files with 63 additions and 93 deletions

View File

@ -103,7 +103,7 @@ void* _vmem_write_const(u32 addr,bool& ismem,u32 sz)
template<typename T,typename Trv>
INLINE Trv DYNACALL _vmem_readt(u32 addr)
{
const u32 sz=sizeof(T);
constexpr u32 sz = sizeof(T);
u32 page=addr>>24; //1 op, shift/extract
unat iirf=(unat)_vmem_MemInfo_ptr[page]; //2 ops, insert + read [vmem table will be on reg ]
@ -154,7 +154,7 @@ template u64 DYNACALL _vmem_readt<u64, u64>(u32 addr);
template<typename T>
INLINE void DYNACALL _vmem_writet(u32 addr,T data)
{
const u32 sz=sizeof(T);
constexpr u32 sz = sizeof(T);
u32 page=addr>>24;
unat iirf=(unat)_vmem_MemInfo_ptr[page];
@ -214,8 +214,7 @@ void DYNACALL _vmem_WriteMem16(u32 Address,u16 data) { _vmem_writet<u16>(Address
void DYNACALL _vmem_WriteMem32(u32 Address,u32 data) { _vmem_writet<u32>(Address,data); }
void DYNACALL _vmem_WriteMem64(u32 Address,u64 data) { _vmem_writet<u64>(Address,data); }
//0xDEADC0D3 or 0
#define MEM_ERROR_RETURN_VALUE 0xDEADC0D3
#define MEM_ERROR_RETURN_VALUE 0
//default read handlers
static u8 DYNACALL _vmem_ReadMem8_not_mapped(u32 addresss)
@ -378,6 +377,8 @@ static void* malloc_pages(size_t size) {
#endif
}
#if FEAT_SHREC != DYNAREC_NONE
// Resets the FPCB table (by either clearing it to the default val
// or by flushing it and making it fault on access again.
void _vmem_bm_reset()
@ -410,6 +411,7 @@ bool BM_LockedWrite(u8* address) {
}
return false;
}
#endif
static void _vmem_set_p0_mappings()
{
@ -481,7 +483,9 @@ void _vmem_init_mappings()
// Allocate it all and initialize it.
p_sh4rcb = (Sh4RCB*)malloc_pages(sizeof(Sh4RCB));
#if FEAT_SHREC != DYNAREC_NONE
bm_vmem_pagefill((void**)p_sh4rcb->fpcb, sizeof(p_sh4rcb->fpcb));
#endif
mem_b.size = RAM_SIZE;
mem_b.data = (u8*)malloc_pages(RAM_SIZE);
@ -726,7 +730,9 @@ u32 _vmem_get_vram_offset(void *addr)
}
if ((offset >> 24) != 4)
return -1;
verify((((u8*)addr - virt_ram_base) >> 29) == 0 || (((u8*)addr - virt_ram_base) >> 29) == 4 || (((u8*)addr - virt_ram_base) >> 29) == 5); // others areas aren't mapped atm
if ((((u8*)addr - virt_ram_base) >> 29) != 0 && (((u8*)addr - virt_ram_base) >> 29) != 4 && (((u8*)addr - virt_ram_base) >> 29) != 5)
// other areas aren't mapped atm
return -1;
return offset & VRAM_MASK;
}

View File

@ -279,6 +279,7 @@ static u32 vmem32_map_mmu(u32 address, bool write)
}
else if (offset >= MAP_RAM_START_OFFSET && offset < MAP_RAM_START_OFFSET + RAM_SIZE)
{
#if FEAT_SHREC != DYNAREC_NONE
// Check system RAM protected pages
u32 start = offset - MAP_RAM_START_OFFSET;
@ -297,6 +298,7 @@ static u32 vmem32_map_mmu(u32 address, bool write)
}
}
else
#endif
verify(vmem32_map_buffer(vpn, page_size, offset, page_size, allow_write) != NULL);
}
else

View File

@ -299,8 +299,9 @@ u32 mmu_data_translation(u32 va, u32& rv)
}
}
if (sr.MD == 1 && ((va & 0xFC000000) == 0x7C000000))
if ((va & 0xFC000000) == 0x7C000000)
{
// On-chip RAM area isn't translated
rv = va;
return MMU_ERROR_NONE;
}
@ -313,7 +314,9 @@ u32 mmu_data_translation(u32 va, u32& rv)
const TLB_Entry *entry;
u32 lookup = mmu_full_lookup(va, &entry, rv);
if (lookup == MMU_ERROR_NONE && (rv & 0x1C000000) == 0x1C000000)
// map 1C000000-1FFFFFFF to P4 memory-mapped registers
rv |= 0xF0000000;
#ifdef TRACE_WINCE_SYSCALLS
if (unresolved_unicode_string != 0 && lookup == MMU_ERROR_NONE)
{

View File

@ -486,9 +486,9 @@ u32 mmu_data_translation(u32 va, u32& rv)
return MMU_ERROR_BADADDR;
}
if (sr.MD == 1 && ((va & 0xFC000000) == 0x7C000000))
if ((va & 0xFC000000) == 0x7C000000)
{
// 7C000000 to 7FFFFFFF in P0 not translated in supervisor mode
// 7C000000 to 7FFFFFFF in P0/U0 not translated
rv = va;
return MMU_ERROR_NONE;
}
@ -537,6 +537,10 @@ u32 mmu_data_translation(u32 va, u32& rv)
else if (entry->Data.D == 0)
return MMU_ERROR_FIRSTWRITE;
}
if ((rv & 0x1C000000) == 0x1C000000)
// map 1C000000-1FFFFFFF to P4 memory-mapped registers
rv |= 0xF0000000;
return MMU_ERROR_NONE;
}
template u32 mmu_data_translation<MMU_TT_DREAD, u8>(u32 va, u32& rv);

View File

@ -98,17 +98,9 @@ bool mmu_is_translated(u32 va, u32 size)
//SQ writes are not translated, only write backs are.
return false;
}
#ifndef sr
// This is why the preprocessor sucks
#define sr Sh4cntx.sr
#define undef_sr
#endif
if (sr.MD == 1 && (va & 0xFC000000) == 0x7C000000)
if ((va & 0xFC000000) == 0x7C000000)
// On-chip RAM area isn't translated
return false;
#ifdef undef_sr
#undef sr
#undef undef_sr
#endif
if (fast_reg_lut[va >> 29] != 0)
return false;

View File

@ -198,8 +198,8 @@ private:
cached = CCN_CCR.ICE == 1 && cachedArea(area);
if (CCN_MMUCR.AT == 0 || !translatedArea(area)
// 7C000000 to 7FFFFFFF in P0 not translated in supervisor mode
|| (!userMode && (address & 0xFC000000) == 0x7C000000))
// 7C000000 to 7FFFFFFF in P0/U0 not translated
|| (address & 0xFC000000) == 0x7C000000)
{
physAddr = address;
}
@ -531,8 +531,8 @@ private:
copyBack = area == 4 ? CCN_CCR.CB : !CCN_CCR.WT;
if (CCN_MMUCR.AT == 0 || !translatedArea(area)
// 7C000000 to 7FFFFFFF in P0 not translated in supervisor mode
|| (!userMode && (address & 0xFC000000) == 0x7C000000))
// 7C000000 to 7FFFFFFF in P0/U0 not translated
|| (address & 0xFC000000) == 0x7C000000)
{
physAddr = address;
}
@ -563,6 +563,10 @@ private:
copyBack = copyBack && entry->Data.WT == 0;
}
cached = cached && entry->Data.C == 1;
if ((physAddr & 0x1C000000) == 0x1C000000)
// map 1C000000-1FFFFFFF to P4 memory-mapped registers
physAddr |= 0xF0000000;
}
return MMU_ERROR_NONE;
}

View File

@ -389,10 +389,11 @@ void DYNACALL WriteMem_P4(u32 addr,T data)
//***********
#define OUT_OF_RANGE(reg) INFO_LOG(SH4, "Out of range on register %s index %x", reg, addr)
#define A7_REG_HASH(addr) (((addr) >> 16) & 0x1FFF)
//Read Area7
//Read P4 memory-mapped registers
template <class T>
T DYNACALL ReadMem_area7(u32 addr)
T DYNACALL ReadMem_p4mmr(u32 addr)
{
constexpr size_t sz = sizeof(T);
/*
@ -415,7 +416,7 @@ T DYNACALL ReadMem_area7(u32 addr)
addr&=0x1FFFFFFF;
u32 map_base=addr>>16;
switch (map_base)
switch (expected(map_base, A7_REG_HASH(TMU_BASE_addr)))
{
case A7_REG_HASH(CCN_BASE_addr):
if (addr<=0x1F000044)
@ -562,13 +563,13 @@ T DYNACALL ReadMem_area7(u32 addr)
break;
}
INFO_LOG(SH4, "Unknown Read from Area7 - addr=%x", addr);
INFO_LOG(SH4, "Unknown Read from P4 mmr - addr=%x", addr);
return 0;
}
//Write Area7
//Write P4 memory-mapped registers
template <class T>
void DYNACALL WriteMem_area7(u32 addr,T data)
void DYNACALL WriteMem_p4mmr(u32 addr,T data)
{
constexpr size_t sz = sizeof(T);
if (likely(addr==0xFF000038))
@ -720,59 +721,30 @@ void DYNACALL WriteMem_area7(u32 addr,T data)
break;
}
INFO_LOG(SH4, "Write to Area7 not implemented, addr=%x, data=%x", addr, data);
INFO_LOG(SH4, "Write to P4 mmr not implemented, addr=%x, data=%x", addr, data);
}
//***********
//On Chip Ram
//***********
//Read OCR
template <class T>
T DYNACALL ReadMem_area7_OCR_T(u32 addr)
T DYNACALL ReadMem_area7_OCR(u32 addr)
{
if (CCN_CCR.ORA)
{
if (sizeof(T) == 1)
return (T)OnChipRAM[addr&OnChipRAM_MASK];
else if (sizeof(T) == 2)
return (T)*(u16*)&OnChipRAM[addr&OnChipRAM_MASK];
else if (sizeof(T) == 4)
return (T)*(u32*)&OnChipRAM[addr&OnChipRAM_MASK];
else
{
ERROR_LOG(SH4, "ReadMem_area7_OCR_T: template SZ is wrong = %zd", sizeof(T));
return 0xDE;
}
}
else
{
INFO_LOG(SH4, "On Chip Ram Read, but OCR is disabled. addr %x", addr);
return 0xDE;
}
if (CCN_CCR.ORA == 1)
return *(T *)&OnChipRAM[addr & OnChipRAM_MASK];
INFO_LOG(SH4, "On Chip Ram Read, but OCR is disabled. addr %x", addr);
return 0;
}
//Write OCR
template <class T>
void DYNACALL WriteMem_area7_OCR_T(u32 addr,T data)
void DYNACALL WriteMem_area7_OCR(u32 addr, T data)
{
if (CCN_CCR.ORA)
{
if (sizeof(T) == 1)
OnChipRAM[addr&OnChipRAM_MASK]=(u8)data;
else if (sizeof(T) == 2)
*(u16*)&OnChipRAM[addr&OnChipRAM_MASK]=(u16)data;
else if (sizeof(T) == 4)
*(u32*)&OnChipRAM[addr&OnChipRAM_MASK]=data;
else
{
ERROR_LOG(SH4, "WriteMem_area7_OCR_T: template SZ is wrong = %zd", sizeof(T));
}
}
if (CCN_CCR.ORA == 1)
*(T *)&OnChipRAM[addr & OnChipRAM_MASK] = data;
else
{
INFO_LOG(SH4, "On Chip Ram Write, but OCR is disabled. addr %x", addr);
}
}
template <class T>
@ -863,42 +835,31 @@ void sh4_mmr_term()
ccn_term();
bsc_term();
}
//Mem map :)
//AREA 7--Sh4 Regs
_vmem_handler area7_handler;
_vmem_handler area7_orc_handler;
// AREA 7--Sh4 Regs
static _vmem_handler p4mmr_handler;
static _vmem_handler area7_ocr_handler;
void map_area7_init()
{
//=_vmem_register_handler(ReadMem8_area7,ReadMem16_area7,ReadMem32_area7,
// WriteMem8_area7,WriteMem16_area7,WriteMem32_area7);
//default area7 handler
area7_handler= _vmem_register_handler_Template(ReadMem_area7,WriteMem_area7);
area7_orc_handler= _vmem_register_handler_Template(ReadMem_area7_OCR_T,WriteMem_area7_OCR_T);
p4mmr_handler = _vmem_register_handler_Template(ReadMem_p4mmr, WriteMem_p4mmr);
area7_ocr_handler = _vmem_register_handler_Template(ReadMem_area7_OCR, WriteMem_area7_OCR);
}
void map_area7(u32 base)
{
//OCR @
//((addr>=0x7C000000) && (addr<=0x7FFFFFFF))
if (base==0x60)
_vmem_map_handler(area7_orc_handler,0x1C | base , 0x1F| base);
else
{
_vmem_map_handler(area7_handler,0x1C | base , 0x1F| base);
}
// on-chip RAM: 7C000000-7FFFFFFF
if (base == 0x60)
_vmem_map_handler(area7_ocr_handler, 0x7C, 0x7F);
}
//P4
void map_p4()
{
//P4 Region :
_vmem_handler p4_handler = _vmem_register_handler_Template(ReadMem_P4,WriteMem_P4);
_vmem_handler p4_handler = _vmem_register_handler_Template(ReadMem_P4, WriteMem_P4);
//register this before area7 and SQ , so they overwrite it and handle em :)
//register this before mmr and SQ so they overwrite it and handle em
//default P4 handler
//0xE0000000-0xFFFFFFFF
_vmem_map_handler(p4_handler,0xE0,0xFF);
@ -909,5 +870,5 @@ void map_p4()
_vmem_map_block(sq_both,0xE2,0xE2,63);
_vmem_map_block(sq_both,0xE3,0xE3,63);
map_area7(0xE0);
_vmem_map_handler(p4mmr_handler, 0xFF, 0xFF);
}

View File

@ -31,8 +31,6 @@ void sh4_mmr_term();
template<typename T>
void sh4_rio_reg(T& arr, u32 addr, RegIO flags, u32 sz, RegReadAddrFP* rf=0, RegWriteAddrFP* wf=0);
#define A7_REG_HASH(addr) (((addr) >> 16) & 0x1FFF)
#define SH4IO_REGN(mod, addr, size) ((mod)[((addr) & 255) / 4].data##size)
#define SH4IO_REG(mod, name, size) SH4IO_REGN(mod, mod##_##name##_addr, size)
#define SH4IO_REG_T(mod, name, size) ((mod##_##name##_type&)SH4IO_REG(mod, name, size))