From 9266308c63b0cb5236c0e79e41b3e304a42f389f Mon Sep 17 00:00:00 2001 From: SimoneN64 Date: Sat, 12 Aug 2023 15:41:05 +0200 Subject: [PATCH] start to implement recompile function and the like --- src/backend/core/JIT.cpp | 86 ++++++++++++++++++++++++++++++---------- src/backend/core/JIT.hpp | 22 ++++++++++ 2 files changed, 87 insertions(+), 21 deletions(-) diff --git a/src/backend/core/JIT.cpp b/src/backend/core/JIT.cpp index 9d14c55a..e78cad49 100644 --- a/src/backend/core/JIT.cpp +++ b/src/backend/core/JIT.cpp @@ -1,3 +1,4 @@ +#include #include namespace n64 { @@ -11,37 +12,80 @@ void JIT::Reset() { } bool JIT::ShouldServiceInterrupt() { + bool interrupts_pending = (regs.cop0.status.im & regs.cop0.cause.interruptPending) != 0; + bool interrupts_enabled = regs.cop0.status.ie == 1; + bool currently_handling_exception = regs.cop0.status.exl == 1; + bool currently_handling_error = regs.cop0.status.erl == 1; + return interrupts_pending && interrupts_enabled && + !currently_handling_exception && !currently_handling_error; } void JIT::CheckCompareInterrupt() { + regs.cop0.count++; + regs.cop0.count &= 0x1FFFFFFFF; + if(regs.cop0.count == (u64)regs.cop0.compare << 1) { + regs.cop0.cause.ip7 = 1; + UpdateInterrupt(mem.mmio.mi, regs); + } +} +Fn JIT::Recompile() { + bool stable = true; + cycles = 0; + prologue(); + while(stable) { + CheckCompareInterrupt(); + + regs.prevDelaySlot = regs.delaySlot; + regs.delaySlot = false; +\ + u32 paddr = 0; + if (!MapVAddr(regs, LOAD, regs.pc, paddr)) { + mov(rdi, u64(this) + offsetof(JIT, regs)); + mov(rsi, regs.pc); + push(rax); + call(HandleTLBException); + mov(rsi, u64(GetTLBExceptionCode(regs.cop0.tlbError, LOAD))); + CodeGenerator::xor_(rdx, rdx); + CodeGenerator::xor_(rcx, rcx); + push(rax); + call(FireException); + return getCode(); + } + + u32 instr = mem.Read32(regs, paddr); + stable = isStable(instr); + + if (ShouldServiceInterrupt()) { + mov(rdi, u64(this) + offsetof(JIT, regs)); + mov(rsi, u64(ExceptionCode::Interrupt)); + CodeGenerator::xor_(rdx, rdx); + CodeGenerator::xor_(rcx, rcx); + push(rax); + call(FireException); + return getCode(); + } + + regs.oldPC = regs.pc; + regs.pc = regs.nextPC; + regs.nextPC += 4; + } + + epilogue(); } int JIT::Step() { - CheckCompareInterrupt(); - - regs.prevDelaySlot = regs.delaySlot; - regs.delaySlot = false; - - u32 paddr = 0; - if(!MapVAddr(regs, LOAD, regs.pc, paddr)) { - HandleTLBException(regs, regs.pc); - FireException(regs, GetTLBExceptionCode(regs.cop0.tlbError, LOAD), 0, false); - return 0; + if(!blocks[regs.pc >> 20]) { + blocks[regs.pc >> 20] = (Fn*)calloc(4096, sizeof(Fn)); + blocks[regs.pc >> 20][regs.pc & 0xfff] = Recompile(); } - u32 instruction = mem.Read32(regs, paddr); - - if(ShouldServiceInterrupt()) { - FireException(regs, ExceptionCode::Interrupt, 0, false); - return 0; + if (!blocks[regs.pc >> 20][regs.pc & 0xfff]) { + blocks[regs.pc >> 20][regs.pc & 0xfff] = Recompile(); } - regs.oldPC = regs.pc; - regs.pc = regs.nextPC; - regs.nextPC += 4; - - return 1; + blocks[regs.pc >> 20][regs.pc & 0xfff](); + return cycles; +} } -} \ No newline at end of file diff --git a/src/backend/core/JIT.hpp b/src/backend/core/JIT.hpp index 904ac7ea..deac1842 100644 --- a/src/backend/core/JIT.hpp +++ b/src/backend/core/JIT.hpp @@ -15,8 +15,30 @@ struct JIT : BaseCPU, Xbyak::CodeGenerator { friend struct Cop1; friend struct Cop0; private: + int cycles = 0; bool ShouldServiceInterrupt() override; void CheckCompareInterrupt() override; + Fn Recompile(); + + bool isStable(u32 instr) { + switch(instr) { + default: return false; + } + } + + FORCE_INLINE void prologue() { + const Xbyak::Reg64 allRegs[]{rax, rcx, rdx, rbx, rsp, rbp, rsi, rdi, r8, r9, r10, r11, r12, r13, r14, r15}; + for(auto r : allRegs) { + push(r); + } + } + + FORCE_INLINE void epilogue() { + const Xbyak::Reg64 allRegs[]{r15, r14, r13, r12, r11, r10, r9, r8, rdi, rsi, rbp, rsp, rbx, rdx, rcx, rax}; + for(auto r : allRegs) { + pop(r); + } + } Fn* blocks[0x80000]{};