register constant check optimization + disable branch likely's for now

This commit is contained in:
irisz64
2025-07-07 10:36:16 +02:00
parent dd6c28c9d9
commit 6e69a37a62
3 changed files with 75 additions and 44 deletions

View File

@@ -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<s64>(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<s64>(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<s32>(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<u32>(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<s64>(RS(instr));
regs.hiIsConstant = true;
regs.SetHIConstant();
} else {
regs.Read<s64>(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<s64>(RS(instr));
regs.loIsConstant = true;
regs.SetLOConstant();
} else {
regs.Read<s64>(RS(instr), code.rax);
code.mov(REG(qword, lo), code.rax);
regs.loIsConstant = false;
regs.UnsetLOConstant();
}
}

View File

@@ -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<bool>(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<u64>(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<u32>(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<s32>(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<u16>(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<s16>(size_t idx, s16 v) {
if (idx == 0)
return;
gprIsConstant[idx] = true;
regIsConstant |= (1 << idx);
gpr[idx] = v;
}
@@ -223,7 +222,7 @@ void Registers::Write<u8>(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<s8>(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<bool>(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<s8>(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<u8>(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<s16>(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<u16>(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<s32>(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<u32>(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<u64>(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?");

View File

@@ -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<bool, 32> gprIsConstant{};
bool loIsConstant = false, hiIsConstant = false;
uint64_t regIsConstant = 0;
Cop0 cop0;
Cop1 cop1;
s64 oldPC{}, pc{}, nextPC{};