Made the JIT bypass the icache when it is executing the external interrupt
exception handler. Fixed by comwiz.k
This commit is contained in:
parent
7f055d6b56
commit
3d2a2abb49
|
@ -419,6 +419,44 @@ u32 Read_Instruction(const u32 em_address)
|
|||
return inst.hex;
|
||||
}
|
||||
|
||||
u32 Read_Opcode_JIT_Uncached(const u32 _Address)
|
||||
{
|
||||
u8* iCache;
|
||||
u32 addr;
|
||||
if (_Address & JIT_ICACHE_VMEM_BIT)
|
||||
{
|
||||
iCache = jit->GetBlockCache()->GetICacheVMEM();
|
||||
addr = _Address & JIT_ICACHE_MASK;
|
||||
}
|
||||
else 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);
|
||||
if (inst == JIT_ICACHE_INVALID_WORD)
|
||||
{
|
||||
u32 cache_block_start = addr & ~0x1f;
|
||||
u32 mem_block_start = _Address & ~0x1f;
|
||||
u8 *pMem = Memory::GetPointer(mem_block_start);
|
||||
memcpy(iCache + cache_block_start, pMem, 32);
|
||||
inst = *(u32*)(iCache + addr);
|
||||
}
|
||||
inst = Common::swap32(inst);
|
||||
|
||||
if ((inst & 0xfc000000) == 0)
|
||||
{
|
||||
inst = jit->GetBlockCache()->GetOriginalFirstOp(inst);
|
||||
}
|
||||
|
||||
return inst;
|
||||
}
|
||||
|
||||
u32 Read_Opcode_JIT(u32 _Address)
|
||||
{
|
||||
#ifdef FAST_ICACHE
|
||||
|
@ -430,8 +468,13 @@ u32 Read_Opcode_JIT(u32 _Address)
|
|||
return 0;
|
||||
}
|
||||
}
|
||||
u32 inst = 0;
|
||||
|
||||
u32 inst = PowerPC::ppcState.iCache.ReadInstruction(_Address);
|
||||
// Bypass the icache for the external interrupt exception handler
|
||||
if ( (_Address & 0x0FFFFF00) == 0x00000500 )
|
||||
inst = Read_Opcode_JIT_Uncached(_Address);
|
||||
else
|
||||
inst = PowerPC::ppcState.iCache.ReadInstruction(_Address);
|
||||
#else
|
||||
u32 inst = Memory::ReadUnchecked_U32(_Address);
|
||||
#endif
|
||||
|
|
|
@ -133,9 +133,9 @@ bool JitBlock::ContainsAddress(u32 em_address)
|
|||
DestroyBlock(i, false);
|
||||
}
|
||||
links_to.clear();
|
||||
block_map.clear();
|
||||
num_blocks = 0;
|
||||
memset(blockCodePointers, 0, sizeof(u8*)*MAX_NUM_BLOCKS);
|
||||
ClearSafe();
|
||||
}
|
||||
|
||||
void JitBlockCache::ClearSafe()
|
||||
|
@ -207,9 +207,8 @@ bool JitBlock::ContainsAddress(u32 em_address)
|
|||
blockCodePointers[block_num] = code_ptr;
|
||||
JitBlock &b = blocks[block_num];
|
||||
b.originalFirstOpcode = Memory::Read_Opcode_JIT(b.originalAddress);
|
||||
if ((b.originalAddress + b.originalSize) > code_high)
|
||||
code_high = b.originalAddress + b.originalSize;
|
||||
Memory::Write_Opcode_JIT(b.originalAddress, (JIT_OPCODE << 26) | block_num);
|
||||
block_map[std::make_pair(b.originalAddress + 4 * b.originalSize - 1, b.originalAddress)] = block_num;
|
||||
if (block_link)
|
||||
{
|
||||
for (int i = 0; i < 2; i++)
|
||||
|
@ -356,44 +355,79 @@ bool JitBlock::ContainsAddress(u32 em_address)
|
|||
|
||||
void JitBlockCache::DestroyBlock(int block_num, bool invalidate)
|
||||
{
|
||||
if (block_num < 0 || block_num >= num_blocks)
|
||||
{
|
||||
PanicAlert("DestroyBlock: Invalid block number %d", block_num);
|
||||
return;
|
||||
}
|
||||
JitBlock &b = blocks[block_num];
|
||||
if (b.invalid)
|
||||
{
|
||||
if (invalidate)
|
||||
PanicAlert("Invalidating invalid block %d", block_num);
|
||||
return;
|
||||
}
|
||||
b.invalid = true;
|
||||
#ifdef JIT_UNLIMITED_ICACHE
|
||||
Memory::Write_Opcode_JIT(b.originalAddress, JIT_ICACHE_INVALID_WORD);
|
||||
Memory::Write_Opcode_JIT(b.originalAddress, b.originalFirstOpcode?b.originalFirstOpcode:JIT_ICACHE_INVALID_WORD);
|
||||
#else
|
||||
if (Memory::ReadFast32(b.originalAddress) == block_num)
|
||||
Memory::WriteUnchecked_U32(b.originalFirstOpcode, b.originalAddress);
|
||||
#endif
|
||||
|
||||
// We don't unlink blocks, we just send anyone who tries to run them back to the dispatcher.
|
||||
// Not entirely ideal, but .. pretty good.
|
||||
// Spurious entrances from previously linked blocks can only come through checkedEntry
|
||||
XEmitter emit((u8 *)b.checkedEntry);
|
||||
emit.MOV(32, M(&PC), Imm32(b.originalAddress));
|
||||
emit.JMP(jit->GetAsmRoutines()->dispatcher, true);
|
||||
// this is not needed really
|
||||
/*
|
||||
emit.SetCodePtr((u8 *)blockCodePointers[blocknum]);
|
||||
emit.MOV(32, M(&PC), Imm32(b.originalAddress));
|
||||
emit.JMP(asm_routines.dispatcher, true);
|
||||
*/
|
||||
}
|
||||
|
||||
|
||||
void JitBlockCache::InvalidateICache(u32 address)
|
||||
{
|
||||
address &= ~0x1f;
|
||||
// destroy JIT blocks
|
||||
// !! this works correctly under assumption that any two overlapping blocks end at the same address
|
||||
std::map<pair<u32,u32>, u32>::iterator it1 = block_map.lower_bound(std::make_pair(address, 0)), it2 = it1, it;
|
||||
while (it2 != block_map.end() && it2->first.second < address + 0x20)
|
||||
{
|
||||
DestroyBlock(it2->second, true);
|
||||
it2++;
|
||||
}
|
||||
if (it1 != it2)
|
||||
{
|
||||
block_map.erase(it1, it2);
|
||||
}
|
||||
|
||||
#ifdef JIT_UNLIMITED_ICACHE
|
||||
// invalidate iCache.
|
||||
// icbi can be called with any address, so we should check
|
||||
if ((address & ~JIT_ICACHE_MASK) != 0x80000000 && (address & ~JIT_ICACHE_MASK) != 0x00000000 &&
|
||||
(address & ~JIT_ICACHE_MASK) != 0x7e000000 && // TLB area
|
||||
(address & ~JIT_ICACHEEX_MASK) != 0x90000000 && (address & ~JIT_ICACHEEX_MASK) != 0x10000000)
|
||||
{
|
||||
return;
|
||||
}
|
||||
if (address & JIT_ICACHE_VMEM_BIT)
|
||||
{
|
||||
u32 cacheaddr = address & JIT_ICACHE_MASK;
|
||||
if (cacheaddr > (code_high & JIT_ICACHE_MASK))
|
||||
return;
|
||||
memset(iCacheVMEM + cacheaddr, JIT_ICACHE_INVALID_BYTE, 32);
|
||||
}
|
||||
else if (address & JIT_ICACHE_EXRAM_BIT)
|
||||
{
|
||||
u32 cacheaddr = address & JIT_ICACHEEX_MASK;
|
||||
if (cacheaddr > (code_high & JIT_ICACHEEX_MASK))
|
||||
return;
|
||||
memset(iCacheEx + cacheaddr, JIT_ICACHE_INVALID_BYTE, 32);
|
||||
}
|
||||
else
|
||||
{
|
||||
u32 cacheaddr = address & JIT_ICACHE_MASK;
|
||||
if (cacheaddr > (code_high & JIT_ICACHE_MASK))
|
||||
return;
|
||||
memset(iCache + cacheaddr, JIT_ICACHE_INVALID_BYTE, 32);
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -76,6 +76,7 @@ class JitBlockCache
|
|||
JitBlock *blocks;
|
||||
int num_blocks;
|
||||
std::multimap<u32, int> links_to;
|
||||
std::map<std::pair<u32,u32>, u32> block_map; // (end_addr, start_addr) -> number
|
||||
#ifdef JIT_UNLIMITED_ICACHE
|
||||
u8 *iCache;
|
||||
u8 *iCacheEx;
|
||||
|
@ -104,7 +105,6 @@ public:
|
|||
void Reset();
|
||||
|
||||
bool IsFull() const;
|
||||
u32 code_high;
|
||||
|
||||
// Code Cache
|
||||
JitBlock *GetBlock(int block_num);
|
||||
|
|
Loading…
Reference in New Issue