From ce8aae5ed1eca2e2e10f0ffaaa2303b8e83a6d34 Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Sun, 8 May 2016 01:43:27 +0200 Subject: [PATCH] Make the IRJit core selectable in developer tools --- Core/Config.cpp | 28 +++++++++++++++++++--------- Core/Config.h | 7 ++++++- Core/CoreParameter.h | 8 ++------ Core/MIPS/IR/IRCompBranch.cpp | 2 +- Core/MIPS/IR/IRInst.cpp | 4 ++++ Core/MIPS/IR/IRInst.h | 2 +- Core/MIPS/IR/IRJit.cpp | 6 ++++++ Core/MIPS/JitCommon/JitCommon.cpp | 4 ---- Core/MIPS/MIPS.cpp | 27 ++++++++++++++++++++------- Core/MemMapFunctions.cpp | 4 ++-- UI/EmuScreen.cpp | 4 ++-- UI/GameSettingsScreen.cpp | 7 +++++-- UI/MiscScreens.cpp | 2 +- UI/NativeApp.cpp | 8 ++++++-- android/jni/TestRunner.cpp | 2 +- headless/Headless.cpp | 10 ++++++---- unittest/JitHarness.cpp | 4 ++-- 17 files changed, 84 insertions(+), 45 deletions(-) diff --git a/Core/Config.cpp b/Core/Config.cpp index 6faa97a075..137194c475 100644 --- a/Core/Config.cpp +++ b/Core/Config.cpp @@ -282,9 +282,20 @@ static int DefaultNumWorkers() { return cpu_info.num_cores; } -static bool DefaultJit() { +// TODO: Default to IRJit on iOS when it's done. +static int DefaultCpuCore() { #ifdef IOS - return iosCanUseJit; + return iosCanUseJit ? CPU_CORE_JIT : CPU_CORE_INTERPRETER; +#elif defined(ARM) || defined(ARM64) || defined(_M_IX86) || defined(_M_X64) + return CPU_CORE_JIT; +#else + return CPU_CORE_INTERPRETER; +#endif +} + +static bool DefaultCodeGen() { +#ifdef IOS + return iosCanUseJit ? true : false; #elif defined(ARM) || defined(ARM64) || defined(_M_IX86) || defined(_M_X64) return true; #else @@ -353,8 +364,7 @@ static bool DefaultSasThread() { } static ConfigSetting cpuSettings[] = { - ReportedConfigSetting("Jit", &g_Config.bJit, &DefaultJit, true, true), - ReportedConfigSetting("CPUCore", &g_Config.bJit, &DefaultJit, true, true), + ReportedConfigSetting("CPUCore", &g_Config.iCpuCore, &DefaultCpuCore, true, true), ReportedConfigSetting("SeparateCPUThread", &g_Config.bSeparateCPUThread, false, true, true), ReportedConfigSetting("SeparateSASThread", &g_Config.bSeparateSASThread, &DefaultSasThread, true, true), ReportedConfigSetting("SeparateIOThread", &g_Config.bSeparateIOThread, true, true, true), @@ -464,7 +474,7 @@ static ConfigSetting graphicsSettings[] = { ReportedConfigSetting("VertexCache", &g_Config.bVertexCache, true, true, true), ReportedConfigSetting("TextureBackoffCache", &g_Config.bTextureBackoffCache, false, true, true), ReportedConfigSetting("TextureSecondaryCache", &g_Config.bTextureSecondaryCache, false, true, true), - ReportedConfigSetting("VertexDecJit", &g_Config.bVertexDecoderJit, &DefaultJit, false), + ReportedConfigSetting("VertexDecJit", &g_Config.bVertexDecoderJit, &DefaultCodeGen, false), #ifndef MOBILE_DEVICE ConfigSetting("FullScreen", &g_Config.bFullScreen, false), @@ -959,16 +969,16 @@ void Config::Load(const char *iniFileName, const char *controllerIniFilename) { } // Override ppsspp.ini JIT value to prevent crashing - if (!DefaultJit() && g_Config.bJit) { + if (DefaultCpuCore() != CPU_CORE_JIT && g_Config.iCpuCore == CPU_CORE_JIT) { jitForcedOff = true; - g_Config.bJit = false; + g_Config.iCpuCore = CPU_CORE_INTERPRETER; } } void Config::Save() { if (jitForcedOff) { // if JIT has been forced off, we don't want to screw up the user's ppsspp.ini - g_Config.bJit = true; + g_Config.iCpuCore = CPU_CORE_JIT; } if (iniFilename_.size() && g_Config.bSaveSettings) { @@ -1037,7 +1047,7 @@ void Config::Save() { } if (jitForcedOff) { // force JIT off again just in case Config::Save() is called without exiting PPSSPP - g_Config.bJit = false; + g_Config.iCpuCore = CPU_CORE_INTERPRETER; } } diff --git a/Core/Config.h b/Core/Config.h index 825091bd0c..6a2016997b 100644 --- a/Core/Config.h +++ b/Core/Config.h @@ -33,6 +33,12 @@ const int PSP_DEFAULT_FIRMWARE = 150; static const s8 VOLUME_OFF = 0; static const s8 VOLUME_MAX = 10; +enum CPUCore { + CPU_CORE_INTERPRETER = 0, + CPU_CORE_JIT = 1, + CPU_CORE_IRJIT = 2, +}; + enum { ROTATION_AUTO = 0, ROTATION_LOCKED_HORIZONTAL = 1, @@ -119,7 +125,6 @@ public: // Core bool bIgnoreBadMemAccess; bool bFastMemory; - bool bJit; int iCpuCore; bool bCheckForNewVersion; bool bForceLagSync; diff --git a/Core/CoreParameter.h b/Core/CoreParameter.h index 1517b50c03..c9351443c7 100644 --- a/Core/CoreParameter.h +++ b/Core/CoreParameter.h @@ -20,12 +20,7 @@ #include #include "Core/Compatibility.h" - -enum CPUCore { - CPU_INTERPRETER, - CPU_JIT, - CPU_IRJIT, -}; +#include "Core/Config.h" enum GPUCore { GPUCORE_NULL, @@ -47,6 +42,7 @@ struct CoreParameter { CPUCore cpuCore; GPUCore gpuCore; + GraphicsContext *graphicsContext; // TODO: Find a better place. Thin3DContext *thin3d; bool enableSound; // there aren't multiple sound cores. diff --git a/Core/MIPS/IR/IRCompBranch.cpp b/Core/MIPS/IR/IRCompBranch.cpp index 9d69b282c2..2b478f695a 100644 --- a/Core/MIPS/IR/IRCompBranch.cpp +++ b/Core/MIPS/IR/IRCompBranch.cpp @@ -219,7 +219,7 @@ void IRJit::BranchVFPUFlag(MIPSOpcode op, IRComparison cc, bool likely) { MIPSOpcode delaySlotOp = GetOffsetInstruction(1); - ir.Write(IROp::VfpCondToReg, IRTEMP_0); + ir.Write(IROp::VfpuCtrlToReg, IRTEMP_0, VFPU_CTRL_CC); ir.Write(IROp::Downcount, 0, js.downcountAmount & 0xFF, js.downcountAmount >> 8); diff --git a/Core/MIPS/IR/IRInst.cpp b/Core/MIPS/IR/IRInst.cpp index b4eb14d98f..cba03ae795 100644 --- a/Core/MIPS/IR/IRInst.cpp +++ b/Core/MIPS/IR/IRInst.cpp @@ -81,6 +81,7 @@ static const IRMeta irMeta[] = { { IROp::FMovFromGPR, "FMovFromGPR", "FG" }, { IROp::FMovToGPR, "FMovToGPR", "GF" }, { IROp::FpCondToReg, "FpCondToReg", "G" }, + { IROp::VfpuCtrlToReg, "VfpuCtrlToReg", "GI" }, { IROp::SetCtrlVFPU, "SetCtrlVFPU", "TC" }, { IROp::Interpret, "Interpret", "_C" }, { IROp::Downcount, "Downcount", "_II" }, @@ -329,6 +330,9 @@ u32 IRInterpret(MIPSState *mips, const IRInst *inst, const u32 *constPool, int c case IROp::FpCondToReg: mips->r[inst->dest] = mips->fpcond; break; + case IROp::VfpuCtrlToReg: + mips->r[inst->dest] = mips->vfpuCtrl[inst->src1]; + break; case IROp::FRound: mips->r[inst->dest] = (int)floorf(mips->f[inst->src1] + 0.5f); break; diff --git a/Core/MIPS/IR/IRInst.h b/Core/MIPS/IR/IRInst.h index 2c6ab75cd7..e044825f1c 100644 --- a/Core/MIPS/IR/IRInst.h +++ b/Core/MIPS/IR/IRInst.h @@ -119,7 +119,7 @@ enum class IROp : u8 { FMovToGPR, FpCondToReg, - VfpCondToReg, + VfpuCtrlToReg, ZeroFpCond, FCmpUnordered, diff --git a/Core/MIPS/IR/IRJit.cpp b/Core/MIPS/IR/IRJit.cpp index d393bf78ca..0d8fca504b 100644 --- a/Core/MIPS/IR/IRJit.cpp +++ b/Core/MIPS/IR/IRJit.cpp @@ -255,6 +255,12 @@ void IRJit::DoJit(u32 em_address, IRBlock *b) { MIPSCompileOp(inst, this); js.compilerPC += 4; js.numInstructions++; + + if (ir.GetConstants().size() > 128) { + // Need to break the block + ir.Write(IROp::ExitToConst, ir.AddConstant(js.compilerPC)); + js.compiling = false; + } } ir.Simplify(); diff --git a/Core/MIPS/JitCommon/JitCommon.cpp b/Core/MIPS/JitCommon/JitCommon.cpp index 630494f973..e267b9352e 100644 --- a/Core/MIPS/JitCommon/JitCommon.cpp +++ b/Core/MIPS/JitCommon/JitCommon.cpp @@ -47,9 +47,6 @@ namespace MIPSComp { } JitInterface *CreateNativeJit(MIPSState *mips) { -#if 1 - return new MIPSComp::IRJit(mips); -#else #if defined(ARM) return new MIPSComp::ArmJit(mips); #elif defined(ARM64) @@ -60,7 +57,6 @@ namespace MIPSComp { return new MIPSComp::MipsJit(mips); #else return new MIPSComp::FakeJit(mips); -#endif #endif } diff --git a/Core/MIPS/MIPS.cpp b/Core/MIPS/MIPS.cpp index 1140b67914..0482f21211 100644 --- a/Core/MIPS/MIPS.cpp +++ b/Core/MIPS/MIPS.cpp @@ -27,6 +27,7 @@ #include "Core/MIPS/MIPSTables.h" #include "Core/MIPS/MIPSDebugInterface.h" #include "Core/MIPS/MIPSVFPUUtils.h" +#include "Core/MIPS/IR/IRJit.h" #include "Core/Reporting.h" #include "Core/System.h" #include "Core/HLE/sceDisplay.h" @@ -206,8 +207,10 @@ void MIPSState::Init() { // Initialize the VFPU random number generator with .. something? rng.Init(0x1337); - if (PSP_CoreParameter().cpuCore == CPU_JIT) { + if (PSP_CoreParameter().cpuCore == CPU_CORE_JIT) { MIPSComp::jit = MIPSComp::CreateNativeJit(this); + } else if (PSP_CoreParameter().cpuCore == CPU_CORE_IRJIT) { + MIPSComp::jit = new MIPSComp::IRJit(this); } else { MIPSComp::jit = nullptr; } @@ -224,14 +227,23 @@ void MIPSState::UpdateCore(CPUCore desired) { PSP_CoreParameter().cpuCore = desired; switch (PSP_CoreParameter().cpuCore) { - case CPU_JIT: + case CPU_CORE_JIT: INFO_LOG(CPU, "Switching to JIT"); - if (!MIPSComp::jit) { - MIPSComp::jit = MIPSComp::CreateNativeJit(this); + if (MIPSComp::jit) { + delete MIPSComp::jit; } + MIPSComp::jit = MIPSComp::CreateNativeJit(this); break; - case CPU_INTERPRETER: + case CPU_CORE_IRJIT: + INFO_LOG(CPU, "Switching to IRJIT"); + if (MIPSComp::jit) { + delete MIPSComp::jit; + } + MIPSComp::jit = new MIPSComp::IRJit(this); + break; + + case CPU_CORE_INTERPRETER: INFO_LOG(CPU, "Switching to interpreter"); delete MIPSComp::jit; MIPSComp::jit = 0; @@ -292,11 +304,12 @@ void MIPSState::SingleStep() { // returns 1 if reached ticks limit int MIPSState::RunLoopUntil(u64 globalTicks) { switch (PSP_CoreParameter().cpuCore) { - case CPU_JIT: + case CPU_CORE_JIT: + case CPU_CORE_IRJIT: MIPSComp::jit->RunLoopUntil(globalTicks); break; - case CPU_INTERPRETER: + case CPU_CORE_INTERPRETER: return MIPSInterpret_RunUntil(globalTicks); } return 1; diff --git a/Core/MemMapFunctions.cpp b/Core/MemMapFunctions.cpp index 93029d65ff..d367205ef7 100644 --- a/Core/MemMapFunctions.cpp +++ b/Core/MemMapFunctions.cpp @@ -87,7 +87,7 @@ inline void ReadFromHardware(T &var, const u32 address) { var = *((const T*)GetPointerUnchecked(address)); } else { // In jit, we only flush PC when bIgnoreBadMemAccess is off. - if (g_Config.bJit && g_Config.bIgnoreBadMemAccess) { + if (g_Config.iCpuCore != CPU_CORE_INTERPRETER && g_Config.bIgnoreBadMemAccess) { WARN_LOG(MEMMAP, "ReadFromHardware: Invalid address %08x", address); } else { WARN_LOG(MEMMAP, "ReadFromHardware: Invalid address %08x PC %08x LR %08x", address, currentMIPS->pc, currentMIPS->r[MIPS_REG_RA]); @@ -123,7 +123,7 @@ inline void WriteToHardware(u32 address, const T data) { *(T*)GetPointerUnchecked(address) = data; } else { // In jit, we only flush PC when bIgnoreBadMemAccess is off. - if (g_Config.bJit && g_Config.bIgnoreBadMemAccess) { + if (g_Config.iCpuCore != CPU_CORE_INTERPRETER && g_Config.bIgnoreBadMemAccess) { WARN_LOG(MEMMAP, "WriteToHardware: Invalid address %08x", address); } else { WARN_LOG(MEMMAP, "WriteToHardware: Invalid address %08x PC %08x LR %08x", address, currentMIPS->pc, currentMIPS->r[MIPS_REG_RA]); diff --git a/UI/EmuScreen.cpp b/UI/EmuScreen.cpp index dd89e1ae7d..06a3446eb6 100644 --- a/UI/EmuScreen.cpp +++ b/UI/EmuScreen.cpp @@ -101,7 +101,7 @@ void EmuScreen::bootGame(const std::string &filename) { invalid_ = true; CoreParameter coreParam; - coreParam.cpuCore = g_Config.bJit ? CPU_JIT : CPU_INTERPRETER; + coreParam.cpuCore = (CPUCore)g_Config.iCpuCore; coreParam.gpuCore = GPUCORE_GLES; switch (GetGPUBackend()) { case GPUBackend::OPENGL: @@ -282,7 +282,7 @@ void EmuScreen::sendMessage(const char *message, const char *value) { } else if (!strcmp(message, "clear jit")) { currentMIPS->ClearJitCache(); if (PSP_IsInited()) { - currentMIPS->UpdateCore(g_Config.bJit ? CPU_JIT : CPU_INTERPRETER); + currentMIPS->UpdateCore((CPUCore)g_Config.iCpuCore); } } else if (!strcmp(message, "window minimized")) { if (!strcmp(value, "true")) { diff --git a/UI/GameSettingsScreen.cpp b/UI/GameSettingsScreen.cpp index 2a5828eaec..1ade2a4303 100644 --- a/UI/GameSettingsScreen.cpp +++ b/UI/GameSettingsScreen.cpp @@ -1059,8 +1059,11 @@ void DeveloperToolsScreen::CreateViews() { } } #endif - if (canUseJit) { - list->Add(new CheckBox(&g_Config.bJit, sy->T("Dynarec", "Dynarec (JIT)")))->OnClick.Handle(this, &DeveloperToolsScreen::OnJitAffectingSetting); + + static const char *cpuCores[] = { "Interpreter", "Dynarec (JIT)", "IRJit" }; + PopupMultiChoice *core = list->Add(new PopupMultiChoice(&g_Config.iCpuCore, gr->T("CPU Core"), cpuCores, 0, ARRAY_SIZE(cpuCores), sy->GetName(), screenManager())); + if (!canUseJit) { + core->HideChoice(1); } list->Add(new CheckBox(&g_Config.bShowDeveloperMenu, dev->T("Show Developer Menu"))); diff --git a/UI/MiscScreens.cpp b/UI/MiscScreens.cpp index e6f0cc28e6..c94c9e6df4 100644 --- a/UI/MiscScreens.cpp +++ b/UI/MiscScreens.cpp @@ -133,7 +133,7 @@ void HandleCommonMessages(const char *message, const char *value, ScreenManager MIPSComp::jit->ClearCache(); } if (PSP_IsInited()) { - currentMIPS->UpdateCore(g_Config.bJit ? CPU_JIT : CPU_INTERPRETER); + currentMIPS->UpdateCore((CPUCore)g_Config.iCpuCore); } } } diff --git a/UI/NativeApp.cpp b/UI/NativeApp.cpp index 786e4e5126..9ca8045dd8 100644 --- a/UI/NativeApp.cpp +++ b/UI/NativeApp.cpp @@ -392,11 +392,15 @@ void NativeInit(int argc, const char *argv[], const char *savegame_dir, const ch gfxLog = true; break; case 'j': - g_Config.bJit = true; + g_Config.iCpuCore = CPU_CORE_JIT; g_Config.bSaveSettings = false; break; case 'i': - g_Config.bJit = false; + g_Config.iCpuCore = CPU_CORE_INTERPRETER; + g_Config.bSaveSettings = false; + break; + case 'r': + g_Config.iCpuCore = CPU_CORE_IRJIT; g_Config.bSaveSettings = false; break; case '-': diff --git a/android/jni/TestRunner.cpp b/android/jni/TestRunner.cpp index cfc4e0354e..29ca2b2a0c 100644 --- a/android/jni/TestRunner.cpp +++ b/android/jni/TestRunner.cpp @@ -69,7 +69,7 @@ void RunTests() #endif CoreParameter coreParam; - coreParam.cpuCore = g_Config.bJit ? CPU_JIT : CPU_INTERPRETER; + coreParam.cpuCore = (CPUCore)g_Config.iCpuCore; coreParam.gpuCore = g_Config.bSoftwareRendering ? GPUCORE_SOFTWARE : GPUCORE_GLES; coreParam.enableSound = g_Config.bEnableSound; coreParam.graphicsContext = PSP_CoreParameter().graphicsContext; diff --git a/headless/Headless.cpp b/headless/Headless.cpp index 687ac1d875..f818da68ca 100644 --- a/headless/Headless.cpp +++ b/headless/Headless.cpp @@ -207,11 +207,11 @@ int main(int argc, const char* argv[]) #endif bool fullLog = false; - bool useJit = true; bool autoCompare = false; bool verbose = false; const char *stateToLoad = 0; GPUCore gpuCore = GPUCORE_NULL; + CPUCore cpuCore = CPU_CORE_JIT; std::vector testFilenames; const char *mountIso = 0; @@ -236,9 +236,11 @@ int main(int argc, const char* argv[]) else if (!strcmp(argv[i], "-l") || !strcmp(argv[i], "--log")) fullLog = true; else if (!strcmp(argv[i], "-i")) - useJit = false; + cpuCore = CPU_CORE_INTERPRETER; else if (!strcmp(argv[i], "-j")) - useJit = true; + cpuCore = CPU_CORE_JIT; + else if (!strcmp(argv[i], "-ir")) + cpuCore = CPU_CORE_IRJIT; else if (!strcmp(argv[i], "-c") || !strcmp(argv[i], "--compare")) autoCompare = true; else if (!strcmp(argv[i], "-v") || !strcmp(argv[i], "--verbose")) @@ -311,7 +313,7 @@ int main(int argc, const char* argv[]) } CoreParameter coreParameter; - coreParameter.cpuCore = useJit ? CPU_JIT : CPU_INTERPRETER; + coreParameter.cpuCore = cpuCore; coreParameter.gpuCore = glWorking ? gpuCore : GPUCORE_NULL; coreParameter.graphicsContext = graphicsContext; coreParameter.enableSound = false; diff --git a/unittest/JitHarness.cpp b/unittest/JitHarness.cpp index b80fb04e6d..2467a27c0b 100644 --- a/unittest/JitHarness.cpp +++ b/unittest/JitHarness.cpp @@ -83,7 +83,7 @@ static void SetupJitHarness() { coreState = CORE_POWERUP; currentMIPS = &mipsr4k; Memory::g_MemorySize = Memory::RAM_NORMAL_SIZE; - PSP_CoreParameter().cpuCore = CPU_INTERPRETER; + PSP_CoreParameter().cpuCore = CPU_CORE_INTERPRETER; PSP_CoreParameter().unthrottle = true; Memory::Init(); @@ -169,7 +169,7 @@ bool TestJit() { double jit_speed = 0.0, interp_speed = 0.0; if (compileSuccess) { interp_speed = ExecCPUTest(); - mipsr4k.UpdateCore(CPU_JIT); + mipsr4k.UpdateCore(CPU_CORE_JIT); jit_speed = ExecCPUTest(); // Disassemble