diff --git a/src/backend/core/JIT.cpp b/src/backend/core/JIT.cpp index c667f740..5fe6a552 100644 --- a/src/backend/core/JIT.cpp +++ b/src/backend/core/JIT.cpp @@ -2,7 +2,6 @@ #include #include - namespace n64 { namespace fs = std::filesystem; @@ -25,6 +24,7 @@ JIT::JIT() : code(CODECACHE_SIZE, codeCache) { dump.open("jit.dump", std::ios::ate | std::ios::binary); dump.unsetf(std::ios::skipws); + regs.Reset(); } inline bool ShouldServiceInterrupt(Registers& regs) { @@ -64,23 +64,21 @@ void JIT::Recompile(Mem& mem, u32 pc) { instrInBlock++; prevBranch = branch; u32 instr = mem.Read32(regs, loopPC); + loopPC += 4; - emitBreakpoint(); code.mov(rdi, (uintptr_t)this); - code.mov(rsi, instr); - - code.mov(r8, qword[rdi + REG_OFFSET(oldPC)]); - code.mov(r9, qword[rdi + REG_OFFSET(pc)]); - code.mov(r10, qword[rdi + REG_OFFSET(nextPC)]); + code.mov(qword[rdi + GPR_OFFSET(0, this)], 0); + code.mov(r8, qword[rdi + REG_OFFSET(oldPC, this)]); + code.mov(r9, qword[rdi + REG_OFFSET(pc, this)]); + code.mov(r10, qword[rdi + REG_OFFSET(nextPC, this)]); code.mov(r8, r9); code.mov(r9, r10); code.add(r10, 4); - code.mov(qword[rdi + REG_OFFSET(oldPC)], r8); - code.mov(qword[rdi + REG_OFFSET(pc)], r9); - code.mov(qword[rdi + REG_OFFSET(nextPC)], r10); - - loopPC += 4; + code.mov(qword[rdi + REG_OFFSET(oldPC, this)], r8); + code.mov(qword[rdi + REG_OFFSET(pc, this)], r9); + code.mov( qword[rdi + REG_OFFSET(nextPC, this)], r10); + code.mov(esi, instr); branch = Exec(mem, instr); } @@ -89,7 +87,6 @@ void JIT::Recompile(Mem& mem, u32 pc) { dump.write(code.getCode(), code.getSize()); blockCache[startPC >> 20][startPC & 0xFFF] = block; - blockCache[startPC >> 20][startPC & 0xFFF](); } void JIT::AllocateOuter(u32 pc) { @@ -98,7 +95,6 @@ void JIT::AllocateOuter(u32 pc) { int JIT::Run() { instrInBlock = 0; - regs.gpr[0] = 0; regs.prevDelaySlot = regs.delaySlot; regs.delaySlot = false; @@ -110,23 +106,22 @@ int JIT::Run() { return 0; } - if(blockCache[pc >> 20]) { - if(blockCache[pc >> 20][pc & 0xfff]) { - blockCache[pc >> 20][pc & 0xfff](); - } else { - Recompile(mem, pc); - } - } else { + if(!blockCache[pc >> 20]) { AllocateOuter(pc); + } + + if(!blockCache[pc >> 20][pc & 0xfff]) { Recompile(mem, pc); } CheckCompareInterrupt(mem.mmio.mi, regs); - if(ShouldServiceInterrupt(regs)) { FireException(regs, ExceptionCode::Interrupt, 0, false); + return 0; } + blockCache[pc >> 20][pc & 0xfff](); + return instrInBlock; } diff --git a/src/backend/core/JIT.hpp b/src/backend/core/JIT.hpp index b3b31f51..85c65e62 100644 --- a/src/backend/core/JIT.hpp +++ b/src/backend/core/JIT.hpp @@ -9,8 +9,8 @@ using namespace Xbyak; using namespace Xbyak::util; using Fn = void (*)(); -#define GPR_OFFSET(x) ((uintptr_t)®s.gpr[(x)] - (uintptr_t)®s) -#define REG_OFFSET(kind) ((uintptr_t)®s.kind - (uintptr_t)®s) +#define GPR_OFFSET(x, jit) ((uintptr_t)®s.gpr[(x)] - (uintptr_t)jit) +#define REG_OFFSET(kind, jit) ((uintptr_t)®s.kind - (uintptr_t)jit) #define CODECACHE_SIZE (2 << 25) #define CODECACHE_OVERHEAD (CODECACHE_SIZE - 1_kb) @@ -28,17 +28,9 @@ private: Fn* blockCache[0x80000]{}; u8* codeCache; int instrInBlock = 0; - bool enableBreakpoints = false; u64 sizeUsed = 0; std::ofstream dump; - inline void emitBreakpoint() { - #ifndef NDEBUG - if(enableBreakpoints) - code.int3(); - #endif - } - void* bumpAlloc(u64 size, u8 val = 0); void Recompile(Mem&, u32 pc); void AllocateOuter(u32 pc); diff --git a/src/backend/core/interpreter/decode.cpp b/src/backend/core/interpreter/decode.cpp index c5e78fe4..dc6a72e7 100644 --- a/src/backend/core/interpreter/decode.cpp +++ b/src/backend/core/interpreter/decode.cpp @@ -130,7 +130,7 @@ void Interpreter::Exec(u32 instr) { case 0x0D: ori(instr); break; case 0x0E: xori(instr); break; case 0x0F: lui(instr); break; - case 0x10: regs.cop0.decode(regs, mem, instr); break; + case 0x10: regs.cop0.decode(regs, instr); break; case 0x11: regs.cop1.decode(regs, *this, instr); break; case 0x12: cop2Decode(instr); break; case 0x14: bl(instr, regs.gpr[RS(instr)] == regs.gpr[RT(instr)]); break; diff --git a/src/backend/core/jit/MemoryManagement.cpp b/src/backend/core/jit/MemoryManagement.cpp index 4cf1045e..5a182a7f 100644 --- a/src/backend/core/jit/MemoryManagement.cpp +++ b/src/backend/core/jit/MemoryManagement.cpp @@ -7,8 +7,8 @@ void JIT::InvalidatePage(u32 paddr) { void JIT::InvalidateCache() { sizeUsed = 0; - for(int i = 0; i < 0x80000; i++) { - blockCache[i] = nullptr; + for(auto &i : blockCache) { + i = nullptr; } } diff --git a/src/backend/core/jit/cop/cop0decode.cpp b/src/backend/core/jit/cop/cop0decode.cpp index 62a35f9f..1a4932c4 100644 --- a/src/backend/core/jit/cop/cop0decode.cpp +++ b/src/backend/core/jit/cop/cop0decode.cpp @@ -3,10 +3,11 @@ #include namespace n64 { -void cop0Decode(Registers& regs, JIT& cpu, u32 instr) { +void cop0Decode(JIT& cpu, u32 instr) { u8 mask_cop = (instr >> 21) & 0x1F; u8 mask_cop2 = instr & 0x3F; Xbyak::CodeGenerator& code = cpu.code; + Registers& regs = cpu.regs; switch(mask_cop) { case 0x00: @@ -32,7 +33,7 @@ void cop0Decode(Registers& regs, JIT& cpu, u32 instr) { code.call(code.rax); break; case 0x02: - code.mov(code.rcx, code.dword[code.rdi + offsetof(Registers, cop0.index)]); + code.mov(code.rcx, code.dword[code.rdi + REG_OFFSET(cop0.index, &cpu)]); code.and_(code.rcx, 0x3F); code.mov(code.rsi, code.rcx); code.mov(code.rax, (u64)tlbw); diff --git a/src/backend/core/jit/cop/cop0decode.hpp b/src/backend/core/jit/cop/cop0decode.hpp index 7ca05474..9457f038 100644 --- a/src/backend/core/jit/cop/cop0decode.hpp +++ b/src/backend/core/jit/cop/cop0decode.hpp @@ -3,5 +3,5 @@ namespace n64 { struct Registers; -void cop0Decode(Registers&, JIT& cpu, u32 instr); +void cop0Decode(JIT& cpu, u32 instr); } \ No newline at end of file diff --git a/src/backend/core/jit/cop/cop1decode.cpp b/src/backend/core/jit/cop/cop1decode.cpp index 74ea97e8..4b582873 100644 --- a/src/backend/core/jit/cop/cop1decode.cpp +++ b/src/backend/core/jit/cop/cop1decode.cpp @@ -3,8 +3,9 @@ #include namespace n64 { -bool cop1Decode(Registers& regs, JIT& cpu, u32 instr) { +bool cop1Decode(JIT& cpu, u32 instr) { Xbyak::CodeGenerator& code = cpu.code; + Registers& regs = cpu.regs; u8 mask_sub = (instr >> 21) & 0x1F; u8 mask_fun = instr & 0x3F; diff --git a/src/backend/core/jit/cop/cop1decode.hpp b/src/backend/core/jit/cop/cop1decode.hpp index 968ce28d..2aab3e56 100644 --- a/src/backend/core/jit/cop/cop1decode.hpp +++ b/src/backend/core/jit/cop/cop1decode.hpp @@ -2,5 +2,5 @@ #include namespace n64 { -bool cop1Decode(Registers&, JIT& cpu, u32 instr); +bool cop1Decode(JIT& cpu, u32 instr); } \ No newline at end of file diff --git a/src/backend/core/jit/cop/cop1instructions.cpp b/src/backend/core/jit/cop/cop1instructions.cpp index 9aac547c..d5090d35 100644 --- a/src/backend/core/jit/cop/cop1instructions.cpp +++ b/src/backend/core/jit/cop/cop1instructions.cpp @@ -29,91 +29,93 @@ inline int PushRoundingMode(const FCR31& fcr31) { } \ } while(0) -void absd(JIT& cpu, u32 instr) { - Registers& regs = cpu.regs; - auto fs = regs.cop1.GetCop1Reg(regs.cop0, FS(instr)); +void absd(JIT& dyn, u32 instr) { + Registers& regs = dyn.regs; + double fs = regs.cop1.GetCop1Reg(regs.cop0, FS(instr)); regs.cop1.SetCop1Reg(regs.cop0, FD(instr), std::abs(fs)); } -void abss(JIT& cpu, u32 instr) { - Registers& regs = cpu.regs; - auto fs = regs.cop1.GetCop1Reg(regs.cop0, FS(instr)); +void abss(JIT& dyn, u32 instr) { + Registers& regs = dyn.regs; + float fs = regs.cop1.GetCop1Reg(regs.cop0, FS(instr)); regs.cop1.SetCop1Reg(regs.cop0, FD(instr), std::abs(fs)); } -void absw(JIT& cpu, u32 instr) { - Registers& regs = cpu.regs; +void absw(JIT& dyn, u32 instr) { + Registers& regs = dyn.regs; s32 fs = regs.cop1.GetReg(regs.cop0, FS(instr)); regs.cop1.SetReg(regs.cop0, FD(instr), std::abs(fs)); } -void absl(JIT& cpu, u32 instr) { - Registers& regs = cpu.regs; +void absl(JIT& dyn, u32 instr) { + Registers& regs = dyn.regs; s64 fs = regs.cop1.GetReg(regs.cop0, FS(instr)); regs.cop1.SetReg(regs.cop0, FD(instr), std::abs(fs)); } -void adds(JIT& cpu, u32 instr) { - Registers& regs = cpu.regs; - auto fs = regs.cop1.GetCop1Reg(regs.cop0, FS(instr)); - auto ft = regs.cop1.GetCop1Reg(regs.cop0, FT(instr)); +void adds(JIT& dyn, u32 instr) { + Registers& regs = dyn.regs; + float fs = regs.cop1.GetCop1Reg(regs.cop0, FS(instr)); + float ft = regs.cop1.GetCop1Reg(regs.cop0, FT(instr)); checknanregs(fs, ft); float result = fs + ft; regs.cop1.SetCop1Reg(regs.cop0, FD(instr), result); } -void addd(JIT& cpu, u32 instr) { - Registers& regs = cpu.regs; - auto fs = regs.cop1.GetCop1Reg(regs.cop0, FS(instr)); - auto ft = regs.cop1.GetCop1Reg(regs.cop0, FT(instr)); +void addd(JIT& dyn, u32 instr) { + Registers& regs = dyn.regs; + double fs = regs.cop1.GetCop1Reg(regs.cop0, FS(instr)); + double ft = regs.cop1.GetCop1Reg(regs.cop0, FT(instr)); checknanregs(fs, ft); double result = fs + ft; regs.cop1.SetCop1Reg(regs.cop0, FD(instr), result); } -void ceills(JIT& cpu, u32 instr) { - Registers& regs = cpu.regs; - auto fs = regs.cop1.GetCop1Reg(regs.cop0, FS(instr)); +void ceills(JIT& dyn, u32 instr) { + Registers& regs = dyn.regs; + float fs = regs.cop1.GetCop1Reg(regs.cop0, FS(instr)); s64 result = std::ceil(fs); regs.cop1.SetReg(regs.cop0, FD(instr), result); } -void ceilws(JIT& cpu, u32 instr) { - Registers& regs = cpu.regs; - auto fs = regs.cop1.GetCop1Reg(regs.cop0, FS(instr)); +void ceilws(JIT& dyn, u32 instr) { + Registers& regs = dyn.regs; + float fs = regs.cop1.GetCop1Reg(regs.cop0, FS(instr)); s32 result = std::ceil(fs); regs.cop1.SetReg(regs.cop0, FD(instr), result); } -void ceilld(JIT& cpu, u32 instr) { - Registers& regs = cpu.regs; - auto fs = regs.cop1.GetCop1Reg(regs.cop0, FS(instr)); +void ceilld(JIT& dyn, u32 instr) { + Registers& regs = dyn.regs; + double fs = regs.cop1.GetCop1Reg(regs.cop0, FS(instr)); s64 result = std::ceil(fs); regs.cop1.SetReg(regs.cop0, FD(instr), result); } -void ceilwd(JIT& cpu, u32 instr) { - Registers& regs = cpu.regs; - auto fs = regs.cop1.GetCop1Reg(regs.cop0, FS(instr)); +void ceilwd(JIT& dyn, u32 instr) { + Registers& regs = dyn.regs; + double fs = regs.cop1.GetCop1Reg(regs.cop0, FS(instr)); s32 result = std::ceil(fs); regs.cop1.SetReg(regs.cop0, FD(instr), result); } -void cfc1(JIT& cpu, u32 instr) { - Registers& regs = cpu.regs; +void cfc1(JIT& dyn, u32 instr) { + Registers& regs = dyn.regs; u8 fd = RD(instr); s32 val = 0; switch(fd) { case 0: val = regs.cop1.fcr0; break; - case 31: val = regs.cop1.fcr31.raw; break; + case 31: + val = regs.cop1.fcr31.raw; + break; default: Util::panic("Undefined CFC1 with rd != 0 or 31\n"); } regs.gpr[RT(instr)] = val; } -void ctc1(JIT& cpu, u32 instr) { - Registers& regs = cpu.regs; - u8 fs = FS(instr); +void ctc1(JIT& dyn, u32 instr) { + Registers& regs = dyn.regs; + u8 fs = RD(instr); u32 val = regs.gpr[RT(instr)]; switch(fs) { case 0: break; @@ -125,8 +127,8 @@ void ctc1(JIT& cpu, u32 instr) { } } -void cvtds(JIT& cpu, u32 instr) { - Registers& regs = cpu.regs; +void cvtds(JIT& dyn, u32 instr) { + Registers& regs = dyn.regs; regs.cop1.SetCop1Reg( regs.cop0, FD(instr), @@ -137,8 +139,8 @@ void cvtds(JIT& cpu, u32 instr) { ); } -void cvtsd(JIT& cpu, u32 instr) { - Registers& regs = cpu.regs; +void cvtsd(JIT& dyn, u32 instr) { + Registers& regs = dyn.regs; regs.cop1.SetCop1Reg( regs.cop0, FD(instr), @@ -149,8 +151,8 @@ void cvtsd(JIT& cpu, u32 instr) { ); } -void cvtwd(JIT& cpu, u32 instr) { - Registers& regs = cpu.regs; +void cvtwd(JIT& dyn, u32 instr) { + Registers& regs = dyn.regs; regs.cop1.SetReg( regs.cop0, FD(instr), @@ -161,8 +163,8 @@ void cvtwd(JIT& cpu, u32 instr) { ); } -void cvtws(JIT& cpu, u32 instr) { - Registers& regs = cpu.regs; +void cvtws(JIT& dyn, u32 instr) { + Registers& regs = dyn.regs; regs.cop1.SetReg( regs.cop0, FD(instr), @@ -173,8 +175,8 @@ void cvtws(JIT& cpu, u32 instr) { ); } -void cvtls(JIT& cpu, u32 instr) { - Registers& regs = cpu.regs; +void cvtls(JIT& dyn, u32 instr) { + Registers& regs = dyn.regs; regs.cop1.SetReg( regs.cop0, FD(instr), @@ -185,8 +187,8 @@ void cvtls(JIT& cpu, u32 instr) { ); } -void cvtsl(JIT& cpu, u32 instr) { - Registers& regs = cpu.regs; +void cvtsl(JIT& dyn, u32 instr) { + Registers& regs = dyn.regs; regs.cop1.SetCop1Reg( regs.cop0, FD(instr), @@ -197,8 +199,8 @@ void cvtsl(JIT& cpu, u32 instr) { ); } -void cvtdw(JIT& cpu, u32 instr) { - Registers& regs = cpu.regs; +void cvtdw(JIT& dyn, u32 instr) { + Registers& regs = dyn.regs; regs.cop1.SetCop1Reg( regs.cop0, FD(instr), @@ -209,8 +211,8 @@ void cvtdw(JIT& cpu, u32 instr) { ); } -void cvtsw(JIT& cpu, u32 instr) { - Registers& regs = cpu.regs; +void cvtsw(JIT& dyn, u32 instr) { + Registers& regs = dyn.regs; regs.cop1.SetCop1Reg( regs.cop0, FD(instr), @@ -221,8 +223,8 @@ void cvtsw(JIT& cpu, u32 instr) { ); } -void cvtdl(JIT& cpu, u32 instr) { - Registers& regs = cpu.regs; +void cvtdl(JIT& dyn, u32 instr) { + Registers& regs = dyn.regs; regs.cop1.SetCop1Reg( regs.cop0, FD(instr), @@ -233,8 +235,8 @@ void cvtdl(JIT& cpu, u32 instr) { ); } -void cvtld(JIT& cpu, u32 instr) { - Registers& regs = cpu.regs; +void cvtld(JIT& dyn, u32 instr) { + Registers& regs = dyn.regs; regs.cop1.SetReg( regs.cop0, FD(instr), @@ -246,8 +248,7 @@ void cvtld(JIT& cpu, u32 instr) { } template -inline bool CalculateCondition(JIT& cpu, T fs, T ft, CompConds cond) { - Registers& regs = cpu.regs; +inline bool CalculateCondition(Registers& regs, T fs, T ft, CompConds cond) { switch(cond) { case F: return false; case UN: return std::isnan(fs) || std::isnan(ft); @@ -265,94 +266,94 @@ inline bool CalculateCondition(JIT& cpu, T fs, T ft, CompConds cond) { return false; } - return CalculateCondition(cpu, fs, ft, static_cast(cond - 8)); + return CalculateCondition(regs, fs, ft, static_cast(cond - 8)); } } template -void ccond(JIT& cpu, u32 instr, CompConds cond) { - Registers& regs = cpu.regs; +void ccond(JIT& dyn, u32 instr, CompConds cond) { + Registers& regs = dyn.regs; T fs = regs.cop1.GetCop1Reg(regs.cop0, FS(instr)); T ft = regs.cop1.GetCop1Reg(regs.cop0, FT(instr)); - regs.cop1.fcr31.compare = CalculateCondition(cpu, fs, ft, cond); + regs.cop1.fcr31.compare = CalculateCondition(regs, fs, ft, cond); } -template void ccond(JIT& cpu, u32 instr, CompConds cond); -template void ccond(JIT& cpu, u32 instr, CompConds cond); +template void ccond(JIT& dyn, u32 instr, CompConds cond); +template void ccond(JIT& dyn, u32 instr, CompConds cond); -void divs(JIT& cpu, u32 instr) { - Registers& regs = cpu.regs; +void divs(JIT& dyn, u32 instr) { + Registers& regs = dyn.regs; float fs = regs.cop1.GetCop1Reg(regs.cop0, FS(instr)); float ft = regs.cop1.GetCop1Reg(regs.cop0, FT(instr)); regs.cop1.SetCop1Reg(regs.cop0, FD(instr), fs / ft); } -void divd(JIT& cpu, u32 instr) { - Registers& regs = cpu.regs; +void divd(JIT& dyn, u32 instr) { + Registers& regs = dyn.regs; double fs = regs.cop1.GetCop1Reg(regs.cop0, FS(instr)); double ft = regs.cop1.GetCop1Reg(regs.cop0, FT(instr)); regs.cop1.SetCop1Reg(regs.cop0, FD(instr), fs / ft); } -void muls(JIT& cpu, u32 instr) { - Registers& regs = cpu.regs; +void muls(JIT& dyn, u32 instr) { + Registers& regs = dyn.regs; float fs = regs.cop1.GetCop1Reg(regs.cop0, FS(instr)); float ft = regs.cop1.GetCop1Reg(regs.cop0, FT(instr)); regs.cop1.SetCop1Reg(regs.cop0, FD(instr), fs * ft); } -void muld(JIT& cpu, u32 instr) { - Registers& regs = cpu.regs; +void muld(JIT& dyn, u32 instr) { + Registers& regs = dyn.regs; double fs = regs.cop1.GetCop1Reg(regs.cop0, FS(instr)); double ft = regs.cop1.GetCop1Reg(regs.cop0, FT(instr)); regs.cop1.SetCop1Reg(regs.cop0, FD(instr), fs * ft); } -void mulw(JIT& cpu, u32 instr) { - Registers& regs = cpu.regs; +void mulw(JIT& dyn, u32 instr) { + Registers& regs = dyn.regs; u32 fs = regs.cop1.GetReg(regs.cop0, FS(instr)); u32 ft = regs.cop1.GetReg(regs.cop0, FT(instr)); regs.cop1.SetReg(regs.cop0, FD(instr), fs * ft); } -void mull(JIT& cpu, u32 instr) { - Registers& regs = cpu.regs; +void mull(JIT& dyn, u32 instr) { + Registers& regs = dyn.regs; u64 fs = regs.cop1.GetReg(regs.cop0, FS(instr)); u64 ft = regs.cop1.GetReg(regs.cop0, FT(instr)); regs.cop1.SetReg(regs.cop0, FD(instr), fs * ft); } -void subs(JIT& cpu, u32 instr) { - Registers& regs = cpu.regs; +void subs(JIT& dyn, u32 instr) { + Registers& regs = dyn.regs; float fs = regs.cop1.GetCop1Reg(regs.cop0, FS(instr)); float ft = regs.cop1.GetCop1Reg(regs.cop0, FT(instr)); regs.cop1.SetCop1Reg(regs.cop0, FD(instr), fs - ft); } -void subd(JIT& cpu, u32 instr) { - Registers& regs = cpu.regs; +void subd(JIT& dyn, u32 instr) { + Registers& regs = dyn.regs; double fs = regs.cop1.GetCop1Reg(regs.cop0, FS(instr)); double ft = regs.cop1.GetCop1Reg(regs.cop0, FT(instr)); regs.cop1.SetCop1Reg(regs.cop0, FD(instr), fs - ft); } -void subw(JIT& cpu, u32 instr) { - Registers& regs = cpu.regs; +void subw(JIT& dyn, u32 instr) { + Registers& regs = dyn.regs; u32 fs = regs.cop1.GetReg(regs.cop0, FS(instr)); u32 ft = regs.cop1.GetReg(regs.cop0, FT(instr)); regs.cop1.SetReg(regs.cop0, FD(instr), fs - ft); } -void subl(JIT& cpu, u32 instr) { - Registers& regs = cpu.regs; +void subl(JIT& dyn, u32 instr) { + Registers& regs = dyn.regs; u64 fs = regs.cop1.GetReg(regs.cop0, FS(instr)); u64 ft = regs.cop1.GetReg(regs.cop0, FT(instr)); regs.cop1.SetReg(regs.cop0, FD(instr), fs - ft); } -void movs(JIT& cpu, u32 instr) { - Registers& regs = cpu.regs; +void movs(JIT& dyn, u32 instr) { + Registers& regs = dyn.regs; regs.cop1.SetCop1Reg( regs.cop0, FD(instr), @@ -363,8 +364,8 @@ void movs(JIT& cpu, u32 instr) { ); } -void movd(JIT& cpu, u32 instr) { - Registers& regs = cpu.regs; +void movd(JIT& dyn, u32 instr) { + Registers& regs = dyn.regs; regs.cop1.SetCop1Reg( regs.cop0, FD(instr), @@ -375,8 +376,8 @@ void movd(JIT& cpu, u32 instr) { ); } -void movw(JIT& cpu, u32 instr) { - Registers& regs = cpu.regs; +void movw(JIT& dyn, u32 instr) { + Registers& regs = dyn.regs; regs.cop1.SetReg( regs.cop0, FD(instr), @@ -387,8 +388,8 @@ void movw(JIT& cpu, u32 instr) { ); } -void movl(JIT& cpu, u32 instr) { - Registers& regs = cpu.regs; +void movl(JIT& dyn, u32 instr) { + Registers& regs = dyn.regs; regs.cop1.SetReg( regs.cop0, FD(instr), @@ -399,8 +400,8 @@ void movl(JIT& cpu, u32 instr) { ); } -void negs(JIT& cpu, u32 instr) { - Registers& regs = cpu.regs; +void negs(JIT& dyn, u32 instr) { + Registers& regs = dyn.regs; regs.cop1.SetCop1Reg( regs.cop0, FD(instr), @@ -411,8 +412,8 @@ void negs(JIT& cpu, u32 instr) { ); } -void negd(JIT& cpu, u32 instr) { - Registers& regs = cpu.regs; +void negd(JIT& dyn, u32 instr) { + Registers& regs = dyn.regs; regs.cop1.SetCop1Reg( regs.cop0, FD(instr), @@ -423,77 +424,76 @@ void negd(JIT& cpu, u32 instr) { ); } -void sqrts(JIT& cpu, u32 instr) { - Registers& regs = cpu.regs; +void sqrts(JIT& dyn, u32 instr) { + Registers& regs = dyn.regs; float fs = regs.cop1.GetCop1Reg(regs.cop0, FS(instr)); regs.cop1.SetCop1Reg(regs.cop0, FD(instr), std::sqrt(fs)); } -void sqrtd(JIT& cpu, u32 instr) { - Registers& regs = cpu.regs; +void sqrtd(JIT& dyn, u32 instr) { + Registers& regs = dyn.regs; double fs = regs.cop1.GetCop1Reg(regs.cop0, FS(instr)); regs.cop1.SetCop1Reg(regs.cop0, FD(instr), std::sqrt(fs)); } -void roundls(JIT& cpu, u32 instr) { - Registers& regs = cpu.regs; +void roundls(JIT& dyn, u32 instr) { + Registers& regs = dyn.regs; float fs = regs.cop1.GetCop1Reg(regs.cop0, FS(instr)); PUSHROUNDINGMODE; regs.cop1.SetReg(regs.cop0, FD(instr), (s32)std::nearbyint(fs)); POPROUNDINGMODE; } -void roundld(JIT& cpu, u32 instr) { - Registers& regs = cpu.regs; +void roundld(JIT& dyn, u32 instr) { + Registers& regs = dyn.regs; double fs = regs.cop1.GetCop1Reg(regs.cop0, FS(instr)); PUSHROUNDINGMODE; regs.cop1.SetReg(regs.cop0, FD(instr), (s64)std::nearbyint(fs)); POPROUNDINGMODE; } -void roundws(JIT& cpu, u32 instr) { - Registers& regs = cpu.regs; +void roundws(JIT& dyn, u32 instr) { + Registers& regs = dyn.regs; float fs = regs.cop1.GetCop1Reg(regs.cop0, FS(instr)); PUSHROUNDINGMODE; regs.cop1.SetReg(regs.cop0, FD(instr), (s32)std::nearbyint(fs)); POPROUNDINGMODE; } -void roundwd(JIT& cpu, u32 instr) { - Registers& regs = cpu.regs; +void roundwd(JIT& dyn, u32 instr) { + Registers& regs = dyn.regs; double fs = regs.cop1.GetCop1Reg(regs.cop0, FS(instr)); PUSHROUNDINGMODE; regs.cop1.SetReg(regs.cop0, FD(instr), (s32)std::nearbyint(fs)); POPROUNDINGMODE; } -void floorls(JIT& cpu, u32 instr) { - Registers& regs = cpu.regs; +void floorls(JIT& dyn, u32 instr) { + Registers& regs = dyn.regs; float fs = regs.cop1.GetCop1Reg(regs.cop0, FS(instr)); regs.cop1.SetReg(regs.cop0, FD(instr), (s64)std::floor(fs)); } -void floorld(JIT& cpu, u32 instr) { - Registers& regs = cpu.regs; +void floorld(JIT& dyn, u32 instr) { + Registers& regs = dyn.regs; double fs = regs.cop1.GetCop1Reg(regs.cop0, FS(instr)); regs.cop1.SetReg(regs.cop0, FD(instr), (s64)std::floor(fs)); } -void floorws(JIT& cpu, u32 instr) { - Registers& regs = cpu.regs; +void floorws(JIT& dyn, u32 instr) { + Registers& regs = dyn.regs; float fs = regs.cop1.GetCop1Reg(regs.cop0, FS(instr)); regs.cop1.SetReg(regs.cop0, FD(instr), (s64)std::floor(fs)); } -void floorwd(JIT& cpu, u32 instr) { - Registers& regs = cpu.regs; +void floorwd(JIT& dyn, u32 instr) { + Registers& regs = dyn.regs; double fs = regs.cop1.GetCop1Reg(regs.cop0, FS(instr)); regs.cop1.SetReg(regs.cop0, FD(instr), (s64)std::floor(fs)); } -void lwc1(JIT& cpu, u32 instr) { - Mem& mem = cpu.mem; - Registers& regs = cpu.regs; +void lwc1(JIT& dyn, u32 instr) { + Registers& regs = dyn.regs; if(!regs.cop0.status.cu1) { FireException(regs, ExceptionCode::CoprocessorUnusable, 1, true); return; @@ -506,14 +506,13 @@ void lwc1(JIT& cpu, u32 instr) { HandleTLBException(regs, addr); FireException(regs, GetTLBExceptionCode(regs.cop0.tlbError, LOAD), 0, true); } else { - u32 data = mem.Read32(regs, physical); + u32 data = dyn.mem.Read32(regs, physical); regs.cop1.SetReg(regs.cop0, FT(instr), data); } } -void swc1(JIT& cpu, u32 instr) { - Mem& mem = cpu.mem; - Registers& regs = cpu.regs; +void swc1(JIT& dyn, u32 instr) { + Registers& regs = dyn.regs; if(!regs.cop0.status.cu1) { FireException(regs, ExceptionCode::CoprocessorUnusable, 1, true); return; @@ -526,13 +525,12 @@ void swc1(JIT& cpu, u32 instr) { HandleTLBException(regs, addr); FireException(regs, GetTLBExceptionCode(regs.cop0.tlbError, STORE), 0, true); } else { - mem.Write32(regs, physical, regs.cop1.GetReg(regs.cop0, FT(instr))); + dyn.mem.Write32(regs, physical, regs.cop1.GetReg(regs.cop0, FT(instr))); } } -void ldc1(JIT& cpu, u32 instr) { - Mem& mem = cpu.mem; - Registers& regs = cpu.regs; +void ldc1(JIT& dyn, u32 instr) { + Registers& regs = dyn.regs; if(!regs.cop0.status.cu1) { FireException(regs, ExceptionCode::CoprocessorUnusable, 1, true); return; @@ -545,14 +543,13 @@ void ldc1(JIT& cpu, u32 instr) { HandleTLBException(regs, addr); FireException(regs, GetTLBExceptionCode(regs.cop0.tlbError, LOAD), 0, true); } else { - u64 data = mem.Read64(regs, physical); + u64 data = dyn.mem.Read64(regs, physical); regs.cop1.SetReg(regs.cop0, FT(instr), data); } } -void sdc1(JIT& cpu, u32 instr) { - Mem& mem = cpu.mem; - Registers& regs = cpu.regs; +void sdc1(JIT& dyn, u32 instr) { + Registers& regs = dyn.regs; if(!regs.cop0.status.cu1) { FireException(regs, ExceptionCode::CoprocessorUnusable, 1, true); return; @@ -565,55 +562,56 @@ void sdc1(JIT& cpu, u32 instr) { HandleTLBException(regs, addr); FireException(regs, GetTLBExceptionCode(regs.cop0.tlbError, STORE), 0, true); } else { - mem.Write64(regs, physical, regs.cop1.GetReg(regs.cop0, FT(instr))); + dyn.mem.Write64(regs, physical, regs.cop1.GetReg(regs.cop0, FT(instr))); } } -void truncws(JIT& cpu, u32 instr) { - Registers& regs = cpu.regs; +void truncws(JIT& dyn, u32 instr) { + Registers& regs = dyn.regs; float fs = regs.cop1.GetCop1Reg(regs.cop0, FS(instr)); s32 result = (s32)std::trunc(fs); regs.cop1.SetReg(regs.cop0, FD(instr), result); } -void truncwd(JIT& cpu, u32 instr) { - Registers& regs = cpu.regs; +void truncwd(JIT& dyn, u32 instr) { + Registers& regs = dyn.regs; double fs = regs.cop1.GetCop1Reg(regs.cop0, FS(instr)); s32 result = (s32)std::trunc(fs); regs.cop1.SetReg(regs.cop0, FD(instr), result); } -void truncls(JIT& cpu, u32 instr) { - Registers& regs = cpu.regs; +void truncls(JIT& dyn, u32 instr) { + Registers& regs = dyn.regs; float fs = regs.cop1.GetCop1Reg(regs.cop0, FS(instr)); s64 result = (s64)std::trunc(fs); regs.cop1.SetReg(regs.cop0, FD(instr), result); } -void truncld(JIT& cpu, u32 instr) { - Registers& regs = cpu.regs; +void truncld(JIT& dyn, u32 instr) { + Registers& regs = dyn.regs; double fs = regs.cop1.GetCop1Reg(regs.cop0, FS(instr)); s64 result = (s64)std::trunc(fs); regs.cop1.SetReg(regs.cop0, FD(instr), result); } -void mfc1(JIT& cpu, u32 instr) { - Registers& regs = cpu.regs; +void mfc1(JIT& dyn, u32 instr) { + Registers& regs = dyn.regs; regs.gpr[RT(instr)] = (s32)regs.cop1.GetReg(regs.cop0, FS(instr)); } -void dmfc1(JIT& cpu, u32 instr) { - Registers& regs = cpu.regs; +void dmfc1(JIT& dyn, u32 instr) { + Registers& regs = dyn.regs; regs.gpr[RT(instr)] = (s64)regs.cop1.GetReg(regs.cop0, FS(instr)); } -void mtc1(JIT& cpu, u32 instr) { - Registers& regs = cpu.regs; +void mtc1(JIT& dyn, u32 instr) { + Registers& regs = dyn.regs; regs.cop1.SetReg(regs.cop0, FS(instr), regs.gpr[RT(instr)]); } -void dmtc1(JIT& cpu, u32 instr) { - Registers& regs = cpu.regs; +void dmtc1(JIT& dyn, u32 instr) { + Registers& regs = dyn.regs; regs.cop1.SetReg(regs.cop0, FS(instr), regs.gpr[RT(instr)]); } + } \ No newline at end of file diff --git a/src/backend/core/jit/decode.cpp b/src/backend/core/jit/decode.cpp index 26eafb3f..1b909f27 100644 --- a/src/backend/core/jit/decode.cpp +++ b/src/backend/core/jit/decode.cpp @@ -190,8 +190,8 @@ bool JIT::special(u32 instr) { code.call(rax); break; case 0x30: - code.mov(r8, qword[rdi + GPR_OFFSET(RS(instr))]); - code.mov(rcx, qword[rdi + GPR_OFFSET(RT(instr))]); + code.mov(r8, qword[rdi + GPR_OFFSET(RS(instr), this)]); + code.mov(rcx, qword[rdi + GPR_OFFSET(RT(instr), this)]); code.xor_(rsi, rsi); code.cmp(r8, rcx); code.setge(sil); @@ -200,8 +200,8 @@ bool JIT::special(u32 instr) { res = true; break; case 0x31: - code.mov(r8, qword[rdi + GPR_OFFSET(RS(instr))]); - code.mov(rcx, qword[rdi + GPR_OFFSET(RT(instr))]); + code.mov(r8, qword[rdi + GPR_OFFSET(RS(instr), this)]); + code.mov(rcx, qword[rdi + GPR_OFFSET(RT(instr), this)]); code.xor_(rsi, rsi); code.cmp(r8, rcx); code.setae(sil); @@ -210,8 +210,8 @@ bool JIT::special(u32 instr) { res = true; break; case 0x32: - code.mov(r8, qword[rdi + GPR_OFFSET(RS(instr))]); - code.mov(rcx, qword[rdi + GPR_OFFSET(RT(instr))]); + code.mov(r8, qword[rdi + GPR_OFFSET(RS(instr), this)]); + code.mov(rcx, qword[rdi + GPR_OFFSET(RT(instr), this)]); code.xor_(rsi, rsi); code.cmp(r8, rcx); code.setl(sil); @@ -220,8 +220,8 @@ bool JIT::special(u32 instr) { res = true; break; case 0x33: - code.mov(r8, qword[rdi + GPR_OFFSET(RS(instr))]); - code.mov(rcx, qword[rdi + GPR_OFFSET(RT(instr))]); + code.mov(r8, qword[rdi + GPR_OFFSET(RS(instr), this)]); + code.mov(rcx, qword[rdi + GPR_OFFSET(RT(instr), this)]); code.xor_(rsi, rsi); code.cmp(r8, rcx); code.setb(sil); @@ -230,8 +230,8 @@ bool JIT::special(u32 instr) { res = true; break; case 0x34: - code.mov(r8, qword[rdi + GPR_OFFSET(RS(instr))]); - code.mov(rcx, qword[rdi + GPR_OFFSET(RT(instr))]); + code.mov(r8, qword[rdi + GPR_OFFSET(RS(instr), this)]); + code.mov(rcx, qword[rdi + GPR_OFFSET(RT(instr), this)]); code.xor_(rsi, rsi); code.cmp(r8, rcx); code.sete(sil); @@ -240,8 +240,8 @@ bool JIT::special(u32 instr) { res = true; break; case 0x36: - code.mov(r8, qword[rdi + GPR_OFFSET(RS(instr))]); - code.mov(rcx, qword[rdi + GPR_OFFSET(RT(instr))]); + code.mov(r8, qword[rdi + GPR_OFFSET(RS(instr), this)]); + code.mov(rcx, qword[rdi + GPR_OFFSET(RT(instr), this)]); code.xor_(rsi, rsi); code.cmp(r8, rcx); code.setne(sil); @@ -285,7 +285,7 @@ bool JIT::regimm(u32 instr) { // 000r_rccc switch (mask) { // TODO: named constants for clearer code case 0x00: - code.mov(r8, qword[rdi + GPR_OFFSET(RS(instr))]); + code.mov(r8, qword[rdi + GPR_OFFSET(RS(instr), this)]); code.xor_(rdx, rdx); code.cmp(r8, 0); code.setl(dl); @@ -293,7 +293,7 @@ bool JIT::regimm(u32 instr) { code.call(rax); break; case 0x01: - code.mov(r8, qword[rdi + GPR_OFFSET(RS(instr))]); + code.mov(r8, qword[rdi + GPR_OFFSET(RS(instr), this)]); code.xor_(rdx, rdx); code.cmp(r8, 0); code.setge(dl); @@ -301,7 +301,7 @@ bool JIT::regimm(u32 instr) { code.call(rax); break; case 0x02: - code.mov(r8, qword[rdi + GPR_OFFSET(RS(instr))]); + code.mov(r8, qword[rdi + GPR_OFFSET(RS(instr), this)]); code.xor_(rdx, rdx); code.cmp(r8, 0); code.setl(dl); @@ -309,7 +309,7 @@ bool JIT::regimm(u32 instr) { code.call(rax); break; case 0x03: - code.mov(r8, qword[rdi + GPR_OFFSET(RS(instr))]); + code.mov(r8, qword[rdi + GPR_OFFSET(RS(instr), this)]); code.xor_(rdx, rdx); code.cmp(r8, 0); code.setge(dl); @@ -317,7 +317,7 @@ bool JIT::regimm(u32 instr) { code.call(rax); break; case 0x08: - code.mov(r8, qword[rdi + GPR_OFFSET(RS(instr))]); + code.mov(r8, qword[rdi + GPR_OFFSET(RS(instr), this)]); code.xor_(rsi, rsi); code.cmp(r8, s64(s16(instr))); code.setge(sil); @@ -325,7 +325,7 @@ bool JIT::regimm(u32 instr) { code.call(rax); break; case 0x09: - code.mov(r8, qword[rdi + GPR_OFFSET(RS(instr))]); + code.mov(r8, qword[rdi + GPR_OFFSET(RS(instr), this)]); code.xor_(rsi, rsi); code.cmp(r8, u64(s64(s16(instr)))); code.setae(sil); @@ -333,7 +333,7 @@ bool JIT::regimm(u32 instr) { code.call(rax); break; case 0x0A: - code.mov(r8, qword[rdi + GPR_OFFSET(RS(instr))]); + code.mov(r8, qword[rdi + GPR_OFFSET(RS(instr), this)]); code.xor_(rsi, rsi); code.cmp(r8, s64(s16(instr))); code.setl(sil); @@ -341,7 +341,7 @@ bool JIT::regimm(u32 instr) { code.call(rax); break; case 0x0B: - code.mov(r8, qword[rdi + GPR_OFFSET(RS(instr))]); + code.mov(r8, qword[rdi + GPR_OFFSET(RS(instr), this)]); code.xor_(rsi, rsi); code.cmp(r8, u64(s64(s16(instr)))); code.setb(sil); @@ -349,7 +349,7 @@ bool JIT::regimm(u32 instr) { code.call(rax); break; case 0x0C: - code.mov(r8, qword[rdi + GPR_OFFSET(RS(instr))]); + code.mov(r8, qword[rdi + GPR_OFFSET(RS(instr), this)]); code.xor_(rsi, rsi); code.cmp(r8, s64(s16(instr))); code.sete(sil); @@ -357,7 +357,7 @@ bool JIT::regimm(u32 instr) { code.call(rax); break; case 0x0E: - code.mov(r8, qword[rdi + GPR_OFFSET(RS(instr))]); + code.mov(r8, qword[rdi + GPR_OFFSET(RS(instr), this)]); code.xor_(rsi, rsi); code.cmp(r8, s64(s16(instr))); code.setne(sil); @@ -365,7 +365,7 @@ bool JIT::regimm(u32 instr) { code.call(rax); break; case 0x10: - code.mov(rcx, qword[rdi + GPR_OFFSET(RS(instr))]); + code.mov(rcx, qword[rdi + GPR_OFFSET(RS(instr), this)]); code.xor_(rdx, rdx); code.cmp(rcx, 0); code.setl(dl); @@ -373,7 +373,7 @@ bool JIT::regimm(u32 instr) { code.call(rax); break; case 0x11: - code.mov(rcx, qword[rdi + GPR_OFFSET(RS(instr))]); + code.mov(rcx, qword[rdi + GPR_OFFSET(RS(instr), this)]); code.xor_(rdx, rdx); code.cmp(rcx, 0); code.setge(dl); @@ -381,7 +381,7 @@ bool JIT::regimm(u32 instr) { code.call(rax); break; case 0x12: - code.mov(rcx, qword[rdi + GPR_OFFSET(RS(instr))]); + code.mov(rcx, qword[rdi + GPR_OFFSET(RS(instr), this)]); code.xor_(rdx, rdx); code.cmp(rcx, 0); code.setl(dl); @@ -389,7 +389,7 @@ bool JIT::regimm(u32 instr) { code.call(rax); break; case 0x13: - code.mov(rcx, qword[rdi + GPR_OFFSET(RS(instr))]); + code.mov(rcx, qword[rdi + GPR_OFFSET(RS(instr), this)]); code.xor_(rdx, rdx); code.cmp(rcx, 0); code.setge(dl); @@ -422,27 +422,27 @@ bool JIT::Exec(Mem& mem, u32 instr) { res = true; break; case 0x04: - code.mov(r8, qword[rdi + GPR_OFFSET(RS(instr))]); - code.mov(rcx, qword[rdi + GPR_OFFSET(RT(instr))]); + code.mov(r8, qword[rdi + GPR_OFFSET(RS(instr), this)]); + code.mov(r9, qword[rdi + GPR_OFFSET(RT(instr), this)]); code.xor_(rdx, rdx); - code.cmp(r8, rcx); + code.cmp(r8, r9); code.sete(dl); code.mov(rax, (u64)b); code.call(rax); res = true; break; case 0x05: - code.mov(r8, qword[rdi + GPR_OFFSET(RS(instr))]); - code.mov(rcx, qword[rdi + GPR_OFFSET(RT(instr))]); + code.mov(r8, qword[rdi + GPR_OFFSET(RS(instr), this)]); + code.mov(r9, qword[rdi + GPR_OFFSET(RT(instr), this)]); code.xor_(rdx, rdx); - code.cmp(r8, rcx); + code.cmp(r8, r9); code.setne(dl); code.mov(rax, (u64)b); code.call(rax); res = true; break; case 0x06: - code.mov(r8, qword[rdi + GPR_OFFSET(RS(instr))]); + code.mov(r8, qword[rdi + GPR_OFFSET(RS(instr), this)]); code.xor_(rdx, rdx); code.test(r8, r8); code.setnz(dl); @@ -451,7 +451,7 @@ bool JIT::Exec(Mem& mem, u32 instr) { res = true; break; case 0x07: - code.mov(r8, qword[rdi + GPR_OFFSET(RS(instr))]); + code.mov(r8, qword[rdi + GPR_OFFSET(RS(instr), this)]); code.xor_(rdx, rdx); code.test(r8, r8); code.setg(dl); @@ -491,12 +491,12 @@ bool JIT::Exec(Mem& mem, u32 instr) { code.mov(rax, (u64)lui); code.call(rax); break; - case 0x10: cop0Decode(regs, *this, instr); break; - case 0x11: res = cop1Decode(regs, *this, instr); break; + case 0x10: cop0Decode(*this, instr); break; + case 0x11: res = cop1Decode(*this, instr); break; case 0x12: cop2Decode(instr); break; case 0x14: - code.mov(r8, qword[rdi + GPR_OFFSET(RS(instr))]); - code.mov(rcx, qword[rdi + GPR_OFFSET(RT(instr))]); + code.mov(r8, qword[rdi + GPR_OFFSET(RS(instr), this)]); + code.mov(rcx, qword[rdi + GPR_OFFSET(RT(instr), this)]); code.xor_(rdx, rdx); code.cmp(r8, rcx); code.sete(dl); @@ -504,8 +504,8 @@ bool JIT::Exec(Mem& mem, u32 instr) { code.call(rax); break; case 0x15: - code.mov(r8, qword[rdi + GPR_OFFSET(RS(instr))]); - code.mov(rcx, qword[rdi + GPR_OFFSET(RT(instr))]); + code.mov(r8, qword[rdi + GPR_OFFSET(RS(instr), this)]); + code.mov(rcx, qword[rdi + GPR_OFFSET(RT(instr), this)]); code.xor_(rdx, rdx); code.cmp(r8, rcx); code.setne(dl); @@ -513,7 +513,7 @@ bool JIT::Exec(Mem& mem, u32 instr) { code.call(rax); break; case 0x16: - code.mov(r8, qword[rdi + GPR_OFFSET(RS(instr))]); + code.mov(r8, qword[rdi + GPR_OFFSET(RS(instr), this)]); code.xor_(rdx, rdx); code.cmp(r8, 0); code.setle(dl); @@ -521,7 +521,7 @@ bool JIT::Exec(Mem& mem, u32 instr) { code.call(rax); break; case 0x17: - code.mov(r8, qword[rdi + GPR_OFFSET(RS(instr))]); + code.mov(r8, qword[rdi + GPR_OFFSET(RS(instr), this)]); code.xor_(rdx, rdx); code.cmp(r8, 0); code.setg(dl); diff --git a/src/backend/core/jit/instructions.cpp b/src/backend/core/jit/instructions.cpp index f229469a..0132cdb6 100644 --- a/src/backend/core/jit/instructions.cpp +++ b/src/backend/core/jit/instructions.cpp @@ -1,7 +1,6 @@ #include -#define se_imm(x) ((s16)((x) & 0xFFFF)) -#define check_address_error(mask, addr) (((!regs.cop0.is_64bit_addressing) && (s32)(addr) != (addr)) || (((addr) & (mask)) != 0)) +#define check_address_error(mask, vaddr) (((!regs.cop0.is_64bit_addressing) && (s32)(vaddr) != (vaddr)) || (((vaddr) & (mask)) != 0)) #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) @@ -11,6 +10,9 @@ void add(JIT& dyn, u32 instr) { u32 rs = (s32)regs.gpr[RS(instr)]; u32 rt = (s32)regs.gpr[RT(instr)]; u32 result = rs + rt; + + Util::debug("add r{}, r{}, r{} = {:08X}\n", RD(instr), RS(instr), RT(instr), result); + if(check_signed_overflow(rs, rt, result)) { FireException(regs, ExceptionCode::Overflow, 0, true); } else { @@ -27,6 +29,7 @@ void addu(JIT& dyn, u32 instr) { s32 rt = (s32)regs.gpr[RT(instr)]; s32 result = rs + rt; regs.gpr[RD(instr)] = result; + Util::debug("addu r{}, r{}, r{} = {:08X}\n", RD(instr), RS(instr), RT(instr), (u32)result); } } @@ -35,6 +38,7 @@ void addi(JIT& dyn, u32 instr) { u32 rs = regs.gpr[RS(instr)]; u32 imm = s32(s16(instr)); u32 result = rs + imm; + Util::debug("addi r{}, r{}, {:08X} = {:08X}\n", RT(instr), RS(instr), imm, result); if(check_signed_overflow(rs, imm, result)) { FireException(regs, ExceptionCode::Overflow, 0, true); } else { @@ -174,8 +178,8 @@ void branch(JIT& dyn, bool cond, s64 address) { void branch_likely(JIT& dyn, bool cond, s64 address) { Registers& regs = dyn.regs; - regs.delaySlot = true; if (cond) { + regs.delaySlot = true; regs.nextPC = address; } else { regs.SetPC64(regs.nextPC); @@ -184,7 +188,8 @@ void branch_likely(JIT& dyn, bool cond, s64 address) { void b(JIT& dyn, u32 instr, bool cond) { Registers& regs = dyn.regs; - s64 offset = (s64)se_imm(instr) << 2; + s16 imm = instr; + s64 offset = (s64)imm << 2; s64 address = regs.pc + offset; branch(dyn, cond, address); } @@ -192,14 +197,16 @@ void b(JIT& dyn, u32 instr, bool cond) { void blink(JIT& dyn, u32 instr, bool cond) { Registers& regs = dyn.regs; regs.gpr[31] = regs.nextPC; - s64 offset = (s64)se_imm(instr) << 2; + s16 imm = instr; + s64 offset = (s64)imm << 2; s64 address = regs.pc + offset; branch(dyn, cond, address); } void bl(JIT& dyn, u32 instr, bool cond) { Registers& regs = dyn.regs; - s64 offset = (s64)se_imm(instr) << 2; + s16 imm = instr; + s64 offset = (s64)imm << 2; s64 address = regs.pc + offset; branch_likely(dyn, cond, address); } @@ -207,7 +214,8 @@ void bl(JIT& dyn, u32 instr, bool cond) { void bllink(JIT& dyn, u32 instr, bool cond) { Registers& regs = dyn.regs; regs.gpr[31] = regs.nextPC; - s64 offset = (s64)se_imm(instr) << 2; + s16 imm = instr; + s64 offset = (s64)imm << 2; s64 address = regs.pc + offset; branch_likely(dyn, cond, address); } @@ -247,7 +255,7 @@ void lh(JIT& dyn, u32 instr) { HandleTLBException(regs, address); FireException(regs, GetTLBExceptionCode(regs.cop0.tlbError, LOAD), 0, true); } else { - regs.gpr[RT(instr)] = (s16)mem.Read16(regs, address); + regs.gpr[RT(instr)] = (s16)mem.Read16(regs, paddr); } } @@ -256,7 +264,7 @@ void lw(JIT& dyn, u32 instr) { Mem& mem = dyn.mem; s16 offset = instr; u64 address = regs.gpr[RS(instr)] + offset; - if (check_address_error(address, 0b11)) { + if (check_address_error(0b11, address)) { HandleTLBException(regs, address); FireException(regs, ExceptionCode::AddressErrorLoad, 0, true); return; @@ -330,14 +338,20 @@ void ld(JIT& dyn, u32 instr) { Registers& regs = dyn.regs; Mem& mem = dyn.mem; s64 address = regs.gpr[RS(instr)] + (s16)instr; - if (check_address_error(address, 0b111)) { + if (check_address_error(0b111, address)) { HandleTLBException(regs, address); FireException(regs, ExceptionCode::AddressErrorLoad, 0, true); return; } - s64 value = mem.Read64(regs, address); - regs.gpr[RT(instr)] = value; + u32 paddr = 0; + if(!MapVAddr(regs, LOAD, address, paddr)) { + HandleTLBException(regs, address); + FireException(regs, GetTLBExceptionCode(regs.cop0.tlbError, LOAD), 0, true); + } else { + s64 value = mem.Read64(regs, paddr); + regs.gpr[RT(instr)] = value; + } } void lld(JIT& dyn, u32 instr) { @@ -402,43 +416,66 @@ void lbu(JIT& dyn, u32 instr) { Registers& regs = dyn.regs; Mem& mem = dyn.mem; u64 address = regs.gpr[RS(instr)] + (s16)instr; - u8 value = mem.Read8(regs, address); - regs.gpr[RT(instr)] = value; + u32 paddr; + if (!MapVAddr(regs, LOAD, address, paddr)) { + HandleTLBException(regs, address); + FireException(regs, GetTLBExceptionCode(regs.cop0.tlbError, LOAD), 0, true); + } else { + u8 value = mem.Read8(regs, paddr); + regs.gpr[RT(instr)] = value; + } } void lhu(JIT& dyn, u32 instr) { Registers& regs = dyn.regs; Mem& mem = dyn.mem; s64 address = regs.gpr[RS(instr)] + (s16)instr; - if (check_address_error(address, 0b1)) { + if ((address & 0b1) > 0) { HandleTLBException(regs, address); FireException(regs, ExceptionCode::AddressErrorLoad, 0, true); return; } - - u16 value = mem.Read16(regs, address); - regs.gpr[RT(instr)] = value; + u32 paddr; + if (!MapVAddr(regs, LOAD, address, paddr)) { + HandleTLBException(regs, address); + FireException(regs, GetTLBExceptionCode(regs.cop0.tlbError, LOAD), 0, true); + } else { + u16 value = mem.Read16(regs, paddr); + regs.gpr[RT(instr)] = value; + } } void lwu(JIT& dyn, u32 instr) { Registers& regs = dyn.regs; Mem& mem = dyn.mem; s64 address = regs.gpr[RS(instr)] + (s16)instr; - if (check_address_error(address, 0b11)) { + if ((address & 0b11) > 0) { HandleTLBException(regs, address); FireException(regs, ExceptionCode::AddressErrorLoad, 0, true); return; } - u32 value = mem.Read32(regs, address); - regs.gpr[RT(instr)] = value; + u32 paddr; + if (!MapVAddr(regs, LOAD, address, paddr)) { + HandleTLBException(regs, address); + FireException(regs, GetTLBExceptionCode(regs.cop0.tlbError, LOAD), 0, true); + } else { + u32 value = mem.Read32(regs, paddr); + regs.gpr[RT(instr)] = value; + } } void sb(JIT& dyn, u32 instr) { Registers& regs = dyn.regs; Mem& mem = dyn.mem; - u32 address = regs.gpr[RS(instr)] + (s16)instr; - mem.Write8(regs, dyn, address, regs.gpr[RT(instr)]); + u64 address = regs.gpr[RS(instr)] + (s16)instr; + u32 paddr; + if (!MapVAddr(regs, STORE, address, paddr)) { + HandleTLBException(regs, address); + FireException(regs, GetTLBExceptionCode(regs.cop0.tlbError, STORE), 0, true); + } else { + mem.Write8(regs, paddr, regs.gpr[RT(instr)]); + } } void sc(JIT& dyn, u32 instr) { @@ -458,7 +495,7 @@ void sc(JIT& dyn, u32 instr) { HandleTLBException(regs, address); FireException(regs, GetTLBExceptionCode(regs.cop0.tlbError, STORE), 0, true); } else { - mem.Write32(regs, dyn, paddr, regs.gpr[RT(instr)]); + mem.Write32(regs, paddr, regs.gpr[RT(instr)]); regs.gpr[RT(instr)] = 1; } } else { @@ -469,37 +506,44 @@ void sc(JIT& dyn, u32 instr) { void scd(JIT& dyn, u32 instr) { Registers& regs = dyn.regs; Mem& mem = dyn.mem; + if (!regs.cop0.is_64bit_addressing && !regs.cop0.kernel_mode) { + FireException(regs, ExceptionCode::ReservedInstruction, 0, true); + return; + } + s64 address = regs.gpr[RS(instr)] + (s16)instr; - if (check_address_error(address, 0b111)) { + if ((address & 0b111) > 0) { HandleTLBException(regs, address); FireException(regs, ExceptionCode::AddressErrorStore, 0, true); return; } if(regs.cop0.llbit) { - mem.Write64(regs, dyn, address, regs.gpr[RT(instr)]); + regs.cop0.llbit = false; + u32 paddr = 0; + if(!MapVAddr(regs, STORE, address, paddr)) { + HandleTLBException(regs, address); + FireException(regs, GetTLBExceptionCode(regs.cop0.tlbError, STORE), 0, true); + } else { + mem.Write32(regs, paddr, regs.gpr[RT(instr)]); + regs.gpr[RT(instr)] = 1; + } + } else { + regs.gpr[RT(instr)] = 0; } - - regs.gpr[RT(instr)] = (s64)((u64)regs.cop0.llbit); - regs.cop0.llbit = false; } void sh(JIT& dyn, u32 instr) { Registers& regs = dyn.regs; Mem& mem = dyn.mem; s64 address = regs.gpr[RS(instr)] + (s16)instr; - if (check_address_error(address, 0b1)) { - HandleTLBException(regs, address); - FireException(regs, ExceptionCode::AddressErrorStore, 0, true); - return; - } u32 physical; if(!MapVAddr(regs, STORE, address, physical)) { HandleTLBException(regs, address); FireException(regs, GetTLBExceptionCode(regs.cop0.tlbError, STORE), 0, true); } else { - mem.Write16(regs, dyn, physical, regs.gpr[RT(instr)]); + mem.Write16(regs, physical, regs.gpr[RT(instr)]); } } @@ -508,7 +552,7 @@ void sw(JIT& dyn, u32 instr) { Mem& mem = dyn.mem; s16 offset = instr; u64 address = regs.gpr[RS(instr)] + offset; - if (check_address_error(address, 0b11)) { + if (check_address_error(0b11, address)) { HandleTLBException(regs, address); FireException(regs, ExceptionCode::AddressErrorStore, 0, true); return; @@ -519,7 +563,7 @@ void sw(JIT& dyn, u32 instr) { HandleTLBException(regs, address); FireException(regs, GetTLBExceptionCode(regs.cop0.tlbError, STORE), 0, true); } else { - mem.Write32(regs, dyn, physical, regs.gpr[RT(instr)]); + mem.Write32(regs, physical, regs.gpr[RT(instr)]); } } @@ -527,7 +571,7 @@ void sd(JIT& dyn, u32 instr) { Registers& regs = dyn.regs; Mem& mem = dyn.mem; s64 address = regs.gpr[RS(instr)] + (s16)instr; - if (check_address_error(address, 0b11)) { + if (check_address_error(0b111, address)) { HandleTLBException(regs, address); FireException(regs, ExceptionCode::AddressErrorStore, 0, true); return; @@ -538,9 +582,8 @@ void sd(JIT& dyn, u32 instr) { HandleTLBException(regs, address); FireException(regs, GetTLBExceptionCode(regs.cop0.tlbError, STORE), 0, true); } else { - mem.Write64(regs, dyn, physical, regs.gpr[RT(instr)]); + mem.Write64(regs, physical, regs.gpr[RT(instr)]); } - } void sdl(JIT& dyn, u32 instr) { @@ -556,7 +599,7 @@ void sdl(JIT& dyn, u32 instr) { u64 mask = 0xFFFFFFFFFFFFFFFF >> shift; u64 data = mem.Read64(regs, paddr & ~7); u64 rt = regs.gpr[RT(instr)]; - mem.Write64(regs, dyn, paddr & ~7, (data & ~mask) | (rt >> shift)); + mem.Write64(regs, paddr & ~7, (data & ~mask) | (rt >> shift)); } } @@ -573,7 +616,7 @@ void sdr(JIT& dyn, u32 instr) { u64 mask = 0xFFFFFFFFFFFFFFFF << shift; u64 data = mem.Read64(regs, paddr & ~7); u64 rt = regs.gpr[RT(instr)]; - mem.Write64(regs, dyn, paddr & ~7, (data & ~mask) | (rt << shift)); + mem.Write64(regs, paddr & ~7, (data & ~mask) | (rt << shift)); } } @@ -590,7 +633,7 @@ void swl(JIT& dyn, u32 instr) { u32 mask = 0xFFFFFFFF >> shift; u32 data = mem.Read32(regs, paddr & ~3); u32 rt = regs.gpr[RT(instr)]; - mem.Write32(regs, dyn, paddr & ~3, (data & ~mask) | (rt >> shift)); + mem.Write32(regs, paddr & ~3, (data & ~mask) | (rt >> shift)); } } @@ -607,7 +650,7 @@ void swr(JIT& dyn, u32 instr) { u32 mask = 0xFFFFFFFF << shift; u32 data = mem.Read32(regs, paddr & ~3); u32 rt = regs.gpr[RT(instr)]; - mem.Write32(regs, dyn, paddr & ~3, (data & ~mask) | (rt << shift)); + mem.Write32(regs, paddr & ~3, (data & ~mask) | (rt << shift)); } } @@ -634,8 +677,9 @@ void nor(JIT& dyn, u32 instr) { void j(JIT& dyn, u32 instr) { Registers& regs = dyn.regs; - u64 target = (instr & 0x3ffffff) << 2; - u64 address = ((regs.pc - 4) & ~0xfffffff) | target; + Mem& mem = dyn.mem; + s32 target = (instr & 0x3ffffff) << 2; + s64 address = (regs.oldPC & ~0xfffffff) | target; branch(dyn, true, address); } @@ -648,6 +692,7 @@ void jal(JIT& dyn, u32 instr) { void jalr(JIT& dyn, u32 instr) { Registers& regs = dyn.regs; + Mem& mem = dyn.mem; branch(dyn, true, regs.gpr[RS(instr)]); if(likely(RD(instr) != 0)) { regs.gpr[RD(instr)] = regs.pc + 4; @@ -656,12 +701,14 @@ void jalr(JIT& dyn, u32 instr) { void slti(JIT& dyn, u32 instr) { Registers& regs = dyn.regs; - regs.gpr[RT(instr)] = regs.gpr[RS(instr)] < se_imm(instr); + s16 imm = instr; + regs.gpr[RT(instr)] = regs.gpr[RS(instr)] < imm; } void sltiu(JIT& dyn, u32 instr) { Registers& regs = dyn.regs; - regs.gpr[RT(instr)] = (u64)regs.gpr[RS(instr)] < se_imm(instr); + s16 imm = instr; + regs.gpr[RT(instr)] = (u64)regs.gpr[RS(instr)] < imm; } void slt(JIT& dyn, u32 instr) { @@ -812,8 +859,8 @@ void sra(JIT& dyn, u32 instr) { void srav(JIT& dyn, u32 instr) { Registers& regs = dyn.regs; + s64 rt = regs.gpr[RT(instr)]; if(likely(RD(instr) != 0)) { - s64 rt = regs.gpr[RT(instr)]; s64 rs = regs.gpr[RS(instr)]; u8 sa = rs & 0x1f; s32 result = rt >> sa; @@ -855,11 +902,6 @@ void dsra32(JIT& dyn, u32 instr) { void jr(JIT& dyn, u32 instr) { Registers& regs = dyn.regs; s64 address = regs.gpr[RS(instr)]; - if (check_address_error(address, 0b11)) { - HandleTLBException(regs, address); - FireException(regs, ExceptionCode::DataBusError, 0, true); - } - branch(dyn, true, address); } @@ -972,9 +1014,8 @@ void mthi(JIT& dyn, u32 instr) { } void trap(JIT& dyn, bool cond) { - Registers& regs = dyn.regs; if(cond) { - FireException(regs, ExceptionCode::Trap, 0, true); + FireException(dyn.regs, ExceptionCode::Trap, 0, true); } } diff --git a/src/backend/core/mmio/SI.cpp b/src/backend/core/mmio/SI.cpp index d39daaf1..ce2c9cf6 100644 --- a/src/backend/core/mmio/SI.cpp +++ b/src/backend/core/mmio/SI.cpp @@ -74,7 +74,7 @@ void SI::Write(Mem& mem, Registers& regs, u32 addr, u32 val) { InterruptLower(mem.mmio.mi, regs, Interrupt::SI); break; default: - Util::panic("Unhandled SI[%08X] write (%08X)\n", addr, val); + Util::panic("Unhandled SI[{:08X}] write ({:08X})\n", addr, val); } } } \ No newline at end of file diff --git a/src/backend/core/registers/Cop0.cpp b/src/backend/core/registers/Cop0.cpp index 596e65d8..fbaa910d 100644 --- a/src/backend/core/registers/Cop0.cpp +++ b/src/backend/core/registers/Cop0.cpp @@ -323,7 +323,7 @@ ExceptionCode GetTLBExceptionCode(TLBError error, TLBAccessType accessType) { } } -void Cop0::decode(Registers& regs, Mem& mem, u32 instr) { +void Cop0::decode(Registers& regs, u32 instr) { u8 mask_cop = (instr >> 21) & 0x1F; u8 mask_cop2 = instr & 0x3F; switch(mask_cop) { diff --git a/src/backend/core/registers/Cop0.hpp b/src/backend/core/registers/Cop0.hpp index 55ab0e0e..8f0fc770 100644 --- a/src/backend/core/registers/Cop0.hpp +++ b/src/backend/core/registers/Cop0.hpp @@ -235,7 +235,7 @@ struct Cop0 { TLBEntry tlb[32]{}; TLBError tlbError = NONE; s64 openbus{}; - void decode(Registers&, Mem&, u32); + void decode(Registers&, u32); inline u32 GetRandom() { int val = rand(); int wired = GetWired(); diff --git a/src/backend/core/registers/Registers.cpp b/src/backend/core/registers/Registers.cpp index d96bc89a..8eecf253 100644 --- a/src/backend/core/registers/Registers.cpp +++ b/src/backend/core/registers/Registers.cpp @@ -6,6 +6,8 @@ Registers::Registers() { } void Registers::Reset() { + hi = 0; + lo = 0; delaySlot = false; prevDelaySlot = false; memset(gpr, 0, 32*sizeof(s64));