From 6e69a37a62d48cdc8d538960cef4df29d2fe6397 Mon Sep 17 00:00:00 2001 From: irisz64 Date: Mon, 7 Jul 2025 10:36:16 +0200 Subject: [PATCH] register constant check optimization + disable branch likely's for now --- src/backend/core/jit/instructions.cpp | 52 ++++++++++++++---------- src/backend/core/registers/Registers.cpp | 37 ++++++++--------- src/backend/core/registers/Registers.hpp | 30 ++++++++++++-- 3 files changed, 75 insertions(+), 44 deletions(-) diff --git a/src/backend/core/jit/instructions.cpp b/src/backend/core/jit/instructions.cpp index 0b77a490..e74ceb63 100644 --- a/src/backend/core/jit/instructions.cpp +++ b/src/backend/core/jit/instructions.cpp @@ -310,6 +310,7 @@ void JIT::bgez(const u32 instr) { } void JIT::bltzl(const u32 instr) { + Util::panic("Implement branch likely < 0"); const s16 imm = instr; const s64 offset = u64((s64)imm) << 2; if (regs.IsRegConstant(RS(instr))) { @@ -323,6 +324,7 @@ void JIT::bltzl(const u32 instr) { } void JIT::bgezl(const u32 instr) { + Util::panic("Implement branch likely >= 0"); const s16 imm = instr; const s64 offset = u64((s64)imm) << 2; if (regs.IsRegConstant(RS(instr))) { @@ -364,6 +366,7 @@ void JIT::bgezal(const u32 instr) { } void JIT::bltzall(const u32 instr) { + Util::panic("Implement branch likely and link < 0"); const s16 imm = instr; const s64 offset = u64((s64)imm) << 2; regs.Write(31, blockNextPC); @@ -378,6 +381,7 @@ void JIT::bltzall(const u32 instr) { } void JIT::bgezall(const u32 instr) { + Util::panic("Implement branch likely and link >= 0"); const s16 imm = instr; const s64 offset = u64((s64)imm) << 2; regs.Write(31, blockNextPC); @@ -420,6 +424,7 @@ void JIT::beq(const u32 instr) { } void JIT::beql(const u32 instr) { + Util::panic("Implement branch likely =="); const s16 imm = instr; const s64 offset = u64((s64)imm) << 2; if (regs.IsRegConstant(RS(instr)) && regs.IsRegConstant(RT(instr))) { @@ -476,6 +481,7 @@ void JIT::bne(const u32 instr) { } void JIT::bnel(const u32 instr) { + Util::panic("Implement branch likely !="); const s16 imm = instr; const s64 offset = u64((s64)imm) << 2; if (regs.IsRegConstant(RS(instr)) && regs.IsRegConstant(RT(instr))) { @@ -517,6 +523,7 @@ void JIT::blez(const u32 instr) { } void JIT::blezl(const u32 instr) { + Util::panic("Implement branch likely <= 0"); const s16 imm = instr; const s64 offset = u64((s64)imm) << 2; if (regs.IsRegConstant(RS(instr))) { @@ -543,6 +550,7 @@ void JIT::bgtz(const u32 instr) { } void JIT::bgtzl(const u32 instr) { + Util::panic("Implement branch likely > 0"); const s16 imm = instr; const s64 offset = u64((s64)imm) << 2; if (regs.IsRegConstant(RS(instr))) { @@ -639,8 +647,8 @@ void JIT::ddiv(u32 instr) { regs.hi = remainder; } - regs.loIsConstant = true; - regs.hiIsConstant = true; + regs.SetLOConstant(); + regs.SetHIConstant(); } else { Util::panic("[JIT]: Implement non constant DDIV!"); } @@ -660,8 +668,8 @@ void JIT::ddivu(u32 instr) { regs.hi = (s64)remainder; } - regs.loIsConstant = true; - regs.hiIsConstant = true; + regs.SetLOConstant(); + regs.SetHIConstant(); } else { Util::panic("[JIT]: Implement non constant DDIVU!"); } @@ -686,8 +694,8 @@ void JIT::div(u32 instr) { regs.hi = remainder; } - regs.loIsConstant = true; - regs.hiIsConstant = true; + regs.SetLOConstant(); + regs.SetHIConstant(); } else { Util::panic("[JIT]: Implement non constant DIV!"); } @@ -707,8 +715,8 @@ void JIT::divu(u32 instr) { regs.hi = remainder; } - regs.loIsConstant = true; - regs.hiIsConstant = true; + regs.SetLOConstant(); + regs.SetHIConstant(); } else { Util::panic("[JIT]: Implement non constant DIVU!"); } @@ -721,8 +729,8 @@ void JIT::dmult(u32 instr) { s128 result = (s128)rt * (s128)rs; regs.lo = result & 0xFFFFFFFFFFFFFFFF; regs.hi = result >> 64; - regs.hiIsConstant = true; - regs.loIsConstant = true; + regs.SetHIConstant(); + regs.SetLOConstant(); } else { Util::panic("[JIT]: Implement non constant DMULT!"); } @@ -735,8 +743,8 @@ void JIT::dmultu(u32 instr) { u128 result = (u128)rt * (u128)rs; regs.lo = s64(result & 0xFFFFFFFFFFFFFFFF); regs.hi = s64(result >> 64); - regs.hiIsConstant = true; - regs.loIsConstant = true; + regs.SetHIConstant(); + regs.SetLOConstant(); } else { Util::panic("[JIT]: Implement non constant DMULT!"); } @@ -1135,7 +1143,7 @@ void JIT::lwu(u32) { Util::panic("[JIT]: Implement constant LWU!"); } void JIT::lwr(u32) { Util::panic("[JIT]: Implement constant LWR!"); } void JIT::mfhi(u32 instr) { - if (regs.hiIsConstant) { + if (regs.GetHIConstant()) { regs.Write(RD(instr), regs.hi); } else { code.mov(code.rax, REG(qword, hi)); @@ -1144,7 +1152,7 @@ void JIT::mfhi(u32 instr) { } void JIT::mflo(u32 instr) { - if (regs.loIsConstant) { + if (regs.GetLOConstant()) { regs.Write(RD(instr), regs.lo); } else { code.mov(code.rax, REG(qword, lo)); @@ -1158,9 +1166,9 @@ void JIT::mult(u32 instr) { auto rs = regs.Read(RS(instr)); s64 result = (s64)rt * (s64)rs; regs.lo = (s64)((s32)result); - regs.loIsConstant = true; + regs.SetLOConstant(); regs.hi = (s64)((s32)(result >> 32)); - regs.hiIsConstant = true; + regs.SetHIConstant(); } else { Util::panic("[JIT]: Implement non constant MULT!"); } @@ -1172,9 +1180,9 @@ void JIT::multu(u32 instr) { auto rs = regs.Read(RS(instr)); u64 result = (u64)rt * (u64)rs; regs.lo = (s64)((s32)result); - regs.loIsConstant = true; + regs.SetLOConstant(); regs.hi = (s64)((s32)(result >> 32)); - regs.hiIsConstant = true; + regs.SetHIConstant(); } else { Util::panic("[JIT]: Implement non constant MULTU!"); } @@ -1183,22 +1191,22 @@ void JIT::multu(u32 instr) { void JIT::mthi(u32 instr) { if (regs.IsRegConstant(RS(instr))) { regs.hi = regs.Read(RS(instr)); - regs.hiIsConstant = true; + regs.SetHIConstant(); } else { regs.Read(RS(instr), code.rax); code.mov(REG(qword, hi), code.rax); - regs.hiIsConstant = false; + regs.UnsetHIConstant(); } } void JIT::mtlo(u32 instr) { if (regs.IsRegConstant(RS(instr))) { regs.lo = regs.Read(RS(instr)); - regs.loIsConstant = true; + regs.SetLOConstant(); } else { regs.Read(RS(instr), code.rax); code.mov(REG(qword, lo), code.rax); - regs.loIsConstant = false; + regs.UnsetLOConstant(); } } diff --git a/src/backend/core/registers/Registers.cpp b/src/backend/core/registers/Registers.cpp index ad97fb78..4a8df75a 100644 --- a/src/backend/core/registers/Registers.cpp +++ b/src/backend/core/registers/Registers.cpp @@ -13,8 +13,7 @@ void Registers::Reset() { delaySlot = false; prevDelaySlot = false; gpr.fill(0); - gprIsConstant.fill(false); - gprIsConstant[0] = true; + regIsConstant = 1; // first bit is true indicating $zero is constant which yes it is always cop0.Reset(); cop1.Reset(); @@ -162,7 +161,7 @@ void Registers::Write(size_t idx, bool v) { if (idx == 0) return; - gprIsConstant[idx] = true; + regIsConstant |= (1 << idx); gpr[idx] = v; } @@ -171,7 +170,7 @@ void Registers::Write(size_t idx, u64 v) { if (idx == 0) return; - gprIsConstant[idx] = true; + regIsConstant |= (1 << idx); gpr[idx] = v; } @@ -185,7 +184,7 @@ void Registers::Write(size_t idx, u32 v) { if (idx == 0) return; - gprIsConstant[idx] = true; + regIsConstant |= (1 << idx); gpr[idx] = v; } @@ -195,7 +194,7 @@ void Registers::Write(size_t idx, s32 v) { if (idx == 0) return; - gprIsConstant[idx] = true; + regIsConstant |= (1 << idx); gpr[idx] = v; } @@ -204,7 +203,7 @@ void Registers::Write(size_t idx, u16 v) { if (idx == 0) return; - gprIsConstant[idx] = true; + regIsConstant |= (1 << idx); gpr[idx] = v; } @@ -214,7 +213,7 @@ void Registers::Write(size_t idx, s16 v) { if (idx == 0) return; - gprIsConstant[idx] = true; + regIsConstant |= (1 << idx); gpr[idx] = v; } @@ -222,8 +221,8 @@ template <> void Registers::Write(size_t idx, u8 v) { if (idx == 0) return; - - gprIsConstant[idx] = true; + + regIsConstant |= (1 << idx); gpr[idx] = v; } @@ -233,7 +232,7 @@ void Registers::Write(size_t idx, s8 v) { if (idx == 0) return; - gprIsConstant[idx] = true; + regIsConstant |= (1 << idx); gpr[idx] = v; } @@ -243,7 +242,7 @@ void Registers::Write(size_t idx, Xbyak::Reg v) { if (idx == 0) return; - gprIsConstant[idx] = false; + regIsConstant &= ~(1 << idx); if (!jit) Util::panic("Did you try to call Registers::Write(size_t, *Xbyak::Reg*) from the interpreter?"); @@ -257,7 +256,7 @@ void Registers::Write(size_t idx, Xbyak::Reg v) { if (idx == 0) return; - gprIsConstant[idx] = false; + regIsConstant &= ~(1 << idx); if (!jit) Util::panic("Did you try to call Registers::Write(size_t, *Xbyak::Reg*) from the interpreter?"); @@ -271,7 +270,7 @@ void Registers::Write(size_t idx, Xbyak::Reg v) { if (idx == 0) return; - gprIsConstant[idx] = false; + regIsConstant &= ~(1 << idx); if (!jit) Util::panic("Did you try to call Registers::Write(size_t, *Xbyak::Reg*) from the interpreter?"); @@ -285,7 +284,7 @@ void Registers::Write(size_t idx, Xbyak::Reg v) { if (idx == 0) return; - gprIsConstant[idx] = false; + regIsConstant &= ~(1 << idx); if (!jit) Util::panic("Did you try to call Registers::Write(size_t, *Xbyak::Reg*) from the interpreter?"); @@ -299,7 +298,7 @@ void Registers::Write(size_t idx, Xbyak::Reg v) { if (idx == 0) return; - gprIsConstant[idx] = false; + regIsConstant &= ~(1 << idx); if (!jit) Util::panic("Did you try to call Registers::Write(size_t, *Xbyak::Reg*) from the interpreter?"); @@ -313,7 +312,7 @@ void Registers::Write(size_t idx, Xbyak::Reg v) { if (idx == 0) return; - gprIsConstant[idx] = false; + regIsConstant &= ~(1 << idx); if (!jit) Util::panic("Did you try to call Registers::Write(size_t, *Xbyak::Reg*) from the interpreter?"); @@ -327,7 +326,7 @@ void Registers::Write(size_t idx, Xbyak::Reg v) { if (idx == 0) return; - gprIsConstant[idx] = false; + regIsConstant &= ~(1 << idx); if (!jit) Util::panic("Did you try to call Registers::Write(size_t, *Xbyak::Reg*) from the interpreter?"); @@ -341,7 +340,7 @@ void Registers::Write(size_t idx, Xbyak::Reg v) { if (idx == 0) return; - gprIsConstant[idx] = false; + regIsConstant &= ~(1 << idx); if (!jit) Util::panic("Did you try to call Registers::Write(size_t, *Xbyak::Reg*) from the interpreter?"); diff --git a/src/backend/core/registers/Registers.hpp b/src/backend/core/registers/Registers.hpp index 24dded1c..e393a5fd 100644 --- a/src/backend/core/registers/Registers.hpp +++ b/src/backend/core/registers/Registers.hpp @@ -14,17 +14,41 @@ struct Registers { [[nodiscard]] bool IsRegConstant(const u32 index) const { if (index == 0) return true; - return gprIsConstant[index]; + return regIsConstant & (1 << index); } [[nodiscard]] bool IsRegConstant(const u32 first, const u32 second) const { return IsRegConstant(first) && IsRegConstant(second); } + bool GetLOConstant() { + return regIsConstant & (1ull << 32); + } + + bool GetHIConstant() { + return regIsConstant & (1ull << 33); + } + + void SetLOConstant() { + regIsConstant |= (1ull << 32); + } + + void SetHIConstant() { + regIsConstant |= (1ull << 33); + } + + void UnsetLOConstant() { + regIsConstant &= ~(1ull << 32); + } + + void UnsetHIConstant() { + regIsConstant &= ~(1ull << 33); + } + JIT *jit = nullptr; - std::array gprIsConstant{}; - bool loIsConstant = false, hiIsConstant = false; + uint64_t regIsConstant = 0; + Cop0 cop0; Cop1 cop1; s64 oldPC{}, pc{}, nextPC{};