Added the ExRAM support to the iCache (only JIT and Interpreter for now, JIT IL fix will be a bit later)
git-svn-id: https://dolphin-emu.googlecode.com/svn/trunk@4358 8ced0084-cf51-0410-be5f-012b33b47a6e
This commit is contained in:
parent
b843378636
commit
26a60eb9bf
|
@ -537,22 +537,32 @@ u32 Read_Instruction(const u32 em_address)
|
||||||
|
|
||||||
u32 Read_Opcode_JIT(const u32 _Address)
|
u32 Read_Opcode_JIT(const u32 _Address)
|
||||||
{
|
{
|
||||||
#ifdef JIT_UNLIMITED_ICACHE
|
#ifdef JIT_UNLIMITED_ICACHE
|
||||||
//return Memory::ReadUnchecked_U32(_Address);
|
if ((_Address & ~JIT_ICACHE_MASK) != 0x80000000 && (_Address & ~JIT_ICACHE_MASK) != 0x00000000 &&
|
||||||
if ((_Address & ~JIT_ICACHE_MASK) != 0x80000000 && (_Address & ~JIT_ICACHE_MASK) != 0x00000000)
|
(_Address & ~JIT_ICACHEEX_MASK) != 0x90000000 && (_Address & ~JIT_ICACHEEX_MASK) != 0x10000000)
|
||||||
{
|
{
|
||||||
PanicAlert("iCacheJIT: Reading Opcode from %x. Please report.", _Address);
|
PanicAlert("iCacheJIT: Reading Opcode from %x. Please report.", _Address);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
u8* iCache = jit.GetBlockCache()->GetICache();
|
u8* iCache;
|
||||||
u32 addr = _Address & JIT_ICACHE_MASK;
|
u32 addr;
|
||||||
jit.GetBlockCache()->GetICache();
|
if (_Address & JIT_ICACHE_EXRAM_BIT)
|
||||||
|
{
|
||||||
|
iCache = jit.GetBlockCache()->GetICacheEx();
|
||||||
|
addr = _Address & JIT_ICACHEEX_MASK;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
iCache = jit.GetBlockCache()->GetICache();
|
||||||
|
addr = _Address & JIT_ICACHE_MASK;
|
||||||
|
}
|
||||||
u32 inst = *(u32*)(iCache + addr);
|
u32 inst = *(u32*)(iCache + addr);
|
||||||
if (inst == JIT_ICACHE_INVALID_WORD)
|
if (inst == JIT_ICACHE_INVALID_WORD)
|
||||||
{
|
{
|
||||||
u32 block_start = addr & ~0x1f;
|
u32 cache_block_start = addr & ~0x1f;
|
||||||
u8 *pMem = Memory::GetPointer(block_start);
|
u32 mem_block_start = _Address & ~0x1f;
|
||||||
memcpy(iCache + block_start, pMem, 32);
|
u8 *pMem = Memory::GetPointer(mem_block_start);
|
||||||
|
memcpy(iCache + cache_block_start, pMem, 32);
|
||||||
inst = *(u32*)(iCache + addr);
|
inst = *(u32*)(iCache + addr);
|
||||||
}
|
}
|
||||||
inst = Common::swap32(inst);
|
inst = Common::swap32(inst);
|
||||||
|
@ -563,22 +573,37 @@ u32 Read_Opcode_JIT(const u32 _Address)
|
||||||
{
|
{
|
||||||
inst = jit.GetBlockCache()->GetOriginalFirstOp(inst);
|
inst = jit.GetBlockCache()->GetOriginalFirstOp(inst);
|
||||||
}
|
}
|
||||||
//PanicAlert("Read from %x. res = %x. mem=%x", _Address, inst, Memory::Read_U32(_Address));
|
|
||||||
|
// if a crash occured after that message
|
||||||
|
// that means that we've compiled outdated code from the cache instead of memory
|
||||||
|
// this could happen if a game forgot to icbi the new code
|
||||||
|
u32 inst_mem = Memory::ReadUnchecked_U32(_Address);
|
||||||
|
if (inst_mem != inst)
|
||||||
|
ERROR_LOG(POWERPC, "JIT: compiling outdated code. addr=%x, mem=%x, cache=%x", _Address, inst_mem, inst);
|
||||||
return inst;
|
return inst;
|
||||||
}
|
}
|
||||||
|
|
||||||
u32 Read_Opcode_JIT_LC(const u32 _Address)
|
u32 Read_Opcode_JIT_LC(const u32 _Address)
|
||||||
{
|
{
|
||||||
#ifdef JIT_UNLIMITED_ICACHE
|
#ifdef JIT_UNLIMITED_ICACHE
|
||||||
//return Memory::ReadUnchecked_U32(_Address);
|
if ((_Address & ~JIT_ICACHE_MASK) != 0x80000000 && (_Address & ~JIT_ICACHE_MASK) != 0x00000000 &&
|
||||||
if ((_Address & ~JIT_ICACHE_MASK) != 0x80000000 && (_Address & ~JIT_ICACHE_MASK) != 0x00000000)
|
(_Address & ~JIT_ICACHEEX_MASK) != 0x90000000 && (_Address & ~JIT_ICACHEEX_MASK) != 0x10000000)
|
||||||
{
|
{
|
||||||
PanicAlert("iCacheJIT: Reading Opcode from %x. Please report.", _Address);
|
PanicAlert("iCacheJIT: Reading Opcode from %x. Please report.", _Address);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
u8* iCache = jit.GetBlockCache()->GetICache();
|
u8* iCache;
|
||||||
u32 addr = _Address & JIT_ICACHE_MASK;
|
u32 addr;
|
||||||
jit.GetBlockCache()->GetICache();
|
if (_Address & JIT_ICACHE_EXRAM_BIT)
|
||||||
|
{
|
||||||
|
iCache = jit.GetBlockCache()->GetICacheEx();
|
||||||
|
addr = _Address & JIT_ICACHEEX_MASK;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
iCache = jit.GetBlockCache()->GetICache();
|
||||||
|
addr = _Address & JIT_ICACHE_MASK;
|
||||||
|
}
|
||||||
u32 inst = *(u32*)(iCache + addr);
|
u32 inst = *(u32*)(iCache + addr);
|
||||||
if (inst == JIT_ICACHE_INVALID_WORD)
|
if (inst == JIT_ICACHE_INVALID_WORD)
|
||||||
inst = Memory::ReadUnchecked_U32(_Address);
|
inst = Memory::ReadUnchecked_U32(_Address);
|
||||||
|
@ -590,7 +615,7 @@ u32 Read_Opcode_JIT_LC(const u32 _Address)
|
||||||
if ((inst & 0xfc000000) == 0)
|
if ((inst & 0xfc000000) == 0)
|
||||||
{
|
{
|
||||||
inst = jit.GetBlockCache()->GetOriginalFirstOp(inst);
|
inst = jit.GetBlockCache()->GetOriginalFirstOp(inst);
|
||||||
}
|
}
|
||||||
return inst;
|
return inst;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -599,7 +624,12 @@ u32 Read_Opcode_JIT_LC(const u32 _Address)
|
||||||
void Write_Opcode_JIT(const u32 _Address, const u32 _Value)
|
void Write_Opcode_JIT(const u32 _Address, const u32 _Value)
|
||||||
{
|
{
|
||||||
#ifdef JIT_UNLIMITED_ICACHE
|
#ifdef JIT_UNLIMITED_ICACHE
|
||||||
*(u32*)(jit.GetBlockCache()->GetICache() + (_Address & JIT_ICACHE_MASK)) = Common::swap32(_Value);
|
if (_Address & JIT_ICACHE_EXRAM_BIT)
|
||||||
|
{
|
||||||
|
*(u32*)(jit.GetBlockCache()->GetICacheEx() + (_Address & JIT_ICACHEEX_MASK)) = Common::swap32(_Value);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
*(u32*)(jit.GetBlockCache()->GetICache() + (_Address & JIT_ICACHE_MASK)) = Common::swap32(_Value);
|
||||||
#else
|
#else
|
||||||
Memory::WriteUnchecked_U32(_Value, _Address);
|
Memory::WriteUnchecked_U32(_Value, _Address);
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -87,23 +87,9 @@ void AsmRoutineManager::Generate()
|
||||||
MOV(32, R(EAX), M(&PowerPC::ppcState.pc));
|
MOV(32, R(EAX), M(&PowerPC::ppcState.pc));
|
||||||
dispatcherPcInEAX = GetCodePtr();
|
dispatcherPcInEAX = GetCodePtr();
|
||||||
|
|
||||||
#ifdef JIT_UNLIMITED_ICACHE
|
FixupBranch needinst = J(true);
|
||||||
AND(32, R(EAX), Imm32(JIT_ICACHE_MASK));
|
const u8* haveinst = GetCodePtr();
|
||||||
#ifdef _M_IX86
|
|
||||||
MOV(32, R(EAX), MDisp(EAX, (u32)jit.GetBlockCache()->GetICache()));
|
|
||||||
#else
|
|
||||||
MOV(64, R(RSI), Imm64((u64)jit.GetBlockCache()->GetICache()));
|
|
||||||
MOV(32, R(EAX), MComplex(RSI, EAX, SCALE_1, 0));
|
|
||||||
#endif
|
|
||||||
#else
|
|
||||||
#ifdef _M_IX86
|
|
||||||
AND(32, R(EAX), Imm32(Memory::MEMVIEW32_MASK));
|
|
||||||
MOV(32, R(EBX), Imm32((u32)Memory::base));
|
|
||||||
MOV(32, R(EAX), MComplex(EBX, EAX, SCALE_1, 0));
|
|
||||||
#else
|
|
||||||
MOV(32, R(EAX), MComplex(RBX, RAX, SCALE_1, 0));
|
|
||||||
#endif
|
|
||||||
#endif
|
|
||||||
TEST(32, R(EAX), Imm32(0xFC));
|
TEST(32, R(EAX), Imm32(0xFC));
|
||||||
FixupBranch notfound = J_CC(CC_NZ);
|
FixupBranch notfound = J_CC(CC_NZ);
|
||||||
BSWAP(32, EAX);
|
BSWAP(32, EAX);
|
||||||
|
@ -169,6 +155,45 @@ void AsmRoutineManager::Generate()
|
||||||
ABI_PopAllCalleeSavedRegsAndAdjustStack();
|
ABI_PopAllCalleeSavedRegsAndAdjustStack();
|
||||||
RET();
|
RET();
|
||||||
|
|
||||||
|
|
||||||
|
SetJumpTarget(needinst);
|
||||||
|
#ifdef JIT_UNLIMITED_ICACHE
|
||||||
|
|
||||||
|
TEST(32, R(EAX), Imm32(JIT_ICACHE_EXRAM_BIT));
|
||||||
|
FixupBranch exram = J_CC(CC_NZ);
|
||||||
|
|
||||||
|
AND(32, R(EAX), Imm32(JIT_ICACHE_MASK));
|
||||||
|
#ifdef _M_IX86
|
||||||
|
MOV(32, R(EAX), MDisp(EAX, (u32)jit.GetBlockCache()->GetICache()));
|
||||||
|
#else
|
||||||
|
MOV(64, R(RSI), Imm64((u64)jit.GetBlockCache()->GetICache()));
|
||||||
|
MOV(32, R(EAX), MComplex(RSI, EAX, SCALE_1, 0));
|
||||||
|
#endif
|
||||||
|
|
||||||
|
FixupBranch getinst = J();
|
||||||
|
SetJumpTarget(exram);
|
||||||
|
|
||||||
|
AND(32, R(EAX), Imm32(JIT_ICACHEEX_MASK));
|
||||||
|
#ifdef _M_IX86
|
||||||
|
MOV(32, R(EAX), MDisp(EAX, (u32)jit.GetBlockCache()->GetICacheEx()));
|
||||||
|
#else
|
||||||
|
MOV(64, R(RSI), Imm64((u64)jit.GetBlockCache()->GetICacheEx()));
|
||||||
|
MOV(32, R(EAX), MComplex(RSI, EAX, SCALE_1, 0));
|
||||||
|
#endif
|
||||||
|
|
||||||
|
SetJumpTarget(getinst);
|
||||||
|
#else
|
||||||
|
#ifdef _M_IX86
|
||||||
|
AND(32, R(EAX), Imm32(Memory::MEMVIEW32_MASK));
|
||||||
|
MOV(32, R(EBX), Imm32((u32)Memory::base));
|
||||||
|
MOV(32, R(EAX), MComplex(EBX, EAX, SCALE_1, 0));
|
||||||
|
#else
|
||||||
|
MOV(32, R(EAX), MComplex(RBX, RAX, SCALE_1, 0));
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
JMP(haveinst, true);
|
||||||
|
|
||||||
|
|
||||||
breakpointBailout = GetCodePtr();
|
breakpointBailout = GetCodePtr();
|
||||||
//Landing pad for drec space
|
//Landing pad for drec space
|
||||||
ABI_PopAllCalleeSavedRegsAndAdjustStack();
|
ABI_PopAllCalleeSavedRegsAndAdjustStack();
|
||||||
|
|
|
@ -86,19 +86,21 @@ bool JitBlock::ContainsAddress(u32 em_address)
|
||||||
blocks = new JitBlock[MAX_NUM_BLOCKS];
|
blocks = new JitBlock[MAX_NUM_BLOCKS];
|
||||||
blockCodePointers = new const u8*[MAX_NUM_BLOCKS];
|
blockCodePointers = new const u8*[MAX_NUM_BLOCKS];
|
||||||
#ifdef JIT_UNLIMITED_ICACHE
|
#ifdef JIT_UNLIMITED_ICACHE
|
||||||
if (iCache == 0)
|
if (iCache == 0 && iCacheEx == 0)
|
||||||
{
|
{
|
||||||
iCache = new u8[JIT_ICACHE_SIZE];
|
iCache = new u8[JIT_ICACHE_SIZE];
|
||||||
|
iCacheEx = new u8[JIT_ICACHEEX_SIZE];
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
PanicAlert("JitBlockCache::Init() - iCache is already initialized");
|
PanicAlert("JitBlockCache::Init() - iCache is already initialized");
|
||||||
}
|
}
|
||||||
if (iCache == 0)
|
if (iCache == 0 || iCacheEx == 0)
|
||||||
{
|
{
|
||||||
PanicAlert("JitBlockCache::Init() - unable to allocate iCache");
|
PanicAlert("JitBlockCache::Init() - unable to allocate iCache");
|
||||||
}
|
}
|
||||||
memset(iCache, JIT_ICACHE_INVALID_BYTE, JIT_ICACHE_SIZE);
|
memset(iCache, JIT_ICACHE_INVALID_BYTE, JIT_ICACHE_SIZE);
|
||||||
|
memset(iCacheEx, JIT_ICACHE_INVALID_BYTE, JIT_ICACHEEX_SIZE);
|
||||||
#endif
|
#endif
|
||||||
Clear();
|
Clear();
|
||||||
}
|
}
|
||||||
|
@ -111,6 +113,9 @@ bool JitBlock::ContainsAddress(u32 em_address)
|
||||||
if (iCache != 0)
|
if (iCache != 0)
|
||||||
delete [] iCache;
|
delete [] iCache;
|
||||||
iCache = 0;
|
iCache = 0;
|
||||||
|
if (iCacheEx != 0)
|
||||||
|
delete [] iCacheEx;
|
||||||
|
iCacheEx = 0;
|
||||||
#endif
|
#endif
|
||||||
blocks = 0;
|
blocks = 0;
|
||||||
blockCodePointers = 0;
|
blockCodePointers = 0;
|
||||||
|
@ -224,10 +229,15 @@ bool JitBlock::ContainsAddress(u32 em_address)
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef JIT_UNLIMITED_ICACHE
|
#ifdef JIT_UNLIMITED_ICACHE
|
||||||
u8 *JitBlockCache::GetICache()
|
u8* JitBlockCache::GetICache()
|
||||||
{
|
{
|
||||||
return iCache;
|
return iCache;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
u8* JitBlockCache::GetICacheEx()
|
||||||
|
{
|
||||||
|
return iCacheEx;
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
int JitBlockCache::GetBlockNumberFromStartAddress(u32 addr)
|
int JitBlockCache::GetBlockNumberFromStartAddress(u32 addr)
|
||||||
|
@ -235,7 +245,15 @@ bool JitBlock::ContainsAddress(u32 em_address)
|
||||||
if (!blocks)
|
if (!blocks)
|
||||||
return -1;
|
return -1;
|
||||||
#ifdef JIT_UNLIMITED_ICACHE
|
#ifdef JIT_UNLIMITED_ICACHE
|
||||||
u32 inst = *(u32*)(iCache + (addr & JIT_ICACHE_MASK));
|
u32 inst;
|
||||||
|
if (addr & JIT_ICACHE_EXRAM_BIT)
|
||||||
|
{
|
||||||
|
inst = *(u32*)(iCacheEx + (addr & JIT_ICACHEEX_MASK));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
inst = *(u32*)(iCache + (addr & JIT_ICACHE_MASK));
|
||||||
|
}
|
||||||
inst = Common::swap32(inst);
|
inst = Common::swap32(inst);
|
||||||
#else
|
#else
|
||||||
u32 inst = Memory::ReadFast32(addr);
|
u32 inst = Memory::ReadFast32(addr);
|
||||||
|
@ -369,16 +387,29 @@ bool JitBlock::ContainsAddress(u32 em_address)
|
||||||
}
|
}
|
||||||
if (it1 != it2)
|
if (it1 != it2)
|
||||||
{
|
{
|
||||||
block_map.erase(it1, it2);
|
if (address & JIT_ICACHE_EXRAM_BIT)
|
||||||
|
PanicAlert("icbi deleted blocks. addr=%x", address);
|
||||||
|
block_map.erase(it1, it2);
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef JIT_UNLIMITED_ICACHE
|
#ifdef JIT_UNLIMITED_ICACHE
|
||||||
// invalidate iCache
|
// invalidate iCache.
|
||||||
if ((address & ~JIT_ICACHE_MASK) != 0x80000000 && (address & ~JIT_ICACHE_MASK) != 0x00000000)
|
// icbi can be called with any address, so we sholud check
|
||||||
|
if ((address & ~JIT_ICACHE_MASK) != 0x80000000 && (address & ~JIT_ICACHE_MASK) != 0x00000000 &&
|
||||||
|
(address & ~JIT_ICACHEEX_MASK) != 0x90000000 && (address & ~JIT_ICACHEEX_MASK) != 0x10000000)
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
u32 cacheaddr = address & JIT_ICACHE_MASK;
|
if (address & JIT_ICACHE_EXRAM_BIT)
|
||||||
memset(iCache + cacheaddr, JIT_ICACHE_INVALID_BYTE, 32);
|
{
|
||||||
|
ERROR_LOG(POWERPC, "icbi clearing exram icache. addr=%x", address);
|
||||||
|
u32 cacheaddr = address & JIT_ICACHEEX_MASK;
|
||||||
|
memset(iCacheEx + cacheaddr, JIT_ICACHE_INVALID_BYTE, 32);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
u32 cacheaddr = address & JIT_ICACHE_MASK;
|
||||||
|
memset(iCache + cacheaddr, JIT_ICACHE_INVALID_BYTE, 32);
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
|
@ -34,6 +34,9 @@
|
||||||
|
|
||||||
#define JIT_ICACHE_SIZE 0x2000000
|
#define JIT_ICACHE_SIZE 0x2000000
|
||||||
#define JIT_ICACHE_MASK 0x1ffffff
|
#define JIT_ICACHE_MASK 0x1ffffff
|
||||||
|
#define JIT_ICACHEEX_SIZE 0x4000000
|
||||||
|
#define JIT_ICACHEEX_MASK 0x3ffffff
|
||||||
|
#define JIT_ICACHE_EXRAM_BIT 0x10000000
|
||||||
// this corresponds to opcode 5 which is invalid in PowerPC
|
// this corresponds to opcode 5 which is invalid in PowerPC
|
||||||
#define JIT_ICACHE_INVALID_BYTE 0x14
|
#define JIT_ICACHE_INVALID_BYTE 0x14
|
||||||
#define JIT_ICACHE_INVALID_WORD 0x14141414
|
#define JIT_ICACHE_INVALID_WORD 0x14141414
|
||||||
|
@ -85,6 +88,7 @@ class JitBlockCache
|
||||||
std::map<std::pair<u32,u32>, u32> block_map; // (end_addr, start_addr) -> number
|
std::map<std::pair<u32,u32>, u32> block_map; // (end_addr, start_addr) -> number
|
||||||
#ifdef JIT_UNLIMITED_ICACHE
|
#ifdef JIT_UNLIMITED_ICACHE
|
||||||
u8 *iCache;
|
u8 *iCache;
|
||||||
|
u8 *iCacheEx;
|
||||||
#endif
|
#endif
|
||||||
int MAX_NUM_BLOCKS;
|
int MAX_NUM_BLOCKS;
|
||||||
|
|
||||||
|
@ -111,6 +115,7 @@ public:
|
||||||
const u8 **GetCodePointers();
|
const u8 **GetCodePointers();
|
||||||
#ifdef JIT_UNLIMITED_ICACHE
|
#ifdef JIT_UNLIMITED_ICACHE
|
||||||
u8 *GetICache();
|
u8 *GetICache();
|
||||||
|
u8 *GetICacheEx();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Fast way to get a block. Only works on the first ppc instruction of a block.
|
// Fast way to get a block. Only works on the first ppc instruction of a block.
|
||||||
|
|
|
@ -71,6 +71,7 @@ namespace PowerPC
|
||||||
memset(plru, 0, sizeof(plru));
|
memset(plru, 0, sizeof(plru));
|
||||||
#ifdef FAST_ICACHE
|
#ifdef FAST_ICACHE
|
||||||
memset(lookup_table, 0xff, sizeof(lookup_table));
|
memset(lookup_table, 0xff, sizeof(lookup_table));
|
||||||
|
memset(lookup_table_ex, 0xff, sizeof(lookup_table_ex));
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -84,20 +85,31 @@ namespace PowerPC
|
||||||
for (int i = 0; i < 8; i++)
|
for (int i = 0; i < 8; i++)
|
||||||
if (valid[set] & (1<<i))
|
if (valid[set] & (1<<i))
|
||||||
{
|
{
|
||||||
lookup_table[((tags[set][i] << 7) | set) & 0xfffff] = 0xff;
|
if (tags[set][i] & (ICACHE_EXRAM_BIT >> 12))
|
||||||
|
lookup_table_ex[((tags[set][i] << 7) | set) & 0x1fffff] = 0xff;
|
||||||
|
else
|
||||||
|
lookup_table[((tags[set][i] << 7) | set) & 0xfffff] = 0xff;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
valid[set] = 0;
|
valid[set] = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
u32 InstructionCache::ReadInstruction(u32 addr)
|
u32 InstructionCache::ReadInstruction(u32 addr)
|
||||||
{
|
{
|
||||||
if (!HID0.ICE) // instuction cache is disabled
|
if (!HID0.ICE) // instuction cache is disabled
|
||||||
return Memory::ReadUnchecked_U32(addr);
|
return Memory::ReadUnchecked_U32(addr);
|
||||||
u32 set = (addr >> 5) & 0x7f;
|
u32 set = (addr >> 5) & 0x7f;
|
||||||
u32 tag = addr >> 12;
|
u32 tag = addr >> 12;
|
||||||
#ifdef FAST_ICACHE
|
#ifdef FAST_ICACHE
|
||||||
u32 t = lookup_table[(addr>>5) & 0xfffff];
|
u32 t;
|
||||||
|
if (addr & ICACHE_EXRAM_BIT)
|
||||||
|
{
|
||||||
|
t = lookup_table_ex[(addr>>5) & 0x1fffff];
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
t = lookup_table[(addr>>5) & 0xfffff];
|
||||||
|
}
|
||||||
#else
|
#else
|
||||||
u32 t = 0xff;
|
u32 t = 0xff;
|
||||||
for (u32 i = 0; i < 8; i++)
|
for (u32 i = 0; i < 8; i++)
|
||||||
|
@ -121,15 +133,24 @@ namespace PowerPC
|
||||||
memcpy(data[set][t], p, 32);
|
memcpy(data[set][t], p, 32);
|
||||||
#ifdef FAST_ICACHE
|
#ifdef FAST_ICACHE
|
||||||
if (valid[set] & (1<<t))
|
if (valid[set] & (1<<t))
|
||||||
lookup_table[((tags[set][t] << 7) | set) & 0xfffff] = 0xff;
|
{
|
||||||
lookup_table[(addr>>5) & 0xfffff] = t;
|
if (tags[set][t] & (ICACHE_EXRAM_BIT >> 12))
|
||||||
|
lookup_table_ex[((tags[set][t] << 7) | set) & 0x1fffff] = 0xff;
|
||||||
|
else
|
||||||
|
lookup_table[((tags[set][t] << 7) | set) & 0xfffff] = 0xff;
|
||||||
|
}
|
||||||
|
if (addr & ICACHE_EXRAM_BIT)
|
||||||
|
lookup_table_ex[(addr>>5) & 0x1fffff] = t;
|
||||||
|
else
|
||||||
|
lookup_table[(addr>>5) & 0xfffff] = t;
|
||||||
#endif
|
#endif
|
||||||
tags[set][t] = tag;
|
tags[set][t] = tag;
|
||||||
valid[set] |= 1<<t;
|
valid[set] |= 1<<t;
|
||||||
}
|
}
|
||||||
// update plru
|
// update plru
|
||||||
plru[set] = (plru[set] & ~plru_mask[t]) | plru_value[t];
|
plru[set] = (plru[set] & ~plru_mask[t]) | plru_value[t];
|
||||||
return Common::swap32(data[set][t][(addr>>2)&7]);
|
u32 res = Common::swap32(data[set][t][(addr>>2)&7]);
|
||||||
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
|
@ -25,11 +25,13 @@
|
||||||
namespace PowerPC
|
namespace PowerPC
|
||||||
{
|
{
|
||||||
|
|
||||||
const u32 ICACHE_SETS = 128;
|
const u32 ICACHE_SETS = 128;
|
||||||
const u32 ICACHE_WAYS = 8;
|
const u32 ICACHE_WAYS = 8;
|
||||||
// size of an instruction cache block in words
|
// size of an instruction cache block in words
|
||||||
const u32 ICACHE_BLOCK_SIZE = 8;
|
const u32 ICACHE_BLOCK_SIZE = 8;
|
||||||
|
|
||||||
|
const u32 ICACHE_EXRAM_BIT = 0x10000000;
|
||||||
|
|
||||||
struct InstructionCache
|
struct InstructionCache
|
||||||
{
|
{
|
||||||
u32 data[ICACHE_SETS][ICACHE_WAYS][ICACHE_BLOCK_SIZE];
|
u32 data[ICACHE_SETS][ICACHE_WAYS][ICACHE_BLOCK_SIZE];
|
||||||
|
@ -42,6 +44,7 @@ namespace PowerPC
|
||||||
|
|
||||||
#ifdef FAST_ICACHE
|
#ifdef FAST_ICACHE
|
||||||
u8 lookup_table[1<<20];
|
u8 lookup_table[1<<20];
|
||||||
|
u8 lookup_table_ex[1<<21];
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
InstructionCache();
|
InstructionCache();
|
||||||
|
|
|
@ -67,7 +67,6 @@ struct GC_ALIGNED64(PowerPCState)
|
||||||
u32 spr[1024];
|
u32 spr[1024];
|
||||||
|
|
||||||
InstructionCache iCache;
|
InstructionCache iCache;
|
||||||
// JIT-mode instruction cache. Managed by JitCache
|
|
||||||
};
|
};
|
||||||
|
|
||||||
enum CPUState
|
enum CPUState
|
||||||
|
|
|
@ -96,7 +96,8 @@ void DoState(PointerWrap &p)
|
||||||
HW::DoState(p);
|
HW::DoState(p);
|
||||||
CoreTiming::DoState(p);
|
CoreTiming::DoState(p);
|
||||||
#ifdef JIT_UNLIMITED_ICACHE
|
#ifdef JIT_UNLIMITED_ICACHE
|
||||||
p.DoVoid(jit.GetBlockCache()->GetICache(), JIT_ICACHE_SIZE);
|
p.DoVoid(jit.GetBlockCache()->GetICache(), JIT_ICACHE_SIZE);
|
||||||
|
p.DoVoid(jit.GetBlockCache()->GetICacheEx(), JIT_ICACHEEX_SIZE);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue