diff --git a/src/backend/core/JIT.cpp b/src/backend/core/JIT.cpp index efe6ba67..5ebf85fc 100644 --- a/src/backend/core/JIT.cpp +++ b/src/backend/core/JIT.cpp @@ -35,9 +35,8 @@ int JIT::Step() { /*regs.cop0.HandleTLBException(blockPC); regs.cop0.FireException(Cop0::GetTLBExceptionCode(regs.cop0.tlbError, Cop0::LOAD), 0, blockPC); return 1;*/ - Util::panic( - "[JIT]: Unhandled exception TLB exception {} when retrieving PC physical address! (virtual: 0x{:016lX})", - static_cast(Cop0::GetTLBExceptionCode(regs.cop0.tlbError, Cop0::LOAD)), static_cast(blockPC)); + Util::panic("[JIT]: Unhandled exception TLB exception {} when retrieving PC physical address! (virtual: 0x{:016X})", + static_cast(Cop0::GetTLBExceptionCode(regs.cop0.tlbError, Cop0::LOAD)), static_cast(blockPC)); } u32 upperIndex = paddr >> kUpperShift; @@ -45,12 +44,14 @@ int JIT::Step() { if (!blockCache[upperIndex].empty()) { if (blockCache[upperIndex][lowerIndex]) { + Util::trace("[JIT]: Executing already compiled block @ 0x{:016X}", blockPC); return blockCache[upperIndex][lowerIndex](); } } else { blockCache[upperIndex].resize(kLowerSize); } + Util::trace("[JIT]: Compiling block @ 0x{:016X}", blockPC); const auto block = code.getCurr(); blockCache[upperIndex][lowerIndex] = block; @@ -63,7 +64,6 @@ int JIT::Step() { bool branchWasLikely = false; bool blockEndsOnBranch = false; - // code.int3(); code.sub(code.rsp, 8); code.push(code.rbp); code.mov(code.rbp, reinterpret_cast(this)); // Load context pointer @@ -76,7 +76,7 @@ int JIT::Step() { regs.cop0.FireException(ExceptionCode::AddressErrorLoad, 0, blockPC); return 1;*/ - Util::panic("[JIT]: Unhandled exception ADL due to unaligned PC virtual value! (0x{:016lX})", blockPC); + Util::panic("[JIT]: Unhandled exception ADL due to unaligned PC virtual value! (0x{:016X})", blockPC); } if (!regs.cop0.MapVAddr(Cop0::LOAD, blockPC, paddr)) { @@ -84,7 +84,7 @@ int JIT::Step() { regs.cop0.FireException(Cop0::GetTLBExceptionCode(regs.cop0.tlbError, Cop0::LOAD), 0, blockPC); return 1;*/ Util::panic( - "[JIT]: Unhandled exception TLB exception {} when retrieving PC physical address! (virtual: 0x{:016lX})", + "[JIT]: Unhandled exception TLB exception {} when retrieving PC physical address! (virtual: 0x{:016X})", static_cast(Cop0::GetTLBExceptionCode(regs.cop0.tlbError, Cop0::LOAD)), static_cast(blockPC)); } @@ -127,9 +127,9 @@ int JIT::Step() { code.add(code.rsp, 8); code.ret(); code.setProtectModeRE(); - const auto dump = code.getCode(); - Util::WriteFileBinary(dump, code.getSize(), "jit.dump"); - // Util::panic(""); + // const auto dump = code.getCode(); + // Util::WriteFileBinary(dump, code.getSize(), "jit.dump"); + // Util::panic(""); return block(); } diff --git a/src/backend/core/JIT.hpp b/src/backend/core/JIT.hpp index 823844ae..7f612444 100644 --- a/src/backend/core/JIT.hpp +++ b/src/backend/core/JIT.hpp @@ -92,6 +92,7 @@ private: void SkipSlot(); void SkipSlotConstant(); + void BranchNotTaken(); void BranchTaken(s64 offs); void BranchTaken(const Xbyak::Reg64 &offs); void BranchAbsTaken(s64 addr); @@ -185,17 +186,17 @@ private: void mthi(u32); void mtlo(u32); void nor(u32); - void sb(u32) {} - void sc(u32) {} - void scd(u32) {} - void sd(u32) {} - void sdc1(u32) {} - void sdl(u32) {} - void sdr(u32) {} - void sh(u32) {} + void sb(u32) { Util::panic("[JIT] Implement sb!"); } + void sc(u32) { Util::panic("[JIT] Implement sc!"); } + void scd(u32) { Util::panic("[JIT] Implement scd!"); } + void sd(u32) { Util::panic("[JIT] Implement sd!"); } + void sdc1(u32) { Util::panic("[JIT] Implement sdc1!"); } + void sdl(u32) { Util::panic("[JIT] Implement sdl!"); } + void sdr(u32) { Util::panic("[JIT] Implement sdr!"); } + void sh(u32) { Util::panic("[JIT] Implement sh!"); } void sw(u32); - void swl(u32) {} - void swr(u32) {} + void swl(u32) { Util::panic("[JIT] Implement swl!"); } + void swr(u32) { Util::panic("[JIT] Implement swr!"); } void slti(u32); void sltiu(u32); void slt(u32); @@ -204,12 +205,12 @@ private: void sllv(u32); void sub(u32); void subu(u32); - void swc1(u32) {} + void swc1(u32) { Util::panic("[JIT] Implement swc1!"); } void sra(u32); void srav(u32); void srl(u32); void srlv(u32); - void trap(bool) {} + void trap(bool) { Util::panic("[JIT] Implement trap!"); } void or_(u32); void ori(u32); void xor_(u32); diff --git a/src/backend/core/jit/helpers.hpp b/src/backend/core/jit/helpers.hpp index 8e8b5cb9..9878313e 100644 --- a/src/backend/core/jit/helpers.hpp +++ b/src/backend/core/jit/helpers.hpp @@ -38,12 +38,22 @@ static bool InstrEndsBlock(const u32 instr) { } static bool IsBranchLikely(const u32 instr) { - switch (instr >> 26 & 0x1F) { + switch (instr >> 26 & 0x3F) { case BEQL: case BNEL: case BLEZL: case BGTZL: return true; + case REGIMM: + switch (instr >> 16 & 0x1f) { + case BLTZL: + case BGEZL: + case BLTZALL: + case BGEZALL: + return true; + default: + return false; + } case COP1: { const u8 mask_sub = (instr >> 21) & 0x1F; @@ -58,15 +68,7 @@ static bool IsBranchLikely(const u32 instr) { return false; } default: - switch (instr >> 16 & 0x1F) { - case BLTZL: - case BGEZL: - case BLTZALL: - case BGEZALL: - return true; - default: - return false; - } + return false; } } } // namespace n64 diff --git a/src/backend/core/jit/instructions.cpp b/src/backend/core/jit/instructions.cpp index f5f69b5c..0f3e9c26 100644 --- a/src/backend/core/jit/instructions.cpp +++ b/src/backend/core/jit/instructions.cpp @@ -165,6 +165,11 @@ void JIT::BranchTaken(const s64 offs) { code.mov(REG(qword, pc), code.rax); } +void JIT::BranchNotTaken() { + code.mov(code.rax, blockPC); + code.mov(REG(qword, pc), code.rax); +} + void JIT::BranchTaken(const Xbyak::Reg64 &offs) { code.add(offs, blockPC); code.mov(REG(qword, pc), offs); @@ -181,8 +186,7 @@ void JIT::BranchAbsTaken(const Xbyak::Reg64 &addr) { code.mov(REG(qword, pc), ad do { \ Xbyak::Label taken, not_taken; \ code.j##cond(taken); \ - code.mov(code.rax, blockPC); \ - code.mov(REG(qword, pc), code.rax); \ + BranchNotTaken(); \ code.jmp(not_taken); \ code.L(taken); \ BranchTaken(offs); \ @@ -194,8 +198,7 @@ void JIT::BranchAbsTaken(const Xbyak::Reg64 &addr) { code.mov(REG(qword, pc), ad do { \ Xbyak::Label taken, not_taken; \ code.j##cond(taken); \ - code.mov(code.rax, blockPC); \ - code.mov(REG(qword, pc), code.rax); \ + BranchNotTaken(); \ code.jmp(not_taken); \ code.L(taken); \ BranchAbsTaken(addr); \ @@ -217,7 +220,10 @@ void JIT::BranchAbsTaken(const Xbyak::Reg64 &addr) { code.mov(REG(qword, pc), ad void JIT::branch_constant(const bool cond, const s64 offset) { if (cond) { BranchTaken(offset); + return; } + + BranchNotTaken(); } void JIT::branch_likely_constant(const bool cond, const s64 offset) { @@ -231,35 +237,46 @@ void JIT::branch_likely_constant(const bool cond, const s64 offset) { void JIT::branch_abs_constant(const bool cond, const s64 address) { if (cond) { BranchAbsTaken(address); + return; } + + BranchNotTaken(); } void JIT::bfc0(u32 instr) { const s16 imm = instr; const s64 offset = u64((s64)imm) << 2; - const s64 address = regs.pc + offset; - // branch(regs, EvaluateCondition(regs, cond, regs.cop1.fcr31.compare, 1), address); + const s64 address = blockPC + offset; + // code.mov(code.al, REG(byte, cop1.fcr31.compare)); + // code.test(code.al, code.al); + // branch(address, z); } void JIT::blfc0(u32 instr) { const s16 imm = instr; const s64 offset = u64((s64)imm) << 2; - const s64 address = regs.pc + offset; - // branch_likely(regs, EvaluateCondition(regs, cond, regs.cop1.fcr31.compare, 1), address); + const s64 address = blockPC + offset; + // code.mov(code.al, REG(byte, cop1.fcr31.compare)); + // code.test(code.al, code.al); + // branch_likely(address, z); } void JIT::bfc1(u32 instr) { const s16 imm = instr; const s64 offset = u64((s64)imm) << 2; - const s64 address = regs.pc + offset; - // branch(regs, EvaluateCondition(regs, cond, regs.cop1.fcr31.compare, 1), address); + const s64 address = blockPC + offset; + // code.mov(code.al, REG(byte, cop1.fcr31.compare)); + // code.test(code.al, code.al); + // branch(address, nz); } void JIT::blfc1(u32 instr) { const s16 imm = instr; const s64 offset = u64((s64)imm) << 2; - const s64 address = regs.pc + offset; - // branch_likely(regs, EvaluateCondition(regs, cond, regs.cop1.fcr31.compare, 1), address); + const s64 address = blockPC + offset; + // code.mov(code.al, REG(byte, cop1.fcr31.compare)); + // code.test(code.al, code.al); + // branch_likely(address, nz); } void JIT::bltz(const u32 instr) { @@ -547,7 +564,7 @@ void JIT::dadd(u32 instr) { return; } - if(regs.IsRegConstant(RS(instr))) { + if (regs.IsRegConstant(RS(instr))) { auto rs = regs.Read(RS(instr)); regs.Read(RT(instr), code.rax); code.add(code.rax, rs); @@ -555,7 +572,7 @@ void JIT::dadd(u32 instr) { return; } - if(regs.IsRegConstant(RT(instr))) { + if (regs.IsRegConstant(RT(instr))) { auto rt = regs.Read(RT(instr)); regs.Read(RS(instr), code.rax); code.add(code.rax, rt); @@ -589,7 +606,7 @@ void JIT::daddi(u32 instr) { regs.Read(RS(instr), code.rax); code.add(code.rax, imm); - regs.Write(RT(instr), code.rax); + regs.Write(RT(instr), code.rax); } void JIT::daddiu(u32 instr) { @@ -847,7 +864,7 @@ void JIT::dsubu(u32 instr) { void JIT::j(const u32 instr) { const s32 target = (instr & 0x3ffffff) << 2; - const s64 oldPC = branchPC - 8; + const s64 oldPC = blockPC - 8; const s64 address = (oldPC & ~0xfffffff) | target; branch_abs_constant(true, address); } @@ -882,8 +899,10 @@ void JIT::lbu(u32 instr) { // regs.cop0.FireException(Cop0::GetTLBExceptionCode(regs.cop0.tlbError, Cop0::LOAD), 0, regs.oldPC); Util::panic("[JIT]: Unhandled TLBL exception in LBU!"); } else { - const u8 value = mem.Read(regs, paddr); - regs.Write(RT(instr), value); + code.mov(code.rsi, code.ptr[code.rbp + (reinterpret_cast(®s) - reinterpret_cast(this))]); + code.mov(code.edx, paddr); + emitMemberFunctionCall(&Mem::Read, &mem); + regs.Write(RT(instr), code.rax); } } else { Util::panic("[JIT]: Implement non constant LBU!"); @@ -898,7 +917,10 @@ void JIT::lb(u32 instr) { // regs.cop0.FireException(Cop0::GetTLBExceptionCode(regs.cop0.tlbError, Cop0::LOAD), 0, regs.oldPC); Util::panic("[JIT]: Unhandled TLBL exception in LB!"); } else { - regs.Write(RT(instr), (s8)mem.Read(regs, paddr)); + code.mov(code.rsi, code.ptr[code.rbp + (reinterpret_cast(®s) - reinterpret_cast(this))]); + code.mov(code.edx, paddr); + emitMemberFunctionCall(&Mem::Read, &mem); + regs.Write(RT(instr), code.rax); } } else { Util::panic("[JIT]: Implement non constant LB!"); @@ -921,8 +943,10 @@ void JIT::ld(u32 instr) { // regs.cop0.FireException(Cop0::GetTLBExceptionCode(regs.cop0.tlbError, Cop0::LOAD), 0, regs.oldPC); Util::panic("[JIT]: Unhandled TLBL exception in LD!"); } else { - const s64 value = mem.Read(regs, paddr); - regs.Write(RT(instr), value); + code.mov(code.rsi, code.ptr[code.rbp + (reinterpret_cast(®s) - reinterpret_cast(this))]); + code.mov(code.edx, paddr); + emitMemberFunctionCall(&Mem::Read, &mem); + regs.Write(RT(instr), code.rax); } } else { Util::panic("[JIT]: Implement non constant LD!"); @@ -956,6 +980,7 @@ void JIT::ldl(u32 instr) { // regs.cop0.FireException(Cop0::GetTLBExceptionCode(regs.cop0.tlbError, Cop0::LOAD), 0, regs.oldPC); Util::panic("[JIT]: Unhandled TLBL exception in LDL!"); } else { + Util::panic("[JIT]: Implement constant LDL!"); const s32 shift = 8 * ((address ^ 0) & 7); const u64 mask = 0xFFFFFFFFFFFFFFFF << shift; const u64 data = mem.Read(regs, paddr & ~7); @@ -976,6 +1001,7 @@ void JIT::ldr(u32 instr) { // regs.cop0.FireException(Cop0::GetTLBExceptionCode(regs.cop0.tlbError, Cop0::LOAD), 0, regs.oldPC); Util::panic("[JIT]: Unhandled TLBL exception in LDR!"); } else { + Util::panic("[JIT]: Implement constant LDR!"); const s32 shift = 8 * ((address ^ 7) & 7); const u64 mask = 0xFFFFFFFFFFFFFFFF >> shift; const u64 data = mem.Read(regs, paddr & ~7); @@ -1016,15 +1042,16 @@ void JIT::lh(u32 instr) { Util::panic("[JIT]: Implement non constant LH!"); } -void JIT::lhu(u32) {} +void JIT::lhu(u32) { Util::panic("[JIT]: Implement LHU!"); } -void JIT::ll(u32) {} +void JIT::ll(u32) { Util::panic("[JIT]: Implement constant LL!"); } -void JIT::lld(u32) {} +void JIT::lld(u32) { Util::panic("[JIT]: Implement constant LLD!"); } void JIT::lw(u32 instr) { + const s16 offset = instr; + u32 paddr = 0; if (regs.IsRegConstant(RS(instr))) { - const s16 offset = instr; const u64 address = regs.Read(RS(instr)) + offset; if (check_address_error(0b11, address)) { // regs.cop0.HandleTLBException(address); @@ -1034,7 +1061,6 @@ void JIT::lw(u32 instr) { return; } - u32 paddr = 0; if (!regs.cop0.MapVAddr(Cop0::LOAD, address, paddr)) { // regs.cop0.HandleTLBException(address); // regs.cop0.FireException(Cop0::GetTLBExceptionCode(regs.cop0.tlbError, Cop0::LOAD), 0, regs.oldPC); @@ -1049,22 +1075,32 @@ void JIT::lw(u32 instr) { return; } - Util::panic("[JIT]: Implement non constant LW!"); + code.mov(code.esi, Cop0::LOAD); + regs.Read(RS(instr), code.rdx); + code.add(code.rdx, offset); + code.mov(code.rcx, reinterpret_cast(&paddr)); + emitMemberFunctionCall(&Cop0::MapVAddr, ®s.cop0); + + code.mov(code.rsi, code.ptr[code.rbp + (reinterpret_cast(®s) - reinterpret_cast(this))]); + code.mov(code.edx, paddr); + emitMemberFunctionCall(&Mem::Read, &mem); + regs.Write(RT(instr), code.rax); } -void JIT::lwc1(u32) {} +void JIT::lwc1(u32) { Util::panic("[JIT]: Implement constant LWC1!"); } -void JIT::lwl(u32) {} +void JIT::lwl(u32) { Util::panic("[JIT]: Implement constant LWL!"); } -void JIT::lwu(u32) {} +void JIT::lwu(u32) { Util::panic("[JIT]: Implement constant LWU!"); } -void JIT::lwr(u32) {} +void JIT::lwr(u32) { Util::panic("[JIT]: Implement constant LWR!"); } void JIT::mfhi(u32 instr) { if (regs.hiIsConstant) { regs.Write(RD(instr), regs.hi); } else { - Util::panic("[JIT]: Implement non constant MFHI!"); + code.mov(code.rax, REG(qword, hi)); + regs.Write(RD(instr), code.rax); } } @@ -1072,7 +1108,8 @@ void JIT::mflo(u32 instr) { if (regs.loIsConstant) { regs.Write(RD(instr), regs.lo); } else { - Util::panic("[JIT]: Implement non constant MFLO!"); + code.mov(code.rax, REG(qword, lo)); + regs.Write(RD(instr), code.rax); } } @@ -1109,7 +1146,9 @@ void JIT::mthi(u32 instr) { regs.hi = regs.Read(RS(instr)); regs.hiIsConstant = true; } else { - Util::panic("[JIT]: Implement non constant MTHI!"); + regs.Read(RS(instr), code.rax); + code.mov(REG(qword, hi), code.rax); + regs.hiIsConstant = false; } } @@ -1118,7 +1157,9 @@ void JIT::mtlo(u32 instr) { regs.lo = regs.Read(RS(instr)); regs.loIsConstant = true; } else { - Util::panic("[JIT]: Implement non constant MTLO!"); + regs.Read(RS(instr), code.rax); + code.mov(REG(qword, lo), code.rax); + regs.loIsConstant = false; } } @@ -1165,12 +1206,14 @@ void JIT::sltu(u32 instr) { } void JIT::sll(u32 instr) { + u8 sa = ((instr >> 6) & 0x1f); if (regs.IsRegConstant(RT(instr))) { - u8 sa = ((instr >> 6) & 0x1f); s32 result = regs.Read(RT(instr)) << sa; regs.Write(RD(instr), (s64)result); } else { - Util::panic("[JIT]: Implement non constant SLL!"); + regs.Read(RT(instr), code.rax); + code.sal(code.rax, sa); + regs.Write(RD(instr), code.eax); } } @@ -1246,6 +1289,7 @@ void JIT::srl(u32 instr) { } void JIT::sw(const u32 instr) { + u32 physical; if (regs.IsRegConstant(RS(instr), RT(instr))) { const s16 offset = instr; const u64 address = regs.Read(RS(instr)) + offset; @@ -1256,7 +1300,6 @@ void JIT::sw(const u32 instr) { return; } - u32 physical; if (!regs.cop0.MapVAddr(Cop0::STORE, address, physical)) { // regs.cop0.HandleTLBException(address); // regs.cop0.FireException(Cop0::GetTLBExceptionCode(regs.cop0.tlbError, Cop0::STORE), 0, regs.oldPC); @@ -1281,7 +1324,6 @@ void JIT::sw(const u32 instr) { return; } - u32 physical; if (!regs.cop0.MapVAddr(Cop0::STORE, address, physical)) { // regs.cop0.HandleTLBException(address); // regs.cop0.FireException(Cop0::GetTLBExceptionCode(regs.cop0.tlbError, Cop0::STORE), 0, regs.oldPC); @@ -1303,7 +1345,6 @@ void JIT::sw(const u32 instr) { code.mov(code.esi, Cop0::STORE); - u32 physical; code.mov(code.rcx, reinterpret_cast(&physical)); emitMemberFunctionCall(&Cop0::MapVAddr, ®s.cop0); @@ -1321,7 +1362,6 @@ void JIT::sw(const u32 instr) { code.mov(code.esi, Cop0::STORE); - u32 physical; code.mov(code.rcx, reinterpret_cast(&physical)); emitMemberFunctionCall(&Cop0::MapVAddr, ®s.cop0); @@ -1351,9 +1391,6 @@ void JIT::or_(u32 instr) { } void JIT::ori(u32 instr) { - if (RT(instr) == 0) - return; - s64 imm = (u16)instr; if (regs.IsRegConstant(RS(instr))) { s64 result = imm | regs.Read(RS(instr)); diff --git a/src/backend/core/registers/Cop0.cpp b/src/backend/core/registers/Cop0.cpp index 4f56e0a3..e0ef2077 100644 --- a/src/backend/core/registers/Cop0.cpp +++ b/src/backend/core/registers/Cop0.cpp @@ -501,7 +501,7 @@ void Cop0::decodeInterp(const u32 instr) { eret(); break; default: - Util::panic("Unimplemented COP0 function {} {} ({:08X}) ({:016lX})", mask_cop2 >> 3, mask_cop2 & 7, instr, + Util::panic("Unimplemented COP0 function {} {} ({:08X}) ({:016X})", mask_cop2 >> 3, mask_cop2 & 7, instr, regs.oldPC); } break; diff --git a/src/backend/core/registers/Registers.cpp b/src/backend/core/registers/Registers.cpp index bb4f126d..5355bd17 100644 --- a/src/backend/core/registers/Registers.cpp +++ b/src/backend/core/registers/Registers.cpp @@ -120,7 +120,7 @@ void Registers::Write(size_t idx, bool v) { if (idx == 0) return; - gprIsConstant[idx] = isConstant; + gprIsConstant[idx] = true; gpr[idx] = v; } @@ -129,13 +129,13 @@ void Registers::Write(size_t idx, u64 v) { if (idx == 0) return; - gprIsConstant[idx] = isConstant; + gprIsConstant[idx] = true; gpr[idx] = v; } template <> void Registers::Write(size_t idx, s64 v) { - Write(idx, v, isConstant); + Write(idx, v); } template <> @@ -143,7 +143,7 @@ void Registers::Write(size_t idx, u32 v) { if (idx == 0) return; - gprIsConstant[idx] = isConstant; + gprIsConstant[idx] = true; gpr[idx] = v; } @@ -153,7 +153,7 @@ void Registers::Write(size_t idx, s32 v) { if (idx == 0) return; - gprIsConstant[idx] = isConstant; + gprIsConstant[idx] = true; gpr[idx] = v; } @@ -162,7 +162,7 @@ void Registers::Write(size_t idx, u16 v) { if (idx == 0) return; - gprIsConstant[idx] = isConstant; + gprIsConstant[idx] = true; gpr[idx] = v; } @@ -172,7 +172,7 @@ void Registers::Write(size_t idx, s16 v) { if (idx == 0) return; - gprIsConstant[idx] = isConstant; + gprIsConstant[idx] = true; gpr[idx] = v; } @@ -181,7 +181,7 @@ void Registers::Write(size_t idx, u8 v) { if (idx == 0) return; - gprIsConstant[idx] = isConstant; + gprIsConstant[idx] = true; gpr[idx] = v; } @@ -191,7 +191,7 @@ void Registers::Write(size_t idx, s8 v) { if (idx == 0) return; - gprIsConstant[idx] = isConstant; + gprIsConstant[idx] = true; gpr[idx] = v; }