Changed the HLE system to allow it to hook the beginning, the end or replace the entire function without changing the GC memory. Fixes Kirby's Return to Dreamland.

Added a way to categorise the type of HLE function.  Currently, there are debug, floating point, memory and generic functions.
Added a HLE function for OSGetResetCode (Warm reset).  Fixes the CSI games.
Added a switch to disable all of the HLE functions if the idle skipping option is disabled.
This commit is contained in:
skidau 2012-12-28 14:26:46 +11:00
parent 05730af724
commit 95f6685900
14 changed files with 339 additions and 123 deletions

Binary file not shown.

View File

@ -258,7 +258,7 @@ bool CBoot::BootUp()
}
// Scan for common HLE functions
if (!_StartupPara.bEnableDebugging && Memory::Read_U16(0x00003140) >= 30)
if (_StartupPara.bSkipIdle && !_StartupPara.bEnableDebugging)
{
PPCAnalyst::FindFunctions(0x80004000, 0x811fffff, &g_symbolDB);
SignatureDB db;
@ -267,7 +267,6 @@ bool CBoot::BootUp()
db.Apply(&g_symbolDB);
HLE::PatchFunctions();
db.Clear();
g_symbolDB.Clear();
}
}

View File

@ -375,7 +375,7 @@ bool CBoot::EmulatedBS2_Wii()
u32 iLength = Memory::ReadUnchecked_U32(0x81300008);
u32 iDVDOffset = Memory::ReadUnchecked_U32(0x8130000c) << 2;
INFO_LOG(BOOT, "DVDRead: offset: %08x memOffse: %08x length: %i", iDVDOffset, iRamAddress, iLength);
INFO_LOG(BOOT, "DVDRead: offset: %08x memOffset: %08x length: %i", iDVDOffset, iRamAddress, iLength);
DVDInterface::DVDRead(iDVDOffset, iRamAddress, iLength);
} while(PowerPC::ppcState.gpr[3] != 0x00);

View File

@ -15,7 +15,6 @@
// Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/
#include <map>
#include "Common.h"
#include "HLE.h"
@ -29,6 +28,7 @@
#include "HLE_Misc.h"
#include "IPC_HLE/WII_IPC_HLE_Device_es.h"
#include "ConfigManager.h"
#include "Core.h"
namespace HLE
{
@ -47,56 +47,72 @@ struct SPatch
{
char m_szPatchName[128];
TPatchFunction PatchFunction;
int type;
int flags;
};
static const SPatch OSPatches[] =
{
{ "FAKE_TO_SKIP_0", HLE_Misc::UnimplementedFunction },
{ "FAKE_TO_SKIP_0", HLE_Misc::UnimplementedFunction, HLE_HOOK_REPLACE, HLE_TYPE_GENERIC },
// speedup
//{ "OSProtectRange", HLE_Misc::UnimplementedFunctionFalse },
//{ "THPPlayerGetState", HLE_Misc:THPPlayerGetState },
//{ "OSProtectRange", HLE_Misc::UnimplementedFunctionFalse, HLE_HOOK_REPLACE, HLE_TYPE_GENERIC },
//{ "THPPlayerGetState", HLE_Misc:THPPlayerGetState, HLE_HOOK_REPLACE, HLE_TYPE_GENERIC },
//{ "memcpy", HLE_Misc::memcpy, HLE_HOOK_REPLACE, HLE_TYPE_MEMORY },
//{ "memcmp", HLE_Misc::memcmp, HLE_HOOK_REPLACE, HLE_TYPE_MEMORY },
//{ "memset", HLE_Misc::memset, HLE_HOOK_REPLACE, HLE_TYPE_MEMORY },
//{ "memmove", HLE_Misc::memmove, HLE_HOOK_REPLACE, HLE_TYPE_MEMORY },
//{ "__div2i", HLE_Misc::div2i, HLE_HOOK_REPLACE, HLE_TYPE_GENERIC }, // Slower?
//{ "__div2u", HLE_Misc::div2u, HLE_HOOK_REPLACE, HLE_TYPE_GENERIC }, // Slower?
//{ "DCFlushRange", HLE_Misc::UnimplementedFunction, HLE_HOOK_REPLACE, HLE_TYPE_GENERIC },
//{ "DCInvalidateRange", HLE_Misc::UnimplementedFunction, HLE_HOOK_REPLACE, HLE_TYPE_GENERIC },
//{ "DCZeroRange", HLE_Misc::UnimplementedFunction, HLE_HOOK_REPLACE, HLE_TYPE_GENERIC },
// debug out is very nice ;)
{ "OSReport", HLE_OS::HLE_GeneralDebugPrint },
{ "DEBUGPrint", HLE_OS::HLE_GeneralDebugPrint },
{ "WUD_DEBUGPrint", HLE_OS::HLE_GeneralDebugPrint },
{ "OSPanic", HLE_OS::HLE_OSPanic },
{ "vprintf", HLE_OS::HLE_GeneralDebugPrint },
{ "printf", HLE_OS::HLE_GeneralDebugPrint },
{ "puts", HLE_OS::HLE_GeneralDebugPrint }, // gcc-optimized printf?
{ "___blank(char *,...)", HLE_OS::HLE_GeneralDebugPrint }, // used for early init things (normally)
{ "___blank", HLE_OS::HLE_GeneralDebugPrint },
{ "__write_console", HLE_OS::HLE_write_console }, // used by sysmenu (+more?)
{ "OSReport", HLE_OS::HLE_GeneralDebugPrint, HLE_HOOK_REPLACE, HLE_TYPE_DEBUG },
{ "DEBUGPrint", HLE_OS::HLE_GeneralDebugPrint, HLE_HOOK_REPLACE, HLE_TYPE_DEBUG },
{ "WUD_DEBUGPrint", HLE_OS::HLE_GeneralDebugPrint, HLE_HOOK_REPLACE, HLE_TYPE_DEBUG },
{ "OSPanic", HLE_OS::HLE_OSPanic, HLE_HOOK_REPLACE, HLE_TYPE_DEBUG },
{ "vprintf", HLE_OS::HLE_GeneralDebugPrint, HLE_HOOK_REPLACE, HLE_TYPE_DEBUG },
{ "printf", HLE_OS::HLE_GeneralDebugPrint, HLE_HOOK_REPLACE, HLE_TYPE_DEBUG },
{ "puts", HLE_OS::HLE_GeneralDebugPrint, HLE_HOOK_REPLACE, HLE_TYPE_DEBUG }, // gcc-optimized printf?
{ "___blank(char *,...)", HLE_OS::HLE_GeneralDebugPrint, HLE_HOOK_REPLACE, HLE_TYPE_DEBUG }, // used for early init things (normally)
{ "___blank", HLE_OS::HLE_GeneralDebugPrint, HLE_HOOK_REPLACE, HLE_TYPE_DEBUG },
{ "__write_console", HLE_OS::HLE_write_console, HLE_HOOK_REPLACE, HLE_TYPE_DEBUG }, // used by sysmenu (+more?)
// wii only
//{ "__OSInitAudioSystem", HLE_Misc::UnimplementedFunction },
//{ "__OSInitAudioSystem", HLE_Misc::UnimplementedFunction, HLE_HOOK_REPLACE, HLE_TYPE_GENERIC },
// Super Monkey Ball - no longer needed.
//{ ".evil_vec_cosine", HLE_Misc::SMB_EvilVecCosine },
//{ ".evil_normalize", HLE_Misc::SMB_EvilNormalize },
//{ ".evil_vec_setlength", HLE_Misc::SMB_evil_vec_setlength },
//{ ".evil_vec_something", HLE_Misc::FZero_evil_vec_normalize },
{ "PanicAlert", HLE_Misc::HLEPanicAlert },
//{ ".sqrt_internal_needs_cr1", HLE_Misc::SMB_sqrt_internal },
//{ ".rsqrt_internal_needs_cr1", HLE_Misc::SMB_rsqrt_internal },
//{ ".atan2", HLE_Misc::SMB_atan2},
//{ ".sqrt_fz", HLE_Misc::FZ_sqrt},
//{ ".evil_vec_cosine", HLE_Misc::SMB_EvilVecCosine, HLE_HOOK_REPLACE, HLE_TYPE_GENERIC },
//{ ".evil_normalize", HLE_Misc::SMB_EvilNormalize, HLE_HOOK_REPLACE, HLE_TYPE_GENERIC },
//{ ".evil_vec_setlength", HLE_Misc::SMB_evil_vec_setlength, HLE_HOOK_REPLACE, HLE_TYPE_GENERIC },
//{ ".evil_vec_something", HLE_Misc::FZero_evil_vec_normalize, HLE_HOOK_REPLACE, HLE_TYPE_GENERIC },
{ "PanicAlert", HLE_Misc::HLEPanicAlert, HLE_HOOK_REPLACE, HLE_TYPE_DEBUG },
//{ ".sqrt_internal_needs_cr1", HLE_Misc::SMB_sqrt_internal, HLE_HOOK_REPLACE, HLE_TYPE_GENERIC },
//{ ".rsqrt_internal_needs_cr1", HLE_Misc::SMB_rsqrt_internal, HLE_HOOK_REPLACE, HLE_TYPE_GENERIC },
//{ ".atan2", HLE_Misc::SMB_atan2HLE_HOOK_REPLACE, HLE_TYPE_GENERIC },
//{ ".sqrt_fz", HLE_Misc::FZ_sqrtHLE_HOOK_REPLACE, HLE_TYPE_GENERIC },
// F-zero still isn't working correctly, but these aren't really helping.
//{ ".sqrt_internal_fz", HLE_Misc::FZ_sqrt_internal },
//{ ".rsqrt_internal_fz", HLE_Misc::FZ_rsqrt_internal },
//{ ".sqrt_internal_fz", HLE_Misc::FZ_sqrt_internal, HLE_HOOK_REPLACE, HLE_TYPE_GENERIC },
//{ ".rsqrt_internal_fz", HLE_Misc::FZ_rsqrt_internal, HLE_HOOK_REPLACE, HLE_TYPE_GENERIC },
//{ ".kill_infinites", HLE_Misc::FZero_kill_infinites },
//{ ".kill_infinites", HLE_Misc::FZero_kill_infinites, HLE_HOOK_REPLACE, HLE_TYPE_GENERIC },
// special
// { "GXPeekZ", HLE_Misc::GXPeekZ},
// { "GXPeekARGB", HLE_Misc::GXPeekARGB},
// { "GXPeekZ", HLE_Misc::GXPeekZHLE_HOOK_REPLACE, HLE_TYPE_GENERIC },
// { "GXPeekARGB", HLE_Misc::GXPeekARGBHLE_HOOK_REPLACE, HLE_TYPE_GENERIC },
// Name doesn't matter, installed in CBoot::BootUp()
{ "HBReload", HLE_Misc::HBReload },
{ "__OSBootDol", HLE_Misc::OSBootDol },
{ "HBReload", HLE_Misc::HBReload, HLE_HOOK_REPLACE, HLE_TYPE_GENERIC },
// ES_LAUNCH
{ "__OSBootDol", HLE_Misc::OSBootDol, HLE_HOOK_REPLACE, HLE_TYPE_GENERIC },
{ "OSGetResetCode", HLE_Misc::OSGetResetCode, HLE_HOOK_REPLACE, HLE_TYPE_GENERIC },
};
static const SPatch OSBreakPoints[] =
@ -104,17 +120,13 @@ static const SPatch OSBreakPoints[] =
{ "FAKE_TO_SKIP_0", HLE_Misc::UnimplementedFunction },
};
static std::map<u32, u32> orig_instruction;
void Patch(u32 address, const char *hle_func_name)
void Patch(u32 addr, const char *hle_func_name)
{
for (u32 i = 0; i < sizeof(OSPatches) / sizeof(SPatch); i++)
{
if (!strcmp(OSPatches[i].m_szPatchName, hle_func_name))
{
u32 HLEPatchValue = (1 & 0x3f) << 26;
Memory::Write_U32(HLEPatchValue | i, address);
orig_instruction[addr] = i;
return;
}
}
@ -128,11 +140,9 @@ void PatchFunctions()
Symbol *symbol = g_symbolDB.GetSymbolFromName(OSPatches[i].m_szPatchName);
if (symbol > 0)
{
u32 HLEPatchValue = (1 & 0x3f) << 26;
for (u32 addr = symbol->address; addr < symbol->address + symbol->size; addr += 4)
{
orig_instruction[addr] = Memory::ReadUnchecked_U32(addr);
Memory::Write_U32(HLEPatchValue | i, addr);
orig_instruction[addr] = i;
}
INFO_LOG(OSHLE, "Patching %s %08x", OSPatches[i].m_szPatchName, symbol->address);
}
@ -169,12 +179,33 @@ void Execute(u32 _CurrentPC, u32 _Instruction)
// _dbg_assert_msg_(HLE,NPC == LR, "Broken HLE function (doesn't set NPC)", OSPatches[pos].m_szPatchName);
}
u32 GetOrigInstruction(u32 addr)
u32 GetFunctionIndex(u32 addr)
{
std::map<u32, u32>::const_iterator iter = orig_instruction.find(addr);
return (iter != orig_instruction.end()) ? iter->second : 0;
}
int GetFunctionTypeByIndex(u32 index)
{
return OSPatches[index].type;
}
int GetFunctionFlagsByIndex(u32 index)
{
return OSPatches[index].flags;
}
bool IsEnabled(int flags)
{
if (flags == HLE::HLE_TYPE_MEMORY && Core::g_CoreStartupParameter.bMMU)
return false;
if (flags == HLE::HLE_TYPE_DEBUG && !Core::g_CoreStartupParameter.bEnableDebugging && PowerPC::GetMode() != MODE_INTERPRETER)
return false;
return true;
}
u32 UnPatch(std::string patchName)
{
Symbol *symbol = g_symbolDB.GetSymbolFromName(patchName.c_str());
@ -182,7 +213,7 @@ u32 UnPatch(std::string patchName)
{
for (u32 addr = symbol->address; addr < symbol->address + symbol->size; addr += 4)
{
Memory::WriteUnchecked_U32(orig_instruction[addr], addr);
orig_instruction[addr] = 0;
PowerPC::ppcState.iCache.Invalidate(addr);
}
return symbol->address;

View File

@ -18,16 +18,40 @@
#ifndef _HLE_H
#define _HLE_H
#include <map>
#include "Common.h"
namespace HLE
{
enum
{
HLE_HOOK_START = 0, // Hook the beginning of the function and execute the function afterwards
HLE_HOOK_END = 1, // Hook the end of the function, executing the function first before the hook
HLE_HOOK_REPLACE = 2, // Replace the function with the HLE version
HLE_HOOK_NONE = 3, // Do not hook the function
};
enum
{
HLE_TYPE_GENERIC = 0, // Miscellaneous function
HLE_TYPE_MEMORY = 1, // Memory operation
HLE_TYPE_FP = 2, // Floating Point operation
HLE_TYPE_DEBUG = 3, // Debug output function
};
void PatchFunctions();
void Patch(u32 pc, const char *func_name);
u32 UnPatch(std::string patchName);
void Execute(u32 _CurrentPC, u32 _Instruction);
u32 GetOrigInstruction(u32 em_address);
u32 GetFunctionIndex(u32 em_address);
int GetFunctionTypeByIndex(u32 index);
int GetFunctionFlagsByIndex(u32 index);
bool IsEnabled(int flags);
static std::map<u32, u32> orig_instruction;
}
#endif

View File

@ -37,7 +37,6 @@
namespace HLE_Misc
{
std::string dol;
std::string args;
u32 argsPtr;
u32 bootType;
@ -302,7 +301,7 @@ void HBReload()
void ExecuteDOL(u8* dolFile, u32 fileSize)
{
// Clear memory before loading the dol
for (int i = 0x80004000; i < Memory::Read_U32(0x00000034); i += 4)
for (u32 i = 0x80004000; i < Memory::Read_U32(0x00000034); i += 4)
{
// TODO: Should not write over the "save region"
Memory::Write_U32(0x00000000, i);
@ -320,7 +319,6 @@ void ExecuteDOL(u8* dolFile, u32 fileSize)
db.Apply(&g_symbolDB);
HLE::PatchFunctions();
db.Clear();
g_symbolDB.Clear();
}
}
@ -359,12 +357,12 @@ void ExecuteDOL(u8* dolFile, u32 fileSize)
NPC = dolLoader.GetEntryPoint() | 0x80000000;
}
void LoadDOLFromDisc()
void LoadDOLFromDisc(std::string dol)
{
DiscIO::IVolume* pVolume = DiscIO::CreateVolumeFromFilename(SConfig::GetInstance().m_LastFilename.c_str());
DiscIO::IFileSystem* pFileSystem = DiscIO::CreateFileSystem(pVolume);
if (dol.substr(1, 1).compare("//"))
if (dol.length() > 1 && dol.compare(0, 1, "/") == 0)
dol = dol.substr(1);
u32 fileSize = (u32) pFileSystem->GetFileSize(dol.c_str());
@ -391,19 +389,92 @@ void LoadBootDOLFromDisc()
delete[] dolFile;
}
u32 GetDolFileSize()
u32 GetDolFileSize(std::string dol)
{
DiscIO::IVolume* pVolume = DiscIO::CreateVolumeFromFilename(SConfig::GetInstance().m_LastFilename.c_str());
DiscIO::IFileSystem* pFileSystem = DiscIO::CreateFileSystem(pVolume);
std::string dolFile;
if (dol.substr(1, 1).compare("//"))
if (dol.length() > 1 && dol.compare(0, 1, "/") == 0)
dolFile = dol.substr(1);
else
dolFile = dol;
return (u32)pFileSystem->GetFileSize(dolFile.c_str());
}
void memmove()
{
u32 dest = GPR(3);
u32 src = GPR(4);
u32 count = GPR(5);
std::memmove((u8*)(Memory::base + dest), (u8*)(Memory::base + src), count);
NPC = LR;
}
void memcpy()
{
u32 dest = GPR(3);
u32 src = GPR(4);
u32 count = GPR(5);
std::memcpy((u8*)(Memory::base + dest), (u8*)(Memory::base + src), count);
NPC = LR;
}
void memset()
{
u32 dest = GPR(3);
u32 ch = GPR(4);
u32 count = GPR(5);
std::memset((u8*)(Memory::base + dest), ch, count);
NPC = LR;
}
void memcmp()
{
u32 dest = GPR(3);
u32 src = GPR(4);
u32 count = GPR(5);
GPR(3) = std::memcmp((u8*)(Memory::base + dest), (u8*)(Memory::base + src), count);
NPC = LR;
}
void div2i()
{
s64 num = (s64)(GPR(3)) << 32 | GPR(4);
s64 den = (s64)(GPR(5)) << 32 | GPR(6);
s64 quo = num / den;
GPR(3) = quo >> 32;
GPR(4) = quo & 0xffffffff;
NPC = LR;
}
void div2u()
{
u64 num = (u64)(GPR(3)) << 32 | GPR(4);
u64 den = (u64)(GPR(5)) << 32 | GPR(6);
u64 quo = num / den;
GPR(3) = quo >> 32;
GPR(4) = quo & 0xffffffff;
NPC = LR;
}
void OSGetResetCode()
{
u32 resetCode = Memory::Read_U32(0xCC003024);
if (resetCode != 0)
{
GPR(3) = resetCode | 0x80000000;
}
else
{
GPR(3) = 0;
}
NPC = LR;
}
void OSBootDol()
{
IOSv = Memory::Read_U16(0x00003140);
@ -417,8 +488,7 @@ void OSBootDol()
u32 resetCode = GPR(30);
// Reset game
Memory::Write_U32(resetCode << 3, 0xCC003024);
//Memory::Write_U32((resetCode << 3) | 0x80000000, 0x800030f0); // Warm reset
Memory::Write_U32(resetCode, 0xCC003024);
LoadBootDOLFromDisc();
return;
}
@ -429,15 +499,17 @@ void OSBootDol()
}
else if ((GPR(4) >> 28) == 0xC)
{
std::string dol;
// Boot DOL from disc
u32 ptr = GPR(28);
Memory::GetString(dol, ptr);
if (GetDolFileSize() == 0)
if (GetDolFileSize(dol) == 0)
{
ptr = GPR(30);
Memory::GetString(dol, ptr);
if (GetDolFileSize() == 0)
if (GetDolFileSize(dol) == 0)
{
// Cannot locate the dol file, exit.
HLE::UnPatch("__OSBootDol");
@ -448,7 +520,7 @@ void OSBootDol()
argsPtr = Memory::Read_U32(GPR(5));
Memory::GetString(args, argsPtr);
LoadDOLFromDisc();
LoadDOLFromDisc(dol);
return;
}
else

View File

@ -40,6 +40,13 @@ namespace HLE_Misc
void FZ_rsqrt_internal();
void HBReload();
void OSBootDol();
void OSGetResetCode();
void memcpy();
void memset();
void memmove();
void memcmp();
void div2i();
void div2u();
void ExecuteDOL(u8* dolFile, u32 fileSize);
}

View File

@ -416,10 +416,7 @@ bool AreMemoryBreakpointsActivated()
u32 Read_Instruction(const u32 em_address)
{
UGeckoInstruction inst = ReadUnchecked_U32(em_address);
if (inst.OPCD == 1)
return HLE::GetOrigInstruction(em_address);
else
return inst.hex;
return inst.hex;
}
u32 Read_Opcode_JIT_Uncached(const u32 _Address)

View File

@ -96,8 +96,7 @@ void Init()
m_FlipperRev = 0x246500B1; // revision C
m_Unknown = 0;
// Bleh, why?
//m_ResetCode |= 0x80000000;
m_ResetCode = 0x80000000; // Cold reset
m_InterruptCause = INT_CAUSE_RST_BUTTON | INT_CAUSE_VI;
toggleResetButton = CoreTiming::RegisterEvent("ToggleResetButton", &ToggleResetButtonCallback);

View File

@ -26,6 +26,7 @@
#include "PowerPCDisasm.h"
#include "../../IPC_HLE/WII_IPC_HLE.h"
#include "Atomic.h"
#include "HLE/HLE.h"
namespace {
@ -79,57 +80,63 @@ int startTrace = 0;
void Trace( UGeckoInstruction &instCode )
{
char regs[500]="";
char reg[25]="";
std::string regs = "";
for (int i=0; i<32; i++) {
sprintf(regs, "%sr%02d: %08x ", regs, i, PowerPC::ppcState.gpr[i]);
sprintf(reg, "r%02d: %08x ", i, PowerPC::ppcState.gpr[i]);
regs.append(reg);
}
char fregs[500]="";
char freg[25]="";
std::string fregs = "";
for (int i=0; i<32; i++) {
sprintf(fregs, "%sf%02d: %08llx %08llx ", fregs, i,
PowerPC::ppcState.ps[i][0], PowerPC::ppcState.ps[i][1]);
sprintf(freg, "f%02d: %08llx %08llx ", i, PowerPC::ppcState.ps[i][0], PowerPC::ppcState.ps[i][1]);
fregs.append(freg);
}
char ppcInst[256];
DisassembleGekko(instCode.hex, PC, ppcInst, 256);
DEBUG_LOG(POWERPC, "INTER PC: %08x SRR0: %08x SRR1: %08x CRfast: %02x%02x%02x%02x%02x%02x%02x%02x FPSCR: %08x MSR: %08x LR: %08x %s %s %08x %s", PC, SRR0, SRR1, PowerPC::ppcState.cr_fast[0], PowerPC::ppcState.cr_fast[1], PowerPC::ppcState.cr_fast[2], PowerPC::ppcState.cr_fast[3], PowerPC::ppcState.cr_fast[4], PowerPC::ppcState.cr_fast[5], PowerPC::ppcState.cr_fast[6], PowerPC::ppcState.cr_fast[7], PowerPC::ppcState.fpscr, PowerPC::ppcState.msr, PowerPC::ppcState.spr[8], regs, fregs, instCode.hex, ppcInst);
DEBUG_LOG(POWERPC, "INTER PC: %08x SRR0: %08x SRR1: %08x CRfast: %02x%02x%02x%02x%02x%02x%02x%02x FPSCR: %08x MSR: %08x LR: %08x %s %s %08x %s", PC, SRR0, SRR1, PowerPC::ppcState.cr_fast[0], PowerPC::ppcState.cr_fast[1], PowerPC::ppcState.cr_fast[2], PowerPC::ppcState.cr_fast[3], PowerPC::ppcState.cr_fast[4], PowerPC::ppcState.cr_fast[5], PowerPC::ppcState.cr_fast[6], PowerPC::ppcState.cr_fast[7], PowerPC::ppcState.fpscr, PowerPC::ppcState.msr, PowerPC::ppcState.spr[8], regs.c_str(), fregs.c_str(), instCode.hex, ppcInst);
}
int Interpreter::SingleStepInner(void)
{
static UGeckoInstruction instCode;
NPC = PC + sizeof(UGeckoInstruction);
instCode.hex = Memory::Read_Opcode(PC);
// Uncomment to trace the interpreter
//if ((PC & 0xffffff)>=0x0ab54c && (PC & 0xffffff)<=0x0ab624)
// startTrace = 1;
//else
// startTrace = 0;
if (startTrace)
u32 function = m_EndBlock ? HLE::GetFunctionIndex(PC) : 0; // Check for HLE functions after branches
if (function != 0)
{
Trace(instCode);
}
if (instCode.hex != 0)
{
UReg_MSR& msr = (UReg_MSR&)MSR;
if (msr.FP) //If FPU is enabled, just execute
int type = HLE::GetFunctionTypeByIndex(function);
if (type == HLE::HLE_HOOK_START || type == HLE::HLE_HOOK_REPLACE)
{
m_opTable[instCode.OPCD](instCode);
if (PowerPC::ppcState.Exceptions & EXCEPTION_DSI)
int flags = HLE::GetFunctionFlagsByIndex(function);
if (HLE::IsEnabled(flags))
{
PowerPC::CheckExceptions();
m_EndBlock = true;
HLEFunction(function);
}
}
else
}
else
{
NPC = PC + sizeof(UGeckoInstruction);
instCode.hex = Memory::Read_Opcode(PC);
// Uncomment to trace the interpreter
//if ((PC & 0xffffff)>=0x0ab54c && (PC & 0xffffff)<=0x0ab624)
// startTrace = 1;
//else
// startTrace = 0;
if (startTrace)
{
// check if we have to generate a FPU unavailable exception
if (!PPCTables::UsesFPU(instCode))
Trace(instCode);
}
if (instCode.hex != 0)
{
UReg_MSR& msr = (UReg_MSR&)MSR;
if (msr.FP) //If FPU is enabled, just execute
{
m_opTable[instCode.OPCD](instCode);
if (PowerPC::ppcState.Exceptions & EXCEPTION_DSI)
@ -140,17 +147,30 @@ int Interpreter::SingleStepInner(void)
}
else
{
Common::AtomicOr(PowerPC::ppcState.Exceptions, EXCEPTION_FPU_UNAVAILABLE);
PowerPC::CheckExceptions();
m_EndBlock = true;
// check if we have to generate a FPU unavailable exception
if (!PPCTables::UsesFPU(instCode))
{
m_opTable[instCode.OPCD](instCode);
if (PowerPC::ppcState.Exceptions & EXCEPTION_DSI)
{
PowerPC::CheckExceptions();
m_EndBlock = true;
}
}
else
{
Common::AtomicOr(PowerPC::ppcState.Exceptions, EXCEPTION_FPU_UNAVAILABLE);
PowerPC::CheckExceptions();
m_EndBlock = true;
}
}
}
}
else
{
// Memory exception on instruction fetch
PowerPC::CheckExceptions();
m_EndBlock = true;
else
{
// Memory exception on instruction fetch
PowerPC::CheckExceptions();
m_EndBlock = true;
}
}
last_pc = PC;
PC = NPC;

View File

@ -252,8 +252,6 @@ void Jit64::HLEFunction(UGeckoInstruction _inst)
gpr.Flush(FLUSH_ALL);
fpr.Flush(FLUSH_ALL);
ABI_CallFunctionCC((void*)&HLE::Execute, js.compilerPC, _inst.hex);
MOV(32, R(EAX), M(&NPC));
WriteExitDestInEAX();
}
void Jit64::DoNothing(UGeckoInstruction _inst)
@ -566,6 +564,27 @@ const u8* Jit64::DoJit(u32 em_address, PPCAnalyst::CodeBuffer *code_buf, JitBloc
ABI_CallFunction(thunks.ProtectFunction((void *)&GPFifo::CheckGatherPipe, 0));
}
u32 function = HLE::GetFunctionIndex(ops[i].address);
if (function != 0)
{
int type = HLE::GetFunctionTypeByIndex(function);
if (type == HLE::HLE_HOOK_START || type == HLE::HLE_HOOK_REPLACE)
{
int flags = HLE::GetFunctionFlagsByIndex(function);
if (HLE::IsEnabled(flags))
{
HLEFunction(function);
if (type == HLE::HLE_HOOK_REPLACE)
{
MOV(32, R(EAX), M(&NPC));
js.downcountAmount += js.st.numCycles;
WriteExitDestInEAX();
break;
}
}
}
}
if (!ops[i].skip)
{
if ((opinfo->flags & FL_USE_FPU) && !js.firstFPInstructionFound)
@ -668,6 +687,20 @@ const u8* Jit64::DoJit(u32 em_address, PPCAnalyst::CodeBuffer *code_buf, JitBloc
break;
}
u32 function = HLE::GetFunctionIndex(js.blockStart);
if (function != 0)
{
int type = HLE::GetFunctionTypeByIndex(function);
if (type == HLE::HLE_HOOK_END)
{
int flags = HLE::GetFunctionFlagsByIndex(function);
if (HLE::IsEnabled(flags))
{
HLEFunction(function);
}
}
}
if (memory_exception)
{
// Address of instruction could not be translated

View File

@ -199,7 +199,7 @@ namespace JitILProfiler
static u64 beginTime;
static Block& Add(u64 codeHash)
{
const u32 _blockIndex = blocks.size();
const u32 _blockIndex = (u32)blocks.size();
blocks.push_back(Block());
Block& block = blocks.back();
block.index = _blockIndex;
@ -649,6 +649,27 @@ const u8* JitIL::DoJit(u32 em_address, PPCAnalyst::CodeBuffer *code_buf, JitBloc
js.next_compilerPC = ops[i + 1].address;
}
u32 function = HLE::GetFunctionIndex(ops[i].address);
if (function != 0)
{
int type = HLE::GetFunctionTypeByIndex(function);
if (type == HLE::HLE_HOOK_START || type == HLE::HLE_HOOK_REPLACE)
{
int flags = HLE::GetFunctionFlagsByIndex(function);
if (HLE::IsEnabled(flags))
{
HLEFunction(function);
if (type == HLE::HLE_HOOK_REPLACE)
{
MOV(32, R(EAX), M(&NPC));
jit->js.downcountAmount += jit->js.st.numCycles;
WriteExitDestInOpArg(R(EAX));
break;
}
}
}
}
if (!ops[i].skip)
{
if (js.memcheck && (opinfo->flags & FL_USE_FPU))
@ -665,7 +686,7 @@ const u8* JitIL::DoJit(u32 em_address, PPCAnalyst::CodeBuffer *code_buf, JitBloc
{
ibuild.EmitBreakPointCheck(ibuild.EmitIntConst(ops[i].address));
}
JitILTables::CompileInstruction(ops[i]);
if (js.memcheck && (opinfo->flags & FL_LOADSTORE))
@ -681,6 +702,20 @@ const u8* JitIL::DoJit(u32 em_address, PPCAnalyst::CodeBuffer *code_buf, JitBloc
}
}
u32 function = HLE::GetFunctionIndex(jit->js.blockStart);
if (function != 0)
{
int type = HLE::GetFunctionTypeByIndex(function);
if (type == HLE::HLE_HOOK_END)
{
int flags = HLE::GetFunctionFlagsByIndex(function);
if (HLE::IsEnabled(flags))
{
HLEFunction(function);
}
}
}
if (memory_exception)
{
ibuild.EmitISIException(ibuild.EmitIntConst(em_address));

View File

@ -135,7 +135,11 @@ bool JitBlock::ContainsAddress(u32 em_address)
// is full and when saving and loading states.
void JitBlockCache::Clear()
{
Core::DisplayMessage("Clearing code cache.", 3000);
if (IsFull())
Core::DisplayMessage("Clearing block cache.", 3000);
else
Core::DisplayMessage("Clearing code cache.", 3000);
for (int i = 0; i < num_blocks; i++)
{
DestroyBlock(i, false);

View File

@ -269,23 +269,18 @@ void EmuCodeBlock::SafeWriteRegToReg(X64Reg reg_value, X64Reg reg_addr, int acce
void EmuCodeBlock::SafeWriteFloatToReg(X64Reg xmm_value, X64Reg reg_addr)
{
u32 mem_mask = Memory::ADDR_MASK_HW_ACCESS;
if (Core::g_CoreStartupParameter.bMMU || Core::g_CoreStartupParameter.iTLBHack)
{
mem_mask |= Memory::ADDR_MASK_MEM1;
}
#ifdef ENABLE_MEM_CHECK
if (Core::g_CoreStartupParameter.bEnableDebugging)
{
mem_mask |= Memory::EXRAM_MASK;
}
#endif
TEST(32, R(reg_addr), Imm32(mem_mask));
if (false && cpu_info.bSSSE3) {
// This path should be faster but for some reason it causes errors so I've disabled it.
u32 mem_mask = Memory::ADDR_MASK_HW_ACCESS;
if (Core::g_CoreStartupParameter.bMMU || Core::g_CoreStartupParameter.iTLBHack)
mem_mask |= Memory::ADDR_MASK_MEM1;
#ifdef ENABLE_MEM_CHECK
if (Core::g_CoreStartupParameter.bEnableDebugging)
mem_mask |= Memory::EXRAM_MASK;
#endif
TEST(32, R(reg_addr), Imm32(mem_mask));
FixupBranch argh = J_CC(CC_Z);
MOVSS(M(&float_buffer), xmm_value);
MOV(32, R(EAX), M(&float_buffer));