From 24fb2898e9092d169ccd312772d55930ba993214 Mon Sep 17 00:00:00 2001 From: iris Date: Fri, 29 May 2026 14:32:07 +0200 Subject: [PATCH] attempting more serious idle skipping --- src/backend/Core.cpp | 3 +-- src/backend/core/Interpreter.cpp | 7 ++--- src/backend/core/JITUtils.hpp | 3 ++- src/backend/core/interpreter/instructions.cpp | 10 ++++--- src/backend/core/jit/helpers.hpp | 27 +++++++++++++++++++ 5 files changed, 40 insertions(+), 10 deletions(-) diff --git a/src/backend/Core.cpp b/src/backend/Core.cpp index a2308ed..c8a6003 100644 --- a/src/backend/Core.cpp +++ b/src/backend/Core.cpp @@ -120,8 +120,7 @@ void Core::Run(const float volumeL, const float volumeR) { const u32 taken = StepCPU(); cycles += taken; frameCycles += taken; - if (cpuType == Interpreted) // because i will call it inside instead, when it's not the interpreter - StepRSP(taken); + StepRSP(taken); Scheduler::GetInstance().Tick(taken); } } diff --git a/src/backend/core/Interpreter.cpp b/src/backend/core/Interpreter.cpp index 81e4192..54ccaf6 100644 --- a/src/backend/core/Interpreter.cpp +++ b/src/backend/core/Interpreter.cpp @@ -152,7 +152,6 @@ u32 Interpreter::ExecuteCached() { // 0, making so the emulator halts cause the outer loop won't advance const auto blockCycles = line->cycles; for (u32 i = 0; i < line->len; i++) { - Core::GetInstance().StepRSP(1); if (!MaybeAdvance()) return i + 1; @@ -167,11 +166,13 @@ u32 Interpreter::ExecuteCached() { break; } - if (blockCycles == 0) { - panic("Cycles are 0!"); + if (line->idleSkip) { Scheduler::GetInstance().SkipToNext(); } + if (blockCycles == 0) + panic("Cycles are 0"); + return blockCycles; } diff --git a/src/backend/core/JITUtils.hpp b/src/backend/core/JITUtils.hpp index 9fe9f09..e63977a 100644 --- a/src/backend/core/JITUtils.hpp +++ b/src/backend/core/JITUtils.hpp @@ -10,10 +10,11 @@ static constexpr u32 MAX_INSTR_PER_BLOCK = 128; #define CACHE_GET_LINE(addr) ((addr & ((cachedState.MAX_LINES) - 1)) >> 2) struct CachedLine { + bool idleSkip = false; std::array code = {}; u32 len = 0; u32 cycles = 0; -} __attribute__((__packed__)); +}; template struct CachedBlock { diff --git a/src/backend/core/interpreter/instructions.cpp b/src/backend/core/interpreter/instructions.cpp index 62871d9..4259029 100644 --- a/src/backend/core/interpreter/instructions.cpp +++ b/src/backend/core/interpreter/instructions.cpp @@ -1,4 +1,5 @@ #include +#include #define check_signed_overflow(op1, op2, res) (((~((op1) ^ (op2)) & ((op1) ^ (res))) >> ((sizeof(res) * 8) - 1)) & 1) #define check_signed_underflow(op1, op2, res) (((((op1) ^ (op2)) & ((op1) ^ (res))) >> ((sizeof(res) * 8) - 1)) & 1) @@ -144,12 +145,13 @@ void Interpreter::branch(const bool cond, const s64 address) { } void Interpreter::branch_likely(const bool cond, const s64 address) { - if (cond) { - regs.delaySlot = true; - regs.nextPC = address; - } else { + if (!cond) { regs.SetPC64(regs.nextPC); + return; } + + regs.delaySlot = true; + regs.nextPC = address; } void Interpreter::b(const Instruction instr, const bool cond) { diff --git a/src/backend/core/jit/helpers.hpp b/src/backend/core/jit/helpers.hpp index 98ce5dc..39806fe 100644 --- a/src/backend/core/jit/helpers.hpp +++ b/src/backend/core/jit/helpers.hpp @@ -113,6 +113,33 @@ static bool IsBranchLikely(const Instruction instr) { } } +static bool IsBranch(const Instruction instr) { + switch (instr.opcode()) { + case Instruction::BEQ: + case Instruction::BNE: + case Instruction::BLEZ: + case Instruction::BGTZ: + return true; + case Instruction::REGIMM: + switch (instr.regimm()) { + case Instruction::BLTZ: + case Instruction::BGEZ: + case Instruction::BLTZAL: + case Instruction::BGEZAL: + return true; + default: + return false; + } + case Instruction::COP1: + if (instr.cop_rs() == 8 && (instr.cop_rt() == 0 || instr.cop_rt() == 1)) + return true; + + return false; + default: + return false; + } +} + #ifdef _WIN32 #define ARG1 rcx #define ARG2 rdx