From f3c69fc5d17a71a73b0e9717bb76b1c5b0c6412d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Thu, 15 Oct 2026 02:24:25 +0200 Subject: [PATCH] Remove FakeJit and the pre-IR JitBlockCache FakeJit was the native JIT for architectures without one, but the config already forces those onto the IR interpreter, so CreateNativeJit() now returns that instead. The vertex decoder fallback no longer needs FakeEmitter. JitBlockCache was the block cache of the pre-IR JITs. Its header keeps the debug interface types the IR block caches use. Also removes the JitInterface link hooks only it called, and the JitState fields tied to it. This fixes a null dereference in the ImDebugger memory section, which read GetBlockCache(), always null with the IR JITs. Co-Authored-By: Claude Opus 5.5 (1M context) --- Common/CMakeLists.txt | 1 - Common/Common.vcxproj | 1 - Common/Common.vcxproj.filters | 1 - Common/FakeEmitter.h | 425 ------------------ Core/CMakeLists.txt | 3 - Core/Core.vcxproj | 3 - Core/Core.vcxproj.filters | 12 - Core/MIPS/ARM64/Arm64IRJit.cpp | 1 + Core/MIPS/IR/IRFrontend.cpp | 3 - Core/MIPS/IR/IRJit.cpp | 8 - Core/MIPS/IR/IRJit.h | 5 - Core/MIPS/IR/IRNativeCommon.h | 1 + Core/MIPS/JitCommon/JitBlockCache.cpp | 540 ----------------------- Core/MIPS/JitCommon/JitBlockCache.h | 144 +----- Core/MIPS/JitCommon/JitCommon.cpp | 5 +- Core/MIPS/JitCommon/JitCommon.h | 8 - Core/MIPS/JitCommon/JitState.cpp | 21 - Core/MIPS/JitCommon/JitState.h | 27 -- Core/MIPS/LoongArch64/LoongArch64Jit.cpp | 1 + Core/MIPS/RiscV/RiscVJit.cpp | 1 + Core/MIPS/fake/FakeJit.cpp | 227 ---------- Core/MIPS/fake/FakeJit.h | 177 -------- Core/MIPS/x86/X64IRJit.cpp | 1 + GPU/Common/VertexDecoderCommon.cpp | 2 + GPU/Common/VertexDecoderCommon.h | 10 +- UI/ImDebugger/ImDebugger.cpp | 2 - UWP/CoreUWP/CoreUWP.vcxproj | 1 - UWP/CoreUWP/CoreUWP.vcxproj.filters | 1 - android/jni/Android.mk | 1 - libretro/Makefile.common | 1 - 30 files changed, 14 insertions(+), 1620 deletions(-) delete mode 100644 Common/FakeEmitter.h delete mode 100644 Core/MIPS/JitCommon/JitBlockCache.cpp delete mode 100644 Core/MIPS/fake/FakeJit.cpp delete mode 100644 Core/MIPS/fake/FakeJit.h diff --git a/Common/CMakeLists.txt b/Common/CMakeLists.txt index f269ad4689..e47554fb94 100644 --- a/Common/CMakeLists.txt +++ b/Common/CMakeLists.txt @@ -337,7 +337,6 @@ add_library(Common STATIC CommonTypes.h CommonWindows.h DbgNew.h - FakeEmitter.h FakeCPUDetect.cpp ExceptionHandlerSetup.cpp ExceptionHandlerSetup.h diff --git a/Common/Common.vcxproj b/Common/Common.vcxproj index ff1434abb5..42db8c9207 100644 --- a/Common/Common.vcxproj +++ b/Common/Common.vcxproj @@ -414,7 +414,6 @@ - diff --git a/Common/Common.vcxproj.filters b/Common/Common.vcxproj.filters index 9a02b190d8..50a14be6e1 100644 --- a/Common/Common.vcxproj.filters +++ b/Common/Common.vcxproj.filters @@ -54,7 +54,6 @@ Serialize - ext\libpng17 diff --git a/Common/FakeEmitter.h b/Common/FakeEmitter.h deleted file mode 100644 index 5727be7b5c..0000000000 --- a/Common/FakeEmitter.h +++ /dev/null @@ -1,425 +0,0 @@ -// Copyright (C) 2003 Dolphin Project. - -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, version 2.0. - -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License 2.0 for more details. - -// A copy of the GPL 2.0 should have been included with the program. -// If not, see http://www.gnu.org/licenses/ - -// Official SVN repository and contact information can be found at -// http://code.google.com/p/dolphin-emu/ - -// WARNING - THIS LIBRARY IS NOT THREAD SAFE!!! - -#ifndef _DOLPHIN_FAKE_CODEGEN_ -#define _DOLPHIN_FAKE_CODEGEN_ - -#include - -#include "Common/CommonTypes.h" -#include "Common/CodeBlock.h" - -// VCVT flags -#define TO_FLOAT 0 -#define TO_INT 1 << 0 -#define IS_SIGNED 1 << 1 -#define ROUND_TO_ZERO 1 << 2 - -namespace FakeGen -{ -enum FakeReg -{ - // GPRs - R0 = 0, R1, R2, R3, R4, R5, - R6, R7, R8, R9, R10, R11, - - // SPRs - // R13 - R15 are SP, LR, and PC. - // Almost always referred to by name instead of register number - R12 = 12, R13 = 13, R14 = 14, R15 = 15, - R_IP = 12, R_SP = 13, R_LR = 14, R_PC = 15, - - - // VFP single precision registers - S0, S1, S2, S3, S4, S5, S6, - S7, S8, S9, S10, S11, S12, S13, - S14, S15, S16, S17, S18, S19, S20, - S21, S22, S23, S24, S25, S26, S27, - S28, S29, S30, S31, - - // VFP Double Precision registers - D0, D1, D2, D3, D4, D5, D6, D7, - D8, D9, D10, D11, D12, D13, D14, D15, - D16, D17, D18, D19, D20, D21, D22, D23, - D24, D25, D26, D27, D28, D29, D30, D31, - - // ASIMD Quad-Word registers - Q0, Q1, Q2, Q3, Q4, Q5, Q6, Q7, - Q8, Q9, Q10, Q11, Q12, Q13, Q14, Q15, - - // for NEON VLD/VST instructions - REG_UPDATE = R13, - INVALID_REG = 0xFFFFFFFF -}; - -enum CCFlags -{ - CC_EQ = 0, // Equal - CC_NEQ, // Not equal - CC_CS, // Carry Set - CC_CC, // Carry Clear - CC_MI, // Minus (Negative) - CC_PL, // Plus - CC_VS, // Overflow - CC_VC, // No Overflow - CC_HI, // Unsigned higher - CC_LS, // Unsigned lower or same - CC_GE, // Signed greater than or equal - CC_LT, // Signed less than - CC_GT, // Signed greater than - CC_LE, // Signed less than or equal - CC_AL, // Always (unconditional) 14 - CC_HS = CC_CS, // Alias of CC_CS Unsigned higher or same - CC_LO = CC_CC, // Alias of CC_CC Unsigned lower -}; -const u32 NO_COND = 0xE0000000; - -enum ShiftType -{ - ST_LSL = 0, - ST_ASL = 0, - ST_LSR = 1, - ST_ASR = 2, - ST_ROR = 3, - ST_RRX = 4 -}; -enum IntegerSize -{ - I_I8 = 0, - I_I16, - I_I32, - I_I64 -}; - -enum -{ - NUMGPRs = 13, -}; - -class FakeXEmitter; - -enum OpType -{ - TYPE_IMM = 0, - TYPE_REG, - TYPE_IMMSREG, - TYPE_RSR, - TYPE_MEM -}; - -// This is no longer a proper operand2 class. Need to split up. -class Operand2 -{ - friend class FakeXEmitter; -protected: - u32 Value; - -private: - OpType Type; - - // IMM types - u8 Rotation; // Only for u8 values - - // Register types - u8 IndexOrShift; - ShiftType Shift; -public: - OpType GetType() - { - return Type; - } - Operand2() {} - Operand2(u32 imm, OpType type = TYPE_IMM) : IndexOrShift(), Shift() - { - Type = type; - Value = imm; - Rotation = 0; - } - - Operand2(FakeReg Reg) : IndexOrShift(), Shift() - { - Type = TYPE_REG; - Value = Reg; - Rotation = 0; - } - Operand2(u8 imm, u8 rotation) : IndexOrShift(), Shift() - { - Type = TYPE_IMM; - Value = imm; - Rotation = rotation; - } - Operand2(FakeReg base, ShiftType type, FakeReg shift) : Rotation(0) // RSR - { - Type = TYPE_RSR; - _assert_msg_(type != ST_RRX, "Invalid Operand2: RRX does not take a register shift amount"); - IndexOrShift = shift; - Shift = type; - Value = base; - } - - Operand2(FakeReg base, ShiftType type, u8 shift) : Rotation(0) // For IMM shifted register - { - if(shift == 32) shift = 0; - switch (type) - { - case ST_LSL: - _assert_msg_(shift < 32, "Invalid Operand2: LSL %u", shift); - break; - case ST_LSR: - _assert_msg_(shift <= 32, "Invalid Operand2: LSR %u", shift); - if (!shift) - type = ST_LSL; - if (shift == 32) - shift = 0; - break; - case ST_ASR: - _assert_msg_(shift < 32, "Invalid Operand2: ASR %u", shift); - if (!shift) - type = ST_LSL; - if (shift == 32) - shift = 0; - break; - case ST_ROR: - _assert_msg_(shift < 32, "Invalid Operand2: ROR %u", shift); - if (!shift) - type = ST_LSL; - break; - case ST_RRX: - _assert_msg_(shift == 0, "Invalid Operand2: RRX does not take an immediate shift amount"); - type = ST_ROR; - break; - } - IndexOrShift = shift; - Shift = type; - Value = base; - Type = TYPE_IMMSREG; - } - u32 GetData() - { - switch(Type) - { - case TYPE_IMM: - return Imm12Mod(); // This'll need to be changed later - case TYPE_REG: - return Rm(); - case TYPE_IMMSREG: - return IMMSR(); - case TYPE_RSR: - return RSR(); - default: - _assert_msg_(false, "GetData with Invalid Type"); - return 0; - } - } - u32 IMMSR() // IMM shifted register - { - _assert_msg_(Type == TYPE_IMMSREG, "IMMSR must be imm shifted register"); - return ((IndexOrShift & 0x1f) << 7 | (Shift << 5) | Value); - } - u32 RSR() // Register shifted register - { - _assert_msg_(Type == TYPE_RSR, "RSR must be RSR Of Course"); - return (IndexOrShift << 8) | (Shift << 5) | 0x10 | Value; - } - u32 Rm() - { - _assert_msg_(Type == TYPE_REG, "Rm must be with Reg"); - return Value; - } - - u32 Imm5() - { - _assert_msg_(Type == TYPE_IMM, "Imm5 not IMM value"); - return ((Value & 0x0000001F) << 7); - } - u32 Imm8() - { - _assert_msg_(Type == TYPE_IMM, "Imm8Rot not IMM value"); - return Value & 0xFF; - } - u32 Imm8Rot() // IMM8 with Rotation - { - _assert_msg_(Type == TYPE_IMM, "Imm8Rot not IMM value"); - _assert_msg_((Rotation & 0xE1) != 0, "Invalid Operand2: immediate rotation %u", Rotation); - return (1 << 25) | (Rotation << 7) | (Value & 0x000000FF); - } - u32 Imm12() - { - _assert_msg_(Type == TYPE_IMM, "Imm12 not IMM"); - return (Value & 0x00000FFF); - } - - u32 Imm12Mod() - { - // This is an IMM12 with the top four bits being rotation and the - // bottom eight being an IMM. This is for instructions that need to - // expand a 8bit IMM to a 32bit value and gives you some rotation as - // well. - // Each rotation rotates to the right by 2 bits - _assert_msg_(Type == TYPE_IMM, "Imm12Mod not IMM"); - return ((Rotation & 0xF) << 8) | (Value & 0xFF); - } - u32 Imm16() - { - _assert_msg_(Type == TYPE_IMM, "Imm16 not IMM"); - return ( (Value & 0xF000) << 4) | (Value & 0x0FFF); - } - u32 Imm16Low() - { - return Imm16(); - } - u32 Imm16High() // Returns high 16bits - { - _assert_msg_(Type == TYPE_IMM, "Imm16 not IMM"); - return ( ((Value >> 16) & 0xF000) << 4) | ((Value >> 16) & 0x0FFF); - } - u32 Imm24() - { - _assert_msg_(Type == TYPE_IMM, "Imm16 not IMM"); - return (Value & 0x0FFFFFFF); - } -}; - -// Use these when you don't know if an imm can be represented as an operand2. -// This lets you generate both an optimal and a fallback solution by checking -// the return value, which will be false if these fail to find a Operand2 that -// represents your 32-bit imm value. -bool TryMakeOperand2(u32 imm, Operand2 &op2); -bool TryMakeOperand2_AllowInverse(u32 imm, Operand2 &op2, bool *inverse); -bool TryMakeOperand2_AllowNegation(s32 imm, Operand2 &op2, bool *negated); - -// Use this only when you know imm can be made into an Operand2. -Operand2 AssumeMakeOperand2(u32 imm); - -inline Operand2 R(FakeReg Reg) { return Operand2(Reg, TYPE_REG); } -inline Operand2 IMM(u32 Imm) { return Operand2(Imm, TYPE_IMM); } -inline Operand2 Mem(void *ptr) { return Operand2((u32)(uintptr_t)ptr, TYPE_IMM); } -//usage: struct {int e;} s; STRUCT_OFFSET(s,e) -#define STRUCT_OFF(str,elem) ((u32)((u32)&(str).elem-(u32)&(str))) - - -struct FixupBranch -{ - u8 *ptr; - u32 condition; // Remembers our codition at the time - int type; //0 = B 1 = BL -}; - -typedef const u8* JumpTarget; - -// XXX: Stop polluting the global namespace -const u32 I_8 = (1 << 0); -const u32 I_16 = (1 << 1); -const u32 I_32 = (1 << 2); -const u32 I_64 = (1 << 3); -const u32 I_SIGNED = (1 << 4); -const u32 I_UNSIGNED = (1 << 5); -const u32 F_32 = (1 << 6); -const u32 I_POLYNOMIAL = (1 << 7); // Only used in VMUL/VMULL - -u32 EncodeVd(FakeReg Vd); -u32 EncodeVn(FakeReg Vn); -u32 EncodeVm(FakeReg Vm); - -u32 encodedSize(u32 value); - -// Subtracts the base from the register to give us the real one -FakeReg SubBase(FakeReg Reg); - -// See A.7.1 in the Fakev7-A -// VMUL F32 scalars can only be up to D15[0], D15[1] - higher scalars cannot be individually addressed -FakeReg DScalar(FakeReg dreg, int subScalar); -FakeReg QScalar(FakeReg qreg, int subScalar); - -enum NEONAlignment { - ALIGN_NONE = 0, - ALIGN_64 = 1, - ALIGN_128 = 2, - ALIGN_256 = 3 -}; - - -class NEONXEmitter; - -class FakeXEmitter -{ - friend struct OpArg; // for Write8 etc -private: - u8 *code, *startcode; - u8 *lastCacheFlushEnd; - u32 condition; - -protected: - inline void Write32(u32 value) {*(u32*)code = value; code+=4;} - -public: - FakeXEmitter() : code(0), startcode(0), lastCacheFlushEnd(0) { - condition = CC_AL << 28; - } - FakeXEmitter(u8 *code_ptr) { - code = code_ptr; - lastCacheFlushEnd = code_ptr; - startcode = code_ptr; - condition = CC_AL << 28; - } - virtual ~FakeXEmitter() {} - - void SetCodePointer(u8 *ptr, u8 *writePtr) {} - const u8 *GetCodePointer() const { return nullptr; } - - void SetCodePtr(u8 *ptr) {} - void ReserveCodeSpace(u32 bytes) {} - const u8 *AlignCode16() { return nullptr; } - const u8 *AlignCodePage() { return nullptr; } - const u8 *GetCodePtr() const { return nullptr; } - void FlushIcache() {} - void FlushIcacheSection(u8 *start, u8 *end) {} - u8 *GetWritableCodePtr() { return nullptr; } - - CCFlags GetCC() { return CCFlags(condition >> 28); } - void SetCC(CCFlags cond = CC_AL) {} - - // Special purpose instructions - - // Do nothing - void NOP(int count = 1) {} //nop padding - TODO: fast nop slides, for amd and intel (check their manuals) - -#ifdef CALL -#undef CALL -#endif - - void QuickCallFunction(FakeReg scratchreg, const void *func); - template void QuickCallFunction(FakeReg scratchreg, T func) { - QuickCallFunction(scratchreg, (const void *)func); - } -}; // class FakeXEmitter - - -// Everything that needs to generate machine code should inherit from this. -// You get memory management for free, plus, you can use all the MOV etc functions without -// having to prefix them with gen-> or something similar. -class FakeXCodeBlock : public CodeBlock { -public: - void PoisonMemory(int offset) override { - } -}; - -} // namespace - -#endif // _DOLPHIN_FAKE_CODEGEN_ diff --git a/Core/CMakeLists.txt b/Core/CMakeLists.txt index 34e9f16f7c..c84d0a269a 100644 --- a/Core/CMakeLists.txt +++ b/Core/CMakeLists.txt @@ -188,8 +188,6 @@ if(NOT LIBRETRO) HW/StereoResampler.h MIPS/MIPSAsm.cpp MIPS/MIPSAsm.h - MIPS/fake/FakeJit.cpp - MIPS/fake/FakeJit.h Util/GameManager.cpp Util/GameManager.h Util/VideoPlayer.cpp @@ -632,7 +630,6 @@ add_library(Core STATIC MIPS/MIPSTracer.h MIPS/JitCommon/JitCommon.cpp MIPS/JitCommon/JitCommon.h - MIPS/JitCommon/JitBlockCache.cpp MIPS/JitCommon/JitBlockCache.h MIPS/JitCommon/JitState.cpp MIPS/JitCommon/JitState.h diff --git a/Core/Core.vcxproj b/Core/Core.vcxproj index b6a47a8d6f..ca1683c618 100644 --- a/Core/Core.vcxproj +++ b/Core/Core.vcxproj @@ -508,7 +508,6 @@ - @@ -694,7 +693,6 @@ - @@ -871,7 +869,6 @@ - diff --git a/Core/Core.vcxproj.filters b/Core/Core.vcxproj.filters index f293f6ac42..69b9d96243 100644 --- a/Core/Core.vcxproj.filters +++ b/Core/Core.vcxproj.filters @@ -85,9 +85,6 @@ {0201ff27-4fa8-4cf3-bbb9-accfdc0c7046} - - {678fa299-0ff7-4983-982d-2da47b52e238} - {067e3128-3aaf-4ed1-b19e-bab11606abe7} @@ -481,9 +478,6 @@ HLE\Libraries - - MIPS\JitCommon - Core @@ -925,9 +919,6 @@ Debugger\WebSocket - - MIPS\fake - Debugger @@ -2079,9 +2070,6 @@ Debugger\WebSocket - - MIPS\fake - Debugger diff --git a/Core/MIPS/ARM64/Arm64IRJit.cpp b/Core/MIPS/ARM64/Arm64IRJit.cpp index ca4136c020..3b99093dd0 100644 --- a/Core/MIPS/ARM64/Arm64IRJit.cpp +++ b/Core/MIPS/ARM64/Arm64IRJit.cpp @@ -20,6 +20,7 @@ #if PPSSPP_ARCH(ARM64) || (PPSSPP_PLATFORM(WINDOWS) && !defined(__LIBRETRO__)) #include +#include #include "Core/MemMap.h" #include "Core/MIPS/MIPSTables.h" #include "Core/MIPS/ARM64/Arm64IRJit.h" diff --git a/Core/MIPS/IR/IRFrontend.cpp b/Core/MIPS/IR/IRFrontend.cpp index c79670cfeb..043716999a 100644 --- a/Core/MIPS/IR/IRFrontend.cpp +++ b/Core/MIPS/IR/IRFrontend.cpp @@ -278,10 +278,7 @@ void IRFrontend::DoJit(u32 em_address, std::vector &instructions, u32 &m js.cancel = false; js.blockStart = em_address; js.compilerPC = em_address; - js.initialBlockSize = 0; - js.nextExit = 0; js.downcountAmount = 0; - js.curBlock = nullptr; js.compiling = true; js.hadBreakpoints = false; js.blockWrotePrefixes = false; diff --git a/Core/MIPS/IR/IRJit.cpp b/Core/MIPS/IR/IRJit.cpp index 2c1f2aaff4..f6f1cca8fb 100644 --- a/Core/MIPS/IR/IRJit.cpp +++ b/Core/MIPS/IR/IRJit.cpp @@ -245,14 +245,6 @@ bool IRJit::DescribeCodePtr(const u8 *ptr, std::string &name) { return false; } -void IRJit::LinkBlock(u8 *exitPoint, const u8 *checkedEntry) { - Crash(); -} - -void IRJit::UnlinkBlock(u8 *checkedEntry, u32 originalAddress) { - Crash(); -} - void IRBlockCache::Clear() { for (int i = 0; i < (int)blocks_.size(); ++i) { int cookie = compileToNative_ ? blocks_[i].GetNativeOffset() : blocks_[i].GetIRArenaOffset(); diff --git a/Core/MIPS/IR/IRJit.h b/Core/MIPS/IR/IRJit.h index 6ccdba5bd5..b40a8ed450 100644 --- a/Core/MIPS/IR/IRJit.h +++ b/Core/MIPS/IR/IRJit.h @@ -214,8 +214,6 @@ public: void Compile(u32 em_address) override; // Compiles a block at current MIPS PC bool DescribeCodePtr(const u8 *ptr, std::string &name) override; - // Not using a regular block cache. - JitBlockCache *GetBlockCache() override { return nullptr; } JitBlockCacheDebugInterface *GetBlockCacheDebugInterface() override { return &blocks_; } void ClearCache() override; @@ -229,9 +227,6 @@ public: const u8 *GetDispatcher() const override { return nullptr; } const u8 *GetCrashHandler() const override { return nullptr; } - void LinkBlock(u8 *exitPoint, const u8 *checkedEntry) override; - void UnlinkBlock(u8 *checkedEntry, u32 originalAddress) override; - // This gets overridden by the native-backed IR jits. const u8 *GetCodeBase() const override { return nullptr; } diff --git a/Core/MIPS/IR/IRNativeCommon.h b/Core/MIPS/IR/IRNativeCommon.h index 89d83ddb50..686d24406b 100644 --- a/Core/MIPS/IR/IRNativeCommon.h +++ b/Core/MIPS/IR/IRNativeCommon.h @@ -19,6 +19,7 @@ #include +#include "Common/CodeBlock.h" #include "Core/MIPS/IR/IRJit.h" #include "Core/MIPS/JitCommon/JitBlockCache.h" diff --git a/Core/MIPS/JitCommon/JitBlockCache.cpp b/Core/MIPS/JitCommon/JitBlockCache.cpp deleted file mode 100644 index 133a436ffb..0000000000 --- a/Core/MIPS/JitCommon/JitBlockCache.cpp +++ /dev/null @@ -1,540 +0,0 @@ -// Copyright (c) 2012- PPSSPP Project / Dolphin Project. - -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, version 2.0 or later versions. - -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License 2.0 for more details. - -// A copy of the GPL 2.0 should have been included with the program. -// If not, see http://www.gnu.org/licenses/ - -// Official git repository and contact information can be found at -// https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/. - -#include "ppsspp_config.h" -#include -#include - -#include "ext/xxhash.h" -#include "Common/CommonTypes.h" -#include "Common/Profiler/Profiler.h" - -#ifdef _WIN32 -#include "Common/CommonWindows.h" -#endif - -#include "Core/Core.h" -#include "Core/MemMap.h" -#include "Core/HLE/ReplaceTables.h" -#include "Core/CoreTiming.h" -#include "Core/Reporting.h" - -#include "Core/MIPS/MIPS.h" -#include "Core/MIPS/MIPSTables.h" -#include "Core/MIPS/MIPSAnalyst.h" - -#include "Core/MIPS/JitCommon/JitBlockCache.h" -#include "Core/MIPS/JitCommon/JitCommon.h" - -constexpr u32 INVALID_EXIT = 0xFFFFFFFF; -constexpr u32 SENTINEL_VAL = 0xc0ffeefe; - -static uint64_t HashJitBlock(const JitBlock &b) { - PROFILE_THIS_SCOPE("jithash"); - if (JIT_USE_COMPILEDHASH) { - if (Memory::IsValidRange(b.originalAddress, b.originalSize * 4)) { - return XXH3_64bits(Memory::GetPointerUnchecked(b.originalAddress), b.originalSize * 4); - } else { - // Hm, this would be bad. - return 0; - } - } - return 0; -} - -bool JitBlock::ContainsAddress(u32 address) const { - // WARNING - THIS DOES NOT WORK WITH JIT INLINING ENABLED. - // However, that doesn't exist yet so meh. - return address >= originalAddress && address < originalAddress + 4 * originalSize; -} - -void JitBlock::DoIntegrityCheck(u32 emAddress, int num, const char *reason) const { - _assert_msg_(emAddress == originalAddress, "%s: Bad orig %08x (expected: %08x, snt: %08x) in block %d (b.num: %d) sz: %d", reason, originalAddress, emAddress, sentinel, num, blockNum, codeSize); - // Also alert just if the sentinel got corrupted. - _assert_msg_(sentinel == SENTINEL_VAL, "%s: Block %d(%d) sentinel got corrupted: %08x != %08x (origAddr: %08x)", reason, num, blockNum, sentinel, SENTINEL_VAL, originalAddress); -} - -JitBlockCache::JitBlockCache(MIPSState *mipsState, CodeBlockCommon *codeBlock) : codeBlock_(codeBlock) {} - -JitBlockCache::~JitBlockCache() { - Shutdown(); -} - -bool JitBlockCache::IsFull() const { - // Subtract some amount to safely leave space for some proxy blocks (now obsolete, but let's still have some extra margin). - return num_blocks_ >= MAX_NUM_BLOCKS - 64; -} - -void JitBlockCache::Init() { - blocks_ = new JitBlock[MAX_NUM_BLOCKS]; - Clear(); -} - -void JitBlockCache::Shutdown() { - Clear(); // Make sure proxy block links are deleted - delete [] blocks_; - blocks_ = 0; - num_blocks_ = 0; -} - -// This clears the JIT cache. It's called from JitCache.cpp when the JIT cache -// is full and when saving and loading states. -void JitBlockCache::Clear() { - // Note: We intentionally clear the block_map_ first to avoid O(N^2) behavior in RemoveBlockMap - block_map_.clear(); - for (int i = 0; i < num_blocks_; i++) { - DestroyBlock(i, DestroyType::CLEAR); - } - links_to_.clear(); - num_blocks_ = 0; - - blockMemRanges_[JITBLOCK_RANGE_SCRATCH] = std::make_pair(0xFFFFFFFF, 0x00000000); - blockMemRanges_[JITBLOCK_RANGE_RAMBOTTOM] = std::make_pair(0xFFFFFFFF, 0x00000000); - blockMemRanges_[JITBLOCK_RANGE_RAMTOP] = std::make_pair(0xFFFFFFFF, 0x00000000); -} - -void JitBlockCache::Reset() { - Shutdown(); - Init(); -} - -int JitBlockCache::AllocateBlock(u32 startAddress) { - _assert_(num_blocks_ < MAX_NUM_BLOCKS); - - const int numBlocks = num_blocks_; - - JitBlock &b = blocks_[numBlocks]; - - b.invalid = false; - b.originalAddress = startAddress; - for (int i = 0; i < MAX_JIT_BLOCK_EXITS; ++i) { - b.exitAddress[i] = INVALID_EXIT; - b.exitPtrs[i] = 0; - b.linkStatus[i] = false; - } - b.blockNum = numBlocks; - b.sentinel = SENTINEL_VAL; - - num_blocks_ = numBlocks + 1; //commit the current block - return numBlocks; -} - -void JitBlockCache::AddBlockMap(int block_num) { - const JitBlock &b = blocks_[block_num]; - // Convert the logical address to a physical address for the block map - u32 pAddr = b.originalAddress & 0x1FFFFFFF; - block_map_[std::make_pair(pAddr + 4 * b.originalSize, pAddr)] = block_num; -} - -void JitBlockCache::RemoveBlockMap(int block_num) { - const JitBlock &b = blocks_[block_num]; - if (b.invalid) { - return; - } - - const u32 pAddr = b.originalAddress & 0x1FFFFFFF; - auto it = block_map_.find(std::make_pair(pAddr + 4 * b.originalSize, pAddr)); - if (it != block_map_.end() && it->second == (u32)block_num) { - block_map_.erase(it); - } else { - // It wasn't in there, or it has the wrong key. Let's search... - // TODO: This is O(n), so O(n^2) when called for every block. - for (auto it = block_map_.begin(); it != block_map_.end(); ++it) { - if (it->second == (u32)block_num) { - _dbg_assert_(false); - block_map_.erase(it); - break; - } - } - } -} - -static void ExpandRange(std::pair &range, u32 newStart, u32 newEnd) { - range.first = std::min(range.first, newStart); - range.second = std::max(range.second, newEnd); -} - -void JitBlockCache::FinalizeBlock(int block_num, bool block_link) { - JitBlock &b = blocks_[block_num]; - - b.originalFirstOpcode = Memory::ReadUnchecked_Instruction(b.originalAddress); - Memory::WriteBlockShadow(b.originalAddress, GetShadowValueForBlock(block_num)); - b.compiledHash = HashJitBlock(b); - - AddBlockMap(block_num); - - if (block_link) { - for (int i = 0; i < MAX_JIT_BLOCK_EXITS; i++) { - if (b.exitAddress[i] != INVALID_EXIT) { - links_to_.emplace(b.exitAddress[i], block_num); - } - } - - LinkBlock(block_num); - LinkBlockExits(block_num); - } - - const u32 blockEnd = b.originalAddress + b.originalSize * 4 - 4; - if (Memory::IsScratchpadAddress(b.originalAddress)) { - ExpandRange(blockMemRanges_[JITBLOCK_RANGE_SCRATCH], b.originalAddress, blockEnd); - } - const u32 halfUserMemory = (PSP_GetUserMemoryEnd() - PSP_GetUserMemoryBase()) / 2; - if (b.originalAddress < PSP_GetUserMemoryBase() + halfUserMemory) { - ExpandRange(blockMemRanges_[JITBLOCK_RANGE_RAMBOTTOM], b.originalAddress, blockEnd); - } - // >=, not >: the bottom check above is strict, so a block sitting exactly on the midpoint - // would otherwise land in neither range. - if (blockEnd >= PSP_GetUserMemoryBase() + halfUserMemory) { - ExpandRange(blockMemRanges_[JITBLOCK_RANGE_RAMTOP], b.originalAddress, blockEnd); - } -} - -bool JitBlockCache::RangeMayHaveBlocks(u32 start, u32 end) const { - for (int i = 0; i < JITBLOCK_RANGE_COUNT; ++i) { - if (end >= blockMemRanges_[i].first && start <= blockMemRanges_[i].second) { - return true; - } - } - return false; -} - -static int binary_search(const JitBlock blocks_[], const u8 *baseoff, int imin, int imax) { - while (imin < imax) { - int imid = (imin + imax) >> 1; - if (blocks_[imid].normalEntry < baseoff) - imin = imid + 1; - else - imax = imid; - } - if ((imax == imin) && (blocks_[imin].normalEntry == baseoff)) - return imin; - else - return -1; -} - -int JitBlockCache::GetBlockNumberFromShadowValue(u32 value) const { - if (!num_blocks_ || value == 0) - return -1; - - const u8 *baseoff = codeBlock_->GetBasePtr() + value; - if (baseoff >= codeBlock_->GetCodePtr()) { - ERROR_LOG(Log::JIT, "JitBlockCache: Invalid block shadow value %08x", value); - return -1; - } - - int bl = binary_search(blocks_, baseoff, 0, num_blocks_ - 1); - if (bl >= 0 && blocks_[bl].invalid) { - return -1; - } else { - return bl; - } -} - -u32 JitBlockCache::GetShadowValueForBlock(int blockNum) const { - // Never 0, the dispatcher is at the start of the code space. - const u32 off = (u32)(blocks_[blockNum].normalEntry - codeBlock_->GetBasePtr()); - _dbg_assert_(off != 0); - return off; -} - -int JitBlockCache::GetBlockNumberFromStartAddress(u32 addr) const { - if (!blocks_ || !Memory::IsValid4AlignedAddress(addr)) - return -1; - - // A replacement hook's value is the dispatcher's compile path, which isn't any block's entry. - int bl = GetBlockNumberFromShadowValue(Memory::ReadBlockShadow(addr)); - if (bl < 0) { - return -1; - } - - if (blocks_[bl].originalAddress != addr) - return -1; - - return bl; -} - -void JitBlockCache::GetBlockNumbersFromAddress(u32 em_address, std::vector *block_numbers) const { - for (int i = 0; i < num_blocks_; i++) - if (blocks_[i].ContainsAddress(em_address)) - block_numbers->push_back(i); -} - -int JitBlockCache::GetBlockNumberFromAddress(u32 em_address) const { - for (int i = 0; i < num_blocks_; i++) { - if (blocks_[i].ContainsAddress(em_address)) - return i; - } - return -1; -} - -u32 JitBlockCache::GetAddressFromBlockPtr(const u8 *ptr) const { - if (!codeBlock_->IsInSpace(ptr)) - return (u32)-1; - - for (int i = 0; i < num_blocks_; ++i) { - const auto &b = blocks_[i]; - if (!b.invalid && ptr >= b.checkedEntry && ptr < b.normalEntry + b.codeSize) { - return b.originalAddress; - } - } - - // It's in jit somewhere, but we must have deleted it. - return 0; -} - -MIPSOpcode JitBlockCache::GetOriginalFirstOp(int block_num) const { - if (block_num >= num_blocks_ || block_num < 0) { - return MIPSOpcode(block_num); - } - return blocks_[block_num].originalFirstOpcode; -} - -void JitBlockCache::LinkBlockExits(int i) { - JitBlock &b = blocks_[i]; - if (b.invalid) { - // This block is dead. Don't relink it. - return; - } - - for (int e = 0; e < MAX_JIT_BLOCK_EXITS; e++) { - if (b.exitAddress[e] != INVALID_EXIT && !b.linkStatus[e]) { - int destinationBlock = GetBlockNumberFromStartAddress(b.exitAddress[e]); - if (destinationBlock == -1) { - continue; - } - - JitBlock &eb = blocks_[destinationBlock]; - // Make sure the destination is not invalid. - if (!eb.invalid) { - MIPSComp::jit->LinkBlock(b.exitPtrs[e], eb.checkedEntry); - b.linkStatus[e] = true; - } - } - } -} - -void JitBlockCache::LinkBlock(int i) { - LinkBlockExits(i); - JitBlock &b = blocks_[i]; - // equal_range(b) returns pair representing the range - // of element with key b - auto ppp = links_to_.equal_range(b.originalAddress); - if (ppp.first == ppp.second) - return; - for (auto iter = ppp.first; iter != ppp.second; ++iter) { - // INFO_LOG(Log::JIT, "Linking block %i to block %i", iter->second, i); - LinkBlockExits(iter->second); - } -} - -void JitBlockCache::UnlinkBlock(int i) { - JitBlock &b = blocks_[i]; - auto ppp = links_to_.equal_range(b.originalAddress); - if (ppp.first == ppp.second) - return; - for (auto iter = ppp.first; iter != ppp.second; ++iter) { - if ((size_t)iter->second >= num_blocks_) { - // Something probably went very wrong. Try to stumble along nevertheless. - ERROR_LOG(Log::JIT, "UnlinkBlock: Invalid block number %d", iter->second); - continue; - } - JitBlock &sourceBlock = blocks_[iter->second]; - for (int e = 0; e < MAX_JIT_BLOCK_EXITS; e++) { - if (sourceBlock.exitAddress[e] == b.originalAddress) - sourceBlock.linkStatus[e] = false; - } - } -} - -void JitBlockCache::DestroyBlock(int block_num, DestroyType type) { - if (block_num < 0 || block_num >= num_blocks_) { - ERROR_LOG_REPORT(Log::JIT, "DestroyBlock: Invalid block number %d", block_num); - return; - } - JitBlock *b = &blocks_[block_num]; - // No point it being in there anymore. - RemoveBlockMap(block_num); - - // TODO: Handle the case when there's a proxy block and a regular JIT block at the same location. - // In this case we probably "leak" the proxy block currently (no memory leak but it'll stay enabled). - - if (b->invalid) { - if (type == DestroyType::INVALIDATE) - ERROR_LOG(Log::JIT, "Invalidating invalid block %d", block_num); - return; - } - - b->invalid = true; - - // Only clearing the shadow entry needs a valid address. The unlinking below has to - // happen either way - otherwise other blocks go on jumping straight into this one, which - // we've just marked invalid. - if (Memory::IsValid4AlignedAddress(b->originalAddress)) { - // A mirror may have replaced the entry with its own block, leave that alone. - Memory::ClearBlockShadow(b->originalAddress, GetShadowValueForBlock(block_num)); - } else { - _dbg_assert_msg_(false, "Destroying block with invalid original address: %08x (block num: %d)", b->originalAddress, block_num); - } - - // It's not safe to set normalEntry to 0 here, since we use a binary search - // that looks at that later to find blocks. Marking it invalid is enough. - - UnlinkBlock(block_num); - - if (b->checkedEntry) { - // We can skip this if we're clearing anyway, which cuts down on protect back and forth on WX exclusive. - if (type != DestroyType::CLEAR) { - u8 *writableEntry = codeBlock_->GetWritablePtrFromCodePtr(b->checkedEntry); - MIPSComp::jit->UnlinkBlock(writableEntry, b->originalAddress); - } - } else { - ERROR_LOG(Log::JIT, "Unlinking block with no entry: %08x (%d)", b->originalAddress, block_num); - } -} - -void JitBlockCache::InvalidateICache(u32 address, const u32 length) { - // Convert the logical address to a physical address for the block map - const u32 pAddr = address & 0x1FFFFFFF; - const u32 pEnd = pAddr + length; - - if (pEnd < pAddr) { - ERROR_LOG(Log::JIT, "Bad InvalidateICache: %08x with len=%d", address, length); - return; - } - - if (pAddr == 0 && pEnd >= 0x1FFFFFFF) { - InvalidateChangedBlocks(); - return; - } - - // Blocks may start and end in overlapping ways, and destroying one invalidates iterators. - // So after destroying one, we start over. - do { - restart: - auto next = block_map_.lower_bound(std::make_pair(pAddr, 0)); - // block_map_ is keyed by byte addresses, so the margin has to cover the longest - // possible block in bytes, not instructions. - auto last = block_map_.upper_bound(std::make_pair(pEnd + 4 * MAX_BLOCK_INSTRUCTIONS, 0)); - // Note that if next is end(), last will be end() too (equal.) - for (; next != last; ++next) { - const u32 blockStart = next->first.second; - const u32 blockEnd = next->first.first; - if (blockStart < pEnd && blockEnd > pAddr) { - DestroyBlock(next->second, DestroyType::INVALIDATE); - // Our iterator is now invalid. Break and search again. - // Most of the time there shouldn't be a bunch of matching blocks. - goto restart; - } - } - // We got here - it wasn't in the map at all (or anymore.) - } while (false); -} - -void JitBlockCache::InvalidateChangedBlocks() { - // The primary goal of this is to make sure block linking is cleared up. - for (int block_num = 0; block_num < num_blocks_; ++block_num) { - JitBlock &b = blocks_[block_num]; - if (b.invalid) - continue; - - bool changed = false; - if (JIT_USE_COMPILEDHASH) { - changed = b.compiledHash != HashJitBlock(b); - } else { - changed = Memory::ReadUnchecked_U32(b.originalAddress) != b.originalFirstOpcode.encoding; - } - - if (changed) { - DEBUG_LOG(Log::JIT, "Invalidating changed block at %08x", b.originalAddress); - DestroyBlock(block_num, DestroyType::INVALIDATE); - } - } -} - -int JitBlockCache::GetBlockExitSize() { -#if PPSSPP_ARCH(ARM) - // Will depend on the sequence found to encode the destination address. - return 0; -#elif PPSSPP_ARCH(X86) || PPSSPP_ARCH(AMD64) - return 15; -#elif PPSSPP_ARCH(ARM64) - // Will depend on the sequence found to encode the destination address. - return 0; -#elif PPSSPP_ARCH(RISCV64) - // Will depend on the sequence found to encode the destination address. - return 0; -#elif PPSSPP_ARCH(LOONGARCH64) - // Will depend on the sequence found to encode the destination address. - return 0; -#else -#warning GetBlockExitSize unimplemented - return 0; -#endif -} - -void JitBlockCache::ComputeStats(BlockCacheStats &bcStats) const { - double totalBloat = 0.0; - double maxBloat = 0.0; - double minBloat = 1000000000.0; - for (int i = 0; i < num_blocks_; i++) { - const JitBlock *b = GetBlock(i); - double codeSize = (double)b->codeSize; - if (codeSize == 0) - continue; - double origSize = (double)(4 * b->originalSize); - double bloat = codeSize / origSize; - if (bloat < minBloat) { - minBloat = bloat; - bcStats.minBloatBlock = b->originalAddress; - } - if (bloat > maxBloat) { - maxBloat = bloat; - bcStats.maxBloatBlock = b->originalAddress; - } - totalBloat += bloat; - } - bcStats.numBlocks = num_blocks_; - bcStats.minBloat = (float)minBloat; - bcStats.maxBloat = (float)maxBloat; - bcStats.avgBloat = (float)(totalBloat / (double)num_blocks_); -} - -JitBlockDebugInfo JitBlockCache::GetBlockDebugInfo(int blockNum) const { - JitBlockDebugInfo debugInfo{}; - const JitBlock *block = GetBlock(blockNum); - debugInfo.originalAddress = block->originalAddress; - debugInfo.origDisasm.reserve(((block->originalAddress + block->originalSize * 4) - block->originalAddress) / 4); - for (u32 addr = block->originalAddress; addr < block->originalAddress + block->originalSize * 4; addr += 4) { - char temp[256]; - MIPSDisAsm(Replacement_GetDisplayOp(addr), addr, temp, sizeof(temp), true); - std::string mipsDis = temp; - debugInfo.origDisasm.push_back(mipsDis); - } - -#if PPSSPP_ARCH(ARM) - debugInfo.targetDisasm = DisassembleArm2(block->normalEntry, block->codeSize); -#elif PPSSPP_ARCH(ARM64) - debugInfo.targetDisasm = DisassembleArm64(block->normalEntry, block->codeSize); -#elif PPSSPP_ARCH(X86) || PPSSPP_ARCH(AMD64) - debugInfo.targetDisasm = DisassembleX86(block->normalEntry, block->codeSize); -#elif PPSSPP_ARCH(RISCV64) - debugInfo.targetDisasm = DisassembleRV64(block->normalEntry, block->codeSize); -#elif PPSSPP_ARCH(LOONGARCH64) - debugInfo.targetDisasm = DisassembleLA64(block->normalEntry, block->codeSize); -#endif - return debugInfo; -} diff --git a/Core/MIPS/JitCommon/JitBlockCache.h b/Core/MIPS/JitCommon/JitBlockCache.h index a39f37187b..f9ecb7b672 100644 --- a/Core/MIPS/JitCommon/JitBlockCache.h +++ b/Core/MIPS/JitCommon/JitBlockCache.h @@ -18,20 +18,10 @@ #pragma once #include -#include -#include -#include #include +#include -#include "ppsspp_config.h" #include "Common/CommonTypes.h" -#include "Common/CodeBlock.h" -#include "Core/MIPS/MIPS.h" - -// Can probably reduce to 2 now that block continuation is gone. -const int MAX_JIT_BLOCK_EXITS = 4; - -constexpr bool JIT_USE_COMPILEDHASH = true; struct BlockCacheStats { int numBlocks; @@ -42,41 +32,6 @@ struct BlockCacheStats { u32 maxBloatBlock; }; -enum class DestroyType { - DESTROY, - INVALIDATE, - // Skips jit unlink, since it'll be poisoned anyway. - CLEAR, -}; - -// We should be careful not to access these block structures during runtime as they are large. -// Fine to mess with them at block compile time though. -struct JitBlock { - bool ContainsAddress(u32 address) const; - void DoIntegrityCheck(u32 emAddress, int blockNum, const char *reason) const; - - const u8 *checkedEntry; // const, we have to translate to writable. - const u8 *normalEntry; - - u8 *exitPtrs[MAX_JIT_BLOCK_EXITS]; // to be able to rewrite the exit jump - u32 exitAddress[MAX_JIT_BLOCK_EXITS]; // 0xFFFFFFFF == unknown - u32 sentinel; - - u32 originalAddress; - MIPSOpcode originalFirstOpcode; //to be able to restore - - uint64_t compiledHash; - - u32 codeSize; // in bytes, so it doesn't fit in a u16 for a long block - u16 originalSize; // in instructions, bounded by MAX_BLOCK_INSTRUCTIONS - u16 blockNum; - - bool invalid; - bool linkStatus[MAX_JIT_BLOCK_EXITS]; -}; - -typedef void (*CompiledCode)(); - struct JitBlockDebugInfo { uint32_t originalAddress; std::vector origDisasm; @@ -109,100 +64,3 @@ public: virtual ~JitBlockCacheDebugInterface() {} }; - -class JitBlockCache : public JitBlockCacheDebugInterface { -public: - JitBlockCache(MIPSState *mipsState, CodeBlockCommon *codeBlock); - ~JitBlockCache(); - - int AllocateBlock(u32 emAddress); - void FinalizeBlock(int block_num, bool block_link); - - void Clear(); - void Init(); - void Shutdown(); - void Reset(); - - bool IsFull() const; - void ComputeStats(BlockCacheStats &bcStats) const override; - - // Code Cache - JitBlock *GetBlock(int no) { return &blocks_[no]; } - const JitBlock *GetBlock(int no) const { return &blocks_[no]; } - - // Fast way to get a block. Only works on the first source-cpu instruction of a block. - int GetBlockNumberFromStartAddress(u32 em_address) const override; - - // slower, but can get numbers from within blocks, not just the first instruction. - // WARNING! WILL NOT WORK WITH JIT INLINING ENABLED (not yet a feature but will be soon) - // Returns a list of block numbers - only one block can start at a particular address, but they CAN overlap. - // This one is slow so should only be used for one-shots from the debugger UI, not for anything during runtime. - void GetBlockNumbersFromAddress(u32 em_address, std::vector *block_numbers) const; - // Similar to above, but only the first matching address. - int GetBlockNumberFromAddress(u32 em_address) const; - int GetBlockNumberFromShadowValue(u32 value) const; - - u32 GetAddressFromBlockPtr(const u8 *ptr) const; - - MIPSOpcode GetOriginalFirstOp(int block_num) const; - - bool RangeMayHaveBlocks(u32 start, u32 end) const; - - // DOES NOT WORK CORRECTLY WITH JIT INLINING - void InvalidateICache(u32 address, const u32 length); - void InvalidateChangedBlocks(); - void DestroyBlock(int block_num, DestroyType type); - - int GetNumBlocks() const override { return num_blocks_; } - bool IsValidBlock(int blockNum) const override { return blockNum >= 0 && blockNum < num_blocks_ && !blocks_[blockNum].invalid; } - JitBlockMeta GetBlockMeta(int blockNum) const override { - JitBlockMeta meta{}; - if (IsValidBlock(blockNum)) { - meta.valid = true; - meta.addr = blocks_[blockNum].originalAddress; - meta.sizeInBytes = blocks_[blockNum].originalSize; - } - return meta; - } - JitBlockProfileStats GetBlockProfileStats(int blockNum) const override { - return JitBlockProfileStats{}; - } - - static int GetBlockExitSize(); - - JitBlockDebugInfo GetBlockDebugInfo(int blockNum) const override; - - enum { - MAX_BLOCK_INSTRUCTIONS = 0x4000, - }; - -private: - void LinkBlockExits(int i); - void LinkBlock(int i); - void UnlinkBlock(int i); - - void AddBlockMap(int block_num); - void RemoveBlockMap(int block_num); - - // What the block shadow holds for a block: its normal entry's offset into the code space. - u32 GetShadowValueForBlock(int block_num) const; - - int num_blocks_ = 0; - CodeBlockCommon *codeBlock_; - JitBlock *blocks_ = nullptr; - std::unordered_multimap links_to_; - std::map, u32> block_map_; // (end_addr, start_addr) -> number - - enum { - JITBLOCK_RANGE_SCRATCH = 0, - JITBLOCK_RANGE_RAMBOTTOM = 1, - JITBLOCK_RANGE_RAMTOP = 2, - JITBLOCK_RANGE_COUNT = 3, - }; - std::pair blockMemRanges_[JITBLOCK_RANGE_COUNT]; - - enum { - // Where does this number come from? - MAX_NUM_BLOCKS = 65536 * 4 - }; -}; diff --git a/Core/MIPS/JitCommon/JitCommon.cpp b/Core/MIPS/JitCommon/JitCommon.cpp index 1a065d9935..06c1494bf9 100644 --- a/Core/MIPS/JitCommon/JitCommon.cpp +++ b/Core/MIPS/JitCommon/JitCommon.cpp @@ -48,8 +48,6 @@ #include "../RiscV/RiscVJit.h" #elif PPSSPP_ARCH(LOONGARCH64) #include "../LoongArch64/LoongArch64Jit.h" -#else -#include "../fake/FakeJit.h" #endif namespace MIPSComp { @@ -115,7 +113,8 @@ namespace MIPSComp { #elif PPSSPP_ARCH(LOONGARCH64) return new MIPSComp::LoongArch64Jit(mipsState); #else - return new MIPSComp::FakeJit(mipsState); + // No native JIT for this architecture. + return new MIPSComp::IRJit(mipsState, false); #endif } diff --git a/Core/MIPS/JitCommon/JitCommon.h b/Core/MIPS/JitCommon/JitCommon.h index 4dc09a892c..ea17846606 100644 --- a/Core/MIPS/JitCommon/JitCommon.h +++ b/Core/MIPS/JitCommon/JitCommon.h @@ -31,8 +31,6 @@ std::vector DisassembleX86(const u8 *data, int size); std::vector DisassembleRV64(const u8 *data, int size); std::vector DisassembleLA64(const u8 *data, int size); -struct JitBlock; -class JitBlockCache; class JitBlockCacheDebugInterface; class PointerWrap; @@ -127,7 +125,6 @@ namespace MIPSComp { } virtual const u8 *GetDispatcher() const = 0; virtual const u8 *GetCrashHandler() const = 0; - virtual JitBlockCache *GetBlockCache() = 0; virtual JitBlockCacheDebugInterface *GetBlockCacheDebugInterface() = 0; virtual void InvalidateCacheAt(u32 em_address, int length = 4) = 0; virtual void DoState(PointerWrap &p) = 0; @@ -138,11 +135,6 @@ namespace MIPSComp { // What the block shadow holds for a replacement hook without a compiled block. The // dispatcher has to send this to the compiler. virtual u32 GetBlockShadowHookValue() const { return Memory::BLOCK_SHADOW_HOOK_NO_JIT; } - - // Block linking. This may need to work differently for whole-function JITs and stuff - // like that. - virtual void LinkBlock(u8 *exitPoint, const u8 *entryPoint) = 0; - virtual void UnlinkBlock(u8 *checkedEntry, u32 originalAddress) = 0; }; typedef void (MIPSFrontendInterface::*MIPSCompileFunc)(MIPSOpcode opcode); diff --git a/Core/MIPS/JitCommon/JitState.cpp b/Core/MIPS/JitCommon/JitState.cpp index 458fdb56f6..c77b6ab0ee 100644 --- a/Core/MIPS/JitCommon/JitState.cpp +++ b/Core/MIPS/JitCommon/JitState.cpp @@ -19,28 +19,11 @@ #include "Common/CPUDetect.h" #include "Core/Config.h" #include "Core/MIPS/JitCommon/JitState.h" -#include "Core/MIPS/JitCommon/JitBlockCache.h" #include "Core/MemMap.h" #include "Common/MemoryUtil.h" namespace MIPSComp { -void JitState::Begin(JitBlock *block) { - cancel = false; - blockStart = block->originalAddress; - compilerPC = block->originalAddress; - initialBlockSize = 0; - nextExit = 0; - downcountAmount = 0; - curBlock = block; - compiling = true; - inDelaySlot = false; - blockWrotePrefixes = false; - afterOp = JitState::AFTER_NONE; - kernelMode = Memory::IsKernelCodeAddress(block->originalAddress); - PrefixStart(); -} - JitOptions::JitOptions() { disableFlags = (JitDisable)g_Config.uJitDisableFlags; @@ -61,11 +44,7 @@ void JitState::Begin(JitBlock *block) { // We can get block linking to work with W^X by doing even more unprotect/re-protect, but let's try without first. // enableBlocklink = !PlatformIsWXExclusive(); // Revert to this line if block linking is slow in W^X mode -#if PPSSPP_ARCH(MIPS) - enableBlocklink = false; -#else enableBlocklink = !Disabled(JitDisable::BLOCKLINK); -#endif useStaticAlloc = false; enablePointerify = false; #if PPSSPP_ARCH(ARM64) || PPSSPP_ARCH(RISCV64) || PPSSPP_ARCH(LOONGARCH64) diff --git a/Core/MIPS/JitCommon/JitState.h b/Core/MIPS/JitCommon/JitState.h index a5f2725dd4..65c7b57c24 100644 --- a/Core/MIPS/JitCommon/JitState.h +++ b/Core/MIPS/JitCommon/JitState.h @@ -23,22 +23,8 @@ #include "Common/Log.h" #include "Core/MIPS/MIPS.h" -struct JitBlock; -class JitBlockCache; - namespace MIPSComp { - enum CompileDelaySlotFlags { - // Easy, nothing extra. - DELAYSLOT_NICE = 0, - // Flush registers after delay slot. - DELAYSLOT_FLUSH = 1, - // Preserve flags. - DELAYSLOT_SAFE = 2, - // Flush registers after and preserve flags. - DELAYSLOT_SAFE_FLUSH = DELAYSLOT_FLUSH | DELAYSLOT_SAFE, - }; - struct JitState { enum PrefixState { PREFIX_UNKNOWN = 0x00, @@ -47,29 +33,18 @@ namespace MIPSComp { PREFIX_KNOWN_DIRTY = 0x11, }; - enum AfterOp { - AFTER_NONE = 0x00, - AFTER_CORE_STATE = 0x01, - }; - u32 compilerPC; u32 blockStart; - u32 initialBlockSize; - int nextExit; bool cancel; bool inDelaySlot; bool kernelMode; // Changes what instructions are allowed. - // See JitState::AfterOp for values. - int afterOp; int downcountAmount; int numInstructions; bool compiling; // TODO: get rid of this in favor of using analysis results to determine end of block bool hadBreakpoints; - JitBlock *curBlock; u8 hasSetRounding = 0; u8 lastSetRounding = 0; - const u8 *currentRoundingFunc = nullptr; // VFPU prefix magic bool startDefaultPrefix = true; @@ -81,8 +56,6 @@ namespace MIPSComp { PrefixState prefixTFlag = PREFIX_UNKNOWN; PrefixState prefixDFlag = PREFIX_UNKNOWN; - void Begin(JitBlock *block); - void PrefixStart() { if (startDefaultPrefix) { EatPrefix(); diff --git a/Core/MIPS/LoongArch64/LoongArch64Jit.cpp b/Core/MIPS/LoongArch64/LoongArch64Jit.cpp index eb9e56570e..dd2db5cc27 100644 --- a/Core/MIPS/LoongArch64/LoongArch64Jit.cpp +++ b/Core/MIPS/LoongArch64/LoongArch64Jit.cpp @@ -16,6 +16,7 @@ // https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/. #include +#include #include "Core/MemMap.h" #include "Core/MIPS/MIPSTables.h" #include "Core/MIPS/LoongArch64/LoongArch64Jit.h" diff --git a/Core/MIPS/RiscV/RiscVJit.cpp b/Core/MIPS/RiscV/RiscVJit.cpp index 7d9d9fe7a1..4cc2bf72de 100644 --- a/Core/MIPS/RiscV/RiscVJit.cpp +++ b/Core/MIPS/RiscV/RiscVJit.cpp @@ -16,6 +16,7 @@ // https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/. #include +#include #include "Core/MemMap.h" #include "Core/MIPS/MIPSTables.h" #include "Core/MIPS/RiscV/RiscVJit.h" diff --git a/Core/MIPS/fake/FakeJit.cpp b/Core/MIPS/fake/FakeJit.cpp deleted file mode 100644 index 58d08260ba..0000000000 --- a/Core/MIPS/fake/FakeJit.cpp +++ /dev/null @@ -1,227 +0,0 @@ -// Copyright (c) 2012- PPSSPP Project. - -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, version 2.0 or later versions. - -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License 2.0 for more details. - -// A copy of the GPL 2.0 should have been included with the program. -// If not, see http://www.gnu.org/licenses/ - -// Official git repository and contact information can be found at -// https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/. - -#include "Common/Serialize/Serializer.h" -#include "Common/Serialize/SerializeFuncs.h" -#include "Core/Reporting.h" -#include "Core/Core.h" -#include "Core/CoreTiming.h" -#include "Core/Debugger/Breakpoints.h" -#include "Core/Debugger/SymbolMap.h" -#include "Core/MemMap.h" -#include "Core/MIPS/MIPS.h" -#include "Core/MIPS/MIPSCodeUtils.h" -#include "Core/MIPS/Interpreter.h" -#include "Core/MIPS/MIPSTables.h" -#include "Core/HLE/ReplaceTables.h" - -#include "FakeEmitter.h" -#include "FakeJit.h" -#include "CPUDetect.h" - -void DisassembleFake(const u8 *data, int size) { -} - -namespace MIPSComp -{ - -FakeJit::FakeJit(MIPSState *mipsState) : blocks(mipsState, this), mips_(mipsState), js() -{ - logBlocks = 0; - dontLogBlocks = 0; - blocks.Init(); -} - -void FakeJit::DoState(PointerWrap &p) { - auto s = p.Section("Jit", 1, 2); - if (!s) - return; - - Do(p, js.startDefaultPrefix); - if (s >= 2) { - Do(p, js.hasSetRounding); - if (p.mode == PointerWrap::MODE_READ) { - js.lastSetRounding = 0; - } - } else { - js.hasSetRounding = 1; - } - - // The debugger sets this so that "go" on a breakpoint will actually... go. - // But if they load a state, we can end up hitting it by mistake, since it's based on PC and ticks. - g_breakpoints.SetSkipFirst(0); -} - -// This is here so the savestate matches between jit and non-jit. -void FakeJit::DoDummyState(PointerWrap &p) -{ - auto s = p.Section("FakeJit", 1, 2); - if (!s) - return; - - bool dummy = false; - Do(p, dummy); - if (s >= 2) { - dummy = true; - Do(p, dummy); - } -} - -void FakeJit::FlushAll() -{ - //gpr.FlushAll(); - //fpr.FlushAll(); - FlushPrefixV(); -} - -void FakeJit::FlushPrefixV() -{ -} - -void FakeJit::ClearCache() -{ - blocks.Clear(); - ClearCodeSpace(0); - //GenerateFixedCode(); -} - -void FakeJit::InvalidateCacheAt(u32 em_address, int length) { - if (blocks.RangeMayHaveBlocks(em_address, em_address + length)) { - blocks.InvalidateICache(em_address, length); - } -} - -void FakeJit::EatInstruction(MIPSOpcode op) { - MIPSInfo info = MIPSGetInfo(op); - if (info & DELAYSLOT) { - ERROR_LOG_REPORT_ONCE(ateDelaySlot, Log::JIT, "Ate a branch op."); - } - if (js.inDelaySlot) { - ERROR_LOG_REPORT_ONCE(ateInDelaySlot, Log::JIT, "Ate an instruction inside a delay slot."); - } - - js.numInstructions++; - js.compilerPC += 4; - js.downcountAmount += MIPSGetInstructionCycleEstimate(op); -} - -void FakeJit::CompileDelaySlot(int flags) -{ -} - - -void FakeJit::Compile(u32 em_address) { -} - -void FakeJit::RunLoopUntil(u64 globalticks) { - MIPSInterpret_RunUntil(currentMIPS, globalticks); -} - -void FakeJit::DoJit(u32 em_address, JitBlock *b) { - _assert_(false); -} - -bool FakeJit::DescribeCodePtr(const u8 *ptr, std::string &name) -{ - // TODO: Not used by anything yet. - return false; -} - -void FakeJit::Comp_ReplacementFunc(MIPSOpcode op) -{ -} - -void FakeJit::Comp_Generic(MIPSOpcode op) -{ - FlushAll(); - MIPSInterpretFunc func = MIPSGetInterpretFunc(op); - if (func) - { - SaveDowncount(); - RestoreDowncount(); - } - - const MIPSInfo info = MIPSGetInfo(op); - if ((info & IS_VFPU) != 0 && (info & VFPU_NO_PREFIX) == 0) - { - // If it does eat them, it'll happen in MIPSCompileOp(). - if ((info & OUT_EAT_PREFIX) == 0) - js.PrefixUnknown(); - } -} - -void FakeJit::MovFromPC(FakeReg r) { -} - -void FakeJit::MovToPC(FakeReg r) { -} - -void FakeJit::SaveDowncount() { -} - -void FakeJit::RestoreDowncount() { -} - -void FakeJit::WriteDownCount(int offset) { -} - -// Abuses R2 -void FakeJit::WriteDownCountR(FakeReg reg) { -} - -void FakeJit::RestoreRoundingMode(bool force) { -} - -void FakeJit::ApplyRoundingMode(bool force) { -} - -void FakeJit::UpdateRoundingMode() { -} - -void FakeJit::WriteExit(u32 destination, int exit_num) -{ -} - -void FakeJit::WriteExitDestInR(FakeReg Reg) -{ -} - -void FakeJit::WriteSyscallExit() -{ -} - -#define _RS ((op>>21) & 0x1F) -#define _RT ((op>>16) & 0x1F) -#define _RD ((op>>11) & 0x1F) -#define _FS ((op>>11) & 0x1F) -#define _FT ((op>>16) & 0x1F) -#define _FD ((op>>6) & 0x1F) -#define _POS ((op>>6) & 0x1F) -#define _SIZE ((op>>11) & 0x1F) - -//memory regions: -// -// 08-0A -// 48-4A -// 04-05 -// 44-45 -// mov eax, addrreg - // shr eax, 28 -// mov eax, [table+eax] -// mov dreg, [eax+offreg] - -} diff --git a/Core/MIPS/fake/FakeJit.h b/Core/MIPS/fake/FakeJit.h deleted file mode 100644 index 8f325cccb8..0000000000 --- a/Core/MIPS/fake/FakeJit.h +++ /dev/null @@ -1,177 +0,0 @@ -// Copyright (c) 2012- PPSSPP Project. - -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, version 2.0 or later versions. - -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License 2.0 for more details. - -// A copy of the GPL 2.0 should have been included with the program. -// If not, see http://www.gnu.org/licenses/ - -// Official git repository and contact information can be found at -// https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/. - -#pragma once - -#include "Common/FakeEmitter.h" -#include "Core/MIPS/JitCommon/JitBlockCache.h" -#include "Core/MIPS/JitCommon/JitState.h" -#include "Core/MIPS/JitCommon/JitCommon.h" -#include "../MIPSVFPUUtils.h" - -#ifndef offsetof -#include "stddef.h" -#endif - -namespace MIPSComp { - -typedef int FakeReg; - -class FakeJit : public FakeGen::FakeXCodeBlock, public JitInterface, public MIPSFrontendInterface { -public: - FakeJit(MIPSState *mipsState); - - void DoState(PointerWrap &p) override; - static void DoDummyState(PointerWrap &p); - - const JitOptions &GetJitOptions() { return jo; } - - void Comp_Generic(MIPSOpcode op) override; - - void RunLoopUntil(u64 globalticks) override; - - void Compile(u32 em_address) override; // Compiles a block at current MIPS PC - void DoJit(u32 em_address, JitBlock *b); - - const u8 *GetCrashHandler() const override { return nullptr; } - bool CodeInRange(const u8 *ptr) const override { return IsInSpace(ptr); } - bool DescribeCodePtr(const u8 *ptr, std::string &name) override; - - void CompileDelaySlot(int flags); - void EatInstruction(MIPSOpcode op); - - void Comp_ReplacementFunc(MIPSOpcode op) override; - - // Ops - void Comp_ITypeMem(MIPSOpcode op) override {} - void Comp_StoreSync(MIPSOpcode op) override {} - void Comp_Cache(MIPSOpcode op) override {} - - void Comp_RelBranch(MIPSOpcode op) override {} - void Comp_RelBranchRI(MIPSOpcode op) override {} - void Comp_FPUBranch(MIPSOpcode op) override {} - void Comp_FPULS(MIPSOpcode op) override {} - void Comp_FPUComp(MIPSOpcode op) override {} - void Comp_Jump(MIPSOpcode op) override {} - void Comp_JumpReg(MIPSOpcode op) override {} - void Comp_Syscall(MIPSOpcode op) override {} - void Comp_Break(MIPSOpcode op) override {} - - void Comp_IType(MIPSOpcode op) override {} - void Comp_RType2(MIPSOpcode op) override {} - void Comp_RType3(MIPSOpcode op) override {} - void Comp_ShiftType(MIPSOpcode op) override {} - void Comp_Allegrex(MIPSOpcode op) override {} - void Comp_Allegrex2(MIPSOpcode op) override {} - void Comp_VBranch(MIPSOpcode op) override {} - void Comp_MulDivType(MIPSOpcode op) override {} - void Comp_Special3(MIPSOpcode op) override {} - - void Comp_FPU3op(MIPSOpcode op) override {} - void Comp_FPU2op(MIPSOpcode op) override {} - void Comp_mxc1(MIPSOpcode op) override {} - - void Comp_DoNothing(MIPSOpcode op) override {} - - void Comp_SV(MIPSOpcode op) override {} - void Comp_SVQ(MIPSOpcode op) override {} - void Comp_VPFX(MIPSOpcode op) override {} - void Comp_VVectorInit(MIPSOpcode op) override {} - void Comp_VMatrixInit(MIPSOpcode op) override {} - void Comp_VDot(MIPSOpcode op) override {} - void Comp_VecDo3(MIPSOpcode op) override {} - void Comp_VV2Op(MIPSOpcode op) override {} - void Comp_Mftv(MIPSOpcode op) override {} - void Comp_Vmfvc(MIPSOpcode op) override {} - void Comp_Vmtvc(MIPSOpcode op) override {} - void Comp_Vmmov(MIPSOpcode op) override {} - void Comp_VScl(MIPSOpcode op) override {} - void Comp_Vmmul(MIPSOpcode op) override {} - void Comp_Vmscl(MIPSOpcode op) override {} - void Comp_Vtfm(MIPSOpcode op) override {} - void Comp_VHdp(MIPSOpcode op) override {} - void Comp_VCrs(MIPSOpcode op) override {} - void Comp_VDet(MIPSOpcode op) override {} - void Comp_Vi2x(MIPSOpcode op) override {} - void Comp_Vx2i(MIPSOpcode op) override {} - void Comp_Vf2i(MIPSOpcode op) override {} - void Comp_Vi2f(MIPSOpcode op) override {} - void Comp_Vh2f(MIPSOpcode op) override {} - void Comp_Vcst(MIPSOpcode op) override {} - void Comp_Vhoriz(MIPSOpcode op) override {} - void Comp_VRot(MIPSOpcode op) override {} - void Comp_VIdt(MIPSOpcode op) override {} - void Comp_Vcmp(MIPSOpcode op) override {} - void Comp_Vcmov(MIPSOpcode op) override {} - void Comp_Viim(MIPSOpcode op) override {} - void Comp_Vfim(MIPSOpcode op) override {} - void Comp_VCrossQuat(MIPSOpcode op) override {} - void Comp_Vsgn(MIPSOpcode op) override {} - void Comp_Vocp(MIPSOpcode op) override {} - void Comp_ColorConv(MIPSOpcode op) override {} - void Comp_Vbfy(MIPSOpcode op) override {} - - int Replace_fabsf() override { return 0; } - - JitBlockCache *GetBlockCache() override { return &blocks; } - JitBlockCacheDebugInterface *GetBlockCacheDebugInterface() override { return &blocks; } - - void ClearCache() override; - void InvalidateCacheAt(u32 em_address, int length = 4) override; - void UpdateFCR31() override {} - - const u8 *GetDispatcher() const override { - return nullptr; - } - - void LinkBlock(u8 *exitPoint, const u8 *checkedEntry) override {} - void UnlinkBlock(u8 *checkedEntry, u32 originalAddress) override {} - - void EatPrefix() override { js.EatPrefix(); } - -private: - void GenerateFixedCode(); - void FlushAll(); - void FlushPrefixV(); - - void WriteDownCount(int offset = 0); - void WriteDownCountR(FakeReg reg); - void RestoreRoundingMode(bool force = false); - void ApplyRoundingMode(bool force = false); - void UpdateRoundingMode(); - void MovFromPC(FakeReg r); - void MovToPC(FakeReg r); - - void SaveDowncount(); - void RestoreDowncount(); - - void WriteExit(u32 destination, int exit_num); - void WriteExitDestInR(FakeReg Reg); - void WriteSyscallExit(); - - JitBlockCache blocks; - JitOptions jo; - JitState js; - - MIPSState *mips_; - - int dontLogBlocks; - int logBlocks; -}; - -} // namespace MIPSComp - diff --git a/Core/MIPS/x86/X64IRJit.cpp b/Core/MIPS/x86/X64IRJit.cpp index c391e97985..d9c1195c8d 100644 --- a/Core/MIPS/x86/X64IRJit.cpp +++ b/Core/MIPS/x86/X64IRJit.cpp @@ -19,6 +19,7 @@ #if PPSSPP_ARCH(X86) || PPSSPP_ARCH(AMD64) #include +#include #include "Common/StringUtils.h" #include "Core/MemMap.h" #include "Core/MIPS/MIPSTables.h" diff --git a/GPU/Common/VertexDecoderCommon.cpp b/GPU/Common/VertexDecoderCommon.cpp index 4dfee2a768..eed7049be8 100644 --- a/GPU/Common/VertexDecoderCommon.cpp +++ b/GPU/Common/VertexDecoderCommon.cpp @@ -1629,6 +1629,7 @@ std::string VertexDecoder::GetString(DebugShaderStringType stringType) const { } } +#ifdef VERTEXDECODER_JIT_BACKEND VertexDecoderJitCache::VertexDecoderJitCache() #if PPSSPP_ARCH(ARM64) : fp(this) @@ -1653,6 +1654,7 @@ VertexDecoderJitCache::VertexDecoderJitCache() void VertexDecoderJitCache::Clear() { ClearCodeSpace(0); } +#endif struct StepFunctionNameEntry { StepFunction func; diff --git a/GPU/Common/VertexDecoderCommon.h b/GPU/Common/VertexDecoderCommon.h index d11e74f023..3d63dddad1 100644 --- a/GPU/Common/VertexDecoderCommon.h +++ b/GPU/Common/VertexDecoderCommon.h @@ -39,8 +39,6 @@ #include "Common/RiscVEmitter.h" #elif PPSSPP_ARCH(LOONGARCH64) #include "Common/LoongArch64Emitter.h" -#else -#include "Common/FakeEmitter.h" #endif // Keep this in 4 bits. @@ -432,13 +430,13 @@ private: #endif }; #else -class VertexDecoderJitCache : public FakeGen::FakeXCodeBlock { +// No vertex decoder JIT for this architecture. +class VertexDecoderJitCache { public: - VertexDecoderJitCache(); - JittedVertexDecoder Compile(const VertexDecoder &dec, int32_t *jittedSize) { return nullptr; } - void Clear(); + void Clear() {} + bool IsInSpace(const u8 *ptr) const { return false; } }; #endif diff --git a/UI/ImDebugger/ImDebugger.cpp b/UI/ImDebugger/ImDebugger.cpp index 8f32259f25..a824729edd 100644 --- a/UI/ImDebugger/ImDebugger.cpp +++ b/UI/ImDebugger/ImDebugger.cpp @@ -848,8 +848,6 @@ static void DrawInternals(ImConfig &cfg) { ImGui::Text("Base pointer: %p", Memory::base); ImGui::Text("Main memory size: %08x", Memory::g_MemorySize); if (MIPSComp::jit) { - const JitBlockCache *bc = MIPSComp::jit->GetBlockCache(); - ImGui::Text("JIT block cache: %p", bc->GetBlock(0)); ImGui::Text("JIT code cache: %p", MIPSComp::jit->GetCodeBase()); ImGui::Text("MIPS state: %p", currentMIPS); } diff --git a/UWP/CoreUWP/CoreUWP.vcxproj b/UWP/CoreUWP/CoreUWP.vcxproj index 59badf30a4..b20455fa64 100644 --- a/UWP/CoreUWP/CoreUWP.vcxproj +++ b/UWP/CoreUWP/CoreUWP.vcxproj @@ -587,7 +587,6 @@ - diff --git a/UWP/CoreUWP/CoreUWP.vcxproj.filters b/UWP/CoreUWP/CoreUWP.vcxproj.filters index 9d0f9ce361..a0d6e0a145 100644 --- a/UWP/CoreUWP/CoreUWP.vcxproj.filters +++ b/UWP/CoreUWP/CoreUWP.vcxproj.filters @@ -214,7 +214,6 @@ - diff --git a/android/jni/Android.mk b/android/jni/Android.mk index dd00926e83..9a20982d63 100644 --- a/android/jni/Android.mk +++ b/android/jni/Android.mk @@ -844,7 +844,6 @@ EXEC_AND_LIB_FILES := \ $(SRC)/Core/FileSystems/VirtualDiscFileSystem.cpp \ $(SRC)/Core/FileSystems/tlzrc.cpp \ $(SRC)/Core/MIPS/JitCommon/JitCommon.cpp \ - $(SRC)/Core/MIPS/JitCommon/JitBlockCache.cpp \ $(SRC)/Core/MIPS/JitCommon/JitState.cpp \ $(SRC)/Core/Util/AtracTrack.cpp \ $(SRC)/Core/Util/AudioFormat.cpp \ diff --git a/libretro/Makefile.common b/libretro/Makefile.common index abb9c6accb..3d7282e419 100644 --- a/libretro/Makefile.common +++ b/libretro/Makefile.common @@ -858,7 +858,6 @@ SOURCES_CXX += \ $(COREDIR)/Loaders.cpp \ $(COREDIR)/MIPS/JitCommon/JitCommon.cpp \ $(COREDIR)/MIPS/JitCommon/JitState.cpp \ - $(COREDIR)/MIPS/JitCommon/JitBlockCache.cpp \ $(COREDIR)/MIPS/IR/IRAnalysis.cpp \ $(COREDIR)/MIPS/IR/IRCompALU.cpp \ $(COREDIR)/MIPS/IR/IRCompBranch.cpp \