2013-12-19 17:10:14 +00:00
|
|
|
#pragma once
|
|
|
|
#include "types.h"
|
|
|
|
#include "hw/sh4/sh4_mmr.h"
|
2019-06-08 11:04:35 +00:00
|
|
|
#include "hw/mem/_vmem.h"
|
2021-03-01 09:13:40 +00:00
|
|
|
#include "cfg/option.h"
|
2021-05-17 09:59:34 +00:00
|
|
|
#include "hw/sh4/dyna/ngen.h"
|
2013-12-19 17:10:14 +00:00
|
|
|
|
2019-03-25 10:56:41 +00:00
|
|
|
//Translation Types
|
|
|
|
//Opcode read
|
|
|
|
#define MMU_TT_IREAD 0
|
|
|
|
//Data write
|
|
|
|
#define MMU_TT_DWRITE 1
|
|
|
|
//Data write
|
|
|
|
#define MMU_TT_DREAD 2
|
|
|
|
|
2019-04-15 16:02:34 +00:00
|
|
|
//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
|
2021-05-14 17:03:57 +00:00
|
|
|
//data-Opcode read/write misaligned
|
2019-04-15 16:02:34 +00:00
|
|
|
#define MMU_ERROR_BADADDR 5
|
|
|
|
//Can't Execute
|
|
|
|
#define MMU_ERROR_EXECPROT 6
|
|
|
|
|
2013-12-19 17:10:14 +00:00
|
|
|
struct TLB_Entry
|
|
|
|
{
|
|
|
|
CCN_PTEH_type Address;
|
|
|
|
CCN_PTEL_type Data;
|
2019-03-19 20:35:55 +00:00
|
|
|
CCN_PTEA_type Assistance;
|
2013-12-19 17:10:14 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
extern TLB_Entry UTLB[64];
|
|
|
|
extern TLB_Entry ITLB[4];
|
|
|
|
extern u32 sq_remap[64];
|
|
|
|
|
2021-05-14 17:03:57 +00:00
|
|
|
constexpr u32 fast_reg_lut[8] =
|
|
|
|
{
|
|
|
|
0, 0, 0, 0 //P0-U0
|
|
|
|
, 1 //P1
|
|
|
|
, 1 //P2
|
|
|
|
, 0 //P3
|
|
|
|
, 1 //P4
|
|
|
|
};
|
|
|
|
|
|
|
|
constexpr 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
|
|
|
|
};
|
|
|
|
|
2015-08-27 14:57:22 +00:00
|
|
|
bool UTLB_Sync(u32 entry);
|
2013-12-19 17:10:14 +00:00
|
|
|
void ITLB_Sync(u32 entry);
|
|
|
|
|
2015-09-17 15:52:01 +00:00
|
|
|
bool mmu_match(u32 va, CCN_PTEH_type Address, CCN_PTEL_type Data);
|
2019-03-17 21:59:18 +00:00
|
|
|
void mmu_set_state();
|
2019-03-25 10:56:41 +00:00
|
|
|
void mmu_flush_table();
|
2020-06-09 10:02:01 +00:00
|
|
|
void mmu_raise_exception(u32 mmu_error, u32 address, u32 am);
|
2019-03-25 10:56:41 +00:00
|
|
|
|
2021-05-17 09:59:34 +00:00
|
|
|
static inline bool mmu_enabled()
|
2019-03-25 10:56:41 +00:00
|
|
|
{
|
2021-03-01 09:13:40 +00:00
|
|
|
return config::FullMMU && CCN_MMUCR.AT == 1;
|
2019-03-25 10:56:41 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
template<bool internal = false>
|
|
|
|
u32 mmu_full_lookup(u32 va, const TLB_Entry **entry, u32& rv);
|
2020-06-24 13:23:47 +00:00
|
|
|
u32 mmu_instruction_lookup(u32 va, const TLB_Entry **entry, u32& rv);
|
|
|
|
template<u32 translation_type>
|
|
|
|
u32 mmu_full_SQ(u32 va, u32& rv);
|
2019-05-26 11:30:05 +00:00
|
|
|
|
|
|
|
#ifdef FAST_MMU
|
2021-05-17 09:59:34 +00:00
|
|
|
static inline u32 mmu_instruction_translation(u32 va, u32& rv)
|
2019-05-26 11:30:05 +00:00
|
|
|
{
|
|
|
|
if (va & 1)
|
|
|
|
return MMU_ERROR_BADADDR;
|
|
|
|
if (fast_reg_lut[va >> 29] != 0)
|
|
|
|
{
|
|
|
|
rv = va;
|
|
|
|
return MMU_ERROR_NONE;
|
|
|
|
}
|
|
|
|
|
2021-05-14 17:03:57 +00:00
|
|
|
return mmu_full_lookup(va, nullptr, rv);
|
2019-05-26 11:30:05 +00:00
|
|
|
}
|
|
|
|
#else
|
|
|
|
u32 mmu_instruction_translation(u32 va, u32& rv);
|
|
|
|
#endif
|
|
|
|
|
2019-03-25 10:56:41 +00:00
|
|
|
template<u32 translation_type, typename T>
|
2021-05-14 17:03:57 +00:00
|
|
|
u32 mmu_data_translation(u32 va, u32& rv);
|
2021-03-14 19:17:37 +00:00
|
|
|
void DoMMUException(u32 addr, u32 mmu_error, u32 access_type);
|
2015-09-17 15:52:01 +00:00
|
|
|
|
2021-05-14 17:03:57 +00:00
|
|
|
inline static bool mmu_is_translated(u32 va, u32 size)
|
2021-01-07 18:18:53 +00:00
|
|
|
{
|
2021-05-14 17:03:57 +00:00
|
|
|
#ifndef FAST_MMU
|
2021-01-07 18:18:53 +00:00
|
|
|
if (va & (size - 1))
|
|
|
|
return true;
|
2021-05-14 17:03:57 +00:00
|
|
|
#endif
|
2021-01-07 18:18:53 +00:00
|
|
|
|
2021-05-14 17:03:57 +00:00
|
|
|
if (fast_reg_lut[va >> 29] != 0)
|
2021-01-07 18:18:53 +00:00
|
|
|
return false;
|
|
|
|
|
2021-05-14 17:03:57 +00:00
|
|
|
if ((va & 0xFC000000) == 0x7C000000)
|
|
|
|
// On-chip RAM area isn't translated
|
2021-01-07 18:18:53 +00:00
|
|
|
return false;
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2021-05-14 17:03:57 +00:00
|
|
|
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 adr, u32* out);
|
2015-08-27 14:57:22 +00:00
|
|
|
|
2021-05-17 09:59:34 +00:00
|
|
|
// maps 4K virtual page number to physical address
|
|
|
|
extern u32 mmuAddressLUT[0x100000];
|
2019-04-15 16:02:34 +00:00
|
|
|
|
2021-05-17 09:59:34 +00:00
|
|
|
static inline void mmuAddressLUTFlush(bool full) {
|
|
|
|
if (full)
|
2021-05-18 10:53:14 +00:00
|
|
|
memset(mmuAddressLUT, 0, sizeof(mmuAddressLUT) / 2); // flush user memory
|
2021-05-14 17:03:57 +00:00
|
|
|
else
|
2019-06-08 11:04:35 +00:00
|
|
|
{
|
2021-05-17 09:59:34 +00:00
|
|
|
constexpr u32 slotPages = (32 * 1024 * 1024) >> 12;
|
2021-05-18 10:53:14 +00:00
|
|
|
memset(mmuAddressLUT, 0, slotPages * sizeof(u32)); // flush slot 0
|
2019-06-08 11:04:35 +00:00
|
|
|
}
|
2021-05-14 17:03:57 +00:00
|
|
|
}
|
2019-06-08 11:04:35 +00:00
|
|
|
|
2021-05-17 09:59:34 +00:00
|
|
|
static inline u32 mmuDynarecLookup(u32 vaddr, u32 write, u32 pc)
|
2021-05-14 17:03:57 +00:00
|
|
|
{
|
2021-05-17 09:59:34 +00:00
|
|
|
u32 paddr;
|
|
|
|
u32 rv;
|
|
|
|
if (write)
|
|
|
|
rv = mmu_data_translation<MMU_TT_DWRITE, u32>(vaddr, paddr);
|
2021-05-14 17:03:57 +00:00
|
|
|
else
|
2021-05-17 09:59:34 +00:00
|
|
|
rv = mmu_data_translation<MMU_TT_DREAD, u32>(vaddr, paddr);
|
|
|
|
if (unlikely(rv != MMU_ERROR_NONE))
|
2019-06-08 11:04:35 +00:00
|
|
|
{
|
2021-05-17 09:59:34 +00:00
|
|
|
Sh4cntx.pc = pc;
|
|
|
|
DoMMUException(vaddr, rv, write ? MMU_TT_DWRITE : MMU_TT_DREAD);
|
|
|
|
host_context_t ctx;
|
|
|
|
ngen_HandleException(ctx);
|
|
|
|
((void (*)())ctx.pc)();
|
|
|
|
// not reached
|
|
|
|
return 0;
|
2019-06-08 11:04:35 +00:00
|
|
|
}
|
2021-05-18 10:53:14 +00:00
|
|
|
if (vaddr >> 31 == 0)
|
|
|
|
mmuAddressLUT[vaddr >> 12] = paddr & ~0xfff;
|
2021-05-17 09:59:34 +00:00
|
|
|
|
|
|
|
return paddr;
|
2021-05-14 17:03:57 +00:00
|
|
|
}
|