131 lines
2.8 KiB
C++
131 lines
2.8 KiB
C++
#pragma once
|
|
#include "types.h"
|
|
#include "hw/sh4/sh4_mmr.h"
|
|
#include "hw/mem/_vmem.h"
|
|
|
|
//Translation Types
|
|
//Opcode read
|
|
#define MMU_TT_IREAD 0
|
|
//Data write
|
|
#define MMU_TT_DWRITE 1
|
|
//Data write
|
|
#define MMU_TT_DREAD 2
|
|
|
|
//Return Values
|
|
//Translation was successful
|
|
#define MMU_ERROR_NONE 0
|
|
//TLB miss
|
|
#define MMU_ERROR_TLB_MISS 1
|
|
//TLB Multihit
|
|
#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
|
|
|
|
struct TLB_Entry
|
|
{
|
|
CCN_PTEH_type Address;
|
|
CCN_PTEL_type Data;
|
|
CCN_PTEA_type Assistance;
|
|
};
|
|
|
|
extern TLB_Entry UTLB[64];
|
|
extern TLB_Entry ITLB[4];
|
|
extern u32 sq_remap[64];
|
|
extern const u32 fast_reg_lut[8];
|
|
|
|
//These are working only for SQ remaps on ndce
|
|
bool UTLB_Sync(u32 entry);
|
|
void ITLB_Sync(u32 entry);
|
|
|
|
bool mmu_match(u32 va, CCN_PTEH_type Address, CCN_PTEL_type Data);
|
|
void mmu_set_state();
|
|
void mmu_flush_table();
|
|
|
|
static INLINE bool mmu_enabled()
|
|
{
|
|
#ifndef NO_MMU
|
|
return settings.dreamcast.FullMMU && CCN_MMUCR.AT == 1;
|
|
#else
|
|
return false;
|
|
#endif
|
|
}
|
|
|
|
template<bool internal = false>
|
|
u32 mmu_full_lookup(u32 va, const TLB_Entry **entry, u32& rv);
|
|
|
|
#ifdef FAST_MMU
|
|
static INLINE u32 mmu_instruction_translation(u32 va, u32& rv)
|
|
{
|
|
if (va & 1)
|
|
return MMU_ERROR_BADADDR;
|
|
if (fast_reg_lut[va >> 29] != 0)
|
|
{
|
|
rv = va;
|
|
return MMU_ERROR_NONE;
|
|
}
|
|
|
|
const TLB_Entry *tlb_entry;
|
|
return mmu_full_lookup(va, &tlb_entry, rv);
|
|
}
|
|
#else
|
|
u32 mmu_instruction_translation(u32 va, u32& rv);
|
|
#endif
|
|
|
|
template<u32 translation_type, typename T>
|
|
extern u32 mmu_data_translation(u32 va, u32& rv);
|
|
void DoMMUException(u32 addr, u32 error_code, u32 access_type);
|
|
|
|
#if defined(NO_MMU)
|
|
bool inline mmu_TranslateSQW(u32 addr, u32* mapped) {
|
|
*mapped = sq_remap[(addr>>20)&0x3F] | (addr & 0xFFFE0);
|
|
return true;
|
|
}
|
|
void inline mmu_flush_table() {}
|
|
#else
|
|
template<typename T> T DYNACALL mmu_ReadMem(u32 adr);
|
|
u16 DYNACALL mmu_IReadMem16(u32 addr);
|
|
|
|
template<typename T> void DYNACALL mmu_WriteMem(u32 adr, T data);
|
|
|
|
bool mmu_TranslateSQW(u32 addr, u32* mapped);
|
|
|
|
template<typename T>
|
|
T DYNACALL mmu_ReadMemNoEx(u32 adr, u32 *exception_occurred)
|
|
{
|
|
u32 addr;
|
|
u32 rv = mmu_data_translation<MMU_TT_DREAD, T>(adr, addr);
|
|
if (rv != MMU_ERROR_NONE)
|
|
{
|
|
DoMMUException(adr, rv, MMU_TT_DREAD);
|
|
*exception_occurred = 1;
|
|
return 0;
|
|
}
|
|
else
|
|
{
|
|
*exception_occurred = 0;
|
|
return _vmem_readt<T, T>(addr);
|
|
}
|
|
}
|
|
|
|
template<typename T>
|
|
u32 DYNACALL mmu_WriteMemNoEx(u32 adr, T data)
|
|
{
|
|
u32 addr;
|
|
u32 rv = mmu_data_translation<MMU_TT_DWRITE, T>(adr, addr);
|
|
if (rv != MMU_ERROR_NONE)
|
|
{
|
|
DoMMUException(adr, rv, MMU_TT_DWRITE);
|
|
return 1;
|
|
}
|
|
_vmem_writet<T>(addr, data);
|
|
return 0;
|
|
}
|
|
|
|
#endif
|