fix jit boogs

This commit is contained in:
IrisZ64
2025-12-18 21:36:45 +01:00
parent b4a17416e4
commit 219c46e475
10 changed files with 195 additions and 179 deletions

View File

@@ -13,6 +13,7 @@ if(APPLE)
enable_language(OBJC) enable_language(OBJC)
endif() endif()
set(VULKAN_VALIDATION FALSE)
set(SANITIZERS FALSE) set(SANITIZERS FALSE)
set(CMAKE_CXX_STANDARD 23) set(CMAKE_CXX_STANDARD 23)
set(CMAKE_CXX_STANDARD_REQUIRED ON) set(CMAKE_CXX_STANDARD_REQUIRED ON)
@@ -102,7 +103,8 @@ if (HAS_SIMD)
add_compile_options(${SIMD_FLAG}) add_compile_options(${SIMD_FLAG})
endif () endif ()
if (${CMAKE_BUILD_TYPE} MATCHES Debug) if (${CMAKE_BUILD_TYPE} MATCHES Debug AND VULKAN_VALIDATION)
message("VALIDATION LAYERS: ON")
add_compile_definitions(VULKAN_DEBUG) add_compile_definitions(VULKAN_DEBUG)
endif () endif ()

View File

@@ -5,14 +5,14 @@
namespace n64 { namespace n64 {
Core::Core() { Core::Core() {
auto cpuType = Options::GetInstance().GetValue<std::string>("cpu", "type"); const auto selectedCpu = Options::GetInstance().GetValue<std::string>("cpu", "type");
if (cpuType == "interpreter") { if (selectedCpu == "interpreter") {
cpuType = Interpreted; cpuType = Interpreted;
cpu = std::make_unique<Interpreter>(parallel, *mem, regs); cpu = std::make_unique<Interpreter>(*mem, regs);
} else if(cpuType == "jit") { } else if(selectedCpu == "jit") {
#ifndef __aarch64__ #ifndef __aarch64__
cpuType = DynamicRecompiler; cpuType = DynamicRecompiler;
cpu = std::make_unique<JIT>(parallel, *mem, regs); cpu = std::make_unique<JIT>(*mem, regs);
#else #else
panic("JIT currently unsupported on aarch64"); panic("JIT currently unsupported on aarch64");
#endif #endif
@@ -62,11 +62,11 @@ void Core::LoadROM(const std::string &rom_) {
romLoaded = true; romLoaded = true;
} }
int Core::StepCPU() { u32 Core::StepCPU() {
return cpu->Step() + regs.PopStalledCycles(); return cpu->Step() + regs.PopStalledCycles();
} }
void Core::StepRSP(int cpuCycles) { void Core::StepRSP(const u32 cpuCycles) {
MMIO &mmio = mem->mmio; MMIO &mmio = mem->mmio;
if (mmio.rsp.spStatus.halt) { if (mmio.rsp.spStatus.halt) {
@@ -75,10 +75,10 @@ void Core::StepRSP(int cpuCycles) {
return; return;
} }
static constexpr int cpuRatio = 3, rspRatio = 2; static constexpr u32 cpuRatio = 3, rspRatio = 2;
regs.steps += cpuCycles; regs.steps += cpuCycles;
int sets = regs.steps / cpuRatio; const auto sets = regs.steps / cpuRatio;
mmio.rsp.steps += sets * rspRatio; mmio.rsp.steps += sets * rspRatio;
regs.steps -= sets * cpuRatio; regs.steps -= sets * cpuRatio;
@@ -88,7 +88,7 @@ void Core::StepRSP(int cpuCycles) {
} }
} }
void Core::Run(float volumeL, float volumeR) { void Core::Run(const float volumeL, const float volumeR) {
MMIO &mmio = mem->mmio; MMIO &mmio = mem->mmio;
bool broken = false; bool broken = false;
@@ -102,7 +102,7 @@ void Core::Run(float volumeL, float volumeR) {
} }
while(cycles < mem->mmio.vi.cyclesPerHalfline) { while(cycles < mem->mmio.vi.cyclesPerHalfline) {
u32 taken = StepCPU(); const u32 taken = StepCPU();
cycles += taken; cycles += taken;
if((broken = breakpoints.contains(regs.nextPC))) if((broken = breakpoints.contains(regs.nextPC)))

View File

@@ -29,8 +29,8 @@ struct Core {
return *GetInstance().mem; return *GetInstance().mem;
} }
int StepCPU(); u32 StepCPU();
void StepRSP(int cpuCycles); void StepRSP(u32 cpuCycles);
void Stop(); void Stop();
void Reset(); void Reset();
void LoadROM(const std::string &); void LoadROM(const std::string &);

View File

@@ -6,7 +6,7 @@
namespace n64 { namespace n64 {
struct BaseCPU { struct BaseCPU {
virtual ~BaseCPU() = default; virtual ~BaseCPU() = default;
virtual int Step() = 0; virtual u32 Step() = 0;
virtual void Reset() = 0; virtual void Reset() = 0;
}; };
} // namespace n64 } // namespace n64

View File

@@ -1,7 +1,7 @@
#include <Core.hpp> #include <Core.hpp>
namespace n64 { namespace n64 {
Interpreter::Interpreter(ParallelRDP& parallel, Mem& mem, Registers& regs) : mem(mem), regs(regs) {} Interpreter::Interpreter(Mem& mem, Registers& regs) : regs(regs), mem(mem) {}
bool Interpreter::ShouldServiceInterrupt() const { bool Interpreter::ShouldServiceInterrupt() const {
const bool interrupts_pending = (regs.cop0.status.im & regs.cop0.cause.interruptPending) != 0; const bool interrupts_pending = (regs.cop0.status.im & regs.cop0.cause.interruptPending) != 0;
@@ -12,7 +12,7 @@ bool Interpreter::ShouldServiceInterrupt() const {
return interrupts_pending && interrupts_enabled && !currently_handling_exception && !currently_handling_error; return interrupts_pending && interrupts_enabled && !currently_handling_exception && !currently_handling_error;
} }
void Interpreter::CheckCompareInterrupt() { void Interpreter::CheckCompareInterrupt() const {
regs.cop0.count++; regs.cop0.count++;
regs.cop0.count &= 0x1FFFFFFFF; regs.cop0.count &= 0x1FFFFFFFF;
if (regs.cop0.count == static_cast<u64>(regs.cop0.compare) << 1) { if (regs.cop0.count == static_cast<u64>(regs.cop0.compare) << 1) {
@@ -21,7 +21,7 @@ void Interpreter::CheckCompareInterrupt() {
} }
} }
int Interpreter::Step() { u32 Interpreter::Step() {
CheckCompareInterrupt(); CheckCompareInterrupt();
regs.prevDelaySlot = regs.delaySlot; regs.prevDelaySlot = regs.delaySlot;

View File

@@ -6,10 +6,10 @@
namespace n64 { namespace n64 {
struct Core; struct Core;
struct Interpreter : BaseCPU { struct Interpreter final : BaseCPU {
explicit Interpreter(ParallelRDP&, Mem&, Registers&); explicit Interpreter(Mem&, Registers&);
~Interpreter() override = default; ~Interpreter() override = default;
int Step() override; u32 Step() override;
void Reset() override { void Reset() override {
cop2Latch = {}; cop2Latch = {};
@@ -22,8 +22,8 @@ private:
friend struct Cop1; friend struct Cop1;
#define check_address_error(mask, vaddr) \ #define check_address_error(mask, vaddr) \
(((!regs.cop0.is64BitAddressing) && (s32)(vaddr) != (vaddr)) || (((vaddr) & (mask)) != 0)) (((!regs.cop0.is64BitAddressing) && (s32)(vaddr) != (vaddr)) || (((vaddr) & (mask)) != 0))
bool ShouldServiceInterrupt() const; [[nodiscard]] bool ShouldServiceInterrupt() const;
void CheckCompareInterrupt(); void CheckCompareInterrupt() const;
void cop2Decode(Instruction); void cop2Decode(Instruction);
void special(Instruction); void special(Instruction);

View File

@@ -3,7 +3,7 @@
namespace n64 { namespace n64 {
#ifndef __aarch64__ #ifndef __aarch64__
JIT::JIT(ParallelRDP& parallel, Mem& mem, Registers& regs) : mem(mem), regs(regs) { JIT::JIT(Mem& mem, Registers& regs) : regs(regs), mem(mem) {
regs.SetJIT(this); regs.SetJIT(this);
blockCache.resize(kUpperSize); blockCache.resize(kUpperSize);
if (cs_open(CS_ARCH_MIPS, static_cast<cs_mode>(CS_MODE_MIPS64 | CS_MODE_BIG_ENDIAN), &disassemblerMips) != if (cs_open(CS_ARCH_MIPS, static_cast<cs_mode>(CS_MODE_MIPS64 | CS_MODE_BIG_ENDIAN), &disassemblerMips) !=
@@ -25,7 +25,7 @@ bool JIT::ShouldServiceInterrupt() const {
return interrupts_pending && interrupts_enabled && !currently_handling_exception && !currently_handling_error; return interrupts_pending && interrupts_enabled && !currently_handling_exception && !currently_handling_error;
} }
void JIT::CheckCompareInterrupt() { void JIT::CheckCompareInterrupt() const {
regs.cop0.count++; regs.cop0.count++;
regs.cop0.count &= 0x1FFFFFFFF; regs.cop0.count &= 0x1FFFFFFFF;
if (regs.cop0.count == static_cast<u64>(regs.cop0.compare) << 1) { if (regs.cop0.count == static_cast<u64>(regs.cop0.compare) << 1) {
@@ -63,19 +63,23 @@ u32 JIT::FetchInstruction() {
return 0; return 0;
} }
return Core::GetMem().Read<u32>(paddr); const u32 instr = Core::GetMem().Read<u32>(paddr);
info("{}", Disassembler::GetInstance().DisassembleSimple(paddr, instr).full);
return instr;
} }
void JIT::SetPC32(s32 val) { void JIT::SetPC32(const s32 val) {
code.mov(code.SCR1, REG(qword, pc)); code.mov(code.SCR1, REG(qword, pc));
code.mov(REG(qword, oldPC), code.SCR1); code.mov(REG(qword, oldPC), code.SCR1);
code.mov(code.SCR1, s64(val)); code.mov(code.SCR1, val);
code.mov(REG(qword, pc), code.SCR1); code.mov(REG(qword, pc), code.SCR1);
code.mov(code.SCR1, s64(val) + 4); code.mov(code.SCR1, val + 4);
code.mov(REG(qword, nextPC), code.SCR1); code.mov(REG(qword, nextPC), code.SCR1);
} }
void JIT::SetPC64(s64 val) { void JIT::SetPC64(const s64 val) {
code.mov(code.SCR1, REG(qword, pc)); code.mov(code.SCR1, REG(qword, pc));
code.mov(REG(qword, oldPC), code.SCR1); code.mov(REG(qword, oldPC), code.SCR1);
code.mov(code.SCR1, val); code.mov(code.SCR1, val);
@@ -101,7 +105,7 @@ void JIT::SetPC64(const Xbyak::Reg64& val) {
code.mov(REG(qword, nextPC), val); code.mov(REG(qword, nextPC), val);
} }
int JIT::Step() { u32 JIT::Step() {
blockOldPC = regs.oldPC; blockOldPC = regs.oldPC;
blockPC = regs.pc; blockPC = regs.pc;
blockNextPC = regs.nextPC; blockNextPC = regs.nextPC;
@@ -111,15 +115,15 @@ int JIT::Step() {
/*regs.cop0.HandleTLBException(blockPC); /*regs.cop0.HandleTLBException(blockPC);
regs.cop0.FireException(Cop0::GetTLBExceptionCode(regs.cop0.tlbError, Cop0::LOAD), 0, blockPC); regs.cop0.FireException(Cop0::GetTLBExceptionCode(regs.cop0.tlbError, Cop0::LOAD), 0, blockPC);
return 1;*/ return 1;*/
Util::Error::GetInstance().Throw( Util::Error::GetInstance().Throw({Util::Error::Severity::NON_FATAL}, {Util::Error::Type::UNHANDLED_EXCEPTION},
{Util::Error::Severity::NON_FATAL}, {Util::Error::Type::UNHANDLED_EXCEPTION}, blockPC, {}, blockPC, {},
"[JIT]: Unhandled exception TLB exception {} when retrieving PC physical address!", "[JIT]: Unhandled exception TLB exception {} when retrieving PC physical address!",
static_cast<int>(Cop0::GetTLBExceptionCode(regs.cop0.tlbError, Cop0::LOAD))); static_cast<int>(Cop0::GetTLBExceptionCode(regs.cop0.tlbError, Cop0::LOAD)));
return 0; return 0;
} }
u32 upperIndex = paddr >> kUpperShift; const u32 upperIndex = paddr >> kUpperShift;
u32 lowerIndex = paddr & kLowerMask; const u32 lowerIndex = paddr & kLowerMask;
if (!blockCache[upperIndex].empty()) { if (!blockCache[upperIndex].empty()) {
if (blockCache[upperIndex][lowerIndex]) { if (blockCache[upperIndex][lowerIndex]) {
@@ -130,7 +134,7 @@ int JIT::Step() {
blockCache[upperIndex].resize(kLowerSize); blockCache[upperIndex].resize(kLowerSize);
} }
info("[JIT]: Compiling block @ 0x{:016X}:", blockPC); info("[JIT]: Compiling block @ 0x{:016X}:", static_cast<u64>(blockPC));
const auto blockInfo = code.getCurr(); const auto blockInfo = code.getCurr();
const auto block = code.getCurr<BlockFn>(); const auto block = code.getCurr<BlockFn>();
blockCache[upperIndex][lowerIndex] = block; blockCache[upperIndex][lowerIndex] = block;
@@ -147,8 +151,12 @@ int JIT::Step() {
code.mov(code.rbp, reinterpret_cast<uintptr_t>(this)); // Load context pointer code.mov(code.rbp, reinterpret_cast<uintptr_t>(this)); // Load context pointer
cs_insn *insn; cs_insn *insn;
info("\tMIPS code (guest PC = 0x{:016X}):", blockPC); info("\tMIPS code (guest PC = 0x{:016X}):", static_cast<u64>(blockPC));
while (!instrEndsBlock) { while (!instrEndsBlock) {
code.mov(code.SCR1, REG(byte, delaySlot));
code.mov(REG(byte, prevDelaySlot), code.SCR1);
code.mov(REG(byte, delaySlot), 0);
// CheckCompareInterrupt(); // CheckCompareInterrupt();
paddr = 0; paddr = 0;
@@ -194,6 +202,7 @@ int JIT::Step() {
instructionsInBlock++; instructionsInBlock++;
const u32 delay_instruction = FetchInstruction(); const u32 delay_instruction = FetchInstruction();
instrEndsBlock = InstrEndsBlock(delay_instruction); instrEndsBlock = InstrEndsBlock(delay_instruction);
if(instrEndsBlock) { if(instrEndsBlock) {
Util::Error::GetInstance().Throw( Util::Error::GetInstance().Throw(
@@ -210,25 +219,30 @@ int JIT::Step() {
Emit(instruction); Emit(instruction);
if(!regs.delaySlot) { Xbyak::Label clearDelaySlot;
code.mov(code.SCR1, blockOldPC);
code.mov(REG(qword, oldPC), code.SCR1); code.mov(code.SCR1, REG(byte, delaySlot));
code.mov(code.SCR1, blockPC); code.cmp(code.SCR1, 0);
code.mov(REG(qword, pc), code.SCR1); code.jne(clearDelaySlot);
code.mov(code.SCR1, blockNextPC); code.mov(code.SCR1, blockOldPC);
code.mov(REG(qword, nextPC), code.SCR1); code.mov(REG(qword, oldPC), code.SCR1);
} code.mov(code.SCR1, blockPC);
code.mov(REG(qword, pc), code.SCR1);
code.mov(code.SCR1, blockNextPC);
code.mov(REG(qword, nextPC), code.SCR1);
code.L(clearDelaySlot);
code.mov(REG(byte, delaySlot), 0);
code.mov(code.rax, instructionsInBlock); code.mov(code.rax, instructionsInBlock);
code.pop(code.rbp); code.pop(code.rbp);
code.add(code.rsp, 8); code.add(code.rsp, 8);
code.ret(); code.ret();
code.setProtectModeRE(); code.setProtectModeRE();
static auto blockInfoSize = 0; static size_t blockInfoSize = 0;
blockInfoSize = code.getSize() - blockInfoSize; blockInfoSize = code.getSize() - blockInfoSize;
info("\tX86 code (block address = 0x{:016X}):", (uintptr_t)block); info("\tX86 code (block address = 0x{:016X}):", reinterpret_cast<uintptr_t>(block));
auto count = cs_disasm(disassemblerX86, blockInfo, blockInfoSize, (uintptr_t)block, 0, &insn); const auto count = cs_disasm(disassemblerX86, blockInfo, blockInfoSize, reinterpret_cast<uintptr_t>(block), 0, &insn);
if (count > 0) { if (count > 0) {
for (size_t j = 0; j < count; j++) { for (size_t j = 0; j < count; j++) {
info("\t\t0x{:016X}:\t{}\t\t{}", insn[j].address, insn[j].mnemonic, insn[j].op_str); info("\t\t0x{:016X}:\t{}\t\t{}", insn[j].address, insn[j].mnemonic, insn[j].op_str);
@@ -241,7 +255,7 @@ int JIT::Step() {
} }
#endif #endif
void JIT::DumpBlockCacheToDisk() { void JIT::DumpBlockCacheToDisk() const {
Util::WriteFileBinary(code.getCode<u8*>(), code.getSize(), "jit.dump"); Util::WriteFileBinary(code.getCode<u8*>(), code.getSize(), "jit.dump");
} }
} // namespace n64 } // namespace n64

View File

@@ -16,15 +16,15 @@ static constexpr u32 kUpperSize = kAddressSpaceSize >> kUpperShift; // 0x800000
static constexpr u32 kLowerSize = 0x100; // 0x80 static constexpr u32 kLowerSize = 0x100; // 0x80
static constexpr u32 kCodeCacheSize = 32_mb; static constexpr u32 kCodeCacheSize = 32_mb;
static constexpr u32 kCodeCacheAllocSize = kCodeCacheSize + 4_kb; static constexpr u32 kCodeCacheAllocSize = kCodeCacheSize + 4_kb;
#define REG(acc, x) code.acc[reinterpret_cast<uintptr_t>(&regs.x)] #define REG(acc, x) code.acc[code.rbp + (reinterpret_cast<uintptr_t>(&regs.x) - reinterpret_cast<uintptr_t>(this))]
#ifdef __aarch64__ #ifdef __aarch64__
struct JIT : BaseCPU {}; struct JIT : BaseCPU {};
#else #else
struct JIT : BaseCPU { struct JIT final : BaseCPU {
explicit JIT(ParallelRDP&, Mem&, Registers&); explicit JIT(Mem&, Registers&);
~JIT() override = default; ~JIT() override = default;
int Step() override; u32 Step() override;
void Reset() override { void Reset() override {
code.reset(); code.reset();
@@ -32,7 +32,7 @@ struct JIT : BaseCPU {
blockCache.resize(kUpperSize); blockCache.resize(kUpperSize);
} }
void DumpBlockCacheToDisk(); void DumpBlockCacheToDisk() const;
void InvalidateBlock(u32); void InvalidateBlock(u32);
private: private:
@@ -40,13 +40,13 @@ private:
Mem& mem; Mem& mem;
Xbyak::CodeGenerator code{kCodeCacheAllocSize}; Xbyak::CodeGenerator code{kCodeCacheAllocSize};
u64 cop2Latch{}; u64 cop2Latch{};
u64 blockOldPC = 0, blockPC = 0, blockNextPC = 0; s64 blockOldPC = 0, blockPC = 0, blockNextPC = 0;
friend struct Cop1; friend struct Cop1;
friend struct Registers; friend struct Registers;
using BlockFn = int (*)(); using BlockFn = int (*)();
std::vector<std::vector<BlockFn>> blockCache; std::vector<std::vector<BlockFn>> blockCache;
Xbyak::Label branch_likely_not_taken; Xbyak::Label branch_likely_not_taken;
csh disassemblerMips, disassemblerX86; csh disassemblerMips{}, disassemblerX86{};
template <typename T> template <typename T>
Xbyak::Address GPR(const size_t index) const { Xbyak::Address GPR(const size_t index) const {
@@ -108,89 +108,89 @@ private:
(((!regs.cop0.is64BitAddressing) && (s32)(vaddr) != (vaddr)) || (((vaddr) & (mask)) != 0)) (((!regs.cop0.is64BitAddressing) && (s32)(vaddr) != (vaddr)) || (((vaddr) & (mask)) != 0))
[[nodiscard]] bool ShouldServiceInterrupt() const; [[nodiscard]] bool ShouldServiceInterrupt() const;
void CheckCompareInterrupt(); void CheckCompareInterrupt() const;
u32 FetchInstruction(); u32 FetchInstruction();
void Emit(const Instruction); void Emit(Instruction);
void special(const Instruction); void special(Instruction);
void regimm(const Instruction); void regimm(Instruction);
void add(const Instruction); void add(Instruction);
void addu(const Instruction); void addu(Instruction);
void addi(const Instruction); void addi(Instruction);
void addiu(const Instruction); void addiu(Instruction);
void andi(const Instruction); void andi(Instruction);
void and_(const Instruction); void and_(Instruction);
void branch_constant(bool cond, s64 offset); void branch_constant(bool cond, s64 offset);
void branch_likely_constant(bool cond, s64 offset); void branch_likely_constant(bool cond, s64 offset);
void branch_abs_constant(bool cond, s64 address); void branch_abs_constant(bool cond, s64 address);
void bltz(const Instruction); void bltz(Instruction);
void bgez(const Instruction); void bgez(Instruction);
void bltzl(const Instruction); void bltzl(Instruction);
void bgezl(const Instruction); void bgezl(Instruction);
void bltzal(const Instruction); void bltzal(Instruction);
void bgezal(const Instruction); void bgezal(Instruction);
void bltzall(const Instruction); void bltzall(Instruction);
void bgezall(const Instruction); void bgezall(Instruction);
void beq(const Instruction); void beq(Instruction);
void beql(const Instruction); void beql(Instruction);
void bne(const Instruction); void bne(Instruction);
void bnel(const Instruction); void bnel(Instruction);
void blez(const Instruction); void blez(Instruction);
void blezl(const Instruction); void blezl(Instruction);
void bgtz(const Instruction); void bgtz(Instruction);
void bgtzl(const Instruction); void bgtzl(Instruction);
void bfc1(const Instruction); void bfc1(Instruction);
void blfc1(const Instruction); void blfc1(Instruction);
void bfc0(const Instruction); void bfc0(Instruction);
void blfc0(const Instruction); void blfc0(Instruction);
void dadd(const Instruction); void dadd(Instruction);
void daddu(const Instruction); void daddu(Instruction);
void daddi(const Instruction); void daddi(Instruction);
void daddiu(const Instruction); void daddiu(Instruction);
void ddiv(const Instruction); void ddiv(Instruction);
void ddivu(const Instruction); void ddivu(Instruction);
void div(const Instruction); void div(Instruction);
void divu(const Instruction); void divu(Instruction);
void dmult(const Instruction); void dmult(Instruction);
void dmultu(const Instruction); void dmultu(Instruction);
void dsll(const Instruction); void dsll(Instruction);
void dsllv(const Instruction); void dsllv(Instruction);
void dsll32(const Instruction); void dsll32(Instruction);
void dsra(const Instruction); void dsra(Instruction);
void dsrav(const Instruction); void dsrav(Instruction);
void dsra32(const Instruction); void dsra32(Instruction);
void dsrl(const Instruction); void dsrl(Instruction);
void dsrlv(const Instruction); void dsrlv(Instruction);
void dsrl32(const Instruction); void dsrl32(Instruction);
void dsub(const Instruction); void dsub(Instruction);
void dsubu(const Instruction); void dsubu(Instruction);
void j(const Instruction); void j(Instruction);
void jr(const Instruction); void jr(Instruction);
void jal(const Instruction); void jal(Instruction);
void jalr(const Instruction); void jalr(Instruction);
void lui(const Instruction); void lui(Instruction);
void lbu(const Instruction); void lbu(Instruction);
void lb(const Instruction); void lb(Instruction);
void ld(const Instruction); void ld(Instruction);
void ldc1(const Instruction); void ldc1(Instruction);
void ldl(const Instruction); void ldl(Instruction);
void ldr(const Instruction); void ldr(Instruction);
void lh(const Instruction); void lh(Instruction);
void lhu(const Instruction); void lhu(Instruction);
void ll(const Instruction); void ll(Instruction);
void lld(const Instruction); void lld(Instruction);
void lw(const Instruction); void lw(Instruction);
void lwc1(const Instruction); void lwc1(Instruction);
void lwl(const Instruction); void lwl(Instruction);
void lwu(const Instruction); void lwu(Instruction);
void lwr(const Instruction); void lwr(Instruction);
void mfhi(const Instruction); void mfhi(Instruction);
void mflo(const Instruction); void mflo(Instruction);
void mult(const Instruction); void mult(Instruction);
void multu(const Instruction); void multu(Instruction);
void mthi(const Instruction); void mthi(Instruction);
void mtlo(const Instruction); void mtlo(Instruction);
void nor(const Instruction); void nor(Instruction);
void sb(const Instruction) { void sb(const Instruction) {
Util::Error::GetInstance().Throw( Util::Error::GetInstance().Throw(
{Util::Error::Severity::NON_FATAL}, {Util::Error::Type::UNHANDLED_INSTRUCTION}, {Util::Error::Severity::NON_FATAL}, {Util::Error::Type::UNHANDLED_INSTRUCTION},
@@ -231,7 +231,7 @@ private:
{Util::Error::Severity::NON_FATAL}, {Util::Error::Type::UNHANDLED_INSTRUCTION}, {Util::Error::Severity::NON_FATAL}, {Util::Error::Type::UNHANDLED_INSTRUCTION},
blockPC, {}, "[JIT]: Unhandled 'sh'!"); blockPC, {}, "[JIT]: Unhandled 'sh'!");
} }
void sw(const Instruction); void sw(Instruction);
void swl(const Instruction) { void swl(const Instruction) {
Util::Error::GetInstance().Throw( Util::Error::GetInstance().Throw(
{Util::Error::Severity::NON_FATAL}, {Util::Error::Type::UNHANDLED_INSTRUCTION}, {Util::Error::Severity::NON_FATAL}, {Util::Error::Type::UNHANDLED_INSTRUCTION},
@@ -242,32 +242,32 @@ private:
{Util::Error::Severity::NON_FATAL}, {Util::Error::Type::UNHANDLED_INSTRUCTION}, {Util::Error::Severity::NON_FATAL}, {Util::Error::Type::UNHANDLED_INSTRUCTION},
blockPC, {}, "[JIT]: Unhandled 'swr'!"); blockPC, {}, "[JIT]: Unhandled 'swr'!");
} }
void slti(const Instruction); void slti(Instruction);
void sltiu(const Instruction); void sltiu(Instruction);
void slt(const Instruction); void slt(Instruction);
void sltu(const Instruction); void sltu(Instruction);
void sll(const Instruction); void sll(Instruction);
void sllv(const Instruction); void sllv(Instruction);
void sub(const Instruction); void sub(Instruction);
void subu(const Instruction); void subu(Instruction);
void swc1(const Instruction) { void swc1(const Instruction) {
Util::Error::GetInstance().Throw( Util::Error::GetInstance().Throw(
{Util::Error::Severity::NON_FATAL}, {Util::Error::Type::JIT_BRANCH_INSIDE_DELAY_SLOT}, {Util::Error::Severity::NON_FATAL}, {Util::Error::Type::JIT_BRANCH_INSIDE_DELAY_SLOT},
blockPC, {}, "[JIT]: Unhandled case of branch from delay slot!"); blockPC, {}, "[JIT]: Unhandled case of branch from delay slot!");
} }
void sra(const Instruction); void sra(Instruction);
void srav(const Instruction); void srav(Instruction);
void srl(const Instruction); void srl(Instruction);
void srlv(const Instruction); void srlv(Instruction);
void trap(bool) { void trap(bool) {
Util::Error::GetInstance().Throw( Util::Error::GetInstance().Throw(
{Util::Error::Severity::NON_FATAL}, {Util::Error::Type::JIT_BRANCH_INSIDE_DELAY_SLOT}, {Util::Error::Severity::NON_FATAL}, {Util::Error::Type::JIT_BRANCH_INSIDE_DELAY_SLOT},
blockPC, {}, "[JIT]: Unhandled case of branch from delay slot!"); blockPC, {}, "[JIT]: Unhandled case of branch from delay slot!");
} }
void or_(const Instruction); void or_(Instruction);
void ori(const Instruction); void ori(Instruction);
void xor_(const Instruction); void xor_(Instruction);
void xori(const Instruction); void xori(Instruction);
}; };
#endif #endif
} // namespace n64 } // namespace n64

View File

@@ -135,7 +135,7 @@ struct RSP {
void SetVTE(const VPR &vt, u8 e); void SetVTE(const VPR &vt, u8 e);
auto Read(u32 addr) -> u32; auto Read(u32 addr) -> u32;
void Write(u32 addr, u32 val); void Write(u32 addr, u32 val);
void Exec(const Instruction instr); void Exec(Instruction instr);
SPStatus spStatus{}; SPStatus spStatus{};
u16 oldPC{}, pc{}, nextPC{}; u16 oldPC{}, pc{}, nextPC{};
SPDMASPAddr spDMASPAddr{}; SPDMASPAddr spDMASPAddr{};
@@ -151,7 +151,7 @@ struct RSP {
VPR vce{}; VPR vce{};
s16 divIn{}, divOut{}; s16 divIn{}, divOut{};
bool divInLoaded = false; bool divInLoaded = false;
int steps = 0; u32 steps = 0;
struct { struct {
VPR h{}, m{}, l{}; VPR h{}, m{}, l{};
@@ -257,12 +257,12 @@ struct RSP {
FORCE_INLINE void ReleaseSemaphore() { semaphore = false; } FORCE_INLINE void ReleaseSemaphore() { semaphore = false; }
void special(const Instruction instr); void special(Instruction instr);
void regimm(const Instruction instr); void regimm(Instruction instr);
void lwc2(const Instruction instr); void lwc2(Instruction instr);
void swc2(const Instruction instr); void swc2(Instruction instr);
void cop2(const Instruction instr); void cop2(Instruction instr);
void cop0(const Instruction instr); void cop0(Instruction instr);
void add(Instruction instr); void add(Instruction instr);
void addi(Instruction instr); void addi(Instruction instr);

View File

@@ -192,35 +192,35 @@ void JIT::blfc1(const Instruction instr) {
} }
void JIT::BranchNotTaken() {} void JIT::BranchNotTaken() {}
void JIT::BranchTaken(s64 offs) {
void JIT::BranchTaken(const s64 offs) {
code.mov(code.SCR1, REG(qword, pc)); code.mov(code.SCR1, REG(qword, pc));
code.add(code.SCR1, offs); code.add(code.SCR1, offs);
SetPC64(offs); SetPC64(code.SCR1);
} }
void JIT::BranchTaken(const Xbyak::Reg64 &offs) { void JIT::BranchTaken(const Xbyak::Reg64 &offs) {
code.mov(code.SCR1, REG(qword, pc)); code.mov(code.SCR1, REG(qword, pc));
code.add(code.SCR1, offs); code.add(code.SCR1, offs);
SetPC64(offs); SetPC64(code.SCR1);
} }
void JIT::BranchAbsTaken(s64 addr) { void JIT::BranchAbsTaken(const s64 addr) {
code.add(code.SCR1, addr); SetPC64(addr);
code.mov(REG(qword, nextPC), code.SCR1);
} }
void JIT::BranchAbsTaken(const Xbyak::Reg64 &addr) { void JIT::BranchAbsTaken(const Xbyak::Reg64 &addr) {
code.mov(REG(qword, nextPC), addr); SetPC64(addr);
} }
void JIT::branch_constant(const bool cond, s64 offset) { void JIT::branch_constant(const bool cond, const s64 offset) {
if(cond) { if(cond) {
regs.delaySlot = true; regs.delaySlot = true;
BranchTaken(offset); BranchTaken(offset);
} }
} }
void JIT::branch_likely_constant(bool cond, s64 offset) { void JIT::branch_likely_constant(const bool cond, const s64 offset) {
if(cond) { if(cond) {
regs.delaySlot = true; regs.delaySlot = true;
BranchTaken(offset); BranchTaken(offset);
@@ -229,7 +229,7 @@ void JIT::branch_likely_constant(bool cond, s64 offset) {
} }
} }
void JIT::branch_abs_constant(bool cond, s64 address) { void JIT::branch_abs_constant(const bool cond, const s64 address) {
if(cond) { if(cond) {
regs.delaySlot = true; regs.delaySlot = true;
BranchAbsTaken(address); BranchAbsTaken(address);
@@ -238,7 +238,7 @@ void JIT::branch_abs_constant(bool cond, s64 address) {
#define branch(offs, cond) do { \ #define branch(offs, cond) do { \
Xbyak::Label taken, not_taken; \ Xbyak::Label taken, not_taken; \
code.j##cond(taken); \ code.j## cond(taken); \
code.jmp(not_taken); \ code.jmp(not_taken); \
code.L(taken); \ code.L(taken); \
BranchTaken(offs); \ BranchTaken(offs); \
@@ -247,7 +247,7 @@ void JIT::branch_abs_constant(bool cond, s64 address) {
#define branch_abs(addr, cond) do { \ #define branch_abs(addr, cond) do { \
Xbyak::Label taken, not_taken; \ Xbyak::Label taken, not_taken; \
code.j##cond(taken); \ code.j## cond(taken); \
code.jmp(not_taken); \ code.jmp(not_taken); \
code.L(taken); \ code.L(taken); \
BranchAbsTaken(addr); \ BranchAbsTaken(addr); \
@@ -256,7 +256,7 @@ void JIT::branch_abs_constant(bool cond, s64 address) {
#define branch_likely(offs, cond) do { \ #define branch_likely(offs, cond) do { \
Xbyak::Label taken, not_taken; \ Xbyak::Label taken, not_taken; \
code.j##cond(taken); \ code.j## cond(taken); \
code.jmp(not_taken); \ code.jmp(not_taken); \
code.L(taken); \ code.L(taken); \
BranchTaken(offs); \ BranchTaken(offs); \
@@ -266,7 +266,7 @@ void JIT::branch_abs_constant(bool cond, s64 address) {
void JIT::bltz(const Instruction instr) { void JIT::bltz(const Instruction instr) {
const s16 imm = instr; const s16 imm = instr;
const s64 offset = u64((s64)imm) << 2; const s64 offset = static_cast<s64>(imm) << 2;
if (regs.IsRegConstant(instr.rs())) { if (regs.IsRegConstant(instr.rs())) {
branch_constant(regs.Read<s64>(instr.rs()) < 0, offset); branch_constant(regs.Read<s64>(instr.rs()) < 0, offset);
return; return;
@@ -435,7 +435,7 @@ void JIT::beql(const Instruction instr) {
void JIT::bne(const Instruction instr) { void JIT::bne(const Instruction instr) {
const s16 imm = instr; const s16 imm = instr;
const s64 offset = u64((s64)imm) << 2; const s64 offset = static_cast<s64>(imm) << 2;
if (regs.IsRegConstant(instr.rs()) && regs.IsRegConstant(instr.rt())) { if (regs.IsRegConstant(instr.rs()) && regs.IsRegConstant(instr.rt())) {
branch_constant(regs.Read<s64>(instr.rs()) != regs.Read<s64>(instr.rt()), offset); branch_constant(regs.Read<s64>(instr.rs()) != regs.Read<s64>(instr.rt()), offset);
return; return;
@@ -857,13 +857,13 @@ void JIT::dsubu(const Instruction instr) {
void JIT::j(const Instruction instr) { void JIT::j(const Instruction instr) {
const s32 target = (instr & 0x3ffffff) << 2; const s32 target = (instr & 0x3ffffff) << 2;
const s64 address = (blockOldPC & ~0xfffffff) | target; const s64 address = blockOldPC & ~0xfffffff | target;
branch_abs_constant(true, address); branch_abs_constant(true, address);
} }
void JIT::jr(const Instruction instr) { void JIT::jr(const Instruction instr) {
if (regs.IsRegConstant(instr.rs())) { if (regs.IsRegConstant(instr.rs())) {
const u64 address = regs.Read<s64>(instr.rs()); const auto address = regs.Read<s64>(instr.rs());
branch_abs_constant(true, address); branch_abs_constant(true, address);
return; return;
} }