diff --git a/parallel-rsp/parallel.cpp b/parallel-rsp/parallel.cpp index 614da2f..b3cf43d 100644 --- a/parallel-rsp/parallel.cpp +++ b/parallel-rsp/parallel.cpp @@ -83,7 +83,9 @@ extern "C" RSP::cpu.invalidate_imem(); // Run CPU until we either break or we need to fire an IRQ. - cycles = RSP::cpu.get_state().pc = *RSP::rsp.SP_PC_REG & 0xfff; + RSP::cpu.get_state().pc = *RSP::rsp.SP_PC_REG & 0xfff; + RSP::cpu.get_state().instruction_count = 0; + RSP::cpu.get_state().last_instruction_type = RSP::VU_INSTRUCTION; #ifdef INTENSE_DEBUG fprintf(stderr, "RUN TASK: %u\n", RSP::cpu.get_state().pc); @@ -100,15 +102,11 @@ extern "C" break; } - if (RSP::cpu.get_state().pc > cycles) - cycles = RSP::cpu.get_state().pc - cycles; - else - cycles = 0; *RSP::rsp.SP_PC_REG = 0x04001000 | (RSP::cpu.get_state().pc & 0xffc); // From CXD4. if (*RSP::rsp.SP_STATUS_REG & SP_STATUS_BROKE) - return cycles; + return RSP::cpu.get_state().instruction_count * 1.5; // Converting RCP clock rate to CPU clock rate else if (*RSP::cpu.get_state().cp0.irq & 1) RSP::rsp.CheckInterrupts(); else if (*RSP::rsp.SP_SEMAPHORE_REG != 0) // Semaphore lock fixes. @@ -120,7 +118,7 @@ extern "C" // CPU restarts with the correct SIGs. *RSP::rsp.SP_STATUS_REG &= ~SP_STATUS_HALT; - return cycles; + return RSP::cpu.get_state().instruction_count * 1.5; // Converting RCP clock rate to CPU clock rate } EXPORT m64p_error CALL PluginGetVersion(m64p_plugin_type *PluginType, int *PluginVersion, diff --git a/parallel-rsp/rsp_jit.cpp b/parallel-rsp/rsp_jit.cpp index a0e1c36..9b1c554 100644 --- a/parallel-rsp/rsp_jit.cpp +++ b/parallel-rsp/rsp_jit.cpp @@ -305,6 +305,12 @@ extern "C" printf(" ... Enter 0x%03x ... ", unsigned(pc & 0xffcu)); } #endif + static void add_instruction_count(CPUState *rsp, uint32_t instruction_type) + { + if (instruction_type == rsp->last_instruction_type) + ++rsp->instruction_count; + rsp->last_instruction_type = instruction_type; + } } void CPU::jit_save_indirect_register(jit_state_t *_jit, unsigned mips_register) @@ -864,6 +870,11 @@ void CPU::jit_instruction(jit_state_t *_jit, uint32_t pc, uint32_t instr, // VU if ((instr >> 25) == 0x25) { + regs.flush_register_window(_jit); + jit_begin_call(_jit); + jit_pushargr(JIT_REGISTER_STATE); + jit_pushargi(RSP::VU_INSTRUCTION); + jit_end_call(_jit, reinterpret_cast(add_instruction_count)); // VU instruction. COP2, and high bit of opcode is set. uint32_t op = instr & 63; uint32_t vd = (instr >> 6) & 31; @@ -896,6 +907,14 @@ void CPU::jit_instruction(jit_state_t *_jit, uint32_t pc, uint32_t instr, jit_end_call(_jit ,reinterpret_cast(vuop)); return; } + else + { + regs.flush_register_window(_jit); + jit_begin_call(_jit); + jit_pushargr(JIT_REGISTER_STATE); + jit_pushargi(RSP::SU_INSTRUCTION); + jit_end_call(_jit, reinterpret_cast(add_instruction_count)); + } // TODO: Meaningful register allocation. // For now, always flush register state to memory after an instruction for simplicity. diff --git a/parallel-rsp/state.hpp b/parallel-rsp/state.hpp index ce80dae..afb2ab0 100644 --- a/parallel-rsp/state.hpp +++ b/parallel-rsp/state.hpp @@ -117,6 +117,8 @@ struct alignas(64) CP2 struct CPUState { uint32_t pc = 0; + uint32_t instruction_count = 0; + uint32_t last_instruction_type = 0; uint32_t dirty_blocks = 0; static_assert(CODE_BLOCKS <= 32, "Code blocks must fit in 32-bit register."); @@ -141,6 +143,12 @@ enum ReturnMode MODE_CHECK_FLAGS = 4 }; +enum InstructionType +{ + VU_INSTRUCTION = 0, + SU_INSTRUCTION = 1 +}; + } // namespace RSP #endif