start to implement recompile function and the like
This commit is contained in:
@@ -1,3 +1,4 @@
|
||||
#include <Cop0.hpp>
|
||||
#include <JIT.hpp>
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
int JIT::Step() {
|
||||
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)) {
|
||||
HandleTLBException(regs, regs.pc);
|
||||
FireException(regs, GetTLBExceptionCode(regs.cop0.tlbError, LOAD), 0, false);
|
||||
return 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<Fn>();
|
||||
}
|
||||
|
||||
u32 instruction = mem.Read32(regs, paddr);
|
||||
u32 instr = mem.Read32(regs, paddr);
|
||||
stable = isStable(instr);
|
||||
|
||||
if(ShouldServiceInterrupt()) {
|
||||
FireException(regs, ExceptionCode::Interrupt, 0, false);
|
||||
return 0;
|
||||
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<Fn>();
|
||||
}
|
||||
|
||||
regs.oldPC = regs.pc;
|
||||
regs.pc = regs.nextPC;
|
||||
regs.nextPC += 4;
|
||||
}
|
||||
|
||||
return 1;
|
||||
epilogue();
|
||||
}
|
||||
|
||||
int JIT::Step() {
|
||||
if(!blocks[regs.pc >> 20]) {
|
||||
blocks[regs.pc >> 20] = (Fn*)calloc(4096, sizeof(Fn));
|
||||
blocks[regs.pc >> 20][regs.pc & 0xfff] = Recompile();
|
||||
}
|
||||
|
||||
if (!blocks[regs.pc >> 20][regs.pc & 0xfff]) {
|
||||
blocks[regs.pc >> 20][regs.pc & 0xfff] = Recompile();
|
||||
}
|
||||
|
||||
blocks[regs.pc >> 20][regs.pc & 0xfff]();
|
||||
return cycles;
|
||||
}
|
||||
}
|
||||
@@ -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]{};
|
||||
|
||||
|
||||
Reference in New Issue
Block a user