mirror of
https://github.com/cemu-project/Cemu.git
synced 2025-07-06 06:51:18 +12:00
PPCRec: Added dump option for recompiled functions + more fixes
This commit is contained in:
parent
b55785a0a0
commit
25794f70fa
6 changed files with 72 additions and 53 deletions
|
@ -265,7 +265,7 @@ sint32 IMLRA_CountDistanceUntilFixedRegUsage(IMLSegment* imlSegment, raInstructi
|
||||||
{
|
{
|
||||||
if(fixedRegLoc.reg.IsInvalid() || fixedRegLoc.reg.GetRegID() != ourRegId)
|
if(fixedRegLoc.reg.IsInvalid() || fixedRegLoc.reg.GetRegID() != ourRegId)
|
||||||
{
|
{
|
||||||
cemu_assert_debug(fixedRegLoc.physRegSet.HasExactlyOneAvailable()); // this whole function only makes sense when there is only one fixed register, otherwise there are extra permutations to consider
|
cemu_assert_debug(fixedRegLoc.reg.IsInvalid() || fixedRegLoc.physRegSet.HasExactlyOneAvailable()); // this whole function only makes sense when there is only one fixed register, otherwise there are extra permutations to consider. Except for IMLREG_INVALID which is used to indicate reserved registers
|
||||||
if(fixedRegLoc.physRegSet.IsAvailable(physRegister))
|
if(fixedRegLoc.physRegSet.IsAvailable(physRegister))
|
||||||
return currentPos.GetRaw() - startPosition.GetRaw();
|
return currentPos.GetRaw() - startPosition.GetRaw();
|
||||||
}
|
}
|
||||||
|
@ -572,30 +572,35 @@ void IMLRA_HandleFixedRegisters(ppcImlGenContext_t* ppcImlGenContext, IMLSegment
|
||||||
for(size_t i=0; i<frr.size(); i++)
|
for(size_t i=0; i<frr.size(); i++)
|
||||||
{
|
{
|
||||||
raFixedRegRequirementWithVGPR& entry = frr[i];
|
raFixedRegRequirementWithVGPR& entry = frr[i];
|
||||||
cemu_assert_debug(entry.allowedReg.HasExactlyOneAvailable()); // we currently only handle fixed register requirements with a single register
|
// we currently only handle fixed register requirements with a single register
|
||||||
IMLPhysReg physReg = entry.allowedReg.GetFirstAvailableReg();
|
// with one exception: When regId is IMLRegID_INVALID then the entry acts as a list of reserved registers
|
||||||
// check if the assigned vGPR has changed
|
cemu_assert_debug(entry.regId == IMLRegID_INVALID || entry.allowedReg.HasExactlyOneAvailable());
|
||||||
bool vgprHasChanged = false;
|
for(IMLPhysReg physReg = entry.allowedReg.GetFirstAvailableReg(); physReg >= 0; physReg = entry.allowedReg.GetNextAvailableReg(physReg+1))
|
||||||
auto it = lastVGPR.find(physReg);
|
|
||||||
if(it != lastVGPR.end())
|
|
||||||
vgprHasChanged = it->second != entry.regId;
|
|
||||||
else
|
|
||||||
vgprHasChanged = true;
|
|
||||||
lastVGPR[physReg] = entry.regId;
|
|
||||||
|
|
||||||
if(!vgprHasChanged)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
boost::container::small_vector<raLivenessRange*, 8> overlappingRanges = IMLRA_GetRangeWithFixedRegReservationOverlappingPos(imlSegment, entry.pos, physReg);
|
|
||||||
if(entry.regId != IMLRegID_INVALID)
|
|
||||||
cemu_assert_debug(!overlappingRanges.empty()); // there should always be at least one range that overlaps corresponding to the fixed register requirement, except for IMLRegID_INVALID which is used to indicate reserved registers
|
|
||||||
|
|
||||||
for(auto& range : overlappingRanges)
|
|
||||||
{
|
{
|
||||||
if(range->interval2.start < entry.pos)
|
// check if the assigned vGPR has changed
|
||||||
|
bool vgprHasChanged = false;
|
||||||
|
auto it = lastVGPR.find(physReg);
|
||||||
|
if(it != lastVGPR.end())
|
||||||
|
vgprHasChanged = it->second != entry.regId;
|
||||||
|
else
|
||||||
|
vgprHasChanged = true;
|
||||||
|
lastVGPR[physReg] = entry.regId;
|
||||||
|
|
||||||
|
if(!vgprHasChanged)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
boost::container::small_vector<raLivenessRange*, 8> overlappingRanges = IMLRA_GetRangeWithFixedRegReservationOverlappingPos(imlSegment, entry.pos, physReg);
|
||||||
|
if(entry.regId != IMLRegID_INVALID)
|
||||||
|
cemu_assert_debug(!overlappingRanges.empty()); // there should always be at least one range that overlaps corresponding to the fixed register requirement, except for IMLRegID_INVALID which is used to indicate reserved registers
|
||||||
|
|
||||||
|
for(auto& range : overlappingRanges)
|
||||||
{
|
{
|
||||||
PPCRecRA_splitLocalSubrange2(ppcImlGenContext, range, entry.pos, true);
|
if(range->interval2.start < entry.pos)
|
||||||
|
{
|
||||||
|
PPCRecRA_splitLocalSubrange2(ppcImlGenContext, range, entry.pos, true);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// finally iterate ranges and assign fixed registers
|
// finally iterate ranges and assign fixed registers
|
||||||
|
|
|
@ -396,13 +396,14 @@ PPCRecFunction_t* PPCRecompiler_recompileFunction(PPCFunctionBoundaryTracker::PP
|
||||||
{
|
{
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
if (ActiveSettings::DumpRecompilerFunctionsEnabled())
|
||||||
if (ppcRecFunc->ppcAddress == 0x2B7A8D4)
|
|
||||||
{
|
{
|
||||||
// write code to binary file
|
FileStream* fs = FileStream::createFile2(ActiveSettings::GetUserDataPath(fmt::format("dump/recompiler/ppc_{:08x}.bin", ppcRecFunc->ppcAddress)));
|
||||||
FILE* f = fopen("ppcRecFunc_2B7A8D4.bin", "wb");
|
if (fs)
|
||||||
fwrite(ppcRecFunc->x86Code, 1, ppcRecFunc->x86Size, f);
|
{
|
||||||
fclose(f);
|
fs->writeData(ppcRecFunc->x86Code, ppcRecFunc->x86Size);
|
||||||
|
delete fs;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// collect list of PPC-->x64 entry points
|
// collect list of PPC-->x64 entry points
|
||||||
|
|
|
@ -165,6 +165,11 @@ bool ActiveSettings::DumpTexturesEnabled()
|
||||||
return s_dump_textures;
|
return s_dump_textures;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool ActiveSettings::DumpRecompilerFunctionsEnabled()
|
||||||
|
{
|
||||||
|
return s_dump_recompiler_functions;
|
||||||
|
}
|
||||||
|
|
||||||
bool ActiveSettings::DumpLibcurlRequestsEnabled()
|
bool ActiveSettings::DumpLibcurlRequestsEnabled()
|
||||||
{
|
{
|
||||||
return s_dump_libcurl_requests;
|
return s_dump_libcurl_requests;
|
||||||
|
@ -180,6 +185,11 @@ void ActiveSettings::EnableDumpTextures(bool state)
|
||||||
s_dump_textures = state;
|
s_dump_textures = state;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ActiveSettings::EnableDumpRecompilerFunctions(bool state)
|
||||||
|
{
|
||||||
|
s_dump_recompiler_functions = state;
|
||||||
|
}
|
||||||
|
|
||||||
void ActiveSettings::EnableDumpLibcurlRequests(bool state)
|
void ActiveSettings::EnableDumpLibcurlRequests(bool state)
|
||||||
{
|
{
|
||||||
s_dump_libcurl_requests = state;
|
s_dump_libcurl_requests = state;
|
||||||
|
|
|
@ -109,9 +109,11 @@ public:
|
||||||
// dump options
|
// dump options
|
||||||
[[nodiscard]] static bool DumpShadersEnabled();
|
[[nodiscard]] static bool DumpShadersEnabled();
|
||||||
[[nodiscard]] static bool DumpTexturesEnabled();
|
[[nodiscard]] static bool DumpTexturesEnabled();
|
||||||
|
[[nodiscard]] static bool DumpRecompilerFunctionsEnabled();
|
||||||
[[nodiscard]] static bool DumpLibcurlRequestsEnabled();
|
[[nodiscard]] static bool DumpLibcurlRequestsEnabled();
|
||||||
static void EnableDumpShaders(bool state);
|
static void EnableDumpShaders(bool state);
|
||||||
static void EnableDumpTextures(bool state);
|
static void EnableDumpTextures(bool state);
|
||||||
|
static void EnableDumpRecompilerFunctions(bool state);
|
||||||
static void EnableDumpLibcurlRequests(bool state);
|
static void EnableDumpLibcurlRequests(bool state);
|
||||||
|
|
||||||
// hacks
|
// hacks
|
||||||
|
@ -125,6 +127,7 @@ private:
|
||||||
// dump options
|
// dump options
|
||||||
inline static bool s_dump_shaders = false;
|
inline static bool s_dump_shaders = false;
|
||||||
inline static bool s_dump_textures = false;
|
inline static bool s_dump_textures = false;
|
||||||
|
inline static bool s_dump_recompiler_functions = false;
|
||||||
inline static bool s_dump_libcurl_requests = false;
|
inline static bool s_dump_libcurl_requests = false;
|
||||||
|
|
||||||
// timer speed
|
// timer speed
|
||||||
|
|
|
@ -144,6 +144,7 @@ enum
|
||||||
// debug->dump
|
// debug->dump
|
||||||
MAINFRAME_MENU_ID_DEBUG_DUMP_TEXTURES = 21600,
|
MAINFRAME_MENU_ID_DEBUG_DUMP_TEXTURES = 21600,
|
||||||
MAINFRAME_MENU_ID_DEBUG_DUMP_SHADERS,
|
MAINFRAME_MENU_ID_DEBUG_DUMP_SHADERS,
|
||||||
|
MAINFRAME_MENU_ID_DEBUG_DUMP_RECOMPILER_FUNCTIONS,
|
||||||
MAINFRAME_MENU_ID_DEBUG_DUMP_RAM,
|
MAINFRAME_MENU_ID_DEBUG_DUMP_RAM,
|
||||||
MAINFRAME_MENU_ID_DEBUG_DUMP_FST,
|
MAINFRAME_MENU_ID_DEBUG_DUMP_FST,
|
||||||
MAINFRAME_MENU_ID_DEBUG_DUMP_CURL_REQUESTS,
|
MAINFRAME_MENU_ID_DEBUG_DUMP_CURL_REQUESTS,
|
||||||
|
@ -206,8 +207,9 @@ EVT_MENU_RANGE(MAINFRAME_MENU_ID_NFC_RECENT_0 + 0, MAINFRAME_MENU_ID_NFC_RECENT_
|
||||||
EVT_MENU_RANGE(MAINFRAME_MENU_ID_DEBUG_LOGGING0 + 0, MAINFRAME_MENU_ID_DEBUG_LOGGING0 + 98, MainWindow::OnDebugLoggingToggleFlagGeneric)
|
EVT_MENU_RANGE(MAINFRAME_MENU_ID_DEBUG_LOGGING0 + 0, MAINFRAME_MENU_ID_DEBUG_LOGGING0 + 98, MainWindow::OnDebugLoggingToggleFlagGeneric)
|
||||||
EVT_MENU(MAINFRAME_MENU_ID_DEBUG_ADVANCED_PPC_INFO, MainWindow::OnPPCInfoToggle)
|
EVT_MENU(MAINFRAME_MENU_ID_DEBUG_ADVANCED_PPC_INFO, MainWindow::OnPPCInfoToggle)
|
||||||
// debug -> dump menu
|
// debug -> dump menu
|
||||||
EVT_MENU(MAINFRAME_MENU_ID_DEBUG_DUMP_TEXTURES, MainWindow::OnDebugDumpUsedTextures)
|
EVT_MENU(MAINFRAME_MENU_ID_DEBUG_DUMP_TEXTURES, MainWindow::OnDebugDumpGeneric)
|
||||||
EVT_MENU(MAINFRAME_MENU_ID_DEBUG_DUMP_SHADERS, MainWindow::OnDebugDumpUsedShaders)
|
EVT_MENU(MAINFRAME_MENU_ID_DEBUG_DUMP_SHADERS, MainWindow::OnDebugDumpGeneric)
|
||||||
|
EVT_MENU(MAINFRAME_MENU_ID_DEBUG_DUMP_RECOMPILER_FUNCTIONS, MainWindow::OnDebugDumpGeneric)
|
||||||
EVT_MENU(MAINFRAME_MENU_ID_DEBUG_DUMP_CURL_REQUESTS, MainWindow::OnDebugSetting)
|
EVT_MENU(MAINFRAME_MENU_ID_DEBUG_DUMP_CURL_REQUESTS, MainWindow::OnDebugSetting)
|
||||||
// debug -> Other options
|
// debug -> Other options
|
||||||
EVT_MENU(MAINFRAME_MENU_ID_DEBUG_RENDER_UPSIDE_DOWN, MainWindow::OnDebugSetting)
|
EVT_MENU(MAINFRAME_MENU_ID_DEBUG_RENDER_UPSIDE_DOWN, MainWindow::OnDebugSetting)
|
||||||
|
@ -1091,31 +1093,29 @@ void MainWindow::OnPPCInfoToggle(wxCommandEvent& event)
|
||||||
g_config.Save();
|
g_config.Save();
|
||||||
}
|
}
|
||||||
|
|
||||||
void MainWindow::OnDebugDumpUsedTextures(wxCommandEvent& event)
|
void MainWindow::OnDebugDumpGeneric(wxCommandEvent& event)
|
||||||
{
|
{
|
||||||
const bool value = event.IsChecked();
|
std::string dumpSubpath;
|
||||||
ActiveSettings::EnableDumpTextures(value);
|
std::function<void(bool)> setDumpState;
|
||||||
if (value)
|
switch(event.GetId())
|
||||||
{
|
{
|
||||||
try
|
case MAINFRAME_MENU_ID_DEBUG_DUMP_TEXTURES:
|
||||||
{
|
dumpSubpath = "dump/textures";
|
||||||
// create directory
|
setDumpState = ActiveSettings::EnableDumpTextures;
|
||||||
const fs::path path(ActiveSettings::GetUserDataPath());
|
break;
|
||||||
fs::create_directories(path / "dump" / "textures");
|
case MAINFRAME_MENU_ID_DEBUG_DUMP_SHADERS:
|
||||||
}
|
dumpSubpath = "dump/shaders";
|
||||||
catch (const std::exception& ex)
|
setDumpState = ActiveSettings::EnableDumpShaders;
|
||||||
{
|
break;
|
||||||
SystemException sys(ex);
|
case MAINFRAME_MENU_ID_DEBUG_DUMP_RECOMPILER_FUNCTIONS:
|
||||||
cemuLog_log(LogType::Force, "can't create texture dump folder: {}", ex.what());
|
dumpSubpath = "dump/recompiler";
|
||||||
ActiveSettings::EnableDumpTextures(false);
|
setDumpState = ActiveSettings::EnableDumpRecompilerFunctions;
|
||||||
}
|
break;
|
||||||
|
default:
|
||||||
|
UNREACHABLE;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
void MainWindow::OnDebugDumpUsedShaders(wxCommandEvent& event)
|
|
||||||
{
|
|
||||||
const bool value = event.IsChecked();
|
const bool value = event.IsChecked();
|
||||||
ActiveSettings::EnableDumpShaders(value);
|
setDumpState(value);
|
||||||
if (value)
|
if (value)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
|
@ -2239,6 +2239,7 @@ void MainWindow::RecreateMenu()
|
||||||
wxMenu* debugDumpMenu = new wxMenu;
|
wxMenu* debugDumpMenu = new wxMenu;
|
||||||
debugDumpMenu->AppendCheckItem(MAINFRAME_MENU_ID_DEBUG_DUMP_TEXTURES, _("&Textures"), wxEmptyString)->Check(ActiveSettings::DumpTexturesEnabled());
|
debugDumpMenu->AppendCheckItem(MAINFRAME_MENU_ID_DEBUG_DUMP_TEXTURES, _("&Textures"), wxEmptyString)->Check(ActiveSettings::DumpTexturesEnabled());
|
||||||
debugDumpMenu->AppendCheckItem(MAINFRAME_MENU_ID_DEBUG_DUMP_SHADERS, _("&Shaders"), wxEmptyString)->Check(ActiveSettings::DumpShadersEnabled());
|
debugDumpMenu->AppendCheckItem(MAINFRAME_MENU_ID_DEBUG_DUMP_SHADERS, _("&Shaders"), wxEmptyString)->Check(ActiveSettings::DumpShadersEnabled());
|
||||||
|
debugDumpMenu->AppendCheckItem(MAINFRAME_MENU_ID_DEBUG_DUMP_RECOMPILER_FUNCTIONS, _("&Recompiler functions"), wxEmptyString)->Check(ActiveSettings::DumpRecompilerFunctionsEnabled());
|
||||||
debugDumpMenu->AppendCheckItem(MAINFRAME_MENU_ID_DEBUG_DUMP_CURL_REQUESTS, _("&nlibcurl HTTP/HTTPS requests"), wxEmptyString);
|
debugDumpMenu->AppendCheckItem(MAINFRAME_MENU_ID_DEBUG_DUMP_CURL_REQUESTS, _("&nlibcurl HTTP/HTTPS requests"), wxEmptyString);
|
||||||
// debug submenu
|
// debug submenu
|
||||||
wxMenu* debugMenu = new wxMenu();
|
wxMenu* debugMenu = new wxMenu();
|
||||||
|
|
|
@ -107,8 +107,7 @@ public:
|
||||||
void OnDebugSetting(wxCommandEvent& event);
|
void OnDebugSetting(wxCommandEvent& event);
|
||||||
void OnDebugLoggingToggleFlagGeneric(wxCommandEvent& event);
|
void OnDebugLoggingToggleFlagGeneric(wxCommandEvent& event);
|
||||||
void OnPPCInfoToggle(wxCommandEvent& event);
|
void OnPPCInfoToggle(wxCommandEvent& event);
|
||||||
void OnDebugDumpUsedTextures(wxCommandEvent& event);
|
void OnDebugDumpGeneric(wxCommandEvent& event);
|
||||||
void OnDebugDumpUsedShaders(wxCommandEvent& event);
|
|
||||||
void OnLoggingWindow(wxCommandEvent& event);
|
void OnLoggingWindow(wxCommandEvent& event);
|
||||||
void OnGDBStubToggle(wxCommandEvent& event);
|
void OnGDBStubToggle(wxCommandEvent& event);
|
||||||
void OnDebugViewPPCThreads(wxCommandEvent& event);
|
void OnDebugViewPPCThreads(wxCommandEvent& event);
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue