Actually mark scratch registers + comment out branches for now + rework compilation loop a bit

This commit is contained in:
irisz64
2025-07-07 15:54:04 +02:00
parent f91b0d0242
commit d072d37733
3 changed files with 114 additions and 199 deletions

View File

@@ -72,11 +72,9 @@ int JIT::Step() {
code.setProtectModeRW();
u32 instructionsInBlock = 0;
u32 instruction = 0;
bool instrEndsBlock = false;
bool instrInDelaySlot = false;
bool branchWasLikely = false;
bool blockEndsOnBranch = false;
code.sub(code.rsp, 8);
code.push(code.rbp);
@@ -84,7 +82,7 @@ int JIT::Step() {
//cs_insn *insn;
Util::trace("\tMIPS code (guest PC = 0x{:016X}):", blockPC);
while (!instrInDelaySlot) {
while (!instrEndsBlock) {
// CheckCompareInterrupt();
if (check_address_error(0b11, u64(blockPC))) [[unlikely]] {
@@ -104,7 +102,7 @@ int JIT::Step() {
static_cast<int>(Cop0::GetTLBExceptionCode(regs.cop0.tlbError, Cop0::LOAD)), static_cast<u64>(blockPC));
}
const u32 instruction = mem.Read<u32>(regs, paddr);
instruction = mem.Read<u32>(regs, paddr);
/*u32 bswapped = bswap(instruction);
auto count = cs_disasm(disassemblerMips, reinterpret_cast<const u8 *>(&bswapped), 4, blockPC, 0, &insn);
@@ -127,29 +125,19 @@ int JIT::Step() {
instructionsInBlock++;
Emit(instruction);
instrInDelaySlot = instrEndsBlock;
instrEndsBlock = InstrEndsBlock(instruction);
if (instrEndsBlock) {
branchWasLikely = IsBranchLikely(instruction);
}
if (instrInDelaySlot) {
blockEndsOnBranch = true;
}
if (instrInDelaySlot && branchWasLikely) {
branchWasLikely = false;
code.L(branch_likely_not_taken);
code.mov(code.rax, blockPC);
code.mov(REG(qword, pc), code.rax);
}
}
// emit code to store the value of pc
if (!blockEndsOnBranch) {
code.mov(code.rax, blockPC);
code.mov(REG(qword, pc), code.rax);
}
instruction = mem.Read<u32>(regs, paddr);
instrEndsBlock = InstrEndsBlock(instruction);
if(instrEndsBlock)
Util::panic("Branch in delay slot - YOU SHOULD KILL YOURSELF, NOW!!!");
blockOldPC = blockPC;
blockPC = blockNextPC;
blockNextPC += 4;
instructionsInBlock++;
Emit(instruction);
code.mov(code.rax, instructionsInBlock);
code.pop(code.rbp);

View File

@@ -77,6 +77,13 @@ static bool IsBranchLikely(const u32 instr) {
#define ARG2 rdx
#define ARG3 r8
#define ARG4 r9
#define SCR1 rax
#define SCR2 rcx
#define SCR3 rdx
#define SCR4 r8
#define SCR5 r9
#define SCR6 r10
#define SCR7 r11
#else
#define ARG1 rdi
#define ARG2 rsi
@@ -84,5 +91,14 @@ static bool IsBranchLikely(const u32 instr) {
#define ARG4 rcx
#define ARG5 r8
#define ARG6 r9
#define SCR1 rax
#define SCR2 rdi
#define SCR3 rsi
#define SCR4 rdx
#define SCR5 rcx
#define SCR6 r8
#define SCR7 r9
#define SCR8 r10
#define SCR9 r11
#endif
} // namespace n64

View File

@@ -29,26 +29,26 @@ void JIT::add(const u32 instr) {
if (regs.IsRegConstant(RS(instr))) {
const u32 rs = regs.Read<s32>(RS(instr));
regs.Read<u32>(RT(instr), code.eax);
code.add(code.eax, rs);
regs.Write<s32>(RD(instr), code.eax);
regs.Read<u32>(RT(instr), code.SCR1.cvt32());
code.add(code.SCR1.cvt32(), rs);
regs.Write<s32>(RD(instr), code.SCR1.cvt32());
return;
}
if (regs.IsRegConstant(RT(instr))) {
const u32 rt = regs.Read<s32>(RT(instr));
regs.Read<u32>(RS(instr), code.eax);
code.add(code.eax, rt);
regs.Write<s32>(RD(instr), code.eax);
regs.Read<u32>(RS(instr), code.SCR1.cvt32());
code.add(code.SCR1.cvt32(), rt);
regs.Write<s32>(RD(instr), code.SCR1.cvt32());
return;
}
regs.Read<u32>(RT(instr), code.eax);
regs.Read<u32>(RS(instr), code.edi);
code.add(code.eax, code.edi);
regs.Write<s32>(RD(instr), code.eax);
regs.Read<u32>(RT(instr), code.SCR1.cvt32());
regs.Read<u32>(RS(instr), code.SCR2.cvt32());
code.add(code.SCR1.cvt32(), code.SCR2.cvt32());
regs.Write<s32>(RD(instr), code.SCR1.cvt32());
}
void JIT::addu(u32 instr) {
@@ -63,24 +63,24 @@ void JIT::addu(u32 instr) {
if (regs.IsRegConstant(RS(instr))) {
const s32 rs = regs.Read<s32>(RS(instr));
regs.Read<s32>(RT(instr), code.eax);
code.add(code.eax, rs);
regs.Write<s32>(RD(instr), code.eax);
regs.Read<s32>(RT(instr), code.SCR1.cvt32());
code.add(code.SCR1.cvt32(), rs);
regs.Write<s32>(RD(instr), code.SCR1.cvt32());
return;
}
if (regs.IsRegConstant(RT(instr))) {
const s32 rs = regs.Read<s32>(RT(instr));
regs.Read<s32>(RS(instr), code.eax);
code.add(code.eax, rs);
regs.Write<s32>(RD(instr), code.eax);
regs.Read<s32>(RS(instr), code.SCR1.cvt32());
code.add(code.SCR1.cvt32(), rs);
regs.Write<s32>(RD(instr), code.SCR1.cvt32());
return;
}
regs.Read<s32>(RS(instr), code.eax);
regs.Read<s32>(RT(instr), code.edi);
code.add(code.eax, code.edi);
regs.Write<s32>(RD(instr), code.eax);
regs.Read<s32>(RS(instr), code.SCR1.cvt32());
regs.Read<s32>(RT(instr), code.SCR2.cvt32());
code.add(code.SCR1.cvt32(), code.SCR2.cvt32());
regs.Write<s32>(RD(instr), code.SCR1.cvt32());
}
void JIT::addi(u32 instr) {
@@ -96,9 +96,9 @@ void JIT::addi(u32 instr) {
return;
}
regs.Read<u32>(RS(instr), code.eax);
code.add(code.eax, imm);
regs.Write<s32>(RT(instr), code.eax);
regs.Read<u32>(RS(instr), code.SCR1.cvt32());
code.add(code.eax, SCR1.cvt32());
regs.Write<s32>(RT(instr), code.SCR1.cvt32());
}
void JIT::addiu(u32 instr) {
@@ -111,9 +111,9 @@ void JIT::addiu(u32 instr) {
return;
}
regs.Read<u32>(RS(instr), code.eax);
code.add(code.eax, imm);
regs.Write<s32>(RT(instr), code.eax);
regs.Read<u32>(RS(instr), code.SCR1.cvt32());
code.add(code.SCR1.cvt32(), imm);
regs.Write<s32>(RT(instr), code.SCR1.cvt32());
}
void JIT::andi(u32 instr) {
@@ -123,9 +123,9 @@ void JIT::andi(u32 instr) {
return;
}
regs.Read<s64>(RS(instr), code.rax);
code.and_(code.rax, imm);
regs.Write<s64>(RT(instr), code.rax);
regs.Read<s64>(RS(instr), code.SCR1);
code.and_(code.SCR1, imm);
regs.Write<s64>(RT(instr), code.SCR1);
}
void JIT::and_(u32 instr) {
@@ -136,115 +136,24 @@ void JIT::and_(u32 instr) {
if (regs.IsRegConstant(RS(instr))) {
const auto rs = regs.Read<s64>(RS(instr));
regs.Read<s64>(RT(instr), code.rax);
code.and_(code.rax, rs);
regs.Write<s64>(RD(instr), code.rax);
regs.Read<s64>(RT(instr), code.SCR1);
code.and_(code.SCR1, rs);
regs.Write<s64>(RD(instr), code.SCR1);
return;
}
if (regs.IsRegConstant(RT(instr))) {
const auto rt = regs.Read<s64>(RT(instr));
regs.Read<s64>(RS(instr), code.rax);
code.and_(code.rax, rt);
regs.Write<s64>(RD(instr), code.rax);
regs.Read<s64>(RS(instr), code.SCR1);
code.and_(code.SCR1, rt);
regs.Write<s64>(RD(instr), code.SCR1);
return;
}
regs.Read<s64>(RS(instr), code.rax);
regs.Read<s64>(RT(instr), code.rdi);
code.and_(code.rdi, code.rax);
regs.Write<s64>(RD(instr), code.rdi);
}
void JIT::SkipSlot() { code.jmp("not_taken"); }
void JIT::SkipSlotConstant() {
blockOldPC = blockPC;
blockPC = blockNextPC;
blockNextPC = blockPC + 4;
}
void JIT::BranchTaken(const s64 offs) {
code.mov(code.rax, blockPC + offs);
code.mov(REG(qword, pc), code.rax);
}
void JIT::BranchNotTaken() {
code.mov(code.rax, blockPC + 4);
code.mov(REG(qword, pc), code.rax);
}
void JIT::BranchTaken(const Xbyak::Reg64 &offs) {
code.add(offs, blockPC);
code.mov(REG(qword, pc), offs);
}
void JIT::BranchAbsTaken(const s64 addr) {
code.mov(code.rax, addr);
code.mov(REG(qword, pc), code.rax);
}
void JIT::BranchAbsTaken(const Xbyak::Reg64 &addr) { code.mov(REG(qword, pc), addr); }
#define branch(offs, cond) \
do { \
Xbyak::Label taken, not_taken; \
code.j##cond(taken); \
BranchNotTaken(); \
code.jmp(not_taken); \
code.L(taken); \
BranchTaken(offs); \
code.L(not_taken); \
} \
while (0)
#define branch_abs(addr, cond) \
do { \
Xbyak::Label taken, not_taken; \
code.j##cond(taken); \
BranchNotTaken(); \
code.jmp(not_taken); \
code.L(taken); \
BranchAbsTaken(addr); \
code.L(not_taken); \
} \
while (0)
#define branch_likely(offs, cond) \
do { \
Xbyak::Label taken; \
code.j##cond(taken); \
SkipSlot(); \
code.jmp(branch_likely_not_taken); \
code.L(taken); \
BranchTaken(offs); \
} \
while (0)
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) {
if (cond) {
BranchTaken(offset);
} else {
SkipSlotConstant();
}
}
void JIT::branch_abs_constant(const bool cond, const s64 address) {
if (cond) {
BranchAbsTaken(address);
return;
}
BranchNotTaken();
regs.Read<s64>(RS(instr), code.SCR1);
regs.Read<s64>(RT(instr), code.SCR2);
code.and_(code.SCR2, code.SCR1);
regs.Write<s64>(RD(instr), code.SCR2);
}
void JIT::bfc0(u32 instr) {
@@ -282,7 +191,7 @@ void JIT::blfc1(u32 instr) {
// code.test(code.al, code.al);
// branch_likely(address, nz);
}
/*
void JIT::bltz(const u32 instr) {
const s16 imm = instr;
const s64 offset = u64((s64)imm) << 2;
@@ -562,7 +471,7 @@ void JIT::bgtzl(const u32 instr) {
code.cmp(code.rax, 0);
branch_likely(offset, g);
}
*/
void JIT::dadd(u32 instr) {
if (regs.IsRegConstant(RS(instr), RT(instr))) {
auto rs = regs.Read<u64>(RS(instr));
@@ -578,24 +487,24 @@ void JIT::dadd(u32 instr) {
if (regs.IsRegConstant(RS(instr))) {
auto rs = regs.Read<u64>(RS(instr));
regs.Read<u64>(RT(instr), code.rax);
code.add(code.rax, rs);
regs.Write<u64>(RD(instr), code.rax);
regs.Read<u64>(RT(instr), code.SCR1);
code.add(code.SCR1, rs);
regs.Write<u64>(RD(instr), code.SCR1);
return;
}
if (regs.IsRegConstant(RT(instr))) {
auto rt = regs.Read<u64>(RT(instr));
regs.Read<u64>(RS(instr), code.rax);
code.add(code.rax, rt);
regs.Write<u64>(RD(instr), code.rax);
regs.Read<u64>(RS(instr), code.SCR1);
code.add(code.SCR1, rt);
regs.Write<u64>(RD(instr), code.SCR1);
return;
}
regs.Read<u64>(RS(instr), code.rax);
regs.Read<u64>(RT(instr), code.rdi);
code.add(code.rax, code.rdi);
regs.Write<u64>(RD(instr), code.rax);
regs.Read<u64>(RS(instr), code.SCR1);
regs.Read<u64>(RT(instr), code.SCR2);
code.add(code.SCR1, code.SCR2);
regs.Write<u64>(RD(instr), code.SCR1);
}
void JIT::daddu(u32 instr) {
@@ -616,9 +525,9 @@ void JIT::daddi(u32 instr) {
return;
}
regs.Read<u64>(RS(instr), code.rax);
code.add(code.rax, imm);
regs.Write<u64>(RT(instr), code.rax);
regs.Read<u64>(RS(instr), code.SCR1);
code.add(code.SCR1, imm);
regs.Write<u64>(RT(instr), code.SCR1);
}
void JIT::daddiu(u32 instr) {
@@ -874,6 +783,7 @@ void JIT::dsubu(u32 instr) {
}
}
/*
void JIT::j(const u32 instr) {
const s32 target = (instr & 0x3ffffff) << 2;
const s64 address = (blockOldPC & ~0xfffffff) | target;
@@ -890,7 +800,7 @@ void JIT::jr(const u32 instr) {
regs.Read<s64>(RS(instr), code.rax);
branch_abs(code.rax, mp);
}
void JIT::jal(const u32 instr) {
regs.Write<s64>(31, blockNextPC);
j(instr);
@@ -900,6 +810,7 @@ void JIT::jalr(const u32 instr) {
regs.Write<s64>(RD(instr), blockNextPC);
jr(instr);
}
*/
void JIT::lbu(u32 instr) {
if (regs.IsRegConstant(RS(instr))) {
@@ -1146,8 +1057,8 @@ void JIT::mfhi(u32 instr) {
if (regs.GetHIConstant()) {
regs.Write(RD(instr), regs.hi);
} else {
code.mov(code.rax, REG(qword, hi));
regs.Write<s64>(RD(instr), code.rax);
code.mov(code.SCR1, REG(qword, hi));
regs.Write<s64>(RD(instr), code.SCR1);
}
}
@@ -1155,8 +1066,8 @@ void JIT::mflo(u32 instr) {
if (regs.GetLOConstant()) {
regs.Write(RD(instr), regs.lo);
} else {
code.mov(code.rax, REG(qword, lo));
regs.Write<s64>(RD(instr), code.rax);
code.mov(code.SCR1, REG(qword, lo));
regs.Write<s64>(RD(instr), code.SCR1);
}
}
@@ -1193,8 +1104,8 @@ void JIT::mthi(u32 instr) {
regs.hi = regs.Read<s64>(RS(instr));
regs.SetHIConstant();
} else {
regs.Read<s64>(RS(instr), code.rax);
code.mov(REG(qword, hi), code.rax);
regs.Read<s64>(RS(instr), code.SCR1);
code.mov(REG(qword, hi), code.SCR1);
regs.UnsetHIConstant();
}
}
@@ -1204,8 +1115,8 @@ void JIT::mtlo(u32 instr) {
regs.lo = regs.Read<s64>(RS(instr));
regs.SetLOConstant();
} else {
regs.Read<s64>(RS(instr), code.rax);
code.mov(REG(qword, lo), code.rax);
regs.Read<s64>(RS(instr), code.SCR1);
code.mov(REG(qword, lo), code.SCR1);
regs.UnsetLOConstant();
}
}
@@ -1245,27 +1156,27 @@ void JIT::slt(u32 instr) {
if (regs.IsRegConstant(RT(instr))) {
s64 rt = regs.Read<s64>(RT(instr));
regs.Read<s64>(RS(instr), code.rax);
code.cmp(code.rax, rt);
code.setl(code.al);
regs.Write<bool>(RD(instr), code.al);
regs.Read<s64>(RS(instr), code.SCR1);
code.cmp(code.SCR1, rt);
code.setl(code.SCR1.cvt8());
regs.Write<bool>(RD(instr), code.SCR1.cvt8());
return;
}
if (regs.IsRegConstant(RS(instr))) {
s64 rs = regs.Read<s64>(RS(instr));
regs.Read<s64>(RT(instr), code.rax);
code.cmp(code.rax, rs);
code.setge(code.al);
regs.Write<bool>(RD(instr), code.al);
regs.Read<s64>(RT(instr), code.SCR1);
code.cmp(code.SCR1, rs);
code.setge(code.SCR1.cvt8());
regs.Write<bool>(RD(instr), code.SCR1.cvt8());
return;
}
regs.Read<s64>(RS(instr), code.rax);
regs.Read<s64>(RT(instr), code.rdx);
code.cmp(code.rax, code.rdx);
code.setl(code.al);
regs.Write<bool>(RD(instr), code.al);
regs.Read<s64>(RS(instr), code.SCR1);
regs.Read<s64>(RT(instr), code.SCR2);
code.cmp(code.SCR1, code.SCR2);
code.setl(code.SCR1.cvt8());
regs.Write<bool>(RD(instr), code.SCR1.cvt8());
}
void JIT::sltu(u32 instr) {
@@ -1282,9 +1193,9 @@ void JIT::sll(u32 instr) {
const s32 result = regs.Read<s64>(RT(instr)) << sa;
regs.Write(RD(instr), (s64)result);
} else {
regs.Read<s64>(RT(instr), code.rax);
code.sal(code.rax, sa);
regs.Write<s32>(RD(instr), code.eax);
regs.Read<s64>(RT(instr), code.SCR1);
code.sal(code.SCR1, sa);
regs.Write<s32>(RD(instr), code.SCR1.cvt32());
}
}
@@ -1432,7 +1343,7 @@ void JIT::sw(const u32 instr) {
const s16 offset = instr;
code.mov(code.ARG2, Cop0::STORE);
regs.Read<s64>(RS(instr), code.rdx);
regs.Read<s64>(RS(instr), code.ARG3);
code.add(code.ARG3, offset);
code.mov(code.ARG4, reinterpret_cast<uintptr_t>(&physical));
@@ -1471,9 +1382,9 @@ void JIT::ori(u32 instr) {
return;
}
regs.Read<s64>(RS(instr), code.rax);
code.or_(code.rax, imm);
regs.Write<s64>(RT(instr), code.rax);
regs.Read<s64>(RS(instr), code.SCR1);
code.or_(code.SCR1, imm);
regs.Write<s64>(RT(instr), code.SCR1);
}
void JIT::xori(u32 instr) {