From 34bfe93ea575a32f9f0d2c9ac0ef2371f533532d Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sun, 23 Jul 2023 08:15:15 -0700 Subject: [PATCH] riscv: Fix block lookup issues. --- Core/MIPS/RiscV/RiscVAsm.cpp | 47 +++++++++++++++++++++++------ Core/MIPS/RiscV/RiscVCompBranch.cpp | 2 +- Core/MIPS/RiscV/RiscVCompSystem.cpp | 2 +- Core/MIPS/RiscV/RiscVJit.cpp | 14 +++++++-- Core/MIPS/RiscV/RiscVJit.h | 2 ++ 5 files changed, 52 insertions(+), 15 deletions(-) diff --git a/Core/MIPS/RiscV/RiscVAsm.cpp b/Core/MIPS/RiscV/RiscVAsm.cpp index 8232b0a286..7fe1ce8b53 100644 --- a/Core/MIPS/RiscV/RiscVAsm.cpp +++ b/Core/MIPS/RiscV/RiscVAsm.cpp @@ -35,7 +35,7 @@ static const bool enableDisasm = false; static void ShowPC(u32 downcount, void *membase, void *jitbase) { static int count = 0; if (currentMIPS) { - ERROR_LOG(JIT, "ShowPC : %08x Downcount : %08x %d %p %p", currentMIPS->pc, downcount, count, membase, jitbase); + ERROR_LOG(JIT, "[%08x] ShowPC Downcount : %08x %d %p %p", currentMIPS->pc, downcount, count, membase, jitbase); } else { ERROR_LOG(JIT, "Universe corrupt?"); } @@ -44,6 +44,16 @@ static void ShowPC(u32 downcount, void *membase, void *jitbase) { count++; } +static void ShowBlockError(int type) { + if (type == 1) { + ERROR_LOG(JIT, "[%08x] ShowBlockError: block num was out of range in emuhack", currentMIPS->pc); + } else if (type == 2) { + ERROR_LOG(JIT, "[%08x] ShowBlockError: block num pointed to null jitblock", currentMIPS->pc); + } else { + ERROR_LOG(JIT, "[%08x] ShowBlockError: invalid error type", currentMIPS->pc); + } +} + void RiscVJit::GenerateFixedCode(const JitOptions &jo) { BeginWrite(GetMemoryProtectPageSize()); const u8 *start = AlignCodePage(); @@ -197,20 +207,37 @@ void RiscVJit::GenerateFixedCode(const JitOptions &jo) { SRLI(SCRATCH2, SCRATCH1, 24); // We're in other words comparing to the top 8 bits of MIPS_EMUHACK_OPCODE by subtracting. ADDI(SCRATCH2, SCRATCH2, -(MIPS_EMUHACK_OPCODE >> 24)); - FixupBranch skipJump = BNE(SCRATCH2, R_ZERO); + FixupBranch needsCompile = BNE(SCRATCH2, R_ZERO); // Use a wall to mask by 0x00FFFFFF and extract the block number. SLLI(SCRATCH1, SCRATCH1, XLEN - 24); // But actually, we want * 8, so skip shifting back just a bit. _assert_msg_(sizeof(blockStartAddrs_[0]) == 8, "RiscVAsm currently assumes pointers are 64-bit"); SRLI(SCRATCH1, SCRATCH1, XLEN - 24 - 3); - ADD(SCRATCH1, JITBASEREG, SCRATCH1); - // TODO: Consider replacing the block nums after all, just trying to use IR block cache. - LD(SCRATCH1, SCRATCH1, 0); - // TODO: This is ugly, but fixes a crash in LBP. May be a copied emuhack? - FixupBranch needCompile = BEQ(SCRATCH1, R_ZERO); - JR(SCRATCH1); - SetJumpTarget(needCompile); - SetJumpTarget(skipJump); + if (enableDebug) { + // Let's do some extra validation of the block number in debug mode for testing. + + LI(SCRATCH2, MAX_ALLOWED_JIT_BLOCKS * 8); + FixupBranch highBlockNum = BGEU(SCRATCH1, SCRATCH2); + ADD(SCRATCH1, JITBASEREG, SCRATCH1); + // TODO: Consider replacing the block nums after all, just trying to use IR block cache. + LD(SCRATCH1, SCRATCH1, 0); + LI(SCRATCH2, 2); + FixupBranch invalidBlockNum = BEQ(SCRATCH1, R_ZERO); + JR(SCRATCH1); + + SetJumpTarget(highBlockNum); + LI(SCRATCH2, 1); + SetJumpTarget(invalidBlockNum); + + MV(X10, SCRATCH2); + QuickCallFunction(&ShowBlockError); + } else { + ADD(SCRATCH1, JITBASEREG, SCRATCH1); + // TODO: Consider replacing the block nums after all, just trying to use IR block cache. + LD(SCRATCH1, SCRATCH1, 0); + JR(SCRATCH1); + } + SetJumpTarget(needsCompile); // No block found, let's jit. We don't need to save static regs, they're all callee saved. RestoreRoundingMode(true); diff --git a/Core/MIPS/RiscV/RiscVCompBranch.cpp b/Core/MIPS/RiscV/RiscVCompBranch.cpp index b3e4247df5..d26a52bdd2 100644 --- a/Core/MIPS/RiscV/RiscVCompBranch.cpp +++ b/Core/MIPS/RiscV/RiscVCompBranch.cpp @@ -19,7 +19,7 @@ #include "Core/MIPS/RiscV/RiscVJit.h" #include "Core/MIPS/RiscV/RiscVRegCache.h" -// This file contains compilation for exits, syscalls, and related. +// This file contains compilation for exits. // // All functions should have CONDITIONAL_DISABLE, so we can narrow things down to a file quickly. // Currently known non working ones should have DISABLE. No flags because that's in IR already. diff --git a/Core/MIPS/RiscV/RiscVCompSystem.cpp b/Core/MIPS/RiscV/RiscVCompSystem.cpp index d097915d0c..6c3bd07f78 100644 --- a/Core/MIPS/RiscV/RiscVCompSystem.cpp +++ b/Core/MIPS/RiscV/RiscVCompSystem.cpp @@ -19,7 +19,7 @@ #include "Core/MIPS/RiscV/RiscVJit.h" #include "Core/MIPS/RiscV/RiscVRegCache.h" -// This file contains compilation for basic PC/downcount accounting, debug funcs, etc. +// This file contains compilation for basic PC/downcount accounting, syscalls, debug funcs, etc. // // All functions should have CONDITIONAL_DISABLE, so we can narrow things down to a file quickly. // Currently known non working ones should have DISABLE. No flags because that's in IR already. diff --git a/Core/MIPS/RiscV/RiscVJit.cpp b/Core/MIPS/RiscV/RiscVJit.cpp index 054b80808e..64b24f0ee5 100644 --- a/Core/MIPS/RiscV/RiscVJit.cpp +++ b/Core/MIPS/RiscV/RiscVJit.cpp @@ -26,8 +26,6 @@ namespace MIPSComp { using namespace RiscVGen; using namespace RiscVJitConstants; -static constexpr int MAX_ALLOWED_JIT_BLOCKS = 262144; - RiscVJit::RiscVJit(MIPSState *mipsState) : IRJit(mipsState), gpr(mipsState, &jo) { // Automatically disable incompatible options. if (((intptr_t)Memory::base & 0x00000000FFFFFFFFUL) != 0) { @@ -39,6 +37,7 @@ RiscVJit::RiscVJit(MIPSState *mipsState) : IRJit(mipsState), gpr(mipsState, &jo) // TODO: Consider replacing block num method form IRJit - this is 2MB. blockStartAddrs_ = new const u8 *[MAX_ALLOWED_JIT_BLOCKS]; + memset(blockStartAddrs_, 0, sizeof(blockStartAddrs_[0]) * MAX_ALLOWED_JIT_BLOCKS); gpr.Init(this); // TODO: fpr @@ -65,7 +64,16 @@ bool RiscVJit::CompileBlock(u32 em_address, std::vector &instructions, u // TODO: Block linking, checked entries and such. - int block_num = blocks_.GetBlockNumberFromStartAddress(em_address); + int block_num; + if (preload) { + block_num = blocks_.GetBlockNumberFromStartAddress(em_address); + } else { + u32 first_inst = Memory::ReadUnchecked_U32(em_address); + _assert_msg_(MIPS_IS_RUNBLOCK(first_inst), "Should've written an emuhack"); + + block_num = first_inst & MIPS_EMUHACK_VALUE_MASK; + } + _assert_msg_(block_num >= 0 && block_num < MAX_ALLOWED_JIT_BLOCKS, "Bad block num"); _assert_msg_(blockStartAddrs_[block_num] == nullptr, "Block %d reused before clear", block_num); blockStartAddrs_[block_num] = GetCodePointer(); diff --git a/Core/MIPS/RiscV/RiscVJit.h b/Core/MIPS/RiscV/RiscVJit.h index f50d1b6782..97d1eaf603 100644 --- a/Core/MIPS/RiscV/RiscVJit.h +++ b/Core/MIPS/RiscV/RiscVJit.h @@ -111,6 +111,8 @@ private: RiscVRegCache gpr; + static constexpr int MAX_ALLOWED_JIT_BLOCKS = 262144; + const u8 *enterDispatcher_ = nullptr; const u8 *outerLoop_ = nullptr;