Fixed TLB games support for the iCache, games using the TLB Hack should now work as before (fixes issue 1218)

git-svn-id: https://dolphin-emu.googlecode.com/svn/trunk@4492 8ced0084-cf51-0410-be5f-012b33b47a6e
This commit is contained in:
sl1nk3.s 2009-11-01 01:24:30 +00:00
parent 22a0864337
commit 6c0c97cffe
12 changed files with 125 additions and 27 deletions

View File

@ -50,7 +50,6 @@ may be redirected here (for example to Read_U32()).
// Declarations and definitions
// ----------------
namespace Memory
@ -539,6 +538,7 @@ u32 Read_Opcode_JIT(const u32 _Address)
{
#ifdef JIT_UNLIMITED_ICACHE
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)
{
PanicAlert("iCacheJIT: Reading Opcode from %x. Please report.", _Address);
@ -546,10 +546,15 @@ u32 Read_Opcode_JIT(const u32 _Address)
}
u8* iCache;
u32 addr;
if (_Address & JIT_ICACHE_EXRAM_BIT)
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;
addr = _Address & JIT_ICACHEEX_MASK;
}
else
{
@ -587,6 +592,7 @@ u32 Read_Opcode_JIT_LC(const u32 _Address)
{
#ifdef JIT_UNLIMITED_ICACHE
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)
{
PanicAlert("iCacheJIT: Reading Opcode from %x. Please report.", _Address);
@ -594,10 +600,15 @@ u32 Read_Opcode_JIT_LC(const u32 _Address)
}
u8* iCache;
u32 addr;
if (_Address & JIT_ICACHE_EXRAM_BIT)
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;
addr = _Address & JIT_ICACHEEX_MASK;
}
else
{
@ -624,7 +635,11 @@ u32 Read_Opcode_JIT_LC(const u32 _Address)
void Write_Opcode_JIT(const u32 _Address, const u32 _Value)
{
#ifdef JIT_UNLIMITED_ICACHE
if (_Address & JIT_ICACHE_EXRAM_BIT)
if (_Address & JIT_ICACHE_VMEM_BIT)
{
*(u32*)(jit.GetBlockCache()->GetICacheVMEM() + (_Address & JIT_ICACHE_MASK)) = Common::swap32(_Value);
}
else if (_Address & JIT_ICACHE_EXRAM_BIT)
{
*(u32*)(jit.GetBlockCache()->GetICacheEx() + (_Address & JIT_ICACHEEX_MASK)) = Common::swap32(_Value);
}
@ -790,7 +805,7 @@ void Memset(const u32 _Address, const u8 _iValue, const u32 _iLength)
}
else
{
// (comment for old implementation) : F|RES: rouge squadron and other games use the TLB ... so this cant work
// (comment for old implementation) : F|RES: rogue squadron and other games use the TLB ... so this cant work
// fixed implementation:
for (u32 i = 0; i < _iLength; i++)
@ -894,6 +909,10 @@ u8 *GetPointer(const u32 _Address)
else
return 0;
case 0x7E:
case 0x7F:
return (u8*)(((char*)m_pFakeVMEM) + (_Address & RAM_MASK));
case 0xE0:
if (_Address < (0xE0000000 + L1_CACHE_SIZE))
return GetCachePtr() + (_Address & L1_CACHE_MASK);

View File

@ -45,6 +45,7 @@ namespace Interpreter
void UpdateSSEState();
// Extremely rare - actually, never seen.
// Star Wars : Rogue Leader spams that at some point :|
void Helper_UpdateCR1(double _fValue)
{
// Should just update exception flags, not do any compares.

View File

@ -159,6 +159,8 @@ void AsmRoutineManager::Generate()
SetJumpTarget(needinst);
#ifdef JIT_UNLIMITED_ICACHE
TEST(32, R(EAX), Imm32(JIT_ICACHE_VMEM_BIT));
FixupBranch vmem = J_CC(CC_NZ);
TEST(32, R(EAX), Imm32(JIT_ICACHE_EXRAM_BIT));
FixupBranch exram = J_CC(CC_NZ);
@ -179,9 +181,21 @@ void AsmRoutineManager::Generate()
#else
MOV(64, R(RSI), Imm64((u64)jit.GetBlockCache()->GetICacheEx()));
MOV(32, R(EAX), MComplex(RSI, EAX, SCALE_1, 0));
#endif
#endif
FixupBranch getinst2 = J();
SetJumpTarget(vmem);
AND(32, R(EAX), Imm32(JIT_ICACHE_MASK));
#ifdef _M_IX86
MOV(32, R(EAX), MDisp(EAX, (u32)jit.GetBlockCache()->GetICacheVMEM()));
#else
MOV(64, R(RSI), Imm64((u64)jit.GetBlockCache()->GetICacheVMEM()));
MOV(32, R(EAX), MComplex(RSI, EAX, SCALE_1, 0));
#endif
SetJumpTarget(getinst);
SetJumpTarget(getinst2);
#else
#ifdef _M_IX86
AND(32, R(EAX), Imm32(Memory::MEMVIEW32_MASK));

View File

@ -164,6 +164,8 @@ void AsmRoutineManager::Generate()
SetJumpTarget(needinst);
#ifdef JIT_UNLIMITED_ICACHE
TEST(32, R(EAX), Imm32(JIT_ICACHE_VMEM_BIT));
FixupBranch vmem = J_CC(CC_NZ);
TEST(32, R(EAX), Imm32(JIT_ICACHE_EXRAM_BIT));
FixupBranch exram = J_CC(CC_NZ);
@ -184,9 +186,21 @@ void AsmRoutineManager::Generate()
#else
MOV(64, R(RSI), Imm64((u64)jit.GetBlockCache()->GetICacheEx()));
MOV(32, R(EAX), MComplex(RSI, EAX, SCALE_1, 0));
#endif
#endif
FixupBranch getinst2 = J();
SetJumpTarget(vmem);
AND(32, R(EAX), Imm32(JIT_ICACHE_MASK));
#ifdef _M_IX86
MOV(32, R(EAX), MDisp(EAX, (u32)jit.GetBlockCache()->GetICacheVMEM()));
#else
MOV(64, R(RSI), Imm64((u64)jit.GetBlockCache()->GetICacheVMEM()));
MOV(32, R(EAX), MComplex(RSI, EAX, SCALE_1, 0));
#endif
SetJumpTarget(getinst);
SetJumpTarget(getinst2);
#else
#ifdef _M_IX86
AND(32, R(EAX), Imm32(Memory::MEMVIEW32_MASK));

View File

@ -86,21 +86,23 @@ bool JitBlock::ContainsAddress(u32 em_address)
blocks = new JitBlock[MAX_NUM_BLOCKS];
blockCodePointers = new const u8*[MAX_NUM_BLOCKS];
#ifdef JIT_UNLIMITED_ICACHE
if (iCache == 0 && iCacheEx == 0)
if (iCache == 0 && iCacheEx == 0 && iCacheVMEM == 0)
{
iCache = new u8[JIT_ICACHE_SIZE];
iCacheEx = new u8[JIT_ICACHEEX_SIZE];
iCacheVMEM = new u8[JIT_ICACHE_SIZE];
}
else
{
PanicAlert("JitBlockCache::Init() - iCache is already initialized");
}
if (iCache == 0 || iCacheEx == 0)
if (iCache == 0 || iCacheEx == 0 || iCacheVMEM == 0)
{
PanicAlert("JitBlockCache::Init() - unable to allocate iCache");
}
memset(iCache, JIT_ICACHE_INVALID_BYTE, JIT_ICACHE_SIZE);
memset(iCacheEx, JIT_ICACHE_INVALID_BYTE, JIT_ICACHEEX_SIZE);
memset(iCacheVMEM, JIT_ICACHE_INVALID_BYTE, JIT_ICACHE_SIZE);
#endif
Clear();
}
@ -116,6 +118,9 @@ bool JitBlock::ContainsAddress(u32 em_address)
if (iCacheEx != 0)
delete [] iCacheEx;
iCacheEx = 0;
if (iCacheVMEM != 0)
delete [] iCacheVMEM;
iCacheVMEM = 0;
#endif
blocks = 0;
blockCodePointers = 0;
@ -238,6 +243,11 @@ bool JitBlock::ContainsAddress(u32 em_address)
{
return iCacheEx;
}
u8* JitBlockCache::GetICacheVMEM()
{
return iCacheVMEM;
}
#endif
int JitBlockCache::GetBlockNumberFromStartAddress(u32 addr)
@ -246,7 +256,11 @@ bool JitBlock::ContainsAddress(u32 em_address)
return -1;
#ifdef JIT_UNLIMITED_ICACHE
u32 inst;
if (addr & JIT_ICACHE_EXRAM_BIT)
if (addr & JIT_ICACHE_VMEM_BIT)
{
inst = *(u32*)(iCacheVMEM + (addr & JIT_ICACHE_MASK));
}
else if (addr & JIT_ICACHE_EXRAM_BIT)
{
inst = *(u32*)(iCacheEx + (addr & JIT_ICACHEEX_MASK));
}
@ -394,11 +408,17 @@ bool JitBlock::ContainsAddress(u32 em_address)
// invalidate iCache.
// icbi can be called with any address, so we sholud 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_EXRAM_BIT)
if (address & JIT_ICACHE_VMEM_BIT)
{
u32 cacheaddr = address & JIT_ICACHE_MASK;
memset(iCacheVMEM + cacheaddr, JIT_ICACHE_INVALID_BYTE, 32);
}
else if (address & JIT_ICACHE_EXRAM_BIT)
{
u32 cacheaddr = address & JIT_ICACHEEX_MASK;
memset(iCacheEx + cacheaddr, JIT_ICACHE_INVALID_BYTE, 32);

View File

@ -37,6 +37,7 @@
#define JIT_ICACHEEX_SIZE 0x4000000
#define JIT_ICACHEEX_MASK 0x3ffffff
#define JIT_ICACHE_EXRAM_BIT 0x10000000
#define JIT_ICACHE_VMEM_BIT 0x20000000
// this corresponds to opcode 5 which is invalid in PowerPC
#define JIT_ICACHE_INVALID_BYTE 0x14
#define JIT_ICACHE_INVALID_WORD 0x14141414
@ -89,6 +90,7 @@ class JitBlockCache
#ifdef JIT_UNLIMITED_ICACHE
u8 *iCache;
u8 *iCacheEx;
u8 *iCacheVMEM;
#endif
int MAX_NUM_BLOCKS;
@ -116,6 +118,7 @@ public:
#ifdef JIT_UNLIMITED_ICACHE
u8 *GetICache();
u8 *GetICacheEx();
u8 *GetICacheVMEM();
#endif
// Fast way to get a block. Only works on the first ppc instruction of a block.

View File

@ -72,6 +72,7 @@ namespace PowerPC
#ifdef FAST_ICACHE
memset(lookup_table, 0xff, sizeof(lookup_table));
memset(lookup_table_ex, 0xff, sizeof(lookup_table_ex));
memset(lookup_table_vmem, 0xff, sizeof(lookup_table_vmem));
#endif
}
@ -85,7 +86,9 @@ namespace PowerPC
for (int i = 0; i < 8; i++)
if (valid[set] & (1<<i))
{
if (tags[set][i] & (ICACHE_EXRAM_BIT >> 12))
if (tags[set][i] & (ICACHE_VMEM_BIT >> 12))
lookup_table_vmem[((tags[set][i] << 7) | set) & 0xfffff] = 0xff;
else 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;
@ -102,7 +105,11 @@ namespace PowerPC
u32 tag = addr >> 12;
#ifdef FAST_ICACHE
u32 t;
if (addr & ICACHE_EXRAM_BIT)
if (addr & ICACHE_VMEM_BIT)
{
t = lookup_table_vmem[(addr>>5) & 0xfffff];
}
else if (addr & ICACHE_EXRAM_BIT)
{
t = lookup_table_ex[(addr>>5) & 0x1fffff];
}
@ -134,12 +141,16 @@ namespace PowerPC
#ifdef FAST_ICACHE
if (valid[set] & (1<<t))
{
if (tags[set][t] & (ICACHE_EXRAM_BIT >> 12))
if (tags[set][t] & (ICACHE_VMEM_BIT >> 12))
lookup_table_vmem[((tags[set][t] << 7) | set) & 0xfffff] = 0xff;
else 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)
if (addr & ICACHE_VMEM_BIT)
lookup_table_vmem[(addr>>5) & 0xfffff] = t;
else if (addr & ICACHE_EXRAM_BIT)
lookup_table_ex[(addr>>5) & 0x1fffff] = t;
else
lookup_table[(addr>>5) & 0xfffff] = t;

View File

@ -31,6 +31,7 @@ namespace PowerPC
const u32 ICACHE_BLOCK_SIZE = 8;
const u32 ICACHE_EXRAM_BIT = 0x10000000;
const u32 ICACHE_VMEM_BIT = 0x20000000;
struct InstructionCache
{
@ -45,6 +46,7 @@ namespace PowerPC
#ifdef FAST_ICACHE
u8 lookup_table[1<<20];
u8 lookup_table_ex[1<<21];
u8 lookup_table_vmem[1<<20];
#endif
InstructionCache();

View File

@ -72,7 +72,7 @@ static Common::Thread *saveThread = NULL;
// Don't forget to increase this after doing changes on the savestate system
#define STATE_VERSION 1
#define STATE_VERSION 2
void DoState(PointerWrap &p)
@ -81,7 +81,8 @@ void DoState(PointerWrap &p)
p.Do(cookie);
if (cookie != 0xBAADBABE + STATE_VERSION)
{
PanicAlert("Savestate version mismatch !\nSorry, you can't load states from other revisions.");
//PanicAlert("Savestate version mismatch !\nSorry, you can't load states from other revisions.");
p.SetMode(PointerWrap::MODE_MEASURE);
return;
}
// Begin with video plugin, so that it gets a chance to clear it's caches and writeback modified things to RAM
@ -97,6 +98,7 @@ void DoState(PointerWrap &p)
#ifdef JIT_UNLIMITED_ICACHE
p.DoVoid(jit.GetBlockCache()->GetICache(), JIT_ICACHE_SIZE);
p.DoVoid(jit.GetBlockCache()->GetICacheEx(), JIT_ICACHEEX_SIZE);
p.DoVoid(jit.GetBlockCache()->GetICacheVMEM(), JIT_ICACHE_SIZE);
#endif
}
@ -345,9 +347,13 @@ void LoadStateCallback(u64 userdata, int cyclesLate)
u8 *ptr = buffer;
PointerWrap p(&ptr, PointerWrap::MODE_READ);
DoState(p);
delete [] buffer;
Core::DisplayMessage(StringFromFormat("Loaded state from %s", cur_filename.c_str()).c_str(), 2000);
if (p.GetMode() == PointerWrap::MODE_READ)
Core::DisplayMessage(StringFromFormat("Loaded state from %s", cur_filename.c_str()).c_str(), 2000);
else
Core::DisplayMessage("Unable to Load : Can't load state from other revisions !", 4000);
delete [] buffer;
}
void State_Init()

View File

@ -659,7 +659,10 @@ void CFrame::OnKeyDown(wxKeyEvent& event)
// Toggle fullscreen
if (event.GetKeyCode() == WXK_ESCAPE || (event.GetKeyCode() == WXK_RETURN && event.GetModifiers() == wxMOD_ALT))
{
DoFullscreen(!IsFullScreen());
// If a modal dialog is open, this will still process the keyboard events, and may cause
// the main window to become unresponsive, so we have to avoid that.
if ((bRenderToMain || Core::GetState() != Core::CORE_RUN) && !m_bModalDialogOpen)
DoFullscreen(!IsFullScreen());
// We do that to avoid the event to be double processed (which would cause the window to be stuck in fullscreen)
event.StopPropagation();
@ -832,9 +835,7 @@ wxAuiNotebook* CFrame::CreateEmptyNotebook()
void CFrame::DoFullscreen(bool bF)
{
// Only switch this to fullscreen if we're rendering to main OR if we're not running a game
// AND if this is the active window, as it could cause the main window to become unresponsive
// if we're switching to fullscreen while a modal dialog is open
if ((bRenderToMain || Core::GetState() != Core::CORE_RUN) && this->IsActive())
if (bRenderToMain || Core::GetState() != Core::CORE_RUN)
{
ShowFullScreen(bF);

View File

@ -194,6 +194,7 @@ class CFrame : public wxFrame
bool m_bEdit;
bool m_bTabSplit;
bool m_bNoDocking;
bool m_bModalDialogOpen;
char **drives;

View File

@ -665,9 +665,11 @@ void CFrame::OnReset(wxCommandEvent& WXUNUSED (event))
void CFrame::OnConfigMain(wxCommandEvent& WXUNUSED (event))
{
m_bModalDialogOpen = true;
CConfigMain ConfigMain(this);
if (ConfigMain.ShowModal() == wxID_OK)
m_GameListCtrl->Update();
m_bModalDialogOpen = false;
}
void CFrame::OnPluginGFX(wxCommandEvent& WXUNUSED (event))
@ -712,8 +714,10 @@ void CFrame::OnHelp(wxCommandEvent& event)
{
case IDM_HELPABOUT:
{
AboutDolphin frame(this);
frame.ShowModal();
m_bModalDialogOpen = true;
AboutDolphin frame(this);
frame.ShowModal();
m_bModalDialogOpen = false;
break;
}
case IDM_HELPWEBSITE:
@ -756,8 +760,10 @@ void CFrame::OnNetPlay(wxCommandEvent& WXUNUSED (event))
void CFrame::OnMemcard(wxCommandEvent& WXUNUSED (event))
{
m_bModalDialogOpen = true;
CMemcardManager MemcardManager(this);
MemcardManager.ShowModal();
m_bModalDialogOpen = false;
}
void CFrame::OnShow_CheatsWindow(wxCommandEvent& WXUNUSED (event))