From d072d3773314fbb66bb7fb29b6c6c43b567b7378 Mon Sep 17 00:00:00 2001 From: irisz64 Date: Mon, 7 Jul 2025 15:54:04 +0200 Subject: [PATCH] Actually mark scratch registers + comment out branches for now + rework compilation loop a bit --- src/backend/core/JIT.cpp | 38 ++-- src/backend/core/jit/helpers.hpp | 16 ++ src/backend/core/jit/instructions.cpp | 259 +++++++++----------------- 3 files changed, 114 insertions(+), 199 deletions(-) diff --git a/src/backend/core/JIT.cpp b/src/backend/core/JIT.cpp index e5b20424..5b4b7131 100644 --- a/src/backend/core/JIT.cpp +++ b/src/backend/core/JIT.cpp @@ -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(Cop0::GetTLBExceptionCode(regs.cop0.tlbError, Cop0::LOAD)), static_cast(blockPC)); } - const u32 instruction = mem.Read(regs, paddr); + instruction = mem.Read(regs, paddr); /*u32 bswapped = bswap(instruction); auto count = cs_disasm(disassemblerMips, reinterpret_cast(&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(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); diff --git a/src/backend/core/jit/helpers.hpp b/src/backend/core/jit/helpers.hpp index 352c8621..ff0661e5 100644 --- a/src/backend/core/jit/helpers.hpp +++ b/src/backend/core/jit/helpers.hpp @@ -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 diff --git a/src/backend/core/jit/instructions.cpp b/src/backend/core/jit/instructions.cpp index e74ceb63..8b846eb4 100644 --- a/src/backend/core/jit/instructions.cpp +++ b/src/backend/core/jit/instructions.cpp @@ -29,26 +29,26 @@ void JIT::add(const u32 instr) { if (regs.IsRegConstant(RS(instr))) { const u32 rs = regs.Read(RS(instr)); - regs.Read(RT(instr), code.eax); - code.add(code.eax, rs); - regs.Write(RD(instr), code.eax); + regs.Read(RT(instr), code.SCR1.cvt32()); + code.add(code.SCR1.cvt32(), rs); + regs.Write(RD(instr), code.SCR1.cvt32()); return; } if (regs.IsRegConstant(RT(instr))) { const u32 rt = regs.Read(RT(instr)); - regs.Read(RS(instr), code.eax); - code.add(code.eax, rt); - regs.Write(RD(instr), code.eax); + regs.Read(RS(instr), code.SCR1.cvt32()); + code.add(code.SCR1.cvt32(), rt); + regs.Write(RD(instr), code.SCR1.cvt32()); return; } - regs.Read(RT(instr), code.eax); - regs.Read(RS(instr), code.edi); - code.add(code.eax, code.edi); - regs.Write(RD(instr), code.eax); + regs.Read(RT(instr), code.SCR1.cvt32()); + regs.Read(RS(instr), code.SCR2.cvt32()); + code.add(code.SCR1.cvt32(), code.SCR2.cvt32()); + regs.Write(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(RS(instr)); - regs.Read(RT(instr), code.eax); - code.add(code.eax, rs); - regs.Write(RD(instr), code.eax); + regs.Read(RT(instr), code.SCR1.cvt32()); + code.add(code.SCR1.cvt32(), rs); + regs.Write(RD(instr), code.SCR1.cvt32()); return; } if (regs.IsRegConstant(RT(instr))) { const s32 rs = regs.Read(RT(instr)); - regs.Read(RS(instr), code.eax); - code.add(code.eax, rs); - regs.Write(RD(instr), code.eax); + regs.Read(RS(instr), code.SCR1.cvt32()); + code.add(code.SCR1.cvt32(), rs); + regs.Write(RD(instr), code.SCR1.cvt32()); return; } - regs.Read(RS(instr), code.eax); - regs.Read(RT(instr), code.edi); - code.add(code.eax, code.edi); - regs.Write(RD(instr), code.eax); + regs.Read(RS(instr), code.SCR1.cvt32()); + regs.Read(RT(instr), code.SCR2.cvt32()); + code.add(code.SCR1.cvt32(), code.SCR2.cvt32()); + regs.Write(RD(instr), code.SCR1.cvt32()); } void JIT::addi(u32 instr) { @@ -96,9 +96,9 @@ void JIT::addi(u32 instr) { return; } - regs.Read(RS(instr), code.eax); - code.add(code.eax, imm); - regs.Write(RT(instr), code.eax); + regs.Read(RS(instr), code.SCR1.cvt32()); + code.add(code.eax, SCR1.cvt32()); + regs.Write(RT(instr), code.SCR1.cvt32()); } void JIT::addiu(u32 instr) { @@ -111,9 +111,9 @@ void JIT::addiu(u32 instr) { return; } - regs.Read(RS(instr), code.eax); - code.add(code.eax, imm); - regs.Write(RT(instr), code.eax); + regs.Read(RS(instr), code.SCR1.cvt32()); + code.add(code.SCR1.cvt32(), imm); + regs.Write(RT(instr), code.SCR1.cvt32()); } void JIT::andi(u32 instr) { @@ -123,9 +123,9 @@ void JIT::andi(u32 instr) { return; } - regs.Read(RS(instr), code.rax); - code.and_(code.rax, imm); - regs.Write(RT(instr), code.rax); + regs.Read(RS(instr), code.SCR1); + code.and_(code.SCR1, imm); + regs.Write(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(RS(instr)); - regs.Read(RT(instr), code.rax); - code.and_(code.rax, rs); - regs.Write(RD(instr), code.rax); + regs.Read(RT(instr), code.SCR1); + code.and_(code.SCR1, rs); + regs.Write(RD(instr), code.SCR1); return; } if (regs.IsRegConstant(RT(instr))) { const auto rt = regs.Read(RT(instr)); - regs.Read(RS(instr), code.rax); - code.and_(code.rax, rt); - regs.Write(RD(instr), code.rax); + regs.Read(RS(instr), code.SCR1); + code.and_(code.SCR1, rt); + regs.Write(RD(instr), code.SCR1); return; } - regs.Read(RS(instr), code.rax); - regs.Read(RT(instr), code.rdi); - code.and_(code.rdi, code.rax); - regs.Write(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(RS(instr), code.SCR1); + regs.Read(RT(instr), code.SCR2); + code.and_(code.SCR2, code.SCR1); + regs.Write(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(RS(instr)); @@ -578,24 +487,24 @@ void JIT::dadd(u32 instr) { if (regs.IsRegConstant(RS(instr))) { auto rs = regs.Read(RS(instr)); - regs.Read(RT(instr), code.rax); - code.add(code.rax, rs); - regs.Write(RD(instr), code.rax); + regs.Read(RT(instr), code.SCR1); + code.add(code.SCR1, rs); + regs.Write(RD(instr), code.SCR1); return; } if (regs.IsRegConstant(RT(instr))) { auto rt = regs.Read(RT(instr)); - regs.Read(RS(instr), code.rax); - code.add(code.rax, rt); - regs.Write(RD(instr), code.rax); + regs.Read(RS(instr), code.SCR1); + code.add(code.SCR1, rt); + regs.Write(RD(instr), code.SCR1); return; } - regs.Read(RS(instr), code.rax); - regs.Read(RT(instr), code.rdi); - code.add(code.rax, code.rdi); - regs.Write(RD(instr), code.rax); + regs.Read(RS(instr), code.SCR1); + regs.Read(RT(instr), code.SCR2); + code.add(code.SCR1, code.SCR2); + regs.Write(RD(instr), code.SCR1); } void JIT::daddu(u32 instr) { @@ -616,9 +525,9 @@ void JIT::daddi(u32 instr) { return; } - regs.Read(RS(instr), code.rax); - code.add(code.rax, imm); - regs.Write(RT(instr), code.rax); + regs.Read(RS(instr), code.SCR1); + code.add(code.SCR1, imm); + regs.Write(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(RS(instr), code.rax); branch_abs(code.rax, mp); } - + void JIT::jal(const u32 instr) { regs.Write(31, blockNextPC); j(instr); @@ -900,6 +810,7 @@ void JIT::jalr(const u32 instr) { regs.Write(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(RD(instr), code.rax); + code.mov(code.SCR1, REG(qword, hi)); + regs.Write(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(RD(instr), code.rax); + code.mov(code.SCR1, REG(qword, lo)); + regs.Write(RD(instr), code.SCR1); } } @@ -1193,8 +1104,8 @@ void JIT::mthi(u32 instr) { regs.hi = regs.Read(RS(instr)); regs.SetHIConstant(); } else { - regs.Read(RS(instr), code.rax); - code.mov(REG(qword, hi), code.rax); + regs.Read(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(RS(instr)); regs.SetLOConstant(); } else { - regs.Read(RS(instr), code.rax); - code.mov(REG(qword, lo), code.rax); + regs.Read(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(RT(instr)); - regs.Read(RS(instr), code.rax); - code.cmp(code.rax, rt); - code.setl(code.al); - regs.Write(RD(instr), code.al); + regs.Read(RS(instr), code.SCR1); + code.cmp(code.SCR1, rt); + code.setl(code.SCR1.cvt8()); + regs.Write(RD(instr), code.SCR1.cvt8()); return; } if (regs.IsRegConstant(RS(instr))) { s64 rs = regs.Read(RS(instr)); - regs.Read(RT(instr), code.rax); - code.cmp(code.rax, rs); - code.setge(code.al); - regs.Write(RD(instr), code.al); + regs.Read(RT(instr), code.SCR1); + code.cmp(code.SCR1, rs); + code.setge(code.SCR1.cvt8()); + regs.Write(RD(instr), code.SCR1.cvt8()); return; } - regs.Read(RS(instr), code.rax); - regs.Read(RT(instr), code.rdx); - code.cmp(code.rax, code.rdx); - code.setl(code.al); - regs.Write(RD(instr), code.al); + regs.Read(RS(instr), code.SCR1); + regs.Read(RT(instr), code.SCR2); + code.cmp(code.SCR1, code.SCR2); + code.setl(code.SCR1.cvt8()); + regs.Write(RD(instr), code.SCR1.cvt8()); } void JIT::sltu(u32 instr) { @@ -1282,9 +1193,9 @@ void JIT::sll(u32 instr) { const s32 result = regs.Read(RT(instr)) << sa; regs.Write(RD(instr), (s64)result); } else { - regs.Read(RT(instr), code.rax); - code.sal(code.rax, sa); - regs.Write(RD(instr), code.eax); + regs.Read(RT(instr), code.SCR1); + code.sal(code.SCR1, sa); + regs.Write(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(RS(instr), code.rdx); + regs.Read(RS(instr), code.ARG3); code.add(code.ARG3, offset); code.mov(code.ARG4, reinterpret_cast(&physical)); @@ -1471,9 +1382,9 @@ void JIT::ori(u32 instr) { return; } - regs.Read(RS(instr), code.rax); - code.or_(code.rax, imm); - regs.Write(RT(instr), code.rax); + regs.Read(RS(instr), code.SCR1); + code.or_(code.SCR1, imm); + regs.Write(RT(instr), code.SCR1); } void JIT::xori(u32 instr) {